mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2026-06-23 14:16:52 +08:00
✨ 添加 Cookie 组件 (#633)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"""nbesf is Nonebot Bison Enchangable Subscribes File!"""
|
||||
|
||||
from . import v1, v2
|
||||
from . import v1, v2, v3
|
||||
from .base import NBESFBase
|
||||
|
||||
__all__ = ["v1", "v2", "NBESFBase"]
|
||||
__all__ = ["v1", "v2", "v3", "NBESFBase"]
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
"""nbesf is Nonebot Bison Enchangable Subscribes File! ver.2"""
|
||||
|
||||
from typing import Any
|
||||
from functools import partial
|
||||
|
||||
from nonebot.log import logger
|
||||
from pydantic import BaseModel
|
||||
from nonebot_plugin_saa.registries import AllSupportedPlatformTarget
|
||||
from nonebot.compat import PYDANTIC_V2, ConfigDict, model_dump, type_validate_json, type_validate_python
|
||||
|
||||
from ..utils import NBESFParseErr
|
||||
from ....types import Tag, Category
|
||||
from .base import NBESFBase, SubReceipt
|
||||
from ...db_model import Cookie as DBCookie
|
||||
from ...db_config import SubscribeDupException, config
|
||||
|
||||
# ===== nbesf 定义格式 ====== #
|
||||
NBESF_VERSION = 3
|
||||
|
||||
|
||||
class Target(BaseModel):
|
||||
"""Bsion快递包发货信息"""
|
||||
|
||||
target_name: str
|
||||
target: str
|
||||
platform_name: str
|
||||
default_schedule_weight: int
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
else:
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class SubPayload(BaseModel):
|
||||
"""Bison快递包里的单件货物"""
|
||||
|
||||
categories: list[Category]
|
||||
tags: list[Tag]
|
||||
target: Target
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
else:
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class Cookie(BaseModel):
|
||||
"""Bison的魔法饼干"""
|
||||
|
||||
site_name: str
|
||||
content: str
|
||||
cookie_name: str
|
||||
cd_milliseconds: int
|
||||
is_universal: bool
|
||||
tags: dict[str, str]
|
||||
targets: list[Target]
|
||||
|
||||
|
||||
class SubPack(BaseModel):
|
||||
"""Bison给指定用户派送的快递包"""
|
||||
|
||||
# user_target: Bison快递包收货信息
|
||||
user_target: AllSupportedPlatformTarget
|
||||
subs: list[SubPayload]
|
||||
|
||||
|
||||
class SubGroup(NBESFBase):
|
||||
"""
|
||||
Bison的全部订单(按用户分组)和魔法饼干
|
||||
|
||||
结构参见`nbesf_model`下的对应版本
|
||||
"""
|
||||
|
||||
version: int = NBESF_VERSION
|
||||
groups: list[SubPack] = []
|
||||
cookies: list[Cookie] = []
|
||||
|
||||
|
||||
# ======================= #
|
||||
|
||||
|
||||
async def subs_receipt_gen(nbesf_data: SubGroup):
|
||||
logger.info("开始添加订阅流程")
|
||||
for item in nbesf_data.groups:
|
||||
sub_receipt = partial(SubReceipt, user=item.user_target)
|
||||
|
||||
for sub in item.subs:
|
||||
receipt = sub_receipt(
|
||||
target=sub.target.target,
|
||||
target_name=sub.target.target_name,
|
||||
platform_name=sub.target.platform_name,
|
||||
cats=sub.categories,
|
||||
tags=sub.tags,
|
||||
)
|
||||
try:
|
||||
await config.add_subscribe(receipt.user, **model_dump(receipt, exclude={"user"}))
|
||||
except SubscribeDupException:
|
||||
logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在")
|
||||
except Exception as e:
|
||||
logger.error(f"!添加订阅条目 {repr(receipt)} 失败: {repr(e)}")
|
||||
else:
|
||||
logger.success(f"添加订阅条目 {repr(receipt)} 成功!")
|
||||
|
||||
|
||||
async def magic_cookie_gen(nbesf_data: SubGroup):
|
||||
logger.info("开始添加 Cookie 流程")
|
||||
for cookie in nbesf_data.cookies:
|
||||
try:
|
||||
new_cookie = DBCookie(**model_dump(cookie, exclude={"targets"}))
|
||||
cookie_id = await config.add_cookie(new_cookie)
|
||||
for target in cookie.targets:
|
||||
await config.add_cookie_target(target.target, target.platform_name, cookie_id)
|
||||
except Exception as e:
|
||||
logger.error(f"!添加 Cookie 条目 {repr(cookie)} 失败: {repr(e)}")
|
||||
else:
|
||||
logger.success(f"添加 Cookie 条目 {repr(cookie)} 成功!")
|
||||
|
||||
|
||||
def nbesf_parser(raw_data: Any) -> SubGroup:
|
||||
try:
|
||||
if isinstance(raw_data, str):
|
||||
nbesf_data = type_validate_json(SubGroup, raw_data)
|
||||
else:
|
||||
nbesf_data = type_validate_python(SubGroup, raw_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("数据解析失败,该数据格式可能不满足NBESF格式标准!")
|
||||
raise NBESFParseErr("数据解析失败") from e
|
||||
else:
|
||||
return nbesf_data
|
||||
@@ -10,12 +10,13 @@ from nonebot.compat import type_validate_python
|
||||
from nonebot_plugin_datastore.db import create_session
|
||||
from sqlalchemy.orm.strategy_options import selectinload
|
||||
|
||||
from .utils import NBESFVerMatchErr
|
||||
from ..db_model import User, Subscribe
|
||||
from .nbesf_model import NBESFBase, v1, v2
|
||||
from .. import config
|
||||
from .utils import NBESFVerMatchErr, row2dict
|
||||
from .nbesf_model import NBESFBase, v1, v2, v3
|
||||
from ..db_model import User, Cookie, Target, Subscribe, CookieTarget
|
||||
|
||||
|
||||
async def subscribes_export(selector: Callable[[Select], Select]) -> v2.SubGroup:
|
||||
async def subscribes_export(selector: Callable[[Select], Select]) -> v3.SubGroup:
|
||||
"""
|
||||
将Bison订阅导出为 Nonebot Bison Exchangable Subscribes File 标准格式的 SubGroup 类型数据
|
||||
|
||||
@@ -34,22 +35,54 @@ async def subscribes_export(selector: Callable[[Select], Select]) -> v2.SubGroup
|
||||
user_stmt = cast(Select[tuple[User]], user_stmt)
|
||||
user_data = await sess.scalars(user_stmt)
|
||||
|
||||
groups: list[v2.SubPack] = []
|
||||
user_id_sub_dict: dict[int, list[v2.SubPayload]] = defaultdict(list)
|
||||
groups: list[v3.SubPack] = []
|
||||
user_id_sub_dict: dict[int, list[v3.SubPayload]] = defaultdict(list)
|
||||
|
||||
for sub in sub_data:
|
||||
sub_paylaod = type_validate_python(v2.SubPayload, sub)
|
||||
sub_paylaod = type_validate_python(v3.SubPayload, sub)
|
||||
user_id_sub_dict[sub.user_id].append(sub_paylaod)
|
||||
|
||||
for user in user_data:
|
||||
assert isinstance(user, User)
|
||||
sub_pack = v2.SubPack(
|
||||
sub_pack = v3.SubPack(
|
||||
user_target=PlatformTarget.deserialize(user.user_target),
|
||||
subs=user_id_sub_dict[user.id],
|
||||
)
|
||||
groups.append(sub_pack)
|
||||
|
||||
sub_group = v2.SubGroup(groups=groups)
|
||||
async with create_session() as sess:
|
||||
cookie_target_stmt = (
|
||||
select(CookieTarget)
|
||||
.join(Cookie)
|
||||
.join(Target)
|
||||
.options(selectinload(CookieTarget.target))
|
||||
.options(selectinload(CookieTarget.cookie))
|
||||
)
|
||||
cookie_target_data = await sess.scalars(cookie_target_stmt)
|
||||
|
||||
cookie_target_dict: dict[Cookie, list[v3.Target]] = defaultdict(list)
|
||||
for cookie_target in cookie_target_data:
|
||||
target_payload = type_validate_python(v3.Target, cookie_target.target)
|
||||
cookie_target_dict[cookie_target.cookie].append(target_payload)
|
||||
|
||||
def cookie_transform(cookie: Cookie, targets: [Target]) -> v3.Cookie:
|
||||
cookie_dict = row2dict(cookie)
|
||||
cookie_dict["tags"] = cookie.tags
|
||||
cookie_dict["targets"] = targets
|
||||
return v3.Cookie(**cookie_dict)
|
||||
|
||||
cookies: list[v3.Cookie] = []
|
||||
cookie_set = set()
|
||||
for cookie, targets in cookie_target_dict.items():
|
||||
assert isinstance(cookie, Cookie)
|
||||
cookies.append(cookie_transform(cookie, targets))
|
||||
cookie_set.add(cookie.id)
|
||||
|
||||
# 添加未关联的cookie
|
||||
all_cookies = await config.get_cookie(is_anonymous=False)
|
||||
cookies.extend([cookie_transform(c, []) for c in all_cookies if c.id not in cookie_set])
|
||||
|
||||
sub_group = v3.SubGroup(groups=groups, cookies=cookies)
|
||||
|
||||
return sub_group
|
||||
|
||||
@@ -72,6 +105,10 @@ async def subscribes_import(
|
||||
case 2:
|
||||
assert isinstance(nbesf_data, v2.SubGroup)
|
||||
await v2.subs_receipt_gen(nbesf_data)
|
||||
case 3:
|
||||
assert isinstance(nbesf_data, v3.SubGroup)
|
||||
await v3.subs_receipt_gen(nbesf_data)
|
||||
await v3.magic_cookie_gen(nbesf_data)
|
||||
case _:
|
||||
raise NBESFVerMatchErr(f"不支持的NBESF版本:{nbesf_data.version}")
|
||||
logger.info("订阅流程结束,请检查所有订阅记录是否全部添加成功")
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
from ..db_model import Model
|
||||
|
||||
|
||||
class NBESFVerMatchErr(Exception): ...
|
||||
|
||||
|
||||
class NBESFParseErr(Exception): ...
|
||||
|
||||
|
||||
def row2dict(row: Model) -> dict:
|
||||
d = {}
|
||||
for column in row.__table__.columns:
|
||||
d[column.name] = str(getattr(row, column.name))
|
||||
|
||||
return d
|
||||
|
||||
Reference in New Issue
Block a user