From 8742de6cd1dacb060290d26bc34afbcd5065ee13 Mon Sep 17 00:00:00 2001 From: suyiiyii Date: Mon, 23 Sep 2024 10:27:27 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E5=9C=A8=20cookie=20=E4=B8=AD?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20cookie=5Fname=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot_bison/admin_page/api.py | 8 ++--- nonebot_bison/config/db_config.py | 1 + nonebot_bison/config/db_model.py | 2 ++ ...d_cookie.py => f90b712557a9_add_cookie.py} | 7 +++-- nonebot_bison/platform/rss.py | 6 ++-- nonebot_bison/platform/weibo.py | 6 ++-- .../sub_manager/add_cookie_target.py | 10 ++----- nonebot_bison/sub_manager/del_cookie.py | 5 +--- .../sub_manager/del_cookie_target.py | 7 +---- nonebot_bison/sub_manager/utils.py | 9 +++--- nonebot_bison/utils/site.py | 29 +++++++++++++------ 11 files changed, 44 insertions(+), 46 deletions(-) rename nonebot_bison/config/migrations/{ef796b74b0fe_add_cookie.py => f90b712557a9_add_cookie.py} (92%) diff --git a/nonebot_bison/admin_page/api.py b/nonebot_bison/admin_page/api.py index d0c2428..4cb0d28 100644 --- a/nonebot_bison/admin_page/api.py +++ b/nonebot_bison/admin_page/api.py @@ -210,15 +210,13 @@ async def update_weigth_config(platformName: str, target: str, weight_config: We @router.get("/cookie", dependencies=[Depends(check_is_superuser)]) -async def get_cookie(site_name: str | None = None, target: str | None = None) -> list[Cookie]: +async def get_cookie(site_name: str = None, target: str = None) -> list[Cookie]: + # todo: 调用 client_mgr 来添加cookie,以校验和获取cookie_name cookies_in_db = await config.get_cookie(site_name, is_anonymous=False) - # client_mgr = cast(CookieClientManager, site_manager[site_name].client_mgr) - # friendly_names = [await client_mgr.get_cookie_friendly_name(x) for x in cookies_in_db] - friendly_names = [x.content[:10] for x in cookies_in_db] return [ Cookie( id=cookies_in_db[i].id, - friendly_name=friendly_names[i], + friendly_name=cookies_in_db[i].cookie_name, site_name=cookies_in_db[i].site_name, last_usage=cookies_in_db[i].last_usage, status=cookies_in_db[i].status, diff --git a/nonebot_bison/config/db_config.py b/nonebot_bison/config/db_config.py index 9dac6dd..996bf2e 100644 --- a/nonebot_bison/config/db_config.py +++ b/nonebot_bison/config/db_config.py @@ -298,6 +298,7 @@ class DBConfig: if not cookie_in_db: raise ValueError(f"cookie {cookie.id} not found") cookie_in_db.content = cookie.content + cookie_in_db.cookie_name = cookie.cookie_name cookie_in_db.last_usage = cookie.last_usage cookie_in_db.status = cookie.status cookie_in_db.tags = cookie.tags diff --git a/nonebot_bison/config/db_model.py b/nonebot_bison/config/db_model.py index 54ea825..94c7d0c 100644 --- a/nonebot_bison/config/db_model.py +++ b/nonebot_bison/config/db_model.py @@ -74,6 +74,8 @@ class Cookie(Model): id: Mapped[int] = mapped_column(primary_key=True) site_name: Mapped[str] = mapped_column(String(100)) content: Mapped[str] = mapped_column(String(1024)) + # Cookie 的友好名字,类似于 Target 的 target_name,用于展示 + cookie_name: Mapped[str] = mapped_column(String(1024), default="unnamed cookie") # 最后使用的时刻 last_usage: Mapped[datetime.datetime] = mapped_column(DateTime, default=datetime.datetime(1970, 1, 1)) # Cookie 当前的状态 diff --git a/nonebot_bison/config/migrations/ef796b74b0fe_add_cookie.py b/nonebot_bison/config/migrations/f90b712557a9_add_cookie.py similarity index 92% rename from nonebot_bison/config/migrations/ef796b74b0fe_add_cookie.py rename to nonebot_bison/config/migrations/f90b712557a9_add_cookie.py index 01d5d4a..b89ce04 100644 --- a/nonebot_bison/config/migrations/ef796b74b0fe_add_cookie.py +++ b/nonebot_bison/config/migrations/f90b712557a9_add_cookie.py @@ -1,8 +1,8 @@ """empty message -Revision ID: ef796b74b0fe +Revision ID: f90b712557a9 Revises: f9baef347cc8 -Create Date: 2024-09-13 00:34:08.601438 +Create Date: 2024-09-23 10:03:30.593263 """ @@ -12,7 +12,7 @@ from sqlalchemy import Text from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. -revision = "ef796b74b0fe" +revision = "f90b712557a9" down_revision = "f9baef347cc8" branch_labels = None depends_on = None @@ -25,6 +25,7 @@ def upgrade() -> None: sa.Column("id", sa.Integer(), nullable=False), sa.Column("site_name", sa.String(length=100), nullable=False), sa.Column("content", sa.String(length=1024), nullable=False), + sa.Column("cookie_name", sa.String(length=1024), nullable=False), sa.Column("last_usage", sa.DateTime(), nullable=False), sa.Column("status", sa.String(length=20), nullable=False), sa.Column("cd_milliseconds", sa.Integer(), nullable=False), diff --git a/nonebot_bison/platform/rss.py b/nonebot_bison/platform/rss.py index de8936b..fbc5cb9 100644 --- a/nonebot_bison/platform/rss.py +++ b/nonebot_bison/platform/rss.py @@ -9,11 +9,11 @@ from bs4 import BeautifulSoup as bs from ..post import Post from .platform import NewMessage from ..types import Target, RawPost -from ..utils import Site, text_similarity -from ..utils.site import create_cookie_client_manager +from ..utils import text_similarity +from ..utils.site import CookieSite, create_cookie_client_manager -class RssSite(Site): +class RssSite(CookieSite): name = "rss" schedule_type = "interval" schedule_setting = {"seconds": 30} diff --git a/nonebot_bison/platform/weibo.py b/nonebot_bison/platform/weibo.py index 3e3ba6a..b5dd7d7 100644 --- a/nonebot_bison/platform/weibo.py +++ b/nonebot_bison/platform/weibo.py @@ -11,10 +11,10 @@ from nonebot.log import logger from bs4 import BeautifulSoup as bs from ..post import Post +from ..utils import http_client from .platform import NewMessage -from ..utils import Site, http_client -from ..utils.site import create_cookie_client_manager from ..types import Tag, Target, RawPost, ApiError, Category +from ..utils.site import CookieSite, create_cookie_client_manager _HEADER = { "accept": ( @@ -36,7 +36,7 @@ _HEADER = { } -class WeiboSite(Site): +class WeiboSite(CookieSite): name = "weibo.com" schedule_type = "interval" schedule_setting = {"seconds": 3} diff --git a/nonebot_bison/sub_manager/add_cookie_target.py b/nonebot_bison/sub_manager/add_cookie_target.py index 73d72e2..8c5cc7a 100644 --- a/nonebot_bison/sub_manager/add_cookie_target.py +++ b/nonebot_bison/sub_manager/add_cookie_target.py @@ -1,5 +1,3 @@ -from typing import cast - from nonebot.typing import T_State from nonebot.matcher import Matcher from nonebot.params import ArgPlainText @@ -9,7 +7,6 @@ from nonebot.internal.adapter import MessageTemplate from ..config import config from ..utils import parse_text from ..platform import platform_manager -from ..utils.site import CookieClientManager from .utils import gen_handle_cancel, generate_sub_list_text @@ -51,9 +48,8 @@ def do_add_cookie_target(add_cookie_target_matcher: type[Matcher]): ) state["cookies"] = cookies - client_mgr = cast(CookieClientManager, state["site"].client_mgr) state["_prompt"] = "请选择一个 Cookie,已关联的 Cookie 不会显示\n" + "\n".join( - [f"{idx}. {await client_mgr.get_cookie_friendly_name(cookie)}" for idx, cookie in enumerate(cookies, 1)] + [f"{idx}. {cookie.cookie_name}" for idx, cookie in enumerate(cookies, 1)] ) @add_cookie_target_matcher.got("cookie_idx", MessageTemplate("{_prompt}"), [handle_cancel]) @@ -68,8 +64,6 @@ def do_add_cookie_target(add_cookie_target_matcher: type[Matcher]): async def add_cookie_target_process(state: T_State): await config.add_cookie_target(state["target"]["target"], state["target"]["platform_name"], state["cookie"].id) cookie = state["cookie"] - client_mgr = cast(CookieClientManager, state["site"].client_mgr) await add_cookie_target_matcher.finish( - f"已关联 Cookie: {await client_mgr.get_cookie_friendly_name(cookie)} " - f"到订阅 {state['site'].name} {state['target']['target']}" + f"已关联 Cookie: {cookie.cookie_name} " f"到订阅 {state['site'].name} {state['target']['target']}" ) diff --git a/nonebot_bison/sub_manager/del_cookie.py b/nonebot_bison/sub_manager/del_cookie.py index 0ccbfe4..901382a 100644 --- a/nonebot_bison/sub_manager/del_cookie.py +++ b/nonebot_bison/sub_manager/del_cookie.py @@ -5,7 +5,6 @@ from nonebot_plugin_saa import MessageFactory from ..config import config from ..utils import parse_text -from ..platform import site_manager from .utils import gen_handle_cancel @@ -21,9 +20,7 @@ def do_del_cookie(del_cookie: type[Matcher]): state["cookie_table"] = {} for index, cookie in enumerate(cookies, 1): state["cookie_table"][index] = cookie - client_mgr = site_manager[cookie.site_name].client_mgr - friendly_name = await client_mgr.get_cookie_friendly_name(cookie) - res += f"{index} {cookie.site_name} {friendly_name} {len(cookie.targets)}个关联\n" + res += f"{index} {cookie.site_name} {cookie.cookie_name} {len(cookie.targets)}个关联\n" if res[-1] != "\n": res += "\n" res += "请输入要删除的 Cookie 的序号\n输入'取消'中止" diff --git a/nonebot_bison/sub_manager/del_cookie_target.py b/nonebot_bison/sub_manager/del_cookie_target.py index d161924..f5dce4d 100644 --- a/nonebot_bison/sub_manager/del_cookie_target.py +++ b/nonebot_bison/sub_manager/del_cookie_target.py @@ -1,5 +1,3 @@ -from typing import cast - from nonebot.typing import T_State from nonebot.matcher import Matcher from nonebot.params import EventPlainText @@ -8,8 +6,6 @@ from nonebot_plugin_saa import MessageFactory from ..config import config from ..utils import parse_text from .utils import gen_handle_cancel -from ..platform import platform_manager -from ..utils.site import CookieClientManager def do_del_cookie_target(del_cookie_target: type[Matcher]): @@ -23,8 +19,7 @@ def do_del_cookie_target(del_cookie_target: type[Matcher]): res = "已关联的 Cookie 为:\n" state["cookie_target_table"] = {} for index, cookie_target in enumerate(cookie_targets, 1): - client_mgr = cast(CookieClientManager, platform_manager[cookie_target.target.platform_name].site.client_mgr) - friendly_name = await client_mgr.get_cookie_friendly_name(cookie_target.cookie) + friendly_name = cookie_target.cookie.cookie_name state["cookie_target_table"][index] = { "platform_name": cookie_target.target.platform_name, "target": cookie_target.target, diff --git a/nonebot_bison/sub_manager/utils.py b/nonebot_bison/sub_manager/utils.py index a74d8ac..1e462c4 100644 --- a/nonebot_bison/sub_manager/utils.py +++ b/nonebot_bison/sub_manager/utils.py @@ -1,7 +1,7 @@ import contextlib +from typing import Annotated from itertools import groupby from operator import attrgetter -from typing import Annotated, cast from nonebot.rule import Rule from nonebot.adapters import Event @@ -13,9 +13,9 @@ from nonebot_plugin_saa import PlatformTarget, extract_target from ..config import config from ..types import Category +from ..platform import platform_manager from ..plugin_config import plugin_config -from ..platform import site_manager, platform_manager -from ..utils.site import CookieClientManager, is_cookie_client_manager +from ..utils.site import is_cookie_client_manager def _configurable_to_me(to_me: bool = EventToMe()): @@ -114,8 +114,7 @@ async def generate_sub_list_text( if target_cookies: res += " 关联的 Cookie:\n" for cookie in target_cookies: - client_mgr = cast(CookieClientManager, site_manager[platform.site.name].client_mgr) - res += f" \t{await client_mgr.get_cookie_friendly_name(cookie)}\n" + res += f" \t{cookie.cookie_name}\n" else: res += f" (平台 {sub.target.platform_name} 已失效,请删除此订阅)" diff --git a/nonebot_bison/utils/site.py b/nonebot_bison/utils/site.py index 54716c9..8410a45 100644 --- a/nonebot_bison/utils/site.py +++ b/nonebot_bison/utils/site.py @@ -1,6 +1,6 @@ import json -from typing import Literal from json import JSONDecodeError +from typing import Literal, cast from abc import ABC, abstractmethod from datetime import datetime, timedelta @@ -62,13 +62,20 @@ class CookieClientManager(ClientManager): @classmethod async def add_user_cookie(cls, content: str): """添加用户 cookie""" + from ..platform import site_manager + + cookie_site = cast(type[CookieSite], site_manager[cls._site_name]) + if not await cls.validate_cookie(content): + raise ValueError() cookie = Cookie(site_name=cls._site_name, content=content) + cookie.cookie_name = cookie_site.get_cookie_name(content) cookie.cd = cls._default_cd await config.add_cookie(cookie) @classmethod async def validate_cookie(cls, content: str) -> bool: """验证 cookie 内容是否有效,添加 cookie 时用,可根据平台的具体情况进行重写""" + # todo: 考虑移动到 cookie site 中 try: data = json.loads(content) if not isinstance(data, dict): @@ -77,13 +84,6 @@ class CookieClientManager(ClientManager): return False return True - @classmethod - async def get_cookie_friendly_name(cls, cookie: Cookie) -> str: - """获取 cookie 的友好名字,用于展示""" - from . import text_fletten - - return text_fletten(f"{cookie.site_name} [{cookie.content[:10]}]") - def _generate_hook(self, cookie: Cookie) -> callable: """hook 函数生成器,用于回写请求状态到数据库""" @@ -156,12 +156,23 @@ class Site(metaclass=RegistryMeta, base=True): client_mgr: type[ClientManager] = DefaultClientManager require_browser: bool = False registry: list[type["Site"]] - cookie_format_prompt = "无效的 Cookie,请检查后重新输入,详情见<待添加的文档>" def __str__(self): return f"[{self.name}]-{self.name}-{self.schedule_setting}" +class CookieSite(Site): + client_mgr: type[CookieClientManager] = CookieClientManager + cookie_format_prompt = "无效的 Cookie,请检查后重新输入,详情见<待添加的文档>" + + @classmethod + def get_cookie_name(cls, content: str) -> str: + """从cookie内容中获取cookie的友好名字,添加cookie时调用,持久化在数据库中""" + from . import text_fletten + + return text_fletten(f"{cls.name} [{content[:10]}]") + + def anonymous_site(schedule_type: Literal["date", "interval", "cron"], schedule_setting: dict) -> type[Site]: return type( "AnonymousSite",