-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upstream #123
Conversation
Walkthrough此次更改涉及多个文件的修改,主要集中在代码结构优化、错误处理改进和功能增强。 Changes
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 23
🧹 Outside diff range and nitpick comments (47)
modules/wiki/utils/mapping.py (2)
5-16
: CSS 选择器列表结构清晰新增的
infobox_elements
列表包含了多种维基页面上的信息框选择器,结构合理。建议考虑以下优化:
- 按照选择器的特异性(specificity)进行排序
- 为不同类型的信息框选择器添加注释,说明其用途
infobox_elements = [ + # 通用信息框 'div#infoboxborder', '.infobox', '.infoboxtable', + # 游戏特定信息框 '.arcaeabox', '.moe-infobox', + # 皮肤和模板信息框 '.skin-infobox', '.tpl-infobox', + # 其他特殊信息框 '.notaninfobox', '.portable-infobox', '.rotable', '.infotemplatebox', ]
18-18
: 建议添加阻止列表说明注释
generate_screenshot_v2_blocklist
缺少对其用途的说明,建议添加注释以提高代码可维护性。+# 不使用 v2 版本截图功能的网站列表 generate_screenshot_v2_blocklist = ['https://mzh.moegirl.org.cn', 'https://zh.moegirl.org.cn']
modules/wiki/utils/screenshot_image.py (2)
20-20
: 正确使用了导入的选择器列表
infobox_elements
的导入和使用方式正确,通过 copy 操作避免了对原始列表的修改。建议添加类型注解以提高代码的可维护性。-from .mapping import infobox_elements +from .mapping import infobox_elements # type: List[str] async def generate_screenshot_v2(page_link: str, section: str = None, allow_special_page=False, content_mode=False, use_local=True, - element=None) -> Union[List[PILImage], bool]: + element: Optional[List[str]] = None) -> Union[List[PILImage], bool]: elements_ = infobox_elements.copy()Also applies to: 25-27
Line range hint
24-83
: 建议优化错误处理逻辑当前的错误处理逻辑在本地渲染失败时会尝试远程渲染,建议将这个重试逻辑抽取为单独的函数,以提高代码可维护性。
+async def _retry_screenshot_generation(page_link: str, section: str, allow_special_page: bool, + content_mode: bool) -> Union[List[PILImage], bool]: + """在本地渲染失败时尝试远程渲染""" + try: + return await generate_screenshot_v2(page_link, section, allow_special_page, content_mode, + use_local=False) + except Exception: + Logger.error(traceback.format_exc()) + return False async def generate_screenshot_v2(...): try: # ... 现有代码 ... except aiohttp.ClientConnectorError: if use_local: - return await generate_screenshot_v2(page_link, section, allow_special_page, content_mode, - use_local=False) + return await _retry_screenshot_generation(page_link, section, allow_special_page, content_mode) else: return Falsemodules/maimai/libraries/chunithm_apidata.py (1)
25-27
: 缓存目录结构优化将缓存文件统一存放到专门的目录中是个好的改进。建议将目录名 'maimai-record' 定义为常量,以便于维护和复用。
+ # 在文件开头添加常量定义 + MAIMAI_RECORD_DIR = 'maimai-record' - dir = os.path.join(cache_path, 'maimai-record') + dir = os.path.join(cache_path, MAIMAI_RECORD_DIR)🧰 Tools
🪛 Ruff (0.8.2)
25-25:
os
may be undefined, or defined from star imports(F405)
26-26:
os
may be undefined, or defined from star imports(F405)
27-27:
os
may be undefined, or defined from star imports(F405)
modules/maimai/libraries/maimaidx_apidata.py (2)
22-22
: 封面图片处理逻辑优化建议当前的封面图片处理逻辑可以进一步改进:
- 建议添加重试机制以处理网络不稳定情况
- 考虑使用异步批量下载提高性能
+ from core.utils.retry import async_retry - await download(url, status_code=200, path=mai_cover_path, filename=f'{id}.png', attempt=1, logging_err_resp=False) + @async_retry(attempts=3, delay=1) + async def download_cover(url: str, path: str, filename: str): + return await download(url, status_code=200, path=path, filename=filename, logging_err_resp=False) + + await download_cover(url, mai_cover_path, f'{id}.png')Also applies to: 27-27, 31-32
59-63
: 优化封面图片回退逻辑当前的封面图片回退逻辑可以更加优雅:
- 建议使用常量定义默认封面
- 可以添加日志记录找不到封面的情况
+ DEFAULT_COVER = '0.png' - cover_path = os.path.join(mai_cover_path, '0.png') + cover_path = os.path.join(mai_cover_path, DEFAULT_COVER) + Logger.debug(f'Using default cover for music {music.id}')🧰 Tools
🪛 Ruff (0.8.2)
59-59:
mai_cover_path
may be undefined, or defined from star imports(F405)
63-63:
mai_cover_path
may be undefined, or defined from star imports(F405)
modules/maimai/libraries/maimaidx_best50.py (1)
Line range hint
1-300
: 建议优化代码结构和组织方式代码结构可以通过以下几点改进:
- 提取常量配置:
- 图片尺寸(如 860x1300, 150x100)
- 颜色值
- 字体大小
- 拆分
_drawBestList
方法,当前方法过长且职责过多- 添加类型注解以提高代码可读性
- 考虑使用数据类来替代字典传递数据
建议添加配置类:
from dataclasses import dataclass from typing import Tuple, List @dataclass class ImageConfig: WIDTH: int = 860 HEIGHT: int = 1300 ITEM_WIDTH: int = 150 ITEM_HEIGHT: int = 100 BG_COLOR: Tuple[int, ...] = (211, 211, 211, 255) DIFFICULTY_COLORS: List[Tuple[int, ...]] = [ (69, 193, 36), (255, 186, 1), (255, 90, 102), (134, 49, 200), (217, 197, 233) ]建议将绘制逻辑拆分为多个方法:
class DrawBest: def _draw_chart_title(self, draw: ImageDraw.Draw, title: str, x: int, y: int) -> None: """绘制歌曲标题""" pass def _draw_chart_stats(self, draw: ImageDraw.Draw, chart: ChartInfo, x: int, y: int) -> None: """绘制成绩数据""" pass def _draw_chart_item(self, chart: ChartInfo, position: Tuple[int, int]) -> None: """绘制单个歌曲项目""" passcore/types/module/component_meta.py (2)
15-16
: 建议为ModuleMeta
类添加文档字符串当前的
ModuleMeta
类为空类,缺少文档字符串。为其添加说明可以提高代码的可读性和可维护性。
22-22
: 检查help_doc
属性的转换器
help_doc
属性使用了field(default=[], converter=convert2lst)
,请确保convert2lst
函数能够正确地将输入转换为列表,防止出现意外的类型转换错误。core/utils/cooldown.py (1)
25-31
: 为_get_cd_dict
方法添加文档字符串为了增加代码的可读性和维护性,建议为
_get_cd_dict
方法添加文档字符串,说明其功能和返回值。bot.py (4)
10-10
:loggerFallback
的命名风格问题在第 10 行,使用了
loggerFallback
作为日志记录器的名称。为了保持命名风格的一致性,建议将其重命名为logger_fallback
。
58-69
: 将数据库更新逻辑封装为独立函数在第 58-69 行,数据库更新逻辑直接写在
init_bot
函数中。为了提高代码的可维护性,建议将数据库更新部分封装为独立的函数或方法。
82-85
: 简化嵌套的if
语句根据静态分析工具的提示,第 82-85 行的嵌套
if
语句可以合并为单个条件判断,从而简化代码结构。应用以下修改:
- if 'enable' in CFGManager.values[t][t]: - if not CFGManager.values[t][t]['enable']: + if CFGManager.values[t][t].get('enable') is False:🧰 Tools
🪛 Ruff (0.8.2)
82-84: Use a single
if
statement instead of nestedif
statements(SIM102)
83-84: Use a single
if
statement instead of nestedif
statements(SIM102)
124-134
: 改进错误日志的信息在
restart_process
函数中,当重启次数达到 3 次时,仅记录了简单的错误信息。建议在日志中包含失败原因和堆栈信息,方便调试。modules/wikilog/__init__.py (1)
265-266
: 优化异常处理,提供更具体的反馈在第265-266行的异常处理代码中,直接捕获了所有
Exception
,并在发生异常时给用户发送通用的失败消息。建议捕获更具体的异常类型,并根据不同的异常情况给予用户更详细的反馈,有助于用户理解问题所在。core/builtins/message/__init__.py (1)
96-98
: 简化条件判断在第96-98行,嵌套的
if
语句可以合并为单个条件判断,以提高代码的简洁性和可读性。建议将代码修改为:
if get_['active'] and (datetime.now().timestamp() - get_['ts'] > get_.get('timeout', 3600)): get_['active'] = False get_['flag'].set()🧰 Tools
🪛 Ruff (0.8.2)
96-98: Use a single
if
statement instead of nestedif
statements(SIM102)
core/parser/message.py (1)
492-496
: 优化错误信息的组装方式以提高可读性在组装
errmsg
时,代码的嵌套层次较深,可能影响可读性。建议简化代码结构,减少不必要的嵌套,提高代码的清晰度。请参考以下修改:
- if Config('bug_report_url', bug_report_url_default, cfg_type=str): - errmsg += '\n' + msg.locale.t('error.prompt.address', - url=Url(Config('bug_report_url', - bug_report_url_default, - cfg_type=str), - use_mm=False)) + bug_report_url = Config('bug_report_url', bug_report_url_default, cfg_type=str) + if bug_report_url: + url = Url(bug_report_url, use_mm=False) + errmsg += '\n' + msg.locale.t('error.prompt.address', url=url)core/types/module/utils.py (1)
4-9
: 函数convert2lst
的参数类型注解可扩展为支持更多类型当前
convert2lst
函数的参数类型注解为Union[str, list, tuple]
,若未来需要支持更多的可迭代类型,建议更改类型注解为更通用的类型,如Sequence
或Iterable
。请参考以下修改:
- from typing import Union + from typing import Union, Iterable - def convert2lst(elements: Union[str, list, tuple]) -> list: + def convert2lst(elements: Union[str, Iterable]) -> list:modules/cytoid/utils.py (1)
8-8
: 建议统一字符串格式化方式在第 8 行中,将字符串拼接方式改为了 f-string,这提高了代码的可读性。建议检查整个模块,确保字符串格式化方式的一致性,使代码风格统一。
core/utils/text.py (3)
7-9
: 改进文档字符串格式文档字符串的添加提高了代码可读性,但建议遵循更规范的格式。
建议按照以下格式修改:
def isfloat(num_str: Any) -> bool: - ''' - 检查字符串是否符合float。 - ''' + """检查字符串是否符合float格式。 + + Args: + num_str: 要检查的输入值 + + Returns: + bool: 如果可以转换为float则返回True,否则返回False + """对
isint
函数也进行类似的改进。Also applies to: 18-20
Line range hint
1-1
: 移除未使用的导入由于
random_string
函数已被移除,random
模块的导入现在是多余的。建议删除未使用的导入:
-import random from datetime import timedelta from typing import Any
Line range hint
6-16
: 改进类型提示和参数验证
isfloat
和isint
函数的类型提示可以更具体,并添加参数验证。建议进行以下改进:
-def isfloat(num_str: Any) -> bool: +def isfloat(num_str: Union[str, int, float]) -> bool: """检查字符串是否符合float格式。""" + if num_str is None: + return False try: float(num_str) return True except ValueError: return False对
isint
函数也进行类似的改进。Also applies to: 17-25
core/joke.py (1)
15-20
: 建议优化条件判断的可读性当前实现逻辑清晰,但可以通过提取变量名使代码更具表达性。
建议如下修改:
def joke(text: str) -> str: - if check_apr_fools(): + should_apply_joke = check_apr_fools() + if should_apply_joke: # 这里可能会增加使用不同玩笑方法的区分,但现在不太想做XD return shuffle_joke(text) else: return textcore/types/module/component_matches.py (2)
5-6
: 需要优化导入语句
field
被导入但未使用,建议移除。-from attrs import define, field +from attrs import define🧰 Tools
🪛 Ruff (0.8.2)
5-5:
attrs.field
imported but unusedRemove unused import:
attrs.field
(F401)
Line range hint
22-71
: 类继承结构优化得当,但建议统一类型定义各个子类重复定义
set
属性是不必要的,可以使用泛型来优化。建议如下修改:
from typing import TypeVar, Generic, List T = TypeVar('T', CommandMeta, RegexMeta, ScheduleMeta, HookMeta) @define class BaseMatches(Generic[T]): set: List[T] = field(factory=list) def add(self, meta: T) -> List[T]: self.set.append(meta) return self.set @define class CommandMatches(BaseMatches[CommandMeta]): pass # 其他类似...🧰 Tools
🪛 Ruff (0.8.2)
66-66:
ScheduleMeta
may be undefined, or defined from star imports(F405)
71-71:
HookMeta
may be undefined, or defined from star imports(F405)
core/utils/web_render.py (3)
2-2
: 移除未使用的导入
Union
类型未在代码中使用,建议将其从导入语句中移除。-from typing import Tuple, Optional, Union +from typing import Tuple, Optional🧰 Tools
🪛 Ruff (0.8.2)
2-2:
typing.Union
imported but unusedRemove unused import:
typing.Union
(F401)
13-20
: 完善函数文档字符串函数文档缺少新增参数
_ignore_status
的说明。建议更新文档以包含所有参数的完整描述。'''根据请求方法生成 WebRender URL。 :param method: API 方法。 :param url: 若 method 为 source,则指定请求的 URL。 :param use_local: 是否使用本地 WebRender。 + :param _ignore_status: 是否忽略渲染状态检查。 :returns: 生成的 WebRender URL。 '''
24-24
: 优化条件表达式可以使用更简洁的条件表达式来提高代码可读性。
- url = '' if not url else url + url = url if url else ''🧰 Tools
🪛 Ruff (0.8.2)
24-24: Use
url if url else ''
instead of'' if not url else url
Replace with
url if url else ''
(SIM212)
modules/cytoid/profile.py (1)
7-7
: 添加类型注解建议为
username
参数添加类型注解,以提高代码的可维护性。-async def cytoid_profile(msg: Bot.MessageSession, username): +async def cytoid_profile(msg: Bot.MessageSession, username: Optional[str] = None):modules/wikilog/locales/zh_cn.json (1)
42-43
: 保持消息格式一致性建议统一消息格式,将 "Keep alive" 翻译为中文,以保持与其他消息的一致性。
- "wikilog.message.keepalive.logged.as": "[Keep alive] 以 ${name} 的身份登录:${wiki}", - "wikilog.message.keepalive.failed": "[Keep alive] 登录状态检查失败:${link}" + "wikilog.message.keepalive.logged.as": "[保持连接] 以 ${name} 的身份登录:${wiki}", + "wikilog.message.keepalive.failed": "[保持连接] 登录状态检查失败:${link}"modules/wiki/search.py (2)
18-18
: 建议完善函数文档函数包含了复杂的 interwiki 链接处理逻辑,建议添加详细的函数文档说明参数用途和处理流程。
建议添加如下文档:
async def search_pages(msg: Bot.MessageSession, title: Union[str, list, tuple], use_prefix: bool = True): + """ + 搜索页面并处理 interwiki 链接 + + Args: + msg: 消息会话对象 + title: 要搜索的页面标题,可以是字符串或字符串列表 + use_prefix: 是否使用页面前缀,默认为 True + + Returns: + None + """
Line range hint
18-73
: 建议增加错误处理当前代码缺少对网络请求失败的处理机制。
建议在调用
WikiLib.search_page
时添加 try-except 块:tasks = [] for rd in ready_for_query_pages: - tasks.append(asyncio.ensure_future( - WikiLib(q, headers).search_page(rd))) + try: + tasks.append(asyncio.ensure_future( + WikiLib(q, headers).search_page(rd))) + except Exception as e: + Logger.error(f"搜索页面时发生错误: {e}") + continuecore/utils/random.py (2)
12-14
: 建议完善类文档当前文档简单说明了类的功能,但缺少对性能影响和安全性的说明。
建议扩展文档内容:
""" - 机器人内置的随机数生成器。在配置文件中将`use_secrets_random`设为`true`时使用`secret`库,否则默认使用`random`库。 + 机器人内置的随机数生成器。 + + 在配置文件中将`use_secrets_random`设为`true`时使用`secret`库,否则默认使用`random`库。 + + 性能说明: + - secrets 库提供更高的安全性,但性能较低 + - random 库性能更好,但不适用于安全敏感场景 + + 使用建议: + - 对于普通随机化场景(如随机表情),使用默认的 random 库 + - 对于安全敏感场景(如生成令牌),建议启用 secrets 库 """
Line range hint
17-24
: 建议优化条件判断结构多个方法中重复出现
if cls.use_secrets
判断,可以考虑使用装饰器模式优化。建议添加装饰器来处理条件判断:
def use_secure_random(func): def wrapper(cls, *args, **kwargs): if cls.use_secrets: # 调用 secrets 版本的实现 return func(cls, *args, **kwargs) else: # 调用 random 版本的实现 return getattr(random, func.__name__)(*args, **kwargs) return wrapper class Random: @classmethod @use_secure_random def random(cls) -> float: return secrets.randbelow(INF) / INF @classmethod @use_secure_random def randint(cls, a: int, b: int) -> int: return secrets.randbelow(b - a + 1) + aAlso applies to: 27-34, 36-43
core/utils/image_table.py (2)
21-26
: 文档字符串格式需要改进建议使用更规范的文档字符串格式,包括返回值说明和类的整体描述。
建议修改为:
- ''' - 图片表格。 - :param data: 表格内容,表格行数需与表格标头的数量相符。 - :param headers: 表格表头。 - ''' + '''图片表格类,用于生成和管理表格数据。 + + Args: + data: 表格内容,表格行数需与表格标头的数量相符 + headers: 表格表头 + + Attributes: + data: 表格内容 + headers: 表格表头 + '''
Line range hint
111-116
: 建议增强错误处理机制当前的错误处理过于简单,建议添加更详细的错误信息和重试机制。
建议在 try-except 块中添加:
- 具体的错误类型处理
- 重试机制
- 详细的错误日志
MAX_RETRIES = 3 retry_count = 0 while retry_count < MAX_RETRIES: try: # 现有的图片处理代码 break except (IOError, ValueError) as e: retry_count += 1 Logger.warning(f"处理图片时发生错误 (尝试 {retry_count}/{MAX_RETRIES}): {str(e)}") if retry_count == MAX_RETRIES: Logger.error("图片处理失败,已达到最大重试次数") raisecore/utils/game.py (2)
8-8
: 建议优化状态管理机制当前使用全局变量
_ps_lst
管理状态可能会导致线程安全问题。建议考虑使用更安全的状态管理方式。建议考虑:
- 使用 Redis 等外部存储管理状态
- 实现状态管理类来封装状态操作
- 添加线程安全机制
示例实现:
from threading import Lock class GameStateManager: def __init__(self): self._states = defaultdict(lambda: defaultdict(dict)) self._lock = Lock() def get_state(self, target_id, sender_id, game): with self._lock: return self._states[target_id][sender_id].get(game)Also applies to: 76-76
Line range hint
93-104
: 建议改进过期检查逻辑当前的过期检查逻辑可以更加灵活和可配置。
建议修改为:
+ @property + def _is_expired(self) -> bool: + """检查游戏状态是否已过期""" + ts = self.get('_timestamp') or 0.0 + return datetime.now().timestamp() - ts >= GAME_EXPIRED + def check(self) -> bool: ''' 检查游戏事件状态,若超过时间则自动关闭。 ''' if self.target_id not in _ps_lst: return False - target_dict = _ps_lst[self.target_id] - if self.all: - status = target_dict.get(self.game, {}).get('_status', False) - ts = target_dict.get(self.game, {}).get('_timestamp', 0.0) - else: - sender_dict = target_dict.get(self.sender_id, {}) - status = sender_dict.get(self.game, {}).get('_status', False) - ts = sender_dict.get(self.game, {}).get('_timestamp', 0.0) - if datetime.now().timestamp() - ts >= GAME_EXPIRED: + status = self.get('_status') or False + if self._is_expired: self.disable(_auto=True) return statuscore/builtins/__init__.py (2)
41-44
: 建议优化参数传递方式当前的参数传递方式较为冗长,可以使用字典解包来简化代码。
建议修改为:
- await target.send_direct_message(message_chain=msg, - disable_secret_check=disable_secret_check, - enable_parse_message=enable_parse_message, - enable_split_image=enable_split_image) + params = { + 'message_chain': msg, + 'disable_secret_check': disable_secret_check, + 'enable_parse_message': enable_parse_message, + 'enable_split_image': enable_split_image + } + await target.send_direct_message(**params)
Line range hint
108-116
: 建议增强错误处理在
FetchedSession
初始化时,建议添加参数验证和更详细的错误处理。建议添加:
def __init__(self, target_from: str, target_id: Union[int, str], sender_from: Optional[str] = None, sender_id: Optional[Union[int, str]] = None): if not target_from: raise ValueError("target_from 不能为空") if not target_id: raise ValueError("target_id 不能为空") sender_from = sender_from or target_from sender_id = sender_id or target_id try: self.target = MsgInfo(...) except Exception as e: Logger.error(f"初始化 MsgInfo 失败: {str(e)}") raise🧰 Tools
🪛 Ruff (0.8.2)
24-24:
ExecutionLockList
may be undefined, or defined from star imports(F405)
26-26:
Temp
may be undefined, or defined from star imports(F405)
modules/wikilog/dbutils.py (2)
126-126
: 需要重构的代码注释应该更具体注释"will rewrite it in the future"过于模糊,建议添加具体的重构原因和计划。
建议修改为:
-def set_keep_alive(self, apilink: str, keep_alive: bool): # oh no it smells shit, will rewrite it in the future +def set_keep_alive(self, apilink: str, keep_alive: bool): # TODO: 重构计划 - 将 keep_alive 相关逻辑抽象到独立的类中,提高代码复用性
140-141
: 建议优化空值检查逻辑当前的检查方式需要两次字典访问,可以使用 dict.get() 方法优化。
建议修改为:
- if apilink in infos and 'keep_alive' in infos[apilink]: - return infos[apilink]['keep_alive'] + return infos.get(apilink, {}).get('keep_alive', False)core/utils/i18n.py (1)
118-121
: 建议完善类文档说明当前的文档说明过于简单,建议添加更详细的信息。
建议修改为:
- """ - 创建一个本地化对象。 - """ + """ + 创建一个本地化对象,用于处理多语言翻译和本地化。 + + 属性: + locale (str): 当前使用的语言代码 + fallback_lng (List[str]): 备选语言列表,当主要语言无法找到翻译时使用 + + 示例: + >>> locale = Locale('zh_cn') + >>> locale.t('message.hello') + '你好' + """core/component.py (1)
187-202
: 代码逻辑正确,但建议改进参数对齐参数对齐存在不一致,建议统一使用相同的缩进级别以提高可读性。
module = Module.assign(alias=alias, - bind_prefix=bind_prefix, - desc=desc, - recommend_modules=recommend_modules, - developers=developers, - base=base, - doc=doc, - hidden=hidden, - load=load, - rss=rss, - required_admin=required_admin, - required_superuser=required_superuser, - required_base_superuser=required_base_superuser, - available_for=available_for, - exclude_from=exclude_from, - support_languages=support_languages) + bind_prefix=bind_prefix, + desc=desc, + recommend_modules=recommend_modules, + developers=developers, + base=base, + doc=doc, + hidden=hidden, + load=load, + rss=rss, + required_admin=required_admin, + required_superuser=required_superuser, + required_base_superuser=required_base_superuser, + available_for=available_for, + exclude_from=exclude_from, + support_languages=support_languages)core/config/__init__.py (1)
352-352
: 建议改进超时处理机制当前的超时处理直接抛出异常,建议添加重试机制或更优雅的错误恢复方式。
@classmethod def wait(cls, _lock): count = 0 + max_retries = 3 + retry_count = 0 while _lock: count += 1 sleep(1) if count > 5: + if retry_count < max_retries: + count = 0 + retry_count += 1 + continue ConfigOperationError('Operation timeout.')modules/wiki/wiki.py (1)
158-164
: 建议优化模板和 MediaWiki 页面的处理逻辑当前的实现方式直接在字符串前添加前缀,建议将这个逻辑抽象为独立的函数以提高可维护性。
+def get_page_title(title: str, is_template: bool = False, is_mediawiki: bool = False) -> str: + if is_template: + return f'Template:{title}' + if is_mediawiki: + return f'MediaWiki:{title}' + return title -if template: - rd = f'Template:{rd}' -if mediawiki: - rd = f'MediaWiki:{rd}' +rd = get_page_title(rd, template, mediawiki)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
poetry.lock
is excluded by!**/*.lock
📒 Files selected for processing (47)
.gitignore
(0 hunks)bot.py
(4 hunks)bots/qqbot/message.py
(3 hunks)core/builtins/__init__.py
(2 hunks)core/builtins/message/__init__.py
(15 hunks)core/builtins/message/chain.py
(3 hunks)core/builtins/message/elements.py
(13 hunks)core/component.py
(1 hunks)core/config/__init__.py
(3 hunks)core/constants/info.py
(1 hunks)core/joke.py
(1 hunks)core/parser/message.py
(1 hunks)core/types/message/__init__.py
(1 hunks)core/types/module/__init__.py
(1 hunks)core/types/module/component_matches.py
(3 hunks)core/types/module/component_meta.py
(1 hunks)core/types/module/utils.py
(1 hunks)core/utils/cooldown.py
(1 hunks)core/utils/game.py
(6 hunks)core/utils/http.py
(3 hunks)core/utils/i18n.py
(1 hunks)core/utils/image_table.py
(4 hunks)core/utils/random.py
(1 hunks)core/utils/text.py
(3 hunks)core/utils/web_render.py
(3 hunks)modules/cytoid/profile.py
(1 hunks)modules/cytoid/rating.py
(3 hunks)modules/cytoid/utils.py
(1 hunks)modules/maimai/libraries/chunithm_apidata.py
(1 hunks)modules/maimai/libraries/maimaidx_apidata.py
(6 hunks)modules/maimai/libraries/maimaidx_best50.py
(3 hunks)modules/maimai/libraries/maimaidx_music.py
(1 hunks)modules/meme/moegirl.py
(2 hunks)modules/wiki/audit.py
(1 hunks)modules/wiki/inline.py
(1 hunks)modules/wiki/search.py
(1 hunks)modules/wiki/utils/mapping.py
(1 hunks)modules/wiki/utils/screenshot_image.py
(1 hunks)modules/wiki/utils/wikilib.py
(5 hunks)modules/wiki/wiki.py
(5 hunks)modules/wikilog/__init__.py
(3 hunks)modules/wikilog/dbutils.py
(2 hunks)modules/wikilog/locales/zh_cn.json
(1 hunks)modules/wordle/__init__.py
(1 hunks)pyproject.toml
(2 hunks)requirements.txt
(3 hunks)schedulers/wiki_bot.py
(1 hunks)
💤 Files with no reviewable changes (1)
- .gitignore
✅ Files skipped from review due to trivial changes (1)
- core/constants/info.py
🧰 Additional context used
🪛 Ruff (0.8.2)
modules/maimai/libraries/maimaidx_apidata.py
25-25: mai_cover_path
may be undefined, or defined from star imports
(F405)
27-27: mai_cover_path
may be undefined, or defined from star imports
(F405)
31-31: mai_cover_path
may be undefined, or defined from star imports
(F405)
35-35: Config
may be undefined, or defined from star imports
(F405)
59-59: mai_cover_path
may be undefined, or defined from star imports
(F405)
63-63: mai_cover_path
may be undefined, or defined from star imports
(F405)
modules/maimai/libraries/chunithm_apidata.py
25-25: os
may be undefined, or defined from star imports
(F405)
26-26: os
may be undefined, or defined from star imports
(F405)
27-27: os
may be undefined, or defined from star imports
(F405)
bot.py
82-84: Use a single if
statement instead of nested if
statements
(SIM102)
83-84: Use a single if
statement instead of nested if
statements
(SIM102)
modules/cytoid/profile.py
11-11: Undefined name CytoidBindInfoManager
(F821)
core/types/module/component_matches.py
5-5: attrs.field
imported but unused
Remove unused import: attrs.field
(F401)
11-11: ModuleMeta
may be undefined, or defined from star imports
(F405)
24-24: CommandMeta
may be undefined, or defined from star imports
(F405)
45-45: RegexMeta
may be undefined, or defined from star imports
(F405)
66-66: ScheduleMeta
may be undefined, or defined from star imports
(F405)
71-71: HookMeta
may be undefined, or defined from star imports
(F405)
core/builtins/__init__.py
26-26: Temp
may be undefined, or defined from star imports
(F405)
modules/wiki/wiki.py
267-267: Function definition does not bind loop variable forum_data
(B023)
268-268: Function definition does not bind loop variable forum_data
(B023)
268-268: Function definition does not bind loop variable r
(B023)
core/utils/web_render.py
2-2: typing.Union
imported but unused
Remove unused import: typing.Union
(F401)
24-24: Use url if url else ''
instead of '' if not url else url
Replace with url if url else ''
(SIM212)
bots/qqbot/message.py
27-27: target_guild_prefix
may be undefined, or defined from star imports
(F405)
30-30: target_group_prefix
may be undefined, or defined from star imports
(F405)
core/types/module/__init__.py
43-43: CommandMatches
may be undefined, or defined from star imports
(F405)
43-43: CommandMatches
may be undefined, or defined from star imports
(F405)
44-44: RegexMatches
may be undefined, or defined from star imports
(F405)
44-44: RegexMatches
may be undefined, or defined from star imports
(F405)
45-45: ScheduleMatches
may be undefined, or defined from star imports
(F405)
45-45: ScheduleMatches
may be undefined, or defined from star imports
(F405)
46-46: HookMatches
may be undefined, or defined from star imports
(F405)
46-46: HookMatches
may be undefined, or defined from star imports
(F405)
core/builtins/message/__init__.py
96-98: Use a single if
statement instead of nested if
statements
(SIM102)
169-169: MessageChain
may be undefined, or defined from star imports
(F405)
208-208: MessageChain
may be undefined, or defined from star imports
(F405)
🔇 Additional comments (44)
modules/wiki/utils/screenshot_image.py (1)
25-27
: 验证元素列表的合并逻辑
当前的元素列表合并逻辑可能需要验证是否所有调用处都正确传递了兼容的元素格式。
✅ Verification successful
Let me gather more information about the element parameter usage and list handling.
元素列表合并逻辑验证完成,实现正确
根据代码分析,元素列表的合并逻辑是安全的:
infobox_elements
在 mapping.py 中定义为固定的 CSS 选择器列表generate_screenshot_v2
函数中通过copy()
创建新列表,避免修改原始列表- 仅在传入参数
element
为列表类型时才进行合并操作 - 实际调用中(如 weekly/init.py)传入的确实是列表格式的 CSS 选择器
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 描述:检查 generate_screenshot_v2 函数的调用,验证 element 参数的使用方式
# 搜索函数调用
rg -A 2 "generate_screenshot_v2\(" --type py
# 搜索可能的元素列表定义
ast-grep --pattern 'element = $_'
Length of output: 2697
Script:
#!/bin/bash
# 检查 element 参数的定义和使用
rg -A 5 "infobox_elements" --type py
# 检查 generate_screenshot_v2 函数的完整实现
ast-grep --pattern 'async def generate_screenshot_v2($_) {
$$$
}'
# 检查列表操作相关的代码
rg "elements_" --type py -A 2
Length of output: 4536
modules/maimai/libraries/maimaidx_music.py (1)
13-13
: 类型注解改进
添加 Union[int, str] 类型提示增强了代码的类型安全性,使函数的参数要求更加明确。
core/types/module/component_meta.py (1)
19-31
: 确认 CommandMeta
类属性的类型和默认值
在 CommandMeta
类中,属性如 function
、help_doc
、options_desc
等已定义。请确保所有属性的类型注解和默认值符合预期,避免在使用过程中出现类型错误。
core/utils/cooldown.py (1)
40-59
: 验证 check
方法的逻辑正确性
在 check
方法中,使用了 _cd_lst
的新结构。由于 _cd_lst
是 defaultdict
,可能永远不会出现 self.key
不在 _cd_lst
的情况。请验证逻辑是否符合预期,确保方法返回正确的冷却时间。
core/types/module/__init__.py (1)
10-10
: 🛠️ Refactor suggestion
避免使用通配符导入
在第 10 行,使用了 from .component_matches import *
。通配符导入可能导致命名空间污染,降低代码的可读性。建议明确导入所需的类。
应用以下修改:
- from .component_matches import *
+ from .component_matches import CommandMatches, RegexMatches, ScheduleMatches, HookMatches
Likely invalid or redundant comment.
bot.py (1)
88-99
: 确保子进程在终止前正确关闭
在 multiprocess_run_until_complete
函数中,第 88-99 行可能存在子进程资源未正确释放的问题。建议在调用 p.terminate()
和 p.join()
后,再调用 p.close()
,以确保子进程资源完全释放。
modules/wikilog/__init__.py (2)
5-5
: 导入 I18NContext
支持国际化
在第5行加入了对 I18NContext
的导入,为后续代码中的国际化消息处理提供了支持。
247-266
: 注意 walrus
运算符的兼容性
第261行使用了 walrus
运算符 :=
,该特性在 Python 3.8 及以上版本才支持。请确保运行环境满足版本要求,或者避免使用该语法以提高兼容性。
modules/wiki/inline.py (1)
204-204
: 删除未使用的参数,提高代码简洁性
在第204行的 _callback
函数中,参数 forum_data
和 get_page
已被移除。这是一个很好的改进,使函数签名更加清晰,避免了未使用参数的干扰。
bots/qqbot/message.py (2)
25-34
: 简化异常处理逻辑
在第25-34行的 delete
方法中,将异常捕获的范围扩大到了整个删除过程。这是一个良好的实践,可以捕获在群组和频道消息删除过程中可能发生的所有异常,并统一进行日志记录。
🧰 Tools
🪛 Ruff (0.8.2)
27-27: target_guild_prefix
may be undefined, or defined from star imports
(F405)
30-30: target_group_prefix
may be undefined, or defined from star imports
(F405)
232-233
: 确保在非频道或私信的情况下返回适当的值
在第232-233行,增加了在目标不是频道或私信时,delete
方法显式返回 False
。这提高了代码的可读性和可维护性,确保方法的返回值始终明确。
core/builtins/message/__init__.py (10)
1-2
: 确保兼容未来特性
在第1-2行,添加了 from __future__ import annotations
。这使得类型注解可以使用前向引用,对提升代码的可读性和未来兼容性非常有帮助。
21-23
: 添加类的文档字符串
在第21-23行,为 ExecutionLockList
类添加了文档字符串。这有助于其他开发者理解类的用途和功能,提升代码的可维护性。
48-50
: 添加类的文档字符串
在第48-50行,为 MessageTaskManager
类添加了文档字符串。这有助于明确类的作用,方便后续的维护和协作。
313-314
: 改进类型注解,提高参数灵活性
在第313行,将参数 timeout
的类型从 int
修改为 Optional[float]
,允许传入更灵活的超时时间值。这提升了方法的适用性。
356-357
: 改进类型注解,提高参数灵活性
在第356-357行,将 timeout
的类型从 int
修改为 Optional[float]
,使方法支持更灵活的超时时间设置,增强了代码的健壮性。
395-397
: 添加缺失的参数类型注解
在第395-397行,为 wait_reply
方法的参数添加了类型注解,这有助于提高代码的可读性和可维护性。
436-437
: 改进类型注解,提高参数灵活性
在第436行,将 timeout
的类型从 int
修改为 Optional[float]
,允许更灵活地设置超时时间。这提高了方法的适用性。
555-557
: 添加类的文档字符串
在第555-557行,为 FetchedSession
类添加了文档字符串,有助于明确类的功能,方便他人理解和维护。
598-600
: 添加类的文档字符串
在第598-600行,为 FetchTarget
类添加了文档字符串,提升了代码的可读性和可维护性。
96-98
: 避免重复导入
根据静态分析提示,在第96-98行使用了变量 get_
,请确保在作用域内未重复导入或定义,避免可能的变量覆盖或冲突。
🧰 Tools
🪛 Ruff (0.8.2)
96-98: Use a single if
statement instead of nested if
statements
(SIM102)
core/parser/message.py (1)
Line range hint 8-10
: 修改 temp_ban_check
函数的参数以提高代码一致性
temp_ban_check
函数新增了 command
参数,但在函数内部并未使用该参数。建议检查参数的必要性,确保函数签名与实际使用一致。
请运行以下脚本以验证 temp_ban_check
函数中的 command
参数是否被使用:
schedulers/wiki_bot.py (1)
15-15
: 验证 keepalive 钩子的实现和错误处理
新增的 keepalive 钩子调用需要确保具备适当的错误处理机制,以防止因连接问题影响整个登录流程。
运行以下脚本以验证 keepalive 钩子的实现:
✅ Verification successful
keepalive 钩子已正确实现并具备错误处理机制
从代码分析可以看出:
- keepalive 钩子在
modules/wikilog/__init__.py
中有完整实现,包含了适当的错误处理 - 错误处理使用了 try-except 机制,并通过 Logger 记录错误
- 钩子会向用户发送登录状态反馈,包括成功和失败的情况
- 在
wiki_bot.py
中的调用位置合理,紧跟在登录操作之后
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 描述:检查 wikilog.keepalive 钩子的实现和错误处理
# 搜索 keepalive 钩子的实现
ast-grep --pattern 'async def keepalive($$$)'
# 搜索相关的错误处理代码
rg -A 5 'try:.*wikilog\.keepalive'
Length of output: 84
Script:
#!/bin/bash
# 搜索 wikilog.keepalive 相关的代码实现
rg -g '!{dist,build}/*' -l "wikilog.keepalive"
# 搜索包含 keepalive 的 Python 文件
fd -e py -x grep -l "keepalive"
# 搜索 JobQueue 的 trigger_hook_all 方法实现
ast-grep --pattern 'async def trigger_hook_all($$$)'
# 搜索 try-except 相关的错误处理
rg "try:.*trigger_hook_all.*wikilog"
Length of output: 250
Script:
#!/bin/bash
# 检查 wikilog 模块中的 keepalive 相关实现
cat modules/wikilog/__init__.py
# 检查 JobQueue 的错误处理机制
rg -A 5 "class JobQueue"
rg -A 5 "trigger_hook_all"
# 检查 wiki_bot.py 中的错误处理
cat schedulers/wiki_bot.py
Length of output: 24599
core/types/message/__init__.py (1)
10-11
:
注意:这是一个破坏性更改
将 target_id
和 sender_id
的类型从 Union[int, str]
更改为 str
是一个破坏性更改,可能会影响现有代码。
运行以下脚本以检查可能受影响的代码:
建议:
- 考虑添加类型转换逻辑以保持向后兼容
- 更新相关文档以说明此更改
- 确保所有调用方都进行了相应的更新
✅ Verification successful
target_id 和 sender_id 的类型更改是安全的
根据代码库分析,所有的 target_id
和 sender_id
都是以字符串形式使用的,主要用于以下模式:
- 格式为
{prefix}|{id}
的字符串标识符 - 通过正则表达式进行匹配和提取
- 作为字典键值使用
没有发现任何将整数直接赋值给这些字段的情况,所有的 ID 都是以字符串形式构造和处理的。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 描述:检查使用 MsgInfo.target_id 和 sender_id 的代码
# 搜索可能受影响的代码
rg -A 3 'target_id.*=.*\d+|sender_id.*=.*\d+'
# 搜索类型注解
ast-grep --pattern 'MsgInfo($$$)'
Length of output: 17375
core/joke.py (1)
8-12
: 代码结构优化得当!
将愚人节检查逻辑抽离成独立函数是个很好的改进,提高了代码的可重用性和可维护性。
pyproject.toml (2)
Line range hint 55-65
: 建议为依赖项添加版本锁定
直接使用 Git 仓库作为依赖源可能导致不可预期的更新。建议指定具体的提交哈希或标签。
建议修改为:
-langconv = {git = "https://github.com/OasisAkari/langconv.py.git"}
+langconv = {git = "https://github.com/OasisAkari/langconv.py.git", rev = "specific-commit-hash"}
运行以下脚本检查最新的稳定版本:
✅ Verification successful
建议将 langconv 依赖锁定到特定提交
建议修改为:
-langconv = {git = "https://github.com/OasisAkari/langconv.py.git"}
+langconv = {git = "https://github.com/OasisAkari/langconv.py.git", rev = "975ee0896096b63148f0930db762607a5a2113df"}
该仓库没有发布版本标签,但我们可以锁定到最新的稳定提交以确保依赖的一致性和可重现性。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查 langconv 仓库的最新发布版本和提交
gh api repos/OasisAkari/langconv.py/releases/latest --jq '.tag_name'
gh api repos/OasisAkari/langconv.py/commits/main --jq '.sha'
Length of output: 467
Script:
#!/bin/bash
# Check if the repository exists and get its default branch
gh api repos/OasisAkari/langconv.py --jq '.default_branch'
# List all branches
gh api repos/OasisAkari/langconv.py/branches --jq '.[].name'
# Get the latest commit from master branch (alternative to main)
gh api repos/OasisAkari/langconv.py/commits/master --jq '.sha'
Length of output: 239
Line range hint 65-74
: 验证依赖兼容性
新添加的依赖项 botpy
和更新的版本可能会影响其他包的兼容性。
运行以下脚本检查潜在的依赖冲突:
✅ Verification successful
依赖项兼容性验证结果
根据代码分析,botpy
和 qq-botpy
的使用是相互独立的:
botpy
仅在bots/qqbot/
目录下使用,主要用于消息处理- 代码中没有发现
qq-botpy
的直接使用
由于:
- 这两个包的功能域是分离的
- 其他依赖项都指定了明确的版本约束
- Python 版本要求是 ^3.12.0,这是一个现代的稳定版本
这些依赖项的组合不太可能产生冲突。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查依赖关系和版本约束
poetry check
poetry show --tree
Length of output: 229
Script:
#!/bin/bash
# 检查pyproject.toml中的依赖项
cat pyproject.toml | grep -A 20 "\[tool.poetry.dependencies\]"
# 搜索代码库中使用botpy的地方
rg "import botpy" -A 2
rg "from botpy" -A 2
# 搜索代码库中使用qq-botpy的地方
rg "import qq_botpy" -A 2
rg "from qq_botpy" -A 2
Length of output: 1154
core/builtins/__init__.py (1)
26-26
: 需要验证 Temp 的导入
根据静态分析提示,Temp
可能未定义或来自星号导入。建议明确导入路径。
✅ Verification successful
Temp
的导入和使用是正确的
在 core/builtins/__init__.py
中通过 from .temp import *
导入了 Temp
类,该类定义在 core/builtins/temp/__init__.py
中。这是一个有效的相对导入,代码结构清晰。赋值语句 Temp = Temp
不会造成问题。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 查找 Temp 的定义位置
rg -l "class Temp"
Length of output: 94
Script:
#!/bin/bash
# 检查 core/builtins/__init__.py 中的导入语句
rg -A 5 "^from|^import" core/builtins/__init__.py
# 检查 core/builtins/temp/__init__.py 中的 Temp 类定义
cat core/builtins/temp/__init__.py
Length of output: 689
🧰 Tools
🪛 Ruff (0.8.2)
26-26: Temp
may be undefined, or defined from star imports
(F405)
modules/wikilog/dbutils.py (1)
34-38
: 配置初始化逻辑更新
配置初始化逻辑清晰,使用 setdefault 确保了配置项的一致性。
modules/wiki/audit.py (1)
125-125
: 消息发送逻辑位置调整合理
将消息发送逻辑移动到 if 块内,确保了只有在有内容时才发送消息,避免了发送空消息的情况。
core/utils/http.py (3)
47-47
: 改进了类型安全性和默认值的明确性
- 将 status_code 的默认值从 False 改为 200 更符合 HTTP 成功状态码的语义
- 将 timeout 的类型从 int 改为 Optional[float] 提供了更灵活的超时控制
这些改动都是正确的改进。
Also applies to: 51-51
116-116
: post_url 函数参数改进与 get_url 保持一致
参数的改进与 get_url 函数保持了一致性,这是一个好的实践。
Also applies to: 119-119
185-185
: download 函数参数改进与其他 HTTP 函数保持一致
参数的改进与其他 HTTP 函数保持了一致性,这是一个好的实践。
Also applies to: 189-189
core/builtins/message/elements.py (3)
24-24
: 新增 deepcopy 导入以支持对象深拷贝
良好的改进,通过深拷贝确保返回的实例是独立的,防止意外修改。
48-49
: PlainElement.assign 方法的参数和返回值改进
- 参数类型从
Tuple[str]
改为*texts: Any
,提供了更灵活的参数传递方式 - 返回深拷贝实例而不是直接返回实例,确保了返回值的不可变性
Also applies to: 57-57
105-105
: MessageSession 类型引用更新
将字符串字面量类型提示替换为实际类型引用,提高了代码的类型安全性。
Also applies to: 151-151
modules/cytoid/rating.py (2)
Line range hint 31-36
: 用户查找错误处理优化
改进了用户不存在时的错误处理,返回更友好的错误消息。
🧰 Tools
🪛 Ruff (0.8.2)
33-34: Use a single if
statement instead of nested if
statements
(SIM102)
238-244
: 头像下载功能优化
使用新的 download 函数简化了头像下载逻辑,提高了代码可维护性。
core/builtins/message/chain.py (2)
1-2
: 启用延迟类型注解评估
添加 from __future__ import annotations
是一个好的实践,可以避免前向引用问题。
37-37
: 类型提示改进
将字符串字面量类型替换为实际类型引用(MessageChain 和 MessageSession),提高了代码的类型安全性和可维护性。
Also applies to: 151-151
requirements.txt (2)
16-16
: 版本更新提醒
attrs
包已更新到最新版本 24.2.0,这是一个正向的版本升级。
79-80
: 请验证依赖项的兼容性
langconv
包现在直接从 GitHub 仓库安装,这可能会影响构建的稳定性。langsmith
包版本从 0.1.140 降级到 0.1.139,这是一个回退操作。
core/config/__init__.py (1)
12-14
: 导入语句组织合理
导入语句的组织结构清晰,遵循了 Python 的导入规范。
modules/wiki/wiki.py (1)
60-70
: 函数签名优化合理
参数重新排序和类型注解的更新提高了代码的可读性和类型安全性。
dir = os.path.join(cache_path, 'maimai-record') | ||
os.makedirs(dir, exist_ok=True) | ||
cache_dir = os.path.join(dir, f"{msg.target.sender_id.replace('|', '_')}_maimaidx_record.json") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
缓存目录结构统一化
缓存目录结构的统一化改进很好,但建议:
- 将目录创建逻辑封装成工具函数
- 添加目录清理机制,避免缓存无限增长
+ def ensure_record_cache_dir() -> str:
+ dir = os.path.join(cache_path, 'maimai-record')
+ os.makedirs(dir, exist_ok=True)
+ return dir
- dir = os.path.join(cache_path, 'maimai-record')
- os.makedirs(dir, exist_ok=True)
+ dir = ensure_record_cache_dir()
Also applies to: 153-155, 200-202, 246-248
pngPath = os.path.join(mai_cover_path, f'{chartInfo.idNum}.png') | ||
if not os.path.exists(pngPath): | ||
pngPath = os.path.join(mai_cover_path, '01000.png') | ||
pngPath = os.path.join(mai_cover_path, '0.png') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议重构重复的图片处理逻辑
当前代码中 SD 和 DX 榜单的图片处理逻辑完全相同,建议提取为独立方法以提高代码可维护性。
建议添加以下辅助方法:
class DrawBest:
+ def _get_cover_image(self, chart_info: ChartInfo) -> Image.Image:
+ """获取并处理歌曲封面图片"""
+ itemW = 150
+ itemH = 100
+ pngPath = os.path.join(mai_cover_path, f'{chart_info.idNum}.png')
+ if not os.path.exists(pngPath):
+ pngPath = os.path.join(mai_cover_path, '0.png')
+
+ if os.path.exists(pngPath):
+ temp = Image.open(pngPath).convert('RGB')
+ temp = self._resizePic(temp, itemW / temp.size[0])
+ temp = temp.crop((0, (temp.size[1] - itemH) / 2, itemW, (temp.size[1] + itemH) / 2))
+ temp = temp.filter(ImageFilter.GaussianBlur(2))
+ temp = temp.point(lambda p: int(p * 0.72))
+ else:
+ temp = Image.new('RGB', (int(itemW), int(itemH)), (111, 111, 111, 255))
+ return temp
然后在原代码中调用此方法:
- pngPath = os.path.join(mai_cover_path, f'{chartInfo.idNum}.png')
- if not os.path.exists(pngPath):
- pngPath = os.path.join(mai_cover_path, '0.png')
-
- if os.path.exists(pngPath):
- temp = Image.open(pngPath).convert('RGB')
- temp = self._resizePic(temp, itemW / temp.size[0])
- temp = temp.crop((0, (temp.size[1] - itemH) / 2, itemW, (temp.size[1] + itemH) / 2))
- temp = temp.filter(ImageFilter.GaussianBlur(2))
- temp = temp.point(lambda p: int(p * 0.72))
- else:
- temp = Image.new('RGB', (int(itemW), int(itemH)), (111, 111, 111, 255))
+ temp = self._get_cover_image(chartInfo)
Committable suggestion skipped: line range outside the PR's diff.
pngPath = os.path.join(mai_cover_path, f'{chartInfo.idNum}.png') | ||
if not os.path.exists(pngPath): | ||
pngPath = os.path.join(mai_cover_path, '01000.png') | ||
pngPath = os.path.join(mai_cover_path, '0.png') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
发现封面图片系统存在潜在问题
根据代码分析发现以下问题:
- 默认封面图片
0.png
不存在,但代码中多处依赖此文件作为后备方案 - 在
maimaidx_apidata.py
中仍然使用get_cover_len5_id
下载图片,但新的访问逻辑已改为直接使用idNum
- 缺少图片下载失败时的错误处理机制
建议:
- 确保添加默认的
0.png
封面图片到mai_cover_path
目录 - 更新
maimaidx_apidata.py
中的下载逻辑,使其与新的命名规范保持一致 - 考虑添加图片缺失时的日志记录
🔗 Analysis chain
请验证封面图片的命名规范和默认图片
建议确认以下几点:
- 所有封面图片是否都已按照新的命名规范(直接使用
idNum
)重命名 - 默认图片
0.png
是否已放置在正确位置 - 建议添加日志记录,以便跟踪缺失的封面图片
Let me gather more information about the cover path handling to provide a comprehensive verification.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查封面图片的命名规范和默认图片
# 验证默认图片是否存在
if [ -f "$(fd '0.png' -t f)" ]; then
echo "默认图片存在"
else
echo "警告:默认图片不存在"
fi
# 检查所有封面图片的命名格式
rg -g '*.py' 'idNum.*\.png'
Length of output: 578
Script:
#!/bin/bash
# 检查封面图片相关的路径处理代码
# 查找 mai_cover_path 的定义和使用
rg -g '*.py' 'mai_cover_path' -B 2 -A 2
# 查找与图片路径相关的其他常量或配置
rg -g '*.py' 'COVER_PATH|cover_path|IMAGE_PATH|image_path'
# 检查是否有其他使用 .png 的地方
rg -g '*.py' '\.png'
Length of output: 10066
|
||
from core.builtins import MessageSession | ||
|
||
_cd_lst: Dict[str, Dict[MessageSession, float]] = {} | ||
_cd_lst = defaultdict(lambda: defaultdict(dict)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
注意 _cd_lst
的线程安全性
将 _cd_lst
更改为嵌套的 defaultdict
后,可能在多线程或异步环境下产生线程安全问题。建议在访问或修改 _cd_lst
时使用锁机制,确保线程安全。
command_list: CommandMatches = CommandMatches.init() | ||
regex_list: RegexMatches = RegexMatches.init() | ||
schedule_list: ScheduleMatches = ScheduleMatches.init() | ||
hooks_list: HookMatches = HookMatches.init() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复未定义的名称问题
在第 43-46 行,使用了 CommandMatches
、RegexMatches
、ScheduleMatches
和 HookMatches
,但可能未明确导入这些名称。确保这些类已正确导入,避免在运行时出现 NameError
。
🧰 Tools
🪛 Ruff (0.8.2)
43-43: CommandMatches
may be undefined, or defined from star imports
(F405)
43-43: CommandMatches
may be undefined, or defined from star imports
(F405)
44-44: RegexMatches
may be undefined, or defined from star imports
(F405)
44-44: RegexMatches
may be undefined, or defined from star imports
(F405)
45-45: ScheduleMatches
may be undefined, or defined from star imports
(F405)
45-45: ScheduleMatches
may be undefined, or defined from star imports
(F405)
46-46: HookMatches
may be undefined, or defined from star imports
(F405)
46-46: HookMatches
may be undefined, or defined from star imports
(F405)
wait = await query_pages(QueryInfo.assign('https://mzh.moegirl.org.cn/api.php', headers={'accept': '*/*', | ||
'accept-encoding': 'gzip, deflate', | ||
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,en-GB;q=0.6', | ||
'content-type': 'application/json', | ||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62' | ||
}, | ||
locale=locale.locale), redirect) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议复用已提取的常量
这里的 headers 配置与上面的完全相同,应该复用之前定义的常量。
建议修改为:
- wait = await query_pages(QueryInfo.assign('https://mzh.moegirl.org.cn/api.php', headers={'accept': '*/*',
- 'accept-encoding': 'gzip, deflate',
- 'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,en-GB;q=0.6',
- 'content-type': 'application/json',
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'
- },
- locale=locale.locale), redirect)
+ wait = await query_pages(QueryInfo.assign(MOEGIRL_API_URL,
+ headers=MOEGIRL_HEADERS,
+ locale=locale.locale),
+ redirect)
Committable suggestion skipped: line range outside the PR's diff.
@@ -70,7 +86,7 @@ async def image_table_render(table: Union[ImageTable, List[ImageTable]], save_so | |||
|
|||
try: | |||
pic = await download( | |||
webrender(use_local=use_local), | |||
webrender(use_local=use_local, method=''), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议优化 webrender 方法参数
向 webrender 传递空字符串作为 method 参数可能会导致混淆。建议移除该参数或使用有意义的值。
建议修改为:
- webrender(use_local=use_local, method=''),
+ webrender(use_local=use_local),
同样的修改也应用于第100行。
Also applies to: 100-100
@@ -124,7 +124,7 @@ def format_board(self): | |||
return '\n'.join(''.join(row) for row in formatted) | |||
|
|||
def is_game_over(self): | |||
return bool(len(self.board) != 0 and self.word == self.board[-1]) | |||
return bool(len(self.board) != 0 and (self.word == self.board[-1]) or (len(self.board) > 5)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
游戏结束条件的逻辑错误
当前的实现存在以下问题:
- 括号位置不正确导致逻辑运算顺序错误
- 使用
len(self.board) > 5
可能导致游戏在第6次尝试后立即结束,而不给玩家最后一次机会
建议修改为:
- return bool(len(self.board) != 0 and (self.word == self.board[-1]) or (len(self.board) > 5))
+ return bool(len(self.board) != 0 and (self.word == self.board[-1] or len(self.board) >= 6))
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
return bool(len(self.board) != 0 and (self.word == self.board[-1]) or (len(self.board) > 5)) | |
return bool(len(self.board) != 0 and (self.word == self.board[-1] or len(self.board) >= 6)) |
filename = 'thumbnail.png' | ||
d = os.path.join(cache_path, 'cytoid-cover', uid) | ||
os.makedirs(d, exist_ok=True) | ||
path = os.path.join(d, 'thumbnail.png') | ||
path = os.path.join(d, filename) | ||
if not os.path.exists(path): | ||
level_url = 'http://services.cytoid.io/levels/' + uid | ||
level_url = f'http://services.cytoid.io/levels/{uid}' | ||
get_level = json.loads(await get_url(level_url)) | ||
cover_thumbnail = get_level['cover']['original'] + "?h=240&w=384" | ||
async with aiohttp.ClientSession() as session, session.get(cover_thumbnail) as resp, async_open(path, 'wb+') as jpg: | ||
await jpg.write(await resp.read()) | ||
return path | ||
else: | ||
return path | ||
except BaseException: | ||
cover_thumbnail = f"{get_level['cover']['original']}?h=240&w=384" | ||
path = await download(cover_thumbnail, filename=filename, path=d, logging_err_resp=False) | ||
return path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
下载封面缩略图功能重构
- 使用 cache_path 替代 assets_path
- 使用新的 download 函数简化下载逻辑
- 改进了路径处理和错误处理
建议添加缓存过期处理机制,避免缓存文件无限增长:
+from datetime import datetime, timedelta
+import os.path
async def download_cover_thumb(uid):
try:
filename = 'thumbnail.png'
d = os.path.join(cache_path, 'cytoid-cover', uid)
os.makedirs(d, exist_ok=True)
path = os.path.join(d, filename)
- if not os.path.exists(path):
+ if not os.path.exists(path) or \
+ datetime.fromtimestamp(os.path.getmtime(path)) < datetime.now() - timedelta(days=7):
level_url = f'http://services.cytoid.io/levels/{uid}'
get_level = json.loads(await get_url(level_url))
cover_thumbnail = f"{get_level['cover']['original']}?h=240&w=384"
path = await download(cover_thumbnail, filename=filename, path=d, logging_err_resp=False)
return path
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
filename = 'thumbnail.png' | |
d = os.path.join(cache_path, 'cytoid-cover', uid) | |
os.makedirs(d, exist_ok=True) | |
path = os.path.join(d, 'thumbnail.png') | |
path = os.path.join(d, filename) | |
if not os.path.exists(path): | |
level_url = 'http://services.cytoid.io/levels/' + uid | |
level_url = f'http://services.cytoid.io/levels/{uid}' | |
get_level = json.loads(await get_url(level_url)) | |
cover_thumbnail = get_level['cover']['original'] + "?h=240&w=384" | |
async with aiohttp.ClientSession() as session, session.get(cover_thumbnail) as resp, async_open(path, 'wb+') as jpg: | |
await jpg.write(await resp.read()) | |
return path | |
else: | |
return path | |
except BaseException: | |
cover_thumbnail = f"{get_level['cover']['original']}?h=240&w=384" | |
path = await download(cover_thumbnail, filename=filename, path=d, logging_err_resp=False) | |
return path | |
from datetime import datetime, timedelta | |
import os.path | |
filename = 'thumbnail.png' | |
d = os.path.join(cache_path, 'cytoid-cover', uid) | |
os.makedirs(d, exist_ok=True) | |
path = os.path.join(d, filename) | |
if not os.path.exists(path) or \ | |
datetime.fromtimestamp(os.path.getmtime(path)) < datetime.now() - timedelta(days=7): | |
level_url = f'http://services.cytoid.io/levels/{uid}' | |
get_level = json.loads(await get_url(level_url)) | |
cover_thumbnail = f"{get_level['cover']['original']}?h=240&w=384" | |
path = await download(cover_thumbnail, filename=filename, path=d, logging_err_resp=False) | |
return path |
async def _callback(msg: Bot.MessageSession): | ||
display = msg.as_display(text_only=True) | ||
if isint(display) and int(display) <= len(forum_data) - 1: | ||
await query_pages(session, title=forum_data[display]['text'], start_wiki_api=r.info.api) | ||
|
||
await session.send_message(i_msg_lst, callback=_callback) | ||
await session.send_message(i_msg_lst, callback=_callback) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复回调函数中的变量绑定问题
回调函数中存在循环变量绑定问题,这可能导致意外的行为。
建议修改为:
-async def _callback(msg: Bot.MessageSession):
- display = msg.as_display(text_only=True)
- if isint(display) and int(display) <= len(forum_data) - 1:
- await query_pages(session, title=forum_data[display]['text'], start_wiki_api=r.info.api)
+async def create_callback(current_forum_data, current_r):
+ async def _callback(msg: Bot.MessageSession):
+ display = msg.as_display(text_only=True)
+ if isint(display) and int(display) <= len(current_forum_data) - 1:
+ await query_pages(session, title=current_forum_data[display]['text'],
+ start_wiki_api=current_r.info.api)
+ return _callback
await session.send_message(i_msg_lst, callback=await create_callback(forum_data, r))
Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Ruff (0.8.2)
267-267: Function definition does not bind loop variable forum_data
(B023)
268-268: Function definition does not bind loop variable forum_data
(B023)
268-268: Function definition does not bind loop variable r
(B023)
Summary by CodeRabbit
发布说明
新功能
文档
样式
依赖更新