diff --git a/Guess_voice/__init__.py b/Guess_voice/__init__.py index b8c31d2..60207d5 100644 --- a/Guess_voice/__init__.py +++ b/Guess_voice/__init__.py @@ -1,11 +1,14 @@ import asyncio from pathlib import Path +from typing import Union from nonebot import on_command -from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageSegment, Bot, MessageEvent +from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent, MessageSegment, Bot, MessageEvent, \ + Message from nonebot.exception import FinishedException from nonebot.params import CommandArg from nonebot.permission import SUPERUSER +from nonebot.plugin import PluginMetadata from utils.config import config from . import download_data @@ -16,22 +19,34 @@ setting_time = config.paimon_guess_voice # 游戏持续时间 dir_name = Path() / 'data' / 'LittlePaimon' / 'guess_voice' / 'voice' -__paimon_help__ = { - 'type': '娱乐', - 'range': ['group'] -} + +__plugin_meta__ = PluginMetadata( + name="原神猜语音", + description="小派蒙的原神猜语音模块", + usage=( + "原神猜语音[语言]\n" + "原神语音[语言]<角色名>\n" + "更新原神语音资源\n" + ), + extra={ + 'type': '娱乐', + 'range': ['private', 'group'], + "author": "惜月 <277073121@qq.com>", + "version": "1.0.0", + }, +) guess_game = on_command('原神猜语音', priority=12, block=True) guess_game.__paimon_help__ = { - "usage": "原神猜语音[语言]", + "usage": "原神猜语音[语言]", "introduce": "来一起猜语音吧", - "priority": 5 + "priority": 5 } ys_voice = on_command('原神语音', priority=12, block=True) ys_voice.__paimon_help__ = { - "usage": "原神语音[语言]<角色名>", + "usage": "原神语音[语言]<角色名>", "introduce": "随机发一条该角色的语音", - "priority": 6 + "priority": 6 } update_ys_voice = on_command('更新原神语音资源', priority=12, permission=SUPERUSER, block=True) @@ -45,9 +60,9 @@ async def download_voice(bot: Bot, event: MessageEvent): @guess_game.handle() -async def guess_genshin_voice(bot: Bot, event: GroupMessageEvent, msg=CommandArg()): +async def guess_genshin_voice(bot: Bot, event: GroupMessageEvent, msg: Message = CommandArg()): await download_voice(bot, event) - keyword = str(msg).strip() + keyword = msg.extract_plain_text().strip() guess = Guess(event.group_id, time=setting_time) hard_mode = False @@ -85,13 +100,20 @@ async def guess_genshin_voice(bot: Bot, event: GroupMessageEvent, msg=CommandArg @ys_voice.handle() -async def get_genshin_voice(bot: Bot, event: GroupMessageEvent, msg=CommandArg()): - name = str(msg).strip() +async def get_genshin_voice(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent], msg: Message = CommandArg()): + name = msg.extract_plain_text().strip() if name.startswith('日'): language = '日' name = name[1:] + elif name.startswith('韩'): + language = '韩' + name = name[1:] + elif name.startswith('英'): + language = '英' + name = name[1:] else: language = '中' + name = name.replace('中', '') await download_voice(bot, event) path = await get_random_voice(name, language) if not path: @@ -100,7 +122,7 @@ async def get_genshin_voice(bot: Bot, event: GroupMessageEvent, msg=CommandArg() @update_ys_voice.handle() -async def update_genshin_voice(bot: Bot, event: GroupMessageEvent): +async def update_genshin_voice(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent]): await update_ys_voice.send('将在后台开始更新原神语音资源,请耐心等待资源下载完成后再使用原神语音') await download_data.update_voice_data() await update_ys_voice.finish('原神语音资源更新完成') diff --git a/Paimon_Calendar/__init__.py b/Paimon_Calendar/__init__.py index 5b9f043..9126688 100644 --- a/Paimon_Calendar/__init__.py +++ b/Paimon_Calendar/__init__.py @@ -1,32 +1,37 @@ from nonebot import require, get_bot, on_command, logger from nonebot.adapters.onebot.v11 import MessageEvent, Message from nonebot.params import CommandArg +from nonebot.plugin import PluginMetadata from utils.file_handler import load_json, save_json from utils.message_util import MessageBuild, get_message_id from .generate import * import re -HELP_STR = ''' -原神活动日历 -原神日历 : 查看本群订阅服务器日历 -原神日历 on/off : 订阅/取消订阅指定服务器的日历推送 -原神日历 time 时:分 : 设置日历推送时间 -原神日历 status : 查看本群日历推送设置 -'''.strip() +require('nonebot_plugin_apscheduler') +from nonebot_plugin_apscheduler import scheduler -__paimon_help__ = { - 'type': '原神Wiki', - 'range': ['private', 'group', 'guild'] -} +__plugin_meta__ = PluginMetadata( + name="原神日历", + description="查看原神活动日历", + usage=( + "原神日历 : 查看本群订阅服务器日历\n" + "原神日历 on 时间/off : 订阅/取消订阅指定服务器的日历推送\n" + ), + extra={ + 'type': '原神Wiki', + 'range': ['private', 'group', 'guild'], + "author": "nicklly <1134741727@qq.com>", + "version": "1.0.0", + }, +) calendar = on_command('原神日历', aliases={"原神日历", 'ysrl', '原神日程'}, priority=24, block=True) calendar.__paimon_help__ = { - "usage": "原神日历", + "usage": "原神日历", "introduce": "查看原神活动日历,后加on时间/off可以开启定时推送", - "priority": 99 + "priority": 99 } -scheduler = require('nonebot_plugin_apscheduler').scheduler async def send_calendar(push_id, push_data): diff --git a/Paimon_Chat/Learning_repeate/main.py b/Paimon_Chat/Learning_repeate/main.py index aeba579..356f51a 100644 --- a/Paimon_Chat/Learning_repeate/main.py +++ b/Paimon_Chat/Learning_repeate/main.py @@ -20,12 +20,14 @@ from utils.config import config message_id_lock = threading.Lock() message_id_dict = {} -#检测是否开启该群的机器学习 + +# 检测是否开启该群的机器学习 def checkGroup(event: GroupMessageEvent) -> bool: if event.group_id in Chat.learningGroup: return True return False + async def check_accounts(event: GroupMessageEvent) -> bool: # 不响应其他nonebot_plugin_gocqhttp机器人账号的信息 if os.path.exists('accounts'): @@ -40,7 +42,7 @@ async def get_answer(event: GroupMessageEvent, state: T_State) -> bool: # 不响应被屏蔽的人的信息 if event.user_id in config.paimon_chat_ban: return False - elif not checkGroup(event): # 判断群组 + elif not checkGroup(event): # 判断群组 return False chat: Chat = Chat(event) to_learn = True @@ -91,7 +93,6 @@ async def is_shutup(self_id: int, group_id: int) -> bool: @any_msg.handle() async def _(bot: Bot, event: GroupMessageEvent, state: T_State): - delay = random.randint(2, 4) for item in state['answers']: logger.info(f'repeater:派蒙[{event.self_id}]准备向群[{event.group_id}]回复[{item}]') @@ -220,18 +221,21 @@ def update_data(): Chat.clearup_context() Chat.completely_sober() -#群组开启 + +# 群组开启 onLearningGroup = on_message( - rule = to_me() & keyword("派蒙学习开启","说怪话"), - priority = 4, - block = True, + rule=to_me() & keyword("派蒙学习开启", "说怪话"), + priority=4, + block=True, permission=permission.GROUP_ADMIN | permission.GROUP_OWNER | SUPERUSER ) onLearningGroup.__paimon_help__ = { - "usage": "@派蒙 <说怪话>", + "usage": "@派蒙 <说怪话>", "introduce": "开启派蒙在该群的机器学习能力", - "priority": 94 + "priority": 94 } + + @onLearningGroup.handle() async def _(bot: Bot, event: GroupMessageEvent): if checkGroup(event): @@ -240,18 +244,21 @@ async def _(bot: Bot, event: GroupMessageEvent): Chat.learningGroup.append(event.group_id) await onLearningGroup.finish("派蒙开始学习群友说怪话!") -#群组关闭 + +# 群组关闭 offLearningGroup = on_message( - rule = to_me() & keyword("派蒙学习关闭","不准说怪话"), - priority = 3, - block = True, + rule=to_me() & keyword("派蒙学习关闭", "不准说怪话"), + priority=3, + block=True, permission=permission.GROUP_ADMIN | permission.GROUP_OWNER | SUPERUSER ) offLearningGroup.__paimon_help__ = { - "usage": "@派蒙 <不准说怪话>", + "usage": "@派蒙 <不准说怪话>", "introduce": "关闭派蒙在该群的机器学习能力", - "priority": 95 + "priority": 95 } + + @offLearningGroup.handle() async def _(bot: Bot, event: GroupMessageEvent): if not checkGroup(event): @@ -260,18 +267,21 @@ async def _(bot: Bot, event: GroupMessageEvent): Chat.learningGroup.remove(event.group_id) await offLearningGroup.finish("派蒙不学就是了TAT") -#发癫 + +# 发癫 fun_msg = on_message( - rule=to_me() & keyword('发癫','派蒙发癫','喝酒') & Rule(checkGroup), + rule=to_me() & keyword('发癫', '派蒙发癫', '喝酒') & Rule(checkGroup), priority=6, block=True, permission=permission.GROUP_ADMIN | permission.GROUP_OWNER | SUPERUSER ) fun_msg.__paimon_help__ = { - "usage": "@派蒙 <发癫>", + "usage": "@派蒙 <发癫>", "introduce": "派蒙喝醉了在群里发癫", - "priority": 96 + "priority": 96 } + + @fun_msg.handle() async def funmsg(bot: Bot, event: GroupMessageEvent): logger.info(f'repeater:派蒙开始发癫') @@ -281,21 +291,24 @@ async def funmsg(bot: Bot, event: GroupMessageEvent): Chat.speak_poke_probability = 1 Chat.speak_continuously_max_len = 10 Chat.cross_group_threshold = 1 - msg_send = ['呀,旅行者。你今天走起路来,怎么看着摇摇晃晃的?嘿嘿嘿~~~','……&%*&U(*……&%'] + msg_send = ['呀,旅行者。你今天走起路来,怎么看着摇摇晃晃的?嘿嘿嘿~~~', '……&%*&U(*……&%'] await fun_msg.finish(random.choice(msg_send)) -#停止发癫 + +# 停止发癫 stop_fun_msg = on_message( - rule=to_me() & keyword('恢复','不准发癫','停止','stop'), + rule=to_me() & keyword('恢复', '不准发癫', '停止', 'stop'), priority=5, block=True, permission=permission.GROUP_ADMIN | permission.GROUP_OWNER | SUPERUSER ) stop_fun_msg.__paimon_help__ = { - "usage": "@派蒙 <不准发癫>", + "usage": "@派蒙 <不准发癫>", "introduce": "让派蒙恢复正常", - "priority": 97 + "priority": 97 } + + @stop_fun_msg.handle() async def stopfunmsg(bot: Bot, event: GroupMessageEvent): logger.info(f'repeater:派蒙停止发癫') @@ -308,18 +321,21 @@ async def stopfunmsg(bot: Bot, event: GroupMessageEvent): msg_send = ['呃...头好疼...恢复了'] await stop_fun_msg.finish(msg_send) -#上调学习能力和主动发言 + +# 上调学习能力和主动发言 upLearning = on_message( - rule=to_me() & keyword('加强学习能力','派蒙快学','再学快点','多说点话') & Rule(checkGroup), + rule=to_me() & keyword('加强学习能力', '派蒙快学', '再学快点', '多说点话') & Rule(checkGroup), priority=6, block=True, permission=permission.GROUP_ADMIN | permission.GROUP_OWNER | SUPERUSER ) upLearning.__paimon_help__ = { - "usage": "@派蒙 <派蒙快学>", + "usage": "@派蒙 <派蒙快学>", "introduce": "增强派蒙的学习能力", - "priority": 98 + "priority": 98 } + + @upLearning.handle() async def _(bot: Bot, event: GroupMessageEvent): if Chat.speak_threshold == 1: @@ -330,18 +346,21 @@ async def _(bot: Bot, event: GroupMessageEvent): Chat.answer_threshold = Chat.speak_threshold await upLearning.finish("派蒙会努力学习的") -#降低学习能力和主动发言 + +# 降低学习能力和主动发言 downLearning = on_message( - rule=to_me() & keyword('降低学习能力','派蒙变笨','笨比派蒙','少说点话') & Rule(checkGroup), + rule=to_me() & keyword('降低学习能力', '派蒙变笨', '笨比派蒙', '少说点话') & Rule(checkGroup), priority=6, block=True, permission=permission.GROUP_ADMIN | permission.GROUP_OWNER | SUPERUSER ) downLearning.__paimon_help__ = { - "usage": "@派蒙 <派蒙变笨>", + "usage": "@派蒙 <派蒙变笨>", "introduce": "降低派蒙的学习能力", - "priority": 99 + "priority": 99 } + + @downLearning.handle() async def _(bot: Bot, event: GroupMessageEvent): if Chat.speak_threshold == 6: diff --git a/Paimon_Chat/__init__.py b/Paimon_Chat/__init__.py index 596920b..e515c3a 100644 --- a/Paimon_Chat/__init__.py +++ b/Paimon_Chat/__init__.py @@ -1,10 +1,13 @@ import random +from pathlib import Path +from typing import Union from nonebot import on_regex, on_command, logger from nonebot.matcher import matchers +from nonebot.plugin import PluginMetadata from nonebot.rule import Rule from nonebot import get_driver -from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, MessageSegment +from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, PrivateMessageEvent from nonebot.exception import FinishedException from utils.config import config @@ -12,18 +15,28 @@ from utils.auth_util import FreqLimiter2 from utils.message_util import MessageBuild from utils.file_handler import load_json_from_url -__paimon_help__ = { - 'type': '派蒙机器学习', - 'range': ['private', 'group', 'guild'] -} + +__plugin_meta__ = PluginMetadata( + name="派蒙聊天", + description="派蒙会发语音、会学群友们说骚话哦(", + usage=( + "被动技能" + ), + extra={ + 'type': '派蒙聊天', + 'range': ['group'], + "author": "惜月 SCUOP", + "version": "1.0.1", + }, +) if config.paimon_mongodb_url: try: from .Learning_repeate import main except ImportError: - logger.info('派蒙机器学习聊天启用失败,可能是mongodb连接失败或缺少相关库') + logger.warning('派蒙机器学习聊天启用失败,可能是mongodb连接失败或缺少相关库(jieba_fast、pymongo、pypinyin)') else: - logger.info('派蒙机器学习聊天启用失败,mongodb尚未配置') + logger.warning('派蒙机器学习聊天启用失败,尚未配置mongodb连接url') driver = get_driver() @@ -32,20 +45,17 @@ chat_lmt = FreqLimiter2(60) update_voice = on_command('更新派蒙语音', priority=2) -# TODO 被动效果 - -def check_group(event: GroupMessageEvent) -> bool: - if event.group_id in config.paimon_chat_group: - return True - return False +def check_group(event: Union[GroupMessageEvent, PrivateMessageEvent]) -> bool: + return True if isinstance(event, PrivateMessageEvent) else event.group_id in config.paimon_chat_group @update_voice.handle() async def update_paimon_voice(event: MessageEvent): try: old_len = len([m for m in matchers[10] if m.plugin_name == 'Paimon_Chat']) - voice_list = await load_json_from_url('https://static.cherishmoon.fun/LittlePaimon/voice/voice_list.json') + path = Path() / 'data' / 'LittlePaimon' / 'voice' / 'voice_list.json' + voice_list = await load_json_from_url('https://static.cherishmoon.fun/LittlePaimon/voice/voice_list.json', path, True) matchers[10] = [m for m in matchers[10] if m.plugin_name != 'Paimon_Chat'] for key, value in voice_list.items(): create_matcher(key, value['pattern'], value['cooldown'], value['pro'], value['files']) @@ -62,21 +72,25 @@ def create_matcher(chat_word: str, pattern: str, cooldown: int, pro: float, resp def check_pro() -> bool: return random.random() < pro - def check_cooldown(event: GroupMessageEvent) -> bool: + def check_cooldown(event: Union[GroupMessageEvent, PrivateMessageEvent]) -> bool: return chat_lmt.check(event.group_id, chat_word) hammer = on_regex(pattern, priority=10, rule=Rule(check_group, check_pro, check_cooldown)) hammer.plugin_name = 'Paimon_Chat' @hammer.handle() - async def handler(event: GroupMessageEvent): + async def handler(event: Union[GroupMessageEvent, PrivateMessageEvent]): try: chat_lmt.start_cd(event.group_id, chat_word, cooldown) - response = random.choice(responses) - if '.mp3' not in response: - await hammer.finish(response) - else: + response: str = random.choice(responses) + if response.endswith('.mp3'): await hammer.finish(await MessageBuild.StaticRecord(url=f'LittlePaimon/voice/{response}')) + if response.endswith(('.png', '.jpg', '.jpeg', '.image', '.gif')): + await hammer.finish(await MessageBuild.StaticImage(url=f'LittlePaimon/voice/{response}')) + if response.endswith(('.mp4', '.avi')): + await hammer.finish(await MessageBuild.StaticVideo(url=f'LittlePaimon/voice/{response}')) + else: + await hammer.finish(MessageBuild.Text(response)) except FinishedException: raise except Exception as e: @@ -85,6 +99,7 @@ def create_matcher(chat_word: str, pattern: str, cooldown: int, pro: float, resp @driver.on_startup async def load_voice(): - voice_list = await load_json_from_url('https://static.cherishmoon.fun/LittlePaimon/voice/voice_list.json') + path = Path() / 'data' / 'LittlePaimon' / 'voice' / 'voice_list.json' + voice_list = await load_json_from_url('https://static.cherishmoon.fun/LittlePaimon/voice/voice_list.json', path) for k, v in voice_list.items(): create_matcher(k, v['pattern'], v['cooldown'], v['pro'], v['files']) diff --git a/Paimon_CloudGenshin/__init__.py b/Paimon_CloudGenshin/__init__.py index 7bc1fe5..1e2e8ac 100644 --- a/Paimon_CloudGenshin/__init__.py +++ b/Paimon_CloudGenshin/__init__.py @@ -7,27 +7,39 @@ from nonebot.adapters.onebot.v11 import MessageEvent, Message, GroupMessageEvent from nonebot.internal.matcher import Matcher from nonebot.internal.params import ArgPlainText from nonebot.params import CommandArg +from nonebot.plugin import PluginMetadata + from .data_source import get_Info, get_Notification, check_token from utils.decorator import exception_handler from utils.file_handler import load_json, save_json -HELP_STR = ''' -云原神相关功能 -云原神 绑定/bind : 绑定云原神的token -云原神 信息/info: 查询云原神账户信息 -'''.strip() + +__plugin_meta__ = PluginMetadata( + name="云原神", + description="云原神相关功能模块", + usage=( + "云原神 绑定/bind : 绑定云原神的token\n" + "云原神 信息/info: 查询云原神账户信息\n" + ), + extra={ + 'type': '工具', + 'range': ['private', 'group'], + "author": "nicklly <1134741727@qq.com>", + "version": "1.0.0", + }, +) cloud_ys = on_command('云原神', aliases={'云原神', 'yys'}, priority=16, block=True) rm_cloud_ys = on_command('云原神解绑', aliases={'yys解绑', 'yys解除绑定', 'yysdel'}, priority=16, block=True) cloud_ys.__paimon_help__ = { "usage": "云原神", "introduce": "查询云原神账户信息, 绑定token进行签到", - "priority": 99 + "priority": 95 } rm_cloud_ys.__paimon_help__ = { "usage": "云原神解绑", "introduce": "解绑cookie并取消自动签到", - "priority": 99 + "priority": 96 } scheduler = require('nonebot_plugin_apscheduler').scheduler uuid = str(uuid.uuid4()) diff --git a/Paimon_Exchange/__init__.py b/Paimon_Exchange/__init__.py index df2b67a..0927980 100644 --- a/Paimon_Exchange/__init__.py +++ b/Paimon_Exchange/__init__.py @@ -2,12 +2,26 @@ import re from nonebot import on_command from nonebot.params import CommandArg, T_State, Arg from nonebot.adapters.onebot.v11 import PrivateMessageEvent, Message +from nonebot.plugin import PluginMetadata + from .data_source import get_address, get_goods, save_exchange_info, get_exchange_info, delete_exchange_info -__paimon_help__ = { - 'type': '工具', - 'range': ['private'] -} + +__plugin_meta__ = PluginMetadata( + name="米游币商品抢兑", + description="小派蒙的米游币商品抢兑模块", + usage=( + "myb 跟随派蒙的指引录入兑换计划\n" + "myb_info 查看当前的兑换计划\n" + "myb_delete 删除你的所有兑换计划\n" + ), + extra={ + 'type': '工具', + 'range': ['private'], + "author": "惜月 <277073121@qq.com>", + "version": "1.0.0", + }, +) myb_exchange = on_command('myb', aliases={'米游币兑换', '米游币商品兑换', '米游社商品兑换'}, priority=4, block=True) myb_exchange.__paimon_help__ = { diff --git a/Paimon_Gacha/__init__.py b/Paimon_Gacha/__init__.py index f2dddc7..6667075 100644 --- a/Paimon_Gacha/__init__.py +++ b/Paimon_Gacha/__init__.py @@ -4,6 +4,7 @@ from typing import Dict from nonebot import on_command, on_regex from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message from nonebot.params import RegexDict, CommandArg +from nonebot.plugin import PluginMetadata from utils.config import config from utils import aiorequests @@ -11,22 +12,27 @@ from utils.auth_util import FreqLimiter from .gacha_info import * from .gacha_res import more_ten -__usage__ = ''' -1.[抽n十连xx池]抽n次xx池的十连,最多同时5次 -*池子和官方同步,有角色1|角色2|武器|常驻,默认为角色1 -2.[模拟抽卡记录]查看模拟抽卡记录总结 -3.[模拟抽卡记录 角色/武器]查看模拟抽卡抽到的五星角色/武器 -4.[删除模拟抽卡记录]顾名思义 -5.[选择定轨 武器全名]选择武器定轨 -6.[查看定轨]查看当前定轨的武器 -7.[删除定轨]删除当前定轨的武器 -''' -__help_version__ = '1.0.1' -__paimon_help__ = { - 'type': '原神模拟抽卡', - 'range': ['private', 'group', 'guild'] -} +__plugin_meta__ = PluginMetadata( + name="原神模拟抽卡", + description="小派蒙的原神模拟抽卡模块", + usage=( + "1.[抽n十连xx池]抽n次xx池的十连,最多同时5次" + "*池子和官方同步,有角色1|角色2|武器|常驻,默认为角色1" + "2.[模拟抽卡记录]查看模拟抽卡记录总结" + "3.[模拟抽卡记录 角色/武器]查看模拟抽卡抽到的五星角色/武器" + "4.[删除模拟抽卡记录]顾名思义" + "5.[选择定轨 武器全名]选择武器定轨" + "6.[查看定轨]查看当前定轨的武器" + "7.[删除定轨]删除当前定轨的武器" + ), + extra={ + 'type': '原神模拟抽卡', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "1.0.3", + }, +) sim_gacha = on_regex(r'^抽((?P\d+)|(?:.*))十连(?P.*?)$', priority=5, block=True) sim_gacha.__paimon_help__ = { diff --git a/Paimon_Gacha_Log/__init__.py b/Paimon_Gacha_Log/__init__.py index 581025f..8fed40a 100644 --- a/Paimon_Gacha_Log/__init__.py +++ b/Paimon_Gacha_Log/__init__.py @@ -6,25 +6,28 @@ from typing import Union from nonebot import on_command from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent, GroupMessageEvent from nonebot.params import CommandArg +from nonebot.plugin import PluginMetadata from utils.message_util import get_uid_in_msg from .api import toApi, checkApi from .gacha_logs import get_data from .get_img import get_gacha_log_img -from pathlib import Path - -__usage__ = ''' -1.[获取抽卡记录 (uid) (url)]提供url,获取原神抽卡记录,需要一定时间 -2.[查看抽卡记录 (uid)]查看抽卡记录分析 -3.[导出抽卡记录 (uid) (xlsx/json)]导出抽卡记录文件,上传到群文件中 -''' -__help_version__ = '0.9.0' - -__paimon_help__ = { - 'type': '原神抽卡记录', - 'range': ['private', 'group', 'guild'] -} +__plugin_meta__ = PluginMetadata( + name="Paimon_Gacha_Log", + description="小派蒙的原神抽卡记录模块", + usage=( + "1.[获取抽卡记录 (uid) (url)]提供url,获取原神抽卡记录,需要一定时间" + "2.[查看抽卡记录 (uid)]查看抽卡记录分析" + "3.[导出抽卡记录 (uid) (xlsx/json)]导出抽卡记录文件,上传到群文件中" + ), + extra={ + 'type': '原神抽卡记录', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "0.1.3", + }, +) gacha_log_export = on_command('ckjldc', aliases={'抽卡记录导出', '导出抽卡记录'}, priority=5, block=True) gacha_log_export.__paimon_help__ = { diff --git a/Paimon_Info/__init__.py b/Paimon_Info/__init__.py index ce60fc6..b1f4330 100644 --- a/Paimon_Info/__init__.py +++ b/Paimon_Info/__init__.py @@ -6,7 +6,8 @@ from collections import defaultdict from nonebot import on_command, require, logger, get_bot from nonebot.adapters.onebot.v11 import MessageEvent, Message, Bot, MessageSegment -from nonebot.params import CommandArg +from nonebot.params import CommandArg, Arg +from nonebot.plugin import PluginMetadata from nonebot.typing import T_State from nonebot.permission import SUPERUSER from nonebot.rule import to_me @@ -34,36 +35,44 @@ from .draw_role_card import draw_role_card require('nonebot_plugin_apscheduler') from nonebot_plugin_apscheduler import scheduler -__usage__ = ''' -[ys (uid)]查看原神个人卡片(包含宝箱、探索度等数据) -[ysa (uid)]查看所有公开的8角色的简略信息 -[ysc (uid) 角色名]查看公开的8角色的详细信息 -*绑定私人cookie之后就可以查看所有角色啦 --------- -[ssbq/实时便签 (uid)]查询当前树脂、洞天宝钱、派遣状况等 -[ssbq (uid) 开启提醒(树脂数)/关闭提醒]开启/关闭树脂提醒,达到树脂数时会在群里艾特你 -*绑定私人cookie之后才能使用 --------- -[sy/深渊查询/深境螺旋查询 (uid) (层数)]查询深渊战绩信息 -*绑定私人cookie之后才能查看层数具体阵容哦 --------- -[mys签到]手动进行一次米游社原神签到 -[mys自动签到开启uid/关闭]开启米游社原神自动签到 --------- -[myzj/每月札记/zj (uid) (月份)]查看该月份获得的原石、摩拉数 -*绑定私人cookie之后才能使用,只能查看最近3个月的记录,默认为本月 --------- -[ysb cookie]绑定你的私人cookie以开启高级功能 -[删除ck]删除你的私人cookie -[添加公共ck cookie]添加公共cookie以供大众查询*仅管理员 -''' -__paimon_help__ = { - 'type': '原神信息查询', - 'range': ['private', 'group', 'guild'] -} +__plugin_meta__ = PluginMetadata( + name="Paimon_Info", + description="小派蒙的原神信息查询模块", + usage=( + "[ys (uid)]查看原神个人卡片(包含宝箱、探索度等数据)\n" + "[ysa (uid)]查看所有公开的8角色的简略信息\n" + "[ysc (uid) 角色名]查看公开的8角色的详细信息\n" + "*绑定私人cookie之后就可以查看所有角色啦\n" + "--------\n" + "[ssbq/实时便签 (uid)]查询当前树脂、洞天宝钱、派遣状况等\n" + "[ssbq (uid) 开启提醒(树脂数)/关闭提醒]开启/关闭树脂提醒,达到树脂数时会在群里艾特你\n" + "*绑定私人cookie之后才能使用\n" + "--------\n" + "[sy/深渊查询/深境螺旋查询 (uid) (层数)]查询深渊战绩信息\n" + "*绑定私人cookie之后才能查看层数具体阵容哦\n" + "--------\n" + "[mys签到]手动进行一次米游社原神签到\n" + "[mys自动签到开启uid/关闭]开启米游社原神自动签到\n" + "--------\n" + "[myzj/每月札记/zj (uid) (月份)]查看该月份获得的原石、摩拉数\n" + "*绑定私人cookie之后才能使用,只能查看最近3个月的记录,默认为本月\n" + "--------\n" + "[ysb cookie]绑定你的私人cookie以开启高级功能\n" + "[删除ck]删除你的私人cookie\n" + "[添加公共ck cookie]添加公共cookie以供大众查询*仅管理员\n" + "--------\n" + "[更新角色信息 uid]更新游戏内展柜8个角色的面板信息\n" + "[ysd 角色名 uid]查看指定角色的详细面板信息\n" + ), + extra={ + 'type': '原神信息查询', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "0.1.3", + }, +) -__help_version__ = '1.1.0' sy = on_command('sy', aliases={'深渊信息', '深境螺旋信息'}, priority=7, block=True) sy.__paimon_help__ = { @@ -483,7 +492,7 @@ async def mys_sign_auto_handler(event: MessageEvent, msg: Message = CommandArg() ud_lmt = FreqLimiter(300) -ud_p_lmt = FreqLimiter(12) +ud_p_lmt = FreqLimiter(15) @update_info.handle() @@ -496,33 +505,38 @@ async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()): for msg_seg in msg: if msg_seg.type == "at": user = msg_seg.data['qq'] + break if user: - state['uid'] = await get_last_query(str(user)) + uid = await get_last_query(str(user)) + if uid: + state['uid'] = uid else: - state['uid'] = await get_last_query(str(event.user_id)) - if not ud_lmt.check(state['uid']): + uid = await get_last_query(str(event.user_id)) + if uid: + state['uid'] = uid + if 'uid' in state and not ud_lmt.check(state['uid']): await update_info.finish(f'每个uid每5分钟才能更新一次信息,请稍等一下吧~(剩余{ud_lmt.left_time(state["uid"])}秒)') if not ud_p_lmt.check(get_message_id(event)): - await update_info.finish(f'每个会话每12秒才能更新一次信息,请稍等一下吧~(剩余{ud_lmt.left_time(get_message_id(event))}秒)') + await update_info.finish(f'每个会话每15秒才能更新一次信息,请稍等一下吧~(剩余{ud_lmt.left_time(get_message_id(event))}秒)') @update_info.got('uid', prompt='请把要更新的uid给派蒙哦~') @exception_handler() -async def _(event: MessageEvent, state: T_State): - uid = transform_uid(state['uid']) +async def _(event: MessageEvent, uid: Message = Arg('uid')): + uid = transform_uid(uid) if not uid: - await update_info.finish('这个uid不正确哦~,请检查一下', at_sender=True) + await update_info.finish('这好像不是一个正确的uid哦~,请检查一下', at_sender=True) await update_last_query(str(event.user_id), uid) await update_info.send('派蒙开始更新信息~请稍等哦~') enka_data = await get_enka_data(uid) if not enka_data: if uid[0] == '5' or uid[0] == '2': - await update_info.finish('暂不支持B服和2开头的账号哦~请等待开发者更新吧~') + await update_info.finish('暂不支持B服账号哦~请等待开发者更新吧~') else: await update_info.finish('派蒙没有查到该uid的信息哦~') ud_lmt.start_cd(uid, 300) - ud_lmt.start_cd(get_message_id(event), 12) + ud_lmt.start_cd(get_message_id(event), 15) player_info = PlayerInfo(uid) player_info.set_player(enka_data['playerInfo']) if 'avatarInfoList' not in enka_data: diff --git a/Paimon_Plugins/__init__.py b/Paimon_Plugins/__init__.py index 9f61fd9..04604f4 100644 --- a/Paimon_Plugins/__init__.py +++ b/Paimon_Plugins/__init__.py @@ -1,25 +1,7 @@ -# # 点餐功能 -# from .order import * -# -# # 新闻功能 -# from .news import * -# -# # 随机图片功能 -# from .random_img import * -# -# # 处理好友和群请求功能 -# from .auto_handle import * -# -# # 对联功能 -# from .couplets import * -# -# from .help import help_ - - -# 如果不需要某项功能,将其from xx import * 注释掉即可 - from nonebot import load_plugins import os + + load_plugins(os.path.dirname(__file__)) diff --git a/Paimon_Plugins/couplets.py b/Paimon_Plugins/couplets.py index 301f369..201cdf0 100644 --- a/Paimon_Plugins/couplets.py +++ b/Paimon_Plugins/couplets.py @@ -2,15 +2,27 @@ from urllib.parse import quote from nonebot import on_command from nonebot.params import CommandArg from nonebot.adapters.onebot.v11 import MessageEvent +from nonebot.plugin import PluginMetadata + from utils.auth_util import FreqLimiter from utils.message_util import get_message_id from utils.config import config from utils import aiorequests -__paimon_help__ = { - 'type': '娱乐', - 'range': ['private', 'group', 'guild'] -} + +__plugin_meta__ = PluginMetadata( + name="对对联", + description="人工智能和你对对联", + usage=( + "对对联 <对联内容>" + ), + extra={ + 'type': '娱乐', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "1.0.0", + }, +) couplets = on_command('对联', aliases={'对对联'}, priority=13, block=True) couplets.__paimon_help__ = { @@ -38,7 +50,7 @@ async def couplets_handler(event: MessageEvent, msg=CommandArg()): num = num if num < 10 else 10 couplets_limit.start_cd(get_message_id(event), config.paimon_couplets_cd) text = quote(str(word)) - url = f'https://ai-backend.binwang.me/v0.2/couplet/{text}' + url = f'https://seq2seq-couplet-model.rssbrain.com/v0.2/couplet/{text}' res = await aiorequests.get(url=url) res = res.json() result = '' diff --git a/Paimon_Plugins/news.py b/Paimon_Plugins/news.py index 3acee7b..468a2f2 100644 --- a/Paimon_Plugins/news.py +++ b/Paimon_Plugins/news.py @@ -2,14 +2,26 @@ import re from nonebot import on_command, require, get_bot, logger from nonebot.params import CommandArg from nonebot.adapters.onebot.v11 import MessageEvent, MessageSegment, Message +from nonebot.plugin import PluginMetadata + from utils import aiorequests from utils.file_handler import load_json, save_json from utils.message_util import get_message_id -__paimon_help__ = { - 'type': '娱乐', - 'range': ['private', 'group', 'guild'] -} + +__plugin_meta__ = PluginMetadata( + name="今日早报", + description="60秒读世界早报", + usage=( + "今日早报 后加on时间/off可以开启/关闭推送" + ), + extra={ + 'type': '娱乐', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "1.0.0", + }, +) news60s_pic = on_command('早报', aliases={'今日早报', '今日新闻', '60s读世界'}, priority=13, block=True) news60s_pic.__paimon_help__ = { diff --git a/Paimon_Plugins/order.py b/Paimon_Plugins/order.py index 3c3132b..070fc6e 100644 --- a/Paimon_Plugins/order.py +++ b/Paimon_Plugins/order.py @@ -2,13 +2,25 @@ import random from nonebot import on_command from nonebot.params import CommandArg from nonebot.adapters.onebot.v11 import Message, MessageEvent, MessageSegment +from nonebot.plugin import PluginMetadata + from utils.auth_util import FreqLimiter from utils import aiorequests -__paimon_help__ = { - 'type': '娱乐', - 'range': ['private', 'group', 'guild'] -} + +__plugin_meta__ = PluginMetadata( + name="点餐", + description="点餐查看食物图片", + usage=( + "点餐 食物名" + ), + extra={ + 'type': '娱乐', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "1.0.0", + }, +) order_pic = on_command('点菜', aliases={'点餐', '食谱', '我想吃'}, priority=13, block=True) order_pic.__paimon_help__ = { diff --git a/Paimon_Plugins/paimon_help.py b/Paimon_Plugins/paimon_help.py index a62a3a6..c22c7e3 100644 --- a/Paimon_Plugins/paimon_help.py +++ b/Paimon_Plugins/paimon_help.py @@ -5,17 +5,26 @@ from nonebot import on_command from nonebot import plugin as nb_plugin from nonebot.params import Depends from nonebot.adapters.onebot.v11 import MessageEvent +from nonebot.plugin import PluginMetadata from utils.message_util import MessageBuild -__version__ = 'v1.0.0' -__paimon_help__ = { - 'type': '工具', - 'range': ['private', 'group', 'guild'] -} +__plugin_meta__ = PluginMetadata( + name="帮助菜单", + description="自动读取插件的信息,生成帮助菜单图片", + usage=( + "help" + ), + extra={ + 'type': '工具', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "v1.0.0", + }, +) -help_ = on_command('help', aliases={'帮助菜单'}, priority=1, block=True) +help_ = on_command('help', aliases={'帮助菜单', '派蒙帮助'}, priority=1, block=True) help_.__paimon_help__ = { "usage": "帮助菜单|help", "introduce": "查看派蒙的帮助信息", @@ -84,7 +93,7 @@ def draw_help_info(help_info: dict): img.paste(bg_img, (0, 0), bg_img) draw = ImageDraw.Draw(img) draw_shadow_text(draw, (50, 50), '派蒙帮助', get_font(140), (255, 255, 255), (0, 0, 0, 255), (3, 3)) - draw_shadow_text(draw, (610, 140), __version__, get_font(50), (255, 255, 255), (0, 0, 0, 255), (3, 3)) + draw_shadow_text(draw, (610, 140), __plugin_meta__.extra.get('version', '1.0.0'), get_font(50), (255, 255, 255), (0, 0, 0, 255), (3, 3)) draw_shadow_text(draw, (520, 250), '<>内为必须,[]内为可选,()内只需要第一次', get_font(50), (255, 255, 255), (0, 0, 0, 255), (2, 2)) draw_shadow_text(draw, (620, 300), '描述前带*号说明需要绑定私人cookie', get_font(50), (255, 255, 255), (0, 0, 0, 255), (2, 2)) n = 400 @@ -101,20 +110,22 @@ async def get_all_plugin(event: MessageEvent) -> dict: help_info: Dict[str, List[dict]] = {} for plugin in plugin_list: try: - plugin_info = plugin.module.__getattribute__('__paimon_help__') + plugin_type = plugin.metadata.extra.get('type', '其他') + plugin_range = plugin.metadata.extra.get('range', ['private', 'group', 'guild']) except AttributeError: - plugin_info = {'type': '其他', 'range': ['private', 'group', 'guild']} - if event.message_type not in plugin_info['range']: + plugin_type = '其他' + plugin_range = ['private', 'group', 'guild'] + if event.message_type not in plugin_range: continue - if plugin_info['type'] not in help_info: - help_info[plugin_info['type']] = [] + if plugin_type not in help_info: + help_info[plugin_type] = [] matchers = plugin.matcher for matcher in matchers: try: matchers_info = matcher.__paimon_help__ if 'priority' not in matchers_info: matchers_info['priority'] = 99 - help_info[plugin_info['type']].append(matchers_info) + help_info[plugin_type].append(matchers_info) except AttributeError: pass help_info = {k: v for k, v in help_info.items() if v} diff --git a/Paimon_Plugins/random_img.py b/Paimon_Plugins/random_img.py index d1b7cc7..f0fa742 100644 --- a/Paimon_Plugins/random_img.py +++ b/Paimon_Plugins/random_img.py @@ -2,15 +2,28 @@ import random from nonebot import on_command, on_regex from nonebot.params import RegexGroup from nonebot.adapters.onebot.v11 import Bot, MessageEvent, MessageSegment +from nonebot.plugin import PluginMetadata + from utils.config import config from utils.auth_util import FreqLimiter from utils.message_util import get_message_id from utils.decorator import auto_withdraw -__paimon_help__ = { - 'type': '娱乐', - 'range': ['private', 'group', 'guild'] -} + +__plugin_meta__ = PluginMetadata( + name="随机图片", + description="从各随机图片接口获取一张图片", + usage=( + "来点猫片\n" + "来点二次元图\n" + ), + extra={ + 'type': '娱乐', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "1.0.0", + }, +) cat_lmt = FreqLimiter(config.paimon_cat_cd) ecy_lmt = FreqLimiter(config.paimon_ecy_cd) diff --git a/Paimon_Wiki/__init__.py b/Paimon_Wiki/__init__.py index 8b531ff..f692d44 100644 --- a/Paimon_Wiki/__init__.py +++ b/Paimon_Wiki/__init__.py @@ -6,28 +6,42 @@ from nonebot import on_endswith, on_command, on_regex from nonebot.adapters.onebot.v11 import MessageEvent, Message, MessageSegment from nonebot.params import RegexDict from nonebot.typing import T_State +from nonebot.plugin import PluginMetadata from utils.alias_handler import get_match_alias from utils.file_handler import load_json_from_url from utils.message_util import MessageBuild from .abyss_rate_draw import draw_rate_rank, draw_teams_rate -__usage__ = ''' -1.[xx角色攻略]查看西风驿站出品的角色一图流攻略 -2.[xx角色材料]查看惜月出品的角色材料统计 -3.[xx参考面板]查看blue菌hehe出品的参考面板攻略 -4.[xx收益曲线]查看blue菌hehe出品的收益曲线攻略 -*感谢来自大佬们的授权。角色支持别名查询 -5.[今日/明日/周x材料]查看每日角色天赋材料和武器突破材料表 -6.[深渊登场率]查看2.6深渊角色登场率 -7.[深渊上半/下半阵容出场率]查看2.6深渊阵容出场率 -''' -__help_version__ = '1.0.4' + __paimon_help__ = { 'type': '原神Wiki', 'range': ['private', 'group', 'guild'] } +__plugin_meta__ = PluginMetadata( + name="Paimon_Wiki", + description="小派蒙的wiki查询模块", + usage=( + "1.[xx角色攻略]查看西风驿站出品的角色一图流攻略\n" + "2.[xx角色材料]查看惜月出品的角色材料统计\n" + "3.[xx参考面板]查看blue菌hehe出品的参考面板攻略\n" + "4.[xx收益曲线]查看blue菌hehe出品的收益曲线攻略\n" + "5.[今日/明日/周x材料]查看每日角色天赋材料和武器突破材料表\n" + "6.[深渊登场率]查看2.6深渊角色登场率\n" + "7.[深渊上半/下半阵容出场率]查看2.6深渊阵容出场率\n" + "8.[xx武器攻略]查看武器攻略\n" + "9.[xx原魔图鉴]查看原魔图鉴\n" + ), + extra={ + 'type': '原神Wiki', + 'range': ['private', 'group', 'guild'], + "author": "惜月 <277073121@qq.com>", + "version": "0.1.3", + }, +) + + res_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'res') guide = on_endswith('角色攻略', priority=8) diff --git a/README.md b/README.md index b3463e0..2b19755 100644 --- a/README.md +++ b/README.md @@ -64,45 +64,21 @@ ## 丨更新日志 -+ 5.19 - - 米游社签到新增`全部重签`,仅限超级管理员使用,需@机器人 - - `原神猜语音`不再需要`我猜`,直接回答角色别名即可参与猜猜看 - - 异步请求库从`aiohttp`改用`httpx`,需安装依赖库`pip install httpx` - - 修复`60秒读世界`在频道无法关闭推送的BUG -+ 5.20 - - 修复`ysc`缺少资源问题 - - 封装部分常用方法,优化导包 - - `Paimon_Chat`新增`更新派蒙语音`,实时更新语音 -+ 5.21 - - 修复可能因ssl证书导致的静态资源下载问题 -+ 5.23 - - 新增`xx原魔图鉴` -+ 5.25 - - `ys、ysc、ysa、sy`等和`wiki`模块指令可以对话式查询 -+ 5.27 - - 新增`原神日历`[@nicklly](https://github.com/nicklly) -+ 5.28 - - `Paimon_Chat`聊天新增`学习群友发言`(魔改自[Pallas-Bot](https://github.com/InvoluteHell/Pallas-Bot/tree/master/src/plugins/repeater)),需安装`jieba_fast、pymongo、pypinyin依赖库`、`mongodb数据库`且在`.env.*`配置文件中添加mongodb连接参数`paimon_mongodb_url`,例如`paimon_mongodb_url=mongodb://localhost:27017/` -+ 6.3 - - 新增游戏内展柜角色面板卡片,使用`更新角色面板`来获取角色,`ysd角色名`来查看角色卡片 - - 修复部分不记录上次查询的uid的bug - - 大幅缩短深渊指令`sy`的缓存时间 -+ 6.6 - - 修复`模拟抽卡定轨`和`抽卡记录导出`bug -+ 6.7 - - 修复`原神猜语音`和`模拟抽卡`因`nonebot2.0.0b3`版本Union校验产生的bug,但`原神猜语音`将暂时无法私聊使用 -+ 6.9 - - 新增`帮助菜单`指令~~(不太好看,继续美化)~~ -+ 6.12 - - 新增`云原神签到`等功能[@nicklly](https://github.com/nicklly) - - 修复部分bug,新增`好友、群新成员和龙王提醒`[#45](https://github.com/CMHopeSunshine/LittlePaimon/issues/45) +> README只展示最近2条更新,全部更新日志详见[这里](https://github.com/CMHopeSunshine/LittlePaimon/blob/nonebot2/UPDATE_LOG.md) + 6.19 - 新增`米游币商品兑换`功能,私聊机器人发送`myb`跟着一步步指引来做,目前该功能还没有机会做测试,出现问题请提issue - `ysb`绑定cookie的方法增加腾讯文档 ++ 6.21 + - 适配`nonebot2 beta4`插件元数据,请更新nb版本`pip install nonebot2 --upgrade` + - `Paimon_Chat`现在可以发图片、视频等,可自行添加 + - 修复`Paimon_Wiki`搜索对象名结果只有一个时仍需要选择的bug + - 对对联功能api更换 + - 增加部分注释文档 ## 丨功能列表 -详见[功能列表](https://blog.cherishmoon.fun/posts/nonebot2funclist.html) +详见我的博客[功能列表](https://blog.cherishmoon.fun/posts/nonebot2funclist.html)
+博客内容可能滞后于实际版本 ~~太懒了~~ ## 丨部署方法 ### 我很熟悉NoneBot2 diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md new file mode 100644 index 0000000..483d2bf --- /dev/null +++ b/UPDATE_LOG.md @@ -0,0 +1,43 @@ +# LittlePaimon更新日志 + ++ 5.19 + - 米游社签到新增`全部重签`,仅限超级管理员使用,需@机器人 + - `原神猜语音`不再需要`我猜`,直接回答角色别名即可参与猜猜看 + - 异步请求库从`aiohttp`改用`httpx`,需安装依赖库`pip install httpx` + - 修复`60秒读世界`在频道无法关闭推送的BUG ++ 5.20 + - 修复`ysc`缺少资源问题 + - 封装部分常用方法,优化导包 + - `Paimon_Chat`新增`更新派蒙语音`,实时更新语音 ++ 5.21 + - 修复可能因ssl证书导致的静态资源下载问题 ++ 5.23 + - 新增`xx原魔图鉴` ++ 5.25 + - `ys、ysc、ysa、sy`等和`wiki`模块指令可以对话式查询 ++ 5.27 + - 新增`原神日历`[@nicklly](https://github.com/nicklly) ++ 5.28 + - `Paimon_Chat`聊天新增`学习群友发言`(魔改自[Pallas-Bot](https://github.com/InvoluteHell/Pallas-Bot/tree/master/src/plugins/repeater)),需安装`jieba_fast、pymongo、pypinyin依赖库`、`mongodb数据库`且在`.env.*`配置文件中添加mongodb连接参数`paimon_mongodb_url`,例如`paimon_mongodb_url=mongodb://localhost:27017/` ++ 6.3 + - 新增游戏内展柜角色面板卡片,使用`更新角色面板`来获取角色,`ysd角色名`来查看角色卡片 + - 修复部分不记录上次查询的uid的bug + - 大幅缩短深渊指令`sy`的缓存时间 ++ 6.6 + - 修复`模拟抽卡定轨`和`抽卡记录导出`bug ++ 6.7 + - 修复`原神猜语音`和`模拟抽卡`因`nonebot2.0.0b3`版本Union校验产生的bug,但`原神猜语音`将暂时无法私聊使用 ++ 6.9 + - 新增`帮助菜单`指令 ~~(不太好看,继续美化)~~ ++ 6.12 + - 新增`云原神签到`等功能[@nicklly](https://github.com/nicklly) + - 修复部分bug,新增`好友、群新成员和龙王提醒`[#45](https://github.com/CMHopeSunshine/LittlePaimon/issues/45) ++ 6.19 + - 新增`米游币商品兑换`功能,私聊机器人发送`myb`跟着一步步指引来做,目前该功能还没有机会做测试,出现问题请提issue + - `ysb`绑定cookie的方法增加腾讯文档 ++ 6.21 + - 适配`nonebot2 beta4`插件元数据,请更新nb版本`pip install nonebot2 --upgrade` + - `Paimon_Chat`现在可以发图片、视频等,可自行添加 + - 修复`Paimon_Wiki`搜索对象名结果只有一个时仍需要选择的bug + - 对对联功能api更换 + - 增加部分注释文档 \ No newline at end of file diff --git a/utils/aiorequests.py b/utils/aiorequests.py index 8d7f1c0..ae8e9c4 100644 --- a/utils/aiorequests.py +++ b/utils/aiorequests.py @@ -94,7 +94,7 @@ async def get_img(url: str, timeout=timeout, **kwargs) resp = resp.read() - if b'error' in resp: + if 'NoSuchKey' in resp: return 'No Such File' img = Image.open(BytesIO(resp)) except SSLCertVerificationError: diff --git a/utils/alias_handler.py b/utils/alias_handler.py index 84df89f..4eaf242 100644 --- a/utils/alias_handler.py +++ b/utils/alias_handler.py @@ -5,7 +5,7 @@ import os def get_short_name(name: str): - short_name = load_json(path=os.path.join(os.path.dirname(__file__),'short_name.json')) + short_name = load_json(path=os.path.join(os.path.dirname(__file__), 'short_name.json')) return name if name not in short_name.keys() else short_name[name] @@ -26,7 +26,6 @@ def get_name_by_id(role_id: str): return None - def get_match_alias(msg: str, type: str = 'roles', single_to_dict: bool = False) -> Union[str, list, dict]: alias_file = load_json(path=os.path.join(os.path.dirname(__file__), 'alias.json')) alias_list = alias_file[type] @@ -42,6 +41,8 @@ def get_match_alias(msg: str, type: str = 'roles', single_to_dict: bool = False) else: return alias[0] elif match_list: + if len(match_list) == 1: + return alias[0] possible[alias[0]] = role_id return possible elif type == 'weapons': diff --git a/utils/file_handler.py b/utils/file_handler.py index 1276cbe..c5fdb75 100644 --- a/utils/file_handler.py +++ b/utils/file_handler.py @@ -13,6 +13,16 @@ def load_image( crop: Optional[Tuple[int, int, int, int]] = None, mode: Optional[str] = None, ): + """ + 说明: + 读取图像,并预处理 + 参数: + :param path: 图片路径 + :param size: 预处理尺寸 + :param crop: 预处理裁剪大小 + :param mode: 预处理图像模式 + :return: 图像对象 + """ img = Image.open(path) if size: if isinstance(size, float): @@ -26,7 +36,16 @@ def load_image( return img -def load_json(file: str = None, path: Union[Path, str] = None, encoding: str = 'utf-8'): +def load_json(file: str = None, path: Union[Path, str] = None, encoding: str = 'utf-8') -> dict: + """ + 说明: + 读取本地json文件,返回json字典。file和path参数2选1即可,file需为data/LittlePaimon中的文件,path哪的文件都行 + 参数: + :param file: 文件名 + :param path: 文件路径 + :param encoding: 编码,默认为utf-8 + :return: json字典 + """ if file and not path: path = Path() / 'data' / 'LittlePaimon' / file elif path: @@ -37,12 +56,25 @@ def load_json(file: str = None, path: Union[Path, str] = None, encoding: str = ' return json.load(path.open('r', encoding=encoding)) -async def load_json_from_url(url: str): - try: - resp = await aiorequests.get(url) - except SSLCertVerificationError: - resp = await aiorequests.get(url.replace('https', 'http')) - return resp.json() +async def load_json_from_url(url: str, path: Union[Path, str] = None, force_refresh: bool = False) -> dict: + """ + 从网络url中读取json,当有path参数时,如果path文件不存在,就会从url下载保存到path,如果path文件存在,则直接读取path + :param url: url + :param path: 本地json文件路径 + :param force_refresh: 是否强制重新下载 + :return: json字典 + """ + if path and Path(path).exists() and not force_refresh: + return load_json(path=path) + else: + try: + resp = await aiorequests.get(url) + except SSLCertVerificationError: + resp = await aiorequests.get(url.replace('https', 'http')) + data = resp.json() + if path and not Path(path).exists(): + save_json(data=data, path=path) + return data def save_json(data, file: str = None, path: Union[Path, str] = None, encoding: str = 'utf-8'): diff --git a/utils/json/ban_word.txt b/utils/json/ban_word.txt new file mode 100644 index 0000000..e0363dd --- /dev/null +++ b/utils/json/ban_word.txt @@ -0,0 +1,4 @@ +[CQ: +[cq: +[Cq: +[cQ: diff --git a/utils/message_util.py b/utils/message_util.py index d216213..72d0b57 100644 --- a/utils/message_util.py +++ b/utils/message_util.py @@ -13,6 +13,12 @@ from .db_util import get_last_query, update_last_query from .file_handler import load_image from . import aiorequests +# 加载敏感违禁词列表 +ban_word = [] +with open(Path(__file__).parent / 'json' / 'ban_word.txt', 'r', encoding='utf-8') as f: + for line in f: + ban_word.append(line.strip()) + class MessageBuild: @@ -25,6 +31,16 @@ class MessageBuild: quality: Optional[int] = 100, mode: Optional[str] = 'RGB' ) -> MessageSegment: + """ + 说明: + 图片预处理并构造成MessageSegment + :param img: 图片Image对象或图片路径 + :param size: 预处理尺寸 + :param crop: 预处理裁剪大小 + :param quality: 预处理图片质量 + :param mode: 预处理图像模式 + :return: MessageSegment.image + """ if isinstance(img, str) or isinstance(img, Path): img = load_image(path=img, size=size, mode=mode, crop=crop) else: @@ -48,11 +64,26 @@ class MessageBuild: size: Optional[Tuple[int, int]] = None, crop: Optional[Tuple[int, int, int, int]] = None, quality: Optional[int] = 100, - mode: Optional[str] = 'RGB', - tips: Optional[str] = None + mode: Optional[str] = None, + tips: Optional[str] = None, + is_check_time: Optional[bool] = True, + check_time_day: Optional[int] = 3 ): + """ + 从url下载图片,并预处理并构造成MessageSegment,如果url的图片已存在本地,则直接读取本地图片 + :param url: 图片url + :param size: 预处理尺寸 + :param crop: 预处理裁剪大小 + :param quality: 预处理图片质量 + :param mode: 预处理图像模式 + :param tips: url中不存在该图片时的提示语 + :param is_check_time: 是否检查本地图片最后修改时间 + :param check_time_day: 检查本地图片最后修改时间的天数,超过该天数则重新下载图片 + :return: MessageSegment.image + """ path = Path() / 'data' / url - if path.exists() and not check_time(path.stat().st_mtime, 3): + if path.exists() and ( + not is_check_time or (is_check_time and not check_time(path.stat().st_mtime, check_time_day))): img = Image.open(path) else: path.parent.mkdir(parents=True, exist_ok=True) @@ -63,23 +94,35 @@ class MessageBuild: img = img.resize(size) if crop: img = img.crop(crop) + if mode: + img = img.convert(mode) bio = BytesIO() - img = img.convert(mode) - img.save(bio, format='JPEG' if mode == 'RGB' else 'PNG', quality=quality) + img.save(bio, format=img.format, quality=quality) return MessageSegment.image(bio) @classmethod def Text(cls, text: str) -> MessageSegment: - # TODO 过滤负面文本 + """ + 过滤文本中的敏感词 + :param text: 文本 + :return: MessageSegment.text + """ + for word in ban_word: + if word in text: + text = text.replace(word, '*') return MessageSegment.text(text) @classmethod def Record(cls, path: str) -> MessageSegment: - # TODO 网络语音 return MessageSegment.record(path) @classmethod async def StaticRecord(cls, url: str) -> MessageSegment: + """ + 从url中下载音频文件,并构造成MessageSegment,如果本地已有该音频文件,则直接读取本地文件 + :param url: 语音url + :return: MessageSegment.record + """ path = Path() / 'data' / url if not path.exists(): path.parent.mkdir(parents=True, exist_ok=True) @@ -88,6 +131,25 @@ class MessageBuild: path.write_bytes(content) return MessageSegment.record(file=path) + @classmethod + def Video(cls, path: str) -> MessageSegment: + return MessageSegment.video(path) + + @classmethod + async def StaticVideo(cls, url: str) -> MessageSegment: + """ + 从url中下载视频文件,并构造成MessageSegment,如果本地已有该视频文件,则直接读取本地文件 + :param url: 视频url + :return: MessageSegment.video + """ + path = Path() / 'data' / url + if not path.exists(): + path.parent.mkdir(parents=True, exist_ok=True) + resp = await aiorequests.get(url='https://static.cherishmoon.fun/' + url) + content = resp.content + path.write_bytes(content) + return MessageSegment.video(file=path) + async def get_at_target(msg): for msg_seg in msg: @@ -174,6 +236,8 @@ def replace_all(raw_text: str, text_list: Union[str, list]): def transform_uid(msg): + if not msg: + return None if isinstance(msg, Message): msg = msg.extract_plain_text().strip() check_uid = msg.split(' ') @@ -193,4 +257,3 @@ def check_time(time_stamp, n=1): return True else: return False -