diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
index 7269cd8..cbec41c 100644
--- a/.github/workflows/ruff.yml
+++ b/.github/workflows/ruff.yml
@@ -19,4 +19,9 @@ jobs:
- uses: actions/checkout@v4
- name: Run Ruff Lint
- uses: chartboost/ruff-action@v1
+ uses: astral-sh/ruff-action@v2
+ with:
+ src: >-
+ nonebot_bison/
+ extra_plugins/
+ tests/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index a8c8b66..c5a1554 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -7,22 +7,12 @@ ci:
autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks"
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.8.1
+ rev: v0.8.2
hooks:
- id: ruff
- args: [--fix, --exit-non-zero-on-fix]
+ args: [--fix]
stages: [pre-commit]
-
- - repo: https://github.com/pycqa/isort
- rev: 5.13.2
- hooks:
- - id: isort
- stages: [pre-commit]
-
- - repo: https://github.com/psf/black
- rev: 24.10.0
- hooks:
- - id: black
+ - id: ruff-format
stages: [pre-commit]
- repo: https://github.com/pre-commit/mirrors-prettier
diff --git a/README.md b/README.md
index 266bb16..4419b70 100644
--- a/README.md
+++ b/README.md
@@ -17,9 +17,6 @@ _✨ 通用订阅推送插件 ✨_
-
-
-
diff --git a/extra_plugins/auto_agree.py b/extra_plugins/auto_agree.py
index 53a85a4..8078a72 100644
--- a/extra_plugins/auto_agree.py
+++ b/extra_plugins/auto_agree.py
@@ -1,7 +1,7 @@
from nonebot import on_request
-from nonebot.log import logger
from nonebot.adapters.onebot.v11 import Bot
-from nonebot.adapters.onebot.v11.event import GroupRequestEvent, FriendRequestEvent
+from nonebot.adapters.onebot.v11.event import FriendRequestEvent, GroupRequestEvent
+from nonebot.log import logger
friend_req = on_request(priority=5)
diff --git a/nonebot_bison/__init__.py b/nonebot_bison/__init__.py
index 90da7a1..e939ec9 100644
--- a/nonebot_bison/__init__.py
+++ b/nonebot_bison/__init__.py
@@ -6,8 +6,8 @@ require("nonebot_plugin_saa")
import nonebot_plugin_saa
+from . import admin_page, bootstrap, config, platform, post, scheduler, send, sub_manager, theme, types, utils
from .plugin_config import PlugConfig, plugin_config
-from . import post, send, theme, types, utils, config, platform, bootstrap, scheduler, admin_page, sub_manager
__help__version__ = "0.8.2"
nonebot_plugin_saa.enable_auto_select_bot()
@@ -36,12 +36,12 @@ __all__ = [
"admin_page",
"bootstrap",
"config",
- "sub_manager",
+ "platform",
"post",
"scheduler",
"send",
- "platform",
+ "sub_manager",
+ "theme",
"types",
"utils",
- "theme",
]
diff --git a/nonebot_bison/admin_page/__init__.py b/nonebot_bison/admin_page/__init__.py
index c888bf0..02d0fb6 100644
--- a/nonebot_bison/admin_page/__init__.py
+++ b/nonebot_bison/admin_page/__init__.py
@@ -2,15 +2,16 @@ import os
from pathlib import Path
from typing import TYPE_CHECKING
-from nonebot.log import logger
-from nonebot.rule import to_me
-from nonebot.typing import T_State
from nonebot import get_driver, on_command
from nonebot.adapters.onebot.v11 import Bot
from nonebot.adapters.onebot.v11.event import PrivateMessageEvent
+from nonebot.log import logger
+from nonebot.rule import to_me
+from nonebot.typing import T_State
+
+from nonebot_bison.plugin_config import plugin_config
from .api import router as api_router
-from ..plugin_config import plugin_config
from .token_manager import token_manager as tm
if TYPE_CHECKING:
@@ -21,9 +22,9 @@ STATIC_PATH = (Path(__file__).parent / "dist").resolve()
def init_fastapi(driver: "Driver"):
- import socketio
from fastapi.applications import FastAPI
from fastapi.staticfiles import StaticFiles
+ import socketio
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*")
socket_app = socketio.ASGIApp(sio, socketio_path="socket")
diff --git a/nonebot_bison/admin_page/api.py b/nonebot_bison/admin_page/api.py
index da8208c..c816e75 100644
--- a/nonebot_bison/admin_page/api.py
+++ b/nonebot_bison/admin_page/api.py
@@ -1,38 +1,39 @@
from typing import cast
-import nonebot
from fastapi import status
-from fastapi.routing import APIRouter
-from fastapi.param_functions import Depends
from fastapi.exceptions import HTTPException
+from fastapi.param_functions import Depends
+from fastapi.routing import APIRouter
+from fastapi.security.oauth2 import OAuth2PasswordBearer
+import nonebot
from nonebot_plugin_saa import TargetQQGroup
from nonebot_plugin_saa.auto_select_bot import get_bot
-from fastapi.security.oauth2 import OAuth2PasswordBearer
-from ..types import WeightConfig
-from ..apis import check_sub_target
+from nonebot_bison.apis import check_sub_target
+from nonebot_bison.config import NoSuchSubscribeException, NoSuchTargetException, NoSuchUserException, config
+from nonebot_bison.config.db_config import SubscribeDupException
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.scheduler import scheduler_dict
+from nonebot_bison.types import Target as T_Target
+from nonebot_bison.types import WeightConfig
+from nonebot_bison.utils.get_bot import get_groups
+from nonebot_bison.utils.site import CookieClientManager, is_cookie_client_manager, site_manager
+
from .jwt import load_jwt, pack_jwt
-from ..scheduler import scheduler_dict
-from ..types import Target as T_Target
-from ..utils.get_bot import get_groups
-from ..platform import platform_manager
from .token_manager import token_manager
-from ..config.db_config import SubscribeDupException
-from ..utils.site import CookieClientManager, site_manager, is_cookie_client_manager
-from ..config import NoSuchUserException, NoSuchTargetException, NoSuchSubscribeException, config
from .types import (
+ AddSubscribeReq,
Cookie,
- Target,
- TokenResp,
+ CookieTarget,
GlobalConf,
+ PlatformConfig,
SiteConfig,
StatusResp,
- CookieTarget,
- SubscribeResp,
- PlatformConfig,
- AddSubscribeReq,
SubscribeConfig,
SubscribeGroupDetail,
+ SubscribeResp,
+ Target,
+ TokenResp,
)
router = APIRouter(prefix="/api", tags=["api"])
diff --git a/nonebot_bison/admin_page/jwt.py b/nonebot_bison/admin_page/jwt.py
index 866c184..16cb1aa 100644
--- a/nonebot_bison/admin_page/jwt.py
+++ b/nonebot_bison/admin_page/jwt.py
@@ -1,6 +1,6 @@
+import datetime
import random
import string
-import datetime
import jwt
diff --git a/nonebot_bison/admin_page/token_manager.py b/nonebot_bison/admin_page/token_manager.py
index 365ee64..90c3e31 100644
--- a/nonebot_bison/admin_page/token_manager.py
+++ b/nonebot_bison/admin_page/token_manager.py
@@ -1,6 +1,6 @@
+from datetime import timedelta
import random
import string
-from datetime import timedelta
from expiringdictx import ExpiringDict
diff --git a/nonebot_bison/admin_page/types.py b/nonebot_bison/admin_page/types.py
index a43e90d..316dc7c 100644
--- a/nonebot_bison/admin_page/types.py
+++ b/nonebot_bison/admin_page/types.py
@@ -60,8 +60,8 @@ class StatusResp(BaseModel):
msg: str
-from typing import Any
from datetime import datetime
+from typing import Any
from pydantic import BaseModel
diff --git a/nonebot_bison/apis.py b/nonebot_bison/apis.py
index f13580b..ef81f4c 100644
--- a/nonebot_bison/apis.py
+++ b/nonebot_bison/apis.py
@@ -1,6 +1,6 @@
-from .types import Target
-from .scheduler import scheduler_dict
from .platform import platform_manager
+from .scheduler import scheduler_dict
+from .types import Target
async def check_sub_target(platform_name: str, target: Target):
diff --git a/nonebot_bison/bootstrap.py b/nonebot_bison/bootstrap.py
index 92d06a8..b655966 100644
--- a/nonebot_bison/bootstrap.py
+++ b/nonebot_bison/bootstrap.py
@@ -1,10 +1,10 @@
from nonebot.log import logger
-from sqlalchemy import text, inspect
-from nonebot_plugin_datastore.db import get_engine, pre_db_init, post_db_init
+from nonebot_plugin_datastore.db import get_engine, post_db_init, pre_db_init
+from sqlalchemy import inspect, text
+from .config.config_legacy import start_up as legacy_db_startup
from .config.db_migration import data_migrate
from .scheduler.manager import init_scheduler
-from .config.config_legacy import start_up as legacy_db_startup
@pre_db_init
diff --git a/nonebot_bison/compat.py b/nonebot_bison/compat.py
index d4a65a5..2d40fdb 100644
--- a/nonebot_bison/compat.py
+++ b/nonebot_bison/compat.py
@@ -1,9 +1,9 @@
from typing import Literal, overload
-from pydantic import BaseModel
from nonebot.compat import PYDANTIC_V2
+from pydantic import BaseModel
-__all__ = ("model_validator", "model_rebuild")
+__all__ = ("model_rebuild", "model_validator")
if PYDANTIC_V2:
diff --git a/nonebot_bison/config/__init__.py b/nonebot_bison/config/__init__.py
index a04d41f..b3e2d76 100644
--- a/nonebot_bison/config/__init__.py
+++ b/nonebot_bison/config/__init__.py
@@ -1,4 +1,4 @@
from .db_config import config as config
-from .utils import NoSuchUserException as NoSuchUserException
-from .utils import NoSuchTargetException as NoSuchTargetException
from .utils import NoSuchSubscribeException as NoSuchSubscribeException
+from .utils import NoSuchTargetException as NoSuchTargetException
+from .utils import NoSuchUserException as NoSuchUserException
diff --git a/nonebot_bison/config/config_legacy.py b/nonebot_bison/config/config_legacy.py
index 24e7e4d..a0b4c08 100644
--- a/nonebot_bison/config/config_legacy.py
+++ b/nonebot_bison/config/config_legacy.py
@@ -1,19 +1,20 @@
-import os
+from collections import defaultdict
+from datetime import datetime
import json
+import os
from os import path
from pathlib import Path
-from datetime import datetime
-from collections import defaultdict
from typing import Literal, TypedDict
from nonebot.log import logger
from tinydb import Query, TinyDB
-from ..utils import Singleton
-from ..types import User, Target
-from ..platform import platform_manager
-from ..plugin_config import plugin_config
-from .utils import NoSuchUserException, NoSuchSubscribeException
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.plugin_config import plugin_config
+from nonebot_bison.types import Target, User
+from nonebot_bison.utils import Singleton
+
+from .utils import NoSuchSubscribeException, NoSuchUserException
supported_target_type = platform_manager.keys()
diff --git a/nonebot_bison/config/db_config.py b/nonebot_bison/config/db_config.py
index c76078c..f6c6157 100644
--- a/nonebot_bison/config/db_config.py
+++ b/nonebot_bison/config/db_config.py
@@ -1,20 +1,20 @@
import asyncio
from collections import defaultdict
-from datetime import time, datetime
-from collections.abc import Callable, Sequence, Awaitable
+from collections.abc import Awaitable, Callable, Sequence
+from datetime import datetime, time
from nonebot.compat import model_dump
-from sqlalchemy.orm import selectinload
-from sqlalchemy.exc import IntegrityError
-from sqlalchemy import func, delete, select
-from nonebot_plugin_saa import PlatformTarget
from nonebot_plugin_datastore import create_session
+from nonebot_plugin_saa import PlatformTarget
+from sqlalchemy import delete, func, select
+from sqlalchemy.exc import IntegrityError
+from sqlalchemy.orm import selectinload
-from ..types import Tag
-from ..types import Target as T_Target
-from .utils import NoSuchTargetException, DuplicateCookieTargetException
-from .db_model import User, Cookie, Target, Subscribe, CookieTarget, ScheduleTimeWeight
-from ..types import Category, UserSubInfo, WeightConfig, TimeWeightConfig, PlatformWeightConfigResp
+from nonebot_bison.types import Category, PlatformWeightConfigResp, Tag, TimeWeightConfig, UserSubInfo, WeightConfig
+from nonebot_bison.types import Target as T_Target
+
+from .db_model import Cookie, CookieTarget, ScheduleTimeWeight, Subscribe, Target, User
+from .utils import DuplicateCookieTargetException, NoSuchTargetException
def _get_time():
diff --git a/nonebot_bison/config/db_migration.py b/nonebot_bison/config/db_migration.py
index 75080ad..1ff802a 100644
--- a/nonebot_bison/config/db_migration.py
+++ b/nonebot_bison/config/db_migration.py
@@ -1,11 +1,11 @@
-from nonebot.log import logger
from nonebot.compat import model_dump
+from nonebot.log import logger
from nonebot_plugin_datastore.db import get_engine
-from sqlalchemy.ext.asyncio.session import AsyncSession
from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate
+from sqlalchemy.ext.asyncio.session import AsyncSession
-from .db_model import User, Target, Subscribe
from .config_legacy import Config, ConfigContent, drop
+from .db_model import Subscribe, Target, User
async def data_migrate():
diff --git a/nonebot_bison/config/db_model.py b/nonebot_bison/config/db_model.py
index 94c7d0c..93991a7 100644
--- a/nonebot_bison/config/db_model.py
+++ b/nonebot_bison/config/db_model.py
@@ -1,15 +1,15 @@
import datetime
-from typing import Any
from pathlib import Path
+from typing import Any
-from nonebot_plugin_saa import PlatformTarget
-from sqlalchemy.dialects.postgresql import JSONB
from nonebot.compat import PYDANTIC_V2, ConfigDict
from nonebot_plugin_datastore import get_plugin_data
-from sqlalchemy.orm import Mapped, relationship, mapped_column
-from sqlalchemy import JSON, String, DateTime, ForeignKey, UniqueConstraint
+from nonebot_plugin_saa import PlatformTarget
+from sqlalchemy import JSON, DateTime, ForeignKey, String, UniqueConstraint
+from sqlalchemy.dialects.postgresql import JSONB
+from sqlalchemy.orm import Mapped, mapped_column, relationship
-from ..types import Tag, Category
+from nonebot_bison.types import Category, Tag
Model = get_plugin_data().Model
get_plugin_data().set_migration_dir(Path(__file__).parent / "migrations")
diff --git a/nonebot_bison/config/migrations/0571870f5222_init_db.py b/nonebot_bison/config/migrations/0571870f5222_init_db.py
index 391433f..9f7f334 100644
--- a/nonebot_bison/config/migrations/0571870f5222_init_db.py
+++ b/nonebot_bison/config/migrations/0571870f5222_init_db.py
@@ -6,8 +6,8 @@ Create Date: 2022-03-21 19:18:13.762626
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "0571870f5222"
diff --git a/nonebot_bison/config/migrations/4a46ba54a3f3_alter_type.py b/nonebot_bison/config/migrations/4a46ba54a3f3_alter_type.py
index 4dbeefe..e2e8c13 100644
--- a/nonebot_bison/config/migrations/4a46ba54a3f3_alter_type.py
+++ b/nonebot_bison/config/migrations/4a46ba54a3f3_alter_type.py
@@ -6,8 +6,8 @@ Create Date: 2022-03-27 21:50:10.911649
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "4a46ba54a3f3"
diff --git a/nonebot_bison/config/migrations/5f3370328e44_add_time_weight_table.py b/nonebot_bison/config/migrations/5f3370328e44_add_time_weight_table.py
index 696dfa7..bbfd27b 100644
--- a/nonebot_bison/config/migrations/5f3370328e44_add_time_weight_table.py
+++ b/nonebot_bison/config/migrations/5f3370328e44_add_time_weight_table.py
@@ -6,8 +6,8 @@ Create Date: 2022-05-31 22:05:13.235981
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "5f3370328e44"
diff --git a/nonebot_bison/config/migrations/632b8086bc2b_add_user_target.py b/nonebot_bison/config/migrations/632b8086bc2b_add_user_target.py
index a6f5e3a..26cc354 100644
--- a/nonebot_bison/config/migrations/632b8086bc2b_add_user_target.py
+++ b/nonebot_bison/config/migrations/632b8086bc2b_add_user_target.py
@@ -6,8 +6,8 @@ Create Date: 2023-03-20 00:39:30.199915
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import JSONB
# revision identifiers, used by Alembic.
diff --git a/nonebot_bison/config/migrations/67c38b3f39c2_make_user_target_not_nullable.py b/nonebot_bison/config/migrations/67c38b3f39c2_make_user_target_not_nullable.py
index 1f3e07a..dabcd10 100644
--- a/nonebot_bison/config/migrations/67c38b3f39c2_make_user_target_not_nullable.py
+++ b/nonebot_bison/config/migrations/67c38b3f39c2_make_user_target_not_nullable.py
@@ -6,8 +6,8 @@ Create Date: 2023-03-20 11:08:42.883556
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import JSONB
# revision identifiers, used by Alembic.
diff --git a/nonebot_bison/config/migrations/8d3863e9d74b_remove_uid_and_type.py b/nonebot_bison/config/migrations/8d3863e9d74b_remove_uid_and_type.py
index 649e7f6..4a272aa 100644
--- a/nonebot_bison/config/migrations/8d3863e9d74b_remove_uid_and_type.py
+++ b/nonebot_bison/config/migrations/8d3863e9d74b_remove_uid_and_type.py
@@ -6,8 +6,8 @@ Create Date: 2023-03-20 15:38:20.220599
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "8d3863e9d74b"
diff --git a/nonebot_bison/config/migrations/a333d6224193_add_last_scheduled_time.py b/nonebot_bison/config/migrations/a333d6224193_add_last_scheduled_time.py
index ad0892b..6f06592 100644
--- a/nonebot_bison/config/migrations/a333d6224193_add_last_scheduled_time.py
+++ b/nonebot_bison/config/migrations/a333d6224193_add_last_scheduled_time.py
@@ -6,8 +6,8 @@ Create Date: 2022-03-29 21:01:38.213153
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "a333d6224193"
diff --git a/nonebot_bison/config/migrations/a5466912fad0_map_user.py b/nonebot_bison/config/migrations/a5466912fad0_map_user.py
index c89098f..a87853e 100644
--- a/nonebot_bison/config/migrations/a5466912fad0_map_user.py
+++ b/nonebot_bison/config/migrations/a5466912fad0_map_user.py
@@ -6,10 +6,10 @@ Create Date: 2023-03-20 01:14:42.623789
"""
-import sqlalchemy as sa
from alembic import op
-from sqlalchemy.orm import Session
+import sqlalchemy as sa
from sqlalchemy.ext.automap import automap_base
+from sqlalchemy.orm import Session
# revision identifiers, used by Alembic.
revision = "a5466912fad0"
diff --git a/nonebot_bison/config/migrations/aceef470d69c_alter_fields_not_null.py b/nonebot_bison/config/migrations/aceef470d69c_alter_fields_not_null.py
index c51a400..07f9bd1 100644
--- a/nonebot_bison/config/migrations/aceef470d69c_alter_fields_not_null.py
+++ b/nonebot_bison/config/migrations/aceef470d69c_alter_fields_not_null.py
@@ -6,8 +6,8 @@ Create Date: 2023-03-09 19:10:42.168133
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "aceef470d69c"
diff --git a/nonebot_bison/config/migrations/bd92923c218f_alter_json_not_null.py b/nonebot_bison/config/migrations/bd92923c218f_alter_json_not_null.py
index aa3f2ff..fddec32 100644
--- a/nonebot_bison/config/migrations/bd92923c218f_alter_json_not_null.py
+++ b/nonebot_bison/config/migrations/bd92923c218f_alter_json_not_null.py
@@ -6,11 +6,11 @@ Create Date: 2023-03-02 14:04:16.492133
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
from sqlalchemy import select
-from sqlalchemy.orm import Session
from sqlalchemy.ext.automap import automap_base
+from sqlalchemy.orm import Session
# revision identifiers, used by Alembic.
revision = "bd92923c218f"
diff --git a/nonebot_bison/config/migrations/f90b712557a9_add_cookie.py b/nonebot_bison/config/migrations/f90b712557a9_add_cookie.py
index b89ce04..e759243 100644
--- a/nonebot_bison/config/migrations/f90b712557a9_add_cookie.py
+++ b/nonebot_bison/config/migrations/f90b712557a9_add_cookie.py
@@ -6,8 +6,8 @@ Create Date: 2024-09-23 10:03:30.593263
"""
-import sqlalchemy as sa
from alembic import op
+import sqlalchemy as sa
from sqlalchemy import Text
from sqlalchemy.dialects import postgresql
diff --git a/nonebot_bison/config/migrations/f9baef347cc8_remove_old_target.py b/nonebot_bison/config/migrations/f9baef347cc8_remove_old_target.py
index fbed082..b78a09a 100644
--- a/nonebot_bison/config/migrations/f9baef347cc8_remove_old_target.py
+++ b/nonebot_bison/config/migrations/f9baef347cc8_remove_old_target.py
@@ -6,10 +6,10 @@ Create Date: 2023-08-25 00:20:51.511329
"""
-import sqlalchemy as sa
from alembic import op
-from sqlalchemy.orm import Session
+import sqlalchemy as sa
from sqlalchemy.ext.automap import automap_base
+from sqlalchemy.orm import Session
# revision identifiers, used by Alembic.
revision = "f9baef347cc8"
diff --git a/nonebot_bison/config/subs_io/nbesf_model/__init__.py b/nonebot_bison/config/subs_io/nbesf_model/__init__.py
index dff07d0..3a57855 100644
--- a/nonebot_bison/config/subs_io/nbesf_model/__init__.py
+++ b/nonebot_bison/config/subs_io/nbesf_model/__init__.py
@@ -3,4 +3,4 @@
from . import v1, v2, v3
from .base import NBESFBase
-__all__ = ["v1", "v2", "v3", "NBESFBase"]
+__all__ = ["NBESFBase", "v1", "v2", "v3"]
diff --git a/nonebot_bison/config/subs_io/nbesf_model/base.py b/nonebot_bison/config/subs_io/nbesf_model/base.py
index 426c819..eab9bf5 100644
--- a/nonebot_bison/config/subs_io/nbesf_model/base.py
+++ b/nonebot_bison/config/subs_io/nbesf_model/base.py
@@ -1,10 +1,10 @@
from abc import ABC
-from pydantic import BaseModel
from nonebot.compat import PYDANTIC_V2, ConfigDict
from nonebot_plugin_saa.registries import AllSupportedPlatformTarget as UserInfo
+from pydantic import BaseModel
-from ....types import Tag, Category
+from nonebot_bison.types import Category, Tag
class NBESFBase(BaseModel, ABC):
diff --git a/nonebot_bison/config/subs_io/nbesf_model/v1.py b/nonebot_bison/config/subs_io/nbesf_model/v1.py
index 717deba..63ef67a 100644
--- a/nonebot_bison/config/subs_io/nbesf_model/v1.py
+++ b/nonebot_bison/config/subs_io/nbesf_model/v1.py
@@ -1,17 +1,18 @@
"""nbesf is Nonebot Bison Enchangable Subscribes File! ver.1"""
-from typing import Any
from functools import partial
+from typing import Any
-from nonebot.log import logger
-from pydantic import BaseModel
-from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate
from nonebot.compat import PYDANTIC_V2, ConfigDict, model_dump, type_validate_json, type_validate_python
+from nonebot.log import logger
+from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate
+from pydantic import BaseModel, Field
+
+from nonebot_bison.config.db_config import SubscribeDupException, config
+from nonebot_bison.config.subs_io.utils import NBESFParseErr
+from nonebot_bison.types import Category, Tag
-from ..utils import NBESFParseErr
-from ....types import Tag, Category
from .base import NBESFBase, SubReceipt
-from ...db_config import SubscribeDupException, config
# ===== nbesf 定义格式 ====== #
NBESF_VERSION = 1
@@ -79,7 +80,7 @@ class SubGroup(
"""
version: int = NBESF_VERSION
- groups: list[SubPack] = []
+ groups: list[SubPack] = Field(default_factory=list)
# ======================= #
@@ -108,11 +109,11 @@ async def subs_receipt_gen(nbesf_data: SubGroup):
try:
await config.add_subscribe(receipt.user, **model_dump(receipt, exclude={"user"}))
except SubscribeDupException:
- logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在")
+ logger.warning(f"!添加订阅条目 {receipt!r} 失败: 相同的订阅已存在")
except Exception as e:
- logger.error(f"!添加订阅条目 {repr(receipt)} 失败: {repr(e)}")
+ logger.error(f"!添加订阅条目 {receipt!r} 失败: {e!r}")
else:
- logger.success(f"添加订阅条目 {repr(receipt)} 成功!")
+ logger.success(f"添加订阅条目 {receipt!r} 成功!")
def nbesf_parser(raw_data: Any) -> SubGroup:
diff --git a/nonebot_bison/config/subs_io/nbesf_model/v2.py b/nonebot_bison/config/subs_io/nbesf_model/v2.py
index 714704f..a34383a 100644
--- a/nonebot_bison/config/subs_io/nbesf_model/v2.py
+++ b/nonebot_bison/config/subs_io/nbesf_model/v2.py
@@ -1,17 +1,18 @@
"""nbesf is Nonebot Bison Enchangable Subscribes File! ver.2"""
-from typing import Any
from functools import partial
+from typing import Any
-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 nonebot.log import logger
+from nonebot_plugin_saa.registries import AllSupportedPlatformTarget
+from pydantic import BaseModel, Field
+
+from nonebot_bison.config.db_config import SubscribeDupException, config
+from nonebot_bison.config.subs_io.utils import NBESFParseErr
+from nonebot_bison.types import Category, Tag
-from ..utils import NBESFParseErr
-from ....types import Tag, Category
from .base import NBESFBase, SubReceipt
-from ...db_config import SubscribeDupException, config
# ===== nbesf 定义格式 ====== #
NBESF_VERSION = 2
@@ -64,7 +65,7 @@ class SubGroup(NBESFBase):
"""
version: int = NBESF_VERSION
- groups: list[SubPack] = []
+ groups: list[SubPack] = Field(default_factory=list)
# ======================= #
@@ -85,11 +86,11 @@ async def subs_receipt_gen(nbesf_data: SubGroup):
try:
await config.add_subscribe(receipt.user, **model_dump(receipt, exclude={"user"}))
except SubscribeDupException:
- logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在")
+ logger.warning(f"!添加订阅条目 {receipt!r} 失败: 相同的订阅已存在")
except Exception as e:
- logger.error(f"!添加订阅条目 {repr(receipt)} 失败: {repr(e)}")
+ logger.error(f"!添加订阅条目 {receipt!r} 失败: {e!r}")
else:
- logger.success(f"添加订阅条目 {repr(receipt)} 成功!")
+ logger.success(f"添加订阅条目 {receipt!r} 成功!")
def nbesf_parser(raw_data: Any) -> SubGroup:
diff --git a/nonebot_bison/config/subs_io/nbesf_model/v3.py b/nonebot_bison/config/subs_io/nbesf_model/v3.py
index c6f1c03..a24b0b2 100644
--- a/nonebot_bison/config/subs_io/nbesf_model/v3.py
+++ b/nonebot_bison/config/subs_io/nbesf_model/v3.py
@@ -1,21 +1,20 @@
"""nbesf is Nonebot Bison Enchangable Subscribes File! ver.2"""
-from typing import Any
from functools import partial
+from typing import Any
-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 nonebot.log import logger
+from nonebot_plugin_saa.registries import AllSupportedPlatformTarget
+from pydantic import BaseModel, Field
-from nonebot_bison.types import Tag
-from nonebot_bison.types import Category
+from nonebot_bison.config.db_config import SubscribeDupException, config
+from nonebot_bison.config.db_model import Cookie as DBCookie
+from nonebot_bison.config.subs_io.utils import NBESFParseErr
+from nonebot_bison.types import Category, Tag
from nonebot_bison.types import Target as T_Target
-from ..utils import NBESFParseErr
from .base import NBESFBase, SubReceipt
-from ...db_model import Cookie as DBCookie
-from ...db_config import SubscribeDupException, config
# ===== nbesf 定义格式 ====== #
NBESF_VERSION = 3
@@ -80,8 +79,8 @@ class SubGroup(NBESFBase):
"""
version: int = NBESF_VERSION
- groups: list[SubPack] = []
- cookies: list[Cookie] = []
+ groups: list[SubPack] = Field(default_factory=list)
+ cookies: list[Cookie] = Field(default_factory=list)
# ======================= #
@@ -103,11 +102,11 @@ async def subs_receipt_gen(nbesf_data: SubGroup):
try:
await config.add_subscribe(receipt.user, **model_dump(receipt, exclude={"user"}))
except SubscribeDupException:
- logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在")
+ logger.warning(f"!添加订阅条目 {receipt!r} 失败: 相同的订阅已存在")
except Exception as e:
- logger.error(f"!添加订阅条目 {repr(receipt)} 失败: {repr(e)}")
+ logger.error(f"!添加订阅条目 {receipt!r} 失败: {e!r}")
else:
- logger.success(f"添加订阅条目 {repr(receipt)} 成功!")
+ logger.success(f"添加订阅条目 {receipt!r} 成功!")
async def magic_cookie_gen(nbesf_data: SubGroup):
@@ -119,9 +118,9 @@ async def magic_cookie_gen(nbesf_data: SubGroup):
for target in cookie.targets:
await config.add_cookie_target(T_Target(target.target), target.platform_name, cookie_id)
except Exception as e:
- logger.error(f"!添加 Cookie 条目 {repr(cookie)} 失败: {repr(e)}")
+ logger.error(f"!添加 Cookie 条目 {cookie!r} 失败: {e!r}")
else:
- logger.success(f"添加 Cookie 条目 {repr(cookie)} 成功!")
+ logger.success(f"添加 Cookie 条目 {cookie!r} 成功!")
def nbesf_parser(raw_data: Any) -> SubGroup:
diff --git a/nonebot_bison/config/subs_io/subs_io.py b/nonebot_bison/config/subs_io/subs_io.py
index c871096..a0e1f23 100644
--- a/nonebot_bison/config/subs_io/subs_io.py
+++ b/nonebot_bison/config/subs_io/subs_io.py
@@ -1,19 +1,20 @@
-from typing import cast
from collections import defaultdict
from collections.abc import Callable
+from typing import cast
-from sqlalchemy import select
-from nonebot.log import logger
-from sqlalchemy.sql.selectable import Select
-from nonebot_plugin_saa import PlatformTarget
from nonebot.compat import type_validate_python
+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 nonebot_bison.config import config
+from nonebot_bison.config.db_model import Cookie, CookieTarget, Subscribe, Target, User
-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
+from .utils import NBESFVerMatchErr, row2dict
async def subscribes_export(selector: Callable[[Select], Select]) -> v3.SubGroup:
diff --git a/nonebot_bison/platform/__init__.py b/nonebot_bison/platform/__init__.py
index accdf83..19ebc31 100644
--- a/nonebot_bison/platform/__init__.py
+++ b/nonebot_bison/platform/__init__.py
@@ -1,9 +1,10 @@
-from pathlib import Path
-from pkgutil import iter_modules
from collections import defaultdict
from importlib import import_module
+from pathlib import Path
+from pkgutil import iter_modules
+
+from nonebot_bison.plugin_config import plugin_config
-from ..plugin_config import plugin_config
from .platform import Platform, make_no_target_group
_package_dir = str(Path(__file__).resolve().parent)
diff --git a/nonebot_bison/platform/arknights.py b/nonebot_bison/platform/arknights.py
index f22fd28..f15a368 100644
--- a/nonebot_bison/platform/arknights.py
+++ b/nonebot_bison/platform/arknights.py
@@ -1,18 +1,19 @@
-import re
-import html
-from typing import Any
from functools import partial
+import html
+import re
+from typing import Any, ClassVar
-from yarl import URL
-from httpx import AsyncClient
from bs4 import BeautifulSoup as bs
-from pydantic import Field, BaseModel
+from httpx import AsyncClient
from nonebot.compat import type_validate_python
+from pydantic import BaseModel, Field
+from yarl import URL
+
+from nonebot_bison.post import Post
+from nonebot_bison.post.protocol import HTMLContentSupport
+from nonebot_bison.types import Category, RawPost, Target
+from nonebot_bison.utils import Site
-from ..post import Post
-from ..utils import Site
-from ..types import Target, RawPost, Category
-from ..post.protocol import HTMLContentSupport
from .platform import NewMessage, StatusChange
@@ -58,7 +59,7 @@ class ArkBulletinResponse(ArkResponseBase):
class ArknightsSite(Site):
name = "arknights"
schedule_type = "interval"
- schedule_setting = {"seconds": 30}
+ schedule_setting: ClassVar[dict] = {"seconds": 30}
class ArknightsPost(Post, HTMLContentSupport):
@@ -95,7 +96,7 @@ class ArknightsPost(Post, HTMLContentSupport):
class Arknights(NewMessage):
- categories = {1: "游戏公告"}
+ categories: ClassVar[dict[Category, str]] = {1: "游戏公告"}
platform_name = "arknights"
name = "明日方舟游戏信息"
enable_tag = False
@@ -157,7 +158,7 @@ class Arknights(NewMessage):
class AkVersion(StatusChange):
- categories = {2: "更新信息"}
+ categories: ClassVar[dict[Category, str]] = {2: "更新信息"}
platform_name = "arknights"
name = "明日方舟游戏信息"
enable_tag = False
@@ -202,7 +203,7 @@ class AkVersion(StatusChange):
class MonsterSiren(NewMessage):
- categories = {3: "塞壬唱片新闻"}
+ categories: ClassVar[dict[Category, str]] = {3: "塞壬唱片新闻"}
platform_name = "arknights"
name = "明日方舟游戏信息"
enable_tag = False
@@ -250,7 +251,7 @@ class MonsterSiren(NewMessage):
class TerraHistoricusComic(NewMessage):
- categories = {4: "泰拉记事社漫画"}
+ categories: ClassVar[dict[Category, str]] = {4: "泰拉记事社漫画"}
platform_name = "arknights"
name = "明日方舟游戏信息"
enable_tag = False
diff --git a/nonebot_bison/platform/bilibili/__init__.py b/nonebot_bison/platform/bilibili/__init__.py
index 524529e..c3db36e 100644
--- a/nonebot_bison/platform/bilibili/__init__.py
+++ b/nonebot_bison/platform/bilibili/__init__.py
@@ -1,7 +1,7 @@
from .platforms import Bilibili as Bilibili
-from .platforms import Bilibililive as Bilibililive
-from .scheduler import BilibiliSite as BilibiliSite
-from .scheduler import BililiveSite as BililiveSite
from .platforms import BilibiliBangumi as BilibiliBangumi
+from .platforms import Bilibililive as Bilibililive
from .scheduler import BiliBangumiSite as BiliBangumiSite
from .scheduler import BilibiliClientManager as BilibiliClientManager
+from .scheduler import BilibiliSite as BilibiliSite
+from .scheduler import BililiveSite as BililiveSite
diff --git a/nonebot_bison/platform/bilibili/fsm.py b/nonebot_bison/platform/bilibili/fsm.py
index 6252f53..93949c2 100644
--- a/nonebot_bison/platform/bilibili/fsm.py
+++ b/nonebot_bison/platform/bilibili/fsm.py
@@ -1,22 +1,22 @@
-import sys
import asyncio
-import inspect
+from collections.abc import AsyncGenerator, Awaitable, Callable, Sequence
+from collections.abc import Set as AbstractSet
+from dataclasses import dataclass
from enum import Enum
from functools import wraps
-from dataclasses import dataclass
-from collections.abc import Set as AbstractSet
-from collections.abc import Callable, Sequence, Awaitable, AsyncGenerator
+import inspect
+import sys
from typing import (
TYPE_CHECKING,
Any,
+ Concatenate,
Generic,
- TypeVar,
- Protocol,
+ NamedTuple,
ParamSpec,
+ Protocol,
TypeAlias,
TypedDict,
- NamedTuple,
- Concatenate,
+ TypeVar,
overload,
runtime_checkable,
)
diff --git a/nonebot_bison/platform/bilibili/models.py b/nonebot_bison/platform/bilibili/models.py
index c7de84f..5e040c5 100644
--- a/nonebot_bison/platform/bilibili/models.py
+++ b/nonebot_bison/platform/bilibili/models.py
@@ -1,7 +1,7 @@
-from typing import Any, Literal, TypeVar, TypeAlias
+from typing import Any, Literal, TypeAlias, TypeVar
-from pydantic import BaseModel
from nonebot.compat import PYDANTIC_V2, ConfigDict
+from pydantic import BaseModel
from nonebot_bison.compat import model_rebuild
@@ -13,7 +13,7 @@ TBaseModel = TypeVar("TBaseModel", bound=type[BaseModel])
def model_rebuild_recurse(cls: TBaseModel) -> TBaseModel:
"""Recursively rebuild all BaseModel subclasses in the class."""
if not PYDANTIC_V2:
- from inspect import isclass, getmembers
+ from inspect import getmembers, isclass
for _, sub_cls in getmembers(cls, lambda x: isclass(x) and issubclass(x, BaseModel)):
model_rebuild_recurse(sub_cls)
diff --git a/nonebot_bison/platform/bilibili/platforms.py b/nonebot_bison/platform/bilibili/platforms.py
index dbdd52e..31e5dea 100644
--- a/nonebot_bison/platform/bilibili/platforms.py
+++ b/nonebot_bison/platform/bilibili/platforms.py
@@ -1,41 +1,41 @@
-import re
-import json
from copy import deepcopy
from enum import Enum, unique
-from typing import NamedTuple
+import json
+import re
+from typing import ClassVar, NamedTuple
from typing_extensions import Self
-from yarl import URL
-from nonebot import logger
from httpx import AsyncClient
-from pydantic import Field, BaseModel, ValidationError
+from nonebot import logger
from nonebot.compat import type_validate_json, type_validate_python
+from pydantic import BaseModel, Field, ValidationError
+from yarl import URL
-from nonebot_bison.post.post import Post
from nonebot_bison.compat import model_rebuild
-from nonebot_bison.utils import text_similarity, decode_unicode_escapes
-from nonebot_bison.types import Tag, Target, RawPost, ApiError, Category
+from nonebot_bison.platform.platform import CategoryNotRecognize, CategoryNotSupport, NewMessage, StatusChange
+from nonebot_bison.post.post import Post
+from nonebot_bison.types import ApiError, Category, RawPost, Tag, Target
+from nonebot_bison.utils import decode_unicode_escapes, text_similarity
-from .retry import ApiCode352Error, retry_for_352
-from .scheduler import BilibiliSite, BililiveSite, BiliBangumiSite
-from ..platform import NewMessage, StatusChange, CategoryNotSupport, CategoryNotRecognize
from .models import (
- PostAPI,
- UserAPI,
- PGCMajor,
- DrawMajor,
- LiveMajor,
- OPUSMajor,
- DynRawPost,
- VideoMajor,
- CommonMajor,
- DynamicType,
ArticleMajor,
+ CommonMajor,
CoursesMajor,
DeletedMajor,
- UnknownMajor,
+ DrawMajor,
+ DynamicType,
+ DynRawPost,
+ LiveMajor,
LiveRecommendMajor,
+ OPUSMajor,
+ PGCMajor,
+ PostAPI,
+ UnknownMajor,
+ UserAPI,
+ VideoMajor,
)
+from .retry import ApiCode352Error, retry_for_352
+from .scheduler import BiliBangumiSite, BilibiliSite, BililiveSite
class _ProcessedText(NamedTuple):
@@ -51,7 +51,7 @@ class _ParsedMojarPost(NamedTuple):
class Bilibili(NewMessage):
- categories = {
+ categories: ClassVar[dict[Category, str]] = {
1: "一般动态",
2: "专栏文章",
3: "视频",
@@ -162,7 +162,6 @@ class Bilibili(NewMessage):
return tags
def _text_process(self, dynamic: str, desc: str, title: str) -> _ProcessedText:
-
# 计算视频标题和视频描述相似度
title_similarity = 0.0 if len(title) == 0 or len(desc) == 0 else text_similarity(title, desc[: len(title)])
if title_similarity > 0.9:
@@ -308,7 +307,7 @@ class Bilibili(NewMessage):
class Bilibililive(StatusChange):
- categories = {1: "开播提醒", 2: "标题更新提醒", 3: "下播提醒"}
+ categories: ClassVar[dict[Category, str]] = {1: "开播提醒", 2: "标题更新提醒", 3: "下播提醒"}
platform_name = "bilibili-live"
enable_tag = False
enabled = True
@@ -458,7 +457,7 @@ class Bilibililive(StatusChange):
class BilibiliBangumi(StatusChange):
- categories = {}
+ categories: ClassVar[dict[Category, str]] = {}
platform_name = "bilibili-bangumi"
enable_tag = False
enabled = True
diff --git a/nonebot_bison/platform/bilibili/retry.py b/nonebot_bison/platform/bilibili/retry.py
index 20cc9ed..09e917c 100644
--- a/nonebot_bison/platform/bilibili/retry.py
+++ b/nonebot_bison/platform/bilibili/retry.py
@@ -1,20 +1,20 @@
-import random
-from enum import Enum
-from functools import wraps
+from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from datetime import datetime, timedelta
-from collections.abc import Callable, Awaitable
-from typing_extensions import override, assert_never
+from enum import Enum
+from functools import wraps
+import random
from typing import TYPE_CHECKING, Generic, Literal, TypeVar
+from typing_extensions import assert_never, override
-from strenum import StrEnum
-from nonebot.log import logger
from httpx import URL as HttpxURL
+from nonebot.log import logger
+from strenum import StrEnum
from nonebot_bison.types import Target
+from .fsm import FSM, ActionReturn, Condition, StateGraph, Transition, reset_on_exception
from .models import DynRawPost
-from .fsm import FSM, Condition, StateGraph, Transition, ActionReturn, reset_on_exception
if TYPE_CHECKING:
from .platforms import Bilibili
@@ -115,8 +115,7 @@ class RetryAddon(Generic[TBilibili]):
def record_backoff_finish_time(self):
self.backoff_finish_time = (
- datetime.now()
- + self.backoff_timedelta * self.backoff_count**2
+ datetime.now() + self.backoff_timedelta * self.backoff_count**2
# + timedelta(seconds=random.randint(1, 60)) # jitter
)
logger.trace(f"set backoff finish time: {self.backoff_finish_time}")
diff --git a/nonebot_bison/platform/bilibili/scheduler.py b/nonebot_bison/platform/bilibili/scheduler.py
index 1dddbec..b63fa3b 100644
--- a/nonebot_bison/platform/bilibili/scheduler.py
+++ b/nonebot_bison/platform/bilibili/scheduler.py
@@ -1,17 +1,16 @@
+from datetime import datetime, timedelta
import json
import random
+from typing import TYPE_CHECKING, ClassVar, TypeVar
from typing_extensions import override
-from datetime import datetime, timedelta
-from typing import TYPE_CHECKING, TypeVar
from httpx import AsyncClient
from nonebot import logger, require
from playwright.async_api import Cookie
+from nonebot_bison.config.db_model import Cookie as CookieModel
from nonebot_bison.utils import Site, http_client
-
-from ...utils.site import CookieClientManager
-from ...config.db_model import Cookie as CookieModel
+from nonebot_bison.utils.site import CookieClientManager
if TYPE_CHECKING:
from .platforms import Bilibili
@@ -23,7 +22,6 @@ B = TypeVar("B", bound="Bilibili")
class BilibiliClientManager(CookieClientManager):
-
_default_cookie_cd = timedelta(seconds=120)
async def _get_cookies(self) -> list[Cookie]:
@@ -75,7 +73,7 @@ class BilibiliClientManager(CookieClientManager):
class BilibiliSite(Site):
name = "bilibili.com"
- schedule_setting = {"seconds": 60}
+ schedule_setting: ClassVar[dict] = {"seconds": 60}
schedule_type = "interval"
client_mgr = BilibiliClientManager
require_browser = True
@@ -83,11 +81,11 @@ class BilibiliSite(Site):
class BililiveSite(Site):
name = "live.bilibili.com"
- schedule_setting = {"seconds": 5}
+ schedule_setting: ClassVar[dict] = {"seconds": 5}
schedule_type = "interval"
class BiliBangumiSite(Site):
name = "bilibili.com/bangumi"
- schedule_setting = {"seconds": 30}
+ schedule_setting: ClassVar[dict] = {"seconds": 30}
schedule_type = "interval"
diff --git a/nonebot_bison/platform/ceobecanteen/cache.py b/nonebot_bison/platform/ceobecanteen/cache.py
index b157d56..6343cdd 100644
--- a/nonebot_bison/platform/ceobecanteen/cache.py
+++ b/nonebot_bison/platform/ceobecanteen/cache.py
@@ -1,16 +1,16 @@
-from typing import TypeAlias
-from functools import partial
-from datetime import timedelta
-from types import MappingProxyType
from collections.abc import Callable
+from datetime import timedelta
+from functools import partial
+from types import MappingProxyType
+from typing import TypeAlias
+from expiringdictx import ExpiringDict, SimpleCache
+from hishel import AsyncCacheTransport, AsyncInMemoryStorage, Controller
from httpx import AsyncClient, AsyncHTTPTransport
-from expiringdictx import SimpleCache, ExpiringDict
-from hishel import Controller, AsyncCacheTransport, AsyncInMemoryStorage
from .const import DATASOURCE_URL
-from .utils import process_response
from .models import CeobeSource, CeobeTarget, DataSourceResponse
+from .utils import process_response
cache_transport = AsyncCacheTransport(
AsyncHTTPTransport(),
diff --git a/nonebot_bison/platform/ceobecanteen/models.py b/nonebot_bison/platform/ceobecanteen/models.py
index 1987948..bb857e3 100644
--- a/nonebot_bison/platform/ceobecanteen/models.py
+++ b/nonebot_bison/platform/ceobecanteen/models.py
@@ -1,4 +1,4 @@
-from typing import Literal, TypeVar, NamedTuple
+from typing import Literal, NamedTuple, TypeVar
from pydantic import BaseModel
diff --git a/nonebot_bison/platform/ceobecanteen/platform.py b/nonebot_bison/platform/ceobecanteen/platform.py
index a3674be..1fd9998 100644
--- a/nonebot_bison/platform/ceobecanteen/platform.py
+++ b/nonebot_bison/platform/ceobecanteen/platform.py
@@ -1,23 +1,23 @@
-from typing import ParamSpec
-from functools import partial
-from datetime import timedelta
from collections import defaultdict
+from datetime import timedelta
+from functools import partial
+from typing import ClassVar, ParamSpec
from httpx import AsyncClient
from nonebot import logger, require
from rapidfuzz import fuzz, process
-from nonebot_bison.post import Post
+from nonebot_bison.platform.platform import NewMessage
from nonebot_bison.plugin_config import plugin_config
-from nonebot_bison.types import Target, RawPost, Category
-from nonebot_bison.utils import Site, ClientManager, capture_html
+from nonebot_bison.post import Post
+from nonebot_bison.types import Category, RawPost, Target
+from nonebot_bison.utils import ClientManager, Site, capture_html
-from ..platform import NewMessage
-from .utils import process_response
-from .const import COMB_ID_URL, COOKIES_URL, COOKIE_ID_URL
-from .exception import CeobeSnapshotSkip, CeobeSnapshotFailed
from .cache import CeobeCache, CeobeClient, CeobeDataSourceCache
-from .models import CeobeImage, CeobeCookie, CeobeTextPic, CombIdResponse, CookiesResponse, CookieIdResponse
+from .const import COMB_ID_URL, COOKIE_ID_URL, COOKIES_URL
+from .exception import CeobeSnapshotFailed, CeobeSnapshotSkip
+from .models import CeobeCookie, CeobeImage, CeobeTextPic, CombIdResponse, CookieIdResponse, CookiesResponse
+from .utils import process_response
P = ParamSpec("P")
@@ -49,7 +49,7 @@ class CeobeCanteenSite(Site):
name = "ceobe_canteen"
schedule_type = "interval"
# lwt の 推荐间隔
- schedule_setting = {"seconds": 15}
+ schedule_setting: ClassVar[dict] = {"seconds": 15}
client_mgr = CeobeCanteenClientManager
@@ -64,7 +64,7 @@ class CeobeCanteen(NewMessage):
use_batch: bool = True
default_theme: str = "ceobecanteen"
- categories: dict[Category, str] = {1: "普通", 2: "转发"}
+ categories: ClassVar[dict[Category, str]] = {1: "普通", 2: "转发"}
data_source_cache = CeobeDataSourceCache()
@@ -213,7 +213,9 @@ class CeobeCanteen(NewMessage):
logger.debug(f"snapshot official website url: {url}")
# /html/body/div[1]/div[1]/div/div[1]/div[1]/div
- snapshot_selector = "html > body > div:nth-child(1) > div:nth-child(1) > div > div:nth-child(1) > div:nth-child(1) > div" # noqa: E501
+ snapshot_selector = (
+ "html > body > div:nth-child(1) > div:nth-child(1) > div > div:nth-child(1) > div:nth-child(1) > div"
+ )
# /html/body/div[1]/div[1]/div/div[1]/div[1]/div/div[4]/div/div/div
calculate_selector = "html > body > div:nth-child(1) > div:nth-child(1) > div > div:nth-child(1) > div:nth-child(1) > div > div:nth-child(4) > div > div > div" # noqa: E501
viewport = {"width": 1024, "height": 19990}
diff --git a/nonebot_bison/platform/ceobecanteen/utils.py b/nonebot_bison/platform/ceobecanteen/utils.py
index 83667d5..b9284be 100644
--- a/nonebot_bison/platform/ceobecanteen/utils.py
+++ b/nonebot_bison/platform/ceobecanteen/utils.py
@@ -3,7 +3,7 @@ from nonebot import logger
from nonebot.compat import type_validate_python
from .exception import CeobeResponseError
-from .models import ResponseModel, CookieIdResponse
+from .models import CookieIdResponse, ResponseModel
def process_response(response: Response, parse_model: type[ResponseModel]) -> ResponseModel:
diff --git a/nonebot_bison/platform/ff14.py b/nonebot_bison/platform/ff14.py
index 412a463..81f004c 100644
--- a/nonebot_bison/platform/ff14.py
+++ b/nonebot_bison/platform/ff14.py
@@ -1,15 +1,16 @@
-from typing import Any
+from typing import Any, ClassVar
from httpx import AsyncClient
-from ..post import Post
+from nonebot_bison.post import Post
+from nonebot_bison.types import RawPost, Target
+from nonebot_bison.utils import anonymous_site
+
from .platform import NewMessage
-from ..utils import anonymous_site
-from ..types import Target, RawPost
class FF14(NewMessage):
- categories = {}
+ categories: ClassVar[dict] = {}
platform_name = "ff14"
name = "最终幻想XIV官方公告"
enable_tag = False
diff --git a/nonebot_bison/platform/ncm.py b/nonebot_bison/platform/ncm.py
index 069ef9c..39cee5c 100644
--- a/nonebot_bison/platform/ncm.py
+++ b/nonebot_bison/platform/ncm.py
@@ -1,22 +1,23 @@
import re
-from typing import Any
+from typing import Any, ClassVar
from httpx import AsyncClient
-from ..post import Post
-from ..utils import Site
+from nonebot_bison.post import Post
+from nonebot_bison.types import ApiError, Category, RawPost, Target
+from nonebot_bison.utils import Site
+
from .platform import NewMessage
-from ..types import Target, RawPost, ApiError
class NcmSite(Site):
name = "music.163.com"
schedule_type = "interval"
- schedule_setting = {"minutes": 1}
+ schedule_setting: ClassVar[dict] = {"minutes": 1}
class NcmArtist(NewMessage):
- categories = {}
+ categories: ClassVar[dict[Category, str]] = {}
platform_name = "ncm-artist"
enable_tag = False
enabled = True
@@ -73,7 +74,7 @@ class NcmArtist(NewMessage):
class NcmRadio(NewMessage):
- categories = {}
+ categories: ClassVar[dict[Category, str]] = {}
platform_name = "ncm-radio"
enable_tag = False
enabled = True
diff --git a/nonebot_bison/platform/platform.py b/nonebot_bison/platform/platform.py
index ecbafe6..f018f88 100644
--- a/nonebot_bison/platform/platform.py
+++ b/nonebot_bison/platform/platform.py
@@ -1,22 +1,22 @@
-import ssl
-import json
-import time
-import typing
-from dataclasses import dataclass
from abc import ABC, abstractmethod
from collections import defaultdict
-from typing import Any, TypeVar, ParamSpec
-from collections.abc import Callable, Awaitable, Collection
+from collections.abc import Awaitable, Callable, Collection
+from dataclasses import dataclass
+import json
+import ssl
+import time
+import typing
+from typing import Any, ParamSpec, TypeVar
import httpx
from httpx import AsyncClient
from nonebot.log import logger
from nonebot_plugin_saa import PlatformTarget
-from ..post import Post
-from ..utils import Site, ProcessContext
-from ..plugin_config import plugin_config
-from ..types import Tag, Target, RawPost, SubUnit, Category
+from nonebot_bison.plugin_config import plugin_config
+from nonebot_bison.post import Post
+from nonebot_bison.types import Category, RawPost, SubUnit, Tag, Target
+from nonebot_bison.utils import ProcessContext, Site
class CategoryNotSupport(Exception):
diff --git a/nonebot_bison/platform/rss.py b/nonebot_bison/platform/rss.py
index 1437965..e80dfa8 100644
--- a/nonebot_bison/platform/rss.py
+++ b/nonebot_bison/platform/rss.py
@@ -1,27 +1,27 @@
-import time
import calendar
-from typing import Any
+import time
+from typing import Any, ClassVar
+from bs4 import BeautifulSoup as bs
import feedparser
from httpx import AsyncClient
-from bs4 import BeautifulSoup as bs
-from ..post import Post
+from nonebot_bison.post import Post
+from nonebot_bison.types import Category, RawPost, Target
+from nonebot_bison.utils import text_similarity
+from nonebot_bison.utils.site import CookieClientManager, Site
+
from .platform import NewMessage
-from ..types import Target, RawPost
-from ..utils import text_similarity
-from ..utils.site import Site, CookieClientManager
class RssSite(Site):
name = "rss"
schedule_type = "interval"
- schedule_setting = {"seconds": 30}
+ schedule_setting: ClassVar[dict] = {"seconds": 30}
client_mgr = CookieClientManager.from_name(name)
class RssPost(Post):
-
async def get_plain_content(self) -> str:
soup = bs(self.content, "html.parser")
@@ -38,7 +38,7 @@ class RssPost(Post):
class Rss(NewMessage):
- categories = {}
+ categories: ClassVar[dict[Category, str]] = {}
enable_tag = False
platform_name = "rss"
name = "Rss"
diff --git a/nonebot_bison/platform/weibo.py b/nonebot_bison/platform/weibo.py
index f6c276d..c7b137f 100644
--- a/nonebot_bison/platform/weibo.py
+++ b/nonebot_bison/platform/weibo.py
@@ -1,21 +1,22 @@
-import re
-import json
-from typing import Any
from datetime import datetime
-from urllib.parse import unquote
+import json
+import re
+from typing import Any, ClassVar
from typing_extensions import override
+from urllib.parse import unquote
-from yarl import URL
-from lxml.etree import HTML
-from httpx import AsyncClient
-from nonebot.log import logger
from bs4 import BeautifulSoup as bs
+from httpx import AsyncClient
+from lxml.etree import HTML
+from nonebot.log import logger
+from yarl import URL
+
+from nonebot_bison.post import Post
+from nonebot_bison.types import ApiError, Category, RawPost, Tag, Target
+from nonebot_bison.utils import http_client, text_fletten
+from nonebot_bison.utils.site import CookieClientManager, Site
-from ..post import Post
from .platform import NewMessage
-from ..utils import http_client, text_fletten
-from ..utils.site import Site, CookieClientManager
-from ..types import Tag, Target, RawPost, ApiError, Category
_HEADER = {
"accept": (
@@ -59,12 +60,12 @@ class WeiboClientManager(CookieClientManager):
class WeiboSite(Site):
name = "weibo.com"
schedule_type = "interval"
- schedule_setting = {"seconds": 3}
+ schedule_setting: ClassVar[dict] = {"seconds": 3}
client_mgr = WeiboClientManager
class Weibo(NewMessage):
- categories = {
+ categories: ClassVar[dict[Category, str]] = {
1: "转发",
2: "视频",
3: "图文",
diff --git a/nonebot_bison/plugin_config.py b/nonebot_bison/plugin_config.py
index b7f7307..b330224 100644
--- a/nonebot_bison/plugin_config.py
+++ b/nonebot_bison/plugin_config.py
@@ -1,8 +1,8 @@
import nonebot
-from yarl import URL
from nonebot import get_plugin_config
-from pydantic import Field, BaseModel
from nonebot.compat import PYDANTIC_V2, ConfigDict
+from pydantic import BaseModel, Field
+from yarl import URL
global_config = nonebot.get_driver().config
PlatformName = str
diff --git a/nonebot_bison/post/abstract_post.py b/nonebot_bison/post/abstract_post.py
index 2a76a44..1260327 100644
--- a/nonebot_bison/post/abstract_post.py
+++ b/nonebot_bison/post/abstract_post.py
@@ -1,10 +1,10 @@
-from dataclasses import dataclass
from abc import ABC, abstractmethod
+from dataclasses import dataclass
-from nonebot_plugin_saa import Text, MessageFactory, MessageSegmentFactory
+from nonebot_plugin_saa import MessageFactory, MessageSegmentFactory, Text
-from ..utils import text_to_image
-from ..plugin_config import plugin_config
+from nonebot_bison.plugin_config import plugin_config
+from nonebot_bison.utils import text_to_image
@dataclass(kw_only=True)
diff --git a/nonebot_bison/post/post.py b/nonebot_bison/post/post.py
index 577f81e..1dd1087 100644
--- a/nonebot_bison/post/post.py
+++ b/nonebot_bison/post/post.py
@@ -1,21 +1,22 @@
-import reprlib
+from collections.abc import Sequence
+from dataclasses import dataclass, fields
from io import BytesIO
from pathlib import Path
+import reprlib
from typing import TYPE_CHECKING
-from collections.abc import Sequence
-from dataclasses import fields, dataclass
from nonebot.log import logger
from nonebot_plugin_saa import MessageSegmentFactory
-from ..theme import theme_manager
+from nonebot_bison.plugin_config import plugin_config
+from nonebot_bison.theme import theme_manager
+from nonebot_bison.theme.types import ThemeRenderError, ThemeRenderUnsupportError
+
from .abstract_post import AbstractPost
-from ..plugin_config import plugin_config
from .protocol import PlainContentSupport
-from ..theme.types import ThemeRenderError, ThemeRenderUnsupportError
if TYPE_CHECKING:
- from ..platform import Platform
+ from nonebot_bison.platform import Platform
@dataclass
diff --git a/nonebot_bison/scheduler/__init__.py b/nonebot_bison/scheduler/__init__.py
index 19c9284..87ba97a 100644
--- a/nonebot_bison/scheduler/__init__.py
+++ b/nonebot_bison/scheduler/__init__.py
@@ -1,3 +1,3 @@
-from .manager import init_scheduler, scheduler_dict, handle_delete_target, handle_insert_new_target
+from .manager import handle_delete_target, handle_insert_new_target, init_scheduler, scheduler_dict
-__all__ = ["init_scheduler", "handle_delete_target", "handle_insert_new_target", "scheduler_dict"]
+__all__ = ["handle_delete_target", "handle_insert_new_target", "init_scheduler", "scheduler_dict"]
diff --git a/nonebot_bison/scheduler/manager.py b/nonebot_bison/scheduler/manager.py
index 5a94cf1..a5184ec 100644
--- a/nonebot_bison/scheduler/manager.py
+++ b/nonebot_bison/scheduler/manager.py
@@ -2,14 +2,15 @@ from typing import cast
from nonebot.log import logger
-from ..utils import Site
-from ..config import config
+from nonebot_bison.config import config
+from nonebot_bison.config.db_model import Target
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.plugin_config import plugin_config
+from nonebot_bison.types import Target as T_Target
+from nonebot_bison.utils import Site
+from nonebot_bison.utils.site import CookieClientManager, is_cookie_client_manager
+
from .scheduler import Scheduler
-from ..config.db_model import Target
-from ..types import Target as T_Target
-from ..platform import platform_manager
-from ..plugin_config import plugin_config
-from ..utils.site import CookieClientManager, is_cookie_client_manager
scheduler_dict: dict[type[Site], Scheduler] = {}
diff --git a/nonebot_bison/scheduler/scheduler.py b/nonebot_bison/scheduler/scheduler.py
index f94ea87..883114e 100644
--- a/nonebot_bison/scheduler/scheduler.py
+++ b/nonebot_bison/scheduler/scheduler.py
@@ -1,18 +1,16 @@
-from dataclasses import dataclass
from collections import defaultdict
+from dataclasses import dataclass
from nonebot.log import logger
from nonebot_plugin_apscheduler import scheduler
from nonebot_plugin_saa.utils.exceptions import NoBotFound
-from nonebot_bison.utils import ClientManager
-
-from ..config import config
-from ..send import send_msgs
-from ..types import Target, SubUnit
-from ..platform import platform_manager
-from ..utils import Site, ProcessContext
-from ..utils.site import SkipRequestException
+from nonebot_bison.config import config
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.send import send_msgs
+from nonebot_bison.types import SubUnit, Target
+from nonebot_bison.utils import ClientManager, ProcessContext, Site
+from nonebot_bison.utils.site import SkipRequestException
@dataclass
diff --git a/nonebot_bison/script/cli.py b/nonebot_bison/script/cli.py
index f17e431..420b1ee 100644
--- a/nonebot_bison/script/cli.py
+++ b/nonebot_bison/script/cli.py
@@ -1,25 +1,26 @@
-import json
-import time
+from collections.abc import Callable, Coroutine
+from functools import partial, wraps
import importlib
+import json
from pathlib import Path
+import time
from types import ModuleType
from typing import Any, TypeVar
-from functools import wraps, partial
-from collections.abc import Callable, Coroutine
-from nonebot.log import logger
+from anyio import open_file
from nonebot.compat import model_dump
+from nonebot.log import logger
-from ..scheduler.manager import init_scheduler
-from ..config.subs_io.nbesf_model import v1, v2, v3
-from ..config.subs_io import subscribes_export, subscribes_import
+from nonebot_bison.config.subs_io import subscribes_export, subscribes_import
+from nonebot_bison.config.subs_io.nbesf_model import v1, v2, v3
+from nonebot_bison.scheduler.manager import init_scheduler
try:
from typing_extensions import ParamSpec
import anyio
+ from anyio import from_thread, to_thread
import click
- from anyio import to_thread, from_thread
except ImportError as e: # pragma: no cover
raise ImportError("请使用 `pip install nonebot-bison[cli]` 安装所需依赖") from e
@@ -127,18 +128,18 @@ async def subs_import(path: str, format: str):
import_file_path = Path(path)
assert import_file_path.is_file(), "该路径不是文件!"
- with import_file_path.open("r", encoding="utf-8") as f:
+ async with await open_file(import_file_path, "r", encoding="utf-8") as f:
match format:
case "yaml" | "yml":
logger.info("正在从yaml导入...")
pyyaml = import_yaml_module()
- import_items = pyyaml.safe_load(f)
+ import_items = pyyaml.safe_load(await f.read())
case "json":
logger.info("正在从json导入...")
- import_items = json.load(f)
+ import_items = json.loads(await f.read())
case _:
raise click.BadParameter(message=f"不支持的导入格式: {format}")
diff --git a/nonebot_bison/send.py b/nonebot_bison/send.py
index b48127d..98fa91f 100644
--- a/nonebot_bison/send.py
+++ b/nonebot_bison/send.py
@@ -1,10 +1,10 @@
import asyncio
from collections import deque
-from nonebot.log import logger
-from nonebot_plugin_saa.auto_select_bot import refresh_bots
from nonebot.adapters.onebot.v11.exception import ActionFailed
-from nonebot_plugin_saa import MessageFactory, PlatformTarget, AggregatedMessageFactory
+from nonebot.log import logger
+from nonebot_plugin_saa import AggregatedMessageFactory, MessageFactory, PlatformTarget
+from nonebot_plugin_saa.auto_select_bot import refresh_bots
from .plugin_config import plugin_config
@@ -14,6 +14,8 @@ QUEUE: deque[tuple[PlatformTarget, Sendable, int]] = deque()
MESSGE_SEND_INTERVAL = 1.5
+_MESSAGE_DISPATCH_TASKS: set[asyncio.Task] = set()
+
async def _do_send(send_target: PlatformTarget, msg: Sendable):
try:
@@ -59,7 +61,9 @@ async def _send_msgs_dispatch(send_target: PlatformTarget, msg: Sendable):
QUEUE.append((send_target, msg, plugin_config.bison_resend_times))
# len(QUEUE) before append was 0
if len(QUEUE) == 1:
- asyncio.create_task(do_send_msgs())
+ task = asyncio.create_task(do_send_msgs())
+ _MESSAGE_DISPATCH_TASKS.add(task)
+ task.add_done_callback(_MESSAGE_DISPATCH_TASKS.discard)
else:
await _do_send(send_target, msg)
diff --git a/nonebot_bison/sub_manager/__init__.py b/nonebot_bison/sub_manager/__init__.py
index 9a3e5c2..f73f528 100644
--- a/nonebot_bison/sub_manager/__init__.py
+++ b/nonebot_bison/sub_manager/__init__.py
@@ -2,23 +2,25 @@ import asyncio
from datetime import datetime
from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.matcher import Matcher
-from nonebot.rule import Rule, to_me
-from nonebot.permission import SUPERUSER
-from nonebot_plugin_saa import TargetQQGroup
-from nonebot.params import ArgStr, ArgPlainText
from nonebot.adapters import Bot, MessageTemplate
from nonebot.adapters.onebot.v11.event import PrivateMessageEvent
+from nonebot.matcher import Matcher
+from nonebot.params import ArgPlainText, ArgStr
+from nonebot.permission import SUPERUSER
+from nonebot.rule import Rule, to_me
+from nonebot.typing import T_State
+from nonebot_plugin_saa import TargetQQGroup
+from .add_cookie import do_add_cookie
+from .add_cookie_target import do_add_cookie_target
from .add_sub import do_add_sub
+from .del_cookie import do_del_cookie
+from .del_cookie_target import do_del_cookie_target
from .del_sub import do_del_sub
from .query_sub import do_query_sub
-from .add_cookie import do_add_cookie
-from .del_cookie import do_del_cookie
-from .add_cookie_target import do_add_cookie_target
-from .del_cookie_target import do_del_cookie_target
-from .utils import common_platform, admin_permission, gen_handle_cancel, configurable_to_me, set_target_user_info
+from .utils import admin_permission, common_platform, configurable_to_me, gen_handle_cancel, set_target_user_info
+
+_COMMAND_DISPATCH_TASKS: set[asyncio.Task] = set()
add_sub_matcher = on_command(
"添加订阅",
@@ -149,7 +151,10 @@ async def do_dispatch_command(
else:
do_del_sub(new_matcher)
new_matcher_ins = new_matcher()
- asyncio.create_task(new_matcher_ins.run(bot, event, state))
+
+ task = asyncio.create_task(new_matcher_ins.run(bot, event, state))
+ _COMMAND_DISPATCH_TASKS.add(task)
+ task.add_done_callback(_COMMAND_DISPATCH_TASKS.discard)
no_permission_matcher = on_command(
@@ -167,14 +172,14 @@ async def send_no_permission():
__all__ = [
- "common_platform",
+ "add_cookie_matcher",
+ "add_cookie_target_matcher",
"add_sub_matcher",
- "query_sub_matcher",
+ "common_platform",
+ "del_cookie_matcher",
+ "del_cookie_target_matcher",
"del_sub_matcher",
"group_manage_matcher",
"no_permission_matcher",
- "add_cookie_matcher",
- "add_cookie_target_matcher",
- "del_cookie_target_matcher",
- "del_cookie_matcher",
+ "query_sub_matcher",
]
diff --git a/nonebot_bison/sub_manager/add_cookie.py b/nonebot_bison/sub_manager/add_cookie.py
index 7e6461f..a57d79f 100644
--- a/nonebot_bison/sub_manager/add_cookie.py
+++ b/nonebot_bison/sub_manager/add_cookie.py
@@ -1,16 +1,17 @@
-from typing import cast
from json import JSONDecodeError
+from typing import cast
+from nonebot.adapters import Message, MessageTemplate
+from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.log import logger
-from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.params import Arg, ArgPlainText
-from nonebot.adapters.onebot.v11 import MessageEvent
-from nonebot.adapters import Message, MessageTemplate
+from nonebot.typing import T_State
+
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.scheduler import scheduler_dict
+from nonebot_bison.utils.site import CookieClientManager, is_cookie_client_manager
-from ..scheduler import scheduler_dict
-from ..platform import platform_manager
-from ..utils.site import CookieClientManager, is_cookie_client_manager
from .utils import common_platform, gen_handle_cancel, only_allow_private
diff --git a/nonebot_bison/sub_manager/add_cookie_target.py b/nonebot_bison/sub_manager/add_cookie_target.py
index 919d0ca..4facd6a 100644
--- a/nonebot_bison/sub_manager/add_cookie_target.py
+++ b/nonebot_bison/sub_manager/add_cookie_target.py
@@ -1,14 +1,15 @@
-from nonebot.typing import T_State
-from nonebot.matcher import Matcher
-from nonebot.params import ArgPlainText
-from nonebot_plugin_saa import MessageFactory
from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.internal.adapter import MessageTemplate
+from nonebot.matcher import Matcher
+from nonebot.params import ArgPlainText
+from nonebot.typing import T_State
+from nonebot_plugin_saa import MessageFactory
-from ..config import config
-from ..utils import parse_text
-from ..platform import platform_manager
-from .utils import gen_handle_cancel, only_allow_private, generate_sub_list_text
+from nonebot_bison.config import config
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.utils import parse_text
+
+from .utils import gen_handle_cancel, generate_sub_list_text, only_allow_private
def do_add_cookie_target(add_cookie_target_matcher: type[Matcher]):
@@ -33,7 +34,6 @@ def do_add_cookie_target(add_cookie_target_matcher: type[Matcher]):
@add_cookie_target_matcher.handle()
async def init_promote_cookie(state: T_State):
-
# 获取 site 的所有用户 cookie,再排除掉已经关联的 cookie,剩下的就是可以关联的 cookie
cookies = await config.get_cookie(site_name=state["site"].name, is_anonymous=False)
associated_cookies = await config.get_cookie(
diff --git a/nonebot_bison/sub_manager/add_sub.py b/nonebot_bison/sub_manager/add_sub.py
index 107b9b5..6e26d3a 100644
--- a/nonebot_bison/sub_manager/add_sub.py
+++ b/nonebot_bison/sub_manager/add_sub.py
@@ -1,17 +1,18 @@
import contextlib
-from nonebot.typing import T_State
+from nonebot.adapters import Message, MessageTemplate
from nonebot.matcher import Matcher
from nonebot.params import Arg, ArgPlainText
-from nonebot.adapters import Message, MessageTemplate
-from nonebot_plugin_saa import Text, PlatformTarget, SupportedAdapters
+from nonebot.typing import T_State
+from nonebot_plugin_saa import PlatformTarget, SupportedAdapters, Text
+
+from nonebot_bison.apis import check_sub_target
+from nonebot_bison.config import config
+from nonebot_bison.config.db_config import SubscribeDupException
+from nonebot_bison.platform import Platform, platform_manager, unavailable_paltforms
+from nonebot_bison.types import Target
-from ..types import Target
-from ..config import config
-from ..apis import check_sub_target
-from ..config.db_config import SubscribeDupException
from .utils import common_platform, ensure_user_info, gen_handle_cancel
-from ..platform import Platform, platform_manager, unavailable_paltforms
def do_add_sub(add_sub: type[Matcher]):
diff --git a/nonebot_bison/sub_manager/del_cookie.py b/nonebot_bison/sub_manager/del_cookie.py
index 680d3c0..dfad326 100644
--- a/nonebot_bison/sub_manager/del_cookie.py
+++ b/nonebot_bison/sub_manager/del_cookie.py
@@ -1,11 +1,12 @@
-from nonebot.typing import T_State
+from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.matcher import Matcher
from nonebot.params import EventPlainText
+from nonebot.typing import T_State
from nonebot_plugin_saa import MessageFactory
-from nonebot.adapters.onebot.v11 import MessageEvent
-from ..config import config
-from ..utils import parse_text
+from nonebot_bison.config import config
+from nonebot_bison.utils import parse_text
+
from .utils import gen_handle_cancel, only_allow_private
diff --git a/nonebot_bison/sub_manager/del_cookie_target.py b/nonebot_bison/sub_manager/del_cookie_target.py
index 656e1d2..4bf698e 100644
--- a/nonebot_bison/sub_manager/del_cookie_target.py
+++ b/nonebot_bison/sub_manager/del_cookie_target.py
@@ -1,11 +1,12 @@
-from nonebot.typing import T_State
+from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.matcher import Matcher
from nonebot.params import EventPlainText
+from nonebot.typing import T_State
from nonebot_plugin_saa import MessageFactory
-from nonebot.adapters.onebot.v11 import MessageEvent
-from ..config import config
-from ..utils import parse_text
+from nonebot_bison.config import config
+from nonebot_bison.utils import parse_text
+
from .utils import gen_handle_cancel, only_allow_private
diff --git a/nonebot_bison/sub_manager/del_sub.py b/nonebot_bison/sub_manager/del_sub.py
index b70d923..d54127c 100644
--- a/nonebot_bison/sub_manager/del_sub.py
+++ b/nonebot_bison/sub_manager/del_sub.py
@@ -1,12 +1,13 @@
-from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.params import Arg, EventPlainText
+from nonebot.typing import T_State
from nonebot_plugin_saa import MessageFactory, PlatformTarget
-from ..config import config
-from ..types import Category
-from ..utils import parse_text
-from ..platform import platform_manager
+from nonebot_bison.config import config
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.types import Category
+from nonebot_bison.utils import parse_text
+
from .utils import ensure_user_info, gen_handle_cancel
diff --git a/nonebot_bison/sub_manager/query_sub.py b/nonebot_bison/sub_manager/query_sub.py
index 8f4d7ba..f1c6154 100644
--- a/nonebot_bison/sub_manager/query_sub.py
+++ b/nonebot_bison/sub_manager/query_sub.py
@@ -1,12 +1,13 @@
-from nonebot.params import Arg
from nonebot.matcher import Matcher
+from nonebot.params import Arg
from nonebot_plugin_saa import MessageFactory, PlatformTarget
-from ..config import config
-from ..types import Category
-from ..utils import parse_text
+from nonebot_bison.config import config
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.types import Category
+from nonebot_bison.utils import parse_text
+
from .utils import ensure_user_info
-from ..platform import platform_manager
def do_query_sub(query_sub: type[Matcher]):
diff --git a/nonebot_bison/sub_manager/utils.py b/nonebot_bison/sub_manager/utils.py
index 2418cfc..6c3e100 100644
--- a/nonebot_bison/sub_manager/utils.py
+++ b/nonebot_bison/sub_manager/utils.py
@@ -1,22 +1,22 @@
import contextlib
-from typing import Annotated
from itertools import groupby
from operator import attrgetter
+from typing import Annotated
-from nonebot.rule import Rule
from nonebot.adapters import Event
-from nonebot.typing import T_State
from nonebot.matcher import Matcher
+from nonebot.params import Depends, EventPlainText, EventToMe
from nonebot.permission import SUPERUSER
-from nonebot.params import Depends, EventToMe, EventPlainText
+from nonebot.rule import Rule
+from nonebot.typing import T_State
from nonebot_plugin_saa import PlatformTarget, extract_target
-from ..config import config
-from ..types import Category
-from ..types import Target as T_Target
-from ..platform import platform_manager
-from ..plugin_config import plugin_config
-from ..utils.site import is_cookie_client_manager
+from nonebot_bison.config import config
+from nonebot_bison.platform import platform_manager
+from nonebot_bison.plugin_config import plugin_config
+from nonebot_bison.types import Category
+from nonebot_bison.types import Target as T_Target
+from nonebot_bison.utils.site import is_cookie_client_manager
def _configurable_to_me(to_me: bool = EventToMe()):
diff --git a/nonebot_bison/theme/__init__.py b/nonebot_bison/theme/__init__.py
index fef5cb1..00dcae6 100644
--- a/nonebot_bison/theme/__init__.py
+++ b/nonebot_bison/theme/__init__.py
@@ -1,10 +1,9 @@
+from importlib import import_module
from pathlib import Path
from pkgutil import iter_modules
-from importlib import import_module
-from .types import Theme
from .registry import theme_manager
-from .types import ThemeRegistrationError
+from .types import Theme, ThemeRegistrationError
from .types import ThemeRenderError as ThemeRenderError
from .types import ThemeRenderUnsupportError as ThemeRenderUnsupportError
diff --git a/nonebot_bison/theme/registry.py b/nonebot_bison/theme/registry.py
index 7c8f76f..14afd82 100644
--- a/nonebot_bison/theme/registry.py
+++ b/nonebot_bison/theme/registry.py
@@ -1,11 +1,14 @@
+from typing import ClassVar
+
from nonebot import logger
-from ..plugin_config import plugin_config
+from nonebot_bison.plugin_config import plugin_config
+
from .types import Theme, ThemeRegistrationError
class ThemeManager:
- __themes: dict[str, Theme] = {}
+ __themes: ClassVar[dict[str, Theme]] = {}
def register(self, theme: Theme):
logger.trace(f"Registering theme: {theme}")
diff --git a/nonebot_bison/theme/themes/arknights/build.py b/nonebot_bison/theme/themes/arknights/build.py
index ec6265d..2fe0b22 100644
--- a/nonebot_bison/theme/themes/arknights/build.py
+++ b/nonebot_bison/theme/themes/arknights/build.py
@@ -1,13 +1,13 @@
+from dataclasses import dataclass
from io import BytesIO
from pathlib import Path
-from dataclasses import dataclass
from typing import TYPE_CHECKING, Literal
-from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
-from nonebot_bison.utils import text_fletten
-from nonebot_bison.theme.utils import web_embed_image
from nonebot_bison.theme import Theme, ThemeRenderError, ThemeRenderUnsupportError
+from nonebot_bison.theme.utils import web_embed_image
+from nonebot_bison.utils import text_fletten
if TYPE_CHECKING:
from nonebot_bison.platform.arknights import ArknightsPost
diff --git a/nonebot_bison/theme/themes/basic/build.py b/nonebot_bison/theme/themes/basic/build.py
index 95d2249..3602a62 100644
--- a/nonebot_bison/theme/themes/basic/build.py
+++ b/nonebot_bison/theme/themes/basic/build.py
@@ -1,11 +1,12 @@
+from collections.abc import Sequence
from io import BytesIO
from pathlib import Path
from typing import TYPE_CHECKING, Literal
-from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
from nonebot_bison.theme import Theme
-from nonebot_bison.utils import pic_merge, is_pics_mergable
+from nonebot_bison.utils import is_pics_mergable, pic_merge
if TYPE_CHECKING:
from nonebot_bison.post import Post
@@ -50,7 +51,7 @@ class BasicTheme(Theme):
client = await post.platform.ctx.get_client_for_static()
msgs: list[MessageSegmentFactory] = [Text(text)]
- pics_group: list[list[str | bytes | Path | BytesIO]] = []
+ pics_group: list[Sequence[str | bytes | Path | BytesIO]] = []
if post.images:
pics_group.append(post.images)
if rp and rp.images:
diff --git a/nonebot_bison/theme/themes/brief/build.py b/nonebot_bison/theme/themes/brief/build.py
index 612d41a..57d6290 100644
--- a/nonebot_bison/theme/themes/brief/build.py
+++ b/nonebot_bison/theme/themes/brief/build.py
@@ -1,9 +1,9 @@
from typing import TYPE_CHECKING, Literal
-from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
-from nonebot_bison.utils import pic_merge, is_pics_mergable
from nonebot_bison.theme import Theme, ThemeRenderUnsupportError
+from nonebot_bison.utils import is_pics_mergable, pic_merge
if TYPE_CHECKING:
from nonebot_bison.post import Post
diff --git a/nonebot_bison/theme/themes/ceobe_canteen/build.py b/nonebot_bison/theme/themes/ceobe_canteen/build.py
index 9d3a2be..551fded 100644
--- a/nonebot_bison/theme/themes/ceobe_canteen/build.py
+++ b/nonebot_bison/theme/themes/ceobe_canteen/build.py
@@ -1,19 +1,20 @@
+from collections.abc import Sequence
+from datetime import datetime
from io import BytesIO
from pathlib import Path
-from datetime import datetime
from typing import TYPE_CHECKING, Literal
-import jinja2
-from yarl import URL
from httpx import AsyncClient
-from pydantic import BaseModel
+import jinja2
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
from PIL import Image as PILImage
-from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
+from pydantic import BaseModel
+from yarl import URL
from nonebot_bison.compat import model_validator
-from nonebot_bison.utils import pic_merge, is_pics_mergable
-from nonebot_bison.theme.utils import convert_to_qr, web_embed_image
from nonebot_bison.theme import Theme, ThemeRenderError, ThemeRenderUnsupportError
+from nonebot_bison.theme.utils import convert_to_qr, web_embed_image
+from nonebot_bison.utils import is_pics_mergable, pic_merge
if TYPE_CHECKING:
from nonebot_bison.post import Post
@@ -122,7 +123,7 @@ class CeobeCanteenTheme(Theme):
@staticmethod
async def merge_pics(
- images: list[str | bytes | Path | BytesIO],
+ images: Sequence[str | bytes | Path | BytesIO],
client: AsyncClient,
) -> list[str | bytes | Path | BytesIO]:
if is_pics_mergable(images):
@@ -224,7 +225,7 @@ class CeobeCanteenTheme(Theme):
text += f"详情: {post.url}"
msgs.append(Text(text))
- pics_group: list[list[str | bytes | Path | BytesIO]] = []
+ pics_group: list[Sequence[str | bytes | Path | BytesIO]] = []
if post.images:
pics_group.append(post.images)
if post.repost and post.repost.images:
diff --git a/nonebot_bison/theme/themes/ht2i/build.py b/nonebot_bison/theme/themes/ht2i/build.py
index 4f95fa4..8ef56c1 100644
--- a/nonebot_bison/theme/themes/ht2i/build.py
+++ b/nonebot_bison/theme/themes/ht2i/build.py
@@ -1,12 +1,13 @@
+from collections.abc import Sequence
from io import BytesIO
from pathlib import Path
from typing import TYPE_CHECKING, Literal
-from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
-from nonebot_bison.theme import Theme, ThemeRenderError
from nonebot_bison.post.protocol import HTMLContentSupport
-from nonebot_bison.utils import pic_merge, is_pics_mergable
+from nonebot_bison.theme import Theme, ThemeRenderError
+from nonebot_bison.utils import is_pics_mergable, pic_merge
if TYPE_CHECKING:
from nonebot_bison.post import Post
@@ -31,7 +32,6 @@ class Ht2iTheme(Theme):
raise ThemeRenderError(f"渲染文本失败: {e}")
async def render(self, post: "Post"):
-
md_text = ""
md_text += f"## {post.title}\n\n" if post.title else ""
@@ -50,9 +50,7 @@ class Ht2iTheme(Theme):
else:
rp_content = await rp.get_content()
- md_text += (
- "> \n> " + rp_content if len(rp_content) < 500 else f"{rp_content[:500]}..." + " \n" # noqa: E501
- ) # noqa: E501
+ md_text += "> \n> " + rp_content if len(rp_content) < 500 else f"{rp_content[:500]}..." + " \n"
md_text += "\n\n"
md_text += f"###### 来源: {post.platform.name} {post.nickname or ''}\n"
@@ -68,7 +66,7 @@ class Ht2iTheme(Theme):
if urls:
msgs.append(Text("\n".join(urls)))
- pics_group: list[list[str | bytes | Path | BytesIO]] = []
+ pics_group: list[Sequence[str | bytes | Path | BytesIO]] = []
if post.images:
pics_group.append(post.images)
if rp and rp.images:
diff --git a/nonebot_bison/theme/types.py b/nonebot_bison/theme/types.py
index 8802a08..c81aca8 100644
--- a/nonebot_bison/theme/types.py
+++ b/nonebot_bison/theme/types.py
@@ -1,14 +1,14 @@
-from typing import TYPE_CHECKING
from abc import ABC, abstractmethod
+from typing import TYPE_CHECKING
from nonebot import logger, require
-from pydantic import BaseModel, PrivateAttr
from nonebot_plugin_saa import MessageSegmentFactory
+from pydantic import BaseModel, PrivateAttr
-from ..plugin_config import plugin_config
+from nonebot_bison.plugin_config import plugin_config
if TYPE_CHECKING:
- from ..post.abstract_post import AbstractPost
+ from nonebot_bison.post.abstract_post import AbstractPost
class Theme(ABC, BaseModel):
diff --git a/nonebot_bison/theme/utils.py b/nonebot_bison/theme/utils.py
index cfc03ce..7088737 100644
--- a/nonebot_bison/theme/utils.py
+++ b/nonebot_bison/theme/utils.py
@@ -1,10 +1,10 @@
+from base64 import b64encode
from io import BytesIO
from pathlib import Path
-from base64 import b64encode
from qrcode import constants
-from qrcode.main import QRCode
from qrcode.image.pil import PilImage
+from qrcode.main import QRCode
def convert_to_qr(data: str, **kwarg) -> bytes:
diff --git a/nonebot_bison/types.py b/nonebot_bison/types.py
index 0d08bfd..8bcbe8b 100644
--- a/nonebot_bison/types.py
+++ b/nonebot_bison/types.py
@@ -1,10 +1,10 @@
-from datetime import time
from dataclasses import dataclass
-from typing import Any, Literal, NewType, NamedTuple
+from datetime import time
+from typing import Any, Literal, NamedTuple, NewType
from httpx import URL
-from pydantic import BaseModel
from nonebot_plugin_saa import PlatformTarget as SendTarget
+from pydantic import BaseModel
RawPost = Any
Target = NewType("Target", str)
diff --git a/nonebot_bison/utils/__init__.py b/nonebot_bison/utils/__init__.py
index 5da51f3..32ba253 100644
--- a/nonebot_bison/utils/__init__.py
+++ b/nonebot_bison/utils/__init__.py
@@ -1,29 +1,31 @@
+import difflib
import re
import sys
-import difflib
+from typing import Any, ClassVar
-import nonebot
-from nonebot.plugin import require
from bs4 import BeautifulSoup as bs
-from nonebot.log import logger, default_format
-from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
+import nonebot
+from nonebot.log import default_format, logger
+from nonebot.plugin import require
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
-from .site import Site as Site
-from ..plugin_config import plugin_config
-from .image import pic_merge as pic_merge
+from nonebot_bison.plugin_config import plugin_config
+
+from .context import ProcessContext as ProcessContext
from .http import http_client as http_client
from .image import capture_html as capture_html
-from .site import ClientManager as ClientManager
-from .image import text_to_image as text_to_image
-from .site import anonymous_site as anonymous_site
-from .context import ProcessContext as ProcessContext
from .image import is_pics_mergable as is_pics_mergable
+from .image import pic_merge as pic_merge
from .image import pic_url_to_image as pic_url_to_image
+from .image import text_to_image as text_to_image
+from .site import ClientManager as ClientManager
from .site import DefaultClientManager as DefaultClientManager
+from .site import Site as Site
+from .site import anonymous_site as anonymous_site
class Singleton(type):
- _instances = {}
+ _instances: ClassVar[dict[Any, Any]] = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
diff --git a/nonebot_bison/utils/context.py b/nonebot_bison/utils/context.py
index 5359969..373498f 100644
--- a/nonebot_bison/utils/context.py
+++ b/nonebot_bison/utils/context.py
@@ -1,6 +1,6 @@
from base64 import b64encode
-from httpx import Response, AsyncClient
+from httpx import AsyncClient, Response
from nonebot_bison.types import Target
diff --git a/nonebot_bison/utils/get_bot.py b/nonebot_bison/utils/get_bot.py
index 2ac1e84..6f360e9 100644
--- a/nonebot_bison/utils/get_bot.py
+++ b/nonebot_bison/utils/get_bot.py
@@ -1,12 +1,12 @@
"""提供获取 Bot 的方法"""
-from typing import Any
from collections import defaultdict
+from typing import Any
import nonebot
from nonebot.adapters import Bot
-from nonebot_plugin_saa import PlatformTarget
from nonebot.adapters.onebot.v11 import Bot as Ob11Bot
+from nonebot_plugin_saa import PlatformTarget
GROUP: dict[int, list[Bot]] = {}
USER: dict[int, list[Bot]] = {}
diff --git a/nonebot_bison/utils/http.py b/nonebot_bison/utils/http.py
index 08bfb43..4b7f477 100644
--- a/nonebot_bison/utils/http.py
+++ b/nonebot_bison/utils/http.py
@@ -1,6 +1,6 @@
import httpx
-from ..plugin_config import plugin_config
+from nonebot_bison.plugin_config import plugin_config
http_args = {
"proxies": plugin_config.bison_proxy or None,
diff --git a/nonebot_bison/utils/image.py b/nonebot_bison/utils/image.py
index ac188ff..3857497 100644
--- a/nonebot_bison/utils/image.py
+++ b/nonebot_bison/utils/image.py
@@ -1,16 +1,17 @@
-from io import BytesIO
+from collections.abc import Sequence
from functools import partial
+from io import BytesIO
from typing import Literal, TypeGuard
-from yarl import URL
-from PIL import Image
from httpx import AsyncClient
from nonebot import logger, require
-from PIL.Image import Image as PILImage
-from nonebot_plugin_saa import Text as SaaText
from nonebot_plugin_saa import Image as SaaImage
+from nonebot_plugin_saa import Text as SaaText
+from PIL import Image
+from PIL.Image import Image as PILImage
+from yarl import URL
-from ..plugin_config import plugin_config
+from nonebot_bison.plugin_config import plugin_config
async def pic_url_to_image(data: str | bytes, http_client: AsyncClient) -> PILImage:
@@ -96,7 +97,7 @@ async def pic_merge(pics: list[str | bytes], http_client: AsyncClient) -> list[s
return pics
-def is_pics_mergable(imgs: list) -> TypeGuard[list[str | bytes]]:
+def is_pics_mergable(imgs: Sequence) -> TypeGuard[list[str | bytes]]:
if any(not isinstance(img, str | bytes) for img in imgs):
return False
diff --git a/nonebot_bison/utils/site.py b/nonebot_bison/utils/site.py
index aecb00f..618a4d7 100644
--- a/nonebot_bison/utils/site.py
+++ b/nonebot_bison/utils/site.py
@@ -1,18 +1,19 @@
-import json
-from typing import Literal
-from json import JSONDecodeError
from abc import ABC, abstractmethod
from collections.abc import Callable
from datetime import datetime, timedelta
+import json
+from json import JSONDecodeError
+from typing import Literal
import httpx
from httpx import AsyncClient
from nonebot.log import logger
-from ..types import Target
-from ..config import config
+from nonebot_bison.config import config
+from nonebot_bison.config.db_model import Cookie
+from nonebot_bison.types import Target
+
from .http import http_client
-from ..config.db_model import Cookie
class ClientManager(ABC):
diff --git a/poetry.lock b/poetry.lock
index 1d635c1..da7bc2b 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
[[package]]
name = "aiodns"
@@ -470,57 +470,6 @@ type = "legacy"
url = "https://pypi.org/simple"
reference = "offical-source"
-[[package]]
-name = "black"
-version = "24.8.0"
-description = "The uncompromising code formatter."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"},
- {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"},
- {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"},
- {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"},
- {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"},
- {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"},
- {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"},
- {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"},
- {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"},
- {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"},
- {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"},
- {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"},
- {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"},
- {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"},
- {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"},
- {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"},
- {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"},
- {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"},
- {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"},
- {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"},
- {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"},
- {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"},
-]
-
-[package.dependencies]
-click = ">=8.0.0"
-mypy-extensions = ">=0.4.3"
-packaging = ">=22.0"
-pathspec = ">=0.9.0"
-platformdirs = ">=2"
-tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
-
-[package.extras]
-colorama = ["colorama (>=0.4.3)"]
-d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"]
-jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
-uvloop = ["uvloop (>=0.15.2)"]
-
-[package.source]
-type = "legacy"
-url = "https://pypi.org/simple"
-reference = "offical-source"
-
[[package]]
name = "brotli"
version = "1.1.0"
@@ -1864,25 +1813,6 @@ type = "legacy"
url = "https://pypi.org/simple"
reference = "offical-source"
-[[package]]
-name = "isort"
-version = "5.13.2"
-description = "A Python utility / library to sort Python imports."
-optional = false
-python-versions = ">=3.8.0"
-files = [
- {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
- {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
-]
-
-[package.extras]
-colors = ["colorama (>=0.4.6)"]
-
-[package.source]
-type = "legacy"
-url = "https://pypi.org/simple"
-reference = "offical-source"
-
[[package]]
name = "jedi"
version = "0.19.1"
@@ -2565,22 +2495,6 @@ type = "legacy"
url = "https://pypi.org/simple"
reference = "offical-source"
-[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-description = "Type system extensions for programs checked with the mypy type checker."
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
- {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
-]
-
-[package.source]
-type = "legacy"
-url = "https://pypi.org/simple"
-reference = "offical-source"
-
[[package]]
name = "nb-cli"
version = "1.4.2"
@@ -2970,22 +2884,6 @@ type = "legacy"
url = "https://pypi.org/simple"
reference = "offical-source"
-[[package]]
-name = "pathspec"
-version = "0.12.1"
-description = "Utility library for gitignore style pattern matching of file paths."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
- {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
-]
-
-[package.source]
-type = "legacy"
-url = "https://pypi.org/simple"
-reference = "offical-source"
-
[[package]]
name = "pexpect"
version = "4.9.0"
@@ -4222,29 +4120,29 @@ reference = "offical-source"
[[package]]
name = "ruff"
-version = "0.6.5"
+version = "0.8.2"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
- {file = "ruff-0.6.5-py3-none-linux_armv6l.whl", hash = "sha256:7e4e308f16e07c95fc7753fc1aaac690a323b2bb9f4ec5e844a97bb7fbebd748"},
- {file = "ruff-0.6.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:932cd69eefe4daf8c7d92bd6689f7e8182571cb934ea720af218929da7bd7d69"},
- {file = "ruff-0.6.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a8d42d11fff8d3143ff4da41742a98f8f233bf8890e9fe23077826818f8d680"},
- {file = "ruff-0.6.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a50af6e828ee692fb10ff2dfe53f05caecf077f4210fae9677e06a808275754f"},
- {file = "ruff-0.6.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:794ada3400a0d0b89e3015f1a7e01f4c97320ac665b7bc3ade24b50b54cb2972"},
- {file = "ruff-0.6.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:381413ec47f71ce1d1c614f7779d88886f406f1fd53d289c77e4e533dc6ea200"},
- {file = "ruff-0.6.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:52e75a82bbc9b42e63c08d22ad0ac525117e72aee9729a069d7c4f235fc4d276"},
- {file = "ruff-0.6.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09c72a833fd3551135ceddcba5ebdb68ff89225d30758027280968c9acdc7810"},
- {file = "ruff-0.6.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:800c50371bdcb99b3c1551d5691e14d16d6f07063a518770254227f7f6e8c178"},
- {file = "ruff-0.6.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e25ddd9cd63ba1f3bd51c1f09903904a6adf8429df34f17d728a8fa11174253"},
- {file = "ruff-0.6.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7291e64d7129f24d1b0c947ec3ec4c0076e958d1475c61202497c6aced35dd19"},
- {file = "ruff-0.6.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9ad7dfbd138d09d9a7e6931e6a7e797651ce29becd688be8a0d4d5f8177b4b0c"},
- {file = "ruff-0.6.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:005256d977021790cc52aa23d78f06bb5090dc0bfbd42de46d49c201533982ae"},
- {file = "ruff-0.6.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:482c1e6bfeb615eafc5899127b805d28e387bd87db38b2c0c41d271f5e58d8cc"},
- {file = "ruff-0.6.5-py3-none-win32.whl", hash = "sha256:cf4d3fa53644137f6a4a27a2b397381d16454a1566ae5335855c187fbf67e4f5"},
- {file = "ruff-0.6.5-py3-none-win_amd64.whl", hash = "sha256:3e42a57b58e3612051a636bc1ac4e6b838679530235520e8f095f7c44f706ff9"},
- {file = "ruff-0.6.5-py3-none-win_arm64.whl", hash = "sha256:51935067740773afdf97493ba9b8231279e9beef0f2a8079188c4776c25688e0"},
- {file = "ruff-0.6.5.tar.gz", hash = "sha256:4d32d87fab433c0cf285c3683dd4dae63be05fd7a1d65b3f5bf7cdd05a6b96fb"},
+ {file = "ruff-0.8.2-py3-none-linux_armv6l.whl", hash = "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d"},
+ {file = "ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5"},
+ {file = "ruff-0.8.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c"},
+ {file = "ruff-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f"},
+ {file = "ruff-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897"},
+ {file = "ruff-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58"},
+ {file = "ruff-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29"},
+ {file = "ruff-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248"},
+ {file = "ruff-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93"},
+ {file = "ruff-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d"},
+ {file = "ruff-0.8.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0"},
+ {file = "ruff-0.8.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa"},
+ {file = "ruff-0.8.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f"},
+ {file = "ruff-0.8.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22"},
+ {file = "ruff-0.8.2-py3-none-win32.whl", hash = "sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1"},
+ {file = "ruff-0.8.2-py3-none-win_amd64.whl", hash = "sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea"},
+ {file = "ruff-0.8.2-py3-none-win_arm64.whl", hash = "sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8"},
+ {file = "ruff-0.8.2.tar.gz", hash = "sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5"},
]
[package.source]
@@ -5166,4 +5064,4 @@ yaml = []
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<4.0.0"
-content-hash = "3d3bd947b91b8053fc5fed4873b6d0ed4017a5be118611cd93d30ffa265e04fb"
+content-hash = "c66f1511368c8de33a7706df2a20ef24d4191769fa29bf69bd2d5985381218d4"
diff --git a/pyproject.toml b/pyproject.toml
index 148b15c..ad1445a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -44,13 +44,11 @@ expiringdictx = "^1.1.0"
rapidfuzz = "^3.9.7"
[tool.poetry.group.dev.dependencies]
-black = ">=24.8.0,<25.0"
ipdb = "^0.13.13"
-isort = "^5.13.2"
nonemoji = "^0.1.4"
nb-cli = "^1.4.2"
pre-commit = "^4.0.1"
-ruff = "^0.6.5"
+ruff = "^0.8.2"
[tool.poetry.group.test.dependencies]
flaky = "^3.8.1"
@@ -99,25 +97,44 @@ line-length = 120
target-version = "py310"
[tool.ruff.lint]
-select = ["E", "W", "F", "UP", "C", "T", "PYI", "PT", "Q"]
-ignore = ["E402", "C901", "PT023"]
+select = [
+ "F", # Pyflakes
+ "W", # pycodestyle warnings
+ "E", # pycodestyle errors
+ "I", # isort
+ "UP", # pyupgrade
+ "ASYNC", # flake8-async
+ "C4", # flake8-comprehensions
+ "T10", # flake8-debugger
+ "T20", # flake8-print
+ "PYI", # flake8-pyi
+ "PT", # flake8-pytest-style
+ "Q", # flake8-quotes
+ "TID", # flake8-tidy-imports
+ "RUF", # Ruff-specific rules
+]
+ignore = [
+ "E402", # module-import-not-at-top-of-file
+ "UP037", # quoted-annotation
+ "RUF001", # ambiguous-unicode-character-string
+ "RUF002", # ambiguous-unicode-character-docstring
+ "RUF003", # ambiguous-unicode-character-comment
+]
-[tool.black]
-line-length = 120
-preview = true
-target-version = ["py310", "py311", "py312"]
-include = '\.pyi?$'
-extend-exclude = '''
-'''
+[tool.ruff.format]
+line-ending = "lf"
-[tool.isort]
-profile = "black"
-line_length = 120
-skip_gitignore = true
-length_sort = true
-force_sort_within_sections = true
-src_paths = ["nonebot_bison", "tests"]
-extra_standard_library = ["typing_extensions"]
+[tool.ruff.lint.isort]
+force-sort-within-sections = true
+known-first-party = ["nonebot_bison", "tests/*"]
+extra-standard-library = ["typing_extensions"]
+
+[tool.ruff.lint.flake8-pytest-style]
+fixture-parentheses = false
+mark-parentheses = false
+
+[tool.ruff.lint.pyupgrade]
+keep-runtime-typing = true
[tool.nonebot]
adapters = [
@@ -130,6 +147,7 @@ builtin_plugins = ["echo"]
[tool.pyright]
typeCheckingMode = "basic"
reportShadowedImports = false
+disableBytesTypePromotions = true
pythonVersion = "3.10"
pythonPlatform = "All"
executionEnvironments = [
diff --git a/tests/config/test_config_legacy.py b/tests/config/test_config_legacy.py
index 348d44e..6b485d2 100644
--- a/tests/config/test_config_legacy.py
+++ b/tests/config/test_config_legacy.py
@@ -1,7 +1,7 @@
import typing
-import pytest
from nonebug.app import App
+import pytest
if typing.TYPE_CHECKING:
import sys
diff --git a/tests/config/test_config_operation.py b/tests/config/test_config_operation.py
index f067603..49e7ed3 100644
--- a/tests/config/test_config_operation.py
+++ b/tests/config/test_config_operation.py
@@ -1,16 +1,16 @@
-import pytest
from nonebug.app import App
+import pytest
async def test_add_subscribe(app: App, init_scheduler):
- from nonebot_plugin_saa import TargetQQGroup
- from sqlalchemy.sql.expression import select
from nonebot_plugin_datastore.db import get_engine
+ from nonebot_plugin_saa import TargetQQGroup
from sqlalchemy.ext.asyncio.session import AsyncSession
+ from sqlalchemy.sql.expression import select
from nonebot_bison.config.db_config import config
+ from nonebot_bison.config.db_model import Subscribe, Target, User
from nonebot_bison.types import Target as TTarget
- from nonebot_bison.config.db_model import User, Target, Subscribe
await config.add_subscribe(
TargetQQGroup(group_id=123),
@@ -69,8 +69,8 @@ async def test_add_subscribe(app: App, init_scheduler):
async def test_add_dup_sub(init_scheduler):
from nonebot_plugin_saa import TargetQQGroup
- from nonebot_bison.types import Target as TTarget
from nonebot_bison.config.db_config import SubscribeDupException, config
+ from nonebot_bison.types import Target as TTarget
await config.add_subscribe(
TargetQQGroup(group_id=123),
@@ -93,15 +93,15 @@ async def test_add_dup_sub(init_scheduler):
async def test_del_subsribe(init_scheduler):
- from sqlalchemy.sql.functions import func
- from nonebot_plugin_saa import TargetQQGroup
- from sqlalchemy.sql.expression import select
from nonebot_plugin_datastore.db import get_engine
+ from nonebot_plugin_saa import TargetQQGroup
from sqlalchemy.ext.asyncio.session import AsyncSession
+ from sqlalchemy.sql.expression import select
+ from sqlalchemy.sql.functions import func
from nonebot_bison.config.db_config import config
+ from nonebot_bison.config.db_model import Subscribe, Target
from nonebot_bison.types import Target as TTarget
- from nonebot_bison.config.db_model import Target, Subscribe
await config.add_subscribe(
TargetQQGroup(group_id=123),
diff --git a/tests/config/test_cookie.py b/tests/config/test_cookie.py
index 8d463d4..120caf4 100644
--- a/tests/config/test_cookie.py
+++ b/tests/config/test_cookie.py
@@ -1,9 +1,9 @@
+from datetime import datetime
import json
from typing import cast
-from datetime import datetime
-import pytest
from nonebug import App
+import pytest
@pytest.mark.usefixtures("_patch_weibo_get_cookie_name")
@@ -11,9 +11,9 @@ async def test_cookie(app: App, init_scheduler):
from nonebot_plugin_saa import TargetQQGroup
from nonebot_bison.config.db_config import config
+ from nonebot_bison.config.utils import DuplicateCookieTargetException
from nonebot_bison.scheduler import scheduler_dict
from nonebot_bison.types import Target as T_Target
- from nonebot_bison.config.utils import DuplicateCookieTargetException
from nonebot_bison.utils.site import CookieClientManager, site_manager
target = T_Target("weibo_id")
diff --git a/tests/config/test_data_migration.py b/tests/config/test_data_migration.py
index 61e4575..06154cf 100644
--- a/tests/config/test_data_migration.py
+++ b/tests/config/test_data_migration.py
@@ -1,9 +1,9 @@
async def test_migration(use_legacy_config):
- from nonebot_plugin_saa import TargetQQGroup
from nonebot_plugin_datastore.db import init_db
+ from nonebot_plugin_saa import TargetQQGroup
- from nonebot_bison.config.db_config import config
from nonebot_bison.config.config_legacy import Config
+ from nonebot_bison.config.db_config import config
config_legacy = Config()
config_legacy.add_subscribe(
@@ -57,11 +57,11 @@ async def test_migration(use_legacy_config):
async def test_migrate_dup(use_legacy_config):
- from nonebot_plugin_saa import TargetQQGroup
from nonebot_plugin_datastore.db import init_db
+ from nonebot_plugin_saa import TargetQQGroup
- from nonebot_bison.config.db_config import config
from nonebot_bison.config.config_legacy import Config
+ from nonebot_bison.config.db_config import config
config_legacy = Config()
config_legacy.add_subscribe(
diff --git a/tests/config/test_scheduler_conf.py b/tests/config/test_scheduler_conf.py
index 5da8127..2874aea 100644
--- a/tests/config/test_scheduler_conf.py
+++ b/tests/config/test_scheduler_conf.py
@@ -7,8 +7,8 @@ from pytest_mock import MockerFixture
async def test_create_config(init_scheduler):
from nonebot_plugin_saa import TargetQQGroup
+ from nonebot_bison.config.db_config import TimeWeightConfig, WeightConfig, config
from nonebot_bison.types import Target as T_Target
- from nonebot_bison.config.db_config import WeightConfig, TimeWeightConfig, config
await config.add_subscribe(
TargetQQGroup(group_id=123),
@@ -49,8 +49,8 @@ async def test_get_current_weight(init_scheduler, mocker: MockerFixture):
from nonebot_plugin_saa import TargetQQGroup
from nonebot_bison.config import db_config
+ from nonebot_bison.config.db_config import TimeWeightConfig, WeightConfig, config
from nonebot_bison.types import Target as T_Target
- from nonebot_bison.config.db_config import WeightConfig, TimeWeightConfig, config
await config.add_subscribe(
TargetQQGroup(group_id=123),
@@ -108,13 +108,13 @@ async def test_get_current_weight(init_scheduler, mocker: MockerFixture):
async def test_get_platform_target(app: App, init_scheduler):
- from nonebot_plugin_saa import TargetQQGroup
- from sqlalchemy.sql.expression import select
from nonebot_plugin_datastore.db import get_engine
+ from nonebot_plugin_saa import TargetQQGroup
from sqlalchemy.ext.asyncio.session import AsyncSession
+ from sqlalchemy.sql.expression import select
- from nonebot_bison.config.db_model import Target
from nonebot_bison.config.db_config import config
+ from nonebot_bison.config.db_model import Target
from nonebot_bison.types import Target as T_Target
await config.add_subscribe(
@@ -158,9 +158,9 @@ async def test_get_platform_target(app: App, init_scheduler):
async def test_get_platform_target_subscribers(app: App, init_scheduler):
from nonebot_plugin_saa import TargetQQGroup
- from nonebot_bison.types import UserSubInfo
from nonebot_bison.config.db_config import config
from nonebot_bison.types import Target as T_Target
+ from nonebot_bison.types import UserSubInfo
await config.add_subscribe(
TargetQQGroup(group_id=123),
diff --git a/tests/conftest.py b/tests/conftest.py
index 9e6085e..f5368f0 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,13 +1,13 @@
-import sys
from pathlib import Path
from shutil import rmtree
+import sys
-import pytest
import nonebot
-from sqlalchemy import delete
-from nonebug import NONEBOT_INIT_KWARGS, App
-from pytest_mock.plugin import MockerFixture
from nonebot.adapters.onebot.v11 import Adapter as OnebotV11Adapter
+from nonebug import NONEBOT_INIT_KWARGS, App
+import pytest
+from pytest_mock.plugin import MockerFixture
+from sqlalchemy import delete
from .utils import AppReq
@@ -44,12 +44,12 @@ async def app(tmp_path: Path, request: pytest.FixtureRequest, mocker: MockerFixt
sys.path.append(str(Path(__file__).parent.parent / "src" / "plugins"))
nonebot.require("nonebot_bison")
- from nonebot_plugin_htmlrender.browser import shutdown_browser
- from nonebot_plugin_datastore.db import init_db, create_session
from nonebot_plugin_datastore.config import plugin_config as datastore_config
+ from nonebot_plugin_datastore.db import create_session, init_db
+ from nonebot_plugin_htmlrender.browser import shutdown_browser
from nonebot_bison import plugin_config
- from nonebot_bison.config.db_model import User, Target, Subscribe, ScheduleTimeWeight
+ from nonebot_bison.config.db_model import ScheduleTimeWeight, Subscribe, Target, User
plugin_config.bison_config_path = str(tmp_path / "legacy_config")
plugin_config.bison_filter_log = False
@@ -111,8 +111,8 @@ async def init_scheduler(app: App):
async def use_legacy_config(app: App):
import aiofiles
- from nonebot_bison.utils import Singleton
from nonebot_bison.config.config_legacy import Config, get_config_path
+ from nonebot_bison.utils import Singleton
# 默认不创建配置所在的文件夹
# 如果需要测试需要手动创建相关文件夹
@@ -132,8 +132,8 @@ async def use_legacy_config(app: App):
@pytest.fixture
async def _no_browser(app: App, mocker: MockerFixture):
- from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.platform import _get_unavailable_platforms
+ from nonebot_bison.plugin_config import plugin_config
mocker.patch.object(plugin_config, "bison_use_browser", False)
mocker.patch("nonebot_bison.platform.unavailable_paltforms", _get_unavailable_platforms())
diff --git a/tests/platforms/test_arknights.py b/tests/platforms/test_arknights.py
index 92dd0b9..e58e4ca 100644
--- a/tests/platforms/test_arknights.py
+++ b/tests/platforms/test_arknights.py
@@ -1,10 +1,10 @@
from time import time
-import respx
-import pytest
from httpx import Response
-from nonebug.app import App
from nonebot.compat import model_dump, type_validate_python
+from nonebug.app import App
+import pytest
+import respx
from .utils import get_file, get_json
@@ -12,7 +12,7 @@ from .utils import get_file, get_json
@pytest.fixture
def arknights(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["arknights"](ProcessContext(DefaultClientManager()))
@@ -44,8 +44,8 @@ def monster_siren_list_1():
@respx.mock
async def test_url_parse(app: App):
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
- from nonebot_bison.platform.arknights import Arknights, BulletinData, BulletinListItem, ArkBulletinResponse
+ from nonebot_bison.platform.arknights import ArkBulletinResponse, Arknights, BulletinData, BulletinListItem
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
cid_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletin/1")
@@ -110,10 +110,10 @@ async def test_url_parse(app: App):
assert p4.url == "http://www.baidu.com/"
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
async def test_get_date_in_bulletin(app: App):
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
from nonebot_bison.platform.arknights import Arknights, BulletinListItem
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
arknights = Arknights(ProcessContext(DefaultClientManager()))
assert (
@@ -131,11 +131,11 @@ async def test_get_date_in_bulletin(app: App):
)
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
@respx.mock
async def test_parse_with_breakline(app: App):
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
from nonebot_bison.platform.arknights import Arknights, BulletinListItem
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
detail = get_json("arknights-detail-805")
detail["data"]["header"] = ""
@@ -158,7 +158,7 @@ async def test_parse_with_breakline(app: App):
assert post.title == "【公开招募】 - 标签刷新通知"
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
@respx.mock
async def test_fetch_new(
arknights,
@@ -168,9 +168,9 @@ async def test_fetch_new(
monster_siren_list_0,
monster_siren_list_1,
):
- from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
from nonebot_bison.platform.arknights import ArknightsPost
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import SubUnit, Target
ak_list_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletinList?target=IOS")
detail_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletin/5716")
@@ -229,7 +229,7 @@ async def test_fetch_new(
assert "brief" == post3.get_priority_themes()[0]
-@pytest.mark.render()
+@pytest.mark.render
@respx.mock
async def test_send_with_render(
arknights,
@@ -239,8 +239,8 @@ async def test_send_with_render(
monster_siren_list_0,
monster_siren_list_1,
):
- from nonebot_bison.types import Target, SubUnit
from nonebot_bison.platform.arknights import ArknightsPost
+ from nonebot_bison.types import SubUnit, Target
ak_list_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletinList?target=IOS")
detail_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletin/8397")
@@ -284,13 +284,13 @@ async def test_send_with_render(
assert r
-@pytest.mark.render()
+@pytest.mark.render
@respx.mock
async def test_parse_title(
app: App,
):
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
from nonebot_bison.platform.arknights import Arknights, BulletinListItem
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
detail_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletin/8397")
diff --git a/tests/platforms/test_bilibili.py b/tests/platforms/test_bilibili.py
index 0d48679..c0c7442 100644
--- a/tests/platforms/test_bilibili.py
+++ b/tests/platforms/test_bilibili.py
@@ -1,16 +1,16 @@
+from datetime import datetime
import random
from time import time
-from datetime import datetime
-from typing import TYPE_CHECKING, Any
+from typing import TYPE_CHECKING, Any, ClassVar
-import respx
-import pytest
-from loguru import logger
-from nonebug.app import App
-from httpx import URL, Response
from freezegun import freeze_time
-from pytest_mock import MockerFixture
+from httpx import URL, Response
+from loguru import logger
from nonebot.compat import model_dump, type_validate_python
+from nonebug.app import App
+import pytest
+from pytest_mock import MockerFixture
+import respx
from .utils import get_json
@@ -28,9 +28,9 @@ if TYPE_CHECKING:
@pytest.fixture
def bilibili(app: App) -> "Bilibili":
- from nonebot_bison.utils import ProcessContext
from nonebot_bison.platform import platform_manager
from nonebot_bison.platform.bilibili import BilibiliClientManager
+ from nonebot_bison.utils import ProcessContext
return platform_manager["bilibili"](ProcessContext(BilibiliClientManager())) # type: ignore
@@ -62,7 +62,7 @@ def without_dynamic(app: App):
async def test_reset_on_exception(app: App):
from strenum import StrEnum
- from nonebot_bison.platform.bilibili.fsm import FSM, StateGraph, Transition, ActionReturn, reset_on_exception
+ from nonebot_bison.platform.bilibili.fsm import FSM, ActionReturn, StateGraph, Transition, reset_on_exception
class State(StrEnum):
A = "A"
@@ -146,12 +146,12 @@ async def test_reset_on_exception(app: App):
@pytest.mark.asyncio
async def test_retry_for_352(app: App, mocker: MockerFixture):
- from nonebot_bison.post import Post
- from nonebot_bison.types import Target, RawPost
- from nonebot_bison.platform.platform import NewMessage
from nonebot_bison.platform.bilibili.platforms import ApiCode352Error
- from nonebot_bison.utils import ClientManager, ProcessContext, http_client
from nonebot_bison.platform.bilibili.retry import RetryAddon, RetryState, _retry_fsm, retry_for_352
+ from nonebot_bison.platform.platform import NewMessage
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import RawPost, Target
+ from nonebot_bison.utils import ClientManager, ProcessContext, http_client
mocker.patch.object(random, "random", return_value=0.0) # 稳定触发RAISE阶段的随缘刷新
@@ -166,7 +166,7 @@ async def test_retry_for_352(app: App, mocker: MockerFixture):
is_common = True
schedule_interval = 10
enable_tag = False
- categories = {}
+ categories: ClassVar[dict] = {}
has_target = True
raise352 = False
@@ -422,7 +422,7 @@ async def test_dynamic_forword_deleted(bilibili: "Bilibili", bing_dy_list: list)
@pytest.mark.asyncio
@respx.mock
async def test_fetch_new_without_dynamic(bilibili, dummy_user_subinfo, without_dynamic):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
target = Target("161775300")
post_router = respx.get(
@@ -439,8 +439,8 @@ async def test_fetch_new_without_dynamic(bilibili, dummy_user_subinfo, without_d
async def test_fetch_new(bilibili, dummy_user_subinfo):
from nonebot.compat import model_dump, type_validate_python
- from nonebot_bison.types import Target, SubUnit
from nonebot_bison.platform.bilibili.models import PostAPI
+ from nonebot_bison.types import SubUnit, Target
target = Target("161775300")
@@ -483,8 +483,8 @@ async def test_fetch_new(bilibili, dummy_user_subinfo):
async def test_fetch_new_live_rcmd(bilibili: "Bilibili", dummy_user_subinfo):
from nonebot.compat import model_dump, type_validate_python
- from nonebot_bison.types import Target, SubUnit
from nonebot_bison.platform.bilibili.models import PostAPI
+ from nonebot_bison.types import SubUnit, Target
target = Target("13164144")
diff --git a/tests/platforms/test_bilibili_bangumi.py b/tests/platforms/test_bilibili_bangumi.py
index d4c9c71..9f83491 100644
--- a/tests/platforms/test_bilibili_bangumi.py
+++ b/tests/platforms/test_bilibili_bangumi.py
@@ -1,9 +1,9 @@
import typing
-import respx
-import pytest
from httpx import Response
from nonebug.app import App
+import pytest
+import respx
from .utils import get_json
@@ -14,7 +14,7 @@ if typing.TYPE_CHECKING:
@pytest.fixture
def bili_bangumi(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["bilibili-bangumi"](ProcessContext(DefaultClientManager()))
@@ -38,7 +38,7 @@ async def test_parse_target(bili_bangumi: "BilibiliBangumi"):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_bilibili_bangumi_status(bili_bangumi: "BilibiliBangumi", dummy_user_subinfo):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
bili_bangumi_router = respx.get("https://api.bilibili.com/pgc/review/user?media_id=28235413")
bili_bangumi_detail_router = respx.get("https://api.bilibili.com/pgc/view/web/season?season_id=39719")
diff --git a/tests/platforms/test_bilibili_live.py b/tests/platforms/test_bilibili_live.py
index 65762f5..2c7e713 100644
--- a/tests/platforms/test_bilibili_live.py
+++ b/tests/platforms/test_bilibili_live.py
@@ -1,10 +1,10 @@
from copy import deepcopy
from typing import TYPE_CHECKING
-import respx
-import pytest
from httpx import Response
from nonebug.app import App
+import pytest
+import respx
from .utils import get_json
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
@pytest.fixture
def bili_live(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["bilibili-live"](ProcessContext(DefaultClientManager()))
@@ -33,7 +33,7 @@ def dummy_only_open_user_subinfo(app: App):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_bililive_no_room(bili_live, dummy_only_open_user_subinfo):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
mock_bili_live_status = get_json("bili_live_status.json")
mock_bili_live_status["data"] = {}
@@ -53,7 +53,7 @@ async def test_fetch_bililive_no_room(bili_live, dummy_only_open_user_subinfo):
@respx.mock
async def test_fetch_first_live(bili_live, dummy_only_open_user_subinfo):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
mock_bili_live_status = get_json("bili_live_status.json")
empty_bili_live_status = deepcopy(mock_bili_live_status)
@@ -90,7 +90,7 @@ async def test_fetch_first_live(bili_live, dummy_only_open_user_subinfo):
@respx.mock
async def test_fetch_bililive_only_live_open(bili_live: "Bilibililive", dummy_only_open_user_subinfo):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
mock_bili_live_status = get_json("bili_live_status.json")
@@ -141,11 +141,11 @@ def dummy_only_title_user_subinfo(app: App):
return UserSubInfo(user=user, categories=[2], tags=[])
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
@respx.mock
async def test_fetch_bililive_only_title_change(bili_live, dummy_only_title_user_subinfo):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
mock_bili_live_status = get_json("bili_live_status.json")
target = Target("13164144")
@@ -204,7 +204,7 @@ def dummy_only_close_user_subinfo(app: App):
@respx.mock
async def test_fetch_bililive_only_close(bili_live, dummy_only_close_user_subinfo):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
mock_bili_live_status = get_json("bili_live_status.json")
target = Target("13164144")
@@ -264,7 +264,7 @@ def dummy_bililive_user_subinfo(app: App):
@respx.mock
async def test_fetch_bililive_combo(bili_live, dummy_bililive_user_subinfo):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
mock_bili_live_status = get_json("bili_live_status.json")
target = Target("13164144")
diff --git a/tests/platforms/test_ceobecanteen.py b/tests/platforms/test_ceobecanteen.py
index d2e3988..67186eb 100644
--- a/tests/platforms/test_ceobecanteen.py
+++ b/tests/platforms/test_ceobecanteen.py
@@ -1,10 +1,10 @@
from typing import TYPE_CHECKING
-import respx
-import pytest
from httpx import Response
-from nonebug.app import App
from nonebot.compat import type_validate_python
+from nonebug.app import App
+import pytest
+import respx
from .utils import get_json
@@ -24,9 +24,9 @@ def dummy_only_open_user_subinfo(app: App):
@pytest.fixture
def ceobecanteen(app: App):
- from nonebot_bison.utils import ProcessContext
from nonebot_bison.platform import platform_manager
from nonebot_bison.platform.ceobecanteen.platform import CeobeCanteenClientManager
+ from nonebot_bison.utils import ProcessContext
return platform_manager["ceobecanteen"](ProcessContext(CeobeCanteenClientManager()))
@@ -71,7 +71,7 @@ def ceobecanteen_cookies_1() -> dict:
return get_json("ceobecanteen_cookies_1.json")
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
async def test_parse_retweet(app: App):
from nonebot_bison.platform.ceobecanteen.models import CookiesResponse
@@ -79,7 +79,7 @@ async def test_parse_retweet(app: App):
assert cookie_with_retweet.data.cookies[0].item.retweeted
-@pytest.mark.render()
+@pytest.mark.render
async def test_ceobe_snapshot(app: App, ceobecanteen: "CeobeCanteen"):
from nonebot_bison.platform.ceobecanteen.models import CeobeCookie
@@ -113,7 +113,7 @@ async def test_ceobe_snapshot(app: App, ceobecanteen: "CeobeCanteen"):
@pytest.mark.skip("极限测试, 不在CI中运行")
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
async def test_parse_crazy(app: App, ceobecanteen):
from nonebot_plugin_saa import Image
@@ -139,7 +139,7 @@ async def test_parse_crazy(app: App, ceobecanteen):
show(ext((await post4.generate_messages())[0][0])) # type: ignore
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
@respx.mock
async def test_batch_fetch_new_with_single(
app: App,
@@ -220,7 +220,7 @@ async def test_batch_fetch_new_with_single(
await post3.generate_messages()
-@pytest.mark.asyncio()
+@pytest.mark.asyncio
@respx.mock
async def test_parse_target_fuzzy(app: App, ceobecanteen: "CeobeCanteen", dummy_target, ceobecanteen_targets):
from nonebot_bison.platform.ceobecanteen import CeobeCanteen
diff --git a/tests/platforms/test_ff14.py b/tests/platforms/test_ff14.py
index c6512f8..7b0bf03 100644
--- a/tests/platforms/test_ff14.py
+++ b/tests/platforms/test_ff14.py
@@ -1,7 +1,7 @@
-import respx
-import pytest
from httpx import Response
from nonebug.app import App
+import pytest
+import respx
from .utils import get_json
@@ -9,7 +9,7 @@ from .utils import get_json
@pytest.fixture
def ff14(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["ff14"](ProcessContext(DefaultClientManager()))
@@ -28,7 +28,7 @@ def ff14_newdata_json_1():
@respx.mock
async def test_fetch_new(ff14, dummy_user_subinfo, ff14_newdata_json_0, ff14_newdata_json_1):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
newdata = respx.get(
"https://cqnews.web.sdo.com/api/news/newsList?gameCode=ff&CategoryCode=5309,5310,5311,5312,5313&pageIndex=0&pageSize=5"
diff --git a/tests/platforms/test_ncm_artist.py b/tests/platforms/test_ncm_artist.py
index 91b5921..fc9c716 100644
--- a/tests/platforms/test_ncm_artist.py
+++ b/tests/platforms/test_ncm_artist.py
@@ -1,10 +1,10 @@
import time
import typing
-import respx
-import pytest
from httpx import Response
from nonebug.app import App
+import pytest
+import respx
from .utils import get_json
@@ -15,7 +15,7 @@ if typing.TYPE_CHECKING:
@pytest.fixture
def ncm_artist(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["ncm-artist"](ProcessContext(DefaultClientManager()))
@@ -41,7 +41,7 @@ def ncm_artist_1(ncm_artist_raw: dict):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_new(ncm_artist, ncm_artist_0, ncm_artist_1, dummy_user_subinfo):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
ncm_router = respx.get("https://music.163.com/api/artist/albums/32540734")
ncm_router.mock(return_value=Response(200, json=ncm_artist_0))
diff --git a/tests/platforms/test_ncm_radio.py b/tests/platforms/test_ncm_radio.py
index 37b9d45..bc9cae9 100644
--- a/tests/platforms/test_ncm_radio.py
+++ b/tests/platforms/test_ncm_radio.py
@@ -1,10 +1,10 @@
import time
import typing
-import respx
-import pytest
from httpx import Response
from nonebug.app import App
+import pytest
+import respx
from .utils import get_json
@@ -15,7 +15,7 @@ if typing.TYPE_CHECKING:
@pytest.fixture
def ncm_radio(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["ncm-radio"](ProcessContext(DefaultClientManager()))
@@ -42,7 +42,7 @@ def ncm_radio_1(ncm_radio_raw: dict):
@respx.mock
async def test_fetch_new(ncm_radio, ncm_radio_0, ncm_radio_1, dummy_user_subinfo):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
ncm_router = respx.post("http://music.163.com/api/dj/program/byradio")
ncm_router.mock(return_value=Response(200, json=ncm_radio_0))
diff --git a/tests/platforms/test_platform.py b/tests/platforms/test_platform.py
index 689607b..5efedae 100644
--- a/tests/platforms/test_platform.py
+++ b/tests/platforms/test_platform.py
@@ -1,15 +1,16 @@
from time import time
-from typing import Any
+from typing import Any, ClassVar
-import pytest
from nonebug.app import App
+import pytest
now = time()
passed = now - 3 * 60 * 60
raw_post_list_1 = [{"id": 1, "text": "p1", "date": now, "tags": ["tag1"], "category": 1}]
-raw_post_list_2 = raw_post_list_1 + [
+raw_post_list_2 = [
+ *raw_post_list_1,
{"id": 2, "text": "p2", "date": now, "tags": ["tag1"], "category": 1},
{"id": 3, "text": "p3", "date": now, "tags": ["tag2"], "category": 2},
{"id": 4, "text": "p4", "date": now, "tags": ["tag2"], "category": 3},
@@ -36,9 +37,9 @@ def user_info_factory(app: App, dummy_user):
@pytest.fixture
def mock_platform_without_cats_tags(app: App):
- from nonebot_bison.post import Post
- from nonebot_bison.types import Target, RawPost
from nonebot_bison.platform.platform import NewMessage
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import RawPost, Target
class MockPlatform(NewMessage):
platform_name = "mock_platform"
@@ -47,7 +48,7 @@ def mock_platform_without_cats_tags(app: App):
is_common = True
schedule_interval = 10
enable_tag = False
- categories = {}
+ categories: ClassVar[dict] = {}
has_target = True
sub_index = 0
@@ -83,15 +84,15 @@ def mock_platform_without_cats_tags(app: App):
@pytest.fixture
def mock_platform(app: App):
- from nonebot_bison.post import Post
- from nonebot_bison.utils import Site
from nonebot_bison.platform.platform import NewMessage
- from nonebot_bison.types import Tag, Target, RawPost, Category
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import Category, RawPost, Tag, Target
+ from nonebot_bison.utils import Site
class MockSite(Site):
name = "mock_site"
schedule_type = "interval"
- schedule_setting = {"seconds": 100}
+ schedule_setting: ClassVar[dict] = {"seconds": 100}
class MockPlatform(NewMessage):
platform_name = "mock_platform"
@@ -101,7 +102,7 @@ def mock_platform(app: App):
enable_tag = True
has_target = True
site = MockSite
- categories = {
+ categories: ClassVar[dict] = {
Category(1): "转发",
Category(2): "视频",
}
@@ -150,16 +151,16 @@ def mock_site(app):
class MockSite(Site):
name = "mock_site"
schedule_type = "interval"
- schedule_setting = {"seconds": 100}
+ schedule_setting: ClassVar[dict] = {"seconds": 100}
return MockSite
@pytest.fixture
def mock_platform_no_target(app: App, mock_site):
+ from nonebot_bison.platform.platform import CategoryNotSupport, NewMessage
from nonebot_bison.post import Post
- from nonebot_bison.types import Tag, Target, RawPost, Category
- from nonebot_bison.platform.platform import NewMessage, CategoryNotSupport
+ from nonebot_bison.types import Category, RawPost, Tag, Target
class MockPlatform(NewMessage):
platform_name = "mock_platform"
@@ -169,7 +170,7 @@ def mock_platform_no_target(app: App, mock_site):
site = mock_site
enable_tag = True
has_target = False
- categories = {Category(1): "转发", Category(2): "视频", Category(3): "不支持"}
+ categories: ClassVar[dict] = {Category(1): "转发", Category(2): "视频", Category(3): "不支持"}
sub_index = 0
@@ -212,9 +213,9 @@ def mock_platform_no_target(app: App, mock_site):
@pytest.fixture
def mock_platform_no_target_2(app: App, mock_site):
- from nonebot_bison.post import Post
from nonebot_bison.platform.platform import NewMessage
- from nonebot_bison.types import Tag, Target, RawPost, Category
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import Category, RawPost, Tag, Target
class MockPlatform(NewMessage):
platform_name = "mock_platform"
@@ -224,7 +225,7 @@ def mock_platform_no_target_2(app: App, mock_site):
is_common = True
enable_tag = True
has_target = False
- categories = {
+ categories: ClassVar[dict] = {
Category(4): "leixing4",
Category(5): "leixing5",
}
@@ -259,7 +260,8 @@ def mock_platform_no_target_2(app: App, mock_site):
async def get_sub_list(cls, _: "Target"):
list_1 = [{"id": 5, "text": "p5", "date": now, "tags": ["tag1"], "category": 4}]
- list_2 = list_1 + [
+ list_2 = [
+ *list_1,
{"id": 6, "text": "p6", "date": now, "tags": ["tag1"], "category": 4},
{"id": 7, "text": "p7", "date": now, "tags": ["tag2"], "category": 5},
]
@@ -274,9 +276,9 @@ def mock_platform_no_target_2(app: App, mock_site):
@pytest.fixture
def mock_status_change(app: App):
- from nonebot_bison.post import Post
from nonebot_bison.platform.platform import StatusChange
- from nonebot_bison.types import Target, RawPost, Category
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import Category, RawPost, Target
class MockPlatform(StatusChange):
platform_name = "mock_platform"
@@ -285,9 +287,9 @@ def mock_status_change(app: App):
is_common = True
enable_tag = False
schedule_type = "interval"
- schedule_kw = {"seconds": 10}
+ schedule_kw: ClassVar[dict] = {"seconds": 10}
has_target = False
- categories = {
+ categories: ClassVar[dict] = {
Category(1): "转发",
Category(2): "视频",
}
@@ -323,8 +325,8 @@ def mock_status_change(app: App):
@pytest.mark.asyncio
async def test_new_message_target_without_cats_tags(mock_platform_without_cats_tags, user_info_factory):
- from nonebot_bison.types import Target, SubUnit
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.types import SubUnit, Target
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
res1 = await mock_platform_without_cats_tags(ProcessContext(DefaultClientManager())).fetch_new_post(
SubUnit(Target("dummy"), [user_info_factory([1, 2], [])])
@@ -344,8 +346,8 @@ async def test_new_message_target_without_cats_tags(mock_platform_without_cats_t
@pytest.mark.asyncio
async def test_new_message_target(mock_platform, user_info_factory):
- from nonebot_bison.types import Target, SubUnit
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.types import SubUnit, Target
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
res1 = await mock_platform(ProcessContext(DefaultClientManager())).fetch_new_post(
SubUnit(Target("dummy"), [user_info_factory([1, 2], [])])
@@ -379,8 +381,8 @@ async def test_new_message_target(mock_platform, user_info_factory):
@pytest.mark.asyncio
async def test_new_message_no_target(mock_platform_no_target, user_info_factory):
- from nonebot_bison.types import Target, SubUnit
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.types import SubUnit, Target
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
res1 = await mock_platform_no_target(ProcessContext(DefaultClientManager())).fetch_new_post(
SubUnit(Target("dummy"), [user_info_factory([1, 2], [])])
@@ -418,8 +420,8 @@ async def test_new_message_no_target(mock_platform_no_target, user_info_factory)
@pytest.mark.asyncio
async def test_status_change(mock_status_change, user_info_factory):
- from nonebot_bison.types import Target, SubUnit
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.types import SubUnit, Target
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
res1 = await mock_status_change(ProcessContext(DefaultClientManager())).fetch_new_post(
SubUnit(Target("dummy"), [user_info_factory([1, 2], [])])
@@ -458,9 +460,9 @@ async def test_group(
mock_platform_no_target_2,
user_info_factory,
):
- from nonebot_bison.types import Target, SubUnit
from nonebot_bison.platform.platform import make_no_target_group
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.types import SubUnit, Target
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
dummy = Target("dummy")
@@ -482,11 +484,11 @@ async def test_group(
async def test_batch_fetch_new_message(app: App):
from nonebot_plugin_saa import TargetQQGroup
- from nonebot_bison.post import Post
- from nonebot_bison.utils import DefaultClientManager
from nonebot_bison.platform.platform import NewMessage
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import RawPost, SubUnit, Target, UserSubInfo
+ from nonebot_bison.utils import DefaultClientManager
from nonebot_bison.utils.context import ProcessContext
- from nonebot_bison.types import Target, RawPost, SubUnit, UserSubInfo
class BatchNewMessage(NewMessage):
platform_name = "mock_platform"
@@ -495,7 +497,7 @@ async def test_batch_fetch_new_message(app: App):
is_common = True
schedule_interval = 10
enable_tag = False
- categories = {}
+ categories: ClassVar[dict] = {}
has_target = True
sub_index = 0
@@ -569,11 +571,11 @@ async def test_batch_fetch_new_message(app: App):
async def test_batch_fetch_compare_status(app: App):
from nonebot_plugin_saa import TargetQQGroup
+ from nonebot_bison.platform.platform import StatusChange
from nonebot_bison.post import Post
+ from nonebot_bison.types import Category, RawPost, SubUnit, Target, UserSubInfo
from nonebot_bison.utils import DefaultClientManager
from nonebot_bison.utils.context import ProcessContext
- from nonebot_bison.platform.platform import StatusChange
- from nonebot_bison.types import Target, RawPost, SubUnit, Category, UserSubInfo
class BatchStatusChange(StatusChange):
platform_name = "mock_platform"
@@ -582,9 +584,9 @@ async def test_batch_fetch_compare_status(app: App):
is_common = True
enable_tag = False
schedule_type = "interval"
- schedule_kw = {"seconds": 10}
+ schedule_kw: ClassVar[dict] = {"seconds": 10}
has_target = True
- categories = {
+ categories: ClassVar[dict] = {
Category(1): "转发",
Category(2): "视频",
}
diff --git a/tests/platforms/test_platform_tag_filter.py b/tests/platforms/test_platform_tag_filter.py
index 1e02fa8..6272821 100644
--- a/tests/platforms/test_platform_tag_filter.py
+++ b/tests/platforms/test_platform_tag_filter.py
@@ -1,5 +1,5 @@
-import pytest
from nonebug.app import App
+import pytest
from .utils import get_json
@@ -13,7 +13,7 @@ def test_cases():
@pytest.mark.asyncio
async def test_filter_user_custom_tag(app: App, test_cases):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
bilibili = platform_manager["bilibili"](ProcessContext(DefaultClientManager()))
for case in test_cases:
@@ -25,7 +25,7 @@ async def test_filter_user_custom_tag(app: App, test_cases):
@pytest.mark.asyncio
async def test_tag_separator(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
bilibili = platform_manager["bilibili"](ProcessContext(DefaultClientManager()))
tags = ["~111", "222", "333", "~444", "555"]
diff --git a/tests/platforms/test_rss.py b/tests/platforms/test_rss.py
index dc3a715..cddd3d1 100644
--- a/tests/platforms/test_rss.py
+++ b/tests/platforms/test_rss.py
@@ -1,12 +1,12 @@
-import typing
from datetime import datetime
+import typing
import xml.etree.ElementTree as ET
-import pytz
-import respx
-import pytest
from httpx import Response
from nonebug.app import App
+import pytest
+import pytz
+import respx
from .utils import get_file
@@ -35,7 +35,7 @@ def user_info_factory(app: App, dummy_user):
@pytest.fixture
def rss(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["rss"](ProcessContext(DefaultClientManager()))
@@ -71,7 +71,7 @@ async def test_fetch_new_1(
user_info_factory,
update_time_feed_1,
):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
## 标题重复的情况
rss_router = respx.get("https://rsshub.app/twitter/user/ArknightsStaff")
@@ -113,7 +113,7 @@ async def test_fetch_new_2(
user_info_factory,
update_time_feed_2,
):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
## 标题与正文不重复的情况
rss_router = respx.get("https://www.ruanyifeng.com/blog/atom.xml")
@@ -148,7 +148,7 @@ async def test_fetch_new_3(
user_info_factory,
update_time_feed_3,
):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
## 只有没有
rss_router = respx.get("https://github.com/R3nzTheCodeGOD/R3nzSkin/releases.atom")
@@ -172,7 +172,7 @@ async def test_fetch_new_4(
rss,
user_info_factory,
):
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
## 没有日期信息的情况
rss_router = respx.get("https://rsshub.app/wallhaven/hot?limit=5")
diff --git a/tests/platforms/test_weibo.py b/tests/platforms/test_weibo.py
index e499660..c82a851 100644
--- a/tests/platforms/test_weibo.py
+++ b/tests/platforms/test_weibo.py
@@ -1,12 +1,12 @@
-import typing
from datetime import datetime
+import typing
-import respx
-import pytest
import feedparser
-from pytz import timezone
+from httpx import AsyncClient, Response
from nonebug.app import App
-from httpx import Response, AsyncClient
+import pytest
+from pytz import timezone
+import respx
from .utils import get_file, get_json
@@ -19,7 +19,7 @@ image_cdn_router = respx.route(host__regex=r"wx\d.sinaimg.cn", path__startswith=
@pytest.fixture
def weibo(app: App):
from nonebot_bison.platform import platform_manager
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return platform_manager["weibo"](ProcessContext(DefaultClientManager()))
@@ -42,7 +42,7 @@ async def test_get_name(weibo):
@respx.mock
async def test_fetch_new(weibo, dummy_user_subinfo):
from nonebot_bison.post import Post
- from nonebot_bison.types import Target, SubUnit
+ from nonebot_bison.types import SubUnit, Target
ak_list_router = respx.get("https://m.weibo.cn/api/container/getIndex?containerid=1076036279793937")
detail_router = respx.get("https://m.weibo.cn/statuses/extend?id=4649031014551911")
@@ -184,7 +184,7 @@ async def test_rsshub_compare(weibo):
test_post = {
"mblog": {
- "text": ( # noqa
+ "text": (
'#刚出生的小羊驼长啥样#
小羊驼三三来也
bytes:
@pytest.fixture
def mock_platform(app: App):
- from nonebot_bison.post import Post
- from nonebot_bison.types import Target, RawPost
from nonebot_bison.platform.platform import NewMessage
+ from nonebot_bison.post import Post
+ from nonebot_bison.types import RawPost, Target
class MockPlatform(NewMessage):
platform_name = "mock_platform"
@@ -47,7 +48,7 @@ def mock_platform(app: App):
is_common = True
schedule_interval = 10
enable_tag = False
- categories = {}
+ categories: ClassVar[dict] = {}
has_target = True
sub_index = 0
@@ -84,7 +85,7 @@ def mock_platform(app: App):
@pytest.fixture
def mock_post(app: App, mock_platform):
from nonebot_bison.post import Post
- from nonebot_bison.utils import ProcessContext, DefaultClientManager
+ from nonebot_bison.utils import DefaultClientManager, ProcessContext
return Post(
m := mock_platform(ProcessContext(DefaultClientManager())),
@@ -161,7 +162,7 @@ async def test_theme_no_enable_use_browser(app: App, mock_post, mocker: MockerFi
@pytest.mark.asyncio
@flaky(max_runs=3, min_passes=1)
async def test_arknights_theme(app: App, mock_post):
- from nonebot_plugin_saa import Text, Image
+ from nonebot_plugin_saa import Image, Text
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.arknights import ArknightsTheme
@@ -178,7 +179,7 @@ async def test_arknights_theme(app: App, mock_post):
@pytest.mark.asyncio
async def test_basic_theme(app: App, mock_post: "Post", MERGEABLE_PNG_DATA, SIMPLE_PNG_DATA):
- from nonebot_plugin_saa import Text, Image
+ from nonebot_plugin_saa import Image, Text
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.basic import BasicTheme
@@ -233,7 +234,7 @@ async def test_basic_theme(app: App, mock_post: "Post", MERGEABLE_PNG_DATA, SIMP
@pytest.mark.asyncio
async def test_brief_theme(app: App, mock_post):
- from nonebot_plugin_saa import Text, Image
+ from nonebot_plugin_saa import Image, Text
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.brief import BriefTheme
@@ -275,7 +276,7 @@ async def test_brief_theme(app: App, mock_post):
@pytest.mark.asyncio
@flaky(max_runs=3, min_passes=1)
async def test_ceobecanteen_theme(app: App, mock_post: "Post", MERGEABLE_PNG_DATA, SIMPLE_PNG_DATA):
- from nonebot_plugin_saa import Text, Image
+ from nonebot_plugin_saa import Image, Text
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.ceobe_canteen import CeobeCanteenTheme
@@ -301,7 +302,7 @@ async def test_ceobecanteen_theme(app: App, mock_post: "Post", MERGEABLE_PNG_DAT
@pytest.mark.asyncio
@flaky(max_runs=3, min_passes=1)
async def test_ht2i_theme(app: App, mock_post: "Post", MERGEABLE_PNG_DATA, SIMPLE_PNG_DATA):
- from nonebot_plugin_saa import Text, Image
+ from nonebot_plugin_saa import Image, Text
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.ht2i import Ht2iTheme
diff --git a/tests/utils.py b/tests/utils.py
index 24f459e..21c225a 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -12,9 +12,9 @@ class AppReq(TypedDict, total=False):
def fake_group_message_event(**field) -> "GroupMessageEvent":
- from pydantic import create_model
+ from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
from nonebot.adapters.onebot.v11.event import Sender
- from nonebot.adapters.onebot.v11 import Message, GroupMessageEvent
+ from pydantic import create_model
_Fake = create_model("_Fake", __base__=GroupMessageEvent)
@@ -48,9 +48,9 @@ def fake_group_message_event(**field) -> "GroupMessageEvent":
def fake_private_message_event(**field) -> "PrivateMessageEvent":
- from pydantic import create_model
- from nonebot.adapters.onebot.v11.event import Sender
from nonebot.adapters.onebot.v11 import Message, PrivateMessageEvent
+ from nonebot.adapters.onebot.v11.event import Sender
+ from pydantic import create_model
_Fake = create_model("_Fake", __base__=PrivateMessageEvent)
@@ -89,7 +89,6 @@ add_reply_on_id_input_search = (
class BotReply:
-
@staticmethod
def add_reply_on_platform(platform_manager, common_platform):
return (