diff --git a/README.md b/README.md
index 748fe9ec..4c2bc7bc 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,8 @@
_基于 [Nonebot2](https://github.com/nonebot/nonebot2) 和 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 的 qq 机器人_
-![Nonebot2](https://img.shields.io/badge/Nonebot2-Release_v2.0.0_beta.3-brightgreen)
-![go-cqhttp](https://img.shields.io/badge/go--cqhttp-v1.0.0_rc1-brightgreen)
+![Nonebot2](https://img.shields.io/badge/Nonebot2-Release_v2.0.0_beta.5-brightgreen)
+![go-cqhttp](https://img.shields.io/badge/go--cqhttp-v1.0.0_rc3-brightgreen)
![GitHub](https://img.shields.io/github/license/Ailitonia/omega-miya)
![Python](https://img.shields.io/badge/Python-3.10+-blue)
@@ -18,11 +18,11 @@ _基于 [Nonebot2](https://github.com/nonebot/nonebot2) 和 [go-cqhttp](https://
## 当前适配 nonebot2 版本
-[Nonebot2 Release v2.0.0-beta.3](https://github.com/nonebot/nonebot2/releases/tag/v2.0.0-beta.3)
+[Nonebot2 Release v2.0.0-beta.5](https://github.com/nonebot/nonebot2/releases/tag/v2.0.0-beta.5)
## 当前适配 go-cqhttp 版本
-[go-cqhttp v1.0.0-rc1](https://github.com/Mrs4s/go-cqhttp/releases/tag/v1.0.0-rc1)
+[go-cqhttp v1.0.0-rc3](https://github.com/Mrs4s/go-cqhttp/releases/tag/v1.0.0-rc3)
## 功能 & 特点
diff --git a/omega_miya/database/schemas/pixiv_artwork.py b/omega_miya/database/schemas/pixiv_artwork.py
index 3ce83d13..a8a70bf6 100644
--- a/omega_miya/database/schemas/pixiv_artwork.py
+++ b/omega_miya/database/schemas/pixiv_artwork.py
@@ -286,9 +286,18 @@ async def query_all_pid_by_uid(cls, uid: int) -> IntListResult:
return IntListResult(error=False, info='Success', result=(await cls._query_custom_all(stmt=stmt)))
@classmethod
- async def count_all(cls, keywords: Optional[List[str]] = None) -> PixivArtworkCountResult:
+ async def count_all(
+ cls,
+ keywords: Optional[List[str]] = None,
+ *,
+ classified: Optional[int] = 1
+ ) -> PixivArtworkCountResult:
try:
all_stmt = select(func.count(cls.orm_model.id)).with_for_update(read=True)
+
+ if classified is not None:
+ all_stmt = all_stmt.where(cls.orm_model.classified == classified)
+
if keywords:
for keyword in keywords:
all_stmt = all_stmt.where(or_(
diff --git a/omega_miya/onebot_api/gocq/__init__.py b/omega_miya/onebot_api/gocq/__init__.py
index ca2afe92..45419083 100644
--- a/omega_miya/onebot_api/gocq/__init__.py
+++ b/omega_miya/onebot_api/gocq/__init__.py
@@ -34,7 +34,7 @@
class GoCqhttpBot(BaseOnebotApi):
"""go-cqhttp api
- 适配版本: go-cqhttp v1.0.0-rc2
+ 适配版本: go-cqhttp v1.0.0-rc3
"""
def __init__(self, bot: Bot):
@@ -54,30 +54,35 @@ async def connecting_db_upgrade(self) -> None:
# 更新群组相关信息
groups_result = await self.get_group_list()
group_upgrade_tasks = [
- InternalBotGroup(bot_id=self.self_id, parent_id=self.self_id, entity_id=x.group_id).add_only(
+ InternalBotGroup(bot_id=self.self_id, parent_id=self.self_id, entity_id=x.group_id).add_upgrade(
parent_entity_name=bot_login_info.nickname,
entity_name=x.group_name,
- entity_info=x.group_memo,
- related_entity_name=x.group_name
+ related_entity_name=x.group_name,
+ parent_entity_info=bot_login_info.nickname,
+ entity_info=x.group_memo
)
for x in groups_result]
# 更新用户相关信息
users_result = await self.get_friend_list()
user_upgrade_tasks = [
- InternalBotUser(bot_id=self.self_id, parent_id=self.self_id, entity_id=x.user_id).add_only(
+ InternalBotUser(bot_id=self.self_id, parent_id=self.self_id, entity_id=x.user_id).add_upgrade(
parent_entity_name=bot_login_info.nickname,
entity_name=x.nickname,
- related_entity_name=x.remark
+ related_entity_name=x.remark,
+ parent_entity_info=bot_login_info.nickname,
+ entity_info=x.remark
)
for x in users_result]
# 更新频道相关信息
guild_profile = await self.get_guild_service_profile()
guild_data = await self.get_guild_list()
guild_upgrade_tasks = [
- InternalBotGuild(bot_id=self.self_id, parent_id=guild_profile.tiny_id, entity_id=x.guild_id).add_only(
+ InternalBotGuild(bot_id=self.self_id, parent_id=guild_profile.tiny_id, entity_id=x.guild_id).add_upgrade(
parent_entity_name=guild_profile.nickname,
entity_name=x.guild_name,
- related_entity_name=x.guild_name
+ related_entity_name=x.guild_name,
+ parent_entity_info=guild_profile.nickname,
+ entity_info=x.guild_name
)
for x in guild_data]
@@ -85,10 +90,14 @@ async def connecting_db_upgrade(self) -> None:
for guild in guild_data:
channel_data = await self.get_guild_channel_list(guild_id=guild.guild_id)
channel_upgrade_tasks.extend([
- InternalGuildChannel(bot_id=self.self_id, parent_id=x.owner_guild_id, entity_id=x.channel_id).add_only(
+ InternalGuildChannel(
+ bot_id=self.self_id, parent_id=x.owner_guild_id, entity_id=x.channel_id
+ ).add_upgrade(
parent_entity_name=guild.guild_name,
entity_name=x.channel_name,
- related_entity_name=x.channel_name
+ related_entity_name=x.channel_name,
+ parent_entity_info=guild.guild_name,
+ entity_info=x.channel_name
)
for x in channel_data
])
@@ -486,6 +495,17 @@ async def upload_group_file(self, group_id: int | str, file: str, name: str, fol
"""
return await self.bot.call_api('upload_group_file', group_id=group_id, file=file, name=name, folder=folder)
+ async def upload_private_file(self, user_id: int | str, file: str, name: str) -> None:
+ """上传私聊文件
+
+ 只能上传本地文件, 需要上传 http 文件的话请先调用 download_file API下载
+
+ :param user_id: 好友qq
+ :param file: 本地文件路径
+ :param name: 储存名称
+ """
+ return await self.bot.call_api('upload_private_file', user_id=user_id, file=file, name=name)
+
async def get_group_file_system_info(self, group_id: int | str) -> GroupFileSystemInfo:
system_info_result = await self.bot.call_api('get_group_file_system_info', group_id=group_id)
return GroupFileSystemInfo.parse_obj(system_info_result)
diff --git a/omega_miya/plugins/announce/__init__.py b/omega_miya/plugins/announce/__init__.py
index 0bcbf11e..49dc630d 100644
--- a/omega_miya/plugins/announce/__init__.py
+++ b/omega_miya/plugins/announce/__init__.py
@@ -1,4 +1,5 @@
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
@@ -12,13 +13,13 @@
from omega_miya.utils.process_utils import run_async_catching_exception, semaphore_gather
-# Custom plugin usage text
-__plugin_custom_name__ = '公告'
-__plugin_usage__ = r'''【公告插件】
-快速批量向启用了bot的群组发送通知公告
-
-用法:
-/公告 [公告内容]'''
+__plugin_meta__ = PluginMetadata(
+ name="公告",
+ description="【公告插件】\n"
+ "快速批量向启用了bot的群组发送通知公告",
+ usage="/公告 [公告内容]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/auto_group_sign/__init__.py b/omega_miya/plugins/auto_group_sign/__init__.py
new file mode 100644
index 00000000..e62effba
--- /dev/null
+++ b/omega_miya/plugins/auto_group_sign/__init__.py
@@ -0,0 +1,75 @@
+"""
+@Author : Ailitonia
+@Date : 2022/06/27 20:48
+@FileName : auto_group_sign.py
+@Project : nonebot2_miya
+@Description : 自动群打卡 (go-cqhttp v1.0.0-rc3 以上版本可用)
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot import get_driver
+from nonebot.log import logger
+from nonebot.plugin import PluginMetadata
+from nonebot.adapters import Bot
+from pydantic import BaseModel
+
+from omega_miya.onebot_api import GoCqhttpBot
+from omega_miya.utils.apscheduler import scheduler
+from omega_miya.utils.process_utils import semaphore_gather
+
+
+__plugin_meta__ = PluginMetadata(
+ name="自动群打卡",
+ description="【自动群打卡插件】\n"
+ "让机器人参与抢群打卡每日第一",
+ usage="由管理员配置, 无命令用法",
+ extra={"author": "Ailitonia"},
+)
+
+
+class AutoGroupSignConfig(BaseModel):
+ """自动群打卡插件配置"""
+ # 启用自动群打卡
+ enable_auto_group_sign: bool = False
+
+ class Config:
+ extra = "ignore"
+
+
+_plugin_config = AutoGroupSignConfig.parse_obj(get_driver().config)
+
+
+async def _bot_group_sign(bot: Bot):
+ gocq_bot = GoCqhttpBot(bot=bot)
+ tasks = [gocq_bot.send_group_sign(group_id=group_result.group_id) for group_result in await gocq_bot.get_group_list()]
+ await semaphore_gather(tasks=tasks, semaphore_num=16)
+
+
+async def _sign_main() -> None:
+ logger.debug('AutoGroupSign | Starting sign all groups')
+ tasks = [_bot_group_sign(bot=bot) for _, bot in get_driver().bots.items()]
+ await semaphore_gather(tasks=tasks, semaphore_num=8)
+ logger.debug('AutoGroupSign | Sign tasks completed')
+
+
+if _plugin_config.enable_auto_group_sign:
+ scheduler.add_job(
+ _sign_main,
+ 'cron',
+ # year=None,
+ # month=None,
+ # day='*/1',
+ # week=None,
+ # day_of_week=None,
+ hour='0',
+ minute='0',
+ second='0',
+ # start_date=None,
+ # end_date=None,
+ # timezone=None,
+ id='auto_group_sign',
+ coalesce=True,
+ misfire_grace_time=30
+ )
+ logger.opt(colors=True).success('AutoGroupSign | 自动群打卡已启用')
diff --git a/omega_miya/plugins/bilibili_dynamic_monitor/__init__.py b/omega_miya/plugins/bilibili_dynamic_monitor/__init__.py
index c087deb8..386adbb6 100644
--- a/omega_miya/plugins/bilibili_dynamic_monitor/__init__.py
+++ b/omega_miya/plugins/bilibili_dynamic_monitor/__init__.py
@@ -8,7 +8,8 @@
@Software : PyCharm
"""
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -29,16 +30,16 @@
from .monitor import scheduler
-# Custom plugin usage text
-__plugin_custom_name__ = 'B站动态订阅'
-__plugin_usage__ = r'''【B站动态订阅】
-订阅并跟踪Bilibili用户动态更新
-
-用法:
-仅限私聊或群聊中群管理员使用:
-/B站动态订阅 [UID]
-/B站动态取消订阅 [UID]
-/B站动态订阅列表'''
+__plugin_meta__ = PluginMetadata(
+ name="B站动态订阅",
+ description="【B站动态订阅插件】\n"
+ "订阅并跟踪Bilibili用户动态更新",
+ usage="仅限私聊或群聊中群管理员使用:\n"
+ "/B站动态订阅 [UID]\n"
+ "/B站动态取消订阅 [UID]\n"
+ "/B站动态订阅列表",
+ extra={"author": "Ailitonia"},
+)
add_dynamic_sub = on_command(
diff --git a/omega_miya/plugins/bilibili_live_monitor/__init__.py b/omega_miya/plugins/bilibili_live_monitor/__init__.py
index 390ad504..55602f3f 100644
--- a/omega_miya/plugins/bilibili_live_monitor/__init__.py
+++ b/omega_miya/plugins/bilibili_live_monitor/__init__.py
@@ -1,4 +1,15 @@
-from nonebot import on_command, logger
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : bilibili_live_monitor.py
+@Project : nonebot2_miya
+@Description : Bilibili 直播间订阅
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -18,17 +29,17 @@
from .utils import add_bili_live_room_sub, delete_bili_live_room_sub, query_subscribed_bili_live_room_sub_source
-# Custom plugin usage text
-__plugin_custom_name__ = 'B站直播间订阅'
-__plugin_usage__ = r'''【B站直播间订阅】
-订阅并监控Bilibili直播间状态
-提供开播、下播、直播间换标题提醒
-
-用法:
-仅限私聊或群聊中群管理员使用:
-/B站直播间订阅 [RoomID]
-/B站直播间取消订阅 [RoomID]
-/B站直播间订阅列表'''
+__plugin_meta__ = PluginMetadata(
+ name="B站直播间订阅",
+ description="【B站直播间订阅插件】\n"
+ "订阅并监控Bilibili直播间状态\n"
+ "提供开播、下播、直播间换标题提醒",
+ usage="仅限私聊或群聊中群管理员使用:\n"
+ "/B站直播间订阅 [RoomID]\n"
+ "/B站直播间取消订阅 [RoomID]\n"
+ "/B站直播间订阅列表",
+ extra={"author": "Ailitonia"},
+)
add_live_sub = on_command(
diff --git a/omega_miya/plugins/bilibili_live_monitor/config.py b/omega_miya/plugins/bilibili_live_monitor/config.py
new file mode 100644
index 00000000..c35e081b
--- /dev/null
+++ b/omega_miya/plugins/bilibili_live_monitor/config.py
@@ -0,0 +1,35 @@
+"""
+@Author : Ailitonia
+@Date : 2022/07/30 21:31
+@FileName : config.py
+@Project : nonebot2_miya
+@Description : Bilibili 直播间订阅插件配置
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot import get_driver, logger
+from pydantic import BaseModel, ValidationError
+
+
+class BilibiliLiveMonitorPluginConfig(BaseModel):
+ """BilibiliLiveMonitor 插件配置"""
+
+ # 发送消息通知时尝试@全体
+ bilibili_live_monitor_enable_group_at_all_notice: bool = False
+
+ class Config:
+ extra = "ignore"
+
+
+try:
+ bilibili_live_monitor_plugin_config = BilibiliLiveMonitorPluginConfig.parse_obj(get_driver().config)
+except ValidationError as e:
+ import sys
+ logger.opt(colors=True).critical(f'Bilibili 直播间订阅插件配置格式验证失败, 错误信息:\n{e}')
+ sys.exit(f'Bilibili 直播间订阅插件配置格式验证失败, {e}')
+
+
+__all__ = [
+ 'bilibili_live_monitor_plugin_config'
+]
diff --git a/omega_miya/plugins/bilibili_live_monitor/utils.py b/omega_miya/plugins/bilibili_live_monitor/utils.py
index 16ff25ae..f4d7711b 100644
--- a/omega_miya/plugins/bilibili_live_monitor/utils.py
+++ b/omega_miya/plugins/bilibili_live_monitor/utils.py
@@ -25,6 +25,7 @@
from omega_miya.utils.process_utils import run_async_catching_exception, semaphore_gather
from omega_miya.utils.message_tools import MessageSender
+from .config import bilibili_live_monitor_plugin_config as plugin_config
from .model import (BilibiliLiveRoomStatus, BilibiliLiveRoomTitleChange, BilibiliLiveRoomStartLiving,
BilibiliLiveRoomStartLivingWithUpdateTitle, BilibiliLiveRoomStopLiving,
BilibiliLiveRoomStopLivingWithPlaylist, BilibiliLiveRoomStatusUpdate)
@@ -164,7 +165,7 @@ async def _get_live_room_update_message(
update_data: BilibiliLiveRoomStatusUpdate
) -> str | Message | None:
"""处理直播间更新为消息"""
- send_message = f'【bilibili直播间】\n'
+ send_message = '【bilibili直播间】\n'
user_name = _LIVE_STATUS.get(live_room_data.uid).live_user_name
need_url = False
@@ -206,6 +207,17 @@ async def _msg_sender(entity: BaseInternalEntity, message: str | Message) -> int
"""向 entity 发送消息"""
try:
msg_sender = MessageSender.init_from_bot_id(bot_id=entity.bot_id)
+
+ # 通知群组时检查能不能@全体成员
+ if plugin_config.bilibili_live_monitor_enable_group_at_all_notice and entity.relation_type == 'bot_group':
+ at_all_remain = await run_async_catching_exception(msg_sender.bot.get_group_at_all_remain)(
+ group_id=entity.entity_id)
+ if (not isinstance(at_all_remain, Exception)
+ and at_all_remain.can_at_all
+ and at_all_remain.remain_at_all_count_for_group
+ and at_all_remain.remain_at_all_count_for_uin):
+ message = MessageSegment.at(user_id='all') + message
+
sent_msg_id = await msg_sender.send_internal_entity_msg(entity=entity, message=message)
except KeyError:
logger.debug(f'BilibiliLiveRoomMonitor | Bot({entity.bot_id}) not online, '
diff --git a/omega_miya/plugins/calculator/__init__.py b/omega_miya/plugins/calculator/__init__.py
index bea87452..f1b8b097 100644
--- a/omega_miya/plugins/calculator/__init__.py
+++ b/omega_miya/plugins/calculator/__init__.py
@@ -8,7 +8,8 @@
@Software : PyCharm
"""
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11.permission import GROUP, PRIVATE_FRIEND
from nonebot.adapters.onebot.v11.message import Message
@@ -19,13 +20,13 @@
from .calculator import Calculator, CalculateException
-# Custom plugin usage text
-__plugin_custom_name__ = '计算器'
-__plugin_usage__ = r'''【简易计算器】
-只能计算加减乘除和乘方!
-
-用法:
-/计算 [算式]'''
+__plugin_meta__ = PluginMetadata(
+ name="计算器",
+ description="【简易计算器插件】\n"
+ "只能计算加减乘除和乘方!",
+ usage="/计算 [算式]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/draw/__init__.py b/omega_miya/plugins/draw/__init__.py
index 7c4a4a83..ee063ae2 100644
--- a/omega_miya/plugins/draw/__init__.py
+++ b/omega_miya/plugins/draw/__init__.py
@@ -8,7 +8,7 @@
@Software : PyCharm
"""
-from nonebot import on_command
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11.message import Message
from nonebot.adapters.onebot.v11.event import MessageEvent
@@ -20,15 +20,16 @@
from .deck import draw, get_deck
-# Custom plugin usage text
-__plugin_custom_name__ = '抽卡'
-__plugin_usage__ = r'''【抽卡】
-模拟各种抽卡
-没有保底的啦!
-不要上头啊喂!
-用法
-/抽卡 [卡组]'''
+__plugin_meta__ = PluginMetadata(
+ name="抽卡",
+ description="【抽卡模拟插件】\n"
+ "模拟各种抽卡\n"
+ "没有保底的啦!\n"
+ "不要上头啊喂!",
+ usage="/抽卡 [卡组]",
+ extra={"author": "Ailitonia"},
+)
draw_deck = on_command(
diff --git a/omega_miya/plugins/draw/deck/arknights.py b/omega_miya/plugins/draw/deck/arknights.py
index 639156a4..52d88317 100644
--- a/omega_miya/plugins/draw/deck/arknights.py
+++ b/omega_miya/plugins/draw/deck/arknights.py
@@ -26,24 +26,33 @@ class UpEvent(BaseModel):
UpEvent(
star=6,
operator=[
- Operator(name='归溟幽灵鲨/Irene', star=6, limited=True, recruit_only=False, event_only=False,
- special_only=False),
- Operator(name='艾丽妮/Irene', star=6, limited=False, recruit_only=False, event_only=False,
+ Operator(name='多萝西/Dorothy', star=6, limited=False, recruit_only=False, event_only=False,
special_only=False)
],
- zoom=0.7
+ zoom=0.5
),
UpEvent(
star=5,
operator=[
- Operator(name='掠风/Windflit', star=5, limited=False, recruit_only=False, event_only=False,
- special_only=False)
+ Operator(name='承曦格雷伊/Greyy the Lightningbearer', star=5, limited=False, recruit_only=False,
+ event_only=False, special_only=False),
+ Operator(name='白面鸮/Ptilopsis', star=5, limited=False, recruit_only=False, event_only=False,
+ special_only=False),
],
zoom=0.5
)
]
ALL_OPERATOR: list[Operator] = [
+ Operator(name='多萝西/Dorothy', star=6, limited=False, recruit_only=False, event_only=False, special_only=False),
+ Operator(name='承曦格雷伊/Greyy the Lightningbearer', star=5, limited=False, recruit_only=False, event_only=False,
+ special_only=False),
+ Operator(name='星源/Astgenne', star=5, limited=False, recruit_only=False, event_only=True, special_only=False),
+ Operator(name='黑键/Ebenholz', star=6, limited=False, recruit_only=False, event_only=False, special_only=False),
+ Operator(name='濯尘芙蓉/Hibiscus the Purifier', star=5, limited=False, recruit_only=False, event_only=False,
+ special_only=False),
+ Operator(name='车尔尼/Czerny', star=5, limited=False, recruit_only=False, event_only=True, special_only=False),
+ Operator(name='埃拉托/Erato', star=5, limited=False, recruit_only=False, event_only=True, special_only=False),
Operator(name='归溟幽灵鲨/Irene', star=6, limited=True, recruit_only=False, event_only=False, special_only=False),
Operator(name='艾丽妮/Irene', star=6, limited=False, recruit_only=False, event_only=False, special_only=False),
Operator(name='流明/Lumen', star=6, limited=False, recruit_only=False, event_only=True, special_only=False),
diff --git a/omega_miya/plugins/http_cat/__init__.py b/omega_miya/plugins/http_cat/__init__.py
index 29436f0d..34dfff7b 100644
--- a/omega_miya/plugins/http_cat/__init__.py
+++ b/omega_miya/plugins/http_cat/__init__.py
@@ -8,7 +8,7 @@
@Software : PyCharm
"""
-from nonebot import on_command
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11.message import Message, MessageSegment
from nonebot.adapters.onebot.v11.permission import GROUP, PRIVATE_FRIEND
@@ -20,13 +20,13 @@
from .data_source import get_http_cat
-# Custom plugin usage text
-__plugin_custom_name__ = 'HttpCat'
-__plugin_usage__ = r'''【HttpCat】
-用猫猫表示的http状态码
-
-用法:
-/HttpCat '''
+__plugin_meta__ = PluginMetadata(
+ name="HttpCat",
+ description="【HttpCat插件】\n"
+ "用猫猫表示的http状态码",
+ usage="/HttpCat ",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/image_searcher/__init__.py b/omega_miya/plugins/image_searcher/__init__.py
index 646db91f..aac6a828 100644
--- a/omega_miya/plugins/image_searcher/__init__.py
+++ b/omega_miya/plugins/image_searcher/__init__.py
@@ -8,11 +8,12 @@
@Software : PyCharm
"""
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11.bot import Bot
-from nonebot.adapters.onebot.v11.event import MessageEvent, GroupMessageEvent
+from nonebot.adapters.onebot.v11.event import MessageEvent
from nonebot.adapters.onebot.v11.message import Message
from nonebot.adapters.onebot.v11.permission import GROUP, PRIVATE_FRIEND
from nonebot.params import Depends, RawCommand, CommandArg, Arg, ArgStr
@@ -25,14 +26,14 @@
from omega_miya.onebot_api import GoCqhttpBot
-# Custom plugin usage text
-__plugin_custom_name__ = '识图搜番'
-__plugin_usage__ = r'''【识图搜番助手】
-使用 SauceNAO/iqdb/ascii2d/trace.moe 识别各类图片、插画、番剧
-
-用法:
-/识图
-/搜番'''
+__plugin_meta__ = PluginMetadata(
+ name="识图搜番",
+ description="【识图搜番插件】\n"
+ "使用 SauceNAO/iqdb/ascii2d/trace.moe 识别各类图片、插画、番剧",
+ usage="/识图 [图片]\n"
+ "/搜番 [图片]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
@@ -105,8 +106,6 @@ async def handle_sticker(bot: Bot, matcher: Matcher, event: MessageEvent, state:
elif not searching_result:
await matcher.finish('没有找到相似度足够高的图片QAQ')
else:
- if isinstance(event, GroupMessageEvent):
- await MessageSender(bot=bot).send_group_node_custom_and_recall(group_id=event.group_id, recall_time=60,
- message_list=searching_result)
- else:
- [await matcher.finish(x) for x in searching_result]
+ await MessageSender(bot=bot).send_node_custom_and_recall(
+ event=event, recall_time=90, message_list=searching_result
+ )
diff --git a/omega_miya/plugins/maybe/__init__.py b/omega_miya/plugins/maybe/__init__.py
index 0ddd1531..e545fc66 100644
--- a/omega_miya/plugins/maybe/__init__.py
+++ b/omega_miya/plugins/maybe/__init__.py
@@ -1,5 +1,15 @@
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : maybe.py
+@Project : nonebot2_miya
+@Description : 求签
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
import datetime
-from nonebot import on_command
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11.message import Message
from nonebot.adapters.onebot.v11.event import MessageEvent
@@ -12,15 +22,15 @@
from .utils import query_maybe
-# Custom plugin usage text
-__plugin_custom_name__ = '求签'
-__plugin_usage__ = r'''【求签】
-求签, 求运势, 包括且不限于抽卡、吃饭、睡懒觉、DD
-每个人每天求同一个东西的结果是一样的啦!
-不要不信邪重新抽啦!
-
-用法:
-/求签 [所求之事]'''
+__plugin_meta__ = PluginMetadata(
+ name="求签",
+ description="【求签插件】\n"
+ "求签, 求运势, 包括且不限于抽卡、吃饭、睡懒觉、DD\n"
+ "每个人每天求同一个东西的结果是一样的啦!\n"
+ "不要不信邪重新抽啦!",
+ usage="/求签 [所求之事]",
+ extra={"author": "Ailitonia"},
+)
maybe = on_command(
diff --git a/omega_miya/plugins/mirage_tank/__init__.py b/omega_miya/plugins/mirage_tank/__init__.py
index 4e4824e5..66e4efb5 100644
--- a/omega_miya/plugins/mirage_tank/__init__.py
+++ b/omega_miya/plugins/mirage_tank/__init__.py
@@ -8,7 +8,8 @@
@Software : PyCharm
"""
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11.event import MessageEvent
@@ -23,15 +24,14 @@
from .utils import simple_white, simple_black, complex_gray, complex_color, complex_difference
-# Custom plugin usage text
-__plugin_custom_name__ = '幻影坦克'
-__plugin_usage__ = rf'''【幻影坦克图片生成工具】
-制作幻影坦克图片
-
-/幻影坦克 [模式] [图片]
-
-合成模式可选: "白底", "黑底", "灰度混合", "彩色混合", "差分"
-'''
+__plugin_meta__ = PluginMetadata(
+ name="幻影坦克",
+ description="【幻影坦克图片生成插件】\n"
+ "制作幻影坦克图片",
+ usage="/幻影坦克 [模式] [图片]\n\n"
+ '合成模式可选: "白底", "黑底", "灰度混合", "彩色混合", "差分"',
+ extra={"author": "Ailitonia"},
+)
mirage_tank = on_command(
diff --git a/omega_miya/plugins/miya_button/__init__.py b/omega_miya/plugins/miya_button/__init__.py
index c98317af..a965b469 100644
--- a/omega_miya/plugins/miya_button/__init__.py
+++ b/omega_miya/plugins/miya_button/__init__.py
@@ -9,7 +9,8 @@
"""
import re
-from nonebot import on_command, on_regex, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_regex, PluginMetadata
from nonebot.rule import to_me
from nonebot.typing import T_State
from nonebot.matcher import Matcher
@@ -26,13 +27,13 @@
get_voice_resource_name, set_voice_resource)
-# Custom plugin usage text
-__plugin_custom_name__ = '猫按钮'
-__plugin_usage__ = r'''【猫按钮】
-发出可爱的猫叫
-
-用法:
-@bot 喵一个'''
+__plugin_meta__ = PluginMetadata(
+ name="猫按钮",
+ description="【猫按钮插件】\n"
+ "发出可爱的猫叫",
+ usage="@bot 喵一个",
+ extra={"author": "Ailitonia"},
+)
button_pattern = r'^(.*?)喵一个$'
diff --git a/omega_miya/plugins/moe/__init__.py b/omega_miya/plugins/moe/__init__.py
index 2e4f384c..7a4b4194 100644
--- a/omega_miya/plugins/moe/__init__.py
+++ b/omega_miya/plugins/moe/__init__.py
@@ -10,7 +10,8 @@
import re
from copy import deepcopy
-from nonebot import on_shell_command, on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_shell_command, PluginMetadata
from nonebot.rule import to_me
from nonebot.typing import T_State
from nonebot.matcher import Matcher
@@ -35,25 +36,24 @@
get_query_argument_parser, parse_from_query_parser)
-# Custom plugin usage text
-__plugin_custom_name__ = '来点萌图'
-__plugin_usage__ = r'''【来点萌图】
-随机萌图和随机涩图
-不可以随意涩涩!
-
-用法:
-/来点萌图 [关键词, ...]
-/来点涩图 [关键词, ...]
-
-可用参数:
-'-s', '--nsfw-tag': 指定nsfw_tag
-'-n', '--num': 指定获取的图片数量
-'-nf', '--no-flash': 强制不使用闪照发送图片
-
-仅限管理员使用:
-/图库统计
-/图库查询 [关键词, ...]
-/导入图库'''
+__plugin_meta__ = PluginMetadata(
+ name="来点萌图",
+ description="【来点萌图插件】\n"
+ "随机萌图和随机涩图\n"
+ "不可以随意涩涩!",
+ usage="/来点萌图 [关键词, ...]\n"
+ "/来点涩图 [关键词, ...]\n\n"
+ "可用参数:\n"
+ "'-s', '--nsfw-tag': 指定nsfw_tag\n"
+ "'-n', '--num': 指定获取的图片数量\n"
+ "'-nf', '--no-flash': 强制不使用闪照发送图片\n\n"
+ "仅限管理员使用:\n"
+ "/图库统计\n"
+ "/图库查询 [关键词, ...]\n"
+ "/导入图库",
+ config=moe_plugin_config.__class__,
+ extra={"author": "Ailitonia"},
+)
_ALLOW_R18_NODE = moe_plugin_config.moe_plugin_allow_r18_node
@@ -118,13 +118,16 @@ async def handle_parse_success(bot: Bot, event: MessageEvent, matcher: Matcher,
await matcher.finish('找不到涩图QAQ')
await matcher.send('稍等, 正在下载图片~')
- image_message_tasks = [prepare_send_image(pid=x.pid, enable_flash_mode=(not args.no_flash)) for x in artworks]
+
+ flash_mode = True if moe_plugin_config.moe_plugin_enforce_setu_enable_flash_mode else not args.no_flash
+
+ image_message_tasks = [prepare_send_image(pid=x.pid, enable_flash_mode=flash_mode) for x in artworks]
message_result = await semaphore_gather(tasks=image_message_tasks, semaphore_num=5, filter_exception=True)
send_messages = list(message_result)
if not send_messages:
await matcher.finish('所有图片都获取失败了QAQ, 可能是网络原因或作品被删除, 请稍后再试')
await MessageSender(bot=bot).send_msgs_and_recall(event=event, message_list=send_messages,
- recall_time=moe_plugin_config.moe_plugin_auto_recall_time)
+ recall_time=moe_plugin_config.moe_plugin_setu_auto_recall_time)
moe = on_shell_command(
@@ -176,13 +179,16 @@ async def handle_parse_success(bot: Bot, event: MessageEvent, matcher: Matcher,
await matcher.finish('找不到萌图QAQ')
await matcher.send('稍等, 正在下载图片~')
- image_message_tasks = [prepare_send_image(pid=x.pid, enable_flash_mode=(not args.no_flash)) for x in artworks]
+
+ flash_mode = False if moe_plugin_config.moe_plugin_enforce_moe_disable_flash_mode else not args.no_flash
+
+ image_message_tasks = [prepare_send_image(pid=x.pid, enable_flash_mode=flash_mode) for x in artworks]
message_result = await semaphore_gather(tasks=image_message_tasks, semaphore_num=5, filter_exception=True)
send_messages = list(message_result)
if not send_messages:
await matcher.finish('所有图片都获取失败了QAQ, 可能是网络原因或作品被删除, 请稍后再试')
await MessageSender(bot=bot).send_msgs_and_recall(event=event, message_list=send_messages,
- recall_time=moe_plugin_config.moe_plugin_auto_recall_time)
+ recall_time=moe_plugin_config.moe_plugin_moe_auto_recall_time)
statistics = on_command(
diff --git a/omega_miya/plugins/moe/config.py b/omega_miya/plugins/moe/config.py
index b23bb915..98d32334 100644
--- a/omega_miya/plugins/moe/config.py
+++ b/omega_miya/plugins/moe/config.py
@@ -25,10 +25,18 @@ class MoePluginConfig(BaseModel):
moe_plugin_query_image_num: int = 3
# 允许用户通过参数调整的每次查询的图片数量上限
moe_plugin_query_image_limit: int = 10
+
# 启用使用闪照模式发送图片
moe_plugin_enable_flash_mode: bool = True
- # 默认自动撤回消息时间
- moe_plugin_auto_recall_time: int = 30
+ # 强制不使用闪照发送萌图(会覆盖部分 moe_plugin_enable_flash_mode 配置行为)
+ moe_plugin_enforce_moe_disable_flash_mode: bool = False
+ # 强制使用闪照发送涩图(会覆盖部分 moe_plugin_enable_flash_mode 配置行为)
+ moe_plugin_enforce_setu_enable_flash_mode: bool = False
+
+ # 萌图默认自动撤回消息时间(设置 0 为不撤回)
+ moe_plugin_moe_auto_recall_time: int = 60
+ # 涩图默认自动撤回消息时间(设置 0 为不撤回)
+ moe_plugin_setu_auto_recall_time: int = 30
class Config:
extra = "ignore"
diff --git a/omega_miya/plugins/nbnhhsh/__init__.py b/omega_miya/plugins/nbnhhsh/__init__.py
index 00c9e771..d532f4c5 100644
--- a/omega_miya/plugins/nbnhhsh/__init__.py
+++ b/omega_miya/plugins/nbnhhsh/__init__.py
@@ -1,4 +1,14 @@
-from nonebot import on_command
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : nbnhhsh.py
+@Project : nonebot2_miya
+@Description : 能不能好好说话
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11.message import Message
from nonebot.adapters.onebot.v11.permission import GROUP, PRIVATE_FRIEND
@@ -10,13 +20,13 @@
from .data_source import get_guess
-# Custom plugin usage text
-__plugin_custom_name__ = '好好说话'
-__plugin_usage__ = r'''【能不能好好说话?】
-拼音首字母缩写释义
-
-用法
-/好好说话 [缩写]'''
+__plugin_meta__ = PluginMetadata(
+ name="好好说话",
+ description="【能不能好好说话?】\n"
+ "拼音首字母缩写释义",
+ usage="/好好说话 [缩写]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/nbnhhsh/data_source.py b/omega_miya/plugins/nbnhhsh/data_source.py
index 9d93b106..928bac0b 100644
--- a/omega_miya/plugins/nbnhhsh/data_source.py
+++ b/omega_miya/plugins/nbnhhsh/data_source.py
@@ -26,6 +26,9 @@ def guess_result(self) -> list[str]:
async def _get_guess(guess: str) -> list[GuessResult]:
+ """从 magiconch API 处获取缩写查询结果"""
+ # 该 api 当前不支持查询的缩写中有空格 这里去除待查询文本中的空格
+ guess = guess.replace(' ', '')
payload = {'text': guess}
result = await HttpFetcher().post_json(url=_API_URL, json=payload)
return parse_obj_as(list[GuessResult], result.result)
diff --git a/omega_miya/plugins/nhentai/__init__.py b/omega_miya/plugins/nhentai/__init__.py
index bdef4ee4..0f8b7541 100644
--- a/omega_miya/plugins/nhentai/__init__.py
+++ b/omega_miya/plugins/nhentai/__init__.py
@@ -10,12 +10,13 @@
要求go-cqhttp v0.9.40以上
"""
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11.bot import Bot
-from nonebot.adapters.onebot.v11.event import GroupMessageEvent
-from nonebot.adapters.onebot.v11.permission import GROUP
+from nonebot.adapters.onebot.v11.event import MessageEvent, GroupMessageEvent
+from nonebot.adapters.onebot.v11.permission import GROUP, PRIVATE_FRIEND
from nonebot.adapters.onebot.v11.message import Message, MessageSegment
from nonebot.params import CommandArg, ArgStr
@@ -26,13 +27,14 @@
from omega_miya.web_resource.nhentai import NhentaiGallery
-# Custom plugin usage text
-__plugin_custom_name__ = 'NHentai'
-__plugin_usage__ = r'''【NHentai】
-神秘的插件
-
-/nh search [tag]
-/nh download [id]'''
+__plugin_meta__ = PluginMetadata(
+ name="NHentai",
+ description="【NHentai插件】\n"
+ "神秘的插件",
+ usage="/nh search [tag]\n"
+ "/nh download [id]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
@@ -46,7 +48,7 @@
user_cool_down_override=2
),
aliases={'nhentai', 'nh'},
- permission=GROUP,
+ permission=GROUP | PRIVATE_FRIEND,
priority=20,
block=True
)
@@ -68,7 +70,7 @@ async def handle_parse_operating(state: T_State, cmd_arg: Message = CommandArg()
@nhentai.got('operation_arg', prompt='Please enter the search keywords or download gallery id')
async def handle_operating(
bot: Bot,
- event: GroupMessageEvent,
+ event: MessageEvent,
matcher: Matcher,
operating: str = ArgStr('operating'),
operation_arg: str = ArgStr('operation_arg')
@@ -87,21 +89,19 @@ async def handle_operating(
await matcher.finish('Invalid operation')
-async def handle_search(bot: Bot, event: GroupMessageEvent, matcher: Matcher, keyword: str):
+async def handle_search(bot: Bot, event: MessageEvent, matcher: Matcher, keyword: str):
await matcher.send('获取搜索结果中, 请稍候')
search_tasks = [NhentaiGallery.search_gallery_with_preview(keyword=keyword, page=p) for p in range(1, 6)]
search_results = await semaphore_gather(tasks=search_tasks, semaphore_num=2, filter_exception=True)
if not search_results:
await matcher.finish('没有搜索结果或搜索失败了QAQ, 请稍后再试')
else:
- send_messages = ['已为你找到了以下结果, 可通过id下载']
- send_messages.extend([MessageSegment.image(x.file_uri) for x in search_results])
- await MessageSender(bot=bot).send_group_node_custom_and_recall(group_id=event.group_id,
- message_list=send_messages,
- recall_time=60)
+ message_list = ['已为你找到了以下结果, 可通过id下载']
+ message_list.extend([MessageSegment.image(x.file_uri) for x in search_results])
+ await MessageSender(bot=bot).send_node_custom_and_recall(event=event, message_list=message_list, recall_time=60)
-async def handle_download(bot: Bot, event: GroupMessageEvent, matcher: Matcher, gallery_id: int):
+async def handle_download(bot: Bot, event: MessageEvent, matcher: Matcher, gallery_id: int):
await matcher.send('下载中, 请稍候')
download_result = await run_async_catching_exception(NhentaiGallery(gallery_id=gallery_id).download)()
if isinstance(download_result, Exception):
@@ -109,9 +109,18 @@ async def handle_download(bot: Bot, event: GroupMessageEvent, matcher: Matcher,
await matcher.finish('下载失败QAQ, 请稍后再试')
else:
await matcher.send(f'下载完成, 密码: {download_result.password},\n正在上传文件, 可能需要一段时间...')
- gocq_bot = GoCqhttpBot(bot=bot)
- upload_result = await run_async_catching_exception(gocq_bot.upload_group_file)(
- group_id=event.group_id, file=download_result.file.resolve_path, name=download_result.file.path.name)
+ upload_result = await _upload_file(
+ bot=bot, event=event, file=download_result.file.resolve_path, name=download_result.file.path.name
+ )
if isinstance(upload_result, Exception):
logger.error(f'NHentai | Upload gallery({gallery_id}) to group file failed, {upload_result}')
await matcher.finish('上传文件失败QAQ, 请稍后再试')
+
+
+@run_async_catching_exception
+async def _upload_file(bot: Bot, event: MessageEvent, file: str, name: str) -> None:
+ gocq_bot = GoCqhttpBot(bot=bot)
+ if isinstance(event, GroupMessageEvent):
+ await gocq_bot.upload_group_file(group_id=event.group_id, file=file, name=name)
+ else:
+ await gocq_bot.upload_private_file(user_id=event.user_id, file=file, name=name)
diff --git a/omega_miya/plugins/omega_anti_flash/__init__.py b/omega_miya/plugins/omega_anti_flash/__init__.py
index 2d3bba2a..f1b08b0d 100644
--- a/omega_miya/plugins/omega_anti_flash/__init__.py
+++ b/omega_miya/plugins/omega_anti_flash/__init__.py
@@ -1,5 +1,16 @@
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : omega_anti_flash.py
+@Project : nonebot2_miya
+@Description : Omega 反闪照插件
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
from typing import Literal
-from nonebot import on_command, on_message, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_message, PluginMetadata
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.matcher import Matcher
@@ -15,13 +26,14 @@
from omega_miya.utils.rule import group_has_permission_node
-# Custom plugin usage text
-__plugin_custom_name__ = '反闪照'
-__plugin_usage__ = r'''【AntiFlash 反闪照插件】
-检测闪照并提取原图
-
-用法:
-/AntiFlash '''
+__plugin_meta__ = PluginMetadata(
+ name="反闪照",
+ description="【AntiFlash 反闪照插件】\n"
+ "检测闪照并提取原图",
+ usage="仅限群聊中群管理员使用:\n"
+ "/AntiFlash ",
+ extra={"author": "Ailitonia"},
+)
_ANTI_FLASH_CUSTOM_MODULE_NAME: Literal['Omega.AntiFlash'] = 'Omega.AntiFlash'
diff --git a/omega_miya/plugins/omega_anti_recall/__init__.py b/omega_miya/plugins/omega_anti_recall/__init__.py
index a84ed29f..6c7820fd 100644
--- a/omega_miya/plugins/omega_anti_recall/__init__.py
+++ b/omega_miya/plugins/omega_anti_recall/__init__.py
@@ -1,6 +1,17 @@
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : omega_anti_recall.py
+@Project : nonebot2_miya
+@Description : Omega 反撤回插件
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
from datetime import datetime
from typing import Literal
-from nonebot import on_command, on_notice, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_notice, PluginMetadata
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.matcher import Matcher
@@ -18,13 +29,14 @@
from omega_miya.utils.message_tools import MessageTools
-# Custom plugin usage text
-__plugin_custom_name__ = '反撤回'
-__plugin_usage__ = r'''【AntiRecall 反撤回插件】
-检测消息撤回并提取原消息
-
-用法:
-/AntiRecall '''
+__plugin_meta__ = PluginMetadata(
+ name="反撤回",
+ description="【AntiRecall 反撤回插件】\n"
+ "检测消息撤回并提取原消息",
+ usage="仅限群聊中群管理员使用:\n"
+ "/AntiRecall ",
+ extra={"author": "Ailitonia"},
+)
_ANTI_RECALL_CUSTOM_MODULE_NAME: Literal['Omega.AntiRecall'] = 'Omega.AntiRecall'
diff --git a/omega_miya/plugins/omega_auth_manager/__init__.py b/omega_miya/plugins/omega_auth_manager/__init__.py
index 6dd4226e..1b3465c4 100644
--- a/omega_miya/plugins/omega_auth_manager/__init__.py
+++ b/omega_miya/plugins/omega_auth_manager/__init__.py
@@ -1,4 +1,15 @@
-from nonebot import on_command, get_plugin, get_loaded_plugins, logger
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : omega_auth_manager.py
+@Project : nonebot2_miya
+@Description : Omega 授权管理插件
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot.log import logger
+from nonebot.plugin import get_plugin, get_loaded_plugins, on_command, PluginMetadata
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
@@ -22,23 +33,22 @@
)
-# Custom plugin usage text
-__plugin_custom_name__ = '授权管理'
-__plugin_usage__ = r'''【OmegaAuth 授权管理插件】
-插件特殊权限授权管理
-仅限管理员使用
-
-用法:
-/OmegaAuth [授权操作] [授权对象ID] [插件名称] [权限节点]
-/OmegaAuth [allow|deny] [插件名称] [权限节点]
-/OmegaAuth [list]
-
-可用授权操作:
-allow: 允许会话所在群组/频道/用户
-deny: 禁止会话所在群组/频道/用户
-list: 列出会话所在群组/频道/用户已配置的权限节点
-custom_allow: 允许指定群组/频道/用户
-custom_deny: 禁止指定群组/频道/用户'''
+__plugin_meta__ = PluginMetadata(
+ name="授权管理",
+ description="【OmegaAuth 授权管理插件】\n"
+ "插件特殊权限授权管理\n"
+ "仅限管理员使用",
+ usage="/OmegaAuth [授权操作] [授权对象ID] [插件名称] [权限节点]\n"
+ "/OmegaAuth [allow|deny] [插件名称] [权限节点]\n"
+ "/OmegaAuth [list]\n\n"
+ "可用授权操作:\n"
+ "allow: 允许会话所在群组/频道/用户\n"
+ "deny: 禁止会话所在群组/频道/用户\n"
+ "list: 列出会话所在群组/频道/用户已配置的权限节点\n"
+ "custom_allow: 允许指定群组/频道/用户\n"
+ "custom_deny: 禁止指定群组/频道/用户",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
@@ -122,8 +132,7 @@ async def handle_related_entity_id(
@auth.handle()
async def handle_plugin_name_tips(matcher: Matcher, state: T_State):
if not state.get('plugin_name', None):
- all_plugins = [p.name for p in get_loaded_plugins()
- if getattr(p.module, '__plugin_custom_name__', None) is not None]
+ all_plugins = [p.name for p in get_loaded_plugins() if p.metadata is not None]
all_plugins.sort()
all_plugin_name = '\n'.join(all_plugins)
info_msg = f'现在已安装的插件有:\n\n{all_plugin_name}'
diff --git a/omega_miya/plugins/omega_email/__init__.py b/omega_miya/plugins/omega_email/__init__.py
index 8e0cfdfb..0010cc4f 100644
--- a/omega_miya/plugins/omega_email/__init__.py
+++ b/omega_miya/plugins/omega_email/__init__.py
@@ -1,5 +1,16 @@
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : omega_email.py
+@Project : nonebot2_miya
+@Description : Omega 邮箱插件
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
import re
-from nonebot import CommandGroup, logger
+from nonebot.log import logger
+from nonebot.plugin import CommandGroup, PluginMetadata
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
@@ -19,19 +30,18 @@
from .utils import check_mailbox, get_unseen_mail_data, encrypt_password, decrypt_password
-# Custom plugin usage text
-__plugin_custom_name__ = '收邮件'
-__plugin_usage__ = r'''【OmegaEmail 邮箱插件】
-主要是用来收验证码OvO
-仅限群聊使用
-
-用法:
-/收邮件
-
-管理员命令:
-/添加邮箱
-/绑定邮箱
-/解绑邮箱'''
+__plugin_meta__ = PluginMetadata(
+ name="收邮件",
+ description="【OmegaEmail 邮箱插件】\n"
+ "主要是用来收验证码的\n"
+ "仅限群聊使用",
+ usage="/收邮件\n\n"
+ "管理员命令:\n"
+ "/添加邮箱\n"
+ "/绑定邮箱\n"
+ "/解绑邮箱",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/omega_help/__init__.py b/omega_miya/plugins/omega_help/__init__.py
index 97ee838c..27309d67 100644
--- a/omega_miya/plugins/omega_help/__init__.py
+++ b/omega_miya/plugins/omega_help/__init__.py
@@ -1,5 +1,14 @@
-from nonebot import on_command
-from nonebot.plugin import get_loaded_plugins
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : omega_help.py
+@Project : nonebot2_miya
+@Description : Omega 帮助插件
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot.plugin import get_loaded_plugins, on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11.bot import Bot
@@ -12,13 +21,13 @@
from omega_miya.service.omega_processor_tools import init_processor_state, parse_processor_state
-# Custom plugin usage text
-__plugin_custom_name__ = '帮助'
-__plugin_usage__ = r'''【帮助】
-一个简单的帮助插件
-
-用法:
-/帮助 [插件名]'''
+__plugin_meta__ = PluginMetadata(
+ name="帮助",
+ description="【Omega 帮助插件】\n"
+ "一个简单的帮助插件",
+ usage="/帮助 [插件名]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
@@ -57,18 +66,18 @@ async def handle_help_message(bot: Bot, event: MessageEvent, plugin_name: str =
async def get_all_plugins_desc() -> str:
"""获取全部配置了自定义信息的插件信息"""
- plugin_custom_name = '\n'.join(str(name) for name in (
- getattr(plugin.module, '__plugin_custom_name__', None) for plugin in get_loaded_plugins()
- ) if name is not None)
- return f'现在已安装的插件有: \n\n{plugin_custom_name}\n\n输入"/help [插件名]"即可查看插件详情及帮助'
+ plugins_custom_name = '\n'.join(plugin.metadata.name for plugin in get_loaded_plugins() if plugin.metadata)
+ return f'现在已安装的插件有: \n\n{plugins_custom_name}\n\n输入"/help [插件名]"即可查看插件详情及帮助'
async def get_plugin_desc(plugin_name: str, *, for_superuser: bool = False) -> str:
"""获取指定的配置了自定义信息的插件信息"""
for plugin in get_loaded_plugins():
- plugin_custom_name = getattr(plugin.module, '__plugin_custom_name__', None)
- if plugin_name == plugin_custom_name:
- plugin_usage = getattr(plugin.module, '__plugin_usage__', None)
+ if not plugin.metadata:
+ continue
+
+ if plugin_name == plugin.metadata.name:
+ plugin_usage = f'{plugin.metadata.description}\n\n用法:\n{plugin.metadata.usage}'
if for_superuser:
processor_info = '\n'.join(
f'\n[{s.name}]\nLevel: {s.level if s.level < 4294967296 else "Unlimited"}/Node: {s.auth_node}\n'
diff --git a/omega_miya/plugins/omega_invite_manager/__init__.py b/omega_miya/plugins/omega_invite_manager/__init__.py
index 37f5d9b3..1b6513bb 100644
--- a/omega_miya/plugins/omega_invite_manager/__init__.py
+++ b/omega_miya/plugins/omega_invite_manager/__init__.py
@@ -10,7 +10,8 @@
import random
import string
-from nonebot import on_request, on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_request, PluginMetadata
from nonebot.typing import T_State
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
@@ -27,21 +28,20 @@
from omega_miya.utils.message_tools import MessageTools
-# Custom plugin usage text
-__plugin_custom_name__ = '好友和群组请求管理'
-__plugin_usage__ = r'''【OmegaInviteManager 好友和群组请求管理插件】
-处理加好友请求和加群、退群请求
-
-用法:
-/好友验证码 [用户qq]
-/允许邀请进群 [用户qq]
-/禁止邀请进群 [用户qq]
-
-说明:
-以上命令均只允许管理员使用,
-"好友验证码"命令会为指定用户生成一段验证码, 该用户在验证消息中输入该验证码可让 bot 通过好友验证
-"允许邀请进群"命令会为指定用户分配邀请 bot 进群的权限, 若该用户是 bot 的好友且具备该权限, 则 bot 会自动同意用户的邀请进群请求
-"禁止邀请进群"命令会移除指定用户的邀请 bot 进群的权限, 若 bot 被无该权限的用户邀请进群, 则会自动退群'''
+__plugin_meta__ = PluginMetadata(
+ name="好友和群组请求管理",
+ description="【OmegaInviteManager 好友和群组请求管理插件】\n"
+ "处理加好友请求和加群、退群请求",
+ usage="/好友验证码 [用户qq]\n"
+ "/允许邀请进群 [用户qq]\n"
+ "/禁止邀请进群 [用户qq]\n\n"
+ "说明:\n"
+ "以上命令均只允许管理员使用\n"
+ '"好友验证码"命令会为指定用户生成一段验证码, 该用户在验证消息中输入该验证码可让 bot 通过好友验证\n'
+ '"允许邀请进群"命令会为指定用户分配邀请 bot 进群的权限, 若该用户是 bot 的好友且具备该权限, 则 bot 会自动同意用户的邀请进群请求\n'
+ '"禁止邀请进群"命令会移除指定用户的邀请 bot 进群的权限, 若 bot 被无该权限的用户邀请进群, 则会自动退群',
+ extra={"author": "Ailitonia"},
+)
_FRIEND_ADD_VERIFY_CODE: dict[str, str] = {}
diff --git a/omega_miya/plugins/omega_manager/__init__.py b/omega_miya/plugins/omega_manager/__init__.py
index 0fee9872..c0d2e5d9 100644
--- a/omega_miya/plugins/omega_manager/__init__.py
+++ b/omega_miya/plugins/omega_manager/__init__.py
@@ -10,7 +10,8 @@
"""
from datetime import datetime, timedelta
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.matcher import Matcher
@@ -27,29 +28,28 @@
from omega_miya.utils.apscheduler import scheduler
-# Custom plugin usage text
-__plugin_custom_name__ = '核心管理'
-__plugin_usage__ = r'''【Omega 机器人核心管理插件】
-机器人开关、维护、功能及基础权限管理
-仅限管理员或私聊使用
-
-用法:
-/omega Init
-/omega Enable
-/omega Disable
-/omega SetLevel
-/omega ShowPermission
-/omega QuitGroup
-/omega CancelQuitGroup
-
-说明:
-Init: 初始化并启用基本功能, 不会覆盖已有信息, 仅供第一次使用bot时执行
-Enable: 启用 bot 功能
-Disable: 禁用 bot 功能
-SetLevel: 设置权限等级
-ShowPermission: 查询权限状态
-QuitGroup: 命令bot退群
-CancelQuitGroup: 取消bot退群'''
+__plugin_meta__ = PluginMetadata(
+ name="管理核心",
+ description="【Omega 机器人核心管理插件】\n"
+ "机器人开关、维护、功能及基础权限管理\n"
+ "仅限管理员或私聊使用",
+ usage="/omega Init\n"
+ "/omega Enable\n"
+ "/omega Disable\n"
+ "/omega SetLevel \n"
+ "/omega ShowPermission\n"
+ "/omega QuitGroup\n"
+ "/omega CancelQuitGroup\n\n"
+ "说明:\n"
+ "Init: 初始化并启用基本功能, 不会覆盖已有信息, 仅供第一次使用bot时执行\n"
+ "Enable: 启用 bot 功能\n"
+ "Disable: 禁用 bot 功能\n"
+ "SetLevel: 设置权限等级\n"
+ "ShowPermission: 查询权限状态\n"
+ "QuitGroup: 命令bot退群\n"
+ "CancelQuitGroup: 取消bot退群",
+ extra={"author": "Ailitonia"},
+)
DEFAULT_PERMISSION_LEVEL: int = 10
diff --git a/omega_miya/plugins/omega_plugin_manager/__init__.py b/omega_miya/plugins/omega_plugin_manager/__init__.py
index 6be58124..9ed0a254 100644
--- a/omega_miya/plugins/omega_plugin_manager/__init__.py
+++ b/omega_miya/plugins/omega_plugin_manager/__init__.py
@@ -8,7 +8,8 @@
@Software : PyCharm
"""
-from nonebot import CommandGroup, get_plugin, get_loaded_plugins, logger
+from nonebot.log import logger
+from nonebot.plugin import CommandGroup, get_plugin, get_loaded_plugins, PluginMetadata
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
@@ -22,23 +23,22 @@
from omega_miya.utils.process_utils import run_async_catching_exception
-# Custom plugin usage text
-__plugin_custom_name__ = '插件管理'
-__plugin_usage__ = r'''【OmegaPluginManager 插件管理器】
-管理启用和禁用插件
-仅限管理员使用
-
-用法:
-/OPM.[管理操作] [插件名]
-或使用别名:
-/启用插件 [插件名]
-/禁用插件 [插件名]
-/插件列表
-
-可用管理操作:
-enable: 启用插件
-disable: 禁用插件
-list: 显示插件列表'''
+__plugin_meta__ = PluginMetadata(
+ name="插件管理",
+ description="【OmegaPluginManager 插件管理器】\n"
+ "管理启用和禁用插件\n"
+ "仅限管理员使用",
+ usage="/OPM.[管理操作] [插件名]\n"
+ "或使用别名:\n"
+ "/启用插件 [插件名]\n"
+ "/禁用插件 [插件名]\n"
+ "/插件列表\n\n"
+ "可用管理操作:\n"
+ "enable: 启用插件\n"
+ "disable: 禁用插件\n"
+ "list: 显示插件列表",
+ extra={"author": "Ailitonia"},
+)
_log_prefix: str = 'OmegaPluginManager | '
@@ -157,6 +157,7 @@ def _desc(plugin_name: str) -> str:
plugin = get_plugin(name=plugin_name)
if plugin is None:
return plugin_name
+ elif plugin.metadata is None:
+ return plugin_name
- plugin_custom_name = getattr(plugin.module, '__plugin_custom_name__', '')
- return f'{plugin_name}({plugin_custom_name})'
+ return f'{plugin_name}({plugin.metadata.name})'
diff --git a/omega_miya/plugins/omega_rate_limiting/__init__.py b/omega_miya/plugins/omega_rate_limiting/__init__.py
index b86b238b..5d528b31 100644
--- a/omega_miya/plugins/omega_rate_limiting/__init__.py
+++ b/omega_miya/plugins/omega_rate_limiting/__init__.py
@@ -9,8 +9,8 @@
"""
from datetime import datetime, timedelta
-from nonebot import logger
-from nonebot.plugin import on_notice, CommandGroup
+from nonebot.log import logger
+from nonebot.plugin import on_notice, CommandGroup, PluginMetadata
from nonebot.typing import T_State
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
@@ -25,14 +25,14 @@
from omega_miya.utils.message_tools import MessageTools
-# Custom plugin usage text
-__plugin_custom_name__ = '流控限制'
-__plugin_usage__ = r'''【OmegaRateLimiting 流控限制插件】
-用户及群组流控限制
-
-用法:
-/Ban [用户]
-/GBan [群组]'''
+__plugin_meta__ = PluginMetadata(
+ name="流控限制",
+ description="【OmegaRateLimiting 流控限制插件】\n"
+ "用户及群组流控限制",
+ usage="/Ban [用户]\n"
+ "/GBan [群组]",
+ extra={"author": "Ailitonia"},
+)
_log_prefix: str = 'OmegaRateLimiting | '
diff --git a/omega_miya/plugins/omega_recaller/__init__.py b/omega_miya/plugins/omega_recaller/__init__.py
index 1a589187..49d5b7ac 100644
--- a/omega_miya/plugins/omega_recaller/__init__.py
+++ b/omega_miya/plugins/omega_recaller/__init__.py
@@ -8,8 +8,8 @@
@Software : PyCharm
"""
-from nonebot import logger
-from nonebot.plugin import on_command
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11.permission import GROUP_OWNER, GROUP_ADMIN
from nonebot.adapters.onebot.v11.bot import Bot
@@ -20,15 +20,15 @@
from omega_miya.onebot_api import GoCqhttpBot
-# Custom plugin usage text
-__plugin_custom_name__ = '快速撤回'
-__plugin_usage__ = r'''【快速撤回】
-快速撤回 bot 发送的消息
-仅限群管或超管使用
-
-用法:
-回复需撤回的消息
-/撤回'''
+__plugin_meta__ = PluginMetadata(
+ name="快速撤回",
+ description="【快速撤回插件】\n"
+ "快速撤回 bot 发送的消息\n"
+ "仅限群管或超管使用",
+ usage="回复需撤回的消息\n"
+ "/撤回",
+ extra={"author": "Ailitonia"},
+)
self_recall = on_command(
diff --git a/omega_miya/plugins/omega_sign_in/__init__.py b/omega_miya/plugins/omega_sign_in/__init__.py
index 50ad7d42..a9632692 100644
--- a/omega_miya/plugins/omega_sign_in/__init__.py
+++ b/omega_miya/plugins/omega_sign_in/__init__.py
@@ -11,7 +11,9 @@
import random
from typing import Union
from datetime import datetime
-from nonebot import MatcherGroup, on_notice, get_driver, logger
+from nonebot import get_driver
+from nonebot.log import logger
+from nonebot.plugin import MatcherGroup, on_notice, PluginMetadata
from nonebot.message import handle_event
from nonebot.typing import T_State
from nonebot.rule import to_me
@@ -33,19 +35,19 @@
from .utils import get_head_image, get_hitokoto, generate_signin_card
-# Custom plugin usage text
-__plugin_custom_name__ = '签到'
-__plugin_usage__ = r'''【OmegaSignIn 签到插件】
-签到插件, 好感度系统基础支持
-仅限群聊使用
-
-用法:
-/签到
-/今日运势|今日人品
-/好感度|我的好感
-/一言
-
-可使用戳一戳触发'''
+__plugin_meta__ = PluginMetadata(
+ name="签到",
+ description="【OmegaSignIn 签到插件】\n"
+ "签到插件\n"
+ "好感度系统基础支持",
+ usage="/签到\n"
+ "/今日运势|今日人品\n"
+ "/好感度|我的好感\n"
+ "/一言\n\n"
+ "可使用双击头像戳一戳触发",
+ config=sign_in_config.__class__,
+ extra={"author": "Ailitonia"},
+)
_COMMAND_START: set[str] = get_driver().config.command_start
@@ -171,7 +173,8 @@ async def handle_command_fix_sign_in_check(bot: Bot, event: GroupMessageEvent |
fix_date = datetime.fromordinal(fix_date_result).strftime('%Y年%m月%d日')
fix_days = datetime.now().toordinal() - fix_date_result
- fix_cost = 10 if fix_days <= 3 else fix_days * 3
+ base_cost = 2 * sign_in_config.signin_base_currency
+ fix_cost = base_cost if fix_days <= 3 else fix_days * base_cost
# 获取当前好感度信息
friendship = await run_async_catching_exception(user.get_friendship_model)()
@@ -221,7 +224,7 @@ async def handle_command_fix_sign_in_check(bot: Bot, event: GroupMessageEvent |
f'成功补签了{fix_date}的签到!'})
msg = await handle_fortune(bot=bot, event=event, state=state)
logger.info(f'SignIn | User({user.tid}), 补签成功')
- await command_fix_sign_in.finish(msg)
+ await command_fix_sign_in.finish(msg, at_sender=True)
async def handle_sign_in(bot: Bot, event: MessageEvent, state: T_State) -> Union[Message, MessageSegment, str]:
@@ -252,14 +255,14 @@ async def handle_sign_in(bot: Bot, event: MessageEvent, state: T_State) -> Union
# 尝试为用户增加好感度
# 根据连签日期设置不同增幅
if continuous_days < 7:
- base_friendship_inc = int(10 * (1 + random.gauss(0.25, 0.25)))
- currency_inc = 1
+ base_friendship_inc = int(30 * (1 + random.gauss(0.25, 0.25)))
+ currency_inc = 1 * sign_in_config.signin_base_currency
elif continuous_days < 30:
- base_friendship_inc = int(30 * (1 + random.gauss(0.35, 0.2)))
- currency_inc = 3
+ base_friendship_inc = int(70 * (1 + random.gauss(0.35, 0.2)))
+ currency_inc = 3 * sign_in_config.signin_base_currency
else:
- base_friendship_inc = int(50 * (1 + random.gauss(0.45, 0.15)))
- currency_inc = 5
+ base_friendship_inc = int(110 * (1 + random.gauss(0.45, 0.15)))
+ currency_inc = 5 * sign_in_config.signin_base_currency
# 将能量值兑换为好感度
friendship_inc = friendship.energy * sign_in_config.signin_ef_exchange_rate + base_friendship_inc
diff --git a/omega_miya/plugins/omega_sign_in/config.py b/omega_miya/plugins/omega_sign_in/config.py
index b85fe976..fc41ed10 100644
--- a/omega_miya/plugins/omega_sign_in/config.py
+++ b/omega_miya/plugins/omega_sign_in/config.py
@@ -32,6 +32,8 @@ class SignInConfig(BaseModel):
# 能量值与好感度的兑换比例 公式为(能量值 * 兑换比 = 好感度)
signin_ef_exchange_rate: float = 0.25
+ # 每日首次签到获取的基础硬币数 同时也是补签所需硬币的倍率基数
+ signin_base_currency: int = 5
class Config:
extra = "ignore"
diff --git a/omega_miya/plugins/omega_statistic/__init__.py b/omega_miya/plugins/omega_statistic/__init__.py
index 894fbf7a..8e3b733e 100644
--- a/omega_miya/plugins/omega_statistic/__init__.py
+++ b/omega_miya/plugins/omega_statistic/__init__.py
@@ -9,7 +9,8 @@
"""
from datetime import datetime
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -25,19 +26,18 @@
from .utils import draw_statistics
-# Custom plugin usage text
-__plugin_custom_name__ = '统计信息'
-__plugin_usage__ = r'''【OmegaStatistic 插件使用统计】
-查询插件使用统计信息
-
-用法:
-/统计信息 [条件]
-
-条件:
-- 本月
-- 本年
-- 全部
-- 所有'''
+__plugin_meta__ = PluginMetadata(
+ name="统计信息",
+ description="【OmegaStatistic 插件使用统计】\n"
+ "查询插件使用统计信息",
+ usage="/统计信息 [条件]\n\n"
+ "条件:\n"
+ "- 本月\n"
+ "- 本年\n"
+ "- 全部\n"
+ "- 所有",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
@@ -59,7 +59,7 @@ async def handle_parse_condition(state: T_State, cmd_arg: Message = CommandArg()
if condition:
state.update({'condition': condition})
else:
- state.update({'condition': '全部'})
+ state.update({'condition': '本月'})
@statistic.got('condition', prompt='请输入查询条件:')
diff --git a/omega_miya/plugins/omega_statistic/utils.py b/omega_miya/plugins/omega_statistic/utils.py
index a7860ea1..10777785 100644
--- a/omega_miya/plugins/omega_statistic/utils.py
+++ b/omega_miya/plugins/omega_statistic/utils.py
@@ -11,19 +11,24 @@
import sys
from datetime import datetime
from io import BytesIO
+from matplotlib import font_manager
from matplotlib import pyplot as plt
from omega_miya.database import Statistic
-from omega_miya.local_resource import TmpResource
+from omega_miya.local_resource import LocalResource, TmpResource
from omega_miya.utils.process_utils import run_sync, run_async_catching_exception
-
+_DEFAULT_FONT: LocalResource = LocalResource('fonts', 'fzzxhk.ttf')
+"""默认使用字体"""
_TMP_STATISTIC_IMG_FOLDER: str = 'statistic'
"""生成统计图缓存文件夹名"""
_TMP_STATISTIC_PATH: TmpResource = TmpResource(_TMP_STATISTIC_IMG_FOLDER)
"""生成统计图缓存资源地址"""
+font_manager.fontManager.addfont(_DEFAULT_FONT.resolve_path) # 添加资源文件中字体
+
+
@run_async_catching_exception
async def draw_statistics(
self_id: str,
@@ -43,13 +48,18 @@ async def draw_statistics(
def _handle() -> bytes:
plt.switch_backend('agg') # Fix RuntimeError caused by GUI needed
+ plt.rcParams['font.sans-serif'] = ['FZZhengHei-EL-GBK']
if sys.platform.startswith('win'):
- plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
- plt.barh([x.custom_name for x in statistic_result], [x.call_count for x in statistic_result])
+
+ # 绘制条形图
+ _bar_c = plt.barh([x.custom_name for x in statistic_result], [x.call_count for x in statistic_result])
+ plt.bar_label(_bar_c, label_type='edge')
plt.title(title)
+
+ # 导出图片
with BytesIO() as bf:
- plt.savefig(bf, dpi=300, format='JPG')
+ plt.savefig(bf, dpi=300, format='JPG', bbox_inches='tight')
img_bytes = bf.getvalue()
return img_bytes
diff --git a/omega_miya/plugins/omega_su/__init__.py b/omega_miya/plugins/omega_su/__init__.py
index 83e7aead..a1267c59 100644
--- a/omega_miya/plugins/omega_su/__init__.py
+++ b/omega_miya/plugins/omega_su/__init__.py
@@ -10,8 +10,8 @@
@Software : PyCharm
"""
-from nonebot import logger
-from nonebot.plugin import on, on_command
+from nonebot.log import logger
+from nonebot.plugin import on, on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.message import handle_event
from nonebot.rule import to_me
@@ -25,19 +25,17 @@
from omega_miya.service.gocqhttp_self_sent_patch import MessageSentEvent, SU_SELF_SENT
-_SU_TAG: bool = False
-
-
-# Custom plugin usage text
-__plugin_custom_name__ = '自调用消息'
-__plugin_usage__ = r'''【OmegaSu 自调用消息插件】
-让人工登陆机器人账号时可以通过特殊命令来自己调用自己
-
-用法:
-/su
+__plugin_meta__ = PluginMetadata(
+ name="自调用消息",
+ description="【OmegaSu 自调用消息插件】\n"
+ "让人工登陆机器人账号时可以通过特殊命令来自己调用自己",
+ usage="/su \n\n"
+ "人工登录 bot 使用命令:\n"
+ "!SU [command]",
+ extra={"author": "Ailitonia"},
+)
-人工登录 bot 使用命令:
-!SU [command]'''
+_SU_TAG: bool = False
# 注册事件响应器
diff --git a/omega_miya/plugins/omega_welcome_message/__init__.py b/omega_miya/plugins/omega_welcome_message/__init__.py
index 399a049b..96e253eb 100644
--- a/omega_miya/plugins/omega_welcome_message/__init__.py
+++ b/omega_miya/plugins/omega_welcome_message/__init__.py
@@ -8,8 +8,8 @@
@Software : PyCharm
"""
-from nonebot import logger
-from nonebot.plugin import on_notice, on_command
+from nonebot.log import logger
+from nonebot.plugin import on_notice, on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -26,14 +26,14 @@
from omega_miya.utils.message_tools import MessageTools
-# Custom plugin usage text
-__plugin_custom_name__ = '群欢迎消息'
-__plugin_usage__ = r'''【群自定义欢迎消息插件】
-向新入群的成员发送欢迎消息
-
-用法:
-/设置欢迎消息 [消息内容]
-/移除欢迎消息'''
+__plugin_meta__ = PluginMetadata(
+ name="群欢迎消息",
+ description="【群自定义欢迎消息插件】\n"
+ "向新入群的成员发送欢迎消息",
+ usage="/设置欢迎消息 [消息内容]\n"
+ "/移除欢迎消息",
+ extra={"author": "Ailitonia"},
+)
_SETTING_NAME: str = 'group_welcome_message'
diff --git a/omega_miya/plugins/pixiv/__init__.py b/omega_miya/plugins/pixiv/__init__.py
index 52791d31..772f3f98 100644
--- a/omega_miya/plugins/pixiv/__init__.py
+++ b/omega_miya/plugins/pixiv/__init__.py
@@ -9,7 +9,8 @@
"""
from datetime import datetime, timedelta
-from nonebot import on_command, on_shell_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_shell_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.rule import Namespace
@@ -36,36 +37,35 @@
from .monitor import scheduler
-# Custom plugin usage text
-__plugin_custom_name__ = 'Pixiv'
-__plugin_usage__ = r'''【Pixiv助手】
-查看Pixiv插画、发现与推荐、日榜、周榜、月榜以及搜索作品
-订阅并跟踪画师作品更新
-
-用法:
-/pixiv
-/pixiv发现
-/pixiv推荐 [PID or ArtworkUrl]
-/pixiv日榜 [页码]
-/pixiv周榜 [页码]
-/pixiv月榜 [页码]
-/pixiv用户搜索 [用户昵称]
-/pixiv用户作品 [UID]
-/pixiv用户订阅列表
-/pixiv下载 [页数]
-/pixiv搜索 [关键词]
-
-仅限私聊或群聊中群管理员使用:
-/pixiv用户订阅 [UID]
-/pixiv取消用户订阅 [UID]
-
-搜索命令参数:
-'-c', '--custom': 启用自定义参数
-'-p', '--page': 搜索结果页码
-'-o', '--order': 排序方式, 可选: "date_d", "popular_d"
-'-l', '--like': 筛选最低收藏数
-'-d', '--from-days-ago': 筛选作品发布日期, 从几天前起始发布的作品
-'-s', '--safe-mode': NSFW 模式, 可选: "safe", "all", "r18"'''
+__plugin_meta__ = PluginMetadata(
+ name="Pixiv",
+ description="【Pixiv助手插件】\n"
+ "查看Pixiv插画、发现与推荐、日榜、周榜、月榜以及搜索作品\n"
+ "订阅并跟踪画师作品更新",
+ usage="/pixiv \n"
+ "/pixiv发现\n"
+ "/pixiv推荐 [PID or ArtworkUrl]\n"
+ "/pixiv日榜 [页码]\n"
+ "/pixiv周榜 [页码]\n"
+ "/pixiv月榜 [页码]\n"
+ "/pixiv用户搜索 [用户昵称]\n"
+ "/pixiv用户作品 [UID]\n"
+ "/pixiv用户订阅列表\n"
+ "/pixiv下载 [页数]\n"
+ "/pixiv搜索 [关键词]\n\n"
+ "仅限私聊或群聊中群管理员使用:\n"
+ "/pixiv用户订阅 [UID]\n"
+ "/pixiv取消用户订阅 [UID]\n\n"
+ "搜索命令参数:\n"
+ "'-c', '--custom': 启用自定义参数\n"
+ "'-p', '--page': 搜索结果页码\n"
+ "'-o', '--order': 排序方式, 可选: 'date_d', 'popular_d'\n"
+ "'-l', '--like': 筛选最低收藏数\n"
+ "'-d', '--from-days-ago': 筛选作品发布日期, 从几天前起始发布的作品\n"
+ "'-s', '--safe-mode': NSFW 模式, 可选: 'safe', 'all', 'r18'",
+ config=pixiv_plugin_config.__class__,
+ extra={"author": "Ailitonia"},
+)
_ALLOW_R18_NODE = pixiv_plugin_config.pixiv_plugin_allow_r18_node
@@ -373,7 +373,7 @@ async def handle_parse_success(bot: Bot, event: MessageEvent, matcher: Matcher,
user_cool_down_override=2
),
aliases={'pixiv下载', 'Pixiv下载', 'pixivdl'},
- permission=GROUP,
+ permission=GROUP | PRIVATE_FRIEND,
priority=20,
block=True
)
@@ -395,7 +395,7 @@ async def handle_parse_download_args(state: T_State, cmd_arg: Message = CommandA
@pixiv_download.got('pid', prompt='想要下载哪个作品呢? 请输入作品PID:')
@pixiv_download.got('page', prompt='想要下载作品的哪一页呢? 请输入页码:')
-async def handle_download(bot: Bot, event: GroupMessageEvent, matcher: Matcher,
+async def handle_download(bot: Bot, event: MessageEvent, matcher: Matcher,
pid: str = ArgStr('pid'), page: str = ArgStr('page')):
pid = pid.strip()
page = page.strip()
@@ -428,8 +428,16 @@ async def handle_download(bot: Bot, event: GroupMessageEvent, matcher: Matcher,
gocq_bot = GoCqhttpBot(bot=bot)
file_name = f'{artwork_data.pid}_p{page}_{artwork_data.title}_{artwork_data.uname}{download_file.path.suffix}'
- upload_result = await run_async_catching_exception(gocq_bot.upload_group_file)(
- group_id=event.group_id, file=download_file.resolve_path, name=file_name)
+
+ if isinstance(event, GroupMessageEvent):
+ upload_task = run_async_catching_exception(gocq_bot.upload_group_file)(
+ group_id=event.group_id, file=download_file.resolve_path, name=file_name
+ )
+ else:
+ upload_task = run_async_catching_exception(gocq_bot.upload_private_file)(
+ user_id=event.user_id, file=download_file.resolve_path, name=file_name
+ )
+ upload_result = await upload_task
if isinstance(upload_result, Exception):
logger.warning(f'PixivDownload | 下载作品(pid={pid})失败, 上传群文件失败: {upload_result}')
await matcher.finish('上传图片到群文件失败QAQ, 可能上传仍在进行中, 请等待1~2分钟后再重试')
diff --git a/omega_miya/plugins/pixivsion/__init__.py b/omega_miya/plugins/pixivsion/__init__.py
index 96e3c211..b09d3ca5 100644
--- a/omega_miya/plugins/pixivsion/__init__.py
+++ b/omega_miya/plugins/pixivsion/__init__.py
@@ -8,7 +8,8 @@
@Software : PyCharm
"""
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -27,17 +28,17 @@
from .monitor import scheduler
-# Custom plugin usage text
-__plugin_custom_name__ = 'Pixivision'
-__plugin_usage__ = r'''【Pixivision助手】
-探索并查看Pixivision文章, 订阅最新的Pixivision特辑
-
-用法:
-/pixivision [AID]
-
-仅限私聊或群聊中群管理员使用:
-/pixivision订阅
-/pixivision取消订阅'''
+__plugin_meta__ = PluginMetadata(
+ name="Pixivision",
+ description="【Pixivision助手插件】\n"
+ "探索并查看Pixivision文章\n"
+ "订阅最新的Pixivision特辑",
+ usage="/pixivision [AID]\n\n"
+ "仅限私聊或群聊中群管理员使用:\n"
+ "/pixivision订阅\n"
+ "/pixivision取消订阅",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/repeater/__init__.py b/omega_miya/plugins/repeater/__init__.py
index ce1f7662..3fe692a9 100644
--- a/omega_miya/plugins/repeater/__init__.py
+++ b/omega_miya/plugins/repeater/__init__.py
@@ -1,4 +1,14 @@
-from nonebot import on_message
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : repeater.py
+@Project : nonebot2_miya
+@Description : 复读姬
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot.plugin import on_message, PluginMetadata
from nonebot.exception import FinishedException
from nonebot.adapters.onebot.v11.bot import Bot
from nonebot.adapters.onebot.v11.event import GroupMessageEvent
@@ -7,10 +17,13 @@
from omega_miya.utils.rule import group_has_permission_level
-# Custom plugin usage text
-__plugin_custom_name__ = '复读姬'
-__plugin_usage__ = r'''【复读姬】
-如同人类的本质一样复读'''
+__plugin_meta__ = PluginMetadata(
+ name="复读姬",
+ description="【复读姬插件】\n"
+ "如同人类的本质一样复读",
+ usage="由群聊复读触发",
+ extra={"author": "Ailitonia"},
+)
LAST_MSG: dict[int, str] = {}
diff --git a/omega_miya/plugins/roll/__init__.py b/omega_miya/plugins/roll/__init__.py
index 717b28ce..6a8e0bc0 100644
--- a/omega_miya/plugins/roll/__init__.py
+++ b/omega_miya/plugins/roll/__init__.py
@@ -10,7 +10,7 @@
import re
import random
-from nonebot import on_command
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11.bot import Bot
from nonebot.adapters.onebot.v11.message import Message
@@ -23,16 +23,16 @@
from omega_miya.onebot_api import GoCqhttpBot
-# Custom plugin usage text
-__plugin_custom_name__ = 'Roll'
-__plugin_usage__ = r'''【Roll】
-各种姿势的掷骰子
-选择困难症患者福音
-
-用法:
-/roll d
-/抽奖 <人数>
-/帮我选 [选项1 选项2 ...]'''
+__plugin_meta__ = PluginMetadata(
+ name="Roll",
+ description="【骰子插件】\n"
+ "各种姿势的掷骰子\n"
+ "选择困难症患者福音",
+ usage="/roll d\n"
+ "/抽奖 <人数>\n"
+ "/帮我选 [选项1 选项2 ...]",
+ extra={"author": "Ailitonia"},
+)
_ALL_LOTTERY_NUM: int = 50
diff --git a/omega_miya/plugins/schedule_message/__init__.py b/omega_miya/plugins/schedule_message/__init__.py
index 0a2a59a3..a16237fa 100644
--- a/omega_miya/plugins/schedule_message/__init__.py
+++ b/omega_miya/plugins/schedule_message/__init__.py
@@ -9,7 +9,7 @@
"""
from nonebot.log import logger
-from nonebot.plugin import on_command
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -25,20 +25,18 @@
get_schedule_message_job_list, set_schedule_message_job, remove_schedule_message_job)
-# Custom plugin usage text
-__plugin_custom_name__ = '定时消息'
-__plugin_usage__ = r'''【定时消息】
-设置定时消息
-
-用法:
-/设置定时消息
-/删除定时消息
-/定时消息列表
-
-Crontab格式说明:
- * | * | * | * | *
-分|时|日|月|星期
-'''
+__plugin_meta__ = PluginMetadata(
+ name="定时消息",
+ description="【定时消息插件】\n"
+ "设置定时消息",
+ usage="/设置定时消息\n"
+ "/删除定时消息\n"
+ "/定时消息列表\n\n"
+ "Crontab格式说明:\n"
+ " * | * | * | * | *\n"
+ "分|时|日|月|星期",
+ extra={"author": "Ailitonia"},
+)
set_schedule_message = on_command(
diff --git a/omega_miya/plugins/self_mute/__init__.py b/omega_miya/plugins/self_mute/__init__.py
index f72baf25..bd989c40 100644
--- a/omega_miya/plugins/self_mute/__init__.py
+++ b/omega_miya/plugins/self_mute/__init__.py
@@ -10,7 +10,8 @@
import re
import random
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11.bot import Bot
@@ -24,13 +25,13 @@
from omega_miya.onebot_api import GoCqhttpBot
-# Custom plugin usage text
-__plugin_custom_name__ = '随机口球'
-__plugin_usage__ = r'''【随机口球】
-自取随机口球礼包
-
-用法:
-/随机口球 [n倍]'''
+__plugin_meta__ = PluginMetadata(
+ name="随机口球",
+ description="【随机口球插件】\n"
+ "自取随机口球礼包",
+ usage="/随机口球 [n倍]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/shindan_maker/__init__.py b/omega_miya/plugins/shindan_maker/__init__.py
index 30badc7e..adcc4cd9 100644
--- a/omega_miya/plugins/shindan_maker/__init__.py
+++ b/omega_miya/plugins/shindan_maker/__init__.py
@@ -10,7 +10,8 @@
import re
import datetime
-from nonebot import on_command, on_regex, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_regex, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11.bot import Bot
@@ -27,15 +28,15 @@
from .data_source import ShindanMaker
-# Custom plugin usage text
-__plugin_custom_name__ = 'ShindanMaker'
-__plugin_usage__ = r'''【ShindanMaker 占卜】
-使用ShindanMaker进行各种奇怪的占卜
-只能在群里使用
-就是要公开处刑!
-
-用法:
-/ShindanMaker [占卜名称] [占卜对象名称]'''
+__plugin_meta__ = PluginMetadata(
+ name="ShindanMaker",
+ description="【ShindanMaker 占卜插件】\n"
+ "使用ShindanMaker进行各种奇怪的占卜\n"
+ "只能在群里使用\n"
+ "就是要公开处刑!",
+ usage="/ShindanMaker [占卜名称] [占卜对象名称]",
+ extra={"author": "Ailitonia"},
+)
shindan_maker = on_command(
diff --git a/omega_miya/plugins/sticker_maker/__init__.py b/omega_miya/plugins/sticker_maker/__init__.py
index 6a8ae680..1daee964 100644
--- a/omega_miya/plugins/sticker_maker/__init__.py
+++ b/omega_miya/plugins/sticker_maker/__init__.py
@@ -1,4 +1,15 @@
-from nonebot import on_command, logger
+"""
+@Author : Ailitonia
+@Date : 2022/04/28 20:26
+@FileName : sticker_maker.py
+@Project : nonebot2_miya
+@Description : 表情包插件
+@GitHub : https://github.com/Ailitonia
+@Software : PyCharm
+"""
+
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11.bot import Bot
@@ -17,12 +28,13 @@
from .render import get_render, get_all_render_name, download_source_image
-# Custom plugin usage text
-__plugin_custom_name__ = '表情包'
-__plugin_usage__ = rf'''【表情包助手】
-使用模板快速制作表情包
-
-/表情包 [模板名] [表情包文本] [表情包图片]'''
+__plugin_meta__ = PluginMetadata(
+ name="表情包",
+ description="【表情包助手插件】\n"
+ "使用模板快速制作表情包",
+ usage="/表情包 [模板名] [表情包文本] [表情包图片]",
+ extra={"author": "Ailitonia"},
+)
sticker = on_command(
diff --git a/omega_miya/plugins/sticker_maker/model.py b/omega_miya/plugins/sticker_maker/model.py
index a93ada1d..3fc3e0bf 100644
--- a/omega_miya/plugins/sticker_maker/model.py
+++ b/omega_miya/plugins/sticker_maker/model.py
@@ -9,6 +9,8 @@
"""
import abc
+import imageio
+from typing import Iterable
from datetime import datetime
from io import BytesIO
from PIL import Image
@@ -60,16 +62,37 @@ def need_image(cls) -> bool:
"""是否需要外部图片来作为表情包生成的内容"""
return cls._need_external_img
+ @abc.abstractmethod
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ """静态图片表情包制作方法"""
+ raise NotImplementedError
+
+ @abc.abstractmethod
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ """动态图片表情包制作方法"""
+ raise NotImplementedError
+
@abc.abstractmethod
def _handler(self) -> bytes:
- """表情包制作方法"""
+ """表情包制作入口函数"""
raise NotImplementedError
- def _load_source_image(self) -> Image.Image:
+ def _get_source_image_info(self) -> (str, dict):
+ """获取图片素材格式信息
+
+ :return: format: str, num of frames: int, info: dict
+ """
+ with Image.open(self.source_image.resolve_path) as im:
+ f_im = im.format
+ info = im.info
+ return f_im, info
+
+ def _load_source_image(self, frame: int | None = None) -> Image.Image:
"""载入并初始化图片素材"""
- with self.source_image.open('rb') as f:
- image: Image.Image = Image.open(f)
- image.load()
+ image: Image.Image = Image.open(self.source_image.resolve_path)
+ if frame:
+ image.seek(frame=frame)
+ image.load()
return image
@staticmethod
@@ -122,6 +145,22 @@ def _get_pil_image(image: Image.Image, output_format: str = 'JPEG') -> bytes:
content = bf.getvalue()
return content
+ @staticmethod
+ def _generate_gif_from_bytes_seq(
+ frames: Iterable[bytes],
+ duration: float = 0.06,
+ *,
+ quantizer: int = 2
+ ) -> bytes:
+ """使用图片序列输出 GIF 图像"""
+ frames_list = [imageio.v2.imread(frame) for frame in frames]
+
+ with BytesIO() as bf:
+ imageio.mimsave(bf, frames_list, 'GIF-PIL', duration=duration, quantizer=quantizer)
+ content = bf.getvalue()
+
+ return content
+
async def make(self) -> TmpResource:
"""使用 _handle 方法制作表情包并输出"""
image_content = await run_sync(self._handler)()
diff --git a/omega_miya/plugins/sticker_maker/render.py b/omega_miya/plugins/sticker_maker/render.py
index 5359786a..6113af1a 100644
--- a/omega_miya/plugins/sticker_maker/render.py
+++ b/omega_miya/plugins/sticker_maker/render.py
@@ -8,7 +8,6 @@
@Software : PyCharm
"""
-import imageio
import numpy
from typing import Type, Any
from datetime import date
@@ -43,6 +42,12 @@ class TraitorRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('pixel.ttf')
_default_output_width = 800
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
self.source_image = self._static_resource
image = self._load_source_image()
@@ -89,6 +94,12 @@ class JichouRender(StickerRender):
_static_resource: LocalResource = _STATIC_RESOURCE('jichou', 'default_bg.png')
_font: LocalResource = _FONT_RESOURCE('SourceHanSansSC-Regular.otf')
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
self.source_image = self._static_resource
image = self._load_source_image()
@@ -128,6 +139,12 @@ class PhlogoRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('SourceHanSansSC-Heavy.otf')
_default_font_size = 320
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
# 处理文本主体
test_sentences = self.text.strip().split(maxsplit=1)
@@ -196,6 +213,12 @@ class LuxunSayRender(StickerRender):
_static_resource: LocalResource = _STATIC_RESOURCE('luxunsay', 'default_bg.png')
_font: LocalResource = _FONT_RESOURCE('SourceHanSansSC-Regular.otf')
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
self.source_image = self._static_resource
image = self._load_source_image()
@@ -257,6 +280,12 @@ class LuxunWriteRender(LuxunSayRender):
_sticker_name: str = 'luxunwrite'
_static_resource: LocalResource = _STATIC_RESOURCE('luxunwrite', 'default_bg.png')
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
class JiangzhuangRender(StickerRender):
"""奖状表情包模板
@@ -269,6 +298,12 @@ class JiangzhuangRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('HanYiWeiBeiJian.ttf')
_default_output_width = 1024
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
self.source_image = self._static_resource
image = self._load_source_image()
@@ -304,6 +339,12 @@ class XibaoHorizontalRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('HanYiWeiBeiJian.ttf')
_default_output_width = 1024
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
self.source_image = self._static_resource
image = self._load_source_image()
@@ -343,6 +384,12 @@ class XibaoVerticalRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('SourceHanSerif-Bold.ttc')
_default_output_width = 1024
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
self.source_image = self._static_resource
image = self._load_source_image()
@@ -382,10 +429,7 @@ class DefaultRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('msyhbd.ttc')
_need_external_img: bool = True
- def _handler(self) -> bytes:
- image = self._load_source_image()
- image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
-
+ def _static_handler(self, image: Image) -> bytes:
font_size = image.width // 8
text_stroke_width = int(font_size / 20)
font = ImageFont.truetype(self._font.resolve_path, font_size)
@@ -408,6 +452,35 @@ def _handler(self) -> bytes:
content = self._get_pil_image(image=image)
return content
+ def _gif_handler(self, frames: list[Image], duration: float) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration)
+ else:
+ image = self._load_source_image()
+ image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
+ content = self._static_handler(image=image)
+
+ return content
+
class LittleAngelRender(StickerRender):
"""小天使表情包模板
@@ -420,10 +493,7 @@ class LittleAngelRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('msyhbd.ttc')
_need_external_img: bool = True
- def _handler(self) -> bytes:
- image = self._load_source_image()
- image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
-
+ def _static_handler(self, image: Image) -> bytes:
# 处理文本内容
font_size_up = int(image.width / 7)
font_up = ImageFont.truetype(self._font.resolve_path, font_size_up)
@@ -467,6 +537,35 @@ def _handler(self) -> bytes:
content = self._get_pil_image(image=background)
return content
+ def _gif_handler(self, frames: list[Image], duration: float) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration)
+ else:
+ image = self._load_source_image()
+ image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
+ content = self._static_handler(image=image)
+
+ return content
+
class WhiteBackgroundRender(StickerRender):
"""白底加字表情包模板
@@ -479,10 +578,7 @@ class WhiteBackgroundRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('msyhbd.ttc')
_need_external_img: bool = True
- def _handler(self) -> bytes:
- image = self._load_source_image()
- image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
-
+ def _static_handler(self, image: Image) -> bytes:
font_size = image.width // 10
font = ImageFont.truetype(self._font.resolve_path, font_size)
text_w, text_h = font.getsize_multiline(self.text)
@@ -507,6 +603,35 @@ def _handler(self) -> bytes:
content = self._get_pil_image(image=background)
return content
+ def _gif_handler(self, frames: list[Image], duration: float) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration)
+ else:
+ image = self._load_source_image()
+ image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
+ content = self._static_handler(image=image)
+
+ return content
+
class BlackBackgroundRender(StickerRender):
"""黑边加底字表情包模板
@@ -519,10 +644,7 @@ class BlackBackgroundRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('msyhbd.ttc')
_need_external_img: bool = True
- def _handler(self) -> bytes:
- image = self._load_source_image()
- image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
-
+ def _static_handler(self, image: Image) -> bytes:
font_size = image.width // 8
font = ImageFont.truetype(self._font.resolve_path, font_size)
text_w, text_h = font.getsize_multiline(self.text)
@@ -545,6 +667,35 @@ def _handler(self) -> bytes:
content = self._get_pil_image(image=background)
return content
+ def _gif_handler(self, frames: list[Image], duration: float) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration)
+ else:
+ image = self._load_source_image()
+ image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
+ content = self._static_handler(image=image)
+
+ return content
+
class DeColorizeRender(StickerRender):
"""去色表情包模板
@@ -556,14 +707,41 @@ class DeColorizeRender(StickerRender):
_need_text: bool = False
_need_external_img: bool = True
- def _handler(self) -> bytes:
- image = self._load_source_image()
+ def _static_handler(self, image: Image) -> bytes:
image = image.convert('RGB')
enhancer = ImageEnhance.Color(image)
made_image = enhancer.enhance(0)
content = self._get_pil_image(image=made_image)
return content
+ def _gif_handler(self, frames: list[Image], duration: float) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration)
+ else:
+ image = self._load_source_image()
+ content = self._static_handler(image=image)
+
+ return content
+
class GunjoRender(StickerRender):
"""群青表情包模板
@@ -577,10 +755,8 @@ class GunjoRender(StickerRender):
_default_output_width = 512
_font: LocalResource = _FONT_RESOURCE('SourceHanSansSC-Bold.otf')
- def _handler(self) -> bytes:
- image = self._load_source_image()
+ def _static_handler(self, image: Image) -> bytes:
image = image.convert('RGBA')
- image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
# 图片去色
made_image = ImageEnhance.Color(image).enhance(0)
@@ -613,6 +789,35 @@ def _handler(self) -> bytes:
content = self._get_pil_image(image=background)
return content
+ def _gif_handler(self, frames: list[Image], duration: float) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration)
+ else:
+ image = self._load_source_image()
+ image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
+ content = self._static_handler(image=image)
+
+ return content
+
class MarriageRender(StickerRender):
"""结婚登记表情包模板
@@ -626,17 +831,56 @@ class MarriageRender(StickerRender):
_need_external_img: bool = True
_default_output_width = 1080
- def _handler(self) -> bytes:
- image = self._load_source_image()
- image = self._resize_with_filling(image=image, size=(self._default_output_width, self._default_output_width))
+ def _static_handler(self, image: Image, *, resize_width: int | None = None) -> bytes:
upper_image = self._load_extra_source_image(source_file=self._static_resource)
background = Image.new(mode='RGBA', size=image.size, color=(255, 255, 255, 255))
background.paste(im=image, box=(0, 0), mask=image)
background.paste(im=upper_image, box=(0, 0), mask=upper_image)
+
+ if resize_width:
+ background = self._zoom_pil_image_width(image=background, width=resize_width)
content = self._get_pil_image(image=background)
return content
+ def _gif_handler(self, frames: list[Image], duration: float, output_width: int) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image, resize_width=output_width) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ output_width = 360
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ output_width = image.width
+ image = self._resize_with_filling(
+ image=image,
+ size=(self._default_output_width, self._default_output_width)
+ )
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration, output_width=output_width)
+ else:
+ image = self._load_source_image()
+ image = self._resize_with_filling(
+ image=image,
+ size=(self._default_output_width, self._default_output_width)
+ )
+ content = self._static_handler(image=image)
+
+ return content
+
class GrassJaRender(StickerRender):
"""生草日语表情包模板
@@ -649,12 +893,10 @@ class GrassJaRender(StickerRender):
_font: LocalResource = _FONT_RESOURCE('fzzxhk.ttf')
_need_external_img: bool = True
- def _handler(self) -> bytes:
- image = self._load_source_image()
+ def _static_handler(self, image: Image) -> bytes:
image = image.convert('RGB')
enhancer = ImageEnhance.Color(image)
image = enhancer.enhance(0)
- image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
# 分割文本
font_zh = ImageFont.truetype(self._font.resolve_path, int(image.width / 13))
@@ -685,6 +927,35 @@ def _handler(self) -> bytes:
content = self._get_pil_image(image=background)
return content
+ def _gif_handler(self, frames: list[Image], duration: float) -> bytes:
+ content = self._generate_gif_from_bytes_seq(
+ frames=(self._static_handler(image=image) for image in frames),
+ duration=duration
+ )
+ return content
+
+ def _handler(self) -> bytes:
+ fm, info = self._get_source_image_info()
+ if fm == 'GIF':
+ frames = []
+ frame_index = 0
+ while True:
+ try:
+ image = self._load_source_image(frame=frame_index)
+ frames.append(image)
+ frame_index += 1
+ except EOFError:
+ break
+ duration = info.get('duration', 60) / 1000
+ self._default_output_format = 'gif'
+ content = self._gif_handler(frames=frames, duration=duration)
+ else:
+ image = self._load_source_image()
+ image = self._zoom_pil_image_width(image=image, width=self._default_output_width)
+ content = self._static_handler(image=image)
+
+ return content
+
async def _translate_preprocessor(self) -> None:
text_zh = self.text.replace('\n', ' ')
text_trans_result = await TencentTMT().translate(source_text=self.text, target='ja')
@@ -713,6 +984,12 @@ class PetPetRender(StickerRender):
_need_external_img: bool = True
_default_output_format: str = 'gif'
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
resize_paste_loc: list[tuple[tuple[int, int], tuple[int, int]]] = [
((95, 95), (12, 15)),
@@ -730,12 +1007,9 @@ def _handler(self) -> bytes:
background.paste(frame, (0, 0), mask=frame)
with BytesIO() as f_bf:
background.save(f_bf, format='PNG')
- img_bytes = f_bf.getvalue()
- frames_list.append(imageio.v2.imread(img_bytes))
+ frames_list.append(f_bf.getvalue())
- with BytesIO() as bf:
- imageio.mimsave(bf, frames_list, 'GIF', duration=0.06)
- content = bf.getvalue()
+ content = self._generate_gif_from_bytes_seq(frames=frames_list, duration=0.06)
return content
@@ -772,6 +1046,12 @@ def _get_perspective_data(
res = numpy.dot(numpy.linalg.inv(target_matrix.T * target_matrix) * target_matrix.T, source_array)
return numpy.array(res).reshape(8)
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
image = self._load_source_image()
width, height = image.size
@@ -790,12 +1070,9 @@ def _handler(self) -> bytes:
background.paste(im=frame, box=(0, 0), mask=frame)
with BytesIO() as f_bf:
background.save(f_bf, format='PNG')
- img_bytes = f_bf.getvalue()
- frames_list.append(imageio.v2.imread(img_bytes))
+ frames_list.append(f_bf.getvalue())
- with BytesIO() as bf:
- imageio.mimsave(bf, frames_list, 'GIF', duration=0.04)
- content = bf.getvalue()
+ content = self._generate_gif_from_bytes_seq(frames=frames_list, duration=0.04)
return content
@@ -812,6 +1089,12 @@ class TwistRender(StickerRender):
_need_external_img: bool = True
_default_output_format: str = 'gif'
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
image = self._load_source_image()
image = self._resize_with_filling(image=image, size=(128, 128))
@@ -833,14 +1116,10 @@ def _handler(self) -> bytes:
background.paste(im=frame, box=(0, 0), mask=frame)
with BytesIO() as f_bf:
background.save(f_bf, format='PNG')
- img_bytes = f_bf.getvalue()
- frames_list.append(imageio.v2.imread(img_bytes))
-
+ frames_list.append(f_bf.getvalue())
angle += 36
- with BytesIO() as bf:
- imageio.mimsave(bf, frames_list, 'GIF', duration=0.03)
- content = bf.getvalue()
+ content = self._generate_gif_from_bytes_seq(frames=frames_list, duration=0.03)
return content
@@ -858,6 +1137,12 @@ class WangjingzeRender(StickerRender):
_need_external_img: bool = False
_default_output_format: str = 'gif'
+ def _gif_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
+ def _static_handler(self, *args, **kwargs) -> bytes:
+ raise NotImplementedError
+
def _handler(self) -> bytes:
# 分割文本
text_list = self.text.split(maxsplit=3)
@@ -891,14 +1176,11 @@ def _handler(self) -> bytes:
stroke_width=2, stroke_fill=(0, 0, 0)
)
- with BytesIO() as bf0:
- frame.save(bf0, format='JPEG')
- img_bytes = bf0.getvalue()
- frames_list.append(imageio.v2.imread(img_bytes))
+ with BytesIO() as bf:
+ frame.save(bf, format='JPEG')
+ frames_list.append(bf.getvalue())
- with BytesIO() as bf:
- imageio.mimsave(bf, frames_list, 'GIF', duration=0.13)
- content = bf.getvalue()
+ content = self._generate_gif_from_bytes_seq(frames=frames_list, duration=0.13)
return content
diff --git a/omega_miya/plugins/tarot/__init__.py b/omega_miya/plugins/tarot/__init__.py
index 5b1a2cea..30caa22e 100644
--- a/omega_miya/plugins/tarot/__init__.py
+++ b/omega_miya/plugins/tarot/__init__.py
@@ -9,7 +9,8 @@
"""
import random
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -26,16 +27,15 @@
from .utils import generate_tarot_card, get_tarot_resource_name, set_tarot_resource
-# Custom plugin usage text
-__plugin_custom_name__ = '塔罗牌'
-__plugin_usage__ = r'''【塔罗牌】
-简单的塔罗牌插件
-
-用法:
-/塔罗牌 [卡牌名]
-
-仅限私聊或群聊中群管理员使用:
-/设置塔罗牌组 [资源名]'''
+__plugin_meta__ = PluginMetadata(
+ name="塔罗牌",
+ description="【塔罗牌插件】\n"
+ "简单的塔罗牌插件",
+ usage="/塔罗牌 [卡牌名]\n\n"
+ "仅限私聊或群聊中群管理员使用:\n"
+ "/设置塔罗牌组 [资源名]",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/translate/__init__.py b/omega_miya/plugins/translate/__init__.py
index 19cd50c2..86cd0171 100644
--- a/omega_miya/plugins/translate/__init__.py
+++ b/omega_miya/plugins/translate/__init__.py
@@ -8,7 +8,8 @@
@Software : PyCharm
"""
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.typing import T_State
from nonebot.rule import ArgumentParser
from nonebot.exception import ParserExit
@@ -23,13 +24,14 @@
from omega_miya.web_resource.tencent_cloud import TencentTMT
-# Custom plugin usage text
-__plugin_custom_name__ = '翻译'
-__plugin_usage__ = r'''【翻译插件】
-简单的翻译插件
-目前使用了腾讯云的翻译API
-
-/翻译 [翻译内容]'''
+__plugin_meta__ = PluginMetadata(
+ name="翻译",
+ description="【翻译插件】\n"
+ "简单的翻译插件\n"
+ "目前使用了腾讯云的翻译API",
+ usage="/翻译 [翻译内容]",
+ extra={"author": "Ailitonia"},
+)
translate = on_command(
diff --git a/omega_miya/plugins/what_to_eat/__init__.py b/omega_miya/plugins/what_to_eat/__init__.py
index ce495f46..0e61e422 100644
--- a/omega_miya/plugins/what_to_eat/__init__.py
+++ b/omega_miya/plugins/what_to_eat/__init__.py
@@ -9,7 +9,8 @@
"""
from datetime import datetime
-from nonebot import on_command, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, PluginMetadata
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11.bot import Bot
from nonebot.adapters.onebot.v11.permission import GROUP
@@ -21,17 +22,17 @@
from .model import get_random_food_message
-# Custom plugin usage text
-__plugin_custom_name__ = '今天吃啥'
-__plugin_usage__ = r'''【今天吃啥】
-给吃饭选择困难症一个解决方案
-
-用法:
-/今天吃啥
-/早上吃啥
-/中午吃啥
-/晚上吃啥
-/夜宵吃啥'''
+__plugin_meta__ = PluginMetadata(
+ name="今天吃啥",
+ description="【今天吃啥插件】\n"
+ "给吃饭选择困难症一个解决方案",
+ usage="/今天吃啥\n"
+ "/早上吃啥\n"
+ "/中午吃啥\n"
+ "/晚上吃啥\n"
+ "/夜宵吃啥",
+ extra={"author": "Ailitonia"},
+)
what_eat_today = on_command(
diff --git a/omega_miya/plugins/word_bank/__init__.py b/omega_miya/plugins/word_bank/__init__.py
index dbcdc1ec..591e782b 100644
--- a/omega_miya/plugins/word_bank/__init__.py
+++ b/omega_miya/plugins/word_bank/__init__.py
@@ -8,7 +8,8 @@
@Software : PyCharm
"""
-from nonebot import MatcherGroup, logger
+from nonebot.log import logger
+from nonebot.plugin import MatcherGroup, PluginMetadata
from nonebot.typing import T_State
from nonebot.rule import to_me
from nonebot.matcher import Matcher
@@ -25,20 +26,19 @@
from .word_bank import WordBankManager, WordBankMatcher
-# Custom plugin usage text
-__plugin_custom_name__ = '自动问答'
-__plugin_usage__ = r'''【自动问答】
-使用模糊匹配的轻量化问答插件
-仅限群聊使用
-
-用法:
-@Bot [关键词]
-若匹配成功则会回复
-
-仅限群管理员使用:
-/添加问答
-/删除问答
-/问答列表'''
+__plugin_meta__ = PluginMetadata(
+ name="自动问答",
+ description="【自动问答插件】\n"
+ "使用模糊匹配的轻量化问答插件\n"
+ "仅限群聊使用",
+ usage="@Bot [关键词]\n"
+ "若匹配成功则会回复\n\n"
+ "仅限群管理员使用:\n"
+ "/添加问答\n"
+ "/删除问答\n"
+ "/问答列表",
+ extra={"author": "Ailitonia"},
+)
# 注册事件响应器
diff --git a/omega_miya/plugins/zhoushen_hime/__init__.py b/omega_miya/plugins/zhoushen_hime/__init__.py
index 5200a888..94fa9810 100644
--- a/omega_miya/plugins/zhoushen_hime/__init__.py
+++ b/omega_miya/plugins/zhoushen_hime/__init__.py
@@ -11,7 +11,8 @@
"""
from typing import Literal
-from nonebot import on_command, on_notice, logger
+from nonebot.log import logger
+from nonebot.plugin import on_command, on_notice, PluginMetadata
from nonebot.typing import T_State
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
@@ -29,15 +30,15 @@
from .utils import ZhouChecker, download_file, upload_result_file
-# Custom plugin usage text
-__plugin_custom_name__ = '自动审轴姬'
-__plugin_usage__ = r'''【自动审轴姬】
-检测群内上传文件并自动锤轴
-仅限群聊使用
-
-用法:
-仅限群管理员使用:
-/审轴姬 '''
+__plugin_meta__ = PluginMetadata(
+ name="自动审轴姬",
+ description="【自动审轴姬插件】\n"
+ "检测群内上传文件并自动锤轴\n"
+ "仅限群聊使用",
+ usage="仅限群管理员使用:\n"
+ "/审轴姬 ",
+ extra={"author": "Ailitonia"},
+)
_ZHOUSHEN_HIME_CUSTOM_MODULE_NAME: Literal['Omega.ZhoushenHime'] = 'Omega.ZhoushenHime'
diff --git a/omega_miya/service/gocqhttp_guild_patch/__init__.py b/omega_miya/service/gocqhttp_guild_patch/__init__.py
index 764c7414..99905023 100644
--- a/omega_miya/service/gocqhttp_guild_patch/__init__.py
+++ b/omega_miya/service/gocqhttp_guild_patch/__init__.py
@@ -3,8 +3,15 @@
from nonebot.adapters.onebot.v11 import Bot, Event, Message, MessageSegment
from nonebot.log import logger
-from .models import (GuildMessageEvent, GuildChannelRecallNoticeEvent, MessageReactionsUpdatedNoticeEvent,
- ChannelUpdatedNoticeEvent, ChannelCreatedNoticeEvent, ChannelDestroyedNoticeEvent)
+from .models import (
+ ChannelCreatedNoticeEvent,
+ ChannelDestroyedNoticeEvent,
+ ChannelNoticeEvent,
+ ChannelUpdatedNoticeEvent,
+ GuildChannelRecallNoticeEvent,
+ GuildMessageEvent,
+ MessageReactionsUpdatedNoticeEvent,
+)
from .permission import GUILD, GUILD_SUPERUSER
original_send = Bot.send
@@ -47,12 +54,13 @@ async def patched_send(
__all__ = [
- 'GUILD',
- 'GUILD_SUPERUSER',
- 'GuildMessageEvent',
- 'GuildChannelRecallNoticeEvent',
- 'MessageReactionsUpdatedNoticeEvent',
- 'ChannelUpdatedNoticeEvent',
- 'ChannelCreatedNoticeEvent',
- 'ChannelDestroyedNoticeEvent'
+ "GUILD",
+ "GUILD_SUPERUSER",
+ "GuildMessageEvent",
+ "ChannelNoticeEvent",
+ "GuildChannelRecallNoticeEvent",
+ "MessageReactionsUpdatedNoticeEvent",
+ "ChannelUpdatedNoticeEvent",
+ "ChannelCreatedNoticeEvent",
+ "ChannelDestroyedNoticeEvent",
]
diff --git a/omega_miya/service/gocqhttp_guild_patch/models.py b/omega_miya/service/gocqhttp_guild_patch/models.py
index 4486a7b1..9acc2a88 100644
--- a/omega_miya/service/gocqhttp_guild_patch/models.py
+++ b/omega_miya/service/gocqhttp_guild_patch/models.py
@@ -1,4 +1,3 @@
-import inspect
from typing import List, Optional, Type, TypeVar
from nonebot.adapters.onebot.v11 import (
@@ -6,14 +5,14 @@
Event,
Message,
MessageEvent,
+ MessageSegment,
NoticeEvent,
- MessageSegment
)
+from nonebot.exception import NoLogException
from nonebot.log import logger
from nonebot.typing import overrides
from nonebot.utils import escape_tag
-from nonebot.exception import NoLogException
-from pydantic import BaseModel, Field, parse_obj_as, validator, root_validator
+from pydantic import BaseModel, Field, parse_obj_as, root_validator, validator
from typing_extensions import Literal
from .config import guild_patch_config
@@ -25,7 +24,7 @@ def register_event(event: Event_T) -> Event_T:
Adapter.add_custom_model(event)
logger.opt(colors=True).debug(
f"Custom event {event.__qualname__!r} registered "
- f"from module {inspect.getmodule(event).__name__!r}"
+ f"from module {event.__class__.__module__!r}"
)
return event
@@ -33,6 +32,7 @@ def register_event(event: Event_T) -> Event_T:
@register_event
class GuildMessageEvent(MessageEvent):
"""收到频道消息"""
+
message_type: Literal["guild"]
self_tiny_id: int
message_id: str
@@ -42,35 +42,38 @@ class GuildMessageEvent(MessageEvent):
raw_message: str = Field(alias="message")
font: None = None
- @validator('raw_message', pre=True)
+ @validator("raw_message", pre=True)
def _validate_raw_message(cls, raw_message):
if isinstance(raw_message, str):
return raw_message
elif isinstance(raw_message, list):
return str(parse_obj_as(Message, raw_message))
- raise ValueError('unknown raw message type')
+ raise ValueError("unknown raw message type")
@root_validator(pre=False)
def _validate_is_tome(cls, values):
- message = values.get('message')
- self_tiny_id = values.get('self_tiny_id')
+ message = values.get("message")
+ self_tiny_id = values.get("self_tiny_id")
message, is_tome = cls._check_at_me(message=message, self_tiny_id=self_tiny_id)
- values.update({'message': message, 'to_me': is_tome, 'raw_message': str(message)})
+ values.update(
+ {"message": message, "to_me": is_tome, "raw_message": str(message)}
+ )
return values
@overrides(Event)
def is_tome(self) -> bool:
return self.to_me or any(
- str(msg_seg.data.get('qq', '')) == str(self.self_tiny_id)
+ str(msg_seg.data.get("qq", "")) == str(self.self_tiny_id)
for msg_seg in self.message
- if msg_seg.type == 'at'
+ if msg_seg.type == "at"
)
@overrides(Event)
def get_event_description(self) -> str:
return (
- f'Message {self.message_id} from {self.user_id}@[频道:{self.guild_id}/子频道:{self.channel_id}] "'
- + "".join(
+ f"Message {self.message_id} from "
+ f'{self.user_id}@[Guild:{self.guild_id}/Channel:{self.channel_id}] "%s"'
+ % "".join(
map(
lambda x: escape_tag(str(x))
if x.is_text()
@@ -78,7 +81,6 @@ def get_event_description(self) -> str:
self.message,
)
)
- + '"'
)
def get_log_string(self) -> str:
@@ -92,15 +94,17 @@ def get_session_id(self) -> str:
return f"guild_{self.guild_id}_channel_{self.channel_id}_{self.user_id}"
@staticmethod
- def _check_at_me(message: Message, self_tiny_id: int | str) -> tuple[Message, bool]:
- """检查消息开头或结尾是否存在 @机器人,去除并赋值 ``event.to_me``"""
+ def _check_at_me(message: Message, self_tiny_id: int) -> tuple[Message, bool]:
+ """检查消息开头或结尾是否存在 @机器人,去除并赋值 event.to_me"""
is_tome = False
# ensure message not empty
if not message:
message.append(MessageSegment.text(""))
def _is_at_me_seg(segment: MessageSegment):
- return segment.type == 'at' and str(segment.data.get('qq', '')) == str(self_tiny_id)
+ return segment.type == "at" and str(segment.data.get("qq", "")) == str(
+ self_tiny_id
+ )
# check the first segment
if _is_at_me_seg(message[0]):
@@ -113,9 +117,7 @@ def _is_at_me_seg(segment: MessageSegment):
if message and _is_at_me_seg(message[0]):
message.pop(0)
if message and message[0].type == "text":
- message[0].data["text"] = (
- message[0].data["text"].lstrip()
- )
+ message[0].data["text"] = message[0].data["text"].lstrip()
if not message[0].data["text"]:
del message[0]
@@ -124,9 +126,9 @@ def _is_at_me_seg(segment: MessageSegment):
i = -1
last_msg_seg = message[i]
if (
- last_msg_seg.type == "text"
- and not last_msg_seg.data["text"].strip()
- and len(message) >= 2
+ last_msg_seg.type == "text"
+ and not last_msg_seg.data["text"].strip()
+ and len(message) >= 2
):
i -= 1
last_msg_seg = message[i]
@@ -156,12 +158,12 @@ class Config:
@register_event
class ChannelNoticeEvent(NoticeEvent):
"""频道通知事件"""
+
notice_type: Literal["channel"]
self_tiny_id: int
guild_id: int
channel_id: int
user_id: int
-
sub_type: None = None
def get_log_string(self) -> str:
@@ -174,6 +176,7 @@ def get_log_string(self) -> str:
@register_event
class GuildChannelRecallNoticeEvent(ChannelNoticeEvent):
"""频道消息撤回"""
+
notice_type: Literal["guild_channel_recall"]
operator_id: int
message_id: str
@@ -188,6 +191,7 @@ def get_log_string(self) -> str:
@register_event
class MessageReactionsUpdatedNoticeEvent(ChannelNoticeEvent):
"""频道消息表情贴更新"""
+
notice_type: Literal["message_reactions_updated"]
message_id: str
current_reactions: Optional[List[ReactionInfo]] = None
@@ -229,6 +233,7 @@ class Config:
@register_event
class ChannelUpdatedNoticeEvent(ChannelNoticeEvent):
"""子频道信息更新"""
+
notice_type: Literal["channel_updated"]
operator_id: int
old_info: ChannelInfo
@@ -244,6 +249,7 @@ def get_log_string(self) -> str:
@register_event
class ChannelCreatedNoticeEvent(ChannelNoticeEvent):
"""子频道创建"""
+
notice_type: Literal["channel_created"]
operator_id: int
channel_info: ChannelInfo
@@ -258,6 +264,7 @@ def get_log_string(self) -> str:
@register_event
class ChannelDestroyedNoticeEvent(ChannelNoticeEvent):
"""子频道删除"""
+
notice_type: Literal["channel_destroyed"]
operator_id: int
channel_info: ChannelInfo
@@ -270,14 +277,14 @@ def get_log_string(self) -> str:
__all__ = [
- 'GuildMessageEvent',
- 'ChannelNoticeEvent',
- 'GuildChannelRecallNoticeEvent',
- 'MessageReactionsUpdatedNoticeEvent',
- 'ChannelUpdatedNoticeEvent',
- 'ChannelCreatedNoticeEvent',
- 'ChannelDestroyedNoticeEvent',
- 'ReactionInfo',
- 'SlowModeInfo',
- 'ChannelInfo'
+ "GuildMessageEvent",
+ "ChannelNoticeEvent",
+ "GuildChannelRecallNoticeEvent",
+ "MessageReactionsUpdatedNoticeEvent",
+ "ChannelUpdatedNoticeEvent",
+ "ChannelCreatedNoticeEvent",
+ "ChannelDestroyedNoticeEvent",
+ "ReactionInfo",
+ "SlowModeInfo",
+ "ChannelInfo",
]
diff --git a/omega_miya/service/gocqhttp_guild_patch/permission.py b/omega_miya/service/gocqhttp_guild_patch/permission.py
index de713735..67a84059 100644
--- a/omega_miya/service/gocqhttp_guild_patch/permission.py
+++ b/omega_miya/service/gocqhttp_guild_patch/permission.py
@@ -8,8 +8,9 @@
@Software : PyCharm
"""
-from nonebot.permission import Permission
from nonebot.adapters.onebot.v11.bot import Bot
+from nonebot.permission import Permission
+
from .models import GuildMessageEvent
@@ -18,9 +19,11 @@ async def _guild(event: GuildMessageEvent) -> bool:
async def _guild_superuser(bot: Bot, event: GuildMessageEvent) -> bool:
- return (f"{bot.adapter.get_name().split(maxsplit=1)[0].lower()}:{event.get_user_id()}"
- in bot.config.superusers
- or event.get_user_id() in bot.config.superusers) # 兼容旧配置
+ return (
+ f"{bot.adapter.get_name().split(maxsplit=1)[0].lower()}:{event.get_user_id()}"
+ in bot.config.superusers
+ or event.get_user_id() in bot.config.superusers
+ ) # 兼容旧配置
GUILD: Permission = Permission(_guild)
@@ -29,7 +32,4 @@ async def _guild_superuser(bot: Bot, event: GuildMessageEvent) -> bool:
"""匹配任意超级用户频道消息类型事件"""
-__all__ = [
- 'GUILD',
- 'GUILD_SUPERUSER'
-]
+__all__ = ["GUILD", "GUILD_SUPERUSER"]
\ No newline at end of file
diff --git a/omega_miya/service/omega_processor/history.py b/omega_miya/service/omega_processor/history.py
index 19b9294e..30dc3590 100644
--- a/omega_miya/service/omega_processor/history.py
+++ b/omega_miya/service/omega_processor/history.py
@@ -24,8 +24,8 @@ async def postprocessor_history(event: Event):
self_id = str(event.self_id)
event_type = getattr(event, 'post_type', 'Undefined')
message_id = getattr(event, 'message_id', -1)
- raw_data = repr(event)
- message_data = str(getattr(event, 'message', ''))
+ raw_data = event.json()
+ message_data = getattr(event, 'message', '')
raw_data = str(raw_data) if not isinstance(raw_data, str) else raw_data
msg_data = str(message_data) if not isinstance(message_data, str) else message_data
diff --git a/omega_miya/service/omega_processor/plugin.py b/omega_miya/service/omega_processor/plugin.py
index 7e72fff8..8b9cddc2 100644
--- a/omega_miya/service/omega_processor/plugin.py
+++ b/omega_miya/service/omega_processor/plugin.py
@@ -24,10 +24,11 @@
async def startup_init_plugins():
- tasks = [Plugin(
- plugin_name=plugin.name,
- module_name=plugin.module_name
- ).add_only(info=getattr(plugin.module, '__plugin_custom_name__', None)) for plugin in get_loaded_plugins()]
+ tasks = [
+ Plugin(plugin_name=plugin.name, module_name=plugin.module_name).add_only(
+ info=(plugin.metadata.name if plugin.metadata else None)
+ ) for plugin in get_loaded_plugins()
+ ]
plugins_init_result = await semaphore_gather(tasks=tasks, semaphore_num=1)
diff --git a/omega_miya/service/omega_processor/statistic.py b/omega_miya/service/omega_processor/statistic.py
index 4d847122..ef605b3c 100644
--- a/omega_miya/service/omega_processor/statistic.py
+++ b/omega_miya/service/omega_processor/statistic.py
@@ -45,10 +45,10 @@ async def postprocessor_statistic(matcher: Matcher, bot: Bot, event: Event):
return
# 跳过没有配置自定义名称的(一般来说这样的插件也不用展示统计信息)
- custom_plugin_name = getattr(matcher.plugin.module, '__plugin_custom_name__', None)
- if custom_plugin_name is None:
- logger.opt(colors=True).debug(f'{_log_prefix}Non-custom-name plugin, ignore')
+ if matcher.plugin.metadata is None:
+ logger.opt(colors=True).debug(f'{_log_prefix}Non-metadata plugin, ignore')
return
+ custom_plugin_name = matcher.plugin.metadata.name
# 从 state 中解析 processor 配置要求
module_name = matcher.plugin.module_name
diff --git a/omega_miya/utils/message_tools/__init__.py b/omega_miya/utils/message_tools/__init__.py
index 5f6444b9..ed9813af 100644
--- a/omega_miya/utils/message_tools/__init__.py
+++ b/omega_miya/utils/message_tools/__init__.py
@@ -14,7 +14,7 @@
from nonebot.log import logger
from nonebot.adapters.onebot.v11.bot import Bot
from nonebot.adapters.onebot.v11.message import Message, MessageSegment
-from nonebot.adapters.onebot.v11.event import Event
+from nonebot.adapters.onebot.v11.event import Event, GroupMessageEvent, PrivateMessageEvent
from omega_miya.onebot_api import GoCqhttpBot
from omega_miya.database import EventEntityHelper
@@ -142,6 +142,10 @@ async def send_group_node_custom_and_recall(
message_list=message_list)
sent_result = await self.bot.send_group_forward_msg(group_id=group_id, messages=node_message)
+
+ if recall_time <= 0:
+ return sent_result.message_id
+
await asyncio.sleep(recall_time)
await self.bot.delete_msg(message_id=sent_result.message_id)
return sent_result.message_id
@@ -177,6 +181,10 @@ async def send_private_node_custom_and_recall(
message_list=message_list)
sent_result = await self.bot.send_private_forward_msg(user_id=user_id, messages=node_message)
+
+ if recall_time <= 0:
+ return sent_result.message_id
+
await asyncio.sleep(recall_time)
await self.bot.delete_msg(message_id=sent_result.message_id)
return sent_result.message_id
@@ -187,6 +195,7 @@ async def send_node_custom(
message_list: list[str | Message | MessageSegment],
user_id: int | str | None = None,
group_id: int | str | None = None,
+ event: Event | None = None,
*,
custom_nickname: str = 'Ωμεγα_Μιγα'
) -> int:
@@ -195,7 +204,13 @@ async def send_node_custom(
node_message = self._construct_node_custom(custom_user_id=self.bot.self_id, custom_nickname=custom_nickname,
message_list=message_list)
- sent_result = await self.bot.send_forward_msg(user_id=user_id, group_id=group_id, messages=node_message)
+ if isinstance(event, GroupMessageEvent):
+ sent_result = await self.bot.send_group_forward_msg(group_id=event.group_id, messages=node_message)
+ elif isinstance(event, PrivateMessageEvent):
+ sent_result = await self.bot.send_private_forward_msg(user_id=event.user_id, messages=node_message)
+ else:
+ sent_result = await self.bot.send_forward_msg(user_id=user_id, group_id=group_id, messages=node_message)
+
return sent_result.message_id
@run_async_catching_exception
@@ -204,6 +219,7 @@ async def send_node_custom_and_recall(
message_list: list[str | Message | MessageSegment],
user_id: int | str | None = None,
group_id: int | str | None = None,
+ event: Event | None = None,
*,
recall_time: int = 30,
custom_nickname: str = 'Ωμεγα_Μιγα'
@@ -213,7 +229,16 @@ async def send_node_custom_and_recall(
node_message = self._construct_node_custom(custom_user_id=self.bot.self_id, custom_nickname=custom_nickname,
message_list=message_list)
- sent_result = await self.bot.send_forward_msg(user_id=user_id, group_id=group_id, messages=node_message)
+ if isinstance(event, GroupMessageEvent):
+ sent_result = await self.bot.send_group_forward_msg(group_id=event.group_id, messages=node_message)
+ elif isinstance(event, PrivateMessageEvent):
+ sent_result = await self.bot.send_private_forward_msg(user_id=event.user_id, messages=node_message)
+ else:
+ sent_result = await self.bot.send_forward_msg(user_id=user_id, group_id=group_id, messages=node_message)
+
+ if recall_time <= 0:
+ return sent_result.message_id
+
await asyncio.sleep(recall_time)
await self.bot.delete_msg(message_id=sent_result.message_id)
return sent_result.message_id
@@ -243,6 +268,9 @@ async def send_msgs_and_recall(
logger.opt(colors=True).debug(f'MessageSender| Message({", ".join(str(x) for x in sent_msg_id)}) '
f'will be auto-recalled after {recall_time} seconds')
+ if recall_time <= 0:
+ return sent_msg_id
+
await asyncio.sleep(recall_time)
delete_tasks = [self.bot.delete_msg(message_id=msg_id) for msg_id in sent_msg_id]
diff --git a/omega_miya/web_resource/bilibili/model/dynamic.py b/omega_miya/web_resource/bilibili/model/dynamic.py
index 894dfa15..046dd35e 100644
--- a/omega_miya/web_resource/bilibili/model/dynamic.py
+++ b/omega_miya/web_resource/bilibili/model/dynamic.py
@@ -176,7 +176,7 @@ def output_std_model(self) -> _StdCardOutputData:
class CardType16ShortVideo(_BaseCardType):
- """Bilibili 动态 Card Type 16 小视频动态(大概已废弃)"""
+ """Bilibili 动态 Card Type 16 小视频动态 (可能已废弃)"""
class _Item(BaseBilibiliModel):
"""内部内容信息字段"""
@@ -195,7 +195,7 @@ def output_std_model(self) -> _StdCardOutputData:
class CardType32Anime(_BaseCardType):
- """Bilibili 动态 Card Type 32 番剧动态(大概已废弃)"""
+ """Bilibili 动态 Card Type 32 番剧动态 (可能已废弃)"""
verify_type: int = 32
title: str
dynamic: str
@@ -271,7 +271,7 @@ def output_std_model(self) -> _StdCardOutputData:
class CardType512Anime(_BaseCardType):
- """Bilibili 动态 Card Type 512 番剧更新动态(已废弃)"""
+ """Bilibili 动态 Card Type 512 番剧更新动态 (可能已废弃)"""
class _ApiSeasonInfo(BaseBilibiliModel):
title: str
@@ -317,7 +317,7 @@ def output_std_model(self) -> _StdCardOutputData:
class CardType4200LiveRoom(_BaseCardType):
- """Bilibili 动态 Card Type 4200 直播间动态(疑似)"""
+ """Bilibili 动态 Card Type 4200 直播间动态 (可能已废弃)"""
verify_type: int = 4200
uname: str
title: str
@@ -333,8 +333,40 @@ def output_std_model(self) -> _StdCardOutputData:
return _StdCardOutputData.parse_obj({'content': content, 'text': text, 'img_urls': [self.cover]})
+class CardType4300MediaListShare(_BaseCardType):
+ """Bilibili 动态 Card Type 4300 收藏夹/播放列表分享"""
+
+ class _Upper(BaseBilibiliModel):
+ """内部上传用户信息字段"""
+ mid: int
+ name: str
+ face: AnyHttpUrl
+
+ verify_type: int = 4300
+ cover: AnyHttpUrl
+ cover_type: int
+ fid: int
+ id: int
+ intro: str
+ media_count: int
+ mid: int
+ sharable: bool
+ title: str
+ type: int
+ upper: _Upper
+
+ @property
+ def user_name(self) -> str:
+ return self.upper.name
+
+ def output_std_model(self) -> _StdCardOutputData:
+ content = f'《{self.title}》\n{self.intro}\n- 共{self.media_count}个内容'
+ text = f'{self.user_name}分享了收藏夹和播放列表!\n\n{content}\n'
+ return _StdCardOutputData.parse_obj({'content': content, 'text': text, 'img_urls': [self.cover]})
+
+
class CardType4308LiveRoom(_BaseCardType):
- """Bilibili 动态 Card Type 4308 直播间动态(基本确定)(最近出现的)"""
+ """Bilibili 动态 Card Type 4308 直播间动态"""
class _LivePlayInfo(BaseBilibiliModel):
area_id: int
@@ -398,6 +430,7 @@ class _Item(BaseBilibiliModel):
Json[CardType512Anime] |
Json[CardType2048Active] |
Json[CardType4200LiveRoom] |
+ Json[CardType4300MediaListShare] |
Json[CardType4308LiveRoom]
)] # 被转发动态信息, 套娃, (注意多次转发后原动态一直是最开始的那个, 所以源动态类型不可能也是转发)
origin_user: Optional[BilibiliDynamicCardDescUserProfile] # 被转发用户信息
@@ -432,6 +465,7 @@ class BilibiliDynamicCard(BaseBilibiliModel):
Json[CardType512Anime] |
Json[CardType2048Active] |
Json[CardType4200LiveRoom] |
+ Json[CardType4300MediaListShare] |
Json[CardType4308LiveRoom]
)
diff --git a/omega_miya/web_resource/bilibili/model/user.py b/omega_miya/web_resource/bilibili/model/user.py
index 06dbe87d..0a7afc22 100644
--- a/omega_miya/web_resource/bilibili/model/user.py
+++ b/omega_miya/web_resource/bilibili/model/user.py
@@ -34,7 +34,7 @@ class BilibiliUserDataModel(BaseBilibiliModel):
sign: str
level: int
top_photo: AnyHttpUrl
- live_room: BilibiliUserLiveRoom
+ live_room: Optional[BilibiliUserLiveRoom]
is_senior_member: int
diff --git a/omega_miya/web_resource/pixiv/helper.py b/omega_miya/web_resource/pixiv/helper.py
index 78894e68..e1a9f165 100644
--- a/omega_miya/web_resource/pixiv/helper.py
+++ b/omega_miya/web_resource/pixiv/helper.py
@@ -153,8 +153,8 @@ def parse_pixivision_article_page(content: str, root_url: str) -> PixivisionArti
article_title = article_main.find(name='h1', attrs={'class': 'am__title'}).get_text(strip=True)
article_description = article_main.find(
name='div', attrs={'class': 'am__description _medium-editor-text'}).get_text(strip=True)
- article_eyecatch = article_main.find(name='img', attrs={'class': 'aie__image'})
- article_eyecatch_image = None if article_eyecatch is None else article_eyecatch.attrs.get('src')
+ article_eyecatch = article_main.find(name='div', attrs={'class': '_article-illust-eyecatch'})
+ article_eyecatch_image = None if article_eyecatch is None else article_eyecatch.find('img').attrs.get('src')
# 解析tag
tags_list = []
diff --git a/omega_miya/web_resource/pixiv/pixiv.py b/omega_miya/web_resource/pixiv/pixiv.py
index d8b2c169..5c2d92f8 100644
--- a/omega_miya/web_resource/pixiv/pixiv.py
+++ b/omega_miya/web_resource/pixiv/pixiv.py
@@ -3,7 +3,7 @@
import zipfile
import imageio
import asyncio
-from datetime import datetime, timedelta
+from datetime import datetime
from typing import Literal, Optional
from urllib.parse import urlparse, quote
from io import BytesIO
@@ -185,9 +185,8 @@ async def search(
@classmethod
async def search_by_default_popular_condition(cls, word: str) -> PixivSearchingResultModel:
- """Pixiv 搜索 (使用通用的好图筛选条件) (近三年的图) (会用到仅限pixiv高级会员可用的部分参数)"""
- start_date = datetime.now() - timedelta(days=1080)
- return await cls.search(word=word, mode='illustrations', order='date_d', scd_=start_date, blt_=2500)
+ """Pixiv 搜索 (使用热度作为过滤条件筛选条件) (需要pixiv高级会员)"""
+ return await cls.search(word=word, mode='illustrations', order='popular_d', mode_='safe', type_='illust')
@classmethod
async def search_with_preview(
diff --git a/requirements.txt b/requirements.txt
index 4848aef0..60b45954 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,25 +1,25 @@
-nonebot2==2.0.0b3
+nonebot2==2.0.0b5
nonebot-adapter-onebot==2.1.1
-fastapi==0.78.0
+fastapi==0.79.0
pydantic==1.9.1
APScheduler~=3.9.1
pytz~=2022.1
aiohttp~=3.8.1
-SQLAlchemy~=1.4.37
+SQLAlchemy~=1.4.40
asyncmy~=0.2.5
aiomysql~=0.1.1
aiofiles==0.8.0
-ujson~=5.3.0
+ujson~=5.4.0
beautifulsoup4~=4.11.1
bs4~=0.0.1
-lxml~=4.9.0
-numpy~=1.22.4
+lxml~=4.9.1
+numpy~=1.23.1
matplotlib~=3.5.2
-Pillow~=9.1.1
-imageio~=2.19.3
+Pillow~=9.2.0
+imageio~=2.21.1
msgpack~=1.0.4
-pycryptodome~=3.14.1
-py7zr~=0.18.9
+pycryptodome~=3.15.0
+py7zr~=0.20.0
zhconv~=1.4.3
-rapidfuzz~=2.0.11
-emoji~=1.7.0
\ No newline at end of file
+rapidfuzz~=2.4.3
+emoji~=2.0.0
\ No newline at end of file