diff --git a/handler.py b/handler.py index 324e351d..fe9eec42 100644 --- a/handler.py +++ b/handler.py @@ -7,7 +7,6 @@ from manager import PluginsManager from plugins.auth import Auth from plugins.base import NewChatMembersHandler from plugins.errorhandler import error_handler -from plugins.help import Help from plugins.inline import Inline from plugins.start import start, ping, reply_keyboard_remove, unknown_command from service import BaseService @@ -39,20 +38,18 @@ def register_handlers(application: Application, service: BaseService): plugins_manager.refresh_list("./plugins/*") # 忽略内置模块 - plugins_manager.add_exclude(["help", "start", "base", "auth", "inline", "errorhandler"]) + plugins_manager.add_exclude(["start", "base", "auth", "inline", "errorhandler"]) Log.info("加载插件管理器正在加载插件") plugins_manager.import_module() - plugins_manager.add_handler(application, (service,)) + plugins_manager.add_handler(application, service) Log.info("正在加载内置插件") - plugins_help = Help() inline = Inline(service) auth = Auth(service) add_handler(start, command="start") - add_handler(plugins_help.command_start, command="help") add_handler(ping, command="ping") add_handler(auth.query, query=r"^auth_challenge\|") add_handler(auth.admin, query=r"^auth_admin\|") diff --git a/manager.py b/manager.py index 5e16cdff..1c9083a3 100644 --- a/manager.py +++ b/manager.py @@ -2,20 +2,29 @@ import os from glob import glob from importlib import import_module from os import path -from typing import List, Union +from typing import List, Union, Tuple, Callable from telegram.ext import Application from logger import Log -from plugins.base import BasePlugins +from service import BaseService -PluginsClass: List[BasePlugins] = [] +PluginsClass: List[Tuple[any, dict]] = [] -def listener_plugins_class(): - def decorator(func: BasePlugins): +def listener_plugins_class(need_service: bool = False): + """监听插件 + + :param need_service: 插件类中 create_handlers 函数是否传入 service + :return: None + """ + plugin_info = { + "need_service": need_service + } + + def decorator(func: Callable): PluginsClass.append( - func + (func, plugin_info) ) return func @@ -61,12 +70,17 @@ class PluginsManager: Log.debug(f"插件 {plugin_name} 加载成功") @staticmethod - def add_handler(application: Application, args=None): + def add_handler(application: Application, service: BaseService): for pc in PluginsClass: - if callable(pc): + func = pc[0] + plugin_info = pc[1] + # 构建 kwargs + kwargs = {} + if plugin_info.get("need_service", False): + kwargs["service"] = service + if callable(func): try: - ist: BasePlugins = pc(*args) - handlers_list = ist.create_handlers(*args) + handlers_list = func.create_handlers(**kwargs) for handler in handlers_list: application.add_handler(handler) except AttributeError as exc: diff --git a/plugins/README.md b/plugins/README.md index b7377ed5..a17337bd 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -12,23 +12,23 @@ ``` python from telegram import Update -from telegram.ext import CallbackContext from manager import listener_plugins_class from plugins.base import BasePlugins, restricts from plugins.errorhandler import conversation_error_handler +from utils.base import PaimonContext @listener_plugins_class() class Example(BasePlugins): - @staticmethod - def create_handlers(service: BaseService): - example = Example(service) + @classmethod + def create_handlers(cls): + example = cls() return [CommandHandler('example', example.command_start)] @conversation_error_handler @restricts() - async def command_start(self, update: Update, context: CallbackContext) -> None: + async def command_start(self, update: Update, context: PaimonContext) -> None: await message.reply_text("Example") ``` @@ -51,3 +51,4 @@ plugins 模块下的类必须提供 `create_handlers` 静态函数作为构建 **注意:`@restricts()` 修饰器带参,必须带括号,否则会出现调用错误** +如果 `service` 需要全局共用,可以参考 `daily_note.py` 代码 \ No newline at end of file diff --git a/plugins/abyss.py b/plugins/abyss.py index bfe71f16..2760340c 100644 --- a/plugins/abyss.py +++ b/plugins/abyss.py @@ -13,14 +13,9 @@ from utils.base import PaimonContext @listener_plugins_class() class Abyss(BasePlugins): - def __init__(self, *args): - """Abyss插件入口""" - pass - - @staticmethod - def create_handlers(*args) -> list: - _ = args - abyss = Abyss() + @classmethod + def create_handlers(cls) -> list: + abyss = cls() return [ CommandHandler("abyss", abyss.command_start, block=False), MessageHandler(filters.Regex(r"^深渊数据查询(.*)"), abyss.command_start, block=True) diff --git a/plugins/admin.py b/plugins/admin.py index 4f725d2b..86a96ccf 100644 --- a/plugins/admin.py +++ b/plugins/admin.py @@ -6,13 +6,13 @@ from telegram.ext import CallbackContext, CommandHandler from logger import Log from manager import listener_plugins_class -from plugins.base import BasePlugins -from service import BaseService +from utils.base import PaimonContext def bot_admins_only(func: Callable) -> Callable: # noqa - async def decorator(self, update: Update, context: CallbackContext): - admin_list = await self.service.admin.get_admin_list() + async def decorator(self, update: Update, context: PaimonContext): + service = context.service + admin_list = await service.admin.get_admin_list() if update.message.from_user.id in admin_list: return await func(self, update, context) else: @@ -23,14 +23,13 @@ def bot_admins_only(func: Callable) -> Callable: # noqa @listener_plugins_class() -class Admin(BasePlugins): - """ - 有关BOT ADMIN处理 +class Admin: + """有关BOT ADMIN处理 """ - @staticmethod - def create_handlers(service: BaseService) -> list: - admin = Admin(service) + @classmethod + def create_handlers(cls) -> list: + admin = cls() return [ CommandHandler("add_admin", admin.add_admin, block=False), CommandHandler("del_admin", admin.del_admin, block=False), @@ -38,29 +37,31 @@ class Admin(BasePlugins): ] @bot_admins_only - async def add_admin(self, update: Update, _: CallbackContext): + async def add_admin(self, update: Update, context: PaimonContext): message = update.message reply_to_message = message.reply_to_message - admin_list = await self.service.admin.get_admin_list() + service = context.service + admin_list = await service.admin.get_admin_list() if reply_to_message is None: await message.reply_text("请回复对应消息") else: if reply_to_message.from_user.id in admin_list: await message.reply_text("该用户已经存在管理员列表") else: - await self.service.admin.add_admin(reply_to_message.from_user.id) + await service.admin.add_admin(reply_to_message.from_user.id) await message.reply_text("添加成功") @bot_admins_only - async def del_admin(self, update: Update, _: CallbackContext): + async def del_admin(self, update: Update, context: PaimonContext): message = update.message reply_to_message = message.reply_to_message - admin_list = await self.service.admin.get_admin_list() + service = context.service + admin_list = await service.admin.get_admin_list() if reply_to_message is None: await message.reply_text("请回复对应消息") else: if reply_to_message.from_user.id in admin_list: - await self.service.admin.delete_admin(reply_to_message.from_user.id) + await service.admin.delete_admin(reply_to_message.from_user.id) await message.reply_text("删除成功") else: await message.reply_text("该用户不存在管理员列表") diff --git a/plugins/artifact_rate.py b/plugins/artifact_rate.py index cef1b38b..73c1190b 100644 --- a/plugins/artifact_rate.py +++ b/plugins/artifact_rate.py @@ -9,9 +9,8 @@ from telegram.helpers import escape_markdown from logger import Log from manager import listener_plugins_class from model.apihelper.artifact import ArtifactOcrRate, get_comment, get_format_sub_item -from plugins.base import BasePlugins, restricts +from plugins.base import restricts, BasePlugins from plugins.errorhandler import conversation_error_handler -from service import BaseService @listener_plugins_class() @@ -31,13 +30,12 @@ class ArtifactRate(BasePlugins): f"{i * 5 + j}", callback_data=f"artifact_ocr_rate_data|level|{i * 5 + j}") for j in range(1, 6) ] for i in range(0, 4)] - def __init__(self, service: BaseService): - super().__init__(service) + def __init__(self): self.artifact_rate = ArtifactOcrRate() - @staticmethod - def create_handlers(service: BaseService) -> list: - artifact_rate = ArtifactRate(service) + @classmethod + def create_handlers(cls) -> list: + artifact_rate = cls() return [ ConversationHandler( entry_points=[CommandHandler('artifact_rate', artifact_rate.command_start), diff --git a/plugins/auth.py b/plugins/auth.py index 9d1898cd..f821db6b 100644 --- a/plugins/auth.py +++ b/plugins/auth.py @@ -11,8 +11,8 @@ from telegram.helpers import escape_markdown from logger import Log from model.helpers import get_admin_list -from utils.random import MT19937_Random from service import BaseService +from utils.random import MT19937_Random FullChatPermissions = ChatPermissions( can_send_messages=True, diff --git a/plugins/base.py b/plugins/base.py index 29d1224e..1297899d 100644 --- a/plugins/base.py +++ b/plugins/base.py @@ -4,7 +4,6 @@ from functools import wraps from typing import Callable, Optional from telegram import Update, ReplyKeyboardRemove -from telegram.constants import ChatType from telegram.error import BadRequest from telegram.ext import CallbackContext, ConversationHandler, filters @@ -37,8 +36,6 @@ def add_delete_message_job(context: CallbackContext, chat_id: int, message_id: i class BasePlugins: - def __init__(self, service: BaseService): - self.service = service @staticmethod async def cancel(update: Update, _: CallbackContext) -> int: @@ -88,22 +85,28 @@ class NewChatMembersHandler: def restricts(filters_chat: filters = filters.ALL, return_data=None, try_delete_message: bool = False, restricts_time: int = 5): - """ - 用于装饰在指定函数防止洪水调用的装饰器 + """用于装饰在指定函数防止洪水调用的装饰器 - 被修饰的函数传入参数必须为 - async def command_func(update, context) - 或 - async def command_func(self, update, context) + 被修饰的函数生声明必须为 - 如果修饰的函数属于 - ConversationHandler - 参数 - return_data - 必须传入 - ConversationHandler.END + async def command_func(update, context) + 或 + async def command_func(self, update, context - 我真™是服了某些闲着没事干的群友了 + 如果修饰的函数属于 + ConversationHandler + 参数 + return_data + 必须传入 + ConversationHandler.END + + 我真™是服了某些闲着没事干的群友了 + + :param filters_chat: 要限制的群 + :param return_data: + :param try_delete_message: + :param restricts_time: + :return: return_data """ def decorator(func: Callable): diff --git a/plugins/cookies.py b/plugins/cookies.py index ee01c75c..ac277068 100644 --- a/plugins/cookies.py +++ b/plugins/cookies.py @@ -1,6 +1,4 @@ from http.cookies import SimpleCookie, CookieError -from typing import List -from urllib.request import BaseHandler import genshin import ujson @@ -12,10 +10,10 @@ from telegram.helpers import escape_markdown from logger import Log from manager import listener_plugins_class from model.base import ServiceEnum -from plugins.base import BasePlugins, restricts +from plugins.base import restricts, BasePlugins from plugins.errorhandler import conversation_error_handler -from service import BaseService from service.base import UserInfoData +from utils.base import PaimonContext class CookiesCommandData: @@ -33,9 +31,9 @@ class Cookies(BasePlugins): CHECK_SERVER, CHECK_COOKIES, COMMAND_RESULT = range(10100, 10103) - @staticmethod - def create_handlers(service: BaseService): - cookies = Cookies(service) + @classmethod + def create_handlers(cls): + cookies = cls() cookies_handler = ConversationHandler( entry_points=[CommandHandler('adduser', cookies.command_start, filters.ChatType.PRIVATE, block=True), MessageHandler(filters.Regex(r"^绑定账号(.*)") & filters.ChatType.PRIVATE, @@ -70,10 +68,11 @@ class Cookies(BasePlugins): @conversation_error_handler @restricts(return_data=ConversationHandler.END) - async def check_server(self, update: Update, context: CallbackContext) -> int: + async def check_server(self, update: Update, context: PaimonContext) -> int: user = update.effective_user + service = context.service cookies_command_data: CookiesCommandData = context.chat_data.get("cookies_command_data") - user_info = await self.service.user_service_db.get_user_info(user.id) + user_info = await service.user_service_db.get_user_info(user.id) cookies_command_data.user_info = user_info if update.message.text == "退出": await update.message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove()) @@ -175,8 +174,9 @@ class Cookies(BasePlugins): return self.COMMAND_RESULT @conversation_error_handler - async def command_result(self, update: Update, context: CallbackContext) -> int: + async def command_result(self, update: Update, context: PaimonContext) -> int: user = update.effective_user + service = context.service cookies_command_data: CookiesCommandData = context.chat_data.get("cookies_command_data") if update.message.text == "退出": await update.message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove()) @@ -184,17 +184,17 @@ class Cookies(BasePlugins): elif update.message.text == "确认": data = ujson.dumps(cookies_command_data.cookies) user_info = cookies_command_data.user_info - service = ServiceEnum.NULL.value + game_service = ServiceEnum.NULL.value if cookies_command_data.service == ServiceEnum.HYPERION: user_info.mihoyo_game_uid = cookies_command_data.game_uid - service = ServiceEnum.HYPERION.value + game_service = ServiceEnum.HYPERION.value elif cookies_command_data.service == ServiceEnum.HOYOLAB: user_info.hoyoverse_game_uid = cookies_command_data.game_uid - service = ServiceEnum.HOYOLAB.value - await self.service.user_service_db.set_user_info(user.id, user_info.mihoyo_game_uid, - user_info.hoyoverse_game_uid, - service) - await self.service.user_service_db.set_cookie(user.id, data, cookies_command_data.service) + game_service = ServiceEnum.HOYOLAB.value + await service.user_service_db.set_user_info(user.id, user_info.mihoyo_game_uid, + user_info.hoyoverse_game_uid, + game_service) + await service.user_service_db.set_cookie(user.id, data, cookies_command_data.service) Log.info(f"用户 {user.full_name}[{user.id}] 绑定账号成功") await update.message.reply_text("保存成功", reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END diff --git a/plugins/daily_note.py b/plugins/daily_note.py index 057522db..e2c7a4f1 100644 --- a/plugins/daily_note.py +++ b/plugins/daily_note.py @@ -5,8 +5,8 @@ import genshin from genshin import GenshinException, DataNotPublic from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.constants import ChatAction -from telegram.ext import CallbackContext, CommandHandler, MessageHandler, ConversationHandler, filters, \ - CallbackQueryHandler +from telegram.ext import CommandHandler, MessageHandler, ConversationHandler, filters, \ + CallbackQueryHandler, CallbackContext from logger import Log from manager import listener_plugins_class @@ -21,7 +21,7 @@ class UidCommandData: user_info: UserInfoData = UserInfoData() -@listener_plugins_class() +@listener_plugins_class(need_service=True) class DailyNote(BasePlugins): """ 每日便签 @@ -30,12 +30,12 @@ class DailyNote(BasePlugins): COMMAND_RESULT, = range(10200, 10201) def __init__(self, service: BaseService): - super().__init__(service) + self.service = service self.current_dir = os.getcwd() - @staticmethod - def create_handlers(service: BaseService) -> list: - daily_note = DailyNote(service) + @classmethod + def create_handlers(cls, service: BaseService) -> list: + daily_note = cls(service) daily_note_handler = ConversationHandler( entry_points=[CommandHandler('dailynote', daily_note.command_start, block=True), MessageHandler(filters.Regex(r"^当前状态(.*)"), daily_note.command_start, block=True)], @@ -46,8 +46,8 @@ class DailyNote(BasePlugins): ) return [daily_note_handler] - async def _start_get_daily_note(self, user_info_data: UserInfoData, service: ServiceEnum) -> bytes: - if service == ServiceEnum.HYPERION: + async def _get_daily_note_data(self, user_info_data: UserInfoData, game_service: ServiceEnum) -> bytes: + if game_service == ServiceEnum.HYPERION: client = genshin.ChineseClient(cookies=user_info_data.mihoyo_cookie) uid = user_info_data.mihoyo_game_uid else: diff --git a/plugins/gacha.py b/plugins/gacha.py index c98922df..f2c787bb 100644 --- a/plugins/gacha.py +++ b/plugins/gacha.py @@ -3,14 +3,14 @@ import os from pyppeteer import launch from telegram import Update from telegram.constants import ChatAction -from telegram.ext import CallbackContext, ConversationHandler, filters, CommandHandler, MessageHandler +from telegram.ext import ConversationHandler, filters, CommandHandler, MessageHandler from logger import Log from manager import listener_plugins_class from plugins.base import BasePlugins, restricts from plugins.errorhandler import conversation_error_handler -from service import BaseService from service.wish import WishCountInfo, get_one +from utils.base import PaimonContext @listener_plugins_class() @@ -19,17 +19,16 @@ class Gacha(BasePlugins): 抽卡模拟器(非首模拟器/减寿模拟器) """ - @staticmethod - def create_handlers(service: BaseService) -> list: - gacha = Gacha(service) + @classmethod + def create_handlers(cls) -> list: + gacha = cls() return [ CommandHandler("gacha", gacha.command_start, block=False), MessageHandler(filters.Regex("^抽卡模拟器(.*)"), gacha.command_start, block=False), MessageHandler(filters.Regex("^非首模拟器(.*)"), gacha.command_start, block=False), ] - def __init__(self, service: BaseService): - super().__init__(service) + def __init__(self): self.browser: launch = None self.current_dir = os.getcwd() self.resources_dir = os.path.join(self.current_dir, "resources") @@ -41,11 +40,12 @@ class Gacha(BasePlugins): @conversation_error_handler @restricts(filters.ChatType.GROUPS, restricts_time=20, try_delete_message=True) @restricts(filters.ChatType.PRIVATE) - async def command_start(self, update: Update, context: CallbackContext) -> None: + async def command_start(self, update: Update, context: PaimonContext) -> None: message = update.message user = update.effective_user args = context.args match = context.match + service = context.service gacha_name = "角色活动" if args is None: if match is not None: @@ -64,7 +64,7 @@ class Gacha(BasePlugins): await message.reply_text(f"没有找到名为 {gacha_name} 的卡池") return ConversationHandler.END Log.info(f"用户 {user.full_name}[{user.id}] 抽卡模拟器命令请求 || 参数 {gacha_name}") - gacha_info = await self.service.gacha.gacha_info(gacha_name) + gacha_info = await service.gacha.gacha_info(gacha_name) # 用户数据储存和处理 if gacha_info.get("gacha_id") is None: await message.reply_text(f"没有找到名为 {gacha_name} 的卡池") @@ -104,8 +104,8 @@ class Gacha(BasePlugins): data["items"].sort(key=take_rang, reverse=True) await message.reply_chat_action(ChatAction.UPLOAD_PHOTO) # 因为 gacha_info["title"] 返回的是 HTML 标签 尝试关闭自动转义 - png_data = await self.service.template.render('genshin/gacha', "gacha.html", data, - {"width": 1157, "height": 603}, False, False) + png_data = await service.template.render('genshin/gacha', "gacha.html", data, + {"width": 1157, "height": 603}, False, False) reply_message = await message.reply_photo(png_data) if filters.ChatType.GROUPS.filter(message): diff --git a/plugins/help.py b/plugins/help.py index 32acd9b0..90278400 100644 --- a/plugins/help.py +++ b/plugins/help.py @@ -1,13 +1,16 @@ from telegram import Update from telegram.constants import ChatAction from telegram.error import BadRequest +from telegram.ext import CommandHandler from config import config from logger import Log +from manager import listener_plugins_class from plugins.base import restricts from utils.base import PaimonContext +@listener_plugins_class() class Help: """ 帮助 @@ -17,6 +20,13 @@ class Help: self.help_png = None self.file_id = None + @classmethod + def create_handlers(cls) -> list: + _help = cls() + return [ + CommandHandler("help", _help.command_start, block=False), + ] + @restricts() async def command_start(self, update: Update, context: PaimonContext) -> None: message = update.message diff --git a/plugins/ledger.py b/plugins/ledger.py index 447e4a32..9838c4b2 100644 --- a/plugins/ledger.py +++ b/plugins/ledger.py @@ -1,9 +1,9 @@ -import os import json -import genshin +import os import re - from datetime import datetime, timedelta + +import genshin from genshin import GenshinException, DataNotPublic from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.constants import ChatAction @@ -59,7 +59,7 @@ def process_ledger_month(context: CallbackContext) -> int: return now_time.month -@listener_plugins_class() +@listener_plugins_class(need_service=True) class Ledger(BasePlugins): """ 旅行札记 @@ -68,12 +68,12 @@ class Ledger(BasePlugins): COMMAND_RESULT, = range(10200, 10201) def __init__(self, service: BaseService): - super().__init__(service) + self.service = service self.current_dir = os.getcwd() - @staticmethod - def create_handlers(service: BaseService): - ledger = Ledger(service) + @classmethod + def create_handlers(cls, service: BaseService): + ledger = cls(service) return [ConversationHandler( entry_points=[CommandHandler("ledger", ledger.command_start, block=True), MessageHandler(filters.Regex(r"^旅行扎记(.*)"), ledger.command_start, block=True)], @@ -83,8 +83,8 @@ class Ledger(BasePlugins): fallbacks=[CommandHandler("cancel", ledger.cancel, block=True)] )] - async def _start_get_ledger(self, user_info_data: UserInfoData, service: ServiceEnum, month=None) -> bytes: - if service == ServiceEnum.HYPERION: + async def _start_get_ledger(self, user_info_data: UserInfoData, game_service: ServiceEnum, month=None) -> bytes: + if game_service == ServiceEnum.HYPERION: client = genshin.ChineseClient(cookies=user_info_data.mihoyo_cookie) uid = user_info_data.mihoyo_game_uid else: diff --git a/plugins/post.py b/plugins/post.py index 88762d25..283c898d 100644 --- a/plugins/post.py +++ b/plugins/post.py @@ -27,7 +27,7 @@ class PostHandlerData: self.tags: Optional[List[str]] = [] -@listener_plugins_class() +@listener_plugins_class(need_service=True) class Post(BasePlugins): """ 文章推送 @@ -39,26 +39,26 @@ class Post(BasePlugins): MENU_KEYBOARD = ReplyKeyboardMarkup([["推送频道", "添加TAG"], ["编辑文字", "删除图片"], ["退出"]], True, True) def __init__(self, service: BaseService): - super().__init__(service) + self.service = service self.bbs = Hyperion() - @staticmethod - def create_handlers(service: BaseService): - _post = Post(service) + @classmethod + def create_handlers(cls, service: BaseService): + post = cls(service) post_handler = ConversationHandler( - entry_points=[CommandHandler('post', _post.command_start, block=True)], + entry_points=[CommandHandler('post', post.command_start, block=True)], states={ - _post.CHECK_POST: [MessageHandler(filters.TEXT & ~filters.COMMAND, _post.check_post, block=True)], - _post.SEND_POST: [MessageHandler(filters.TEXT & ~filters.COMMAND, _post.send_post, block=True)], - _post.CHECK_COMMAND: [MessageHandler(filters.TEXT & ~filters.COMMAND, _post.check_command, block=True)], - _post.GTE_DELETE_PHOTO: [ - MessageHandler(filters.TEXT & ~filters.COMMAND, _post.get_delete_photo, block=True)], - _post.GET_POST_CHANNEL: [ - MessageHandler(filters.TEXT & ~filters.COMMAND, _post.get_post_channel, block=True)], - _post.GET_TAGS: [MessageHandler(filters.TEXT & ~filters.COMMAND, _post.get_tags, block=True)], - _post.GET_TEXT: [MessageHandler(filters.TEXT & ~filters.COMMAND, _post.get_edit_text, block=True)] + post.CHECK_POST: [MessageHandler(filters.TEXT & ~filters.COMMAND, post.check_post, block=True)], + post.SEND_POST: [MessageHandler(filters.TEXT & ~filters.COMMAND, post.send_post, block=True)], + post.CHECK_COMMAND: [MessageHandler(filters.TEXT & ~filters.COMMAND, post.check_command, block=True)], + post.GTE_DELETE_PHOTO: [ + MessageHandler(filters.TEXT & ~filters.COMMAND, post.get_delete_photo, block=True)], + post.GET_POST_CHANNEL: [ + MessageHandler(filters.TEXT & ~filters.COMMAND, post.get_post_channel, block=True)], + post.GET_TAGS: [MessageHandler(filters.TEXT & ~filters.COMMAND, post.get_tags, block=True)], + post.GET_TEXT: [MessageHandler(filters.TEXT & ~filters.COMMAND, post.get_edit_text, block=True)] }, - fallbacks=[CommandHandler('cancel', _post.cancel, block=True)] + fallbacks=[CommandHandler('cancel', post.cancel, block=True)] ) return [post_handler] diff --git a/plugins/quiz.py b/plugins/quiz.py index 6b6d9a5f..a82cd2d8 100644 --- a/plugins/quiz.py +++ b/plugins/quiz.py @@ -11,10 +11,10 @@ from telegram.helpers import escape_markdown from logger import Log from manager import listener_plugins_class -from utils.random import MT19937_Random from plugins.base import BasePlugins, restricts from service import BaseService from service.base import QuestionData, AnswerData +from utils.random import MT19937_Random class QuizCommandData: @@ -25,7 +25,7 @@ class QuizCommandData: status: int = 0 -@listener_plugins_class() +@listener_plugins_class(need_service=True) class Quiz(BasePlugins): """ 派蒙的十万个为什么 @@ -37,15 +37,14 @@ class Quiz(BasePlugins): QUESTION_EDIT, SAVE_QUESTION = range(10300, 10308) def __init__(self, service: BaseService): - super().__init__(service) self.user_time = {} self.service = service self.time_out = 120 self.random = MT19937_Random() - @staticmethod - def create_handlers(service: BaseService): - quiz = Quiz(service) + @classmethod + def create_handlers(cls, service: BaseService): + quiz = cls(service) quiz_handler = ConversationHandler( entry_points=[CommandHandler('quiz', quiz.command_start, block=True)], states={ diff --git a/plugins/sign.py b/plugins/sign.py index ab7d4fbe..6e2fbbed 100644 --- a/plugins/sign.py +++ b/plugins/sign.py @@ -13,8 +13,8 @@ from manager import listener_plugins_class from model.base import ServiceEnum from plugins.base import BasePlugins, restricts from plugins.errorhandler import conversation_error_handler -from service import BaseService from service.base import UserInfoData +from utils.base import PaimonContext class SignCommandData: @@ -31,9 +31,9 @@ class Sign(BasePlugins): CHECK_SERVER, COMMAND_RESULT = range(10400, 10402) - @staticmethod - def create_handlers(service: BaseService): - sign = Sign(service) + @classmethod + def create_handlers(cls): + sign = cls() sign_handler = ConversationHandler( entry_points=[CommandHandler('sign', sign.command_start, block=True), MessageHandler(filters.Regex(r"^每日签到(.*)"), sign.command_start, block=True)], @@ -45,8 +45,8 @@ class Sign(BasePlugins): return [sign_handler] @staticmethod - async def _start_sign(user_info: UserInfoData, service: ServiceEnum) -> str: - if service == ServiceEnum.HYPERION: + async def _start_sign(user_info: UserInfoData, game_service: ServiceEnum) -> str: + if game_service == ServiceEnum.HYPERION: client = genshin.ChineseClient(cookies=user_info.mihoyo_cookie) uid = user_info.mihoyo_game_uid else: @@ -93,9 +93,10 @@ class Sign(BasePlugins): @conversation_error_handler @restricts(return_data=ConversationHandler.END) - async def command_start(self, update: Update, context: CallbackContext) -> int: + async def command_start(self, update: Update, context: PaimonContext) -> int: user = update.effective_user message = update.message + service = context.service Log.info(f"用户 {user.full_name}[{user.id}] 每日签到命令请求") if filters.ChatType.GROUPS.filter(message): self._add_delete_message_job(context, message.chat_id, message.message_id) @@ -103,7 +104,7 @@ class Sign(BasePlugins): if sign_command_data is None: sign_command_data = SignCommandData() context.chat_data["sign_command_data"] = sign_command_data - user_info = await self.service.user_service_db.get_user_info(user.id) + user_info = await service.user_service_db.get_user_info(user.id) if user_info.user_id == 0: await update.message.reply_text("未查询到账号信息,请先私聊派蒙绑定账号") return ConversationHandler.END diff --git a/plugins/start.py b/plugins/start.py index 82edb853..db719fdc 100644 --- a/plugins/start.py +++ b/plugins/start.py @@ -2,12 +2,11 @@ from telegram import Update, ReplyKeyboardRemove from telegram.ext import CallbackContext from telegram.helpers import escape_markdown -from utils.base import PaimonContext from plugins.base import restricts @restricts() -async def start(update: Update, context: PaimonContext) -> None: +async def start(update: Update, context: CallbackContext) -> None: user = update.effective_user message = update.message args = context.args diff --git a/plugins/strategy.py b/plugins/strategy.py index cd4e4fe1..e0c4544a 100644 --- a/plugins/strategy.py +++ b/plugins/strategy.py @@ -1,6 +1,6 @@ from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.constants import ChatAction, ParseMode -from telegram.ext import CallbackContext, filters, ConversationHandler, CommandHandler, MessageHandler +from telegram.ext import filters, ConversationHandler, CommandHandler, MessageHandler from logger import Log from manager import listener_plugins_class @@ -8,7 +8,7 @@ from metadata.shortname import roleToName from model.helpers import url_to_file from plugins.base import BasePlugins, restricts from plugins.errorhandler import conversation_error_handler -from service import BaseService +from utils.base import PaimonContext @listener_plugins_class() @@ -19,9 +19,9 @@ class Strategy(BasePlugins): KEYBOARD = [[InlineKeyboardButton(text="查看角色攻略列表并查询", switch_inline_query_current_chat="查看角色攻略列表并查询")]] - @staticmethod - def create_handlers(service: BaseService) -> list: - strategy = Strategy(service) + @classmethod + def create_handlers(cls) -> list: + strategy = cls() return [ CommandHandler("strategy", strategy.command_start, block=False), MessageHandler(filters.Regex("^角色攻略查询(.*)"), strategy.command_start, block=False), @@ -29,11 +29,12 @@ class Strategy(BasePlugins): @conversation_error_handler @restricts(return_data=ConversationHandler.END) - async def command_start(self, update: Update, context: CallbackContext) -> None: + async def command_start(self, update: Update, context: PaimonContext) -> None: message = update.message user = update.effective_user args = context.args match = context.match + service = context.service role_name: str = "" if args is None: if match is not None: @@ -52,7 +53,7 @@ class Strategy(BasePlugins): self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id) return role_name = roleToName(role_name) - url = await self.service.get_game_info.get_characters_cultivation_atlas(role_name) + url = await service.get_game_info.get_characters_cultivation_atlas(role_name) if url == "": reply_message = await message.reply_text(f"没有找到 {role_name} 的攻略", reply_markup=InlineKeyboardMarkup(self.KEYBOARD)) diff --git a/plugins/uid.py b/plugins/uid.py index cfc445f7..37b7d96c 100644 --- a/plugins/uid.py +++ b/plugins/uid.py @@ -22,7 +22,7 @@ class UidCommandData: user_info: UserInfoData = UserInfoData() -@listener_plugins_class() +@listener_plugins_class(need_service=True) class Uid(BasePlugins): """ 玩家查询 @@ -31,12 +31,12 @@ class Uid(BasePlugins): COMMAND_RESULT, = range(10200, 10201) def __init__(self, service: BaseService): - super().__init__(service) + self.service = service self.current_dir = os.getcwd() - @staticmethod - def create_handlers(service: BaseService): - uid = Uid(service) + @classmethod + def create_handlers(cls, service: BaseService): + uid = cls(service) uid_handler = ConversationHandler( entry_points=[CommandHandler('uid', uid.command_start, block=True), MessageHandler(filters.Regex(r"^玩家查询(.*)"), uid.command_start, block=True)], diff --git a/plugins/weapon.py b/plugins/weapon.py index 05389d79..01f4ec04 100644 --- a/plugins/weapon.py +++ b/plugins/weapon.py @@ -1,6 +1,6 @@ from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.constants import ChatAction -from telegram.ext import CallbackContext, filters, CommandHandler, MessageHandler +from telegram.ext import filters, CommandHandler, MessageHandler from logger import Log from manager import listener_plugins_class @@ -8,7 +8,7 @@ from metadata.shortname import weaponToName from model.helpers import url_to_file from plugins.base import BasePlugins, restricts from plugins.errorhandler import conversation_error_handler -from service import BaseService +from utils.base import PaimonContext @listener_plugins_class() @@ -19,9 +19,9 @@ class Weapon(BasePlugins): KEYBOARD = [[InlineKeyboardButton(text="查看武器列表并查询", switch_inline_query_current_chat="查看武器列表并查询")]] - @staticmethod - def create_handlers(service: BaseService) -> list: - weapon = Weapon(service) + @classmethod + def create_handlers(cls) -> list: + weapon = cls() return [ CommandHandler("weapon", weapon.command_start, block=False), MessageHandler(filters.Regex("^武器查询(.*)"), weapon.command_start, block=False) @@ -29,11 +29,12 @@ class Weapon(BasePlugins): @conversation_error_handler @restricts() - async def command_start(self, update: Update, context: CallbackContext) -> None: + async def command_start(self, update: Update, context: PaimonContext) -> None: message = update.message user = update.effective_user args = context.args match = context.match + service = context.service weapon_name: str = "" if args is None: if match is not None: @@ -90,8 +91,8 @@ class Weapon(BasePlugins): return _template_data template_data = await input_template_data(weapon_data) - png_data = await self.service.template.render('genshin/weapon', "weapon.html", template_data, - {"width": 540, "height": 540}) + png_data = await service.template.render('genshin/weapon', "weapon.html", template_data, + {"width": 540, "height": 540}) await message.reply_chat_action(ChatAction.UPLOAD_PHOTO) await message.reply_photo(png_data, filename=f"{template_data['weapon_name']}.png", allow_sending_without_reply=True) diff --git a/plugins/wiki.py b/plugins/wiki.py index 6b2344ca..1a27e2d5 100644 --- a/plugins/wiki.py +++ b/plugins/wiki.py @@ -1,10 +1,10 @@ from telegram import Update -from telegram.ext import CallbackContext, CommandHandler +from telegram.ext import CommandHandler from manager import listener_plugins_class from plugins.admin import bot_admins_only from plugins.base import BasePlugins -from service import BaseService +from utils.base import PaimonContext @listener_plugins_class() @@ -13,16 +13,17 @@ class Wiki(BasePlugins): 有关WIKI """ - @staticmethod - def create_handlers(service: BaseService) -> list: - wiki = Wiki(service) + @classmethod + def create_handlers(cls) -> list: + wiki = cls() return [ CommandHandler("refresh_wiki", wiki.refresh_wiki, block=False), ] @bot_admins_only - async def refresh_wiki(self, update: Update, _: CallbackContext): + async def refresh_wiki(self, update: Update, context: PaimonContext): message = update.message + service = context.service await message.reply_text("正在刷新Wiki缓存,请稍等") - await self.service.wiki.refresh_wiki() + await service.wiki.refresh_wiki() await message.reply_text("刷新Wiki缓存成功") diff --git a/utils/base.py b/utils/base.py index 1dfbcb5a..0e47e61d 100644 --- a/utils/base.py +++ b/utils/base.py @@ -4,13 +4,15 @@ from service import BaseService class PaimonContext(CallbackContext[ExtBot, dict, dict, dict]): - """ - PaimoeContext 类 - """ + """自定义的PaimoeContext""" @property def service(self) -> BaseService: - value = self.bot_data.get("service") + """在回调中从 bot_data 获取 service 实例 + + :return: BaseService 实例 + """ + value = self.application.bot_data.get("service") if value is None: - raise RuntimeError("没有与此上下文对象关联的实例化服务") + raise RuntimeError("没有找到与此上下文对象关联的实例化服务") return value