mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2026-05-09 18:27:56 +08:00
✨ subs-io适配引入saa后的新数据库结构 (#219的subs-io部分) (#224)
* 🚚 将nbesf_model统一放到目录中 * ✨ 添加v2版本的nbesf * ✨ 使subs_import支持导入多个版本的nbesf文件 * ✨ 使用saa的AllSupportedPlatformTarget * 🚧 use deserialize --------- Co-authored-by: felinae98 <731499577@qq.com>
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
from .subs_io import nbesf_parser, subscribes_export, subscribes_import
|
||||
from .subs_io import subscribes_export, subscribes_import
|
||||
|
||||
__all__ = ["subscribes_export", "subscribes_import", "nbesf_parser"]
|
||||
__all__ = ["subscribes_export", "subscribes_import"]
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
""" nbexf is Nonebot Bison Enchangable Subscribes File! """
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ...types import Category, Tag
|
||||
|
||||
# ===== nbesf 定义格式 ====== #
|
||||
NBESF_VERSION = 1
|
||||
|
||||
|
||||
class UserHead(BaseModel, orm_mode=True):
|
||||
"""Bison快递包收货信息"""
|
||||
|
||||
type: str
|
||||
uid: int
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.type, self.uid))
|
||||
|
||||
|
||||
class Target(BaseModel, orm_mode=True):
|
||||
"""Bsion快递包发货信息"""
|
||||
|
||||
target_name: str
|
||||
target: str
|
||||
platform_name: str
|
||||
default_schedule_weight: int
|
||||
|
||||
|
||||
class SubPayload(BaseModel, orm_mode=True):
|
||||
"""Bison快递包里的单件货物"""
|
||||
|
||||
categories: list[Category]
|
||||
tags: list[Tag]
|
||||
target: Target
|
||||
|
||||
|
||||
class SubPack(BaseModel):
|
||||
"""Bison给指定用户派送的快递包"""
|
||||
|
||||
user: UserHead
|
||||
subs: list[SubPayload]
|
||||
|
||||
|
||||
class SubGroup(BaseModel):
|
||||
"""
|
||||
Bison的全部订单(按用户分组)
|
||||
|
||||
结构参见`nbesf_model.py`
|
||||
"""
|
||||
|
||||
version: int = NBESF_VERSION # 表示nbesf格式版本,从1开始
|
||||
groups: list[SubPack]
|
||||
|
||||
|
||||
# ======================= #
|
||||
|
||||
|
||||
class SubReceipt(BaseModel):
|
||||
"""
|
||||
快递包中每件货物的收据
|
||||
|
||||
导入订阅时的Model
|
||||
"""
|
||||
|
||||
user: int
|
||||
user_type: str
|
||||
target: str
|
||||
target_name: str
|
||||
platform_name: str
|
||||
cats: list[Category]
|
||||
tags: list[Tag]
|
||||
# default_schedule_weight: int
|
||||
|
||||
|
||||
class NBESFVerMatchErr(Exception):
|
||||
...
|
||||
|
||||
|
||||
class NBESFParseErr(Exception):
|
||||
...
|
||||
@@ -0,0 +1,6 @@
|
||||
""" nbesf is Nonebot Bison Enchangable Subscribes File! """
|
||||
|
||||
from . import v1, v2
|
||||
from .base import NBESFBase
|
||||
|
||||
__all__ = ["v1", "v2", "NBESFBase"]
|
||||
@@ -0,0 +1,31 @@
|
||||
from abc import ABC
|
||||
|
||||
from nonebot_plugin_saa.utils import AllSupportedPlatformTarget as UserInfo
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ....types import Category, Tag
|
||||
|
||||
|
||||
class NBESFBase(BaseModel, ABC):
|
||||
|
||||
version: int # 表示nbesf格式版本,有效版本从1开始
|
||||
groups: list = list()
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class SubReceipt(BaseModel):
|
||||
"""
|
||||
快递包中每件货物的收据
|
||||
|
||||
导入订阅时的Model
|
||||
"""
|
||||
|
||||
user: UserInfo
|
||||
target: str
|
||||
target_name: str
|
||||
platform_name: str
|
||||
cats: list[Category]
|
||||
tags: list[Tag]
|
||||
# default_schedule_weight: int
|
||||
@@ -0,0 +1,111 @@
|
||||
""" nbesf is Nonebot Bison Enchangable Subscribes File! ver.1"""
|
||||
|
||||
from functools import partial
|
||||
from typing import Any
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ....types import Category, Tag
|
||||
from ...db_config import SubscribeDupException, config
|
||||
from ..utils import NBESFParseErr
|
||||
from .base import NBESFBase, SubReceipt
|
||||
|
||||
# ===== nbesf 定义格式 ====== #
|
||||
NBESF_VERSION = 1
|
||||
|
||||
|
||||
class UserHead(BaseModel, orm_mode=True):
|
||||
"""Bison快递包收货信息"""
|
||||
|
||||
type: str
|
||||
uid: int
|
||||
|
||||
|
||||
class Target(BaseModel, orm_mode=True):
|
||||
"""Bsion快递包发货信息"""
|
||||
|
||||
target_name: str
|
||||
target: str
|
||||
platform_name: str
|
||||
default_schedule_weight: int
|
||||
|
||||
|
||||
class SubPayload(BaseModel, orm_mode=True):
|
||||
"""Bison快递包里的单件货物"""
|
||||
|
||||
categories: list[Category]
|
||||
tags: list[Tag]
|
||||
target: Target
|
||||
|
||||
|
||||
class SubPack(BaseModel):
|
||||
"""Bison给指定用户派送的快递包"""
|
||||
|
||||
user: UserHead
|
||||
subs: list[SubPayload]
|
||||
|
||||
|
||||
class SubGroup(
|
||||
NBESFBase,
|
||||
):
|
||||
"""
|
||||
Bison的全部订单(按用户分组)
|
||||
|
||||
结构参见`nbesf_model`下的对应版本
|
||||
"""
|
||||
|
||||
version = NBESF_VERSION
|
||||
groups: list[SubPack]
|
||||
|
||||
|
||||
# ======================= #
|
||||
|
||||
|
||||
async def subs_receipt_gen(nbesf_data: SubGroup):
|
||||
for item in nbesf_data.groups:
|
||||
|
||||
match item.user.type:
|
||||
case "group":
|
||||
user = TargetQQGroup(group_id=item.user.uid)
|
||||
case "private":
|
||||
user = TargetQQPrivate(user_id=item.user.uid)
|
||||
case _:
|
||||
raise NotImplementedError(f"nbesf v1 不支持的用户类型:{item.user.type}")
|
||||
|
||||
sub_receipt = partial(SubReceipt, user=user)
|
||||
|
||||
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, **receipt.dict(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)} 成功!")
|
||||
|
||||
|
||||
def nbesf_parser(raw_data: Any) -> SubGroup:
|
||||
try:
|
||||
if isinstance(raw_data, str):
|
||||
nbesf_data = SubGroup.parse_raw(raw_data)
|
||||
else:
|
||||
nbesf_data = SubGroup.parse_obj(raw_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("数据解析失败,该数据格式可能不满足NBESF格式标准!")
|
||||
raise NBESFParseErr("数据解析失败") from e
|
||||
else:
|
||||
logger.success("NBESF文件解析成功.")
|
||||
return nbesf_data
|
||||
@@ -0,0 +1,94 @@
|
||||
""" nbesf is Nonebot Bison Enchangable Subscribes File! ver.2"""
|
||||
|
||||
from functools import partial
|
||||
from typing import Any
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot_plugin_saa.utils import AllSupportedPlatformTarget
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ....types import Category, Tag
|
||||
from ...db_config import SubscribeDupException, config
|
||||
from ..utils import NBESFParseErr
|
||||
from .base import NBESFBase, SubReceipt
|
||||
|
||||
# ===== nbesf 定义格式 ====== #
|
||||
NBESF_VERSION = 2
|
||||
|
||||
|
||||
class Target(BaseModel, orm_mode=True):
|
||||
"""Bsion快递包发货信息"""
|
||||
|
||||
target_name: str
|
||||
target: str
|
||||
platform_name: str
|
||||
default_schedule_weight: int
|
||||
|
||||
|
||||
class SubPayload(BaseModel, orm_mode=True):
|
||||
"""Bison快递包里的单件货物"""
|
||||
|
||||
categories: list[Category]
|
||||
tags: list[Tag]
|
||||
target: 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]
|
||||
|
||||
|
||||
# ======================= #
|
||||
|
||||
|
||||
async def subs_receipt_gen(nbesf_data: SubGroup):
|
||||
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, **receipt.dict(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)} 成功!")
|
||||
|
||||
|
||||
def nbesf_parser(raw_data: Any) -> SubGroup:
|
||||
try:
|
||||
if isinstance(raw_data, str):
|
||||
nbesf_data = SubGroup.parse_raw(raw_data)
|
||||
else:
|
||||
nbesf_data = SubGroup.parse_obj(raw_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("数据解析失败,该数据格式可能不满足NBESF格式标准!")
|
||||
raise NBESFParseErr("数据解析失败") from e
|
||||
else:
|
||||
return nbesf_data
|
||||
@@ -1,25 +1,20 @@
|
||||
from collections import defaultdict
|
||||
from typing import Any, Callable, cast
|
||||
from typing import Callable, cast
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot_plugin_datastore.db import create_session
|
||||
from nonebot_plugin_saa import PlatformTarget
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm.strategy_options import selectinload
|
||||
from sqlalchemy.sql.selectable import Select
|
||||
|
||||
from ..db_model import Subscribe, User
|
||||
from .nbesf_model import (
|
||||
NBESFParseErr,
|
||||
NBESFVerMatchErr,
|
||||
SubGroup,
|
||||
SubPack,
|
||||
SubPayload,
|
||||
UserHead,
|
||||
)
|
||||
from .utils import subs_receipt_gen_ver_1
|
||||
from .nbesf_model import NBESFBase, v1, v2
|
||||
from .utils import NBESFVerMatchErr
|
||||
|
||||
|
||||
async def subscribes_export(selector: Callable[[Select], Select]) -> SubGroup:
|
||||
async def subscribes_export(selector: Callable[[Select], Select]) -> v2.SubGroup:
|
||||
|
||||
"""
|
||||
将Bison订阅导出为 Nonebot Bison Exchangable Subscribes File 标准格式的 SubGroup 类型数据
|
||||
|
||||
@@ -37,25 +32,28 @@ async def subscribes_export(selector: Callable[[Select], Select]) -> SubGroup:
|
||||
user_stmt = cast(Select[tuple[User]], user_stmt)
|
||||
user_data = await sess.scalars(user_stmt)
|
||||
|
||||
groups: list[SubPack] = []
|
||||
user_id_sub_dict: dict[int, list[SubPayload]] = defaultdict(list)
|
||||
groups: list[v2.SubPack] = []
|
||||
user_id_sub_dict: dict[int, list[v2.SubPayload]] = defaultdict(list)
|
||||
|
||||
for sub in sub_data:
|
||||
sub_paylaod = SubPayload.from_orm(sub)
|
||||
sub_paylaod = v2.SubPayload.from_orm(sub)
|
||||
user_id_sub_dict[sub.user_id].append(sub_paylaod)
|
||||
|
||||
for user in user_data:
|
||||
user_head = UserHead.from_orm(user)
|
||||
sub_pack = SubPack(user=user_head, subs=user_id_sub_dict[user.id])
|
||||
assert isinstance(user, User)
|
||||
sub_pack = v2.SubPack(
|
||||
user_target=PlatformTarget.deserialize(user.user_target),
|
||||
subs=user_id_sub_dict[user.id],
|
||||
)
|
||||
groups.append(sub_pack)
|
||||
|
||||
sub_group = SubGroup(groups=groups)
|
||||
sub_group = v2.SubGroup(groups=groups)
|
||||
|
||||
return sub_group
|
||||
|
||||
|
||||
async def subscribes_import(
|
||||
nbesf_data: SubGroup,
|
||||
nbesf_data: NBESFBase,
|
||||
):
|
||||
"""
|
||||
从 Nonebot Bison Exchangable Subscribes File 标准格式的数据中导入订阅
|
||||
@@ -67,21 +65,11 @@ async def subscribes_import(
|
||||
logger.info("开始添加订阅流程")
|
||||
match nbesf_data.version:
|
||||
case 1:
|
||||
await subs_receipt_gen_ver_1(nbesf_data)
|
||||
assert isinstance(nbesf_data, v1.SubGroup)
|
||||
await v1.subs_receipt_gen(nbesf_data)
|
||||
case 2:
|
||||
assert isinstance(nbesf_data, v2.SubGroup)
|
||||
await v2.subs_receipt_gen(nbesf_data)
|
||||
case _:
|
||||
raise NBESFVerMatchErr(f"不支持的NBESF版本:{nbesf_data.version}")
|
||||
logger.info("订阅流程结束,请检查所有订阅记录是否全部添加成功")
|
||||
|
||||
|
||||
def nbesf_parser(raw_data: Any) -> SubGroup:
|
||||
try:
|
||||
if isinstance(raw_data, str):
|
||||
nbesf_data = SubGroup.parse_raw(raw_data)
|
||||
else:
|
||||
nbesf_data = SubGroup.parse_obj(raw_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("数据解析失败,该数据格式可能不满足NBESF格式标准!")
|
||||
raise NBESFParseErr("数据解析失败") from e
|
||||
else:
|
||||
return nbesf_data
|
||||
|
||||
@@ -1,28 +1,6 @@
|
||||
from functools import partial
|
||||
|
||||
from nonebot.log import logger
|
||||
|
||||
from ..db_config import SubscribeDupException, config
|
||||
from .nbesf_model import NBESF_VERSION, SubGroup, SubReceipt
|
||||
class NBESFVerMatchErr(Exception):
|
||||
...
|
||||
|
||||
|
||||
async def subs_receipt_gen_ver_1(nbesf_data: SubGroup):
|
||||
for item in nbesf_data.groups:
|
||||
sub_receipt = partial(SubReceipt, user=item.user.uid, user_type=item.user.type)
|
||||
|
||||
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.dict())
|
||||
except SubscribeDupException:
|
||||
logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在")
|
||||
except Exception as e:
|
||||
logger.error(f"!添加订阅条目 {repr(receipt)} 失败: {repr(e)}")
|
||||
else:
|
||||
logger.success(f"添加订阅条目 {repr(receipt)} 成功!")
|
||||
class NBESFParseErr(Exception):
|
||||
...
|
||||
|
||||
Reference in New Issue
Block a user