在 cookie 中添加 cookie_name 字段

This commit is contained in:
suyiiyii 2024-09-23 10:27:27 +08:00
parent 59d42531a3
commit 8742de6cd1
11 changed files with 44 additions and 46 deletions

View File

@ -210,15 +210,13 @@ async def update_weigth_config(platformName: str, target: str, weight_config: We
@router.get("/cookie", dependencies=[Depends(check_is_superuser)]) @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) 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 [ return [
Cookie( Cookie(
id=cookies_in_db[i].id, 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, site_name=cookies_in_db[i].site_name,
last_usage=cookies_in_db[i].last_usage, last_usage=cookies_in_db[i].last_usage,
status=cookies_in_db[i].status, status=cookies_in_db[i].status,

View File

@ -298,6 +298,7 @@ class DBConfig:
if not cookie_in_db: if not cookie_in_db:
raise ValueError(f"cookie {cookie.id} not found") raise ValueError(f"cookie {cookie.id} not found")
cookie_in_db.content = cookie.content 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.last_usage = cookie.last_usage
cookie_in_db.status = cookie.status cookie_in_db.status = cookie.status
cookie_in_db.tags = cookie.tags cookie_in_db.tags = cookie.tags

View File

@ -74,6 +74,8 @@ class Cookie(Model):
id: Mapped[int] = mapped_column(primary_key=True) id: Mapped[int] = mapped_column(primary_key=True)
site_name: Mapped[str] = mapped_column(String(100)) site_name: Mapped[str] = mapped_column(String(100))
content: Mapped[str] = mapped_column(String(1024)) 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)) last_usage: Mapped[datetime.datetime] = mapped_column(DateTime, default=datetime.datetime(1970, 1, 1))
# Cookie 当前的状态 # Cookie 当前的状态

View File

@ -1,8 +1,8 @@
"""empty message """empty message
Revision ID: ef796b74b0fe Revision ID: f90b712557a9
Revises: f9baef347cc8 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 from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = "ef796b74b0fe" revision = "f90b712557a9"
down_revision = "f9baef347cc8" down_revision = "f9baef347cc8"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
@ -25,6 +25,7 @@ def upgrade() -> None:
sa.Column("id", sa.Integer(), nullable=False), sa.Column("id", sa.Integer(), nullable=False),
sa.Column("site_name", sa.String(length=100), nullable=False), sa.Column("site_name", sa.String(length=100), nullable=False),
sa.Column("content", sa.String(length=1024), 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("last_usage", sa.DateTime(), nullable=False),
sa.Column("status", sa.String(length=20), nullable=False), sa.Column("status", sa.String(length=20), nullable=False),
sa.Column("cd_milliseconds", sa.Integer(), nullable=False), sa.Column("cd_milliseconds", sa.Integer(), nullable=False),

View File

@ -9,11 +9,11 @@ from bs4 import BeautifulSoup as bs
from ..post import Post from ..post import Post
from .platform import NewMessage from .platform import NewMessage
from ..types import Target, RawPost from ..types import Target, RawPost
from ..utils import Site, text_similarity from ..utils import text_similarity
from ..utils.site import create_cookie_client_manager from ..utils.site import CookieSite, create_cookie_client_manager
class RssSite(Site): class RssSite(CookieSite):
name = "rss" name = "rss"
schedule_type = "interval" schedule_type = "interval"
schedule_setting = {"seconds": 30} schedule_setting = {"seconds": 30}

View File

@ -11,10 +11,10 @@ from nonebot.log import logger
from bs4 import BeautifulSoup as bs from bs4 import BeautifulSoup as bs
from ..post import Post from ..post import Post
from ..utils import http_client
from .platform import NewMessage 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 ..types import Tag, Target, RawPost, ApiError, Category
from ..utils.site import CookieSite, create_cookie_client_manager
_HEADER = { _HEADER = {
"accept": ( "accept": (
@ -36,7 +36,7 @@ _HEADER = {
} }
class WeiboSite(Site): class WeiboSite(CookieSite):
name = "weibo.com" name = "weibo.com"
schedule_type = "interval" schedule_type = "interval"
schedule_setting = {"seconds": 3} schedule_setting = {"seconds": 3}

View File

@ -1,5 +1,3 @@
from typing import cast
from nonebot.typing import T_State from nonebot.typing import T_State
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.params import ArgPlainText from nonebot.params import ArgPlainText
@ -9,7 +7,6 @@ from nonebot.internal.adapter import MessageTemplate
from ..config import config from ..config import config
from ..utils import parse_text from ..utils import parse_text
from ..platform import platform_manager from ..platform import platform_manager
from ..utils.site import CookieClientManager
from .utils import gen_handle_cancel, generate_sub_list_text 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 state["cookies"] = cookies
client_mgr = cast(CookieClientManager, state["site"].client_mgr)
state["_prompt"] = "请选择一个 Cookie已关联的 Cookie 不会显示\n" + "\n".join( 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]) @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): async def add_cookie_target_process(state: T_State):
await config.add_cookie_target(state["target"]["target"], state["target"]["platform_name"], state["cookie"].id) await config.add_cookie_target(state["target"]["target"], state["target"]["platform_name"], state["cookie"].id)
cookie = state["cookie"] cookie = state["cookie"]
client_mgr = cast(CookieClientManager, state["site"].client_mgr)
await add_cookie_target_matcher.finish( await add_cookie_target_matcher.finish(
f"已关联 Cookie: {await client_mgr.get_cookie_friendly_name(cookie)} " f"已关联 Cookie: {cookie.cookie_name} " f"到订阅 {state['site'].name} {state['target']['target']}"
f"到订阅 {state['site'].name} {state['target']['target']}"
) )

View File

@ -5,7 +5,6 @@ from nonebot_plugin_saa import MessageFactory
from ..config import config from ..config import config
from ..utils import parse_text from ..utils import parse_text
from ..platform import site_manager
from .utils import gen_handle_cancel from .utils import gen_handle_cancel
@ -21,9 +20,7 @@ def do_del_cookie(del_cookie: type[Matcher]):
state["cookie_table"] = {} state["cookie_table"] = {}
for index, cookie in enumerate(cookies, 1): for index, cookie in enumerate(cookies, 1):
state["cookie_table"][index] = cookie state["cookie_table"][index] = cookie
client_mgr = site_manager[cookie.site_name].client_mgr res += f"{index} {cookie.site_name} {cookie.cookie_name} {len(cookie.targets)}个关联\n"
friendly_name = await client_mgr.get_cookie_friendly_name(cookie)
res += f"{index} {cookie.site_name} {friendly_name} {len(cookie.targets)}个关联\n"
if res[-1] != "\n": if res[-1] != "\n":
res += "\n" res += "\n"
res += "请输入要删除的 Cookie 的序号\n输入'取消'中止" res += "请输入要删除的 Cookie 的序号\n输入'取消'中止"

View File

@ -1,5 +1,3 @@
from typing import cast
from nonebot.typing import T_State from nonebot.typing import T_State
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.params import EventPlainText from nonebot.params import EventPlainText
@ -8,8 +6,6 @@ from nonebot_plugin_saa import MessageFactory
from ..config import config from ..config import config
from ..utils import parse_text from ..utils import parse_text
from .utils import gen_handle_cancel 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]): 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" res = "已关联的 Cookie 为:\n"
state["cookie_target_table"] = {} state["cookie_target_table"] = {}
for index, cookie_target in enumerate(cookie_targets, 1): 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 = cookie_target.cookie.cookie_name
friendly_name = await client_mgr.get_cookie_friendly_name(cookie_target.cookie)
state["cookie_target_table"][index] = { state["cookie_target_table"][index] = {
"platform_name": cookie_target.target.platform_name, "platform_name": cookie_target.target.platform_name,
"target": cookie_target.target, "target": cookie_target.target,

View File

@ -1,7 +1,7 @@
import contextlib import contextlib
from typing import Annotated
from itertools import groupby from itertools import groupby
from operator import attrgetter from operator import attrgetter
from typing import Annotated, cast
from nonebot.rule import Rule from nonebot.rule import Rule
from nonebot.adapters import Event from nonebot.adapters import Event
@ -13,9 +13,9 @@ from nonebot_plugin_saa import PlatformTarget, extract_target
from ..config import config from ..config import config
from ..types import Category from ..types import Category
from ..platform import platform_manager
from ..plugin_config import plugin_config from ..plugin_config import plugin_config
from ..platform import site_manager, platform_manager from ..utils.site import is_cookie_client_manager
from ..utils.site import CookieClientManager, is_cookie_client_manager
def _configurable_to_me(to_me: bool = EventToMe()): def _configurable_to_me(to_me: bool = EventToMe()):
@ -114,8 +114,7 @@ async def generate_sub_list_text(
if target_cookies: if target_cookies:
res += " 关联的 Cookie\n" res += " 关联的 Cookie\n"
for cookie in target_cookies: for cookie in target_cookies:
client_mgr = cast(CookieClientManager, site_manager[platform.site.name].client_mgr) res += f" \t{cookie.cookie_name}\n"
res += f" \t{await client_mgr.get_cookie_friendly_name(cookie)}\n"
else: else:
res += f" (平台 {sub.target.platform_name} 已失效,请删除此订阅)" res += f" (平台 {sub.target.platform_name} 已失效,请删除此订阅)"

View File

@ -1,6 +1,6 @@
import json import json
from typing import Literal
from json import JSONDecodeError from json import JSONDecodeError
from typing import Literal, cast
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -62,13 +62,20 @@ class CookieClientManager(ClientManager):
@classmethod @classmethod
async def add_user_cookie(cls, content: str): async def add_user_cookie(cls, content: str):
"""添加用户 cookie""" """添加用户 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(site_name=cls._site_name, content=content)
cookie.cookie_name = cookie_site.get_cookie_name(content)
cookie.cd = cls._default_cd cookie.cd = cls._default_cd
await config.add_cookie(cookie) await config.add_cookie(cookie)
@classmethod @classmethod
async def validate_cookie(cls, content: str) -> bool: async def validate_cookie(cls, content: str) -> bool:
"""验证 cookie 内容是否有效,添加 cookie 时用,可根据平台的具体情况进行重写""" """验证 cookie 内容是否有效,添加 cookie 时用,可根据平台的具体情况进行重写"""
# todo: 考虑移动到 cookie site 中
try: try:
data = json.loads(content) data = json.loads(content)
if not isinstance(data, dict): if not isinstance(data, dict):
@ -77,13 +84,6 @@ class CookieClientManager(ClientManager):
return False return False
return True 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: def _generate_hook(self, cookie: Cookie) -> callable:
"""hook 函数生成器,用于回写请求状态到数据库""" """hook 函数生成器,用于回写请求状态到数据库"""
@ -156,12 +156,23 @@ class Site(metaclass=RegistryMeta, base=True):
client_mgr: type[ClientManager] = DefaultClientManager client_mgr: type[ClientManager] = DefaultClientManager
require_browser: bool = False require_browser: bool = False
registry: list[type["Site"]] registry: list[type["Site"]]
cookie_format_prompt = "无效的 Cookie请检查后重新输入详情见<待添加的文档>"
def __str__(self): def __str__(self):
return f"[{self.name}]-{self.name}-{self.schedule_setting}" 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]: def anonymous_site(schedule_type: Literal["date", "interval", "cron"], schedule_setting: dict) -> type[Site]:
return type( return type(
"AnonymousSite", "AnonymousSite",