From be30efda223089c16dbbf0e715b346996eb7bdcd Mon Sep 17 00:00:00 2001 From: Drsanwujiang Date: Mon, 4 Nov 2024 17:01:22 +0800 Subject: [PATCH 1/5] Fix case sensitivity issue --- app/dispatch.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/dispatch.py b/app/dispatch.py index 9853544..0f3db12 100644 --- a/app/dispatch.py +++ b/app/dispatch.py @@ -63,8 +63,9 @@ def load_orders_and_events(self) -> None: for order in plugin_orders: if isinstance(order, str) and order: + # Orders should be case-insensitive orders[plugin.priority].append({ - "pattern": re.compile(fr"^({order})\s*([\S\s]*)$"), + "pattern": re.compile(fr"^({order})\s*([\S\s]*)$", re.I), "name": plugin_name }) @@ -114,6 +115,7 @@ def dispatch_order(self, message: Message, message_content: str) -> None: plugin_class = self.order_plugins[plugin_name] try: + # Always pass the order converted to lowercase to the plugin plugin = plugin_class(message, order.lower(), order_content, repetition) if not plugin.check_enabled(): From 0f72240fcd016bee2a3d358dd15bc6dbe280282a Mon Sep 17 00:00:00 2001 From: Drsanwujiang Date: Mon, 4 Nov 2024 17:12:19 +0800 Subject: [PATCH 2/5] Fix config issue --- app/config.py | 4 +-- app/exceptions.py | 14 +++++----- app/models/config.py | 42 ++++++++++++++++++----------- app/router/admin.py | 6 ++--- plugin/__init__.py | 14 +++++----- plugin/dicerobot/order/daily_60s.py | 4 +-- 6 files changed, 48 insertions(+), 36 deletions(-) diff --git a/app/config.py b/app/config.py index c443e32..3489430 100644 --- a/app/config.py +++ b/app/config.py @@ -55,8 +55,8 @@ def init_config() -> None: for item in session.execute(select(Replies)).scalars().fetchall(): # type: Replies _replies.setdefault(item.group, {})[item.key] = item.value - for _reply_group, _group_replies in _replies.items(): - replies.set(reply_group=_reply_group, replies=_group_replies) + for _group, _group_replies in _replies.items(): + replies.set_replies(group=_group, replies=_group_replies) logger.info("Config initialized") diff --git a/app/exceptions.py b/app/exceptions.py index 6d42b30..dff4426 100644 --- a/app/exceptions.py +++ b/app/exceptions.py @@ -8,37 +8,37 @@ def __init__(self, reply: str) -> None: class NetworkClientError(DiceRobotException): def __init__(self) -> None: - super().__init__(replies.get_reply(reply_group="dicerobot", reply_key="network_client_error")) + super().__init__(replies.get_reply(group="dicerobot", key="network_client_error")) class NetworkServerError(DiceRobotException): def __init__(self) -> None: - super().__init__(replies.get_reply(reply_group="dicerobot", reply_key="network_server_error")) + super().__init__(replies.get_reply(group="dicerobot", key="network_server_error")) class NetworkInvalidContentError(DiceRobotException): def __init__(self) -> None: - super().__init__(replies.get_reply(reply_group="dicerobot", reply_key="network_invalid_content")) + super().__init__(replies.get_reply(group="dicerobot", key="network_invalid_content")) class NetworkError(DiceRobotException): def __init__(self) -> None: - super().__init__(replies.get_reply(reply_group="dicerobot", reply_key="network_error")) + super().__init__(replies.get_reply(group="dicerobot", key="network_error")) class OrderInvalidError(DiceRobotException): def __init__(self) -> None: - super().__init__(replies.get_reply(reply_group="dicerobot", reply_key="order_invalid")) + super().__init__(replies.get_reply(group="dicerobot", key="order_invalid")) class OrderSuspiciousError(DiceRobotException): def __init__(self) -> None: - super().__init__(replies.get_reply(reply_group="dicerobot", reply_key="order_suspicious")) + super().__init__(replies.get_reply(group="dicerobot", key="order_suspicious")) class OrderRepetitionExceededError(DiceRobotException): def __init__(self) -> None: - super().__init__(replies.get_reply(reply_group="dicerobot", reply_key="order_repetition_exceeded")) + super().__init__(replies.get_reply(group="dicerobot", key="order_repetition_exceeded")) class OrderError(DiceRobotException): diff --git a/app/models/config.py b/app/models/config.py index 109fa41..249a81c 100644 --- a/app/models/config.py +++ b/app/models/config.py @@ -276,7 +276,10 @@ def set(cls, *, plugin: str, settings: dict) -> None: settings: Settings to be set. """ - cls._plugin_settings[plugin] = deepcopy(settings) + if plugin in cls._plugin_settings: + cls._plugin_settings[plugin] |= deepcopy(settings) + else: + cls._plugin_settings[plugin] = deepcopy(settings) @classmethod def dict(cls) -> dict: @@ -323,7 +326,11 @@ def set(cls, *, chat_type: ChatType, chat_id: int, setting_group: str, settings: setting_group: Setting group. settings: Settings to be set. """ - cls._chat_settings[chat_type].setdefault(chat_id, {})[setting_group] = deepcopy(settings) + + if setting_group in cls._chat_settings[chat_type].setdefault(chat_id, {}): + cls._chat_settings[chat_type][chat_id][setting_group] |= deepcopy(settings) + else: + cls._chat_settings[chat_type][chat_id][setting_group] = deepcopy(settings) @classmethod def dict(cls) -> dict: @@ -332,6 +339,7 @@ def dict(cls) -> dict: Returns: A deep copy of all chat settings. """ + return deepcopy(cls._chat_settings) @@ -351,41 +359,45 @@ class Replies: } @classmethod - def get(cls, *, reply_group: str) -> dict: - """Get replies of a plugin. + def get_replies(cls, *, group: str) -> dict: + """Get replies of a group. Args: - reply_group: Reply group, usually the name of the plugin. + group: Reply group, usually the name of the plugin. Returns: A deep copy of the replies of the reply group, for preventing modification. """ - return deepcopy(cls._replies.setdefault(reply_group, {})) + return deepcopy(cls._replies.setdefault(group, {})) @classmethod - def get_reply(cls, *, reply_group: str, reply_key: str) -> str: - """Get a reply of a plugin. + def get_reply(cls, *, group: str, key: str) -> str: + """Get a reply of a group. Args: - reply_group: Reply group, usually the name of the plugin. - reply_key: Reply key. + group: Reply group, usually the name of the plugin. + key: Reply key. Returns: The reply. """ - return cls._replies[reply_group][reply_key] + + return cls._replies[group][key] @classmethod - def set(cls, *, reply_group: str, replies: dict) -> None: - """Set replies of a plugin. + def set_replies(cls, *, group: str, replies: dict) -> None: + """Set replies of a group. Args: - reply_group: Reply group, usually the name of the plugin. + group: Reply group, usually the name of the plugin. replies: Replies to be set. """ - cls._replies[reply_group] = deepcopy(replies) + if group in cls._replies: + cls._replies[group] |= deepcopy(replies) + else: + cls._replies[group] = deepcopy(replies) @classmethod def dict(cls) -> dict: diff --git a/app/router/admin.py b/app/router/admin.py index bc905ab..6cc3c39 100644 --- a/app/router/admin.py +++ b/app/router/admin.py @@ -160,7 +160,7 @@ async def get_plugin_replies(plugin: str) -> JSONResponse: if plugin not in status.plugins: raise ResourceNotFoundError(message="Plugin not found") - return JSONResponse(data=replies.get(reply_group=plugin)) + return JSONResponse(data=replies.get_replies(group=plugin)) @router.patch("/plugin/{plugin}/replies", dependencies=[Depends(verify_jwt_token, use_cache=False)]) @@ -170,7 +170,7 @@ async def update_plugin_replies(plugin: str, data: dict[str, str]) -> JSONRespon if plugin not in status.plugins: raise ResourceNotFoundError(message="Plugin not found") - replies.set(reply_group=plugin, replies=data) + replies.set_replies(group=plugin, replies=data) dispatcher.find_plugin(plugin).load() return JSONResponse() @@ -183,7 +183,7 @@ async def reset_plugin_replies(plugin: str) -> JSONResponse: if plugin not in status.plugins: raise ResourceNotFoundError(message="Plugin not found") - replies.set(reply_group=plugin, replies={}) + replies.set_replies(group=plugin, replies={}) dispatcher.find_plugin(plugin).load() return JSONResponse() diff --git a/plugin/__init__.py b/plugin/__init__.py index 4f2607d..b025909 100644 --- a/plugin/__init__.py +++ b/plugin/__init__.py @@ -46,9 +46,9 @@ def load(cls) -> None: {"enabled": True}, deepcopy(cls.default_plugin_settings), plugin_settings.get(plugin=cls.name) )) - replies.set(reply_group=cls.name, replies=deep_update( + replies.set_replies(group=cls.name, replies=deep_update( deepcopy(cls.default_replies), - replies.get(reply_group=cls.name) + replies.get_replies(group=cls.name) )) @classmethod @@ -79,27 +79,27 @@ def get_plugin_setting(cls, *, plugin: str = None, key: str) -> Any: return plugin_settings.get(plugin=plugin or cls.name)[key] @classmethod - def get_reply(cls, *, reply_group: str = None, reply_key: str) -> str: + def get_reply(cls, *, group: str = None, key: str) -> str: """Get plugin reply. This method should only be used to dynamically get plugin reply within a class method. For normal execution, use ``self.replies`` instead. Args: - reply_group: Reply group. - reply_key: Reply key. + group: Reply group. + key: Reply key. Returns: Reply. """ - return replies.get_reply(reply_group=reply_group or cls.name, reply_key=reply_key) + return replies.get_reply(group=group or cls.name, key=key) def __init__(self) -> None: """Initialize DiceRobot plugin.""" self.plugin_settings = plugin_settings.get(plugin=self.name) - self.replies = replies.get(reply_group=self.name) + self.replies = replies.get_replies(group=self.name) @abstractmethod def __call__(self) -> None: diff --git a/plugin/dicerobot/order/daily_60s.py b/plugin/dicerobot/order/daily_60s.py index 647dd61..223f548 100644 --- a/plugin/dicerobot/order/daily_60s.py +++ b/plugin/dicerobot/order/daily_60s.py @@ -12,7 +12,7 @@ class DailySixtySeconds(OrderPlugin): name = "dicerobot.daily_60s" display_name = "每天60秒读懂世界" description = "每天60秒读懂世界,15条简报+1条微语,让你瞬间了解世界正在发生的大事" - version = "1.1.3" + version = "1.1.4" default_plugin_settings = { "api": "https://api.2xb.cn/zaob", @@ -42,7 +42,7 @@ def send_daily_60s(cls) -> None: if result["datatime"] == str(datetime.date.today()): message = [Image(data=Image.Data(file=result["imageUrl"]))] else: - message = cls.get_reply(reply_key="api_error") + message = cls.get_reply(key="api_error") for chat_id in cls.get_plugin_setting(key="subscribers"): cls.send_group_message(chat_id, message) From a2e18f8aeb3f1996ae5909c33f01bf7699698374 Mon Sep 17 00:00:00 2001 From: Drsanwujiang Date: Mon, 4 Nov 2024 17:29:47 +0800 Subject: [PATCH 3/5] Fix log --- app/log.py | 10 +++++----- app/router/admin.py | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/log.py b/app/log.py index 72219fe..52aaebf 100644 --- a/app/log.py +++ b/app/log.py @@ -1,13 +1,13 @@ from typing import Union import sys import os -import datetime +from datetime import date import tarfile from loguru import logger as _logger LOG_DIR = os.path.join(os.getcwd(), "logs") -TEMP_LOG_DIR = "/temp/dicerobot-logs" +TEMP_LOG_DIR = "/tmp/dicerobot-logs" MAX_LENGTH = 1000 MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB @@ -37,9 +37,9 @@ def init_logger() -> None: logger.debug("Logger initialized") -def load_logs(date: datetime.date) -> Union[list[str], None, False]: - date = date.strftime("%Y-%m-%d") - file = f"dicerobot-{date}.log" +def load_logs(date_: date) -> Union[list[str], None, False]: + date_ = date_.strftime("%Y-%m-%d") + file = f"dicerobot-{date_}.log" log_file = os.path.join(LOG_DIR, file) compressed_file = os.path.join(LOG_DIR, f"{file}.tar.gz") temp_log_file = os.path.join(TEMP_LOG_DIR, file) diff --git a/app/router/admin.py b/app/router/admin.py index 6cc3c39..48ae6d7 100644 --- a/app/router/admin.py +++ b/app/router/admin.py @@ -1,7 +1,8 @@ +from typing import Annotated from datetime import date, datetime, timedelta import signal -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, Query from ..log import logger, load_logs from ..auth import verify_password, generate_jwt_token, verify_jwt_token @@ -34,7 +35,7 @@ async def auth(data: AuthRequest) -> JSONResponse: @router.get("/logs", dependencies=[Depends(verify_jwt_token, use_cache=False)]) -async def get_logs(date_: date) -> JSONResponse: +async def get_logs(date_: Annotated[date, Query(alias="date")]) -> JSONResponse: logger.info(f"Admin request received: get logs, date: {date_}") if (logs := load_logs(date_)) is None: From f378a028a0f9523e81e322f8636ab7dc7ad82af8 Mon Sep 17 00:00:00 2001 From: Drsanwujiang Date: Mon, 4 Nov 2024 21:28:22 +0800 Subject: [PATCH 4/5] Fix log --- app/log.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/log.py b/app/log.py index 52aaebf..9b5a955 100644 --- a/app/log.py +++ b/app/log.py @@ -46,6 +46,8 @@ def load_logs(date_: date) -> Union[list[str], None, False]: if os.path.isfile(log_file): return load_log_file(log_file) + elif os.path.isfile(temp_log_file): + return load_log_file(temp_log_file) elif os.path.isfile(compressed_file): with tarfile.open(compressed_file, "r:gz") as tar: tar.extract(file, TEMP_LOG_DIR) From 18da9949fbe0fb51c31b674873b679e2b170fbcc Mon Sep 17 00:00:00 2001 From: Drsanwujiang Date: Mon, 4 Nov 2024 23:06:26 +0800 Subject: [PATCH 5/5] Update to 4.4.1 --- app/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/version.py b/app/version.py index 0894db9..48b4a35 100644 --- a/app/version.py +++ b/app/version.py @@ -1 +1 @@ -VERSION = "4.4.0" +VERSION = "4.4.1" diff --git a/pyproject.toml b/pyproject.toml index f1db7f2..4af3ed5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dicerobot" -version = "4.4.0" +version = "4.4.1" description = "A TRPG assistant bot" authors = ["Drsanwujiang "] license = "MIT"