From b2507f8d4dd051490e49bf9a0d235ab930b63ddd Mon Sep 17 00:00:00 2001 From: Kyomotoi <0w0@imki.moe> Date: Fri, 4 Nov 2022 10:20:01 +0800 Subject: =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=E9=87=8D=E6=9E=84=E6=8F=92?= =?UTF-8?q?=E4=BB=B6:=20=E5=9F=BA=E7=A1=80=E9=83=A8=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ATRI/plugins/essential.py | 362 ---------------------------------- ATRI/plugins/essential/__init__.py | 274 +++++++++++++++++++++++++ ATRI/plugins/essential/data_source.py | 29 +++ ATRI/plugins/essential/listener.py | 41 ++++ ATRI/plugins/essential/models.py | 8 + 5 files changed, 352 insertions(+), 362 deletions(-) delete mode 100644 ATRI/plugins/essential.py create mode 100644 ATRI/plugins/essential/__init__.py create mode 100644 ATRI/plugins/essential/data_source.py create mode 100644 ATRI/plugins/essential/listener.py create mode 100644 ATRI/plugins/essential/models.py diff --git a/ATRI/plugins/essential.py b/ATRI/plugins/essential.py deleted file mode 100644 index 08c2ec1..0000000 --- a/ATRI/plugins/essential.py +++ /dev/null @@ -1,362 +0,0 @@ -import json -import shutil -import asyncio -from datetime import datetime -from pydantic.main import BaseModel -from random import choice, randint -from pathlib import Path -from typing import Union - -import nonebot -from nonebot.message import run_preprocessor -from nonebot.exception import IgnoredException -from nonebot.adapters.onebot.v11 import ( - Bot, - MessageEvent, - GroupMessageEvent, - FriendRequestEvent, - GroupRequestEvent, - GroupIncreaseNoticeEvent, - GroupDecreaseNoticeEvent, - GroupAdminNoticeEvent, - GroupBanNoticeEvent, - GroupRecallNoticeEvent, - FriendRecallNoticeEvent, - MessageSegment, - Message, -) - -from ATRI import conf -from ATRI.service import Service -from ATRI.log import log -from ATRI.utils import MessageChecker -from ATRI.utils.apscheduler import scheduler -from ATRI.permission import MASTER - - -bots = nonebot.get_bots() - - -ESSENTIAL_DIR = Path(".") / "data" / "plugins" / "essential" -MANEGE_DIR = Path(".") / "data" / "plugins" / "manege" -TEMP_PATH = Path(".") / "data" / "temp" -ESSENTIAL_DIR.mkdir(parents=True, exist_ok=True) -MANEGE_DIR.mkdir(parents=True, exist_ok=True) -TEMP_PATH.mkdir(parents=True, exist_ok=True) - - -@run_preprocessor -async def _check_block(event: MessageEvent): - user_file = "block_user.json" - path = MANEGE_DIR / user_file - if not path.is_file(): - with open(path, "w", encoding="utf-8") as w: - w.write(json.dumps(dict())) - - try: - data = json.loads(path.read_bytes()) - except Exception: - data = dict() - - user_id = event.get_user_id() - if user_id in data: - raise IgnoredException(f"Block user: {user_id}") - - if isinstance(event, GroupMessageEvent): - group_file = "block_group.json" - path = MANEGE_DIR / group_file - if not path.is_file(): - with open(path, "w", encoding="utf-8") as w: - w.write(json.dumps(dict())) - - try: - data = json.loads(path.read_bytes()) - except Exception: - data = dict() - - group_id = str(event.group_id) - if group_id in data: - raise IgnoredException(f"Block group: {user_id}") - - -class FriendRequestInfo(BaseModel): - user_id: str - comment: str - time: str - is_approve: bool - - -class GroupRequestInfo(BaseModel): - user_id: str - comment: str - time: str - is_approve: bool - - -ess = Service("基础部件").document("对bot基础/必须请求进行处理") - - -friend_add_event = ess.on_request("好友添加", "好友添加检测") - - -@friend_add_event.handle() -async def _friend_add(bot: Bot, event: FriendRequestEvent): - """ - 存储文件结构: - { - "Apply code": { - "user_id": "User ID", - "comment": "Comment content" - "time": "Time", - "is_approve": bool # Default: False - } - } - """ - file_name = "friend_add.json" - path = ESSENTIAL_DIR / file_name - if not path.is_file(): - with open(path, "w", encoding="utf-8") as w: - w.write(json.dumps({})) - data = dict() - - apply_code = event.flag - apply_comment = event.comment - user_id = event.get_user_id() - now_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - - data = json.loads(path.read_bytes()) - data[apply_code] = FriendRequestInfo( - user_id=user_id, comment=apply_comment, time=now_time, is_approve=False - ).dict() - with open(path, "w", encoding="utf-8") as w: - w.write(json.dumps(data, indent=4)) - - repo = ( - "咱收到一条好友请求...\n" - f"请求人:{user_id}\n" - f"申请信息:{apply_comment}\n" - f"申请码:{apply_code}\n" - "Tip: 获取好友申请" - ) - for superuser in conf.BotConfig.superusers: - await bot.send_private_msg(user_id=superuser, message=repo) - - -group_invite_event = ess.on_request("邀请入群", "被邀请入群检测") - - -@group_invite_event.handle() -async def _group_invite(bot: Bot, event: GroupRequestEvent): - """ - 存储文件结构: - { - "Apply code": { - "user_id": "User ID", - "comment": "Comment content" - "time": "Time", - "is_approve": bool # Default: False - } - } - """ - file_name = "group_invite.json" - path = ESSENTIAL_DIR / file_name - if not path.is_file(): - with open(path, "w", encoding="utf-8") as w: - w.write(json.dumps({})) - data = dict() - - apply_code = event.flag - apply_comment = event.comment - user_id = event.get_user_id() - now_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - - data = json.loads(path.read_bytes()) - data[apply_code] = GroupRequestInfo( - user_id=user_id, comment=apply_comment, time=now_time, is_approve=False - ).dict() - with open(path, "w", encoding="utf-8") as w: - w.write(json.dumps(data, indent=4)) - - repo = ( - "咱收到一条群聊请求...\n" - f"请求人:{user_id}\n" - f"申请信息:{apply_comment}\n" - f"申请码:{apply_code}\n" - "Tip: 获取邀请列表" - ) - for superuser in conf.BotConfig.superusers: - await bot.send_private_msg(user_id=superuser, message=repo) - - -group_member_event = ess.on_notice("群成员变动", "群成员变动检测") - - -@group_member_event.handle() -async def _group_member_join(bot: Bot, event: GroupIncreaseNoticeEvent): - await asyncio.sleep(randint(1, 6)) - msg = "好欸!事新人!\n" f"在下 {choice(list(conf.BotConfig.nickname))} 哒!w!" - await group_member_event.finish(msg) - - -@group_member_event.handle() -async def _group_member_left(bot: Bot, event: GroupDecreaseNoticeEvent): - await asyncio.sleep(randint(1, 6)) - await group_member_event.finish("呜——有人跑了...") - - -group_admin_event = ess.on_notice("群管理变动", "群管理变动检测") - - -@group_admin_event.handle() -async def _group_admin_event(bot: Bot, event: GroupAdminNoticeEvent): - if not event.is_tome(): - return - - for superuser in conf.BotConfig.superusers: - await bot.send_private_msg( - user_id=int(superuser), message=f"好欸!主人!我在群 {event.group_id} 成为了管理!!" - ) - - -group_ban_event = ess.on_notice("群禁言变动", "群禁言变动检测") - - -@group_ban_event.handle() -async def _group_ban_event(bot: Bot, event: GroupBanNoticeEvent): - if not event.is_tome(): - return - - if event.duration: - msg = ( - "那个..。,主人\n" - f"咱在群 {event.group_id} 被 {event.operator_id} 塞上了口球...\n" - f"时长...是 {event.duration} 秒" - ) - for superuser in conf.BotConfig.superusers: - await bot.send_private_msg(user_id=int(superuser), message=msg) - else: - msg = "好欸!主人\n" f"咱在群 {event.group_id} 的口球被 {event.operator_id} 解除了!" - for superuser in conf.BotConfig.superusers: - await bot.send_private_msg(user_id=int(superuser), message=msg) - - -_acc_recall = True - - -recall_event = ess.on_notice("撤回事件", "撤回事件检测") - - -@recall_event.handle() -async def _recall_group_event(bot: Bot, event: GroupRecallNoticeEvent): - if event.is_tome(): - return - - if not _acc_recall: - return - - try: - repo = await bot.get_msg(message_id=event.message_id) - except Exception: - return - - log.debug(f"Recall raw msg:\n{repo}") - user = event.user_id - group = event.group_id - repo = repo["message"] - - try: - m = recall_msg_dealer(repo) - except Exception: - check = MessageChecker(repo).check_cq_code - if not check: - m = repo - else: - return - msg = f"主人,咱拿到了一条撤回信息!\n{user}@[群:{group}]\n撤回了\n{m}" - for superuser in conf.BotConfig.superusers: - await bot.send_private_msg(user_id=int(superuser), message=Message(msg)) - - -@recall_event.handle() -async def _recall_private_event(bot: Bot, event: FriendRecallNoticeEvent): - if event.is_tome(): - return - - if not _acc_recall: - return - - try: - repo = await bot.get_msg(message_id=event.message_id) - except Exception: - return - - log.debug(f"Recall raw msg:\n{repo}") - user = event.user_id - repo = repo["message"] - - try: - m = recall_msg_dealer(repo) - except Exception: - check = MessageChecker(repo).check_cq_code - if not check: - m = repo - else: - return - - msg = f"主人,咱拿到了一条撤回信息!\n{user}@[私聊]撤回了\n{m}" - for superuser in conf.BotConfig.superusers: - await bot.send_private_msg(user_id=int(superuser), message=Message(msg)) - - -rej_recall = ess.on_command("拒绝撤回", "拒绝撤回信息", permission=MASTER) - - -@rej_recall.handle() -async def _(): - global _acc_recall - _acc_recall = False - await rej_recall.finish("已拒绝撤回信息...") - - -acc_recall = ess.on_command("接受撤回", "接受撤回信息", permission=MASTER) - - -@acc_recall.handle() -async def _(): - global _acc_recall - _acc_recall = True - await acc_recall.finish("现在可以接受撤回信息啦!") - - -@scheduler.scheduled_job("interval", name="清除缓存", minutes=30, misfire_grace_time=5) # type: ignore -async def _clear_cache(): - try: - shutil.rmtree(TEMP_PATH) - TEMP_PATH.mkdir(parents=True, exist_ok=True) - except Exception: - log.warning("清除缓存失败,请手动清除:data/temp") - - -def recall_msg_dealer(msg: Union[str, dict]) -> str: - if isinstance(msg, str): - return msg - temp_m = list() - for i in msg: - _type = i.get("type", "idk") - _data = i.get("data", "idk") - if _type == "text": - temp_m.append(_data["text"]) - elif _type == "image": - url = _data["url"] - check = MessageChecker(url).check_image_url - if check: - temp_m.append(MessageSegment.image(url)) - else: - temp_m.append(f"[该图片可能包含非法内容,源url:{url}]") - elif _type == "face": - temp_m.append(MessageSegment.face(_data["id"])) - else: - temp_m.append(f"[未知类型信息:{_data}]") - - repo = str().join(map(str, temp_m)) - return repo diff --git a/ATRI/plugins/essential/__init__.py b/ATRI/plugins/essential/__init__.py new file mode 100644 index 0000000..4635583 --- /dev/null +++ b/ATRI/plugins/essential/__init__.py @@ -0,0 +1,274 @@ +import json +import shutil +import asyncio +from pathlib import Path +from datetime import datetime +from random import choice, randint + +from nonebot.adapters.onebot.v11 import ( + Bot, + MessageEvent, + FriendRequestEvent, + GroupRequestEvent, + GroupIncreaseNoticeEvent, + GroupDecreaseNoticeEvent, + GroupAdminNoticeEvent, + GroupBanNoticeEvent, + GroupRecallNoticeEvent, + FriendRecallNoticeEvent, +) + +from ATRI import conf +from ATRI.log import log +from ATRI.service import Service +from ATRI.utils.apscheduler import scheduler +from ATRI.utils import FileDealer, MessageChecker +from ATRI.permission import MASTER +from ATRI.message import MessageBuilder + +from .models import RequestInfo +from .data_source import recall_msg_dealer + + +__ESSENTIAL_DIR = Path(".") / "data" / "plugins" / "essential" +__TEMP_DIR = Path(".") / "data" / "temp" +__ESSENTIAL_DIR.mkdir(parents=True, exist_ok=True) +__TEMP_DIR.mkdir(parents=True, exist_ok=True) + +# __REJECT_RECALL_LIST = list() + + +plugin = Service("基础部件").document("对基础请求进行处理") + + +friend_add_event = plugin.on_request("好友申请", "好友申请检测") + + +@friend_add_event.handle() +async def _(event: FriendRequestEvent): + path = __ESSENTIAL_DIR / "friend_add.json" + file = FileDealer(path) + if not path.is_file(): + await file.write(json.dumps(dict())) + data = dict() + + apply_code = event.flag + user_id = event.get_user_id() + apply_comment = event.comment + now_time = str(datetime.now().timestamp()) + + data = file.json() + data[apply_code] = RequestInfo( + user_id=user_id, + comment=apply_comment, + time=now_time, + ) + await file.write(json.dumps(data)) + + result = ( + MessageBuilder("咱收到一条好友请求!") + .text(f"请求人: {user_id}") + .text(f"申请信息: {apply_comment}") + .text(f"申请码: {apply_code}") + .text("Tip: 好友申请列表") + ) + await plugin.send_to_master(result) + + +group_invite_request = plugin.on_request("应邀入群", "应邀入群检测") + + +@group_invite_request.handle() +async def _(event: GroupRequestEvent): + path = __ESSENTIAL_DIR / "group_invite.json" + file = FileDealer(path) + if not path.is_file(): + await file.write(json.dumps(dict())) + data = dict() + + apply_code = event.flag + user_id = event.get_user_id() + apply_comment = event.comment + now_time = str(datetime.now().timestamp()) + + data = file.json() + data[apply_code] = RequestInfo( + user_id=user_id, + comment=apply_comment, + time=now_time, + ) + await file.write(json.dumps(data)) + + result = ( + MessageBuilder("咱收到一条应邀入群请求!") + .text(f"申请人: {user_id}") + .text(f"申请信息: {apply_comment}") + .text(f"申请码: {apply_code}") + .text("Tip: 应邀入群列表") + ) + await plugin.send_to_master(result) + + +group_member_event = plugin.on_notice("群成员变动", "群成员变动检测") + + +@group_member_event.handle() +async def _(event: GroupIncreaseNoticeEvent): + await asyncio.sleep(randint(1, 6)) + await group_member_event.finish( + MessageBuilder("好欸! 事新人!").text(f"在下 {choice(list(conf.BotConfig.nickname))}") + ) + + +@group_member_event.handle() +async def _(event: GroupDecreaseNoticeEvent): + await asyncio.sleep(randint(1, 6)) + await group_member_event.finish("呜——有人跑了...") + + +group_admin_event = plugin.on_notice("群管理变动", "群管理变动检测") + + +@group_admin_event.handle() +async def _(event: GroupAdminNoticeEvent): + sub_type = event.sub_type + if event.is_tome() and sub_type == "set": + await plugin.send_to_master(f"好欸! 咱在群 {event.group_id} 成为了管理!!") + return + elif sub_type == "set": + await group_admin_event.finish("新的py交易已达成") + else: + await group_admin_event.finish("有的人超能力到期了 (") + + +group_ban_event = plugin.on_notice("群禁言变动", "群禁言变动检测") + + +@group_ban_event.handle() +async def _(event: GroupBanNoticeEvent): + if not event.is_tome(): + await group_ban_event.finish("群友喝下管理的红茶昏睡了过去") + + if event.duration: + await plugin.send_to_master( + MessageBuilder("那个...") + .text(f"咱在群 {event.group_id} 被 {event.operator_id} 塞上了口球...") + .text(f"时长...是 {event.duration} 秒") + ) + else: + await plugin.send_to_master( + MessageBuilder("好欸!").text( + f"咱在群 {event.group_id} 的口球被 {event.operator_id} 解除了!" + ) + ) + + +_acc_recall = True + + +recall_event = plugin.on_notice("撤回事件", "撤回事件检测") + + +@recall_event.handle() +async def _(bot: Bot, event: FriendRecallNoticeEvent): + if event.is_tome() and not _acc_recall: + return + + try: + repo = await bot.get_msg(message_id=event.message_id) + except Exception: + return + + log.debug(f"Recall raw msg:\n{repo}") + user = event.user_id + repo = repo["message"] + + try: + m = recall_msg_dealer(repo) + except Exception: + check = MessageChecker(repo).check_cq_code + if not check: + m = repo + else: + return + + await plugin.send_to_master( + MessageBuilder("咱拿到了一条撤回信息!").text(f"{user}@[私聊]").text(f"撤回了\n{m}") + ) + + +@recall_event.handle() +async def _(bot: Bot, event: GroupRecallNoticeEvent): + if event.is_tome() and not _acc_recall: + return + + try: + repo = await bot.get_msg(message_id=event.message_id) + except Exception: + return + + log.debug(f"Recall raw msg:\n{repo}") + user = event.user_id + group = event.group_id + repo = repo["message"] + + try: + m = recall_msg_dealer(repo) + except Exception: + check = MessageChecker(repo).check_cq_code + if not check: + m = repo + else: + return + await plugin.send_to_master( + MessageBuilder("咱拿到了一条撤回信息!").text(f"{user}@[群:{group}]").text(f"撤回了\n{m}") + ) + + +reject_recall = plugin.on_command("拒绝撤回", "拒绝撤回信息", permission=MASTER) + + +@reject_recall.handle() +async def _(event: MessageEvent): + # global __REJECT_RECALL_LIST + + # user_id = event.get_user_id() + # if not user_id in __REJECT_RECALL_LIST: + # __REJECT_RECALL_LIST.append(user_id) + global _acc_recall + + _acc_recall = False + await reject_recall.finish("完成~") + + +accept_recall = plugin.on_command("接受撤回", "拒绝撤回信息", permission=MASTER) + + +@accept_recall.handle() +async def _(event: MessageEvent): + # global __REJECT_RECALL_LIST + + # user_id = event.get_user_id() + # if user_id in __REJECT_RECALL_LIST: + # __REJECT_RECALL_LIST.remove(user_id) + global _acc_recall + + _acc_recall = True + await accept_recall.finish("完成~") + + +@scheduler.scheduled_job("interval", name="清除缓存", minutes=30, misfire_grace_time=5) # type: ignore +async def _(): + try: + shutil.rmtree(__TEMP_DIR) + __TEMP_DIR.mkdir(parents=True, exist_ok=True) + except Exception: + log.warning("清除缓存失败, 请手动清除: data/temp") + + +from ATRI import driver + +from .listener import init_listener + + +driver().on_startup(init_listener) diff --git a/ATRI/plugins/essential/data_source.py b/ATRI/plugins/essential/data_source.py new file mode 100644 index 0000000..8274db0 --- /dev/null +++ b/ATRI/plugins/essential/data_source.py @@ -0,0 +1,29 @@ +from typing import Union + +from ATRI.utils import MessageChecker +from ATRI.message import MessageSegment + + +def recall_msg_dealer(message: Union[dict, str]) -> str: + if isinstance(message, str): + return message + + cache_list = list() + for i in message: + _type = i.get("type") + _data = i.get("data") + if _type == "text": + cache_list.append(_data["text"]) + elif _type == "image": + url = _data["url"] + check = MessageChecker(url).check_image_url + if check: + cache_list.append(MessageSegment.image(url)) + else: + cache_list.append(f"[该图片可能包含危险内容, 源url: {url}]") + elif _type == "face": + cache_list.append(MessageSegment.face(_data["id"])) + else: + cache_list.append(f"[未知类型信息: {_data}]") + + return str().join(map(str, cache_list)) \ No newline at end of file diff --git a/ATRI/plugins/essential/listener.py b/ATRI/plugins/essential/listener.py new file mode 100644 index 0000000..fd05cba --- /dev/null +++ b/ATRI/plugins/essential/listener.py @@ -0,0 +1,41 @@ +import json +from pathlib import Path + +from nonebot.message import run_preprocessor +from nonebot.exception import IgnoredException +from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent + + +__MANEGE_DIR = Path(".") / "data" / "plugins" / "manege" +__MANEGE_DIR.mkdir(parents=True, exist_ok=True) + + +# 检查用户是否存在于黑名单 +@run_preprocessor +async def _(event: MessageEvent): + blockuser_file_path = __MANEGE_DIR / "block_user.json" + if not blockuser_file_path.is_file(): + with open(blockuser_file_path, "w", encoding="utf-8") as w: + w.write(json.dumps(dict())) + + data = json.loads(blockuser_file_path.read_bytes()) + + user_id = event.get_user_id() + if user_id in data: + raise IgnoredException(f"Blocked user: {user_id}") + + if isinstance(event, GroupMessageEvent): + blockgroup_file_path = __MANEGE_DIR / "block_group.json" + if not blockgroup_file_path.is_file(): + with open(blockgroup_file_path, "w", encoding="utf-8") as w: + w.write(json.dumps(dict())) + + data = json.loads(blockgroup_file_path.read_bytes()) + + group_id = str(event.group_id) + if group_id in data: + raise IgnoredException(f"Blocked group: {group_id}") + + +def init_listener(): + """初始化监听器""" diff --git a/ATRI/plugins/essential/models.py b/ATRI/plugins/essential/models.py new file mode 100644 index 0000000..4aa5693 --- /dev/null +++ b/ATRI/plugins/essential/models.py @@ -0,0 +1,8 @@ +from typing import List, Optional +from pydantic import BaseModel + + +class RequestInfo(BaseModel): + user_id: str + comment: str + time: str -- cgit v1.2.3