diff --git a/README.md b/README.md
index 63ae6594..e844a800 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,7 @@
- [x] 移动图片 (同上)
- [x] 删除图片 (同上)
- [x] 群内B站订阅
+- [x] 群词条
### 已实现的超级用户功能
- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
@@ -272,7 +273,7 @@
-## 详细配置请前往文档,以下为最简部署和配置
+## 详细配置请前往文档,以下为最简部署和配置,如果你有基础并学习过nonebot2的话
## 简单部署
@@ -320,6 +321,18 @@ python bot.py
## 更新
+### 2021/11/23
+
+* 替换cos API
+* 提供私聊b了,即跨群b了用户
+* 修复游戏抽卡导入角色失败(原神)
+* 修复无Pixiv代理时报错
+* 将项目中大部分aiohttp替换为httpx
+* 删除了丘丘人翻译插件
+* 新增群词条
+* 修复游戏抽卡碧蓝航线bwiki格式更改导致获取报错
+* 首次启动会生成配置文件后停止程序,配置后再次启动即可
+
### 2021/11/18
* 修复超级用户无法正确拉真寻入群
diff --git a/__version__ b/__version__
index 4ac81ba1..82cda522 100644
--- a/__version__
+++ b/__version__
@@ -1 +1 @@
-__version__: v0.0.6.1
+__version__: v0.0.6.2
diff --git a/basic_plugins/__init__.py b/basic_plugins/__init__.py
old mode 100644
new mode 100755
diff --git a/basic_plugins/admin_bot_manage/__init__.py b/basic_plugins/admin_bot_manage/__init__.py
old mode 100644
new mode 100755
index 0449b3f4..2cf0aeef
--- a/basic_plugins/admin_bot_manage/__init__.py
+++ b/basic_plugins/admin_bot_manage/__init__.py
@@ -4,7 +4,7 @@ import nonebot
Config.add_plugin_config(
"admin_bot_manage:custom_welcome_message",
- "SET_GROUP_WELCOME_MESSAGE_LEVEL",
+ "SET_GROUP_WELCOME_MESSAGE_LEVEL [LEVEL]",
2,
name="群管理员操作",
help_="设置群欢迎消息权限",
diff --git a/basic_plugins/admin_bot_manage/admin_config.py b/basic_plugins/admin_bot_manage/admin_config.py
old mode 100644
new mode 100755
index bd34b3d5..b3ca2380
--- a/basic_plugins/admin_bot_manage/admin_config.py
+++ b/basic_plugins/admin_bot_manage/admin_config.py
@@ -1,38 +1,38 @@
-from nonebot import on_notice
-from services.log import logger
-from nonebot.adapters.cqhttp import Bot, GroupAdminNoticeEvent
-from nonebot.typing import T_State
-from models.level_user import LevelUser
-from models.group_member_info import GroupInfoUser
-from configs.config import Config
-
-
-__zx_plugin_name__ = "群管理员变动监测 [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-admin_notice = on_notice(priority=5)
-
-
-@admin_notice.handle()
-async def _(bot: Bot, event: GroupAdminNoticeEvent, state: T_State):
- try:
- nickname = (
- await GroupInfoUser.get_member_info(event.user_id, event.group_id)
- ).user_name
- except AttributeError:
- nickname = event.user_id
- if event.sub_type == "set":
- await LevelUser.set_level(
- event.user_id,
- event.group_id,
- Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
- )
- logger.info(
- f"为新晋管理员 {nickname}({event.user_id}) "
- f"添加权限等级:{Config.get_config('admin_bot_manage', 'ADMIN_DEFAULT_AUTH')}"
- )
- elif event.sub_type == "unset":
- await LevelUser.delete_level(event.user_id, event.group_id)
- logger.info(f"将非管理员 {nickname}({event.user_id}) 取消权限等级")
+from nonebot import on_notice
+from services.log import logger
+from nonebot.adapters.cqhttp import Bot, GroupAdminNoticeEvent
+from nonebot.typing import T_State
+from models.level_user import LevelUser
+from models.group_member_info import GroupInfoUser
+from configs.config import Config
+
+
+__zx_plugin_name__ = "群管理员变动监测 [Hidden]"
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+admin_notice = on_notice(priority=5)
+
+
+@admin_notice.handle()
+async def _(bot: Bot, event: GroupAdminNoticeEvent, state: T_State):
+ try:
+ nickname = (
+ await GroupInfoUser.get_member_info(event.user_id, event.group_id)
+ ).user_name
+ except AttributeError:
+ nickname = event.user_id
+ if event.sub_type == "set":
+ await LevelUser.set_level(
+ event.user_id,
+ event.group_id,
+ Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
+ )
+ logger.info(
+ f"为新晋管理员 {nickname}({event.user_id}) "
+ f"添加权限等级:{Config.get_config('admin_bot_manage', 'ADMIN_DEFAULT_AUTH')}"
+ )
+ elif event.sub_type == "unset":
+ await LevelUser.delete_level(event.user_id, event.group_id)
+ logger.info(f"将非管理员 {nickname}({event.user_id}) 取消权限等级")
diff --git a/basic_plugins/admin_bot_manage/custom_welcome_message.py b/basic_plugins/admin_bot_manage/custom_welcome_message.py
old mode 100644
new mode 100755
index 6eca8539..dc06f9ef
--- a/basic_plugins/admin_bot_manage/custom_welcome_message.py
+++ b/basic_plugins/admin_bot_manage/custom_welcome_message.py
@@ -1,51 +1,51 @@
-from nonebot import on_command
-from utils.utils import get_message_text, get_message_imgs
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
-from .data_source import custom_group_welcome
-from nonebot.adapters.cqhttp.permission import GROUP
-from configs.config import Config
-from services.log import logger
-
-
-__zx_plugin_name__ = "自定义进群欢迎消息 [Admin]"
-__plugin_usage__ = """
-usage:
- 指令:
- 自定义进群欢迎消息 ?[文本] ?[图片]
- 示例:自定义进群欢迎消息 欢迎新人![图片]
- Note:可以通过[at]来确认是否艾特新成员
- 示例:自定义进群欢迎消息 欢迎你[at]
-""".strip()
-__plugin_des__ = '简易的自定义群欢迎消息'
-__plugin_cmd__ = ['自定义群欢迎消息 ?[文本] ?[图片]']
-__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
-__plugin_settings__ = {
- "admin_level": Config.get_config("admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL"),
-}
-
-custom_welcome = on_command(
- "自定义进群欢迎消息",
- aliases={"自定义欢迎消息", "自定义群欢迎消息", "设置群欢迎消息"},
- permission=GROUP,
- priority=5,
- block=True,
-)
-
-
-@custom_welcome.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- try:
- msg = get_message_text(event.json())
- imgs = get_message_imgs(event.json())
- if not msg and not imgs:
- await custom_welcome.finish(__plugin_usage__)
- await custom_welcome.send(
- await custom_group_welcome(msg, imgs, event.user_id, event.group_id),
- at_sender=True,
- )
- logger.info(f"USER {event.user_id} GROUP {event.group_id} 自定义群欢迎消息:{msg}")
- except Exception as e:
- logger.error(f"自定义进群欢迎消息发生错误 {type(e)}:{e}")
- await custom_welcome.send("发生了一些未知错误...")
+from nonebot import on_command
+from utils.utils import get_message_text, get_message_imgs
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
+from .data_source import custom_group_welcome
+from nonebot.adapters.cqhttp.permission import GROUP
+from configs.config import Config
+from services.log import logger
+
+
+__zx_plugin_name__ = "自定义进群欢迎消息 [Admin]"
+__plugin_usage__ = """
+usage:
+ 指令:
+ 自定义进群欢迎消息 ?[文本] ?[图片]
+ 示例:自定义进群欢迎消息 欢迎新人![图片]
+ Note:可以通过[at]来确认是否艾特新成员
+ 示例:自定义进群欢迎消息 欢迎你[at]
+""".strip()
+__plugin_des__ = '简易的自定义群欢迎消息'
+__plugin_cmd__ = ['自定义群欢迎消息 ?[文本] ?[图片]']
+__plugin_version__ = 0.1
+__plugin_author__ = 'HibiKier'
+__plugin_settings__ = {
+ "admin_level": Config.get_config("admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL"),
+}
+
+custom_welcome = on_command(
+ "自定义进群欢迎消息",
+ aliases={"自定义欢迎消息", "自定义群欢迎消息", "设置群欢迎消息"},
+ permission=GROUP,
+ priority=5,
+ block=True,
+)
+
+
+@custom_welcome.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ try:
+ msg = get_message_text(event.json())
+ imgs = get_message_imgs(event.json())
+ if not msg and not imgs:
+ await custom_welcome.finish(__plugin_usage__)
+ await custom_welcome.send(
+ await custom_group_welcome(msg, imgs, event.user_id, event.group_id),
+ at_sender=True,
+ )
+ logger.info(f"USER {event.user_id} GROUP {event.group_id} 自定义群欢迎消息:{msg}")
+ except Exception as e:
+ logger.error(f"自定义进群欢迎消息发生错误 {type(e)}:{e}")
+ await custom_welcome.send("发生了一些未知错误...")
diff --git a/basic_plugins/admin_bot_manage/data_source.py b/basic_plugins/admin_bot_manage/data_source.py
old mode 100644
new mode 100755
index e0954eaa..345ad630
--- a/basic_plugins/admin_bot_manage/data_source.py
+++ b/basic_plugins/admin_bot_manage/data_source.py
@@ -1,296 +1,290 @@
-from typing import List
-from nonebot.adapters.cqhttp.message import MessageSegment
-from services.log import logger
-from configs.path_config import DATA_PATH
-from utils.message_builder import image
-from utils.utils import get_local_proxy, get_bot
-from pathlib import Path
-from models.group_member_info import GroupInfoUser
-from datetime import datetime
-from services.db_context import db
-from models.level_user import LevelUser
-from configs.config import Config
-from utils.manager import group_manager, plugins2settings_manager, plugins_manager
-from utils.image_utils import CreateImg
-import aiofiles
-import aiohttp
-import asyncio
-import time
-import os
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-async def group_current_status(group_id: int) -> str:
- """
- 获取当前所有通知的开关
- :param group_id: 群号
- """
- rst = "[被动技能 状态]\n"
- _data = group_manager.get_task_data()
- for task in _data.keys():
- rst += f'{_data[task]}: {"√" if await group_manager.check_group_task_status(group_id, task) else "×"}\n'
- return rst.strip()
-
-
-custom_welcome_msg_json = (
- Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
-)
-
-
-async def custom_group_welcome(
- msg: str, imgs: List[str], user_id: int, group_id: int
-) -> str:
- """
- 替换群欢迎消息
- :param msg: 欢迎消息文本
- :param imgs: 欢迎消息图片,只取第一张
- :param user_id: 用户id,用于log记录
- :param group_id: 群号
- """
- img_result = ""
- img = imgs[0] if imgs else ""
- result = ""
- if os.path.exists(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg"):
- os.remove(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
- if not custom_welcome_msg_json.exists():
- custom_welcome_msg_json.parent.mkdir(parents=True, exist_ok=True)
- data = {}
- else:
- try:
- data = json.load(open(custom_welcome_msg_json, "r"))
- except FileNotFoundError:
- data = {}
- try:
- if msg:
- data[str(group_id)] = str(msg)
- json.dump(
- data, open(custom_welcome_msg_json, "w"), indent=4, ensure_ascii=False
- )
- logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息 {msg}")
- result += msg
- if img:
- async with aiohttp.ClientSession() as session:
- async with session.get(img, proxy=get_local_proxy()) as response:
- async with aiofiles.open(
- DATA_PATH + f"custom_welcome_msg/{group_id}.jpg", "wb"
- ) as f:
- await f.write(await response.read())
- img_result = image(abspath=DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
- logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息图片")
- except Exception as e:
- logger.error(f"GROUP {group_id} 替换群消息失败 e:{e}")
- return "替换群消息失败.."
- return f"替换群欢迎消息成功:\n{result}" + img_result
-
-
-task_data = None
-
-
-async def change_group_switch(cmd: str, group_id: int, is_super: bool = False):
- global task_data
- """
- 修改群功能状态
- :param cmd: 功能名称
- :param group_id: 群号
- :param is_super: 是否位超级用户,超级用户用于私聊开关功能状态
- """
- if not task_data:
- task_data = group_manager.get_task_data()
- group_help_file = Path(DATA_PATH) / "group_help" / f"{group_id}.png"
- status = cmd[:2]
- cmd = cmd[2:]
- type_ = "plugin"
- modules = plugins2settings_manager.get_plugin_module(cmd, True)
- if cmd == "全部被动":
- for task in task_data:
- if status == "开启":
- if not await group_manager.check_group_task_status(group_id, task):
- await group_manager.open_group_task(group_id, task)
- else:
- if await group_manager.check_group_task_status(group_id, task):
- await group_manager.close_group_task(group_id, task)
- return f"已 {status} 全部被动技能!"
- if cmd in [task_data[x] for x in task_data.keys()]:
- type_ = "task"
- modules = [x for x in task_data.keys() if task_data[x] == cmd]
- for module in modules:
- if is_super:
- module = f"{module}:super"
- if status == "开启":
- if type_ == "task":
- if await group_manager.check_group_task_status(group_id, module):
- return f"被动 {task_data[module]} 正处于开启状态!不要重复开启."
- await group_manager.open_group_task(group_id, module)
- else:
- if group_manager.get_plugin_status(module, group_id):
- return f"功能 {cmd} 正处于开启状态!不要重复开启."
- group_manager.unblock_plugin(module, group_id)
- else:
- if type_ == "task":
- if not await group_manager.check_group_task_status(group_id, module):
- return f"被动 {task_data[module]} 正处于关闭状态!不要重复关闭."
- await group_manager.close_group_task(group_id, module)
- else:
- if not group_manager.get_plugin_status(module, group_id):
- return f"功能 {cmd} 正处于关闭状态!不要重复关闭."
- group_manager.block_plugin(module, group_id)
- if group_help_file.exists():
- group_help_file.unlink()
- if is_super:
- for file in os.listdir(Path(DATA_PATH) / 'group_help'):
- file = Path(DATA_PATH) / 'group_help' / file
- file.unlink()
- else:
- _help_image = Path(DATA_PATH) / 'group_help' / f"{group_id}.png"
- if _help_image.exists():
- _help_image.unlink()
- return f"{status} {cmd} 功能!"
-
-
-def set_plugin_status(cmd: str, block_type: str = "all"):
- """
- 设置插件功能状态(超级用户使用)
- :param cmd: 功能名称
- :param block_type: 限制类型, 'all': 私聊+群里, 'private': 私聊, 'group': 群聊
- """
- status = cmd[:2]
- cmd = cmd[2:]
- module = plugins2settings_manager.get_plugin_module(cmd)
- if status == "开启":
- plugins_manager.unblock_plugin(module)
- else:
- plugins_manager.block_plugin(module, block_type=block_type)
- for file in os.listdir(Path(DATA_PATH) / 'group_help'):
- file = Path(DATA_PATH) / 'group_help' / file
- file.unlink()
-
-
-async def get_plugin_status():
- """
- 获取功能状态
- """
- return await asyncio.get_event_loop().run_in_executor(None, _get_plugin_status)
-
-
-def _get_plugin_status() -> MessageSegment:
- """
- 合成功能状态图片
- """
- rst = "\t功能\n"
- flag_str = "状态".rjust(4) + "\n"
- for module in plugins_manager.get_data():
- flag = plugins_manager.get_plugin_block_type(module)
- flag = flag.upper() + " CLOSE" if flag else "OPEN"
- try:
- plugin_name = plugins_manager.get(module)["plugin_name"]
- if (
- "[Hidden]" in plugin_name
- or "[Admin]" in plugin_name
- or "[Superuser]" in plugin_name
- ):
- continue
- rst += f"{plugin_name}"
- except KeyError:
- rst += f"{module}"
- if plugins_manager.get(module)["error"]:
- rst += "[ERROR]"
- rst += "\n"
- flag_str += f"{flag}\n"
- height = len(rst.split("\n")) * 24
- a = CreateImg(250, height, font_size=20)
- a.text((10, 10), rst)
- b = CreateImg(200, height, font_size=20)
- b.text((10, 10), flag_str)
- A = CreateImg(500, height)
- A.paste(a)
- A.paste(b, (270, 0))
- return image(b64=A.pic2bs4())
-
-
-async def update_member_info(group_id: int, remind_superuser: bool = False) -> bool:
- """
- 更新群成员信息
- :param group_id: 群号
- :param remind_superuser: 失败信息提醒超级用户
- """
- bot = get_bot()
- _group_user_list = await bot.get_group_member_list(group_id=group_id)
- _error_member_list = []
- _exist_member_list = []
- # try:
- for user_info in _group_user_list:
- if user_info["card"] == "":
- nickname = user_info["nickname"]
- else:
- nickname = user_info["card"]
- async with db.transaction():
- # 更新权限
- if (
- user_info["role"]
- in [
- "owner",
- "admin",
- ]
- and not await LevelUser.is_group_flag(user_info["user_id"], group_id)
- ):
- await LevelUser.set_level(
- user_info["user_id"],
- user_info["group_id"],
- Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
- )
- if str(user_info["user_id"]) in bot.config.superusers:
- await LevelUser.set_level(
- user_info["user_id"], user_info["group_id"], 9
- )
- user = await GroupInfoUser.get_member_info(
- user_info["user_id"], user_info["group_id"]
- )
- if user:
- if user.user_name != nickname:
- await user.update(user_name=nickname).apply()
- logger.info(
- f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
- )
- _exist_member_list.append(int(user_info["user_id"]))
- continue
- join_time = datetime.strptime(
- time.strftime(
- "%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
- ),
- "%Y-%m-%d %H:%M:%S",
- )
- if await GroupInfoUser.add_member_info(
- user_info["user_id"],
- user_info["group_id"],
- nickname,
- join_time,
- ):
- _exist_member_list.append(int(user_info["user_id"]))
- logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
- else:
- _error_member_list.append(
- f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败\n"
- )
- _del_member_list = list(
- set(_exist_member_list).difference(
- set(await GroupInfoUser.get_group_member_id_list(group_id))
- )
- )
- if _del_member_list:
- for del_user in _del_member_list:
- if await GroupInfoUser.delete_member_info(del_user, group_id):
- logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
- else:
- logger.info(f"退群用户{del_user} 所属{group_id} 删除失败")
- if _error_member_list and remind_superuser:
- result = ""
- for error_user in _error_member_list:
- result += error_user
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]), message=result[:-1]
- )
- return True
+from typing import List
+from nonebot.adapters.cqhttp.message import MessageSegment
+from services.log import logger
+from configs.path_config import DATA_PATH
+from utils.message_builder import image
+from utils.utils import get_local_proxy, get_bot
+from pathlib import Path
+from models.group_member_info import GroupInfoUser
+from datetime import datetime
+from services.db_context import db
+from models.level_user import LevelUser
+from configs.config import Config
+from utils.manager import group_manager, plugins2settings_manager, plugins_manager
+from utils.image_utils import CreateImg
+from utils.http_utils import AsyncHttpx
+import asyncio
+import time
+import os
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+async def group_current_status(group_id: int) -> str:
+ """
+ 获取当前所有通知的开关
+ :param group_id: 群号
+ """
+ rst = "[被动技能 状态]\n"
+ _data = group_manager.get_task_data()
+ for task in _data.keys():
+ rst += f'{_data[task]}: {"√" if await group_manager.check_group_task_status(group_id, task) else "×"}\n'
+ return rst.strip()
+
+
+custom_welcome_msg_json = (
+ Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
+)
+
+
+async def custom_group_welcome(
+ msg: str, imgs: List[str], user_id: int, group_id: int
+) -> str:
+ """
+ 替换群欢迎消息
+ :param msg: 欢迎消息文本
+ :param imgs: 欢迎消息图片,只取第一张
+ :param user_id: 用户id,用于log记录
+ :param group_id: 群号
+ """
+ img_result = ""
+ img = imgs[0] if imgs else ""
+ result = ""
+ if os.path.exists(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg"):
+ os.remove(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
+ if not custom_welcome_msg_json.exists():
+ custom_welcome_msg_json.parent.mkdir(parents=True, exist_ok=True)
+ data = {}
+ else:
+ try:
+ data = json.load(open(custom_welcome_msg_json, "r"))
+ except FileNotFoundError:
+ data = {}
+ try:
+ if msg:
+ data[str(group_id)] = str(msg)
+ json.dump(
+ data, open(custom_welcome_msg_json, "w"), indent=4, ensure_ascii=False
+ )
+ logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息 {msg}")
+ result += msg
+ if img:
+ await AsyncHttpx.download_file(img, DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
+ img_result = image(abspath=DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
+ logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息图片")
+ except Exception as e:
+ logger.error(f"GROUP {group_id} 替换群消息失败 e:{e}")
+ return "替换群消息失败.."
+ return f"替换群欢迎消息成功:\n{result}" + img_result
+
+
+task_data = None
+
+
+async def change_group_switch(cmd: str, group_id: int, is_super: bool = False):
+ global task_data
+ """
+ 修改群功能状态
+ :param cmd: 功能名称
+ :param group_id: 群号
+ :param is_super: 是否位超级用户,超级用户用于私聊开关功能状态
+ """
+ if not task_data:
+ task_data = group_manager.get_task_data()
+ group_help_file = Path(DATA_PATH) / "group_help" / f"{group_id}.png"
+ status = cmd[:2]
+ cmd = cmd[2:]
+ type_ = "plugin"
+ modules = plugins2settings_manager.get_plugin_module(cmd, True)
+ if cmd == "全部被动":
+ for task in task_data:
+ if status == "开启":
+ if not await group_manager.check_group_task_status(group_id, task):
+ await group_manager.open_group_task(group_id, task)
+ else:
+ if await group_manager.check_group_task_status(group_id, task):
+ await group_manager.close_group_task(group_id, task)
+ return f"已 {status} 全部被动技能!"
+ if cmd in [task_data[x] for x in task_data.keys()]:
+ type_ = "task"
+ modules = [x for x in task_data.keys() if task_data[x] == cmd]
+ for module in modules:
+ if is_super:
+ module = f"{module}:super"
+ if status == "开启":
+ if type_ == "task":
+ if await group_manager.check_group_task_status(group_id, module):
+ return f"被动 {task_data[module]} 正处于开启状态!不要重复开启."
+ await group_manager.open_group_task(group_id, module)
+ else:
+ if group_manager.get_plugin_status(module, group_id):
+ return f"功能 {cmd} 正处于开启状态!不要重复开启."
+ group_manager.unblock_plugin(module, group_id)
+ else:
+ if type_ == "task":
+ if not await group_manager.check_group_task_status(group_id, module):
+ return f"被动 {task_data[module]} 正处于关闭状态!不要重复关闭."
+ await group_manager.close_group_task(group_id, module)
+ else:
+ if not group_manager.get_plugin_status(module, group_id):
+ return f"功能 {cmd} 正处于关闭状态!不要重复关闭."
+ group_manager.block_plugin(module, group_id)
+ if group_help_file.exists():
+ group_help_file.unlink()
+ if is_super:
+ for file in os.listdir(Path(DATA_PATH) / 'group_help'):
+ file = Path(DATA_PATH) / 'group_help' / file
+ file.unlink()
+ else:
+ _help_image = Path(DATA_PATH) / 'group_help' / f"{group_id}.png"
+ if _help_image.exists():
+ _help_image.unlink()
+ return f"{status} {cmd} 功能!"
+
+
+def set_plugin_status(cmd: str, block_type: str = "all"):
+ """
+ 设置插件功能状态(超级用户使用)
+ :param cmd: 功能名称
+ :param block_type: 限制类型, 'all': 私聊+群里, 'private': 私聊, 'group': 群聊
+ """
+ status = cmd[:2]
+ cmd = cmd[2:]
+ module = plugins2settings_manager.get_plugin_module(cmd)
+ if status == "开启":
+ plugins_manager.unblock_plugin(module)
+ else:
+ plugins_manager.block_plugin(module, block_type=block_type)
+ for file in os.listdir(Path(DATA_PATH) / 'group_help'):
+ file = Path(DATA_PATH) / 'group_help' / file
+ file.unlink()
+
+
+async def get_plugin_status():
+ """
+ 获取功能状态
+ """
+ return await asyncio.get_event_loop().run_in_executor(None, _get_plugin_status)
+
+
+def _get_plugin_status() -> MessageSegment:
+ """
+ 合成功能状态图片
+ """
+ rst = "\t功能\n"
+ flag_str = "状态".rjust(4) + "\n"
+ for module in plugins_manager.get_data():
+ flag = plugins_manager.get_plugin_block_type(module)
+ flag = flag.upper() + " CLOSE" if flag else "OPEN"
+ try:
+ plugin_name = plugins_manager.get(module)["plugin_name"]
+ if (
+ "[Hidden]" in plugin_name
+ or "[Admin]" in plugin_name
+ or "[Superuser]" in plugin_name
+ ):
+ continue
+ rst += f"{plugin_name}"
+ except KeyError:
+ rst += f"{module}"
+ if plugins_manager.get(module)["error"]:
+ rst += "[ERROR]"
+ rst += "\n"
+ flag_str += f"{flag}\n"
+ height = len(rst.split("\n")) * 24
+ a = CreateImg(250, height, font_size=20)
+ a.text((10, 10), rst)
+ b = CreateImg(200, height, font_size=20)
+ b.text((10, 10), flag_str)
+ A = CreateImg(500, height)
+ A.paste(a)
+ A.paste(b, (270, 0))
+ return image(b64=A.pic2bs4())
+
+
+async def update_member_info(group_id: int, remind_superuser: bool = False) -> bool:
+ """
+ 更新群成员信息
+ :param group_id: 群号
+ :param remind_superuser: 失败信息提醒超级用户
+ """
+ bot = get_bot()
+ _group_user_list = await bot.get_group_member_list(group_id=group_id)
+ _error_member_list = []
+ _exist_member_list = []
+ # try:
+ for user_info in _group_user_list:
+ if user_info["card"] == "":
+ nickname = user_info["nickname"]
+ else:
+ nickname = user_info["card"]
+ async with db.transaction():
+ # 更新权限
+ if (
+ user_info["role"]
+ in [
+ "owner",
+ "admin",
+ ]
+ and not await LevelUser.is_group_flag(user_info["user_id"], group_id)
+ ):
+ await LevelUser.set_level(
+ user_info["user_id"],
+ user_info["group_id"],
+ Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
+ )
+ if str(user_info["user_id"]) in bot.config.superusers:
+ await LevelUser.set_level(
+ user_info["user_id"], user_info["group_id"], 9
+ )
+ user = await GroupInfoUser.get_member_info(
+ user_info["user_id"], user_info["group_id"]
+ )
+ if user:
+ if user.user_name != nickname:
+ await user.update(user_name=nickname).apply()
+ logger.info(
+ f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
+ )
+ _exist_member_list.append(int(user_info["user_id"]))
+ continue
+ join_time = datetime.strptime(
+ time.strftime(
+ "%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
+ ),
+ "%Y-%m-%d %H:%M:%S",
+ )
+ if await GroupInfoUser.add_member_info(
+ user_info["user_id"],
+ user_info["group_id"],
+ nickname,
+ join_time,
+ ):
+ _exist_member_list.append(int(user_info["user_id"]))
+ logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
+ else:
+ _error_member_list.append(
+ f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败\n"
+ )
+ _del_member_list = list(
+ set(_exist_member_list).difference(
+ set(await GroupInfoUser.get_group_member_id_list(group_id))
+ )
+ )
+ if _del_member_list:
+ for del_user in _del_member_list:
+ if await GroupInfoUser.delete_member_info(del_user, group_id):
+ logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
+ else:
+ logger.info(f"退群用户{del_user} 所属{group_id} 删除失败")
+ if _error_member_list and remind_superuser:
+ result = ""
+ for error_user in _error_member_list:
+ result += error_user
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]), message=result[:-1]
+ )
+ return True
diff --git a/basic_plugins/admin_bot_manage/rule.py b/basic_plugins/admin_bot_manage/rule.py
old mode 100644
new mode 100755
diff --git a/basic_plugins/admin_bot_manage/switch_rule.py b/basic_plugins/admin_bot_manage/switch_rule.py
old mode 100644
new mode 100755
index fee7660b..7d580610
--- a/basic_plugins/admin_bot_manage/switch_rule.py
+++ b/basic_plugins/admin_bot_manage/switch_rule.py
@@ -1,107 +1,107 @@
-from nonebot import on_command, on_message
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent, GROUP
-from .data_source import (
- change_group_switch,
- set_plugin_status,
- get_plugin_status,
- group_current_status,
-)
-from services.log import logger
-from configs.config import NICKNAME, Config
-from utils.utils import get_message_text, is_number
-from nonebot.permission import SUPERUSER
-from .rule import switch_rule
-
-
-__zx_plugin_name__ = "群功能开关 [Admin]"
-
-__plugin_usage__ = """
-usage:
- 群内功能与被动技能开关
- 指令:
- 开启/关闭[功能]
- 群被动状态
- 开启全部被动
- 关闭全部被动
- 示例:开启/关闭色图
-""".strip()
-__plugin_superuser_usage__ = """
-usage:
- 功能总开关与指定群禁用
- 指令:
- 功能状态
- 开启/关闭[功能] [group]
- 开启/关闭[功能] ['private'/'group']
-""".strip()
-__plugin_des__ = "群内功能开关"
-__plugin_cmd__ = [
- "开启/关闭[功能]",
- "群被动状态",
- "开启全部被动",
- "关闭全部被动",
- "功能状态 [_superuser]",
- "开启/关闭[功能] [group] [_superuser]",
- "开启/关闭[功能] ['private'/'group'] [_superuser]",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "admin_level": Config.get_config("admin_bot_manage", "CHANGE_GROUP_SWITCH_LEVEL"),
- "cmd": ["开启功能", "关闭功能", "开关"]
-}
-
-switch_rule_matcher = on_message(rule=switch_rule, priority=4, block=True)
-
-plugins_status = on_command("功能状态", permission=SUPERUSER, priority=5, block=True)
-
-group_task_status = on_command("群被动状态", permission=GROUP, priority=5, block=True)
-
-
-@switch_rule_matcher.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- _cmd = get_message_text(event.json()).split()[0]
- if isinstance(event, GroupMessageEvent):
- await switch_rule_matcher.send(await change_group_switch(_cmd, event.group_id))
- logger.info(f"USER {event.user_id} GROUP {event.group_id} 使用群功能管理命令 {_cmd}")
- else:
- if str(event.user_id) in bot.config.superusers:
- block_type = " ".join(get_message_text(event.json()).split()[1:])
- block_type = block_type if block_type else "a"
- if is_number(block_type):
- if not int(block_type) in [
- g["group_id"]
- for g in await bot.get_group_list(self_id=int(bot.self_id))
- ]:
- await switch_rule_matcher.finish(f"{NICKNAME}未加入群聊:{block_type}")
- await change_group_switch(_cmd, int(block_type), True)
- group_name = (await bot.get_group_info(group_id=int(block_type)))[
- "group_name"
- ]
- await switch_rule_matcher.send(
- f"已禁用群聊 {group_name}({block_type}) 的 {_cmd[2:]} 功能"
- )
- elif block_type in ["all", "private", "group", "a", "p", "g"]:
- block_type = "all" if block_type == "a" else block_type
- block_type = "private" if block_type == "p" else block_type
- block_type = "group" if block_type == "g" else block_type
- set_plugin_status(_cmd, block_type)
- if block_type == "all":
- await switch_rule_matcher.send(f"已{_cmd[:2]}功能:{_cmd[2:]}")
- elif block_type == "private":
- await switch_rule_matcher.send(f"已在私聊中{_cmd[:2]}功能:{_cmd[2:]}")
- else:
- await switch_rule_matcher.send(f"已在群聊中{_cmd[:2]}功能:{_cmd[2:]}")
- else:
- await switch_rule_matcher.finish("格式错误:关闭[功能] [group]/[p/g]")
- logger.info(f"USER {event.user_id} 使用功能管理命令 {_cmd} | {block_type}")
-
-
-@plugins_status.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- await plugins_status.send(await get_plugin_status())
-
-
-@group_task_status.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- await group_task_status.send(await group_current_status(event.group_id))
+from nonebot import on_command, on_message
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent, GROUP
+from .data_source import (
+ change_group_switch,
+ set_plugin_status,
+ get_plugin_status,
+ group_current_status,
+)
+from services.log import logger
+from configs.config import NICKNAME, Config
+from utils.utils import get_message_text, is_number
+from nonebot.permission import SUPERUSER
+from .rule import switch_rule
+
+
+__zx_plugin_name__ = "群功能开关 [Admin]"
+
+__plugin_usage__ = """
+usage:
+ 群内功能与被动技能开关
+ 指令:
+ 开启/关闭[功能]
+ 群被动状态
+ 开启全部被动
+ 关闭全部被动
+ 示例:开启/关闭色图
+""".strip()
+__plugin_superuser_usage__ = """
+usage:
+ 功能总开关与指定群禁用
+ 指令:
+ 功能状态
+ 开启/关闭[功能] [group]
+ 开启/关闭[功能] ['private'/'group']
+""".strip()
+__plugin_des__ = "群内功能开关"
+__plugin_cmd__ = [
+ "开启/关闭[功能]",
+ "群被动状态",
+ "开启全部被动",
+ "关闭全部被动",
+ "功能状态 [_superuser]",
+ "开启/关闭[功能] [group] [_superuser]",
+ "开启/关闭[功能] ['private'/'group'] [_superuser]",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "admin_level": Config.get_config("admin_bot_manage", "CHANGE_GROUP_SWITCH_LEVEL"),
+ "cmd": ["开启功能", "关闭功能", "开关"]
+}
+
+switch_rule_matcher = on_message(rule=switch_rule, priority=4, block=True)
+
+plugins_status = on_command("功能状态", permission=SUPERUSER, priority=5, block=True)
+
+group_task_status = on_command("群被动状态", permission=GROUP, priority=5, block=True)
+
+
+@switch_rule_matcher.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ _cmd = get_message_text(event.json()).split()[0]
+ if isinstance(event, GroupMessageEvent):
+ await switch_rule_matcher.send(await change_group_switch(_cmd, event.group_id))
+ logger.info(f"USER {event.user_id} GROUP {event.group_id} 使用群功能管理命令 {_cmd}")
+ else:
+ if str(event.user_id) in bot.config.superusers:
+ block_type = " ".join(get_message_text(event.json()).split()[1:])
+ block_type = block_type if block_type else "a"
+ if is_number(block_type):
+ if not int(block_type) in [
+ g["group_id"]
+ for g in await bot.get_group_list(self_id=int(bot.self_id))
+ ]:
+ await switch_rule_matcher.finish(f"{NICKNAME}未加入群聊:{block_type}")
+ await change_group_switch(_cmd, int(block_type), True)
+ group_name = (await bot.get_group_info(group_id=int(block_type)))[
+ "group_name"
+ ]
+ await switch_rule_matcher.send(
+ f"已禁用群聊 {group_name}({block_type}) 的 {_cmd[2:]} 功能"
+ )
+ elif block_type in ["all", "private", "group", "a", "p", "g"]:
+ block_type = "all" if block_type == "a" else block_type
+ block_type = "private" if block_type == "p" else block_type
+ block_type = "group" if block_type == "g" else block_type
+ set_plugin_status(_cmd, block_type)
+ if block_type == "all":
+ await switch_rule_matcher.send(f"已{_cmd[:2]}功能:{_cmd[2:]}")
+ elif block_type == "private":
+ await switch_rule_matcher.send(f"已在私聊中{_cmd[:2]}功能:{_cmd[2:]}")
+ else:
+ await switch_rule_matcher.send(f"已在群聊中{_cmd[:2]}功能:{_cmd[2:]}")
+ else:
+ await switch_rule_matcher.finish("格式错误:关闭[功能] [group]/[p/g]")
+ logger.info(f"USER {event.user_id} 使用功能管理命令 {_cmd} | {block_type}")
+
+
+@plugins_status.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ await plugins_status.send(await get_plugin_status())
+
+
+@group_task_status.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ await group_task_status.send(await group_current_status(event.group_id))
diff --git a/basic_plugins/admin_bot_manage/timing_task.py b/basic_plugins/admin_bot_manage/timing_task.py
old mode 100644
new mode 100755
index 5bb1aadd..7761385d
--- a/basic_plugins/admin_bot_manage/timing_task.py
+++ b/basic_plugins/admin_bot_manage/timing_task.py
@@ -1,51 +1,51 @@
-from utils.utils import scheduler, get_bot
-from .data_source import update_member_info
-from services.log import logger
-from models.group_info import GroupInfo
-from asyncpg.exceptions import ConnectionDoesNotExistError, UndefinedColumnError
-
-
-__zx_plugin_name__ = '管理方面定时任务 [Hidden]'
-__plugin_usage__ = '无'
-__plugin_des__ = '成员信息和管理权限的定时更新'
-__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
-
-
-# 自动更新群员信息
-@scheduler.scheduled_job(
- "cron",
- hour=2,
- minute=1,
-)
-async def _():
- bot = get_bot()
- if bot:
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- for g in gl:
- try:
- await update_member_info(g)
- logger.info(f"更新群组 g:{g} 成功")
- except Exception as e:
- logger.error(f"更新群组错误 g:{g} e:{e}")
-
-
-# 快速更新群员信息以及管理员权限
-@scheduler.scheduled_job(
- "interval",
- minutes=5,
-)
-async def _():
- try:
- bot = get_bot()
- if bot:
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- all_group = [x.group_id for x in await GroupInfo.get_all_group()]
- for g in gl:
- if g not in all_group:
- await update_member_info(g, False)
- logger.info(f"快速更新群信息以及权限:{g}")
- except (IndexError, ConnectionDoesNotExistError, UndefinedColumnError):
- pass
+from utils.utils import scheduler, get_bot
+from .data_source import update_member_info
+from services.log import logger
+from models.group_info import GroupInfo
+from asyncpg.exceptions import ConnectionDoesNotExistError, UndefinedColumnError
+
+
+__zx_plugin_name__ = '管理方面定时任务 [Hidden]'
+__plugin_usage__ = '无'
+__plugin_des__ = '成员信息和管理权限的定时更新'
+__plugin_version__ = 0.1
+__plugin_author__ = 'HibiKier'
+
+
+# 自动更新群员信息
+@scheduler.scheduled_job(
+ "cron",
+ hour=2,
+ minute=1,
+)
+async def _():
+ bot = get_bot()
+ if bot:
+ gl = await bot.get_group_list()
+ gl = [g["group_id"] for g in gl]
+ for g in gl:
+ try:
+ await update_member_info(g)
+ logger.info(f"更新群组 g:{g} 成功")
+ except Exception as e:
+ logger.error(f"更新群组错误 g:{g} e:{e}")
+
+
+# 快速更新群员信息以及管理员权限
+@scheduler.scheduled_job(
+ "interval",
+ minutes=5,
+)
+async def _():
+ try:
+ bot = get_bot()
+ if bot:
+ gl = await bot.get_group_list()
+ gl = [g["group_id"] for g in gl]
+ all_group = [x.group_id for x in await GroupInfo.get_all_group()]
+ for g in gl:
+ if g not in all_group:
+ await update_member_info(g, False)
+ logger.info(f"快速更新群信息以及权限:{g}")
+ except (IndexError, ConnectionDoesNotExistError, UndefinedColumnError):
+ pass
diff --git a/basic_plugins/admin_bot_manage/update_group_member_info.py b/basic_plugins/admin_bot_manage/update_group_member_info.py
old mode 100644
new mode 100755
index 9a5cddec..c7258a36
--- a/basic_plugins/admin_bot_manage/update_group_member_info.py
+++ b/basic_plugins/admin_bot_manage/update_group_member_info.py
@@ -1,41 +1,41 @@
-from nonebot import on_command, on_notice
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
-from .data_source import update_member_info
-
-__zx_plugin_name__ = "更新群组成员列表 [Admin]"
-__plugin_usage__ = """
-usage:
- 更新群组成员的基本信息
- 指令:
- 更新群组成员列表/更新群组成员信息
-""".strip()
-__plugin_des__ = '更新群组成员列表'
-__plugin_cmd__ = ['更新群组成员列表']
-__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
-__plugin_settings__ = {
- "admin_level": 1,
-}
-
-
-refresh_member_group = on_command(
- "更新群组成员列表", aliases={"更新群组成员信息"}, permission=GROUP, priority=5, block=True
-)
-
-
-@refresh_member_group.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- if await update_member_info(event.group_id):
- await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
- else:
- await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
-
-
-group_increase_handle = on_notice(priority=1, block=False)
-
-
-@group_increase_handle.handle()
-async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
- if event.user_id == int(bot.self_id):
- await update_member_info(event.group_id)
+from nonebot import on_command, on_notice
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
+from .data_source import update_member_info
+
+__zx_plugin_name__ = "更新群组成员列表 [Admin]"
+__plugin_usage__ = """
+usage:
+ 更新群组成员的基本信息
+ 指令:
+ 更新群组成员列表/更新群组成员信息
+""".strip()
+__plugin_des__ = '更新群组成员列表'
+__plugin_cmd__ = ['更新群组成员列表']
+__plugin_version__ = 0.1
+__plugin_author__ = 'HibiKier'
+__plugin_settings__ = {
+ "admin_level": 1,
+}
+
+
+refresh_member_group = on_command(
+ "更新群组成员列表", aliases={"更新群组成员信息"}, permission=GROUP, priority=5, block=True
+)
+
+
+@refresh_member_group.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ if await update_member_info(event.group_id):
+ await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
+ else:
+ await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
+
+
+group_increase_handle = on_notice(priority=1, block=False)
+
+
+@group_increase_handle.handle()
+async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
+ if event.user_id == int(bot.self_id):
+ await update_member_info(event.group_id)
diff --git a/basic_plugins/admin_help/__init__.py b/basic_plugins/admin_help/__init__.py
old mode 100644
new mode 100755
index 1262eb22..0b110162
--- a/basic_plugins/admin_help/__init__.py
+++ b/basic_plugins/admin_help/__init__.py
@@ -1,27 +1,27 @@
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.adapters import Bot
-from nonebot.adapters.cqhttp import GroupMessageEvent
-from utils.message_builder import image
-from .data_source import create_help_image, admin_help_image
-
-
-__zx_plugin_name__ = '管理帮助 [Admin]'
-__plugin_usage__ = '管理员帮助,在群内回复“管理员帮助”'
-__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
-__plugin_settings__ = {
- "admin_level": 1,
-}
-
-admin_help = on_command("管理员帮助", aliases={"管理帮助"}, priority=5, block=True)
-
-if admin_help_image.exists():
- admin_help_image.unlink()
-
-
-@admin_help.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- if not admin_help_image.exists():
- await create_help_image()
- await admin_help.send(image('admin_help_img.png'))
+from nonebot import on_command
+from nonebot.typing import T_State
+from nonebot.adapters import Bot
+from nonebot.adapters.cqhttp import GroupMessageEvent
+from utils.message_builder import image
+from .data_source import create_help_image, admin_help_image
+
+
+__zx_plugin_name__ = '管理帮助 [Admin]'
+__plugin_usage__ = '管理员帮助,在群内回复“管理员帮助”'
+__plugin_version__ = 0.1
+__plugin_author__ = 'HibiKier'
+__plugin_settings__ = {
+ "admin_level": 1,
+}
+
+admin_help = on_command("管理员帮助", aliases={"管理帮助"}, priority=5, block=True)
+
+if admin_help_image.exists():
+ admin_help_image.unlink()
+
+
+@admin_help.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ if not admin_help_image.exists():
+ await create_help_image()
+ await admin_help.send(image('admin_help_img.png'))
diff --git a/basic_plugins/admin_help/data_source.py b/basic_plugins/admin_help/data_source.py
old mode 100644
new mode 100755
index 9d8959dc..65862fdb
--- a/basic_plugins/admin_help/data_source.py
+++ b/basic_plugins/admin_help/data_source.py
@@ -1,94 +1,94 @@
-from utils.image_utils import CreateImg
-from configs.path_config import IMAGE_PATH
-from services.log import logger
-from utils.utils import get_matchers
-from utils.manager import group_manager
-from nonebot.adapters.cqhttp import Bot
-from pathlib import Path
-from nonebot import Driver
-import asyncio
-import nonebot
-
-
-driver: Driver = nonebot.get_driver()
-
-background = Path(IMAGE_PATH) / "background" / "0.png"
-
-admin_help_image = Path(IMAGE_PATH) / 'admin_help_img.png'
-
-
-@driver.on_bot_connect
-async def init_task(bot: Bot = None):
- if not group_manager.get_task_data():
- await group_manager.init_group_task()
- logger.info(f'已成功加载 {len(group_manager.get_task_data())} 个被动技能.')
-
-
-async def create_help_image():
- """
- 创建管理员帮助图片
- """
- await asyncio.get_event_loop().run_in_executor(
- None, _create_help_image
- )
-
-
-def _create_help_image():
- """
- 创建管理员帮助图片
- """
- _matchers = get_matchers()
- _plugin_name_list = []
- width = 0
- _plugin_level = {}
- for matcher in _matchers:
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- _module = _plugin.module
- try:
- plugin_name = _module.__getattribute__("__zx_plugin_name__")
- except AttributeError:
- continue
- try:
- if (
- "[admin]" in plugin_name.lower()
- and plugin_name not in _plugin_name_list
- and plugin_name != "管理帮助 [Admin]"
- ):
- _plugin_name_list.append(plugin_name)
- plugin_settings = _module.__getattribute__("__plugin_settings__")
- plugin_des = _module.__getattribute__("__plugin_des__")
- plugin_cmd = _module.__getattribute__("__plugin_cmd__")
- plugin_cmd = [x for x in plugin_cmd if "[_superuser]" not in x]
- admin_level = int(plugin_settings["admin_level"])
- if _plugin_level.get(admin_level):
- _plugin_level[admin_level].append(
- f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)
- )
- else:
- _plugin_level[admin_level] = [
- f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)
- ]
- x = len(f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)) * 23
- width = width if width > x else x
- except AttributeError:
- logger.warning(f"获取管理插件 {matcher.module}: {plugin_name} 设置失败...")
- help_str = "* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" \
- "[权限等级] 管理员帮助:\n\n"
- x = list(_plugin_level.keys())
- x.sort()
- for level in x:
- for help_ in _plugin_level[level]:
- help_str += f"\t{help_}\n\n"
- help_str += '-----[被动技能开关]-----\n\n'
- task_data = group_manager.get_task_data()
- for i, x in enumerate(task_data.keys()):
- help_str += f'{i+1}.开启/关闭{task_data[x]}\n\n'
- height = len(help_str.split("\n")) * 33
- A = CreateImg(width, height, font_size=24)
- _background = CreateImg(width, height, background=background)
- A.text((150, 110), help_str)
- A.paste(_background, alpha=True)
- A.save(admin_help_image)
- logger.info(f'已成功加载 {len(_plugin_name_list)} 条管理员命令')
-
-
+from utils.image_utils import CreateImg
+from configs.path_config import IMAGE_PATH
+from services.log import logger
+from utils.utils import get_matchers
+from utils.manager import group_manager
+from nonebot.adapters.cqhttp import Bot
+from pathlib import Path
+from nonebot import Driver
+import asyncio
+import nonebot
+
+
+driver: Driver = nonebot.get_driver()
+
+background = Path(IMAGE_PATH) / "background" / "0.png"
+
+admin_help_image = Path(IMAGE_PATH) / 'admin_help_img.png'
+
+
+@driver.on_bot_connect
+async def init_task(bot: Bot = None):
+ if not group_manager.get_task_data():
+ await group_manager.init_group_task()
+ logger.info(f'已成功加载 {len(group_manager.get_task_data())} 个被动技能.')
+
+
+async def create_help_image():
+ """
+ 创建管理员帮助图片
+ """
+ await asyncio.get_event_loop().run_in_executor(
+ None, _create_help_image
+ )
+
+
+def _create_help_image():
+ """
+ 创建管理员帮助图片
+ """
+ _matchers = get_matchers()
+ _plugin_name_list = []
+ width = 0
+ _plugin_level = {}
+ for matcher in _matchers:
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ _module = _plugin.module
+ try:
+ plugin_name = _module.__getattribute__("__zx_plugin_name__")
+ except AttributeError:
+ continue
+ try:
+ if (
+ "[admin]" in plugin_name.lower()
+ and plugin_name not in _plugin_name_list
+ and plugin_name != "管理帮助 [Admin]"
+ ):
+ _plugin_name_list.append(plugin_name)
+ plugin_settings = _module.__getattribute__("__plugin_settings__")
+ plugin_des = _module.__getattribute__("__plugin_des__")
+ plugin_cmd = _module.__getattribute__("__plugin_cmd__")
+ plugin_cmd = [x for x in plugin_cmd if "[_superuser]" not in x]
+ admin_level = int(plugin_settings["admin_level"])
+ if _plugin_level.get(admin_level):
+ _plugin_level[admin_level].append(
+ f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)
+ )
+ else:
+ _plugin_level[admin_level] = [
+ f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)
+ ]
+ x = len(f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)) * 23
+ width = width if width > x else x
+ except AttributeError:
+ logger.warning(f"获取管理插件 {matcher.module}: {plugin_name} 设置失败...")
+ help_str = "* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" \
+ "[权限等级] 管理员帮助:\n\n"
+ x = list(_plugin_level.keys())
+ x.sort()
+ for level in x:
+ for help_ in _plugin_level[level]:
+ help_str += f"\t{help_}\n\n"
+ help_str += '-----[被动技能开关]-----\n\n'
+ task_data = group_manager.get_task_data()
+ for i, x in enumerate(task_data.keys()):
+ help_str += f'{i+1}.开启/关闭{task_data[x]}\n\n'
+ height = len(help_str.split("\n")) * 33
+ A = CreateImg(width, height, font_size=24)
+ _background = CreateImg(width, height, background=background)
+ A.text((150, 110), help_str)
+ A.paste(_background, alpha=True)
+ A.save(admin_help_image)
+ logger.info(f'已成功加载 {len(_plugin_name_list)} 条管理员命令')
+
+
diff --git a/basic_plugins/apscheduler/__init__.py b/basic_plugins/apscheduler/__init__.py
old mode 100644
new mode 100755
index 5eb8463b..a12aa80e
--- a/basic_plugins/apscheduler/__init__.py
+++ b/basic_plugins/apscheduler/__init__.py
@@ -1,195 +1,195 @@
-from utils.message_builder import image
-from utils.utils import scheduler, get_bot
-from nonebot import on_message
-from services.log import logger
-from models.group_info import GroupInfo
-from models.friend_user import FriendUser
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from configs.config import NICKNAME
-from utils.manager import group_manager
-
-__zx_plugin_name__ = "定时任务相关 [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_task__ = {'zwa': '早晚安'}
-
-
-x = on_message(priority=9, block=False)
-
-
-# 早上好
-@scheduler.scheduled_job(
- "cron",
- hour=6,
- minute=1,
-)
-async def _():
- try:
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- for g in gl:
- if await group_manager.check_group_task_status(g, 'zwa'):
- result = image("zao.jpg", "zhenxun")
- try:
- await bot.send_group_msg(group_id=g, message="早上好" + result)
- except ActionFailed:
- logger.warning(f"{g} 群被禁言中,无法发送早安")
- except Exception as e:
- logger.error(f"早晚安错误 e:{e}")
-
-
-# 睡觉了
-@scheduler.scheduled_job(
- "cron",
- hour=23,
- minute=59,
-)
-async def _():
- try:
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- for g in gl:
- if await group_manager.check_group_task_status(g, 'zwa'):
- result = image("sleep.jpg", "zhenxun")
- try:
- await bot.send_group_msg(
- group_id=g, message=f"{NICKNAME}要睡觉了,你们也要早点睡呀" + result
- )
- except ActionFailed:
- logger.warning(f"{g} 群被禁言中,无法发送晚安")
- except Exception as e:
- logger.error(f"早晚安错误 e:{e}")
-
-
-# 自动更新群组信息
-@scheduler.scheduled_job(
- "cron",
- hour=3,
- minute=1,
-)
-async def _():
- try:
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- for g in gl:
- group_info = await bot.get_group_info(group_id=g)
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- )
- logger.info(f"自动更新群组 {g} 信息成功")
- except Exception as e:
- logger.error(f"自动更新群组信息错误 e:{e}")
-
-
-# 自动更新好友信息
-@scheduler.scheduled_job(
- "cron",
- hour=3,
- minute=1,
-)
-async def _():
- try:
- bot = get_bot()
- fl = await bot.get_friend_list()
- for f in fl:
- if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
- logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
- else:
- logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
- except Exception as e:
- logger.error(f"自动更新群组信息错误 e:{e}")
-
-
- # 一次性任务
-# 固定时间触发,仅触发一次:
-#
-# from datetime import datetime
-#
-# @nonebot.scheduler.scheduled_job(
-# 'date',
-# run_date=datetime(2021, 1, 1, 0, 0),
-# # timezone=None,
-# )
-# async def _():
-# await bot.send_group_msg(group_id=123456,
-# message="2021,新年快乐!")
-
-# 定期任务
-# 从 start_date 开始到 end_date 结束,根据类似 Cron
-#
-# 的规则触发任务:
-#
-# @nonebot.scheduler.scheduled_job(
-# 'cron',
-# # year=None,
-# # month=None,
-# # day=None,
-# # week=None,
-# day_of_week="mon,tue,wed,thu,fri",
-# hour=7,
-# # minute=None,
-# # second=None,
-# # start_date=None,
-# # end_date=None,
-# # timezone=None,
-# )
-# async def _():
-# await bot.send_group_msg(group_id=123456,
-# message="起床啦!")
-
-# 间隔任务
-#
-# interval 触发器
-#
-# 从 start_date 开始,每间隔一段时间触发,到 end_date 结束:
-#
-# @nonebot.scheduler.scheduled_job(
-# 'interval',
-# # weeks=0,
-# # days=0,
-# # hours=0,
-# minutes=5,
-# # seconds=0,
-# # start_date=time.now(),
-# # end_date=None,
-# )
-# async def _():
-# has_new_item = check_new_item()
-# if has_new_item:
-# await bot.send_group_msg(group_id=123456,
-# message="XX有更新啦!")
-
-
-# 动态的计划任务
-# import datetime
-#
-# from apscheduler.triggers.date import DateTrigger # 一次性触发器
-# # from apscheduler.triggers.cron import CronTrigger # 定期触发器
-# # from apscheduler.triggers.interval import IntervalTrigger # 间隔触发器
-# from nonebot import on_command, scheduler
-#
-# @on_command('赖床')
-# async def _(session: CommandSession):
-# await session.send('我会在5分钟后再喊你')
-#
-# # 制作一个“5分钟后”触发器
-# delta = datetime.timedelta(minutes=5)
-# trigger = DateTrigger(
-# run_date=datetime.datetime.now() + delta
-# )
-#
-# # 添加任务
-# scheduler.add_job(
-# func=session.send, # 要添加任务的函数,不要带参数
-# trigger=trigger, # 触发器
-# args=('不要再赖床啦!',), # 函数的参数列表,注意:只有一个值时,不能省略末尾的逗号
-# # kwargs=None,
-# misfire_grace_time=60, # 允许的误差时间,建议不要省略
-# # jobstore='default', # 任务储存库,在下一小节中说明
-# )
+from utils.message_builder import image
+from utils.utils import scheduler, get_bot
+from nonebot import on_message
+from services.log import logger
+from models.group_info import GroupInfo
+from models.friend_user import FriendUser
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from configs.config import NICKNAME
+from utils.manager import group_manager
+
+__zx_plugin_name__ = "定时任务相关 [Hidden]"
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_task__ = {'zwa': '早晚安'}
+
+
+x = on_message(priority=9, block=False)
+
+
+# 早上好
+@scheduler.scheduled_job(
+ "cron",
+ hour=6,
+ minute=1,
+)
+async def _():
+ try:
+ bot = get_bot()
+ gl = await bot.get_group_list()
+ gl = [g["group_id"] for g in gl]
+ for g in gl:
+ if await group_manager.check_group_task_status(g, 'zwa'):
+ result = image("zao.jpg", "zhenxun")
+ try:
+ await bot.send_group_msg(group_id=g, message="早上好" + result)
+ except ActionFailed:
+ logger.warning(f"{g} 群被禁言中,无法发送早安")
+ except Exception as e:
+ logger.error(f"早晚安错误 e:{e}")
+
+
+# 睡觉了
+@scheduler.scheduled_job(
+ "cron",
+ hour=23,
+ minute=59,
+)
+async def _():
+ try:
+ bot = get_bot()
+ gl = await bot.get_group_list()
+ gl = [g["group_id"] for g in gl]
+ for g in gl:
+ if await group_manager.check_group_task_status(g, 'zwa'):
+ result = image("sleep.jpg", "zhenxun")
+ try:
+ await bot.send_group_msg(
+ group_id=g, message=f"{NICKNAME}要睡觉了,你们也要早点睡呀" + result
+ )
+ except ActionFailed:
+ logger.warning(f"{g} 群被禁言中,无法发送晚安")
+ except Exception as e:
+ logger.error(f"早晚安错误 e:{e}")
+
+
+# 自动更新群组信息
+@scheduler.scheduled_job(
+ "cron",
+ hour=3,
+ minute=1,
+)
+async def _():
+ try:
+ bot = get_bot()
+ gl = await bot.get_group_list()
+ gl = [g["group_id"] for g in gl]
+ for g in gl:
+ group_info = await bot.get_group_info(group_id=g)
+ await GroupInfo.add_group_info(
+ group_info["group_id"],
+ group_info["group_name"],
+ group_info["max_member_count"],
+ group_info["member_count"],
+ )
+ logger.info(f"自动更新群组 {g} 信息成功")
+ except Exception as e:
+ logger.error(f"自动更新群组信息错误 e:{e}")
+
+
+# 自动更新好友信息
+@scheduler.scheduled_job(
+ "cron",
+ hour=3,
+ minute=1,
+)
+async def _():
+ try:
+ bot = get_bot()
+ fl = await bot.get_friend_list()
+ for f in fl:
+ if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
+ logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
+ else:
+ logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
+ except Exception as e:
+ logger.error(f"自动更新群组信息错误 e:{e}")
+
+
+ # 一次性任务
+# 固定时间触发,仅触发一次:
+#
+# from datetime import datetime
+#
+# @nonebot.scheduler.scheduled_job(
+# 'date',
+# run_date=datetime(2021, 1, 1, 0, 0),
+# # timezone=None,
+# )
+# async def _():
+# await bot.send_group_msg(group_id=123456,
+# message="2021,新年快乐!")
+
+# 定期任务
+# 从 start_date 开始到 end_date 结束,根据类似 Cron
+#
+# 的规则触发任务:
+#
+# @nonebot.scheduler.scheduled_job(
+# 'cron',
+# # year=None,
+# # month=None,
+# # day=None,
+# # week=None,
+# day_of_week="mon,tue,wed,thu,fri",
+# hour=7,
+# # minute=None,
+# # second=None,
+# # start_date=None,
+# # end_date=None,
+# # timezone=None,
+# )
+# async def _():
+# await bot.send_group_msg(group_id=123456,
+# message="起床啦!")
+
+# 间隔任务
+#
+# interval 触发器
+#
+# 从 start_date 开始,每间隔一段时间触发,到 end_date 结束:
+#
+# @nonebot.scheduler.scheduled_job(
+# 'interval',
+# # weeks=0,
+# # days=0,
+# # hours=0,
+# minutes=5,
+# # seconds=0,
+# # start_date=time.now(),
+# # end_date=None,
+# )
+# async def _():
+# has_new_item = check_new_item()
+# if has_new_item:
+# await bot.send_group_msg(group_id=123456,
+# message="XX有更新啦!")
+
+
+# 动态的计划任务
+# import datetime
+#
+# from apscheduler.triggers.date import DateTrigger # 一次性触发器
+# # from apscheduler.triggers.cron import CronTrigger # 定期触发器
+# # from apscheduler.triggers.interval import IntervalTrigger # 间隔触发器
+# from nonebot import on_command, scheduler
+#
+# @on_command('赖床')
+# async def _(session: CommandSession):
+# await session.send('我会在5分钟后再喊你')
+#
+# # 制作一个“5分钟后”触发器
+# delta = datetime.timedelta(minutes=5)
+# trigger = DateTrigger(
+# run_date=datetime.datetime.now() + delta
+# )
+#
+# # 添加任务
+# scheduler.add_job(
+# func=session.send, # 要添加任务的函数,不要带参数
+# trigger=trigger, # 触发器
+# args=('不要再赖床啦!',), # 函数的参数列表,注意:只有一个值时,不能省略末尾的逗号
+# # kwargs=None,
+# misfire_grace_time=60, # 允许的误差时间,建议不要省略
+# # jobstore='default', # 任务储存库,在下一小节中说明
+# )
diff --git a/basic_plugins/ban/__init__.py b/basic_plugins/ban/__init__.py
old mode 100644
new mode 100755
index 7592c44a..a9f6f567
--- a/basic_plugins/ban/__init__.py
+++ b/basic_plugins/ban/__init__.py
@@ -1,197 +1,207 @@
-from nonebot import on_command
-from models.ban_user import BanUser
-from models.level_user import LevelUser
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot
-from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
-from utils.utils import get_message_at, get_message_text, is_number
-from configs.config import NICKNAME, Config
-from nonebot.permission import SUPERUSER
-from services.log import logger
-
-
-__zx_plugin_name__ = "封禁Ban用户 [Admin]"
-__plugin_usage__ = """
-usage:
- 将用户拉入或拉出黑名单
- 指令:
- .ban [at] ?[小时] ?[分钟]
- .unban
- 示例:.ban @user
- 示例:.ban @user 6
- 示例:.ban @user 3 10
- 示例:.unban @user
-""".strip()
-__plugin_superuser_usage__ = """
-usage:
- 屏蔽用户消息,相当于最上级.ban
- 指令:
- b了 [at]
- 示例:b了 @user
-""".strip()
-__plugin_des__ = '你被逮捕了!丢进小黑屋!'
-__plugin_cmd__ = ['.ban [at] ?[小时] ?[分钟]', '.unban [at]', 'b了 [at] [_superuser]']
-__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
-__plugin_settings__ = {
- "admin_level": Config.get_config("ban", "BAN_LEVEL"),
- "cmd": ['.ban', '.unban', 'ban', 'unban']
-}
-__plugin_configs__ = {
- "BAN_LEVEL [LEVEL]": {
- "value": 5,
- "help": "ban/unban所需要的管理员权限等级",
- "default_value": 5
- }
-}
-
-
-ban = on_command(
- ".ban",
- aliases={".unban", "/ban", "/unban"},
- priority=5,
- block=True,
-)
-
-super_ban = on_command('b了', permission=SUPERUSER, priority=5, block=True)
-
-
-@ban.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- result = ""
- qq = get_message_at(event.json())
- if qq:
- qq = qq[0]
- user_name = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
- user_name = user_name['card'] if user_name['card'] else user_name['nickname']
- msg = get_message_text(event.json())
- if msg:
- msg = msg.split()
- if len(msg) == 2:
- if not is_number(msg[0].strip()) or not is_number(msg[1].strip()):
- await ban.finish("参数必须是数字!", at_sender=True)
- time = int(msg[0]) * 60 * 60 + int(msg[1]) * 60
- else:
- if not is_number(msg[0].strip()):
- await ban.finish("参数必须是数字!", at_sender=True)
- time = int(msg[0]) * 60 * 60
- else:
- time = -1
- if state["_prefix"]["raw_command"] in [".ban", "/ban"]:
- if (
- await LevelUser.get_user_level(event.user_id, event.group_id)
- <= await LevelUser.get_user_level(qq, event.group_id)
- and str(event.user_id) not in bot.config.superusers
- ):
- await ban.finish(
- f"您的权限等级比对方低或相等, {NICKNAME}不能为您使用此功能!",
- at_sender=True,
- )
- if await BanUser.ban(
- qq, await LevelUser.get_user_level(event.user_id, event.group_id), time
- ):
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 封禁 时长 {time/60} 分钟"
- )
- result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
- if time != -1:
- result += f"将在 {time/60} 分钟后解封"
- else:
- time = await BanUser.check_ban_time(qq)
- if is_number(time):
- time = abs(int(time))
- if time < 60:
- time = str(time) + " 秒"
- else:
- time = str(int(time / 60)) + " 分钟"
- else:
- time += " 分钟"
- result = f"{user_name} 已在黑名单!预计 {time}后解封"
- else:
- if (
- await BanUser.check_ban_level(
- qq, await LevelUser.get_user_level(event.user_id, event.group_id)
- )
- and str(event.user_id) not in bot.config.superusers
- ):
- await ban.finish(
- f"ban掉 {user_name} 的管理员权限比您高,无法进行unban", at_sender=True
- )
- if await BanUser.unban(qq):
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 解禁"
- )
- result = f"已经把 {user_name} 从黑名单中删除了!"
- else:
- result = f"{user_name} 不在黑名单!"
- else:
- await ban.finish("艾特人了吗??", at_sender=True)
- await ban.finish(result, at_sender=True)
-
-
-@ban.handle()
-async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
- if str(event.user_id) in bot.config.superusers:
- msg = get_message_text(event.json())
- msg = msg.split()
- if is_number(msg[0]):
- qq = int(msg[0])
- if state["_prefix"]["raw_command"] in [".ban", "/ban"]:
- hour = 0
- minute = 0
- if len(msg) > 1 and is_number(msg[1]):
- hour = int(msg[1])
- if len(msg) > 2 and is_number(msg[2]):
- minute = int(msg[2])
- time = hour * 60 * 60 + minute * 60
- time = time if time else -1
- if await BanUser.ban(
- qq, 9, time
- ):
- logger.info(
- f"USER {event.user_id} 将 USER {qq} 封禁 时长 {time/60} 分钟"
- )
- result = f"已经将 {qq} 加入{NICKNAME}的黑名单了!"
- if time != -1:
- result += f"将在 {time/60} 分钟后解封"
- else:
- result += f"将在 ∞ 分钟后解封"
- await ban.send(result)
- else:
- time = await BanUser.check_ban_time(qq)
- if is_number(time):
- time = abs(int(time))
- if time < 60:
- time = str(time) + " 秒"
- else:
- time = str(int(time / 60)) + " 分钟"
- else:
- time += " 分钟"
- await ban.send(f"{qq} 已在黑名单!预计 {time}后解封")
- else:
- if await BanUser.unban(qq):
- logger.info(
- f"USER {event.user_id} 将 USER {qq} 解禁"
- )
- result = f"已经把 {qq} 从黑名单中删除了!"
- else:
- result = f"{qq} 不在黑名单!"
- await ban.send(result)
- else:
- await ban.finish('qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?', at_sender=True)
-
-
-@super_ban.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- qq = get_message_at(event.json())
- if qq:
- qq = qq[0]
- user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
- user_name = user['card'] if user['card'] else user['nickname']
- if not await BanUser.ban(qq, 10, 99999999):
- await BanUser.unban(qq)
- await BanUser.ban(qq, 10, 99999999)
- await ban.send(f"已将 {user_name} 拉入黑名单!")
- else:
- await super_ban.send('需要艾特被super ban的对象..')
-
+from nonebot import on_command
+from models.ban_user import BanUser
+from models.level_user import LevelUser
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot
+from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent, MessageEvent
+from utils.utils import get_message_at, get_message_text, is_number
+from configs.config import NICKNAME, Config
+from nonebot.permission import SUPERUSER
+from services.log import logger
+
+
+__zx_plugin_name__ = "封禁Ban用户 [Admin]"
+__plugin_usage__ = """
+usage:
+ 将用户拉入或拉出黑名单
+ 指令:
+ .ban [at] ?[小时] ?[分钟]
+ .unban
+ 示例:.ban @user
+ 示例:.ban @user 6
+ 示例:.ban @user 3 10
+ 示例:.unban @user
+""".strip()
+__plugin_superuser_usage__ = """
+usage:
+ b了=屏蔽用户消息,相当于最上级.ban
+ 跨群ban以及跨群b了
+ 指令:
+ b了 [at/qq]
+ .ban [user_id] ?[小时] ?[分钟]
+ 示例:b了 @user
+ 示例:b了 1234567
+ 示例:.ban 12345567
+""".strip()
+__plugin_des__ = '你被逮捕了!丢进小黑屋!'
+__plugin_cmd__ = ['.ban [at] ?[小时] ?[分钟]', '.unban [at]', 'b了 [at] [_superuser]']
+__plugin_version__ = 0.1
+__plugin_author__ = 'HibiKier'
+__plugin_settings__ = {
+ "admin_level": Config.get_config("ban", "BAN_LEVEL"),
+ "cmd": ['.ban', '.unban', 'ban', 'unban']
+}
+__plugin_configs__ = {
+ "BAN_LEVEL [LEVEL]": {
+ "value": 5,
+ "help": "ban/unban所需要的管理员权限等级",
+ "default_value": 5
+ }
+}
+
+
+ban = on_command(
+ ".ban",
+ aliases={".unban", "/ban", "/unban"},
+ priority=5,
+ block=True,
+)
+
+super_ban = on_command('b了', permission=SUPERUSER, priority=5, block=True)
+
+
+@ban.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ result = ""
+ qq = get_message_at(event.json())
+ if qq:
+ qq = qq[0]
+ user_name = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
+ user_name = user_name['card'] if user_name['card'] else user_name['nickname']
+ msg = get_message_text(event.json())
+ if msg:
+ msg = msg.split()
+ if len(msg) == 2:
+ if not is_number(msg[0].strip()) or not is_number(msg[1].strip()):
+ await ban.finish("参数必须是数字!", at_sender=True)
+ time = int(msg[0]) * 60 * 60 + int(msg[1]) * 60
+ else:
+ if not is_number(msg[0].strip()):
+ await ban.finish("参数必须是数字!", at_sender=True)
+ time = int(msg[0]) * 60 * 60
+ else:
+ time = -1
+ if state["_prefix"]["raw_command"] in [".ban", "/ban"]:
+ if (
+ await LevelUser.get_user_level(event.user_id, event.group_id)
+ <= await LevelUser.get_user_level(qq, event.group_id)
+ and str(event.user_id) not in bot.config.superusers
+ ):
+ await ban.finish(
+ f"您的权限等级比对方低或相等, {NICKNAME}不能为您使用此功能!",
+ at_sender=True,
+ )
+ if await BanUser.ban(
+ qq, await LevelUser.get_user_level(event.user_id, event.group_id), time
+ ):
+ logger.info(
+ f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 封禁 时长 {time/60} 分钟"
+ )
+ result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
+ if time != -1:
+ result += f"将在 {time/60} 分钟后解封"
+ else:
+ time = await BanUser.check_ban_time(qq)
+ if is_number(time):
+ time = abs(int(time))
+ if time < 60:
+ time = str(time) + " 秒"
+ else:
+ time = str(int(time / 60)) + " 分钟"
+ else:
+ time += " 分钟"
+ result = f"{user_name} 已在黑名单!预计 {time}后解封"
+ else:
+ if (
+ await BanUser.check_ban_level(
+ qq, await LevelUser.get_user_level(event.user_id, event.group_id)
+ )
+ and str(event.user_id) not in bot.config.superusers
+ ):
+ await ban.finish(
+ f"ban掉 {user_name} 的管理员权限比您高,无法进行unban", at_sender=True
+ )
+ if await BanUser.unban(qq):
+ logger.info(
+ f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 解禁"
+ )
+ result = f"已经把 {user_name} 从黑名单中删除了!"
+ else:
+ result = f"{user_name} 不在黑名单!"
+ else:
+ await ban.finish("艾特人了吗??", at_sender=True)
+ await ban.finish(result, at_sender=True)
+
+
+@ban.handle()
+async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
+ if str(event.user_id) in bot.config.superusers:
+ msg = get_message_text(event.json())
+ msg = msg.split()
+ if is_number(msg[0]):
+ qq = int(msg[0])
+ if state["_prefix"]["raw_command"] in [".ban", "/ban"]:
+ hour = 0
+ minute = 0
+ if len(msg) > 1 and is_number(msg[1]):
+ hour = int(msg[1])
+ if len(msg) > 2 and is_number(msg[2]):
+ minute = int(msg[2])
+ time = hour * 60 * 60 + minute * 60
+ time = time if time else -1
+ if await BanUser.ban(
+ qq, 9, time
+ ):
+ logger.info(
+ f"USER {event.user_id} 将 USER {qq} 封禁 时长 {time/60} 分钟"
+ )
+ result = f"已经将 {qq} 加入{NICKNAME}的黑名单了!"
+ if time != -1:
+ result += f"将在 {time/60} 分钟后解封"
+ else:
+ result += f"将在 ∞ 分钟后解封"
+ await ban.send(result)
+ else:
+ time = await BanUser.check_ban_time(qq)
+ if is_number(time):
+ time = abs(int(time))
+ if time < 60:
+ time = str(time) + " 秒"
+ else:
+ time = str(int(time / 60)) + " 分钟"
+ else:
+ time += " 分钟"
+ await ban.send(f"{qq} 已在黑名单!预计 {time}后解封")
+ else:
+ if await BanUser.unban(qq):
+ logger.info(
+ f"USER {event.user_id} 将 USER {qq} 解禁"
+ )
+ result = f"已经把 {qq} 从黑名单中删除了!"
+ else:
+ result = f"{qq} 不在黑名单!"
+ await ban.send(result)
+ else:
+ await ban.finish('qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?', at_sender=True)
+
+
+@super_ban.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if isinstance(event, GroupMessageEvent):
+ qq = get_message_at(event.json())
+ else:
+ qq = get_message_text(event.json())
+ if not is_number(qq):
+ await super_ban.finish("对象qq必须为纯数字...")
+ qq = [qq]
+ if qq:
+ qq = qq[0]
+ user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
+ user_name = user['card'] if user['card'] else user['nickname']
+ if not await BanUser.ban(qq, 10, 99999999):
+ await BanUser.unban(qq)
+ await BanUser.ban(qq, 10, 99999999)
+ await ban.send(f"已将 {user_name} 拉入黑名单!")
+ else:
+ await super_ban.send('需要艾特被super ban的对象..')
+
diff --git a/basic_plugins/broadcast/__init__.py b/basic_plugins/broadcast/__init__.py
old mode 100644
new mode 100755
index b97d2a6c..328d73c7
--- a/basic_plugins/broadcast/__init__.py
+++ b/basic_plugins/broadcast/__init__.py
@@ -1,59 +1,59 @@
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.adapters import Bot, Event
-from nonebot.permission import SUPERUSER
-import asyncio
-from utils.utils import get_message_text, get_message_imgs
-from services.log import logger
-from utils.message_builder import image
-from utils.manager import group_manager
-
-__zx_plugin_name__ = "广播 [Superuser]"
-__plugin_usage__ = """
-usage:
- 指令:
- 广播- ?[消息] ?[图片]
- 示例:广播- 你们好!
-""".strip()
-__plugin_des__ = "昭告天下!"
-__plugin_cmd__ = ["广播-"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_task__ = {"broadcast": "广播"}
-
-broadcast = on_command("广播-", priority=1, permission=SUPERUSER, block=True)
-
-
-@broadcast.handle()
-async def _(bot: Bot, event: Event, state: T_State):
- msg = get_message_text(event.json())
- imgs = get_message_imgs(event.json())
- rst = ""
- for img in imgs:
- rst += image(img)
- sid = bot.self_id
- gl = await bot.get_group_list(self_id=sid)
- gl = [
- g["group_id"]
- for g in gl
- if await group_manager.check_group_task_status(g["group_id"], "broadcast")
- ]
- g_cnt = len(gl)
- cnt = 0
- error = ""
- x = 0.25
- for g in gl:
- cnt += 1
- if cnt / g_cnt > x:
- await broadcast.send(f"已播报至 {int(cnt / g_cnt * 100)}% 的群聊")
- x += 0.25
- try:
- await bot.send_group_msg(self_id=sid, group_id=g, message=msg + rst)
- logger.info(f"GROUP {g} 投递广播成功")
- except Exception as e:
- logger.error(f"GROUP {g} 投递广播失败:{type(e)}")
- error += f"GROUP {g} 投递广播失败:{type(e)}\n"
- await asyncio.sleep(0.5)
- await broadcast.send(f"已播报至 100% 的群聊")
- if error:
- await broadcast.send(f"播报时错误:{error}")
+from nonebot import on_command
+from nonebot.typing import T_State
+from nonebot.adapters import Bot, Event
+from nonebot.permission import SUPERUSER
+import asyncio
+from utils.utils import get_message_text, get_message_imgs
+from services.log import logger
+from utils.message_builder import image
+from utils.manager import group_manager
+
+__zx_plugin_name__ = "广播 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 指令:
+ 广播- ?[消息] ?[图片]
+ 示例:广播- 你们好!
+""".strip()
+__plugin_des__ = "昭告天下!"
+__plugin_cmd__ = ["广播-"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_task__ = {"broadcast": "广播"}
+
+broadcast = on_command("广播-", priority=1, permission=SUPERUSER, block=True)
+
+
+@broadcast.handle()
+async def _(bot: Bot, event: Event, state: T_State):
+ msg = get_message_text(event.json())
+ imgs = get_message_imgs(event.json())
+ rst = ""
+ for img in imgs:
+ rst += image(img)
+ sid = bot.self_id
+ gl = await bot.get_group_list(self_id=sid)
+ gl = [
+ g["group_id"]
+ for g in gl
+ if await group_manager.check_group_task_status(g["group_id"], "broadcast")
+ ]
+ g_cnt = len(gl)
+ cnt = 0
+ error = ""
+ x = 0.25
+ for g in gl:
+ cnt += 1
+ if cnt / g_cnt > x:
+ await broadcast.send(f"已播报至 {int(cnt / g_cnt * 100)}% 的群聊")
+ x += 0.25
+ try:
+ await bot.send_group_msg(self_id=sid, group_id=g, message=msg + rst)
+ logger.info(f"GROUP {g} 投递广播成功")
+ except Exception as e:
+ logger.error(f"GROUP {g} 投递广播失败:{type(e)}")
+ error += f"GROUP {g} 投递广播失败:{type(e)}\n"
+ await asyncio.sleep(0.5)
+ await broadcast.send(f"已播报至 100% 的群聊")
+ if error:
+ await broadcast.send(f"播报时错误:{error}")
diff --git a/basic_plugins/group_handle/__init__.py b/basic_plugins/group_handle/__init__.py
old mode 100644
new mode 100755
index d83ae817..ff390d09
--- a/basic_plugins/group_handle/__init__.py
+++ b/basic_plugins/group_handle/__init__.py
@@ -1,184 +1,184 @@
-from nonebot import on_notice, on_request
-from configs.path_config import IMAGE_PATH, DATA_PATH
-from utils.message_builder import image
-from models.group_member_info import GroupInfoUser
-from datetime import datetime
-from services.log import logger
-from nonebot.adapters.cqhttp import (
- Bot,
- GroupIncreaseNoticeEvent,
- GroupDecreaseNoticeEvent,
-)
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from utils.manager import group_manager, plugins2settings_manager, requests_manager
-from configs.config import NICKNAME
-from models.group_info import GroupInfo
-from utils.utils import FreqLimiter
-from configs.config import Config
-from pathlib import Path
-import random
-import os
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-__zx_plugin_name__ = "群事件处理 [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_task__ = {"group_welcome": "进群欢迎", "refund_group_remind": "退群提醒"}
-Config.add_plugin_config(
- "auto_invite", "message", f"请不要未经同意就拉{NICKNAME}入群!告辞!", help_="强制拉群后进群回复的内容.."
-)
-Config.add_plugin_config(
- "auto_invite", "flag", True, help_="被强制拉群后是否直接退出", default_value=True
-)
-Config.add_plugin_config(
- "auto_invite", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5
-)
-_flmt = FreqLimiter(Config.get_config("auto_invite", "welcome_msg_cd"))
-
-
-# 群员增加处理
-group_increase_handle = on_notice(priority=1, block=False)
-# 群员减少处理
-group_decrease_handle = on_notice(priority=1, block=False)
-# (群管理)加群同意请求
-add_group = on_request(priority=1, block=False)
-
-
-@group_increase_handle.handle()
-async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
- if event.user_id == int(bot.self_id):
- group = await GroupInfo.get_group_info(event.group_id)
- # 群聊不存在或被强制拉群,退出该群
- if (not group or group.group_flag == 0) and Config.get_config(
- "auto_invite", "flag"
- ):
- try:
- msg = Config.get_config("auto_invite", "message")
- if msg:
- await bot.send_group_msg(group_id=event.group_id, message=msg)
- await bot.set_group_leave(group_id=event.group_id)
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"触发强制入群保护,已成功退出群聊 {event.group_id}..",
- )
- logger.info(f"强制拉群或未有群信息,退出群聊 {group} 成功")
- requests_manager.remove_request("group", event.group_id)
- except Exception as e:
- logger.info(f"强制拉群或未有群信息,退出群聊 {group} 失败 e:{e}")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"触发强制入群保护,退出群聊 {event.group_id} 失败..",
- )
- # 默认群功能开关
- elif event.group_id not in group_manager["group_manager"].keys():
- data = plugins2settings_manager.get_data()
- for plugin in data.keys():
- if not data[plugin]["default_status"]:
- group_manager.block_plugin(plugin, event.group_id)
- else:
- join_time = datetime.now()
- user_info = await bot.get_group_member_info(
- group_id=event.group_id, user_id=event.user_id
- )
- if await GroupInfoUser.add_member_info(
- user_info["user_id"],
- user_info["group_id"],
- user_info["nickname"],
- join_time,
- ):
- logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
- else:
- logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
-
- # 群欢迎消息
- if await group_manager.check_group_task_status(
- event.group_id, "group_welcome"
- ) and _flmt.check(event.group_id):
- _flmt.start_cd(event.group_id)
- msg = ""
- img = ""
- at_flag = False
- custom_welcome_msg_json = (
- Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
- )
- if custom_welcome_msg_json.exists():
- data = json.load(open(custom_welcome_msg_json, "r"))
- if data.get(str(event.group_id)):
- msg = data[str(event.group_id)]
- if msg.find("[at]") != -1:
- msg = msg.replace("[at]", "")
- at_flag = True
- if os.path.exists(DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"):
- img = image(
- abspath=DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"
- )
- if msg or img:
- await group_increase_handle.send(
- "\n" + msg.strip() + img, at_sender=at_flag
- )
- else:
- await group_increase_handle.send(
- "新人快跑啊!!本群现状↓(快使用自定义!)"
- + image(random.choice(os.listdir(IMAGE_PATH + "qxz/")), "qxz")
- )
-
-
-@group_decrease_handle.handle()
-async def _(bot: Bot, event: GroupDecreaseNoticeEvent, state: dict):
- # 被踢出群
- if event.sub_type == "kick_me":
- group_id = event.group_id
- operator_id = event.operator_id
- try:
- operator_name = (
- await GroupInfoUser.get_member_info(event.operator_id, event.group_id)
- ).user_name
- except AttributeError:
- operator_name = "None"
- group = await GroupInfo.get_group_info(group_id)
- group_name = group.group_name if group else ""
- coffee = int(list(bot.config.superusers)[0])
- await bot.send_private_msg(
- user_id=coffee,
- message=f"****呜..一份踢出报告****\n"
- f"我被 {operator_name}({operator_id})\n"
- f"踢出了 {group_name}({group_id})\n"
- f"日期:{str(datetime.now()).split('.')[0]}",
- )
- return
- if event.user_id == int(bot.self_id):
- group_manager.delete_group(event.group_id)
- return
- try:
- user_name = (
- await GroupInfoUser.get_member_info(event.user_id, event.group_id)
- ).user_name
- except AttributeError:
- user_name = str(event.user_id)
- if await GroupInfoUser.delete_member_info(event.user_id, event.group_id):
- logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除成功")
- else:
- logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除失败")
- if await group_manager.check_group_task_status(
- event.group_id, "refund_group_remind"
- ):
- rst = ""
- if event.sub_type == "leave":
- rst = f"{user_name}离开了我们..."
- if event.sub_type == "kick":
- operator = await bot.get_group_member_info(
- user_id=event.operator_id, group_id=event.group_id
- )
- operator_name = (
- operator["card"] if operator["card"] else operator["nickname"]
- )
- rst = f"{user_name} 被 {operator_name} 送走了."
- try:
- await group_decrease_handle.send(f"{rst}")
- except ActionFailed:
- return
+from nonebot import on_notice, on_request
+from configs.path_config import IMAGE_PATH, DATA_PATH
+from utils.message_builder import image
+from models.group_member_info import GroupInfoUser
+from datetime import datetime
+from services.log import logger
+from nonebot.adapters.cqhttp import (
+ Bot,
+ GroupIncreaseNoticeEvent,
+ GroupDecreaseNoticeEvent,
+)
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from utils.manager import group_manager, plugins2settings_manager, requests_manager
+from configs.config import NICKNAME
+from models.group_info import GroupInfo
+from utils.utils import FreqLimiter
+from configs.config import Config
+from pathlib import Path
+import random
+import os
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+__zx_plugin_name__ = "群事件处理 [Hidden]"
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_task__ = {"group_welcome": "进群欢迎", "refund_group_remind": "退群提醒"}
+Config.add_plugin_config(
+ "invite_manager", "message", f"请不要未经同意就拉{NICKNAME}入群!告辞!", help_="强制拉群后进群回复的内容.."
+)
+Config.add_plugin_config(
+ "invite_manager", "flag", True, help_="被强制拉群后是否直接退出", default_value=True
+)
+Config.add_plugin_config(
+ "invite_manager", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5
+)
+_flmt = FreqLimiter(Config.get_config("invite_manager", "welcome_msg_cd"))
+
+
+# 群员增加处理
+group_increase_handle = on_notice(priority=1, block=False)
+# 群员减少处理
+group_decrease_handle = on_notice(priority=1, block=False)
+# (群管理)加群同意请求
+add_group = on_request(priority=1, block=False)
+
+
+@group_increase_handle.handle()
+async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
+ if event.user_id == int(bot.self_id):
+ group = await GroupInfo.get_group_info(event.group_id)
+ # 群聊不存在或被强制拉群,退出该群
+ if (not group or group.group_flag == 0) and Config.get_config(
+ "invite_manager", "flag"
+ ):
+ try:
+ msg = Config.get_config("invite_manager", "message")
+ if msg:
+ await bot.send_group_msg(group_id=event.group_id, message=msg)
+ await bot.set_group_leave(group_id=event.group_id)
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"触发强制入群保护,已成功退出群聊 {event.group_id}..",
+ )
+ logger.info(f"强制拉群或未有群信息,退出群聊 {group} 成功")
+ requests_manager.remove_request("group", event.group_id)
+ except Exception as e:
+ logger.info(f"强制拉群或未有群信息,退出群聊 {group} 失败 e:{e}")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"触发强制入群保护,退出群聊 {event.group_id} 失败..",
+ )
+ # 默认群功能开关
+ elif event.group_id not in group_manager["group_manager"].keys():
+ data = plugins2settings_manager.get_data()
+ for plugin in data.keys():
+ if not data[plugin]["default_status"]:
+ group_manager.block_plugin(plugin, event.group_id)
+ else:
+ join_time = datetime.now()
+ user_info = await bot.get_group_member_info(
+ group_id=event.group_id, user_id=event.user_id
+ )
+ if await GroupInfoUser.add_member_info(
+ user_info["user_id"],
+ user_info["group_id"],
+ user_info["nickname"],
+ join_time,
+ ):
+ logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
+ else:
+ logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
+
+ # 群欢迎消息
+ if await group_manager.check_group_task_status(
+ event.group_id, "group_welcome"
+ ) and _flmt.check(event.group_id):
+ _flmt.start_cd(event.group_id)
+ msg = ""
+ img = ""
+ at_flag = False
+ custom_welcome_msg_json = (
+ Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
+ )
+ if custom_welcome_msg_json.exists():
+ data = json.load(open(custom_welcome_msg_json, "r"))
+ if data.get(str(event.group_id)):
+ msg = data[str(event.group_id)]
+ if msg.find("[at]") != -1:
+ msg = msg.replace("[at]", "")
+ at_flag = True
+ if os.path.exists(DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"):
+ img = image(
+ abspath=DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"
+ )
+ if msg or img:
+ await group_increase_handle.send(
+ "\n" + msg.strip() + img, at_sender=at_flag
+ )
+ else:
+ await group_increase_handle.send(
+ "新人快跑啊!!本群现状↓(快使用自定义!)"
+ + image(random.choice(os.listdir(IMAGE_PATH + "qxz/")), "qxz")
+ )
+
+
+@group_decrease_handle.handle()
+async def _(bot: Bot, event: GroupDecreaseNoticeEvent, state: dict):
+ # 被踢出群
+ if event.sub_type == "kick_me":
+ group_id = event.group_id
+ operator_id = event.operator_id
+ try:
+ operator_name = (
+ await GroupInfoUser.get_member_info(event.operator_id, event.group_id)
+ ).user_name
+ except AttributeError:
+ operator_name = "None"
+ group = await GroupInfo.get_group_info(group_id)
+ group_name = group.group_name if group else ""
+ coffee = int(list(bot.config.superusers)[0])
+ await bot.send_private_msg(
+ user_id=coffee,
+ message=f"****呜..一份踢出报告****\n"
+ f"我被 {operator_name}({operator_id})\n"
+ f"踢出了 {group_name}({group_id})\n"
+ f"日期:{str(datetime.now()).split('.')[0]}",
+ )
+ return
+ if event.user_id == int(bot.self_id):
+ group_manager.delete_group(event.group_id)
+ return
+ try:
+ user_name = (
+ await GroupInfoUser.get_member_info(event.user_id, event.group_id)
+ ).user_name
+ except AttributeError:
+ user_name = str(event.user_id)
+ if await GroupInfoUser.delete_member_info(event.user_id, event.group_id):
+ logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除成功")
+ else:
+ logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除失败")
+ if await group_manager.check_group_task_status(
+ event.group_id, "refund_group_remind"
+ ):
+ rst = ""
+ if event.sub_type == "leave":
+ rst = f"{user_name}离开了我们..."
+ if event.sub_type == "kick":
+ operator = await bot.get_group_member_info(
+ user_id=event.operator_id, group_id=event.group_id
+ )
+ operator_name = (
+ operator["card"] if operator["card"] else operator["nickname"]
+ )
+ rst = f"{user_name} 被 {operator_name} 送走了."
+ try:
+ await group_decrease_handle.send(f"{rst}")
+ except ActionFailed:
+ return
diff --git a/basic_plugins/help/__init__.py b/basic_plugins/help/__init__.py
old mode 100644
new mode 100755
index da1ffd3c..b747cb05
--- a/basic_plugins/help/__init__.py
+++ b/basic_plugins/help/__init__.py
@@ -1,73 +1,73 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import (
- Bot,
- MessageEvent,
- GroupMessageEvent
-)
-from nonebot.typing import T_State
-from nonebot.rule import to_me
-from configs.path_config import IMAGE_PATH, DATA_PATH
-from utils.message_builder import image
-from .data_source import create_help_img, get_plugin_help
-from utils.utils import get_message_text
-from pathlib import Path
-import os
-
-
-__zx_plugin_name__ = "帮助"
-
-group_help_path = Path(DATA_PATH) / "group_help"
-help_image = Path(IMAGE_PATH) / "help.png"
-simple_help_image = Path(IMAGE_PATH) / "simple_help.png"
-if help_image.exists():
- help_image.unlink()
-if simple_help_image.exists():
- simple_help_image.unlink()
-group_help_path.mkdir(exist_ok=True, parents=True)
-for x in os.listdir(group_help_path):
- group_help_image = group_help_path / x
- group_help_image.unlink()
-
-_help = on_command("详细功能", rule=to_me(), aliases={"详细帮助"}, priority=1, block=True)
-simple_help = on_command("功能", rule=to_me(), aliases={"help", "帮助"}, priority=1, block=True)
-
-
-@_help.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if not help_image.exists():
- if help_image.exists():
- help_image.unlink()
- if simple_help_image.exists():
- simple_help_image.unlink()
- await create_help_img(None, help_image, simple_help_image)
- await _help.finish(image("help.png"))
-
-
-@simple_help.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- is_super = False
- if msg:
- if '-super' in msg:
- if str(event.user_id) in bot.config.superusers:
- is_super = True
- msg = msg.replace('-super', '').strip()
- msg = get_plugin_help(msg, is_super)
- if msg:
- await _help.send(image(b64=msg))
- else:
- await _help.send("没有此功能的帮助信息...")
- else:
- if isinstance(event, GroupMessageEvent):
- _image_path = group_help_path / f"{event.group_id}.png"
- if not _image_path.exists():
- await create_help_img(event.group_id, help_image, _image_path)
- await simple_help.send(image(_image_path))
- else:
- if not simple_help_image.exists():
- if help_image.exists():
- help_image.unlink()
- if simple_help_image.exists():
- simple_help_image.unlink()
- await create_help_img(None, help_image, simple_help_image)
- await _help.finish(image("simple_help.png"))
+from nonebot import on_command
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ GroupMessageEvent
+)
+from nonebot.typing import T_State
+from nonebot.rule import to_me
+from configs.path_config import IMAGE_PATH, DATA_PATH
+from utils.message_builder import image
+from .data_source import create_help_img, get_plugin_help
+from utils.utils import get_message_text
+from pathlib import Path
+import os
+
+
+__zx_plugin_name__ = "帮助"
+
+group_help_path = Path(DATA_PATH) / "group_help"
+help_image = Path(IMAGE_PATH) / "help.png"
+simple_help_image = Path(IMAGE_PATH) / "simple_help.png"
+if help_image.exists():
+ help_image.unlink()
+if simple_help_image.exists():
+ simple_help_image.unlink()
+group_help_path.mkdir(exist_ok=True, parents=True)
+for x in os.listdir(group_help_path):
+ group_help_image = group_help_path / x
+ group_help_image.unlink()
+
+_help = on_command("详细功能", rule=to_me(), aliases={"详细帮助"}, priority=1, block=True)
+simple_help = on_command("功能", rule=to_me(), aliases={"help", "帮助"}, priority=1, block=True)
+
+
+@_help.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if not help_image.exists():
+ if help_image.exists():
+ help_image.unlink()
+ if simple_help_image.exists():
+ simple_help_image.unlink()
+ await create_help_img(None, help_image, simple_help_image)
+ await _help.finish(image("help.png"))
+
+
+@simple_help.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ is_super = False
+ if msg:
+ if '-super' in msg:
+ if str(event.user_id) in bot.config.superusers:
+ is_super = True
+ msg = msg.replace('-super', '').strip()
+ msg = get_plugin_help(msg, is_super)
+ if msg:
+ await _help.send(image(b64=msg))
+ else:
+ await _help.send("没有此功能的帮助信息...")
+ else:
+ if isinstance(event, GroupMessageEvent):
+ _image_path = group_help_path / f"{event.group_id}.png"
+ if not _image_path.exists():
+ await create_help_img(event.group_id, help_image, _image_path)
+ await simple_help.send(image(_image_path))
+ else:
+ if not simple_help_image.exists():
+ if help_image.exists():
+ help_image.unlink()
+ if simple_help_image.exists():
+ simple_help_image.unlink()
+ await create_help_img(None, help_image, simple_help_image)
+ await _help.finish(image("simple_help.png"))
diff --git a/basic_plugins/help/data_source.py b/basic_plugins/help/data_source.py
old mode 100644
new mode 100755
index 64d0276d..6168180d
--- a/basic_plugins/help/data_source.py
+++ b/basic_plugins/help/data_source.py
@@ -1,367 +1,367 @@
-from utils.image_utils import CreateImg
-from configs.path_config import IMAGE_PATH
-from utils.manager import (
- plugins2settings_manager,
- admin_manager,
- plugins_manager,
- group_manager,
-)
-from typing import Optional
-from services.log import logger
-from pathlib import Path
-from utils.utils import get_matchers
-import random
-import asyncio
-import nonebot
-import os
-
-
-random_bk_path = Path(IMAGE_PATH) / "background" / "help" / "simple_help"
-
-background = Path(IMAGE_PATH) / "background" / "0.png"
-
-
-async def create_help_img(
- group_id: Optional[int], help_image: Path, simple_help_image: Path
-):
- """
- 生成帮助图片
- :param group_id: 群号
- :param help_image: 图片路径
- :param simple_help_image: 简易帮助图片路径
- """
- return await asyncio.get_event_loop().run_in_executor(
- None, _create_help_img, group_id, help_image, simple_help_image
- )
-
-
-def _create_help_img(
- group_id: Optional[int], help_image: Path, simple_help_image: Path
-):
- """
- 生成帮助图片
- :param group_id: 群号
- :param help_image: 图片路径
- :param simple_help_image: 简易帮助图片路径
- """
- _matchers = get_matchers()
- width = 0
- matchers_data = {}
- _des_tmp = {}
- _plugin_name_tmp = []
- _tmp = []
- tmp_img = CreateImg(0, 0, plain_text="1", font_size=24)
- font_height = tmp_img.h
- # 插件分类
- for matcher in _matchers:
- plugin_name = None
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- _module = _plugin.module
- try:
- plugin_name = _module.__getattribute__("__zx_plugin_name__")
- try:
- plugin_des = _module.__getattribute__("__plugin_des__")
- except AttributeError:
- plugin_des = "_"
- if (
- "[hidden]" in plugin_name.lower()
- or "[admin]" in plugin_name.lower()
- or "[superuser]" in plugin_name.lower()
- or plugin_name in _plugin_name_tmp
- or plugin_name == "帮助"
- ):
- continue
- plugin_type = ("normal",)
- text_type = 0
- if plugins2settings_manager.get(
- matcher.module
- ) and plugins2settings_manager[matcher.module].get("plugin_type"):
- plugin_type = tuple(
- plugins2settings_manager.get_plugin_data(matcher.module)[
- "plugin_type"
- ]
- )
- else:
- try:
- plugin_type = _module.__getattribute__("__plugin_type__")
- except AttributeError:
- pass
- if len(plugin_type) > 1:
- try:
- text_type = int(plugin_type[1])
- except ValueError as e:
- logger.warning(f"生成列向帮助排列失败 {plugin_name}: {type(e)}: {e}")
- plugin_type = plugin_type[0]
- else:
- plugin_type = plugin_type[0]
- try:
- plugin_cmd = _module.__getattribute__("__plugin_cmd__")
- plugin_cmd = [x for x in plugin_cmd if "[_superuser]" not in x]
- except AttributeError:
- plugin_cmd = []
- if plugin_type not in matchers_data.keys():
- matchers_data[plugin_type] = {}
- if plugin_des in _des_tmp.keys():
- try:
- matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"] = (
- matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"]
- + plugin_cmd
- )
- except KeyError as e:
- logger.warning(f"{type(e)}: {e}")
- else:
- matchers_data[plugin_type][plugin_name] = {
- "module": matcher.module,
- "des": plugin_des,
- "cmd": plugin_cmd,
- "text_type": text_type,
- }
- try:
- if text_type == 0:
- x = tmp_img.getsize(
- f'{plugin_name}: {matchers_data[plugin_type][plugin_name]["des"]} ->'
- + " / ".join(matchers_data[plugin_type][plugin_name]["cmd"])
- )[0]
- width = width if width > x else x
- except KeyError:
- pass
- if plugin_des not in _des_tmp:
- _des_tmp[plugin_des] = plugin_name
- except AttributeError as e:
- if plugin_name not in _plugin_name_tmp:
- logger.warning(f"获取功能 {matcher.module}: {plugin_name} 设置失败...e:{e}")
- if plugin_name not in _plugin_name_tmp:
- _plugin_name_tmp.append(plugin_name)
- help_img_list = []
- simple_help_img_list = []
- types = list(matchers_data.keys())
- types.sort()
- ix = 0
- # 详细帮助
- for type_ in types:
- keys = list(matchers_data[type_].keys())
- keys.sort()
- help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
- simple_help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
- for i, k in enumerate(keys):
- # 禁用flag
- flag = True
- if plugins_manager.get_plugin_status(
- matchers_data[type_][k]["module"], "all"
- ):
- flag = False
- if group_id:
- flag = flag and plugins_manager.get_plugin_status(
- matchers_data[type_][k]["module"], "group"
- )
- simple_help_str += (
- f"{i+1}.{k}<|_|~|>"
- f"{group_manager.get_plugin_status(matchers_data[type_][k]['module'], group_id) if group_id else '_'}|"
- f"{flag}\n"
- )
- if matchers_data[type_][k]["text_type"] == 1:
- _x = tmp_img.getsize(
- f"{i+1}".rjust(5)
- + f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
- )[0]
- _str = (
- f"{i+1}".rjust(5)
- + f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
- )
- _str += matchers_data[type_][k]["cmd"][0] + "\n"
- for c in matchers_data[type_][k]["cmd"][1:]:
- _str += "".rjust(int(_x * 0.125) + 1) + f"{c}\n"
- help_str += _str
- else:
- help_str += (
- f"{i+1}".rjust(5)
- + f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
- + " / ".join(matchers_data[type_][k]["cmd"])
- + "\n"
- )
- height = len(help_str.split("\n")) * (font_height + 5)
- simple_height = len(simple_help_str.split("\n")) * (font_height + 5)
- A = CreateImg(
- width + 150, height, font_size=24, color="white" if not ix % 2 else "black"
- )
- A.text((10, 10), help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
- # 生成各个分类的插件简易帮助图片
- simple_width = 0
- for x in [
- tmp_img.getsize(x.split("<|_|~|>")[0])[0]
- for x in simple_help_str.split("\n")
- ]:
- simple_width = simple_width if simple_width > x else x
- bk = CreateImg(simple_width + 20, simple_height, font_size=24, color="#6495ED")
- B = CreateImg(
- simple_width + 20,
- simple_height,
- font_size=24,
- color="white" if not ix % 2 else "black",
- )
- # 切分,判断插件开关状态
- _s_height = 10
- for _s in simple_help_str.split("\n"):
- text_color = (255, 255, 255) if ix % 2 else (0, 0, 0)
- _line_flag = False
- if "<|_|~|>" in _s:
- _x = _s.split("<|_|~|>")
- _flag_sp = _x[-1].split("|")
- if group_id:
- if _flag_sp[0].lower() != "true":
- text_color = (252, 75, 13)
- if _flag_sp[1].lower() == "true":
- _line_flag = True
- _s = _x[0]
- B.text((10, _s_height), _s, text_color)
- if _line_flag:
- B.line(
- (
- 7,
- _s_height + int(B.getsize(_s)[1] / 2) + 2,
- B.getsize(_s)[0] + 11,
- _s_height + int(B.getsize(_s)[1] / 2) + 2,
- ),
- (236, 66, 7),
- 3,
- )
- _s_height += B.getsize("1")[1] + 5
- # B.text((10, 10), simple_help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
- bk.paste(B, center_type="center")
- bk.transparent(2)
- ix += 1
- help_img_list.append(A)
- simple_help_img_list.append(bk)
- height = 0
- for img in help_img_list:
- height += img.h
- if not group_id:
- A = CreateImg(width + 150, height + 50, font_size=24)
- A.text(
- (10, 10), '* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" "功能名: 功能简介 -> 指令\n\n'
- )
- current_height = 50
- for img in help_img_list:
- A.paste(img, (0, current_height))
- current_height += img.h
- A.save(help_image)
- # 详细帮助生成完毕
- # 简易帮助图片合成
- height = 0
- width = 0
- for img in simple_help_img_list:
- if img.h > height:
- height = img.h
- width += img.w + 10
- B = CreateImg(width + 100, height + 250, font_size=24)
- width, _ = get_max_width_or_paste(simple_help_img_list, B)
- bk = None
- random_bk = os.listdir(random_bk_path)
- if random_bk:
- bk = random.choice(random_bk)
- x = max(width + 50, height + 250)
- B = CreateImg(
- x,
- x,
- font_size=24,
- color="#FFEFD5",
- background=random_bk_path / bk,
- )
- B.filter("GaussianBlur", 10)
- _, B = get_max_width_or_paste(simple_help_img_list, B, True)
- w = 10
- h = 10
- for msg in ["目前支持的功能列表:", "可以通过 ‘帮助[功能名称]’ 来获取对应功能的使用方法", "或者使用 ‘详细帮助’ 来获取所有功能方法"]:
- text = CreateImg(
- 0,
- 0,
- plain_text=msg,
- font_size=24,
- font="yuanshen.ttf",
- )
- B.paste(text, (w, h), True)
- h += 50
- if msg == "目前支持的功能列表:":
- w += 50
- B.paste(
- CreateImg(
- 0,
- 0,
- plain_text="注: 红字代表功能被群管理员禁用,红线代表功能正在维护",
- font_size=24,
- font="yuanshen.ttf",
- font_color=(231, 74, 57)
- ),
- (300, 10),
- True,
- )
- B.save(simple_help_image)
-
-
-def get_max_width_or_paste(
- simple_help_img_list: list, B: CreateImg = None, is_paste: bool = False
-) -> "int, CreateImg":
- """
- 获取最大宽度,或直接贴图
- :param simple_help_img_list: 简单帮助图片列表
- :param B: 背景图
- :param is_paste: 是否直接贴图
- """
- current_width = 50
- current_height = 180
- max_width = simple_help_img_list[0].w
- for i in range(len(simple_help_img_list)):
- try:
- if is_paste and B:
- B.paste(simple_help_img_list[i], (current_width, current_height), True)
- current_height += simple_help_img_list[i].h + 40
- if current_height + simple_help_img_list[i + 1].h > B.h - 10:
- current_height = 180
- current_width += max_width + 30
- max_width = 0
- elif simple_help_img_list[i].w > max_width:
- max_width = simple_help_img_list[i].w
- except IndexError:
- pass
- if current_width > simple_help_img_list[0].w + 50:
- current_width += simple_help_img_list[-1].w
- return current_width, B
-
-
-def get_plugin_help(msg: str, is_super: bool = False) -> Optional[str]:
- """
- 获取功能的帮助信息
- :param msg: 功能cmd
- :param is_super: 是否为超级用户
- """
- module = plugins2settings_manager.get_plugin_module(msg)
- if not module:
- module = admin_manager.get_plugin_module(msg)
- if module:
- try:
- plugin = nonebot.plugin.get_plugin(module)
- if plugin:
- if is_super:
- result = plugin.module.__getattribute__(
- "__plugin_superuser_usage__"
- )
- else:
- result = plugin.module.__getattribute__("__plugin_usage__")
- if result:
- width = 0
- for x in result.split("\n"):
- _width = len(x) * 24
- width = width if width > _width else _width
- height = len(result.split("\n")) * 45
- A = CreateImg(width, height, font_size=24)
- bk = CreateImg(
- width,
- height,
- background=Path(IMAGE_PATH) / "background" / "1.png",
- )
- A.paste(bk, alpha=True)
- A.text((int(width * 0.048), int(height * 0.21)), result)
- return A.pic2bs4()
- except AttributeError:
- pass
- return None
+from utils.image_utils import CreateImg
+from configs.path_config import IMAGE_PATH
+from utils.manager import (
+ plugins2settings_manager,
+ admin_manager,
+ plugins_manager,
+ group_manager,
+)
+from typing import Optional
+from services.log import logger
+from pathlib import Path
+from utils.utils import get_matchers
+import random
+import asyncio
+import nonebot
+import os
+
+
+random_bk_path = Path(IMAGE_PATH) / "background" / "help" / "simple_help"
+
+background = Path(IMAGE_PATH) / "background" / "0.png"
+
+
+async def create_help_img(
+ group_id: Optional[int], help_image: Path, simple_help_image: Path
+):
+ """
+ 生成帮助图片
+ :param group_id: 群号
+ :param help_image: 图片路径
+ :param simple_help_image: 简易帮助图片路径
+ """
+ return await asyncio.get_event_loop().run_in_executor(
+ None, _create_help_img, group_id, help_image, simple_help_image
+ )
+
+
+def _create_help_img(
+ group_id: Optional[int], help_image: Path, simple_help_image: Path
+):
+ """
+ 生成帮助图片
+ :param group_id: 群号
+ :param help_image: 图片路径
+ :param simple_help_image: 简易帮助图片路径
+ """
+ _matchers = get_matchers()
+ width = 0
+ matchers_data = {}
+ _des_tmp = {}
+ _plugin_name_tmp = []
+ _tmp = []
+ tmp_img = CreateImg(0, 0, plain_text="1", font_size=24)
+ font_height = tmp_img.h
+ # 插件分类
+ for matcher in _matchers:
+ plugin_name = None
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ _module = _plugin.module
+ try:
+ plugin_name = _module.__getattribute__("__zx_plugin_name__")
+ try:
+ plugin_des = _module.__getattribute__("__plugin_des__")
+ except AttributeError:
+ plugin_des = "_"
+ if (
+ "[hidden]" in plugin_name.lower()
+ or "[admin]" in plugin_name.lower()
+ or "[superuser]" in plugin_name.lower()
+ or plugin_name in _plugin_name_tmp
+ or plugin_name == "帮助"
+ ):
+ continue
+ plugin_type = ("normal",)
+ text_type = 0
+ if plugins2settings_manager.get(
+ matcher.module
+ ) and plugins2settings_manager[matcher.module].get("plugin_type"):
+ plugin_type = tuple(
+ plugins2settings_manager.get_plugin_data(matcher.module)[
+ "plugin_type"
+ ]
+ )
+ else:
+ try:
+ plugin_type = _module.__getattribute__("__plugin_type__")
+ except AttributeError:
+ pass
+ if len(plugin_type) > 1:
+ try:
+ text_type = int(plugin_type[1])
+ except ValueError as e:
+ logger.warning(f"生成列向帮助排列失败 {plugin_name}: {type(e)}: {e}")
+ plugin_type = plugin_type[0]
+ else:
+ plugin_type = plugin_type[0]
+ try:
+ plugin_cmd = _module.__getattribute__("__plugin_cmd__")
+ plugin_cmd = [x for x in plugin_cmd if "[_superuser]" not in x]
+ except AttributeError:
+ plugin_cmd = []
+ if plugin_type not in matchers_data.keys():
+ matchers_data[plugin_type] = {}
+ if plugin_des in _des_tmp.keys():
+ try:
+ matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"] = (
+ matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"]
+ + plugin_cmd
+ )
+ except KeyError as e:
+ logger.warning(f"{type(e)}: {e}")
+ else:
+ matchers_data[plugin_type][plugin_name] = {
+ "module": matcher.module,
+ "des": plugin_des,
+ "cmd": plugin_cmd,
+ "text_type": text_type,
+ }
+ try:
+ if text_type == 0:
+ x = tmp_img.getsize(
+ f'{plugin_name}: {matchers_data[plugin_type][plugin_name]["des"]} ->'
+ + " / ".join(matchers_data[plugin_type][plugin_name]["cmd"])
+ )[0]
+ width = width if width > x else x
+ except KeyError:
+ pass
+ if plugin_des not in _des_tmp:
+ _des_tmp[plugin_des] = plugin_name
+ except AttributeError as e:
+ if plugin_name not in _plugin_name_tmp:
+ logger.warning(f"获取功能 {matcher.module}: {plugin_name} 设置失败...e:{e}")
+ if plugin_name not in _plugin_name_tmp:
+ _plugin_name_tmp.append(plugin_name)
+ help_img_list = []
+ simple_help_img_list = []
+ types = list(matchers_data.keys())
+ types.sort()
+ ix = 0
+ # 详细帮助
+ for type_ in types:
+ keys = list(matchers_data[type_].keys())
+ keys.sort()
+ help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
+ simple_help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
+ for i, k in enumerate(keys):
+ # 禁用flag
+ flag = True
+ if plugins_manager.get_plugin_status(
+ matchers_data[type_][k]["module"], "all"
+ ):
+ flag = False
+ if group_id:
+ flag = flag and plugins_manager.get_plugin_status(
+ matchers_data[type_][k]["module"], "group"
+ )
+ simple_help_str += (
+ f"{i+1}.{k}<|_|~|>"
+ f"{group_manager.get_plugin_status(matchers_data[type_][k]['module'], group_id) if group_id else '_'}|"
+ f"{flag}\n"
+ )
+ if matchers_data[type_][k]["text_type"] == 1:
+ _x = tmp_img.getsize(
+ f"{i+1}".rjust(5)
+ + f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
+ )[0]
+ _str = (
+ f"{i+1}".rjust(5)
+ + f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
+ )
+ _str += matchers_data[type_][k]["cmd"][0] + "\n"
+ for c in matchers_data[type_][k]["cmd"][1:]:
+ _str += "".rjust(int(_x * 0.125) + 1) + f"{c}\n"
+ help_str += _str
+ else:
+ help_str += (
+ f"{i+1}".rjust(5)
+ + f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
+ + " / ".join(matchers_data[type_][k]["cmd"])
+ + "\n"
+ )
+ height = len(help_str.split("\n")) * (font_height + 5)
+ simple_height = len(simple_help_str.split("\n")) * (font_height + 5)
+ A = CreateImg(
+ width + 150, height, font_size=24, color="white" if not ix % 2 else "black"
+ )
+ A.text((10, 10), help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
+ # 生成各个分类的插件简易帮助图片
+ simple_width = 0
+ for x in [
+ tmp_img.getsize(x.split("<|_|~|>")[0])[0]
+ for x in simple_help_str.split("\n")
+ ]:
+ simple_width = simple_width if simple_width > x else x
+ bk = CreateImg(simple_width + 20, simple_height, font_size=24, color="#6495ED")
+ B = CreateImg(
+ simple_width + 20,
+ simple_height,
+ font_size=24,
+ color="white" if not ix % 2 else "black",
+ )
+ # 切分,判断插件开关状态
+ _s_height = 10
+ for _s in simple_help_str.split("\n"):
+ text_color = (255, 255, 255) if ix % 2 else (0, 0, 0)
+ _line_flag = False
+ if "<|_|~|>" in _s:
+ _x = _s.split("<|_|~|>")
+ _flag_sp = _x[-1].split("|")
+ if group_id:
+ if _flag_sp[0].lower() != "true":
+ text_color = (252, 75, 13)
+ if _flag_sp[1].lower() == "true":
+ _line_flag = True
+ _s = _x[0]
+ B.text((10, _s_height), _s, text_color)
+ if _line_flag:
+ B.line(
+ (
+ 7,
+ _s_height + int(B.getsize(_s)[1] / 2) + 2,
+ B.getsize(_s)[0] + 11,
+ _s_height + int(B.getsize(_s)[1] / 2) + 2,
+ ),
+ (236, 66, 7),
+ 3,
+ )
+ _s_height += B.getsize("1")[1] + 5
+ # B.text((10, 10), simple_help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
+ bk.paste(B, center_type="center")
+ bk.transparent(2)
+ ix += 1
+ help_img_list.append(A)
+ simple_help_img_list.append(bk)
+ height = 0
+ for img in help_img_list:
+ height += img.h
+ if not group_id:
+ A = CreateImg(width + 150, height + 50, font_size=24)
+ A.text(
+ (10, 10), '* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" "功能名: 功能简介 -> 指令\n\n'
+ )
+ current_height = 50
+ for img in help_img_list:
+ A.paste(img, (0, current_height))
+ current_height += img.h
+ A.save(help_image)
+ # 详细帮助生成完毕
+ # 简易帮助图片合成
+ height = 0
+ width = 0
+ for img in simple_help_img_list:
+ if img.h > height:
+ height = img.h
+ width += img.w + 10
+ B = CreateImg(width + 100, height + 250, font_size=24)
+ width, _ = get_max_width_or_paste(simple_help_img_list, B)
+ bk = None
+ random_bk = os.listdir(random_bk_path)
+ if random_bk:
+ bk = random.choice(random_bk)
+ x = max(width + 50, height + 250)
+ B = CreateImg(
+ x,
+ x,
+ font_size=24,
+ color="#FFEFD5",
+ background=random_bk_path / bk,
+ )
+ B.filter("GaussianBlur", 10)
+ _, B = get_max_width_or_paste(simple_help_img_list, B, True)
+ w = 10
+ h = 10
+ for msg in ["目前支持的功能列表:", "可以通过 ‘帮助[功能名称]’ 来获取对应功能的使用方法", "或者使用 ‘详细帮助’ 来获取所有功能方法"]:
+ text = CreateImg(
+ 0,
+ 0,
+ plain_text=msg,
+ font_size=24,
+ font="yuanshen.ttf",
+ )
+ B.paste(text, (w, h), True)
+ h += 50
+ if msg == "目前支持的功能列表:":
+ w += 50
+ B.paste(
+ CreateImg(
+ 0,
+ 0,
+ plain_text="注: 红字代表功能被群管理员禁用,红线代表功能正在维护",
+ font_size=24,
+ font="yuanshen.ttf",
+ font_color=(231, 74, 57)
+ ),
+ (300, 10),
+ True,
+ )
+ B.save(simple_help_image)
+
+
+def get_max_width_or_paste(
+ simple_help_img_list: list, B: CreateImg = None, is_paste: bool = False
+) -> "int, CreateImg":
+ """
+ 获取最大宽度,或直接贴图
+ :param simple_help_img_list: 简单帮助图片列表
+ :param B: 背景图
+ :param is_paste: 是否直接贴图
+ """
+ current_width = 50
+ current_height = 180
+ max_width = simple_help_img_list[0].w
+ for i in range(len(simple_help_img_list)):
+ try:
+ if is_paste and B:
+ B.paste(simple_help_img_list[i], (current_width, current_height), True)
+ current_height += simple_help_img_list[i].h + 40
+ if current_height + simple_help_img_list[i + 1].h > B.h - 10:
+ current_height = 180
+ current_width += max_width + 30
+ max_width = 0
+ elif simple_help_img_list[i].w > max_width:
+ max_width = simple_help_img_list[i].w
+ except IndexError:
+ pass
+ if current_width > simple_help_img_list[0].w + 50:
+ current_width += simple_help_img_list[-1].w
+ return current_width, B
+
+
+def get_plugin_help(msg: str, is_super: bool = False) -> Optional[str]:
+ """
+ 获取功能的帮助信息
+ :param msg: 功能cmd
+ :param is_super: 是否为超级用户
+ """
+ module = plugins2settings_manager.get_plugin_module(msg)
+ if not module:
+ module = admin_manager.get_plugin_module(msg)
+ if module:
+ try:
+ plugin = nonebot.plugin.get_plugin(module)
+ if plugin:
+ if is_super:
+ result = plugin.module.__getattribute__(
+ "__plugin_superuser_usage__"
+ )
+ else:
+ result = plugin.module.__getattribute__("__plugin_usage__")
+ if result:
+ width = 0
+ for x in result.split("\n"):
+ _width = len(x) * 24
+ width = width if width > _width else _width
+ height = len(result.split("\n")) * 45
+ A = CreateImg(width, height, font_size=24)
+ bk = CreateImg(
+ width,
+ height,
+ background=Path(IMAGE_PATH) / "background" / "1.png",
+ )
+ A.paste(bk, alpha=True)
+ A.text((int(width * 0.048), int(height * 0.21)), result)
+ return A.pic2bs4()
+ except AttributeError:
+ pass
+ return None
diff --git a/basic_plugins/hooks/__init__.py b/basic_plugins/hooks/__init__.py
old mode 100644
new mode 100755
index d1c21d41..f33bd813
--- a/basic_plugins/hooks/__init__.py
+++ b/basic_plugins/hooks/__init__.py
@@ -1,38 +1,38 @@
-from configs.config import Config
-import nonebot
-
-
-Config.add_plugin_config(
- "hook",
- "CHECK_NOTICE_INFO_CD",
- 300,
- name="基础hook配置",
- help_="群检测,个人权限检测等各种检测提示信息cd",
- default_value=300
-)
-
-Config.add_plugin_config(
- "hook",
- "MALICIOUS_BAN_TIME",
- 30,
- help_="恶意命令触发检测触发后ban的时长(分钟)",
- default_value=30
-)
-
-Config.add_plugin_config(
- "hook",
- "MALICIOUS_CHECK_TIME",
- 5,
- help_="恶意命令触发检测规定时间内(秒)",
- default_value=5
-)
-
-Config.add_plugin_config(
- "hook",
- "MALICIOUS_BAN_COUNT",
- 6,
- help_="恶意命令触发检测最大触发次数",
- default_value=6
-)
-
-nonebot.load_plugins("basic_plugins/hooks")
+from configs.config import Config
+import nonebot
+
+
+Config.add_plugin_config(
+ "hook",
+ "CHECK_NOTICE_INFO_CD",
+ 300,
+ name="基础hook配置",
+ help_="群检测,个人权限检测等各种检测提示信息cd",
+ default_value=300
+)
+
+Config.add_plugin_config(
+ "hook",
+ "MALICIOUS_BAN_TIME",
+ 30,
+ help_="恶意命令触发检测触发后ban的时长(分钟)",
+ default_value=30
+)
+
+Config.add_plugin_config(
+ "hook",
+ "MALICIOUS_CHECK_TIME",
+ 5,
+ help_="恶意命令触发检测规定时间内(秒)",
+ default_value=5
+)
+
+Config.add_plugin_config(
+ "hook",
+ "MALICIOUS_BAN_COUNT",
+ 6,
+ help_="恶意命令触发检测最大触发次数",
+ default_value=6
+)
+
+nonebot.load_plugins("basic_plugins/hooks")
diff --git a/basic_plugins/hooks/auth_hook.py b/basic_plugins/hooks/auth_hook.py
old mode 100644
new mode 100755
index 1dadbaa2..aaf782bf
--- a/basic_plugins/hooks/auth_hook.py
+++ b/basic_plugins/hooks/auth_hook.py
@@ -1,210 +1,210 @@
-from nonebot.matcher import Matcher
-from nonebot.message import run_preprocessor, IgnoredException
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from utils.manager import (
- plugins2settings_manager,
- admin_manager,
- group_manager,
- plugins_manager,
-)
-from .utils import set_block_limit_false, status_message_manager
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import (
- Bot,
- MessageEvent,
- GroupMessageEvent,
- PokeNotifyEvent,
-)
-from configs.config import Config
-from models.ban_user import BanUser
-from utils.utils import FreqLimiter
-from utils.message_builder import at
-from models.level_user import LevelUser
-
-
-_flmt = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
-_flmt_g = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
-_flmt_s = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
-_flmt_c = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
-
-
-ignore_rst_module = ["ai", "poke", "dialogue"]
-
-
-# 权限检测
-@run_preprocessor
-async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
- module = matcher.module
- plugins2info_dict = plugins2settings_manager.get_data()
- if (
- (not isinstance(event, MessageEvent) and module != "poke")
- or await BanUser.is_ban(event.user_id)
- and str(event.user_id) not in bot.config.superusers
- ) or (
- str(event.user_id) in bot.config.superusers
- and plugins2info_dict.get(module)
- and not plugins2info_dict[module]["limit_superuser"]
- ):
- return
- # 群黑名单检测
- if isinstance(event, GroupMessageEvent):
- if group_manager.get_group_level(event.group_id) < 0:
- raise IgnoredException("群黑名单")
- if module in admin_manager.keys() and matcher.priority not in [1, 9]:
- if isinstance(event, GroupMessageEvent):
- # 个人权限
- if (
- not await LevelUser.check_level(
- event.user_id,
- event.group_id,
- admin_manager.get_plugin_level(module),
- )
- and admin_manager.get_plugin_level(module) > 0
- ):
- try:
- if _flmt.check(event.user_id):
- _flmt.start_cd(event.user_id)
- await bot.send_group_msg(
- group_id=event.group_id,
- message=f"{at(event.user_id)}你的权限不足喔,该功能需要的权限等级:"
- f"{admin_manager.get_plugin_level(module)}",
- )
- except ActionFailed:
- pass
- set_block_limit_false(event, module)
- if event.is_tome():
- status_message_manager.add(event.group_id)
- raise IgnoredException("权限不足")
- else:
- if not await LevelUser.check_level(
- event.user_id, 0, admin_manager.get_plugin_level(module)
- ):
- try:
- await bot.send_private_msg(
- user_id=event.user_id,
- message=f"你的权限不足喔,该功能需要的权限等级:{admin_manager.get_plugin_level(module)}",
- )
- except ActionFailed:
- pass
- set_block_limit_false(event, module)
- if event.is_tome():
- status_message_manager.add(event.user_id)
- raise IgnoredException("权限不足")
- if module in plugins2info_dict.keys() and matcher.priority not in [1, 9]:
- # 戳一戳单独判断
- if isinstance(event, GroupMessageEvent) or (
- isinstance(event, PokeNotifyEvent) and event.group_id
- ):
- if status_message_manager.get(event.group_id) is None:
- status_message_manager.delete(event.group_id)
- if plugins2info_dict[module]["level"] > group_manager.get_group_level(
- event.group_id
- ):
- try:
- if _flmt_g.check(event.user_id) and module not in ignore_rst_module:
- _flmt_g.start_cd(event.user_id)
- await bot.send_group_msg(
- group_id=event.group_id, message="群权限不足..."
- )
- except ActionFailed:
- pass
- if event.is_tome():
- status_message_manager.add(event.group_id)
- set_block_limit_false(event, module)
- raise IgnoredException("群权限不足")
- # 插件状态
- if not group_manager.get_plugin_status(module, event.group_id):
- try:
- if module not in ignore_rst_module and _flmt_s.check(
- event.group_id
- ):
- _flmt_s.start_cd(event.group_id)
- await bot.send_group_msg(
- group_id=event.group_id, message="该群未开启此功能.."
- )
- except ActionFailed:
- pass
- if event.is_tome():
- status_message_manager.add(event.group_id)
- set_block_limit_false(event, module)
- raise IgnoredException("未开启此功能...")
- # 管理员禁用
- if not group_manager.get_plugin_status(f"{module}:super", event.group_id):
- try:
- if (
- _flmt_s.check(event.group_id)
- and module not in ignore_rst_module
- ):
- _flmt_s.start_cd(event.group_id)
- await bot.send_group_msg(
- group_id=event.group_id, message="管理员禁用了此群该功能..."
- )
- except ActionFailed:
- pass
- if event.is_tome():
- status_message_manager.add(event.group_id)
- set_block_limit_false(event, module)
- raise IgnoredException("管理员禁用了此群该功能...")
- # 群聊禁用
- if not plugins_manager.get_plugin_status(module, block_type="group"):
- try:
- if (
- _flmt_c.check(event.group_id)
- and module not in ignore_rst_module
- ):
- _flmt_c.start_cd(event.group_id)
- await bot.send_group_msg(
- group_id=event.group_id, message="该功能在群聊中已被禁用..."
- )
- except ActionFailed:
- pass
- if event.is_tome():
- status_message_manager.add(event.group_id)
- set_block_limit_false(event, module)
- raise IgnoredException("该插件在群聊中已被禁用...")
- else:
- # 私聊禁用
- if not plugins_manager.get_plugin_status(module, block_type="private"):
- try:
- if _flmt_c.check(event.user_id):
- _flmt_c.start_cd(event.user_id)
- await bot.send_private_msg(
- user_id=event.user_id, message="该功能在私聊中已被禁用..."
- )
- except ActionFailed:
- pass
- if event.is_tome():
- status_message_manager.add(event.user_id)
- set_block_limit_false(event, module)
- raise IgnoredException("该插件在私聊中已被禁用...")
- # 维护
- if not plugins_manager.get_plugin_status(module, block_type="all"):
- if isinstance(
- event, GroupMessageEvent
- ) and group_manager.check_group_is_white(event.group_id):
- return
- try:
- if isinstance(event, GroupMessageEvent):
- if (
- _flmt_c.check(event.group_id)
- and module not in ignore_rst_module
- ):
- _flmt_c.start_cd(event.group_id)
- await bot.send_group_msg(
- group_id=event.group_id, message="此功能正在维护..."
- )
- else:
- await bot.send_private_msg(
- user_id=event.user_id, message="此功能正在维护..."
- )
- except ActionFailed:
- pass
- if event.is_tome():
- id_ = (
- event.group_id
- if isinstance(event, GroupMessageEvent)
- else event.user_id
- )
- status_message_manager.add(id_)
- set_block_limit_false(event, module)
- raise IgnoredException("此功能正在维护...")
+from nonebot.matcher import Matcher
+from nonebot.message import run_preprocessor, IgnoredException
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from utils.manager import (
+ plugins2settings_manager,
+ admin_manager,
+ group_manager,
+ plugins_manager,
+)
+from .utils import set_block_limit_false, status_message_manager
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ GroupMessageEvent,
+ PokeNotifyEvent,
+)
+from configs.config import Config
+from models.ban_user import BanUser
+from utils.utils import FreqLimiter
+from utils.message_builder import at
+from models.level_user import LevelUser
+
+
+_flmt = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
+_flmt_g = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
+_flmt_s = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
+_flmt_c = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
+
+
+ignore_rst_module = ["ai", "poke", "dialogue"]
+
+
+# 权限检测
+@run_preprocessor
+async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
+ module = matcher.module
+ plugins2info_dict = plugins2settings_manager.get_data()
+ if (
+ (not isinstance(event, MessageEvent) and module != "poke")
+ or await BanUser.is_ban(event.user_id)
+ and str(event.user_id) not in bot.config.superusers
+ ) or (
+ str(event.user_id) in bot.config.superusers
+ and plugins2info_dict.get(module)
+ and not plugins2info_dict[module]["limit_superuser"]
+ ):
+ return
+ # 群黑名单检测
+ if isinstance(event, GroupMessageEvent):
+ if group_manager.get_group_level(event.group_id) < 0:
+ raise IgnoredException("群黑名单")
+ if module in admin_manager.keys() and matcher.priority not in [1, 9]:
+ if isinstance(event, GroupMessageEvent):
+ # 个人权限
+ if (
+ not await LevelUser.check_level(
+ event.user_id,
+ event.group_id,
+ admin_manager.get_plugin_level(module),
+ )
+ and admin_manager.get_plugin_level(module) > 0
+ ):
+ try:
+ if _flmt.check(event.user_id):
+ _flmt.start_cd(event.user_id)
+ await bot.send_group_msg(
+ group_id=event.group_id,
+ message=f"{at(event.user_id)}你的权限不足喔,该功能需要的权限等级:"
+ f"{admin_manager.get_plugin_level(module)}",
+ )
+ except ActionFailed:
+ pass
+ set_block_limit_false(event, module)
+ if event.is_tome():
+ status_message_manager.add(event.group_id)
+ raise IgnoredException("权限不足")
+ else:
+ if not await LevelUser.check_level(
+ event.user_id, 0, admin_manager.get_plugin_level(module)
+ ):
+ try:
+ await bot.send_private_msg(
+ user_id=event.user_id,
+ message=f"你的权限不足喔,该功能需要的权限等级:{admin_manager.get_plugin_level(module)}",
+ )
+ except ActionFailed:
+ pass
+ set_block_limit_false(event, module)
+ if event.is_tome():
+ status_message_manager.add(event.user_id)
+ raise IgnoredException("权限不足")
+ if module in plugins2info_dict.keys() and matcher.priority not in [1, 9]:
+ # 戳一戳单独判断
+ if isinstance(event, GroupMessageEvent) or (
+ isinstance(event, PokeNotifyEvent) and event.group_id
+ ):
+ if status_message_manager.get(event.group_id) is None:
+ status_message_manager.delete(event.group_id)
+ if plugins2info_dict[module]["level"] > group_manager.get_group_level(
+ event.group_id
+ ):
+ try:
+ if _flmt_g.check(event.user_id) and module not in ignore_rst_module:
+ _flmt_g.start_cd(event.user_id)
+ await bot.send_group_msg(
+ group_id=event.group_id, message="群权限不足..."
+ )
+ except ActionFailed:
+ pass
+ if event.is_tome():
+ status_message_manager.add(event.group_id)
+ set_block_limit_false(event, module)
+ raise IgnoredException("群权限不足")
+ # 插件状态
+ if not group_manager.get_plugin_status(module, event.group_id):
+ try:
+ if module not in ignore_rst_module and _flmt_s.check(
+ event.group_id
+ ):
+ _flmt_s.start_cd(event.group_id)
+ await bot.send_group_msg(
+ group_id=event.group_id, message="该群未开启此功能.."
+ )
+ except ActionFailed:
+ pass
+ if event.is_tome():
+ status_message_manager.add(event.group_id)
+ set_block_limit_false(event, module)
+ raise IgnoredException("未开启此功能...")
+ # 管理员禁用
+ if not group_manager.get_plugin_status(f"{module}:super", event.group_id):
+ try:
+ if (
+ _flmt_s.check(event.group_id)
+ and module not in ignore_rst_module
+ ):
+ _flmt_s.start_cd(event.group_id)
+ await bot.send_group_msg(
+ group_id=event.group_id, message="管理员禁用了此群该功能..."
+ )
+ except ActionFailed:
+ pass
+ if event.is_tome():
+ status_message_manager.add(event.group_id)
+ set_block_limit_false(event, module)
+ raise IgnoredException("管理员禁用了此群该功能...")
+ # 群聊禁用
+ if not plugins_manager.get_plugin_status(module, block_type="group"):
+ try:
+ if (
+ _flmt_c.check(event.group_id)
+ and module not in ignore_rst_module
+ ):
+ _flmt_c.start_cd(event.group_id)
+ await bot.send_group_msg(
+ group_id=event.group_id, message="该功能在群聊中已被禁用..."
+ )
+ except ActionFailed:
+ pass
+ if event.is_tome():
+ status_message_manager.add(event.group_id)
+ set_block_limit_false(event, module)
+ raise IgnoredException("该插件在群聊中已被禁用...")
+ else:
+ # 私聊禁用
+ if not plugins_manager.get_plugin_status(module, block_type="private"):
+ try:
+ if _flmt_c.check(event.user_id):
+ _flmt_c.start_cd(event.user_id)
+ await bot.send_private_msg(
+ user_id=event.user_id, message="该功能在私聊中已被禁用..."
+ )
+ except ActionFailed:
+ pass
+ if event.is_tome():
+ status_message_manager.add(event.user_id)
+ set_block_limit_false(event, module)
+ raise IgnoredException("该插件在私聊中已被禁用...")
+ # 维护
+ if not plugins_manager.get_plugin_status(module, block_type="all"):
+ if isinstance(
+ event, GroupMessageEvent
+ ) and group_manager.check_group_is_white(event.group_id):
+ return
+ try:
+ if isinstance(event, GroupMessageEvent):
+ if (
+ _flmt_c.check(event.group_id)
+ and module not in ignore_rst_module
+ ):
+ _flmt_c.start_cd(event.group_id)
+ await bot.send_group_msg(
+ group_id=event.group_id, message="此功能正在维护..."
+ )
+ else:
+ await bot.send_private_msg(
+ user_id=event.user_id, message="此功能正在维护..."
+ )
+ except ActionFailed:
+ pass
+ if event.is_tome():
+ id_ = (
+ event.group_id
+ if isinstance(event, GroupMessageEvent)
+ else event.user_id
+ )
+ status_message_manager.add(id_)
+ set_block_limit_false(event, module)
+ raise IgnoredException("此功能正在维护...")
diff --git a/basic_plugins/hooks/ban_hook.py b/basic_plugins/hooks/ban_hook.py
old mode 100644
new mode 100755
index e7d131b0..ea59ef0a
--- a/basic_plugins/hooks/ban_hook.py
+++ b/basic_plugins/hooks/ban_hook.py
@@ -1,83 +1,83 @@
-from nonebot.matcher import Matcher
-from nonebot.message import run_preprocessor, IgnoredException
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import (
- Bot,
- MessageEvent,
- GroupMessageEvent,
-)
-from configs.config import Config
-from models.ban_user import BanUser
-from utils.utils import is_number, static_flmt
-from utils.message_builder import at
-
-
-Config.add_plugin_config(
- "hook",
- "BAN_RESULT",
- "才不会给你发消息.",
- help_="对被ban用户发送的消息",
-)
-
-
-# 检查是否被ban
-@run_preprocessor
-async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
- try:
- if (
- await BanUser.is_super_ban(event.user_id)
- and str(event.user_id) not in bot.config.superusers
- ):
- raise IgnoredException("用户处于超级黑名单中")
- except AttributeError:
- pass
- if not isinstance(event, MessageEvent):
- return
- if matcher.type == "message" and matcher.priority not in [1, 9]:
- if (
- await BanUser.is_ban(event.user_id)
- and str(event.user_id) not in bot.config.superusers
- ):
- time = await BanUser.check_ban_time(event.user_id)
- if is_number(time):
- time = abs(int(time))
- if time < 60:
- time = str(time) + " 秒"
- else:
- time = str(int(time / 60)) + " 分钟"
- else:
- time = str(time) + " 分钟"
- if isinstance(event, GroupMessageEvent):
- if not static_flmt.check(event.user_id):
- raise IgnoredException("用户处于黑名单中")
- static_flmt.start_cd(event.user_id)
- if matcher.priority != 9:
- try:
- ban_result = Config.get_config("hook", "BAN_RESULT")
- if ban_result:
- await bot.send_group_msg(
- group_id=event.group_id,
- message=at(event.user_id)
- + ban_result
- + f" 在..在 {time} 后才会理你喔",
- )
- except ActionFailed:
- pass
- else:
- if not static_flmt.check(event.user_id):
- raise IgnoredException("用户处于黑名单中")
- static_flmt.start_cd(event.user_id)
- if matcher.priority != 9:
- try:
- ban_result = Config.get_config("hook", "BAN_RESULT")
- if ban_result:
- await bot.send_private_msg(
- user_id=event.user_id,
- message=at(event.user_id)
- + ban_result
- + f" 在..在 {time}后才会理你喔",
- )
- except ActionFailed:
- pass
+from nonebot.matcher import Matcher
+from nonebot.message import run_preprocessor, IgnoredException
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ GroupMessageEvent,
+)
+from configs.config import Config
+from models.ban_user import BanUser
+from utils.utils import is_number, static_flmt
+from utils.message_builder import at
+
+
+Config.add_plugin_config(
+ "hook",
+ "BAN_RESULT",
+ "才不会给你发消息.",
+ help_="对被ban用户发送的消息",
+)
+
+
+# 检查是否被ban
+@run_preprocessor
+async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
+ try:
+ if (
+ await BanUser.is_super_ban(event.user_id)
+ and str(event.user_id) not in bot.config.superusers
+ ):
+ raise IgnoredException("用户处于超级黑名单中")
+ except AttributeError:
+ pass
+ if not isinstance(event, MessageEvent):
+ return
+ if matcher.type == "message" and matcher.priority not in [1, 9]:
+ if (
+ await BanUser.is_ban(event.user_id)
+ and str(event.user_id) not in bot.config.superusers
+ ):
+ time = await BanUser.check_ban_time(event.user_id)
+ if is_number(time):
+ time = abs(int(time))
+ if time < 60:
+ time = str(time) + " 秒"
+ else:
+ time = str(int(time / 60)) + " 分钟"
+ else:
+ time = str(time) + " 分钟"
+ if isinstance(event, GroupMessageEvent):
+ if not static_flmt.check(event.user_id):
+ raise IgnoredException("用户处于黑名单中")
+ static_flmt.start_cd(event.user_id)
+ if matcher.priority != 9:
+ try:
+ ban_result = Config.get_config("hook", "BAN_RESULT")
+ if ban_result:
+ await bot.send_group_msg(
+ group_id=event.group_id,
+ message=at(event.user_id)
+ + ban_result
+ + f" 在..在 {time} 后才会理你喔",
+ )
+ except ActionFailed:
+ pass
+ else:
+ if not static_flmt.check(event.user_id):
+ raise IgnoredException("用户处于黑名单中")
+ static_flmt.start_cd(event.user_id)
+ if matcher.priority != 9:
+ try:
+ ban_result = Config.get_config("hook", "BAN_RESULT")
+ if ban_result:
+ await bot.send_private_msg(
+ user_id=event.user_id,
+ message=at(event.user_id)
+ + ban_result
+ + f" 在..在 {time}后才会理你喔",
+ )
+ except ActionFailed:
+ pass
raise IgnoredException("用户处于黑名单中")
\ No newline at end of file
diff --git a/basic_plugins/hooks/chkdsk_hook.py b/basic_plugins/hooks/chkdsk_hook.py
old mode 100644
new mode 100755
index 3fa53285..e04d20c4
--- a/basic_plugins/hooks/chkdsk_hook.py
+++ b/basic_plugins/hooks/chkdsk_hook.py
@@ -1,54 +1,54 @@
-from nonebot.matcher import Matcher
-from nonebot.message import run_preprocessor, IgnoredException
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import (
- Bot,
- MessageEvent,
- GroupMessageEvent,
-)
-from configs.config import Config
-from models.ban_user import BanUser
-from utils.utils import BanCheckLimiter
-from utils.message_builder import at
-from services.log import logger
-
-
-_blmt = BanCheckLimiter(
- Config.get_config("hook", "MALICIOUS_CHECK_TIME"),
- Config.get_config("hook", "MALICIOUS_BAN_COUNT"),
-)
-
-
-# 恶意触发命令检测
-@run_preprocessor
-async def _(matcher: Matcher, bot: Bot, event: GroupMessageEvent, state: T_State):
- if not isinstance(event, MessageEvent):
- return
- if matcher.type == "message" and matcher.priority not in [1, 9]:
- if state["_prefix"]["raw_command"]:
- if _blmt.check(f'{event.user_id}{state["_prefix"]["raw_command"]}'):
- if await BanUser.ban(
- event.user_id,
- 9,
- Config.get_config("hook", "MALICIOUS_BAN_TIME") * 60,
- ):
- logger.info(f"USER {event.user_id} 触发了恶意触发检测")
- if isinstance(event, GroupMessageEvent):
- try:
- await bot.send_group_msg(
- group_id=event.group_id,
- message=at(event.user_id) + "检测到恶意触发命令,您将被封禁 30 分钟",
- )
- except ActionFailed:
- pass
- else:
- try:
- await bot.send_private_msg(
- user_id=event.user_id,
- message=at(event.user_id) + "检测到恶意触发命令,您将被封禁 30 分钟",
- )
- except ActionFailed:
- pass
- raise IgnoredException("检测到恶意触发命令")
- _blmt.add(f'{event.user_id}{state["_prefix"]["raw_command"]}')
+from nonebot.matcher import Matcher
+from nonebot.message import run_preprocessor, IgnoredException
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ GroupMessageEvent,
+)
+from configs.config import Config
+from models.ban_user import BanUser
+from utils.utils import BanCheckLimiter
+from utils.message_builder import at
+from services.log import logger
+
+
+_blmt = BanCheckLimiter(
+ Config.get_config("hook", "MALICIOUS_CHECK_TIME"),
+ Config.get_config("hook", "MALICIOUS_BAN_COUNT"),
+)
+
+
+# 恶意触发命令检测
+@run_preprocessor
+async def _(matcher: Matcher, bot: Bot, event: GroupMessageEvent, state: T_State):
+ if not isinstance(event, MessageEvent):
+ return
+ if matcher.type == "message" and matcher.priority not in [1, 9]:
+ if state["_prefix"]["raw_command"]:
+ if _blmt.check(f'{event.user_id}{state["_prefix"]["raw_command"]}'):
+ if await BanUser.ban(
+ event.user_id,
+ 9,
+ Config.get_config("hook", "MALICIOUS_BAN_TIME") * 60,
+ ):
+ logger.info(f"USER {event.user_id} 触发了恶意触发检测")
+ if isinstance(event, GroupMessageEvent):
+ try:
+ await bot.send_group_msg(
+ group_id=event.group_id,
+ message=at(event.user_id) + "检测到恶意触发命令,您将被封禁 30 分钟",
+ )
+ except ActionFailed:
+ pass
+ else:
+ try:
+ await bot.send_private_msg(
+ user_id=event.user_id,
+ message=at(event.user_id) + "检测到恶意触发命令,您将被封禁 30 分钟",
+ )
+ except ActionFailed:
+ pass
+ raise IgnoredException("检测到恶意触发命令")
+ _blmt.add(f'{event.user_id}{state["_prefix"]["raw_command"]}')
diff --git a/basic_plugins/hooks/limit_hook.py b/basic_plugins/hooks/limit_hook.py
old mode 100644
new mode 100755
index eff6760c..8e747316
--- a/basic_plugins/hooks/limit_hook.py
+++ b/basic_plugins/hooks/limit_hook.py
@@ -1,146 +1,146 @@
-from nonebot.matcher import Matcher
-from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from models.friend_user import FriendUser
-from models.group_member_info import GroupInfoUser
-from utils.message_builder import at
-from .utils import status_message_manager, set_block_limit_false
-from utils.manager import (
- plugins2cd_manager,
- plugins2block_manager,
- plugins2count_manager,
-)
-from typing import Optional
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import (
- Bot,
- Event,
- MessageEvent,
- PrivateMessageEvent,
- GroupMessageEvent,
- Message,
-)
-
-
-# 命令cd | 命令阻塞 | 命令次数
-@run_preprocessor
-async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
- if not isinstance(event, MessageEvent) and matcher.module != "poke":
- return
- module = matcher.module
- if (
- isinstance(event, GroupMessageEvent)
- and status_message_manager.get(event.group_id) is None
- ):
- status_message_manager.delete(event.group_id)
- # Count
- if (
- plugins2count_manager.check_plugin_count_status(module)
- and event.user_id not in bot.config.superusers
- ):
- plugin_count_data = plugins2count_manager.get_plugin_count_data(module)
- limit_type = plugin_count_data["limit_type"]
- rst = plugin_count_data["rst"]
- count_type_ = event.user_id
- if limit_type == "group" and isinstance(event, GroupMessageEvent):
- count_type_ = event.group_id
- if not plugins2count_manager.check(module, count_type_):
- if rst:
- rst = await init_rst(rst, event)
- await send_msg(rst, bot, event)
- raise IgnoredException(f"{module} count次数限制...")
- else:
- plugins2count_manager.increase(module, count_type_)
- # Cd
- if plugins2cd_manager.check_plugin_cd_status(module):
- plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
- check_type = plugin_cd_data["check_type"]
- limit_type = plugin_cd_data["limit_type"]
- rst = plugin_cd_data["rst"]
- if (
- (isinstance(event, PrivateMessageEvent) and check_type == "private")
- or (isinstance(event, GroupMessageEvent) and check_type == "group")
- or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all"
- ):
- cd_type_ = event.user_id
- if limit_type == "group" and isinstance(event, GroupMessageEvent):
- cd_type_ = event.group_id
- if not plugins2cd_manager.check(module, cd_type_):
- if rst:
- rst = await init_rst(rst, event)
- await send_msg(rst, bot, event)
- raise IgnoredException(f"{module} 正在cd中...")
- else:
- plugins2cd_manager.start_cd(module, cd_type_)
- # Block
- if plugins2block_manager.check_plugin_block_status(module):
- plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
- check_type = plugin_block_data["check_type"]
- limit_type = plugin_block_data["limit_type"]
- rst = plugin_block_data["rst"]
- if (
- (isinstance(event, PrivateMessageEvent) and check_type == "private")
- or (isinstance(event, GroupMessageEvent) and check_type == "group")
- or check_type == "all"
- ):
- block_type_ = event.user_id
- if limit_type == "group" and isinstance(event, GroupMessageEvent):
- block_type_ = event.group_id
- if plugins2block_manager.check(block_type_, module):
- if rst:
- rst = await init_rst(rst, event)
- await send_msg(rst, bot, event)
- raise IgnoredException(f"{event.user_id}正在调用{module}....")
- else:
- plugins2block_manager.set_true(block_type_, module)
-
-
-async def send_msg(rst: str, bot: Bot, event: MessageEvent):
- """
- 发送信息
- :param rst: pass
- :param bot: pass
- :param event: pass
- """
- rst = await init_rst(rst, event)
- try:
- if isinstance(event, GroupMessageEvent):
- status_message_manager.add(event.group_id)
- await bot.send_group_msg(group_id=event.group_id, message=Message(rst))
- else:
- status_message_manager.add(event.user_id)
- await bot.send_private_msg(user_id=event.user_id, message=Message(rst))
- except ActionFailed:
- pass
-
-
-# 解除命令block阻塞
-@run_postprocessor
-async def _(
- matcher: Matcher,
- exception: Optional[Exception],
- bot: Bot,
- event: Event,
- state: T_State,
-):
- if not isinstance(event, MessageEvent) and matcher.module != "poke":
- return
- module = matcher.module
- set_block_limit_false(event, module)
-
-
-async def init_rst(rst: str, event: MessageEvent):
- if "[uname]" in rst:
- uname = event.sender.card if event.sender.card else event.sender.nickname
- rst = rst.replace("[uname]", uname)
- if "[nickname]" in rst:
- if isinstance(event, GroupMessageEvent):
- nickname = await GroupInfoUser.get_group_member_nickname(
- event.user_id, event.group_id
- )
- else:
- nickname = await FriendUser.get_friend_nickname(event.user_id)
- rst = rst.replace("[nickname]", nickname)
- if "[at]" in rst and isinstance(event, GroupMessageEvent):
- rst = rst.replace("[at]", str(at(event.user_id)))
- return rst
+from nonebot.matcher import Matcher
+from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from models.friend_user import FriendUser
+from models.group_member_info import GroupInfoUser
+from utils.message_builder import at
+from .utils import status_message_manager, set_block_limit_false
+from utils.manager import (
+ plugins2cd_manager,
+ plugins2block_manager,
+ plugins2count_manager,
+)
+from typing import Optional
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import (
+ Bot,
+ Event,
+ MessageEvent,
+ PrivateMessageEvent,
+ GroupMessageEvent,
+ Message,
+)
+
+
+# 命令cd | 命令阻塞 | 命令次数
+@run_preprocessor
+async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
+ if not isinstance(event, MessageEvent) and matcher.module != "poke":
+ return
+ module = matcher.module
+ if (
+ isinstance(event, GroupMessageEvent)
+ and status_message_manager.get(event.group_id) is None
+ ):
+ status_message_manager.delete(event.group_id)
+ # Count
+ if (
+ plugins2count_manager.check_plugin_count_status(module)
+ and event.user_id not in bot.config.superusers
+ ):
+ plugin_count_data = plugins2count_manager.get_plugin_count_data(module)
+ limit_type = plugin_count_data["limit_type"]
+ rst = plugin_count_data["rst"]
+ count_type_ = event.user_id
+ if limit_type == "group" and isinstance(event, GroupMessageEvent):
+ count_type_ = event.group_id
+ if not plugins2count_manager.check(module, count_type_):
+ if rst:
+ rst = await init_rst(rst, event)
+ await send_msg(rst, bot, event)
+ raise IgnoredException(f"{module} count次数限制...")
+ else:
+ plugins2count_manager.increase(module, count_type_)
+ # Cd
+ if plugins2cd_manager.check_plugin_cd_status(module):
+ plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
+ check_type = plugin_cd_data["check_type"]
+ limit_type = plugin_cd_data["limit_type"]
+ rst = plugin_cd_data["rst"]
+ if (
+ (isinstance(event, PrivateMessageEvent) and check_type == "private")
+ or (isinstance(event, GroupMessageEvent) and check_type == "group")
+ or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all"
+ ):
+ cd_type_ = event.user_id
+ if limit_type == "group" and isinstance(event, GroupMessageEvent):
+ cd_type_ = event.group_id
+ if not plugins2cd_manager.check(module, cd_type_):
+ if rst:
+ rst = await init_rst(rst, event)
+ await send_msg(rst, bot, event)
+ raise IgnoredException(f"{module} 正在cd中...")
+ else:
+ plugins2cd_manager.start_cd(module, cd_type_)
+ # Block
+ if plugins2block_manager.check_plugin_block_status(module):
+ plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
+ check_type = plugin_block_data["check_type"]
+ limit_type = plugin_block_data["limit_type"]
+ rst = plugin_block_data["rst"]
+ if (
+ (isinstance(event, PrivateMessageEvent) and check_type == "private")
+ or (isinstance(event, GroupMessageEvent) and check_type == "group")
+ or check_type == "all"
+ ):
+ block_type_ = event.user_id
+ if limit_type == "group" and isinstance(event, GroupMessageEvent):
+ block_type_ = event.group_id
+ if plugins2block_manager.check(block_type_, module):
+ if rst:
+ rst = await init_rst(rst, event)
+ await send_msg(rst, bot, event)
+ raise IgnoredException(f"{event.user_id}正在调用{module}....")
+ else:
+ plugins2block_manager.set_true(block_type_, module)
+
+
+async def send_msg(rst: str, bot: Bot, event: MessageEvent):
+ """
+ 发送信息
+ :param rst: pass
+ :param bot: pass
+ :param event: pass
+ """
+ rst = await init_rst(rst, event)
+ try:
+ if isinstance(event, GroupMessageEvent):
+ status_message_manager.add(event.group_id)
+ await bot.send_group_msg(group_id=event.group_id, message=Message(rst))
+ else:
+ status_message_manager.add(event.user_id)
+ await bot.send_private_msg(user_id=event.user_id, message=Message(rst))
+ except ActionFailed:
+ pass
+
+
+# 解除命令block阻塞
+@run_postprocessor
+async def _(
+ matcher: Matcher,
+ exception: Optional[Exception],
+ bot: Bot,
+ event: Event,
+ state: T_State,
+):
+ if not isinstance(event, MessageEvent) and matcher.module != "poke":
+ return
+ module = matcher.module
+ set_block_limit_false(event, module)
+
+
+async def init_rst(rst: str, event: MessageEvent):
+ if "[uname]" in rst:
+ uname = event.sender.card if event.sender.card else event.sender.nickname
+ rst = rst.replace("[uname]", uname)
+ if "[nickname]" in rst:
+ if isinstance(event, GroupMessageEvent):
+ nickname = await GroupInfoUser.get_group_member_nickname(
+ event.user_id, event.group_id
+ )
+ else:
+ nickname = await FriendUser.get_friend_nickname(event.user_id)
+ rst = rst.replace("[nickname]", nickname)
+ if "[at]" in rst and isinstance(event, GroupMessageEvent):
+ rst = rst.replace("[at]", str(at(event.user_id)))
+ return rst
diff --git a/basic_plugins/hooks/other_hook.py b/basic_plugins/hooks/other_hook.py
old mode 100644
new mode 100755
index b2a85919..b2d617f5
--- a/basic_plugins/hooks/other_hook.py
+++ b/basic_plugins/hooks/other_hook.py
@@ -1,41 +1,41 @@
-from nonebot.matcher import Matcher
-from nonebot.message import run_preprocessor, IgnoredException
-from nonebot.typing import T_State
-from .utils import status_message_manager
-from nonebot.adapters.cqhttp import (
- Bot,
- MessageEvent,
- PrivateMessageEvent,
- GroupMessageEvent,
-)
-
-
-# 为什么AI会自己和自己聊天
-@run_preprocessor
-async def _(matcher: Matcher, bot: Bot, event: PrivateMessageEvent, state: T_State):
- if not isinstance(event, MessageEvent):
- return
- if event.user_id == int(bot.self_id):
- raise IgnoredException("为什么AI会自己和自己聊天")
-
-
-# 有命令就别说话了
-@run_preprocessor
-async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
- if not isinstance(event, MessageEvent):
- return
- if matcher.type == "message" and matcher.module == "ai":
- if (
- isinstance(event, GroupMessageEvent)
- and not status_message_manager.check(event.group_id)
- ):
- status_message_manager.delete(event.group_id)
- raise IgnoredException("有命令就别说话了")
- elif (
- isinstance(event, PrivateMessageEvent)
- and not status_message_manager.check(event.user_id)
- ):
- print(status_message_manager)
- status_message_manager.delete(event.user_id)
- raise IgnoredException("有命令就别说话了")
-
+from nonebot.matcher import Matcher
+from nonebot.message import run_preprocessor, IgnoredException
+from nonebot.typing import T_State
+from .utils import status_message_manager
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ PrivateMessageEvent,
+ GroupMessageEvent,
+)
+
+
+# 为什么AI会自己和自己聊天
+@run_preprocessor
+async def _(matcher: Matcher, bot: Bot, event: PrivateMessageEvent, state: T_State):
+ if not isinstance(event, MessageEvent):
+ return
+ if event.user_id == int(bot.self_id):
+ raise IgnoredException("为什么AI会自己和自己聊天")
+
+
+# 有命令就别说话了
+@run_preprocessor
+async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
+ if not isinstance(event, MessageEvent):
+ return
+ if matcher.type == "message" and matcher.module == "ai":
+ if (
+ isinstance(event, GroupMessageEvent)
+ and not status_message_manager.check(event.group_id)
+ ):
+ status_message_manager.delete(event.group_id)
+ raise IgnoredException("有命令就别说话了")
+ elif (
+ isinstance(event, PrivateMessageEvent)
+ and not status_message_manager.check(event.user_id)
+ ):
+ print(status_message_manager)
+ status_message_manager.delete(event.user_id)
+ raise IgnoredException("有命令就别说话了")
+
diff --git a/basic_plugins/hooks/utils.py b/basic_plugins/hooks/utils.py
old mode 100644
new mode 100755
index 5231b8f9..7860b42e
--- a/basic_plugins/hooks/utils.py
+++ b/basic_plugins/hooks/utils.py
@@ -1,48 +1,48 @@
-from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
-from utils.manager import plugins2block_manager, StaticData
-import time
-
-
-class StatusMessageManager(StaticData):
-
- def __init__(self):
- super().__init__(None)
-
- def add(self, id_: int):
- self._data[id_] = time.time()
-
- def delete(self, id_: int):
- if self._data.get(id_):
- del self._data[id_]
-
- def check(self, id_: int, t: int = 30) -> bool:
- if self._data.get(id_):
- if time.time() - self._data[id_] > t:
- del self._data[id_]
- return True
- return False
- return True
-
-
-status_message_manager = StatusMessageManager()
-
-
-def set_block_limit_false(event, module):
- """
- 设置用户block为false
- :param event: event
- :param module: 插件模块
- """
- if plugins2block_manager.check_plugin_block_status(module):
- plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
- check_type = plugin_block_data["check_type"]
- limit_type = plugin_block_data["limit_type"]
- if not (
- (isinstance(event, GroupMessageEvent) and check_type == "private")
- or (isinstance(event, PrivateMessageEvent) and check_type == "group")
- ):
- block_type_ = event.user_id
- if limit_type == "group" and isinstance(event, GroupMessageEvent):
- block_type_ = event.group_id
- plugins2block_manager.set_false(block_type_, module)
-
+from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
+from utils.manager import plugins2block_manager, StaticData
+import time
+
+
+class StatusMessageManager(StaticData):
+
+ def __init__(self):
+ super().__init__(None)
+
+ def add(self, id_: int):
+ self._data[id_] = time.time()
+
+ def delete(self, id_: int):
+ if self._data.get(id_):
+ del self._data[id_]
+
+ def check(self, id_: int, t: int = 30) -> bool:
+ if self._data.get(id_):
+ if time.time() - self._data[id_] > t:
+ del self._data[id_]
+ return True
+ return False
+ return True
+
+
+status_message_manager = StatusMessageManager()
+
+
+def set_block_limit_false(event, module):
+ """
+ 设置用户block为false
+ :param event: event
+ :param module: 插件模块
+ """
+ if plugins2block_manager.check_plugin_block_status(module):
+ plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
+ check_type = plugin_block_data["check_type"]
+ limit_type = plugin_block_data["limit_type"]
+ if not (
+ (isinstance(event, GroupMessageEvent) and check_type == "private")
+ or (isinstance(event, PrivateMessageEvent) and check_type == "group")
+ ):
+ block_type_ = event.user_id
+ if limit_type == "group" and isinstance(event, GroupMessageEvent):
+ block_type_ = event.group_id
+ plugins2block_manager.set_false(block_type_, module)
+
diff --git a/basic_plugins/hooks/withdraw_message_hook.py b/basic_plugins/hooks/withdraw_message_hook.py
old mode 100644
new mode 100755
index 76356542..d91ef8d3
--- a/basic_plugins/hooks/withdraw_message_hook.py
+++ b/basic_plugins/hooks/withdraw_message_hook.py
@@ -1,28 +1,28 @@
-from nonebot.matcher import Matcher
-from nonebot.message import run_postprocessor
-from typing import Optional
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, Event
-from utils.manager import withdraw_message_manager
-import asyncio
-
-
-# 消息撤回
-@run_postprocessor
-async def _(
- matcher: Matcher,
- exception: Optional[Exception],
- bot: Bot,
- event: Event,
- state: T_State,
-):
- tasks = []
- for id_, time in withdraw_message_manager.data:
- tasks.append(asyncio.ensure_future(_withdraw_message(bot, id_, time)))
- withdraw_message_manager.remove((id_, time))
- await asyncio.gather(*tasks)
-
-
-async def _withdraw_message(bot: Bot, id_: int, time: int):
- await asyncio.sleep(time)
- await bot.delete_msg(message_id=id_, self_id=int(bot.self_id))
+from nonebot.matcher import Matcher
+from nonebot.message import run_postprocessor
+from typing import Optional
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, Event
+from utils.manager import withdraw_message_manager
+import asyncio
+
+
+# 消息撤回
+@run_postprocessor
+async def _(
+ matcher: Matcher,
+ exception: Optional[Exception],
+ bot: Bot,
+ event: Event,
+ state: T_State,
+):
+ tasks = []
+ for id_, time in withdraw_message_manager.data:
+ tasks.append(asyncio.ensure_future(_withdraw_message(bot, id_, time)))
+ withdraw_message_manager.remove((id_, time))
+ await asyncio.gather(*tasks)
+
+
+async def _withdraw_message(bot: Bot, id_: int, time: int):
+ await asyncio.sleep(time)
+ await bot.delete_msg(message_id=id_, self_id=int(bot.self_id))
diff --git a/basic_plugins/init_plugin_config/__init__.py b/basic_plugins/init_plugin_config/__init__.py
old mode 100644
new mode 100755
index 0b4efb6c..65156ada
--- a/basic_plugins/init_plugin_config/__init__.py
+++ b/basic_plugins/init_plugin_config/__init__.py
@@ -9,10 +9,12 @@ from .init_plugins_limit import (
init_plugins_count_limit,
init_plugins_cd_limit,
)
+from .init import init
from .check_plugin_status import check_plugin_status
from nonebot.adapters.cqhttp import Bot
from configs.path_config import DATA_PATH
from services.log import logger
+from pathlib import Path
from nonebot import Driver
import nonebot
@@ -30,6 +32,11 @@ def _():
"""
初始化数据
"""
+ _flag = False
+ config_file = Path(DATA_PATH) / "configs" / "plugins2config.yaml"
+ if not config_file.exists():
+ _flag = True
+ init()
init_plugins_settings(DATA_PATH)
init_plugins_cd_limit(DATA_PATH)
init_plugins_block_limit(DATA_PATH)
@@ -42,6 +49,8 @@ def _():
if x:
for key in x.keys():
plugins_manager.block_plugin(key, block_type=x[key])
+ if _flag:
+ raise Exception("首次运行,已在configs目录下生成配置文件config.yaml,修改后重启即可...")
logger.info("初始化数据完成...")
diff --git a/basic_plugins/init_plugin_config/check_plugin_status.py b/basic_plugins/init_plugin_config/check_plugin_status.py
old mode 100644
new mode 100755
index ad2bd049..c8cbee77
--- a/basic_plugins/init_plugin_config/check_plugin_status.py
+++ b/basic_plugins/init_plugin_config/check_plugin_status.py
@@ -1,18 +1,18 @@
-from utils.manager import plugins_manager
-from nonebot.adapters.cqhttp import Bot
-
-
-async def check_plugin_status(bot: Bot):
- """
- 遍历查看插件加载情况
- """
- rst = ""
- for plugin in plugins_manager.keys():
- data = plugins_manager.get(plugin)
- if data.get("error") or data.get("error") is None:
- rst += f'{plugin}:{data["plugin_name"]}\n'
- if rst:
- rst = "以下插件加载失败..\n" + rst
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]), message=rst[:-1]
- )
+from utils.manager import plugins_manager
+from nonebot.adapters.cqhttp import Bot
+
+
+async def check_plugin_status(bot: Bot):
+ """
+ 遍历查看插件加载情况
+ """
+ rst = ""
+ for plugin in plugins_manager.keys():
+ data = plugins_manager.get(plugin)
+ if data.get("error") or data.get("error") is None:
+ rst += f'{plugin}:{data["plugin_name"]}\n'
+ if rst:
+ rst = "以下插件加载失败..\n" + rst
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]), message=rst[:-1]
+ )
diff --git a/basic_plugins/init_plugin_config/init.py b/basic_plugins/init_plugin_config/init.py
new file mode 100644
index 00000000..d8640828
--- /dev/null
+++ b/basic_plugins/init_plugin_config/init.py
@@ -0,0 +1,14 @@
+from utils.manager import plugins2settings_manager
+
+
+def init():
+ if plugins2settings_manager.get("update_pic"):
+ plugins2settings_manager["update_picture"] = plugins2settings_manager["update_pic"]
+ plugins2settings_manager.delete("update_pic")
+ if plugins2settings_manager.get("white2black_img"):
+ plugins2settings_manager["white2black_image"] = plugins2settings_manager["white2black_img"]
+ plugins2settings_manager.delete("white2black_img")
+ if plugins2settings_manager.get("send_img"):
+ plugins2settings_manager["send_image"] = plugins2settings_manager["send_img"]
+ plugins2settings_manager.delete("send_img")
+
diff --git a/basic_plugins/init_plugin_config/init_group_manager.py b/basic_plugins/init_plugin_config/init_group_manager.py
old mode 100644
new mode 100755
index 3b91ae03..58a1a744
--- a/basic_plugins/init_plugin_config/init_group_manager.py
+++ b/basic_plugins/init_plugin_config/init_group_manager.py
@@ -1,73 +1,73 @@
-from pathlib import Path
-from utils.manager import group_manager
-from services.db_context import db
-from asyncpg.exceptions import DuplicateColumnError
-from services.log import logger
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-try:
- from models.group_remind import GroupRemind
-except ModuleNotFoundError:
- pass
-
-
-async def init_group_manager():
- """
- 旧数据格式替换为新格式
- 初始化数据
- """
- old_group_level_file = Path() / "data" / "manager" / "group_level.json"
- old_plugin_list_file = Path() / "data" / "manager" / "plugin_list.json"
- if old_group_level_file.exists():
- data = json.load(open(old_group_level_file, "r", encoding="utf8"))
- for key in data.keys():
- group = key
- level = data[key]
- group_manager.set_group_level(group, level)
- old_group_level_file.unlink()
- group_manager.save()
-
- if old_plugin_list_file.exists():
- data = json.load(open(old_plugin_list_file, "r", encoding="utf8"))
- for plugin in data.keys():
- for group in data[plugin].keys():
- if group == "default" and not data[plugin]["default"]:
- group_manager.block_plugin(plugin)
- elif not data[plugin][group]:
- group_manager.block_plugin(plugin, group)
- old_plugin_list_file.unlink()
- old_data_table = Path() / "models" / "group_remind.py"
- try:
- if old_data_table.exists():
- b = {
- "hy": "group_welcome",
- "kxcz": "open_case_reset_remind",
- "zwa": "zwa",
- "blpar": "bilibili_parse",
- "epic": "epic_free_game",
- "pa": "pa",
- "almanac": "genshin_alc",
- }
- for group in group_manager.get_data()["group_manager"]:
- for remind in b:
- try:
- status = await GroupRemind.get_status(int(group), remind)
- if status is not None:
- if status:
- await group_manager.open_group_task(group, b[remind])
- logger.info(f"读取旧数据-->{group} 开启 {b[remind]}")
- else:
- await group_manager.close_group_task(group, b[remind])
- logger.info(f"读取旧数据-->{group} 关闭 {b[remind]}")
- except Exception as e:
- pass
- query = db.text("DROP TABLE group_reminds;")
- await db.first(query)
- old_data_table.unlink()
- logger.info("旧数据读取完毕,删除了舍弃表 group_reminds...")
- except (ModuleNotFoundError, DuplicateColumnError):
- pass
- group_manager.save()
+from pathlib import Path
+from utils.manager import group_manager
+from services.db_context import db
+from asyncpg.exceptions import DuplicateColumnError
+from services.log import logger
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+try:
+ from models.group_remind import GroupRemind
+except ModuleNotFoundError:
+ pass
+
+
+async def init_group_manager():
+ """
+ 旧数据格式替换为新格式
+ 初始化数据
+ """
+ old_group_level_file = Path() / "data" / "manager" / "group_level.json"
+ old_plugin_list_file = Path() / "data" / "manager" / "plugin_list.json"
+ if old_group_level_file.exists():
+ data = json.load(open(old_group_level_file, "r", encoding="utf8"))
+ for key in data.keys():
+ group = key
+ level = data[key]
+ group_manager.set_group_level(group, level)
+ old_group_level_file.unlink()
+ group_manager.save()
+
+ if old_plugin_list_file.exists():
+ data = json.load(open(old_plugin_list_file, "r", encoding="utf8"))
+ for plugin in data.keys():
+ for group in data[plugin].keys():
+ if group == "default" and not data[plugin]["default"]:
+ group_manager.block_plugin(plugin)
+ elif not data[plugin][group]:
+ group_manager.block_plugin(plugin, group)
+ old_plugin_list_file.unlink()
+ old_data_table = Path() / "models" / "group_remind.py"
+ try:
+ if old_data_table.exists():
+ b = {
+ "hy": "group_welcome",
+ "kxcz": "open_case_reset_remind",
+ "zwa": "zwa",
+ "blpar": "bilibili_parse",
+ "epic": "epic_free_game",
+ "pa": "pa",
+ "almanac": "genshin_alc",
+ }
+ for group in group_manager.get_data()["group_manager"]:
+ for remind in b:
+ try:
+ status = await GroupRemind.get_status(int(group), remind)
+ if status is not None:
+ if status:
+ await group_manager.open_group_task(group, b[remind])
+ logger.info(f"读取旧数据-->{group} 开启 {b[remind]}")
+ else:
+ await group_manager.close_group_task(group, b[remind])
+ logger.info(f"读取旧数据-->{group} 关闭 {b[remind]}")
+ except Exception as e:
+ pass
+ query = db.text("DROP TABLE group_reminds;")
+ await db.first(query)
+ old_data_table.unlink()
+ logger.info("旧数据读取完毕,删除了舍弃表 group_reminds...")
+ except (ModuleNotFoundError, DuplicateColumnError):
+ pass
+ group_manager.save()
diff --git a/basic_plugins/init_plugin_config/init_none_plugin_count_manager.py b/basic_plugins/init_plugin_config/init_none_plugin_count_manager.py
old mode 100644
new mode 100755
index b89dd422..918ed137
--- a/basic_plugins/init_plugin_config/init_none_plugin_count_manager.py
+++ b/basic_plugins/init_plugin_config/init_none_plugin_count_manager.py
@@ -1,45 +1,45 @@
-from utils.manager import (
- none_plugin_count_manager,
- plugins2count_manager,
- plugins2cd_manager,
- plugins2settings_manager,
- plugins2block_manager,
- plugins_manager,
- resources_manager
-)
-from services.log import logger
-from utils.utils import get_matchers
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-def init_none_plugin_count_manager():
- """
- 清除已删除插件数据
- """
- modules = [x.module for x in get_matchers()]
- for module in none_plugin_count_manager.keys():
- if module not in modules:
- none_plugin_count_manager.add_count(module)
- else:
- none_plugin_count_manager.reset(module)
- if none_plugin_count_manager.check(module):
- try:
- plugin_name = plugins_manager.get(module)["plugin_name"]
- except (AttributeError, KeyError):
- plugin_name = ""
- try:
- plugins2settings_manager.delete(module)
- plugins2count_manager.delete(module)
- plugins2cd_manager.delete(module)
- plugins2block_manager.delete(module)
- plugins_manager.delete(module)
- resources_manager.remove_resource(module)
- logger.info(f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据...")
- except Exception as e:
- logger.error(
- f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据失败...{type(e)}:{e}"
- )
+from utils.manager import (
+ none_plugin_count_manager,
+ plugins2count_manager,
+ plugins2cd_manager,
+ plugins2settings_manager,
+ plugins2block_manager,
+ plugins_manager,
+ resources_manager
+)
+from services.log import logger
+from utils.utils import get_matchers
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+def init_none_plugin_count_manager():
+ """
+ 清除已删除插件数据
+ """
+ modules = [x.module for x in get_matchers()]
+ for module in none_plugin_count_manager.keys():
+ if module not in modules:
+ none_plugin_count_manager.add_count(module)
+ else:
+ none_plugin_count_manager.reset(module)
+ if none_plugin_count_manager.check(module):
+ try:
+ plugin_name = plugins_manager.get(module)["plugin_name"]
+ except (AttributeError, KeyError):
+ plugin_name = ""
+ try:
+ plugins2settings_manager.delete(module)
+ plugins2count_manager.delete(module)
+ plugins2cd_manager.delete(module)
+ plugins2block_manager.delete(module)
+ plugins_manager.delete(module)
+ resources_manager.remove_resource(module)
+ logger.info(f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据...")
+ except Exception as e:
+ logger.error(
+ f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据失败...{type(e)}:{e}"
+ )
diff --git a/basic_plugins/init_plugin_config/init_plugins_config.py b/basic_plugins/init_plugin_config/init_plugins_config.py
old mode 100644
new mode 100755
index addd8602..c4346075
--- a/basic_plugins/init_plugin_config/init_plugins_config.py
+++ b/basic_plugins/init_plugin_config/init_plugins_config.py
@@ -1,147 +1,147 @@
-from pathlib import Path
-from ruamel.yaml import round_trip_load, round_trip_dump, YAML
-from utils.manager import admin_manager, plugins_manager
-from configs.config import Config
-from services.log import logger
-from utils.utils import get_matchers
-from ruamel import yaml
-import nonebot
-
-
-_yaml = YAML(typ="safe")
-
-
-def init_plugins_config(data_path):
- """
- 初始化插件数据配置
- """
- plugins2config_file = Path(data_path) / "configs" / "plugins2config.yaml"
- plugins2config_file.parent.mkdir(parents=True, exist_ok=True)
- _data = {}
- if plugins2config_file.exists():
- _data = _yaml.load(open(plugins2config_file, "r", encoding="utf8"))
- _matchers = get_matchers()
- for matcher in _matchers:
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- except AttributeError:
- continue
- try:
- plugin_version = _module.__getattribute__("__plugin_version__")
- except AttributeError:
- plugin_version = None
- try:
- plugin_configs = _module.__getattribute__("__plugin_configs__")
- except AttributeError:
- continue
- # 插件配置版本更新或为Version为None或不在存储配置内
- if (
- plugin_version is None
- or (
- _data.get(matcher.module)
- and _data[matcher.module].keys() != plugin_configs.keys()
- )
- or plugin_version > plugins_manager.get(matcher.module)["version"]
- or matcher.module not in _data.keys()
- ):
- for key in plugin_configs:
- if isinstance(plugin_configs[key], dict):
- Config.add_plugin_config(
- matcher.module,
- key,
- plugin_configs[key].get("value"),
- help_=plugin_configs[key].get("help"),
- default_value=plugin_configs[key].get("default_value"),
- _override=True,
- )
- else:
- Config.add_plugin_config(matcher.module, key, plugin_configs[key])
- else:
- plugin_configs = _data[matcher.module]
- for key in plugin_configs:
- Config.add_plugin_config(
- matcher.module,
- key,
- plugin_configs[key]["value"],
- help_=plugin_configs[key]["help"],
- default_value=plugin_configs[key]["default_value"],
- _override=True,
- )
- if not Config.is_empty():
- Config.save()
- _data = round_trip_load(open(plugins2config_file, encoding="utf8"))
- for plugin in _data.keys():
- try:
- plugin_name = plugins_manager.get(plugin)["plugin_name"]
- except (AttributeError, TypeError):
- plugin_name = plugin
- _data[plugin].yaml_set_start_comment(plugin_name, indent=2)
- # 初始化未设置的管理员权限等级
- for k, v in Config.get_admin_level_data():
- admin_manager.set_admin_level(k, v)
- # 存完插件基本设置
- with open(plugins2config_file, "w", encoding="utf8") as wf:
- round_trip_dump(
- _data, wf, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True
- )
- # 再开始读取用户配置
- user_config_file = Path() / "configs" / "config.yaml"
- _data = {}
- _tmp_data = {}
- if user_config_file.exists():
- with open(user_config_file, "r", encoding="utf8") as f:
- _data = _yaml.load(f)
- for plugin in Config.keys():
- _tmp_data[plugin] = {}
- for k in Config[plugin].keys():
- if _data.get(plugin) and k in _data[plugin].keys():
- Config.set_config(plugin, k, _data[plugin][k])
- _tmp_data[plugin][k] = Config.get_config(plugin, k)
- Config.save()
- temp_file = Path() / "configs" / "temp_config.yaml"
- try:
- with open(temp_file, "w", encoding="utf8") as wf:
- yaml.dump(
- _tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True
- )
- with open(temp_file, "r", encoding="utf8") as rf:
- _data = round_trip_load(rf)
- # 添加注释
- for plugin in _data.keys():
- rst = ""
- plugin_name = None
- try:
- plugin_data = Config.get(plugin)
- for x in list(Config.get(plugin).keys()):
- try:
- _x = plugin_data[x].get("name")
- if _x:
- plugin_name = _x
- except AttributeError:
- pass
- except (KeyError, AttributeError):
- plugin_name = None
- if not plugin_name:
- try:
- plugin_name = plugins_manager.get(plugin)["plugin_name"]
- except (AttributeError, TypeError):
- plugin_name = plugin
- plugin_name = (
- plugin_name.replace("[Hidden]", "")
- .replace("[Superuser]", "")
- .replace("[Admin]", "")
- .strip()
- )
- rst += plugin_name + "\n"
- for k in _data[plugin].keys():
- rst += f'{k}: {Config[plugin][k]["help"]}' + "\n"
- _data[plugin].yaml_set_start_comment(rst[:-1], indent=2)
- with open(Path() / "configs" / "config.yaml", "w", encoding="utf8") as wf:
- round_trip_dump(
- _data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True
- )
- except Exception as e:
- logger.error(f"生成简易配置注释错误 {type(e)}:{e}")
- if temp_file.exists():
- temp_file.unlink()
+from pathlib import Path
+from ruamel.yaml import round_trip_load, round_trip_dump, YAML
+from utils.manager import admin_manager, plugins_manager
+from configs.config import Config
+from services.log import logger
+from utils.utils import get_matchers
+from ruamel import yaml
+import nonebot
+
+
+_yaml = YAML(typ="safe")
+
+
+def init_plugins_config(data_path):
+ """
+ 初始化插件数据配置
+ """
+ plugins2config_file = Path(data_path) / "configs" / "plugins2config.yaml"
+ plugins2config_file.parent.mkdir(parents=True, exist_ok=True)
+ _data = {}
+ if plugins2config_file.exists():
+ _data = _yaml.load(open(plugins2config_file, "r", encoding="utf8"))
+ _matchers = get_matchers()
+ for matcher in _matchers:
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ except AttributeError:
+ continue
+ try:
+ plugin_version = _module.__getattribute__("__plugin_version__")
+ except AttributeError:
+ plugin_version = None
+ try:
+ plugin_configs = _module.__getattribute__("__plugin_configs__")
+ except AttributeError:
+ continue
+ # 插件配置版本更新或为Version为None或不在存储配置内
+ if (
+ plugin_version is None
+ or (
+ _data.get(matcher.module)
+ and _data[matcher.module].keys() != plugin_configs.keys()
+ )
+ or plugin_version > plugins_manager.get(matcher.module)["version"]
+ or matcher.module not in _data.keys()
+ ):
+ for key in plugin_configs:
+ if isinstance(plugin_configs[key], dict):
+ Config.add_plugin_config(
+ matcher.module,
+ key,
+ plugin_configs[key].get("value"),
+ help_=plugin_configs[key].get("help"),
+ default_value=plugin_configs[key].get("default_value"),
+ _override=True,
+ )
+ else:
+ Config.add_plugin_config(matcher.module, key, plugin_configs[key])
+ else:
+ plugin_configs = _data[matcher.module]
+ for key in plugin_configs:
+ Config.add_plugin_config(
+ matcher.module,
+ key,
+ plugin_configs[key]["value"],
+ help_=plugin_configs[key]["help"],
+ default_value=plugin_configs[key]["default_value"],
+ _override=True,
+ )
+ if not Config.is_empty():
+ Config.save()
+ _data = round_trip_load(open(plugins2config_file, encoding="utf8"))
+ for plugin in _data.keys():
+ try:
+ plugin_name = plugins_manager.get(plugin)["plugin_name"]
+ except (AttributeError, TypeError):
+ plugin_name = plugin
+ _data[plugin].yaml_set_start_comment(plugin_name, indent=2)
+ # 初始化未设置的管理员权限等级
+ for k, v in Config.get_admin_level_data():
+ admin_manager.set_admin_level(k, v)
+ # 存完插件基本设置
+ with open(plugins2config_file, "w", encoding="utf8") as wf:
+ round_trip_dump(
+ _data, wf, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True
+ )
+ # 再开始读取用户配置
+ user_config_file = Path() / "configs" / "config.yaml"
+ _data = {}
+ _tmp_data = {}
+ if user_config_file.exists():
+ with open(user_config_file, "r", encoding="utf8") as f:
+ _data = _yaml.load(f)
+ for plugin in Config.keys():
+ _tmp_data[plugin] = {}
+ for k in Config[plugin].keys():
+ if _data.get(plugin) and k in _data[plugin].keys():
+ Config.set_config(plugin, k, _data[plugin][k])
+ _tmp_data[plugin][k] = Config.get_config(plugin, k)
+ Config.save()
+ temp_file = Path() / "configs" / "temp_config.yaml"
+ try:
+ with open(temp_file, "w", encoding="utf8") as wf:
+ yaml.dump(
+ _tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True
+ )
+ with open(temp_file, "r", encoding="utf8") as rf:
+ _data = round_trip_load(rf)
+ # 添加注释
+ for plugin in _data.keys():
+ rst = ""
+ plugin_name = None
+ try:
+ plugin_data = Config.get(plugin)
+ for x in list(Config.get(plugin).keys()):
+ try:
+ _x = plugin_data[x].get("name")
+ if _x:
+ plugin_name = _x
+ except AttributeError:
+ pass
+ except (KeyError, AttributeError):
+ plugin_name = None
+ if not plugin_name:
+ try:
+ plugin_name = plugins_manager.get(plugin)["plugin_name"]
+ except (AttributeError, TypeError):
+ plugin_name = plugin
+ plugin_name = (
+ plugin_name.replace("[Hidden]", "")
+ .replace("[Superuser]", "")
+ .replace("[Admin]", "")
+ .strip()
+ )
+ rst += plugin_name + "\n"
+ for k in _data[plugin].keys():
+ rst += f'{k}: {Config[plugin][k]["help"]}' + "\n"
+ _data[plugin].yaml_set_start_comment(rst[:-1], indent=2)
+ with open(Path() / "configs" / "config.yaml", "w", encoding="utf8") as wf:
+ round_trip_dump(
+ _data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True
+ )
+ except Exception as e:
+ logger.error(f"生成简易配置注释错误 {type(e)}:{e}")
+ if temp_file.exists():
+ temp_file.unlink()
diff --git a/basic_plugins/init_plugin_config/init_plugins_data.py b/basic_plugins/init_plugin_config/init_plugins_data.py
old mode 100644
new mode 100755
index e90d5238..ca17eaa0
--- a/basic_plugins/init_plugin_config/init_plugins_data.py
+++ b/basic_plugins/init_plugin_config/init_plugins_data.py
@@ -1,82 +1,82 @@
-from pathlib import Path
-from ruamel.yaml import YAML
-from utils.manager import plugins_manager
-from utils.utils import get_matchers
-import nonebot
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-_yaml = YAML(typ="safe")
-
-
-def init_plugins_data(data_path):
- """
- 初始化插件数据信息
- """
- plugin2data_file = Path(data_path) / "manager" / "plugin_manager.json"
- plugin2data_file.parent.mkdir(parents=True, exist_ok=True)
- _data = {}
- if plugin2data_file.exists():
- _data = json.load(open(plugin2data_file, "r", encoding="utf8"))
- _matchers = get_matchers()
- for matcher in _matchers:
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- except AttributeError:
- if matcher.module not in _data.keys():
- plugins_manager.add_plugin_data(
- matcher.module, matcher.module, error=True
- )
- else:
- plugins_manager.set_module_data(matcher.module, "error", True)
- plugin_data = plugins_manager.get(matcher.module)
- if plugin_data:
- plugins_manager.set_module_data(
- matcher.module, "version", plugin_data.get("version")
- )
- else:
- try:
- plugin_version = _module.__getattribute__("__plugin_version__")
- except AttributeError:
- plugin_version = None
- try:
- plugin_name = _module.__getattribute__("__zx_plugin_name__")
- except AttributeError:
- plugin_name = matcher.module
- try:
- plugin_author = _module.__getattribute__("__plugin_author__")
- except AttributeError:
- plugin_author = None
- if matcher.module in plugins_manager.keys():
- plugins_manager.set_module_data(matcher.module, "error", False)
- if matcher.module not in plugins_manager.keys():
- plugins_manager.add_plugin_data(
- matcher.module,
- plugin_name=plugin_name,
- author=plugin_author,
- version=plugin_version,
- )
- elif plugins_manager[matcher.module]["version"] is None or (
- plugin_version is not None
- and plugin_version > plugins_manager[matcher.module]["version"]
- ):
- plugins_manager.set_module_data(
- matcher.module, "plugin_name", plugin_name
- )
- plugins_manager.set_module_data(matcher.module, "author", plugin_author)
- plugins_manager.set_module_data(
- matcher.module, "version", plugin_version
- )
- if matcher.module in _data.keys():
- plugins_manager.set_module_data(
- matcher.module, "error", _data[matcher.module]["error"]
- )
- plugins_manager.set_module_data(
- matcher.module, "plugin_name", _data[matcher.module]["plugin_name"]
- )
- plugins_manager.save()
+from pathlib import Path
+from ruamel.yaml import YAML
+from utils.manager import plugins_manager
+from utils.utils import get_matchers
+import nonebot
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+_yaml = YAML(typ="safe")
+
+
+def init_plugins_data(data_path):
+ """
+ 初始化插件数据信息
+ """
+ plugin2data_file = Path(data_path) / "manager" / "plugin_manager.json"
+ plugin2data_file.parent.mkdir(parents=True, exist_ok=True)
+ _data = {}
+ if plugin2data_file.exists():
+ _data = json.load(open(plugin2data_file, "r", encoding="utf8"))
+ _matchers = get_matchers()
+ for matcher in _matchers:
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ except AttributeError:
+ if matcher.module not in _data.keys():
+ plugins_manager.add_plugin_data(
+ matcher.module, matcher.module, error=True
+ )
+ else:
+ plugins_manager.set_module_data(matcher.module, "error", True)
+ plugin_data = plugins_manager.get(matcher.module)
+ if plugin_data:
+ plugins_manager.set_module_data(
+ matcher.module, "version", plugin_data.get("version")
+ )
+ else:
+ try:
+ plugin_version = _module.__getattribute__("__plugin_version__")
+ except AttributeError:
+ plugin_version = None
+ try:
+ plugin_name = _module.__getattribute__("__zx_plugin_name__")
+ except AttributeError:
+ plugin_name = matcher.module
+ try:
+ plugin_author = _module.__getattribute__("__plugin_author__")
+ except AttributeError:
+ plugin_author = None
+ if matcher.module in plugins_manager.keys():
+ plugins_manager.set_module_data(matcher.module, "error", False)
+ if matcher.module not in plugins_manager.keys():
+ plugins_manager.add_plugin_data(
+ matcher.module,
+ plugin_name=plugin_name,
+ author=plugin_author,
+ version=plugin_version,
+ )
+ elif plugins_manager[matcher.module]["version"] is None or (
+ plugin_version is not None
+ and plugin_version > plugins_manager[matcher.module]["version"]
+ ):
+ plugins_manager.set_module_data(
+ matcher.module, "plugin_name", plugin_name
+ )
+ plugins_manager.set_module_data(matcher.module, "author", plugin_author)
+ plugins_manager.set_module_data(
+ matcher.module, "version", plugin_version
+ )
+ if matcher.module in _data.keys():
+ plugins_manager.set_module_data(
+ matcher.module, "error", _data[matcher.module]["error"]
+ )
+ plugins_manager.set_module_data(
+ matcher.module, "plugin_name", _data[matcher.module]["plugin_name"]
+ )
+ plugins_manager.save()
diff --git a/basic_plugins/init_plugin_config/init_plugins_limit.py b/basic_plugins/init_plugin_config/init_plugins_limit.py
old mode 100644
new mode 100755
index 459f747c..f507b4c5
--- a/basic_plugins/init_plugin_config/init_plugins_limit.py
+++ b/basic_plugins/init_plugin_config/init_plugins_limit.py
@@ -1,157 +1,157 @@
-from pathlib import Path
-from ruamel.yaml import round_trip_load, round_trip_dump, YAML
-from utils.manager import (
- plugins2cd_manager,
- plugins2block_manager,
- plugins2count_manager,
-)
-from utils.utils import get_matchers
-from ruamel import yaml
-import nonebot
-
-
-_yaml = YAML(typ="safe")
-
-
-def init_plugins_cd_limit(data_path):
- """
- 加载 cd 限制
- """
- plugins2cd_file = Path(data_path) / "configs" / "plugins2cd.yaml"
- plugins2cd_file.parent.mkdir(exist_ok=True, parents=True)
- _data = {}
- _matchers = get_matchers()
- for matcher in _matchers:
- if not plugins2cd_manager.get_plugin_cd_data(matcher.module):
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- plugin_cd_limit = _module.__getattribute__("__plugin_cd_limit__")
- plugins2cd_manager.add_cd_limit(
- matcher.module, data_dict=plugin_cd_limit
- )
- except AttributeError:
- pass
- if not plugins2cd_manager.keys():
- plugins2cd_manager.add_cd_limit(
- "这是一个示例"
- )
- _tmp_data = {"PluginCdLimit": plugins2cd_manager.get_data()}
- with open(plugins2cd_file, "w", encoding="utf8") as wf:
- yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- _data = round_trip_load(open(plugins2cd_file, encoding="utf8"))
- _data["PluginCdLimit"].yaml_set_start_comment(
- """# 需要cd的功能
-# 自定义的功能需要cd也可以在此配置
-# key:模块名称
-# cd:cd 时长(秒)
-# status:此限制的开关状态
-# check_type:'private'/'group'/'all',限制私聊/群聊/全部
-# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
-# 示例:'user':用户N秒内触发1次,'group':群N秒内触发1次
-# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
-# rst 为 "" 或 None 时则不回复
-# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
-# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
-# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
- indent=2,
- )
- with open(plugins2cd_file, "w", encoding="utf8") as wf:
- round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- plugins2cd_manager.reload_cd_limit()
-
-
-def init_plugins_block_limit(data_path):
- """
- 加载阻塞限制
- """
- plugins2block_file = Path(data_path) / "configs" / "plugins2block.yaml"
- plugins2block_file.parent.mkdir(exist_ok=True, parents=True)
- _data = {}
- _matchers = get_matchers()
- for matcher in _matchers:
- if not plugins2block_manager.get_plugin_block_data(matcher.module):
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- plugin_block_limit = _module.__getattribute__("__plugin_block_limit__")
- plugins2block_manager.add_block_limit(
- matcher.module, data_dict=plugin_block_limit
- )
- except AttributeError:
- pass
- if not plugins2block_manager.keys():
- plugins2block_manager.add_block_limit(
- "这是一个示例"
- )
- _tmp_data = {"PluginBlockLimit": plugins2block_manager.get_data()}
- with open(plugins2block_file, "w", encoding="utf8") as wf:
- yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- _data = round_trip_load(open(plugins2block_file, encoding="utf8"))
- _data["PluginBlockLimit"].yaml_set_start_comment(
- """# 用户调用阻塞
-# 即 当用户调用此功能还未结束时
-# 用发送消息阻止用户重复调用此命令直到该命令结束
-# key:模块名称
-# status:此限制的开关状态
-# check_type:'private'/'group'/'all',限制私聊/群聊/全部
-# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
-# 示例:'user':阻塞用户,'group':阻塞群聊
-# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
-# rst 为 "" 或 None 时则不回复
-# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
-# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
-# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
- indent=2,
- )
- with open(plugins2block_file, "w", encoding="utf8") as wf:
- round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- plugins2block_manager.reload_block_limit()
-
-
-def init_plugins_count_limit(data_path):
- """
- 加载次数限制
- """
- plugins2count_file = Path(data_path) / "configs" / "plugins2count.yaml"
- plugins2count_file.parent.mkdir(exist_ok=True, parents=True)
- _data = {}
- _matchers = get_matchers()
- for matcher in _matchers:
- if not plugins2count_manager.get_plugin_count_data(matcher.module):
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- plugin_count_limit = _module.__getattribute__("__plugin_count_limit__")
- plugins2count_manager.add_count_limit(
- matcher.module, data_dict=plugin_count_limit
- )
- except AttributeError:
- pass
- if not plugins2count_manager.keys():
- plugins2count_manager.add_count_limit(
- "这是一个示例"
- )
- _tmp_data = {"PluginCountLimit": plugins2count_manager.get_data()}
- with open(plugins2count_file, "w", encoding="utf8") as wf:
- yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- _data = round_trip_load(open(plugins2count_file, encoding="utf8"))
- _data["PluginCountLimit"].yaml_set_start_comment(
- """# 命令每日次数限制
-# 即 用户/群聊 每日可调用命令的次数 [数据内存存储,重启将会重置]
-# 每日调用直到 00:00 刷新
-# key:模块名称
-# max_count: 每日调用上限
-# status:此限制的开关状态
-# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
-# 示例:'user':用户上限,'group':群聊上限
-# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
-# rst 为 "" 或 None 时则不回复
-# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
-# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
-# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
- indent=2,
- )
- with open(plugins2count_file, "w", encoding="utf8") as wf:
- round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- plugins2count_manager.reload_count_limit()
+from pathlib import Path
+from ruamel.yaml import round_trip_load, round_trip_dump, YAML
+from utils.manager import (
+ plugins2cd_manager,
+ plugins2block_manager,
+ plugins2count_manager,
+)
+from utils.utils import get_matchers
+from ruamel import yaml
+import nonebot
+
+
+_yaml = YAML(typ="safe")
+
+
+def init_plugins_cd_limit(data_path):
+ """
+ 加载 cd 限制
+ """
+ plugins2cd_file = Path(data_path) / "configs" / "plugins2cd.yaml"
+ plugins2cd_file.parent.mkdir(exist_ok=True, parents=True)
+ _data = {}
+ _matchers = get_matchers()
+ for matcher in _matchers:
+ if not plugins2cd_manager.get_plugin_cd_data(matcher.module):
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ plugin_cd_limit = _module.__getattribute__("__plugin_cd_limit__")
+ plugins2cd_manager.add_cd_limit(
+ matcher.module, data_dict=plugin_cd_limit
+ )
+ except AttributeError:
+ pass
+ if not plugins2cd_manager.keys():
+ plugins2cd_manager.add_cd_limit(
+ "这是一个示例"
+ )
+ _tmp_data = {"PluginCdLimit": plugins2cd_manager.get_data()}
+ with open(plugins2cd_file, "w", encoding="utf8") as wf:
+ yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ _data = round_trip_load(open(plugins2cd_file, encoding="utf8"))
+ _data["PluginCdLimit"].yaml_set_start_comment(
+ """# 需要cd的功能
+# 自定义的功能需要cd也可以在此配置
+# key:模块名称
+# cd:cd 时长(秒)
+# status:此限制的开关状态
+# check_type:'private'/'group'/'all',限制私聊/群聊/全部
+# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
+# 示例:'user':用户N秒内触发1次,'group':群N秒内触发1次
+# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
+# rst 为 "" 或 None 时则不回复
+# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
+# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
+# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
+ indent=2,
+ )
+ with open(plugins2cd_file, "w", encoding="utf8") as wf:
+ round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ plugins2cd_manager.reload_cd_limit()
+
+
+def init_plugins_block_limit(data_path):
+ """
+ 加载阻塞限制
+ """
+ plugins2block_file = Path(data_path) / "configs" / "plugins2block.yaml"
+ plugins2block_file.parent.mkdir(exist_ok=True, parents=True)
+ _data = {}
+ _matchers = get_matchers()
+ for matcher in _matchers:
+ if not plugins2block_manager.get_plugin_block_data(matcher.module):
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ plugin_block_limit = _module.__getattribute__("__plugin_block_limit__")
+ plugins2block_manager.add_block_limit(
+ matcher.module, data_dict=plugin_block_limit
+ )
+ except AttributeError:
+ pass
+ if not plugins2block_manager.keys():
+ plugins2block_manager.add_block_limit(
+ "这是一个示例"
+ )
+ _tmp_data = {"PluginBlockLimit": plugins2block_manager.get_data()}
+ with open(plugins2block_file, "w", encoding="utf8") as wf:
+ yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ _data = round_trip_load(open(plugins2block_file, encoding="utf8"))
+ _data["PluginBlockLimit"].yaml_set_start_comment(
+ """# 用户调用阻塞
+# 即 当用户调用此功能还未结束时
+# 用发送消息阻止用户重复调用此命令直到该命令结束
+# key:模块名称
+# status:此限制的开关状态
+# check_type:'private'/'group'/'all',限制私聊/群聊/全部
+# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
+# 示例:'user':阻塞用户,'group':阻塞群聊
+# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
+# rst 为 "" 或 None 时则不回复
+# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
+# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
+# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
+ indent=2,
+ )
+ with open(plugins2block_file, "w", encoding="utf8") as wf:
+ round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ plugins2block_manager.reload_block_limit()
+
+
+def init_plugins_count_limit(data_path):
+ """
+ 加载次数限制
+ """
+ plugins2count_file = Path(data_path) / "configs" / "plugins2count.yaml"
+ plugins2count_file.parent.mkdir(exist_ok=True, parents=True)
+ _data = {}
+ _matchers = get_matchers()
+ for matcher in _matchers:
+ if not plugins2count_manager.get_plugin_count_data(matcher.module):
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ plugin_count_limit = _module.__getattribute__("__plugin_count_limit__")
+ plugins2count_manager.add_count_limit(
+ matcher.module, data_dict=plugin_count_limit
+ )
+ except AttributeError:
+ pass
+ if not plugins2count_manager.keys():
+ plugins2count_manager.add_count_limit(
+ "这是一个示例"
+ )
+ _tmp_data = {"PluginCountLimit": plugins2count_manager.get_data()}
+ with open(plugins2count_file, "w", encoding="utf8") as wf:
+ yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ _data = round_trip_load(open(plugins2count_file, encoding="utf8"))
+ _data["PluginCountLimit"].yaml_set_start_comment(
+ """# 命令每日次数限制
+# 即 用户/群聊 每日可调用命令的次数 [数据内存存储,重启将会重置]
+# 每日调用直到 00:00 刷新
+# key:模块名称
+# max_count: 每日调用上限
+# status:此限制的开关状态
+# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
+# 示例:'user':用户上限,'group':群聊上限
+# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
+# rst 为 "" 或 None 时则不回复
+# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
+# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
+# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
+ indent=2,
+ )
+ with open(plugins2count_file, "w", encoding="utf8") as wf:
+ round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ plugins2count_manager.reload_count_limit()
diff --git a/basic_plugins/init_plugin_config/init_plugins_resources.py b/basic_plugins/init_plugin_config/init_plugins_resources.py
old mode 100644
new mode 100755
index 36e2f47b..1fdfa4b3
--- a/basic_plugins/init_plugin_config/init_plugins_resources.py
+++ b/basic_plugins/init_plugin_config/init_plugins_resources.py
@@ -1,43 +1,43 @@
-from utils.manager import resources_manager
-from utils.utils import get_matchers
-from services.log import logger
-from pathlib import Path
-import nonebot
-
-
-def init_plugins_resources():
- """
- 资源文件路径的移动
- """
- _tmp = []
- for matcher in get_matchers():
- if matcher.module not in _tmp:
- _tmp.append(matcher.module)
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- except AttributeError:
- logger.warning(f"插件 {matcher.module} 加载失败...,资源控制未加载...")
- else:
- try:
- resources = _module.__getattribute__("__plugin_resources__")
- except AttributeError:
- pass
- else:
- path = Path(_module.__getattribute__("__file__")).parent
- for resource in resources.keys():
- resources_manager.add_resource(matcher.module, (path / resource).absolute(), resources[resource])
- resources_manager.save()
- resources_manager.start_move()
-
-
-
-
-
-
-
-
-
-
-
-
+from utils.manager import resources_manager
+from utils.utils import get_matchers
+from services.log import logger
+from pathlib import Path
+import nonebot
+
+
+def init_plugins_resources():
+ """
+ 资源文件路径的移动
+ """
+ _tmp = []
+ for matcher in get_matchers():
+ if matcher.module not in _tmp:
+ _tmp.append(matcher.module)
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ except AttributeError:
+ logger.warning(f"插件 {matcher.module} 加载失败...,资源控制未加载...")
+ else:
+ try:
+ resources = _module.__getattribute__("__plugin_resources__")
+ except AttributeError:
+ pass
+ else:
+ path = Path(_module.__getattribute__("__file__")).parent
+ for resource in resources.keys():
+ resources_manager.add_resource(matcher.module, (path / resource).absolute(), resources[resource])
+ resources_manager.save()
+ resources_manager.start_move()
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/basic_plugins/init_plugin_config/init_plugins_settings.py b/basic_plugins/init_plugin_config/init_plugins_settings.py
old mode 100644
new mode 100755
index c1ec6c11..fff027d9
--- a/basic_plugins/init_plugin_config/init_plugins_settings.py
+++ b/basic_plugins/init_plugin_config/init_plugins_settings.py
@@ -1,130 +1,126 @@
-from pathlib import Path
-from ruamel.yaml import round_trip_load, round_trip_dump, YAML
-from utils.manager import plugins2settings_manager, admin_manager
-from services.log import logger
-from utils.utils import get_matchers
-from ruamel import yaml
-import nonebot
-
-
-_yaml = YAML(typ="safe")
-
-
-def init_plugins_settings(data_path: str):
- """
- 初始化插件设置,从插件中获取 __zx_plugin_name__,__plugin_cmd__,__plugin_settings__
- """
- plugins2settings_file = Path(data_path) / "configs" / "plugins2settings.yaml"
- plugins2settings_file.parent.mkdir(exist_ok=True, parents=True)
- _matchers = get_matchers()
- _data = {}
- if plugins2settings_file.exists():
- with open(plugins2settings_file, "r", encoding="utf8") as f:
- _data = _yaml.load(f)
- _data = _data["PluginSettings"] if _data else {}
- _tmp_module = {}
- _tmp = []
- for matcher in _matchers:
- if matcher.module in _data.keys():
- plugins2settings_manager.add_plugin_settings(
- matcher.module,
- plugin_type=_data[matcher.module]["plugin_type"],
- data_dict=_data[matcher.module],
- )
- if _data[matcher.module]["cmd"]:
- _tmp_module[matcher.module] = _data[matcher.module]["cmd"][0]
- else:
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- except AttributeError:
- logger.warning(f"插件 {matcher.module} 加载失败...,插件控制未加载.")
- else:
- try:
- plugin_name = _module.__getattribute__("__zx_plugin_name__")
- if "[admin]" in plugin_name.lower():
- try:
- admin_settings = _module.__getattribute__(
- "__plugin_settings__"
- )
- level = admin_settings["admin_level"]
- cmd = admin_settings.get("cmd")
- except (AttributeError, KeyError):
- level = 5
- cmd = None
- if not level:
- level = 5
- admin_manager.add_admin_plugin_settings(
- matcher.module, cmd, level
- )
- if (
- "[hidden]" in plugin_name.lower()
- or "[admin]" in plugin_name.lower()
- or "[superuser]" in plugin_name.lower()
- or matcher.module in plugins2settings_manager.keys()
- ):
- continue
- except AttributeError:
- if matcher.module not in _tmp:
- logger.warning(
- f"获取插件 {matcher.module} __zx_plugin_name__ 失败...,插件控制未加载."
- )
- else:
- try:
- _tmp_module[matcher.module] = plugin_name
- plugin_settings = _module.__getattribute__(
- "__plugin_settings__"
- )
- if (
- plugin_settings["cmd"]
- and plugin_name not in plugin_settings["cmd"]
- ):
- plugin_settings["cmd"].append(plugin_name)
- if plugins2settings_manager.get(
- matcher.module
- ) and plugins2settings_manager[matcher.module].get(
- "plugin_type"
- ):
- plugin_type = tuple(
- plugins2settings_manager.get_plugin_data(
- matcher.module
- )["plugin_type"]
- )
- else:
- try:
- plugin_type = _module.__getattribute__(
- "__plugin_type__"
- )
- except AttributeError:
- plugin_type = ("normal",)
- if plugin_settings and matcher.module:
- plugins2settings_manager.add_plugin_settings(
- matcher.module,
- plugin_type=plugin_type,
- data_dict=plugin_settings,
- )
- except AttributeError:
- pass
- _tmp.append(matcher.module)
- _tmp_data = {"PluginSettings": plugins2settings_manager.get_data()}
- with open(plugins2settings_file, "w", encoding="utf8") as wf:
- yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- _data = round_trip_load(open(plugins2settings_file, encoding="utf8"))
- _data["PluginSettings"].yaml_set_start_comment(
- """# 模块与对应命令和对应群权限
-# 用于生成帮助图片 和 开关功能
-# key:模块名称
-# level:需要的群等级
-# default_status:加入群时功能的默认开关状态
-# limit_superuser: 功能状态是否限制超级用户
-# cmd: 关闭[cmd] 都会触发命令 关闭对应功能,cmd列表第一个词为统计的功能名称
-# plugin_type: 帮助类别 示例:('原神相关',) 或 ('原神相关', 1),1代表帮助命令列向排列,否则为横向排列""",
- indent=2,
- )
- for plugin in _data["PluginSettings"].keys():
- _data["PluginSettings"][plugin].yaml_set_start_comment(
- f"{plugin}:{_tmp_module[plugin]}", indent=2
- )
- with open(plugins2settings_file, "w", encoding="utf8") as wf:
- round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
- logger.info(f"已成功加载 {len(plugins2settings_manager.get_data())} 个非限制插件.")
+from pathlib import Path
+from ruamel.yaml import round_trip_load, round_trip_dump, YAML
+from utils.manager import plugins2settings_manager, admin_manager
+from services.log import logger
+from utils.utils import get_matchers
+from ruamel import yaml
+import nonebot
+
+
+_yaml = YAML(typ="safe")
+
+
+def init_plugins_settings(data_path: str):
+ """
+ 初始化插件设置,从插件中获取 __zx_plugin_name__,__plugin_cmd__,__plugin_settings__
+ """
+ plugins2settings_file = Path(data_path) / "configs" / "plugins2settings.yaml"
+ plugins2settings_file.parent.mkdir(exist_ok=True, parents=True)
+ _matchers = get_matchers()
+ _tmp_module = {}
+ _tmp = []
+ for x in plugins2settings_manager.keys():
+ try:
+ _plugin = nonebot.plugin.get_plugin(x)
+ _module = _plugin.module
+ plugin_name = _module.__getattribute__("__zx_plugin_name__")
+ _tmp_module[x] = plugin_name
+ except (KeyError, AttributeError) as e:
+ logger.error(f"配置文件 模块:{x} 获取 plugin_name 失败...{e}")
+ _tmp_module[x] = ""
+ for matcher in _matchers:
+ if matcher.module not in plugins2settings_manager.keys():
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ except AttributeError:
+ logger.warning(f"插件 {matcher.module} 加载失败...,插件控制未加载.")
+ else:
+ try:
+ plugin_name = _module.__getattribute__("__zx_plugin_name__")
+ if "[admin]" in plugin_name.lower():
+ try:
+ admin_settings = _module.__getattribute__(
+ "__plugin_settings__"
+ )
+ level = admin_settings["admin_level"]
+ cmd = admin_settings.get("cmd")
+ except (AttributeError, KeyError):
+ level = 5
+ cmd = None
+ if level is None:
+ level = 5
+ admin_manager.add_admin_plugin_settings(
+ matcher.module, cmd, level
+ )
+ if (
+ "[hidden]" in plugin_name.lower()
+ or "[admin]" in plugin_name.lower()
+ or "[superuser]" in plugin_name.lower()
+ or matcher.module in plugins2settings_manager.keys()
+ ):
+ continue
+ except AttributeError:
+ if matcher.module not in _tmp:
+ logger.warning(
+ f"获取插件 {matcher.module} __zx_plugin_name__ 失败...,插件控制未加载."
+ )
+ else:
+ try:
+ _tmp_module[matcher.module] = plugin_name
+ plugin_settings = _module.__getattribute__(
+ "__plugin_settings__"
+ )
+ if (
+ plugin_settings["cmd"] is not None
+ and plugin_name not in plugin_settings["cmd"]
+ ):
+ plugin_settings["cmd"].append(plugin_name)
+ if plugins2settings_manager.get(
+ matcher.module
+ ) and plugins2settings_manager[matcher.module].get(
+ "plugin_type"
+ ):
+ plugin_type = tuple(
+ plugins2settings_manager.get_plugin_data(
+ matcher.module
+ )["plugin_type"]
+ )
+ else:
+ try:
+ plugin_type = _module.__getattribute__(
+ "__plugin_type__"
+ )
+ except AttributeError:
+ plugin_type = ("normal",)
+ if plugin_settings and matcher.module:
+ plugins2settings_manager.add_plugin_settings(
+ matcher.module,
+ plugin_type=plugin_type,
+ data_dict=plugin_settings,
+ )
+ except AttributeError:
+ pass
+ _tmp.append(matcher.module)
+ _tmp_data = {"PluginSettings": plugins2settings_manager.get_data()}
+ with open(plugins2settings_file, "w", encoding="utf8") as wf:
+ yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ _data = round_trip_load(open(plugins2settings_file, encoding="utf8"))
+ _data["PluginSettings"].yaml_set_start_comment(
+ """# 模块与对应命令和对应群权限
+# 用于生成帮助图片 和 开关功能
+# key:模块名称
+# level:需要的群等级
+# default_status:加入群时功能的默认开关状态
+# limit_superuser: 功能状态是否限制超级用户
+# cmd: 关闭[cmd] 都会触发命令 关闭对应功能,cmd列表第一个词为统计的功能名称
+# plugin_type: 帮助类别 示例:('原神相关',) 或 ('原神相关', 1),1代表帮助命令列向排列,否则为横向排列""",
+ indent=2,
+ )
+ for plugin in _data["PluginSettings"].keys():
+ _data["PluginSettings"][plugin].yaml_set_start_comment(
+ f"{plugin}:{_tmp_module[plugin]}", indent=2
+ )
+ with open(plugins2settings_file, "w", encoding="utf8") as wf:
+ round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+ logger.info(f"已成功加载 {len(plugins2settings_manager.get_data())} 个非限制插件.")
diff --git a/basic_plugins/auto_invite/__init__.py b/basic_plugins/invite_manager/__init__.py
old mode 100644
new mode 100755
similarity index 94%
rename from basic_plugins/auto_invite/__init__.py
rename to basic_plugins/invite_manager/__init__.py
index d0d91701..857cac4a
--- a/basic_plugins/auto_invite/__init__.py
+++ b/basic_plugins/invite_manager/__init__.py
@@ -1,149 +1,149 @@
-from nonebot import on_request, on_message
-from nonebot.adapters.cqhttp import (
- Bot,
- FriendRequestEvent,
- GroupRequestEvent,
- MessageEvent,
-)
-from models.friend_user import FriendUser
-from datetime import datetime
-from configs.config import NICKNAME, Config
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from utils.manager import requests_manager
-from models.group_info import GroupInfo
-from utils.utils import scheduler
-import asyncio
-import time
-import re
-
-__zx_plugin_name__ = "好友群聊处理请求 [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_configs__ = {
- "AUTO_ADD_FRIEND": {"value": False, "help": "是否自动同意好友添加", "default_value": False}
-}
-
-friend_req = on_request(priority=5, block=True)
-group_req = on_request(priority=5, block=True)
-x = on_message(priority=9, block=False)
-
-exists_data = {"private": {}, "group": {}}
-
-
-@friend_req.handle()
-async def _(bot: Bot, event: FriendRequestEvent, state: dict):
- global exists_data
- if exists_data["private"].get(event.user_id):
- if time.time() - exists_data["private"][event.user_id] < 60 * 5:
- return
- exists_data["private"][event.user_id] = time.time()
- user = await bot.get_stranger_info(user_id=event.user_id)
- nickname = user["nickname"]
- sex = user["sex"]
- age = str(user["age"])
- comment = event.comment
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"*****一份好友申请*****\n"
- f"昵称:{nickname}({event.user_id})\n"
- f"自动同意:{'√' if Config.get_config('auto_invite', 'AUTO_ADD_FRIEND') else '×'}\n"
- f"日期:{str(datetime.now()).split('.')[0]}\n"
- f"备注:{event.comment}",
- )
- if Config.get_config("auto_invite", "AUTO_ADD_FRIEND"):
- await bot.set_friend_add_request(flag=event.flag, approve=True)
- await FriendUser.add_friend_info(user["user_id"], user["nickname"])
- else:
- requests_manager.add_request(
- event.user_id,
- "private",
- event.flag,
- nickname=nickname,
- sex=sex,
- age=age,
- comment=comment,
- )
-
-
-@group_req.handle()
-async def _(bot: Bot, event: GroupRequestEvent, state: dict):
- global exists_data
- if event.sub_type == "invite":
- if str(event.user_id) in bot.config.superusers:
- try:
- if await GroupInfo.get_group_info(event.group_id):
- await GroupInfo.set_group_flag(event.group_id, 1)
- else:
- group_info = await bot.get_group_info(group_id=event.group_id)
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1,
- )
- await bot.set_group_add_request(
- flag=event.flag, sub_type="invite", approve=True
- )
- except ActionFailed:
- pass
- else:
- user = await bot.get_stranger_info(user_id=event.user_id)
- sex = user["sex"]
- age = str(user["age"])
- if exists_data["group"].get(f"{event.user_id}:{event.group_id}"):
- if (
- time.time()
- - exists_data["group"][f"{event.user_id}:{event.group_id}"]
- < 60 * 5
- ):
- return
- exists_data["group"][f"{event.user_id}:{event.group_id}"] = time.time()
- nickname = await FriendUser.get_user_name(event.user_id)
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"*****一份入群申请*****\n"
- f"申请人:{nickname}({event.user_id})\n"
- f"群聊:{event.group_id}\n"
- f"邀请日期:{str(datetime.now()).split('.')[0]}",
- )
- await bot.send_private_msg(
- user_id=event.user_id,
- message=f"想要邀请我偷偷入群嘛~已经提醒{NICKNAME}的管理员大人了\n"
- "请确保已经群主或群管理沟通过!\n"
- "等待管理员处理吧!",
- )
- requests_manager.add_request(
- event.user_id,
- "group",
- event.flag,
- invite_group=event.group_id,
- nickname=nickname,
- sex=sex,
- age=age,
- )
-
-
-@x.handle()
-async def _(bot: Bot, event: MessageEvent, state: dict):
- await asyncio.sleep(0.1)
- r = re.search(r'groupcode="(.*?)"', str(event.get_message()))
- if r:
- group_id = int(r.group(1))
- else:
- return
- r = re.search(r'groupname="(.*?)"', str(event.get_message()))
- if r:
- group_name = r.group(1)
- else:
- group_name = "None"
- requests_manager.set_group_name(group_name, group_id)
-
-
-@scheduler.scheduled_job(
- "interval",
- minutes=5,
-)
-async def _():
- global exists_data
- exists_data = {"private": {}, "group": {}}
+from nonebot import on_request, on_message
+from nonebot.adapters.cqhttp import (
+ Bot,
+ FriendRequestEvent,
+ GroupRequestEvent,
+ MessageEvent,
+)
+from models.friend_user import FriendUser
+from datetime import datetime
+from configs.config import NICKNAME, Config
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from utils.manager import requests_manager
+from models.group_info import GroupInfo
+from utils.utils import scheduler
+import asyncio
+import time
+import re
+
+__zx_plugin_name__ = "好友群聊处理请求 [Hidden]"
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_configs__ = {
+ "AUTO_ADD_FRIEND": {"value": False, "help": "是否自动同意好友添加", "default_value": False}
+}
+
+friend_req = on_request(priority=5, block=True)
+group_req = on_request(priority=5, block=True)
+x = on_message(priority=9, block=False)
+
+exists_data = {"private": {}, "group": {}}
+
+
+@friend_req.handle()
+async def _(bot: Bot, event: FriendRequestEvent, state: dict):
+ global exists_data
+ if exists_data["private"].get(event.user_id):
+ if time.time() - exists_data["private"][event.user_id] < 60 * 5:
+ return
+ exists_data["private"][event.user_id] = time.time()
+ user = await bot.get_stranger_info(user_id=event.user_id)
+ nickname = user["nickname"]
+ sex = user["sex"]
+ age = str(user["age"])
+ comment = event.comment
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"*****一份好友申请*****\n"
+ f"昵称:{nickname}({event.user_id})\n"
+ f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
+ f"日期:{str(datetime.now()).split('.')[0]}\n"
+ f"备注:{event.comment}",
+ )
+ if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
+ await bot.set_friend_add_request(flag=event.flag, approve=True)
+ await FriendUser.add_friend_info(user["user_id"], user["nickname"])
+ else:
+ requests_manager.add_request(
+ event.user_id,
+ "private",
+ event.flag,
+ nickname=nickname,
+ sex=sex,
+ age=age,
+ comment=comment,
+ )
+
+
+@group_req.handle()
+async def _(bot: Bot, event: GroupRequestEvent, state: dict):
+ global exists_data
+ if event.sub_type == "invite":
+ if str(event.user_id) in bot.config.superusers:
+ try:
+ if await GroupInfo.get_group_info(event.group_id):
+ await GroupInfo.set_group_flag(event.group_id, 1)
+ else:
+ group_info = await bot.get_group_info(group_id=event.group_id)
+ await GroupInfo.add_group_info(
+ group_info["group_id"],
+ group_info["group_name"],
+ group_info["max_member_count"],
+ group_info["member_count"],
+ 1,
+ )
+ await bot.set_group_add_request(
+ flag=event.flag, sub_type="invite", approve=True
+ )
+ except ActionFailed:
+ pass
+ else:
+ user = await bot.get_stranger_info(user_id=event.user_id)
+ sex = user["sex"]
+ age = str(user["age"])
+ if exists_data["group"].get(f"{event.user_id}:{event.group_id}"):
+ if (
+ time.time()
+ - exists_data["group"][f"{event.user_id}:{event.group_id}"]
+ < 60 * 5
+ ):
+ return
+ exists_data["group"][f"{event.user_id}:{event.group_id}"] = time.time()
+ nickname = await FriendUser.get_user_name(event.user_id)
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"*****一份入群申请*****\n"
+ f"申请人:{nickname}({event.user_id})\n"
+ f"群聊:{event.group_id}\n"
+ f"邀请日期:{str(datetime.now()).split('.')[0]}",
+ )
+ await bot.send_private_msg(
+ user_id=event.user_id,
+ message=f"想要邀请我偷偷入群嘛~已经提醒{NICKNAME}的管理员大人了\n"
+ "请确保已经群主或群管理沟通过!\n"
+ "等待管理员处理吧!",
+ )
+ requests_manager.add_request(
+ event.user_id,
+ "group",
+ event.flag,
+ invite_group=event.group_id,
+ nickname=nickname,
+ sex=sex,
+ age=age,
+ )
+
+
+@x.handle()
+async def _(bot: Bot, event: MessageEvent, state: dict):
+ await asyncio.sleep(0.1)
+ r = re.search(r'groupcode="(.*?)"', str(event.get_message()))
+ if r:
+ group_id = int(r.group(1))
+ else:
+ return
+ r = re.search(r'groupname="(.*?)"', str(event.get_message()))
+ if r:
+ group_name = r.group(1)
+ else:
+ group_name = "None"
+ requests_manager.set_group_name(group_name, group_id)
+
+
+@scheduler.scheduled_job(
+ "interval",
+ minutes=5,
+)
+async def _():
+ global exists_data
+ exists_data = {"private": {}, "group": {}}
diff --git a/basic_plugins/nickname.py b/basic_plugins/nickname.py
old mode 100644
new mode 100755
index 75e497d4..f06018b8
--- a/basic_plugins/nickname.py
+++ b/basic_plugins/nickname.py
@@ -1,194 +1,194 @@
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent
-from nonebot.rule import to_me
-from utils.utils import get_message_text
-from models.group_member_info import GroupInfoUser
-from models.friend_user import FriendUser
-import random
-from models.ban_user import BanUser
-from services.log import logger
-from configs.config import NICKNAME
-
-
-__zx_plugin_name__ = "昵称系统"
-__plugin_usage__ = f"""
-usage:
- 个人昵称系统,群聊 与 私聊 昵称相互独立
- 指令:
- 以后叫我 [昵称]
- {NICKNAME}我是谁
-""".strip()
-__plugin_des__ = "区区昵称,才不想叫呢!"
-__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-nickname = on_command(
- "nickname",
- aliases={"以后叫我", "以后请叫我", "称呼我", "以后请称呼我", "以后称呼我", "叫我", "请叫我"},
- rule=to_me(),
- priority=5,
- block=True,
-)
-
-my_nickname = on_command(
- "my_name", aliases={"我叫什么", "我是谁", "我的名字"}, rule=to_me(), priority=5, block=True
-)
-
-
-cancel_nickname = on_command("取消昵称", rule=to_me(), priority=5, block=True)
-
-
-@nickname.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if not msg:
- await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
- if len(msg) > 10:
- await nickname.finish("昵称可不能超过10个字!", at_sender=True)
- if await GroupInfoUser.set_group_member_nickname(
- event.user_id, event.group_id, msg
- ):
- if len(msg) < 5:
- if random.random() < 0.5:
- msg = "~".join(msg)
- await nickname.send(
- random.choice(
- [
- f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
- f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
- f"好突然,突然要叫你昵称什么的...{msg}..",
- f"{NICKNAME}会好好记住的{msg}的,放心吧",
- f"好..好.,那窝以后就叫你{msg}了.",
- ]
- )
- )
- logger.info(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg}")
- else:
- await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
- logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
-
-
-@nickname.handle()
-async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if not msg:
- await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
- if len(msg) > 10:
- await nickname.finish("不要超过10个字!", at_sender=True)
- if await FriendUser.set_friend_nickname(event.user_id, msg):
- await nickname.send(
- random.choice(
- [
- f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
- f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
- f"好突然,突然要叫你昵称什么的...{msg}..",
- f"{NICKNAME}会好好记住的{msg}的,放心吧",
- f"好..好.,那窝以后就叫你{msg}了.",
- ]
- )
- )
- logger.info(f"USER {event.user_id} 设置昵称 {msg}")
- else:
- await nickname.send("设置昵称失败了,明天再来试一试!或联系管理员更新好友!", at_sender=True)
- logger.warning(f"USER {event.user_id} 设置昵称 {msg} 失败")
-
-
-@my_nickname.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- try:
- nickname_ = await GroupInfoUser.get_group_member_nickname(
- event.user_id, event.group_id
- )
- except AttributeError:
- nickname_ = ""
- if nickname_:
- await my_nickname.send(
- random.choice(
- [
- f"我肯定记得你啊,你是{nickname_}啊",
- f"我不会忘记你的,你也不要忘记我!{nickname_}",
- f"哼哼,{NICKNAME}记忆力可是很好的,{nickname_}",
- f"嗯?你是失忆了嘛...{nickname_}..",
- f"不要小看{NICKNAME}的记忆力啊!笨蛋{nickname_}!QAQ",
- f"哎?{nickname_}..怎么了吗..突然这样问..",
- ]
- )
- )
- else:
- nickname_ = event.sender.card if event.sender.card else event.sender.nickname
- await my_nickname.send(
- random.choice(
- ["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
- ).format(nickname_)
- )
-
-
-@my_nickname.handle()
-async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
- nickname_ = await FriendUser.get_friend_nickname(event.user_id)
- if nickname_:
- await my_nickname.send(
- random.choice(
- [
- f"我肯定记得你啊,你是{nickname_}啊",
- f"我不会忘记你的,你也不要忘记我!{nickname_}",
- f"哼哼,{NICKNAME}记忆力可是很好的,{nickname_}",
- f"嗯?你是失忆了嘛...{nickname_}..",
- f"不要小看{NICKNAME}的记忆力啊!笨蛋{nickname_}!QAQ",
- f"哎?{nickname_}..怎么了吗..突然这样问..",
- ]
- )
- )
- else:
- nickname_ = (await bot.get_stranger_info(user_id=event.user_id))["nickname"]
- await my_nickname.send(
- random.choice(
- ["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
- ).format(nickname_)
- )
-
-
-@cancel_nickname.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- nickname_ = await GroupInfoUser.get_group_member_nickname(
- event.user_id, event.group_id
- )
- if nickname_:
- await cancel_nickname.send(
- random.choice(
- [
- f"呜..{NICKNAME}睡一觉就会忘记的..和梦一样..{nickname_}",
- f"窝知道了..{nickname_}..",
- f"是{NICKNAME}哪里做的不好嘛..好吧..晚安{nickname_}",
- f"呃,{nickname_},下次我绝对绝对绝对不会再忘记你!",
- f"可..可恶!{nickname_}!太可恶了!呜",
- ]
- )
- )
- await GroupInfoUser.set_group_member_nickname(event.user_id, event.group_id, "")
- await BanUser.ban(event.user_id, 9, 60)
- else:
- await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
-
-
-@cancel_nickname.handle()
-async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
- nickname_ = await FriendUser.get_friend_nickname(event.user_id)
- if nickname_:
- await cancel_nickname.send(
- random.choice(
- [
- f"呜..{NICKNAME}睡一觉就会忘记的..和梦一样..{nickname_}",
- f"窝知道了..{nickname_}..",
- f"是{NICKNAME}哪里做的不好嘛..好吧..晚安{nickname_}",
- f"呃,{nickname_},下次我绝对绝对绝对不会再忘记你!",
- f"可..可恶!{nickname_}!太可恶了!呜",
- ]
- )
- )
- await FriendUser.get_user_name(event.user_id)
- await BanUser.ban(event.user_id, 9, 60)
- else:
- await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
+from nonebot import on_command
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent
+from nonebot.rule import to_me
+from utils.utils import get_message_text
+from models.group_member_info import GroupInfoUser
+from models.friend_user import FriendUser
+import random
+from models.ban_user import BanUser
+from services.log import logger
+from configs.config import NICKNAME
+
+
+__zx_plugin_name__ = "昵称系统"
+__plugin_usage__ = f"""
+usage:
+ 个人昵称系统,群聊 与 私聊 昵称相互独立
+ 指令:
+ 以后叫我 [昵称]
+ {NICKNAME}我是谁
+""".strip()
+__plugin_des__ = "区区昵称,才不想叫呢!"
+__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+nickname = on_command(
+ "nickname",
+ aliases={"以后叫我", "以后请叫我", "称呼我", "以后请称呼我", "以后称呼我", "叫我", "请叫我"},
+ rule=to_me(),
+ priority=5,
+ block=True,
+)
+
+my_nickname = on_command(
+ "my_name", aliases={"我叫什么", "我是谁", "我的名字"}, rule=to_me(), priority=5, block=True
+)
+
+
+cancel_nickname = on_command("取消昵称", rule=to_me(), priority=5, block=True)
+
+
+@nickname.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if not msg:
+ await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
+ if len(msg) > 10:
+ await nickname.finish("昵称可不能超过10个字!", at_sender=True)
+ if await GroupInfoUser.set_group_member_nickname(
+ event.user_id, event.group_id, msg
+ ):
+ if len(msg) < 5:
+ if random.random() < 0.5:
+ msg = "~".join(msg)
+ await nickname.send(
+ random.choice(
+ [
+ f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
+ f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
+ f"好突然,突然要叫你昵称什么的...{msg}..",
+ f"{NICKNAME}会好好记住的{msg}的,放心吧",
+ f"好..好.,那窝以后就叫你{msg}了.",
+ ]
+ )
+ )
+ logger.info(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg}")
+ else:
+ await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
+ logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
+
+
+@nickname.handle()
+async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if not msg:
+ await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
+ if len(msg) > 10:
+ await nickname.finish("不要超过10个字!", at_sender=True)
+ if await FriendUser.set_friend_nickname(event.user_id, msg):
+ await nickname.send(
+ random.choice(
+ [
+ f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
+ f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
+ f"好突然,突然要叫你昵称什么的...{msg}..",
+ f"{NICKNAME}会好好记住的{msg}的,放心吧",
+ f"好..好.,那窝以后就叫你{msg}了.",
+ ]
+ )
+ )
+ logger.info(f"USER {event.user_id} 设置昵称 {msg}")
+ else:
+ await nickname.send("设置昵称失败了,明天再来试一试!或联系管理员更新好友!", at_sender=True)
+ logger.warning(f"USER {event.user_id} 设置昵称 {msg} 失败")
+
+
+@my_nickname.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ try:
+ nickname_ = await GroupInfoUser.get_group_member_nickname(
+ event.user_id, event.group_id
+ )
+ except AttributeError:
+ nickname_ = ""
+ if nickname_:
+ await my_nickname.send(
+ random.choice(
+ [
+ f"我肯定记得你啊,你是{nickname_}啊",
+ f"我不会忘记你的,你也不要忘记我!{nickname_}",
+ f"哼哼,{NICKNAME}记忆力可是很好的,{nickname_}",
+ f"嗯?你是失忆了嘛...{nickname_}..",
+ f"不要小看{NICKNAME}的记忆力啊!笨蛋{nickname_}!QAQ",
+ f"哎?{nickname_}..怎么了吗..突然这样问..",
+ ]
+ )
+ )
+ else:
+ nickname_ = event.sender.card if event.sender.card else event.sender.nickname
+ await my_nickname.send(
+ random.choice(
+ ["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
+ ).format(nickname_)
+ )
+
+
+@my_nickname.handle()
+async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
+ nickname_ = await FriendUser.get_friend_nickname(event.user_id)
+ if nickname_:
+ await my_nickname.send(
+ random.choice(
+ [
+ f"我肯定记得你啊,你是{nickname_}啊",
+ f"我不会忘记你的,你也不要忘记我!{nickname_}",
+ f"哼哼,{NICKNAME}记忆力可是很好的,{nickname_}",
+ f"嗯?你是失忆了嘛...{nickname_}..",
+ f"不要小看{NICKNAME}的记忆力啊!笨蛋{nickname_}!QAQ",
+ f"哎?{nickname_}..怎么了吗..突然这样问..",
+ ]
+ )
+ )
+ else:
+ nickname_ = (await bot.get_stranger_info(user_id=event.user_id))["nickname"]
+ await my_nickname.send(
+ random.choice(
+ ["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
+ ).format(nickname_)
+ )
+
+
+@cancel_nickname.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ nickname_ = await GroupInfoUser.get_group_member_nickname(
+ event.user_id, event.group_id
+ )
+ if nickname_:
+ await cancel_nickname.send(
+ random.choice(
+ [
+ f"呜..{NICKNAME}睡一觉就会忘记的..和梦一样..{nickname_}",
+ f"窝知道了..{nickname_}..",
+ f"是{NICKNAME}哪里做的不好嘛..好吧..晚安{nickname_}",
+ f"呃,{nickname_},下次我绝对绝对绝对不会再忘记你!",
+ f"可..可恶!{nickname_}!太可恶了!呜",
+ ]
+ )
+ )
+ await GroupInfoUser.set_group_member_nickname(event.user_id, event.group_id, "")
+ await BanUser.ban(event.user_id, 9, 60)
+ else:
+ await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
+
+
+@cancel_nickname.handle()
+async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
+ nickname_ = await FriendUser.get_friend_nickname(event.user_id)
+ if nickname_:
+ await cancel_nickname.send(
+ random.choice(
+ [
+ f"呜..{NICKNAME}睡一觉就会忘记的..和梦一样..{nickname_}",
+ f"窝知道了..{nickname_}..",
+ f"是{NICKNAME}哪里做的不好嘛..好吧..晚安{nickname_}",
+ f"呃,{nickname_},下次我绝对绝对绝对不会再忘记你!",
+ f"可..可恶!{nickname_}!太可恶了!呜",
+ ]
+ )
+ )
+ await FriendUser.get_user_name(event.user_id)
+ await BanUser.ban(event.user_id, 9, 60)
+ else:
+ await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
diff --git a/basic_plugins/scripts.py b/basic_plugins/scripts.py
old mode 100644
new mode 100755
index 2a8879e6..11abd3c3
--- a/basic_plugins/scripts.py
+++ b/basic_plugins/scripts.py
@@ -1,111 +1,103 @@
-from nonebot import Driver
-from services.db_context import db
-from asyncpg.exceptions import DuplicateColumnError
-from models.group_info import GroupInfo
-from nonebot.adapters.cqhttp import Bot
-from utils.user_agent import get_user_agent
-from services.log import logger
-from configs.path_config import TEXT_PATH
-from asyncio.exceptions import TimeoutError
-from pathlib import Path
-import aiohttp
-import nonebot
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-driver: Driver = nonebot.get_driver()
-
-
-@driver.on_startup
-async def update_city():
- """
- 部分插件需要中国省份城市
- 这里直接更新,避免插件内代码重复
- :return:
- """
- china_city = Path(TEXT_PATH) / "china_city.json"
- data = {}
- try:
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(
- "http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
- ) as res:
- provinces_data = json.loads(await res.text(encoding="utf8"))
- for province in provinces_data.keys():
- data[provinces_data[province]] = []
- async with session.get(
- f"http://www.weather.com.cn/data/city3jdata/provshi/{province}.html",
- timeout=5,
- ) as res:
- city_data = json.loads(await res.text(encoding="utf8"))
- for city in city_data.keys():
- data[provinces_data[province]].append(city_data[city])
- with open(china_city, "w", encoding="utf8") as f:
- json.dump(data, f, indent=4, ensure_ascii=False)
- logger.info("自动更新城市列表完成.....")
- except TimeoutError:
- logger.info("自动更新城市列表超时.....")
-
-
-@driver.on_startup
-async def _():
- """
- 数据库表结构变换
- """
- sql_str = [
- "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;" # group_info表添加一个group_flag
- ]
- for sql in sql_str:
- try:
- query = db.text(sql)
- await db.first(query)
- except DuplicateColumnError:
- pass
-
-
-@driver.on_bot_connect
-async def _(bot: Bot):
- """
- 版本某些需要的变换
- """
- # 清空不存在的群聊信息,并将已所有已存在的群聊group_flag设置为1(认证所有已存在的群)
- if not await GroupInfo.get_group_info(114514):
- # 标识符,该功能只需执行一次
- await GroupInfo.add_group_info(
- 114514,
- "114514",
- 114514,
- 114514,
- 1
- )
- group_list = await bot.get_group_list()
- group_list = [g["group_id"] for g in group_list]
- _gl = [x.group_id for x in await GroupInfo.get_all_group()]
- if 114514 in _gl:
- _gl.remove(114514)
- for group_id in _gl:
- if group_id in group_list:
- if await GroupInfo.get_group_info(group_id):
- await GroupInfo.set_group_flag(group_id, 1)
- else:
- group_info = await bot.get_group_info(group_id=group_id)
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1
- )
- logger.info(f"已将群聊 {group_id} 添加认证...")
- else:
- await GroupInfo.delete_group_info(group_id)
- logger.info(f"移除不存在的群聊信息:{group_id}")
-
-
-
-
-
+from nonebot import Driver
+from services.db_context import db
+from asyncpg.exceptions import DuplicateColumnError
+from models.group_info import GroupInfo
+from nonebot.adapters.cqhttp import Bot
+from services.log import logger
+from configs.path_config import TEXT_PATH
+from asyncio.exceptions import TimeoutError
+from utils.http_utils import AsyncHttpx
+from pathlib import Path
+import nonebot
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+driver: Driver = nonebot.get_driver()
+
+
+@driver.on_startup
+async def update_city():
+ """
+ 部分插件需要中国省份城市
+ 这里直接更新,避免插件内代码重复
+ """
+ china_city = Path(TEXT_PATH) / "china_city.json"
+ data = {}
+ try:
+ res = await AsyncHttpx.get(
+ "http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
+ )
+ res.encoding = "utf8"
+ provinces_data = json.loads(res.text)
+ for province in provinces_data.keys():
+ data[provinces_data[province]] = []
+ res = await AsyncHttpx.get(
+ f"http://www.weather.com.cn/data/city3jdata/provshi/{province}.html",
+ timeout=5,
+ )
+ res.encoding = "utf8"
+ city_data = json.loads(res.text)
+ for city in city_data.keys():
+ data[provinces_data[province]].append(city_data[city])
+ with open(china_city, "w", encoding="utf8") as f:
+ json.dump(data, f, indent=4, ensure_ascii=False)
+ logger.info("自动更新城市列表完成.....")
+ except TimeoutError:
+ logger.warning("自动更新城市列表超时.....")
+ except ValueError:
+ logger.warning("自动城市列表失败.....")
+ except Exception as e:
+ logger.error(f"自动城市列表未知错误 {type(e)}:{e}")
+
+
+@driver.on_startup
+async def _():
+ """
+ 数据库表结构变换
+ """
+ sql_str = [
+ "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;" # group_info表添加一个group_flag
+ ]
+ for sql in sql_str:
+ try:
+ query = db.text(sql)
+ await db.first(query)
+ except DuplicateColumnError:
+ pass
+
+
+@driver.on_bot_connect
+async def _(bot: Bot):
+ """
+ 版本某些需要的变换
+ """
+ # 清空不存在的群聊信息,并将已所有已存在的群聊group_flag设置为1(认证所有已存在的群)
+ if not await GroupInfo.get_group_info(114514):
+ # 标识符,该功能只需执行一次
+ await GroupInfo.add_group_info(114514, "114514", 114514, 114514, 1)
+ group_list = await bot.get_group_list()
+ group_list = [g["group_id"] for g in group_list]
+ _gl = [x.group_id for x in await GroupInfo.get_all_group()]
+ if 114514 in _gl:
+ _gl.remove(114514)
+ for group_id in _gl:
+ if group_id in group_list:
+ if await GroupInfo.get_group_info(group_id):
+ await GroupInfo.set_group_flag(group_id, 1)
+ else:
+ group_info = await bot.get_group_info(group_id=group_id)
+ await GroupInfo.add_group_info(
+ group_info["group_id"],
+ group_info["group_name"],
+ group_info["max_member_count"],
+ group_info["member_count"],
+ 1,
+ )
+ logger.info(f"已将群聊 {group_id} 添加认证...")
+ else:
+ await GroupInfo.delete_group_info(group_id)
+ logger.info(f"移除不存在的群聊信息:{group_id}")
diff --git a/basic_plugins/super_cmd/__init__.py b/basic_plugins/super_cmd/__init__.py
old mode 100644
new mode 100755
index b4997936..47831269
--- a/basic_plugins/super_cmd/__init__.py
+++ b/basic_plugins/super_cmd/__init__.py
@@ -1,10 +1,10 @@
-import nonebot
-
-
-nonebot.load_plugins('basic_plugins/super_cmd')
-
-
-
-
-
-
+import nonebot
+
+
+nonebot.load_plugins('basic_plugins/super_cmd')
+
+
+
+
+
+
diff --git a/basic_plugins/super_cmd/bot_friend_group.py b/basic_plugins/super_cmd/bot_friend_group.py
old mode 100644
new mode 100755
index def933c8..ff4b16ab
--- a/basic_plugins/super_cmd/bot_friend_group.py
+++ b/basic_plugins/super_cmd/bot_friend_group.py
@@ -1,152 +1,152 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, Message
-from nonebot.rule import to_me
-from utils.utils import get_message_text, is_number
-from utils.manager import requests_manager
-from utils.message_builder import image
-from models.group_info import GroupInfo
-
-
-__zx_plugin_name__ = "显示所有好友群组 [Superuser]"
-__plugin_usage__ = """
-usage:
- 显示所有好友群组
- 指令:
- 查看所有好友/查看所有群组
- 同意好友请求 [id]
- 拒绝好友请求 [id]
- 同意群聊请求 [id]
- 拒绝群聊请求 [id]
- 查看所有请求
- 清空所有请求
-""".strip()
-__plugin_des__ = "显示所有好友群组"
-__plugin_cmd__ = [
- "查看所有好友/查看所有群组",
- "同意好友请求 [id]",
- "拒绝好友请求 [id]",
- "同意群聊请求 [id]",
- "拒绝群聊请求 [id]",
- "查看所有请求",
- "清空所有请求",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-cls_group = on_command(
- "查看所有群组", rule=to_me(), permission=SUPERUSER, priority=1, block=True
-)
-cls_friend = on_command(
- "查看所有好友", rule=to_me(), permission=SUPERUSER, priority=1, block=True
-)
-
-friend_handle = on_command(
- "同意好友请求", aliases={"拒绝好友请求"}, permission=SUPERUSER, priority=1, block=True
-)
-
-group_handle = on_command(
- "同意群聊请求", aliases={"拒绝群聊请求"}, permission=SUPERUSER, priority=1, block=True
-)
-
-clear_request = on_command("清空所有请求", permission=SUPERUSER, priority=1, block=True)
-
-cls_request = on_command("查看所有请求", permission=SUPERUSER, priority=1, block=True)
-
-
-@cls_group.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- gl = await bot.get_group_list(self_id=int(bot.self_id))
- msg = ["{group_id} {group_name}".format_map(g) for g in gl]
- msg = "\n".join(msg)
- msg = f"bot:{bot.self_id}\n| 群号 | 群名 | 共{len(gl)}个群\n" + msg
- await bot.send_private_msg(
- self_id=int(bot.self_id),
- user_id=int(list(bot.config.superusers)[0]),
- message=msg,
- )
-
-
-@cls_friend.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- gl = await bot.get_friend_list(self_id=int(bot.self_id))
- msg = ["{user_id} {nickname}".format_map(g) for g in gl]
- msg = "\n".join(msg)
- msg = f"| QQ号 | 昵称 | 共{len(gl)}个好友\n" + msg
- await bot.send_private_msg(
- self_id=int(bot.self_id),
- user_id=int(list(bot.config.superusers)[0]),
- message=msg,
- )
-
-
-@friend_handle.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- id_ = get_message_text(event.json())
- if is_number(id_):
- id_ = int(id_)
- if state["_prefix"]["raw_command"][:2] == "同意":
- if await requests_manager.approve(bot, id_, "private"):
- await friend_handle.send("同意好友请求成功..")
- else:
- await friend_handle.send("同意好友请求失败,可能是未找到此id的请求..")
- else:
- if await requests_manager.refused(bot, id_, "private"):
- await friend_handle.send("拒绝好友请求成功..")
- else:
- await friend_handle.send("拒绝好友请求失败,可能是未找到此id的请求..")
- else:
- await friend_handle.send("id必须为纯数字!")
-
-
-@group_handle.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- id_ = get_message_text(event.json())
- if is_number(id_):
- id_ = int(id_)
- if state["_prefix"]["raw_command"][:2] == "同意":
- rid = await requests_manager.approve(bot, id_, "group")
- if rid:
- await friend_handle.send("同意群聊请求成功..")
- if await GroupInfo.get_group_info(rid):
- await GroupInfo.set_group_flag(rid, 1)
- else:
- group_info = await bot.get_group_info(group_id=rid)
- await GroupInfo.add_group_info(
- rid,
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1
- )
- else:
- await friend_handle.send("同意群聊请求失败,可能是未找到此id的请求..")
- else:
- if await requests_manager.refused(bot, id_, "group"):
- await friend_handle.send("拒绝群聊请求成功..")
- else:
- await friend_handle.send("拒绝群聊请求失败,可能是未找到此id的请求..")
- else:
- await friend_handle.send("id必须为纯数字!")
-
-
-@cls_request.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- _str = ""
- for type_ in ["private", "group"]:
- msg = await requests_manager.show(type_)
- if msg:
- _str += image(b64=msg)
- else:
- _str += "没有任何好友请求.." if type_ == "private" else "没有任何群聊请求.."
- if type_ == "private":
- _str += '\n--------------------\n'
- await cls_request.send(Message(_str))
-
-
-@clear_request.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- requests_manager.clear()
- await cls_request.send("已清空所有好友/群聊请求..")
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, Message
+from nonebot.rule import to_me
+from utils.utils import get_message_text, is_number
+from utils.manager import requests_manager
+from utils.message_builder import image
+from models.group_info import GroupInfo
+
+
+__zx_plugin_name__ = "显示所有好友群组 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 显示所有好友群组
+ 指令:
+ 查看所有好友/查看所有群组
+ 同意好友请求 [id]
+ 拒绝好友请求 [id]
+ 同意群聊请求 [id]
+ 拒绝群聊请求 [id]
+ 查看所有请求
+ 清空所有请求
+""".strip()
+__plugin_des__ = "显示所有好友群组"
+__plugin_cmd__ = [
+ "查看所有好友/查看所有群组",
+ "同意好友请求 [id]",
+ "拒绝好友请求 [id]",
+ "同意群聊请求 [id]",
+ "拒绝群聊请求 [id]",
+ "查看所有请求",
+ "清空所有请求",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+cls_group = on_command(
+ "查看所有群组", rule=to_me(), permission=SUPERUSER, priority=1, block=True
+)
+cls_friend = on_command(
+ "查看所有好友", rule=to_me(), permission=SUPERUSER, priority=1, block=True
+)
+
+friend_handle = on_command(
+ "同意好友请求", aliases={"拒绝好友请求"}, permission=SUPERUSER, priority=1, block=True
+)
+
+group_handle = on_command(
+ "同意群聊请求", aliases={"拒绝群聊请求"}, permission=SUPERUSER, priority=1, block=True
+)
+
+clear_request = on_command("清空所有请求", permission=SUPERUSER, priority=1, block=True)
+
+cls_request = on_command("查看所有请求", permission=SUPERUSER, priority=1, block=True)
+
+
+@cls_group.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ gl = await bot.get_group_list(self_id=int(bot.self_id))
+ msg = ["{group_id} {group_name}".format_map(g) for g in gl]
+ msg = "\n".join(msg)
+ msg = f"bot:{bot.self_id}\n| 群号 | 群名 | 共{len(gl)}个群\n" + msg
+ await bot.send_private_msg(
+ self_id=int(bot.self_id),
+ user_id=int(list(bot.config.superusers)[0]),
+ message=msg,
+ )
+
+
+@cls_friend.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ gl = await bot.get_friend_list(self_id=int(bot.self_id))
+ msg = ["{user_id} {nickname}".format_map(g) for g in gl]
+ msg = "\n".join(msg)
+ msg = f"| QQ号 | 昵称 | 共{len(gl)}个好友\n" + msg
+ await bot.send_private_msg(
+ self_id=int(bot.self_id),
+ user_id=int(list(bot.config.superusers)[0]),
+ message=msg,
+ )
+
+
+@friend_handle.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ id_ = get_message_text(event.json())
+ if is_number(id_):
+ id_ = int(id_)
+ if state["_prefix"]["raw_command"][:2] == "同意":
+ if await requests_manager.approve(bot, id_, "private"):
+ await friend_handle.send("同意好友请求成功..")
+ else:
+ await friend_handle.send("同意好友请求失败,可能是未找到此id的请求..")
+ else:
+ if await requests_manager.refused(bot, id_, "private"):
+ await friend_handle.send("拒绝好友请求成功..")
+ else:
+ await friend_handle.send("拒绝好友请求失败,可能是未找到此id的请求..")
+ else:
+ await friend_handle.send("id必须为纯数字!")
+
+
+@group_handle.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ id_ = get_message_text(event.json())
+ if is_number(id_):
+ id_ = int(id_)
+ if state["_prefix"]["raw_command"][:2] == "同意":
+ rid = await requests_manager.approve(bot, id_, "group")
+ if rid:
+ await friend_handle.send("同意群聊请求成功..")
+ if await GroupInfo.get_group_info(rid):
+ await GroupInfo.set_group_flag(rid, 1)
+ else:
+ group_info = await bot.get_group_info(group_id=rid)
+ await GroupInfo.add_group_info(
+ rid,
+ group_info["group_name"],
+ group_info["max_member_count"],
+ group_info["member_count"],
+ 1
+ )
+ else:
+ await friend_handle.send("同意群聊请求失败,可能是未找到此id的请求..")
+ else:
+ if await requests_manager.refused(bot, id_, "group"):
+ await friend_handle.send("拒绝群聊请求成功..")
+ else:
+ await friend_handle.send("拒绝群聊请求失败,可能是未找到此id的请求..")
+ else:
+ await friend_handle.send("id必须为纯数字!")
+
+
+@cls_request.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ _str = ""
+ for type_ in ["private", "group"]:
+ msg = await requests_manager.show(type_)
+ if msg:
+ _str += image(b64=msg)
+ else:
+ _str += "没有任何好友请求.." if type_ == "private" else "没有任何群聊请求.."
+ if type_ == "private":
+ _str += '\n--------------------\n'
+ await cls_request.send(Message(_str))
+
+
+@clear_request.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ requests_manager.clear()
+ await cls_request.send("已清空所有好友/群聊请求..")
diff --git a/basic_plugins/super_cmd/clear_data.py b/basic_plugins/super_cmd/clear_data.py
old mode 100644
new mode 100755
index b77237ad..d7571954
--- a/basic_plugins/super_cmd/clear_data.py
+++ b/basic_plugins/super_cmd/clear_data.py
@@ -1,67 +1,67 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent
-from configs.path_config import TEMP_PATH
-from nonebot.rule import to_me
-from utils.utils import scheduler
-from services.log import logger
-from utils.manager import resources_manager
-import asyncio
-import time
-import os
-
-__zx_plugin_name__ = "清理临时数据 [Superuser]"
-__plugin_usage__ = """
-usage:
- 清理临时数据
- 指令:
- 清理临时数据
-""".strip()
-__plugin_des__ = "清理临时数据"
-__plugin_cmd__ = [
- "清理临时数据",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-clear_data = on_command(
- "清理临时数据", rule=to_me(), permission=SUPERUSER, priority=1, block=True
-)
-
-
-resources_manager.add_temp_dir(TEMP_PATH)
-
-
-@clear_data.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- await clear_data.send("开始清理临时数据....")
- size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
- await clear_data.send("共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
-
-
-def _clear_data() -> float:
- size = 0
- for dir_ in resources_manager.get_temp_data_dir():
- if dir_.exists():
- for file in os.listdir(dir_):
- file = dir_ / file
- try:
- if time.time() - os.path.getatime(file) > 300:
- file_size = os.path.getsize(file)
- file.unlink()
- size += file_size
- except Exception as e:
- logger.error(f"清理临时数据错误...{type(e)}:{e}")
- return float(size)
-
-
-@scheduler.scheduled_job(
- "cron",
- hour=1,
- minute=1,
-)
-async def _():
- size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
- logger.info("自动清理临时数据完成," + "共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from configs.path_config import TEMP_PATH
+from nonebot.rule import to_me
+from utils.utils import scheduler
+from services.log import logger
+from utils.manager import resources_manager
+import asyncio
+import time
+import os
+
+__zx_plugin_name__ = "清理临时数据 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 清理临时数据
+ 指令:
+ 清理临时数据
+""".strip()
+__plugin_des__ = "清理临时数据"
+__plugin_cmd__ = [
+ "清理临时数据",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+clear_data = on_command(
+ "清理临时数据", rule=to_me(), permission=SUPERUSER, priority=1, block=True
+)
+
+
+resources_manager.add_temp_dir(TEMP_PATH)
+
+
+@clear_data.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ await clear_data.send("开始清理临时数据....")
+ size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
+ await clear_data.send("共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
+
+
+def _clear_data() -> float:
+ size = 0
+ for dir_ in resources_manager.get_temp_data_dir():
+ if dir_.exists():
+ for file in os.listdir(dir_):
+ file = dir_ / file
+ try:
+ if time.time() - os.path.getatime(file) > 300:
+ file_size = os.path.getsize(file)
+ file.unlink()
+ size += file_size
+ except Exception as e:
+ logger.error(f"清理临时数据错误...{type(e)}:{e}")
+ return float(size)
+
+
+@scheduler.scheduled_job(
+ "cron",
+ hour=1,
+ minute=1,
+)
+async def _():
+ size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
+ logger.info("自动清理临时数据完成," + "共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
diff --git a/basic_plugins/super_cmd/data_source.py b/basic_plugins/super_cmd/data_source.py
old mode 100644
new mode 100755
index 86c06db0..53244823
--- a/basic_plugins/super_cmd/data_source.py
+++ b/basic_plugins/super_cmd/data_source.py
@@ -1,74 +1,74 @@
-
-
-# async def open_remind(group: int, name: str) -> str:
-# _name = ""
-# if name == "zwa":
-# _name = "早晚安"
-# if name == "dz":
-# _name = "地震播报"
-# if name == "hy":
-# _name = "群欢迎"
-# if name == "kxcz":
-# _name = "开箱重置提醒"
-# if name == "gb":
-# _name = "广播"
-# if await GroupRemind.get_status(group, name):
-# return f"该群已经开启过 {_name} 通知,请勿重复开启!"
-# if await GroupRemind.set_status(group, name, True):
-# return f"成功开启 {_name} 通知!0v0"
-# else:
-# return f"开启 {_name} 通知失败了..."
-#
-#
-# async def close_remind(group: int, name: str) -> str:
-# _name = ""
-# if name == "zwa":
-# _name = "早晚安"
-# if name == "dz":
-# _name = "地震播报"
-# if name == "hy":
-# _name = "群欢迎"
-# if name == "kxcz":
-# _name = "开箱重置提醒"
-# if name == "gb":
-# _name = "广播"
-# if not await GroupRemind.get_status(group, name):
-# return f"该群已经取消过 {_name} 通知,请勿重复取消!"
-# if await GroupRemind.set_status(group, name, False):
-# return f"成功关闭 {_name} 通知!0v0"
-# else:
-# return f"关闭 {_name} 通知失败了..."
-
-
-# cmd_list = ['总开关', '签到', '发送图片', '色图', '黑白草图', 'coser', '鸡汤/语录', '骂我', '开箱', '鲁迅说', '假消息', '商店系统',
-# '操作图片', '查询皮肤', '天气', '疫情', '识番', '搜番', '点歌', 'pixiv', 'rss', '方舟一井', '查干员', '骰子娘', '原神一井']
-#
-#
-# def check_group_switch_json(group_id):
-# if not os.path.exists(DATA_PATH + f'rule/group_switch/'):
-# os.mkdir(DATA_PATH + f'rule/group_switch/')
-# if not os.path.exists(DATA_PATH + f'rule/group_switch/{group_id}.json'):
-# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'w', encoding='utf8') as f:
-# data = {}
-# for cmd in cmd_list:
-# data[cmd] = True
-# f.write(json.dumps(data, ensure_ascii=False))
-# else:
-# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'r', encoding='utf8') as f:
-# try:
-# data = json.load(f)
-# except ValueError:
-# data = {}
-# if len(data.keys()) - 1 != len(cmd_list):
-# for cmd in cmd_list:
-# if cmd not in data.keys():
-# data[cmd] = True
-# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'w', encoding='utf8') as wf:
-# wf.write(json.dumps(data, ensure_ascii=False))
-# reload(data)
-# for file in os.listdir(DATA_PATH + 'group_help'):
-# os.remove(DATA_PATH + f'group_help/{file}')
-
-
-def reload(data):
- static_group_dict = data
+
+
+# async def open_remind(group: int, name: str) -> str:
+# _name = ""
+# if name == "zwa":
+# _name = "早晚安"
+# if name == "dz":
+# _name = "地震播报"
+# if name == "hy":
+# _name = "群欢迎"
+# if name == "kxcz":
+# _name = "开箱重置提醒"
+# if name == "gb":
+# _name = "广播"
+# if await GroupRemind.get_status(group, name):
+# return f"该群已经开启过 {_name} 通知,请勿重复开启!"
+# if await GroupRemind.set_status(group, name, True):
+# return f"成功开启 {_name} 通知!0v0"
+# else:
+# return f"开启 {_name} 通知失败了..."
+#
+#
+# async def close_remind(group: int, name: str) -> str:
+# _name = ""
+# if name == "zwa":
+# _name = "早晚安"
+# if name == "dz":
+# _name = "地震播报"
+# if name == "hy":
+# _name = "群欢迎"
+# if name == "kxcz":
+# _name = "开箱重置提醒"
+# if name == "gb":
+# _name = "广播"
+# if not await GroupRemind.get_status(group, name):
+# return f"该群已经取消过 {_name} 通知,请勿重复取消!"
+# if await GroupRemind.set_status(group, name, False):
+# return f"成功关闭 {_name} 通知!0v0"
+# else:
+# return f"关闭 {_name} 通知失败了..."
+
+
+# cmd_list = ['总开关', '签到', '发送图片', '色图', '黑白草图', 'coser', '鸡汤/语录', '骂我', '开箱', '鲁迅说', '假消息', '商店系统',
+# '操作图片', '查询皮肤', '天气', '疫情', '识番', '搜番', '点歌', 'pixiv', 'rss', '方舟一井', '查干员', '骰子娘', '原神一井']
+#
+#
+# def check_group_switch_json(group_id):
+# if not os.path.exists(DATA_PATH + f'rule/group_switch/'):
+# os.mkdir(DATA_PATH + f'rule/group_switch/')
+# if not os.path.exists(DATA_PATH + f'rule/group_switch/{group_id}.json'):
+# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'w', encoding='utf8') as f:
+# data = {}
+# for cmd in cmd_list:
+# data[cmd] = True
+# f.write(json.dumps(data, ensure_ascii=False))
+# else:
+# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'r', encoding='utf8') as f:
+# try:
+# data = json.load(f)
+# except ValueError:
+# data = {}
+# if len(data.keys()) - 1 != len(cmd_list):
+# for cmd in cmd_list:
+# if cmd not in data.keys():
+# data[cmd] = True
+# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'w', encoding='utf8') as wf:
+# wf.write(json.dumps(data, ensure_ascii=False))
+# reload(data)
+# for file in os.listdir(DATA_PATH + 'group_help'):
+# os.remove(DATA_PATH + f'group_help/{file}')
+
+
+def reload(data):
+ static_group_dict = data
diff --git a/basic_plugins/super_cmd/manager_group.py b/basic_plugins/super_cmd/manager_group.py
old mode 100644
new mode 100755
index 36d4fb56..e6af40c8
--- a/basic_plugins/super_cmd/manager_group.py
+++ b/basic_plugins/super_cmd/manager_group.py
@@ -1,200 +1,200 @@
-from nonebot import on_command, on_regex
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GROUP, GroupMessageEvent
-from nonebot.rule import to_me
-from utils.utils import get_message_text, is_number
-from utils.manager import group_manager, plugins2settings_manager
-from models.group_info import GroupInfo
-from services.log import logger
-from configs.config import NICKNAME
-from nonebot.adapters.cqhttp.exception import ActionFailed
-
-
-__zx_plugin_name__ = "管理群操作 [Superuser]"
-__plugin_usage__ = """
-usage:
- 群权限 | 群白名单 | 退出群 操作
- 指令:
- 退群 [group_id]
- 修改群权限 [group_id] [等级]
- 添加群白名单 *[group_id]
- 删除群白名单 *[group_id]
- 添加群认证 *[group_id]
- 删除群认证 *[group_id]
- 查看群白名单
-""".strip()
-__plugin_des__ = "管理群操作"
-__plugin_cmd__ = [
- "退群 [group_id]",
- "修改群权限 [group_id] [等级]",
- "添加群白名单 *[group_id]",
- "删除群白名单 *[group_id]",
- "添加群认证 *[group_id]",
- "删除群认证 *[group_id]",
- "查看群白名单",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-del_group = on_command("退群", rule=to_me(), permission=SUPERUSER, priority=1, block=True)
-
-add_group_level = on_command("修改群权限", priority=1, permission=SUPERUSER, block=True)
-my_group_level = on_command(
- "查看群权限", aliases={"群权限"}, priority=5, permission=GROUP, block=True
-)
-what_up_group_level = on_regex(
- ".*?(提高|提升|升高|增加|加上)(.*?)群权限.*?",
- rule=to_me(),
- priority=5,
- permission=GROUP,
- block=True,
-)
-manager_group_whitelist = on_command(
- "添加群白名单", aliases={"删除群白名单"}, priority=1, permission=SUPERUSER, block=True
-)
-
-show_group_whitelist = on_command(
- "查看群白名单", priority=1, permission=SUPERUSER, block=True
-)
-
-group_auth = on_command(
- "添加群认证", aliases={"删除群认证"}, priority=1, permission=SUPERUSER, block=True
-)
-
-
-@del_group.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- group_id = get_message_text(event.json())
- if group_id:
- if is_number(group_id):
- try:
- await bot.set_group_leave(group_id=int(group_id))
- logger.info(f"退出群聊 {group_id} 成功")
- await del_group.send(f"退出群聊 {group_id} 成功", at_sender=True)
- group_manager.delete_group(int(group_id))
- await GroupInfo.delete_group_info(int(group_id))
- except Exception as e:
- logger.info(f"退出群聊 {group_id} 失败 e:{e}")
- else:
- await del_group.finish(f"请输入正确的群号", at_sender=True)
- else:
- await del_group.finish(f"请输入群号", at_sender=True)
-
-
-@add_group_level.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- group_id = 0
- level = 0
- if not msg:
- await add_group_level.finish("用法:修改群权限 [group] [level]")
- msg = msg.split(" ")
- if len(msg) < 2:
- await add_group_level.finish("参数不完全..[group] [level]")
- if is_number(msg[0]) and is_number(msg[1]):
- group_id = msg[0]
- level = int(msg[1])
- else:
- await add_group_level.finish("参数错误...group和level必须是数字..")
- old_level = group_manager.get_group_level(group_id)
- group_manager.set_group_level(group_id, level)
- await add_group_level.send("修改成功...", at_sender=True)
- if level > -1:
- await bot.send_group_msg(
- group_id=int(group_id), message=f"管理员修改了此群权限:{old_level} -> {level}"
- )
- logger.info(f"{event.user_id} 修改了 {group_id} 的权限:{level}")
-
-
-@my_group_level.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- level = group_manager.get_group_level(event.group_id)
- tmp = ""
- data = plugins2settings_manager.get_data()
- for module in data:
- if data[module]["level"] > level:
- plugin_name = data[module]["cmd"][0]
- if plugin_name == "pixiv":
- plugin_name = "搜图 p站排行"
- tmp += f"{plugin_name}\n"
- if tmp:
- tmp = "\n目前无法使用的功能:\n" + tmp
- await my_group_level.finish(f"当前群权限:{level}{tmp}")
-
-
-@what_up_group_level.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- await what_up_group_level.finish(
- f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.管理员修改权限"
- )
-
-
-@manager_group_whitelist.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json()).split()
- all_group = [
- g["group_id"] for g in await bot.get_group_list(self_id=int(bot.self_id))
- ]
- group_list = []
- for group in msg:
- if is_number(group) and int(group) in all_group:
- group_list.append(int(group))
- if group_list:
- for group in group_list:
- if state["_prefix"]["raw_command"] in ["添加群白名单"]:
- group_manager.add_group_white_list(group)
- else:
- group_manager.delete_group_white_list(group)
- group_list = [str(x) for x in group_list]
- await manager_group_whitelist.send(
- "已成功将 " + "\n".join(group_list) + " " + state["_prefix"]["raw_command"]
- )
- else:
- await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
-
-
-@show_group_whitelist.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- x = group_manager.get_group_white_list()
- x = [str(g) for g in x]
- if x:
- await show_group_whitelist.send("目前的群白名单:\n" + "\n".join(x))
- else:
- await show_group_whitelist.send("没有任何群在群白名单...")
-
-
-@group_auth.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json()).split()
- for group_id in msg:
- if not is_number(group_id):
- await group_auth.send(f"{group_id}非纯数字,已跳过该项..")
- group_id = int(group_id)
- if state["_prefix"]["raw_command"][:2] == "添加":
- if await GroupInfo.get_group_info(group_id):
- await GroupInfo.set_group_flag(group_id, 1)
- else:
- try:
- group_info = await bot.get_group_info(group_id=group_id)
- except ActionFailed:
- group_info = {
- "group_id": group_id,
- "group_name": "_",
- "max_member_count": -1,
- "member_count": -1,
- }
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1,
- )
- else:
- if await GroupInfo.get_group_info(group_id):
- await GroupInfo.set_group_flag(group_id, 0)
- await group_auth.send(
- f'已为 {group_id} {state["_prefix"]["raw_command"][:2]}群认证..'
- )
+from nonebot import on_command, on_regex
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GROUP, GroupMessageEvent
+from nonebot.rule import to_me
+from utils.utils import get_message_text, is_number
+from utils.manager import group_manager, plugins2settings_manager
+from models.group_info import GroupInfo
+from services.log import logger
+from configs.config import NICKNAME
+from nonebot.adapters.cqhttp.exception import ActionFailed
+
+
+__zx_plugin_name__ = "管理群操作 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 群权限 | 群白名单 | 退出群 操作
+ 指令:
+ 退群 [group_id]
+ 修改群权限 [group_id] [等级]
+ 添加群白名单 *[group_id]
+ 删除群白名单 *[group_id]
+ 添加群认证 *[group_id]
+ 删除群认证 *[group_id]
+ 查看群白名单
+""".strip()
+__plugin_des__ = "管理群操作"
+__plugin_cmd__ = [
+ "退群 [group_id]",
+ "修改群权限 [group_id] [等级]",
+ "添加群白名单 *[group_id]",
+ "删除群白名单 *[group_id]",
+ "添加群认证 *[group_id]",
+ "删除群认证 *[group_id]",
+ "查看群白名单",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+del_group = on_command("退群", rule=to_me(), permission=SUPERUSER, priority=1, block=True)
+
+add_group_level = on_command("修改群权限", priority=1, permission=SUPERUSER, block=True)
+my_group_level = on_command(
+ "查看群权限", aliases={"群权限"}, priority=5, permission=GROUP, block=True
+)
+what_up_group_level = on_regex(
+ ".*?(提高|提升|升高|增加|加上)(.*?)群权限.*?",
+ rule=to_me(),
+ priority=5,
+ permission=GROUP,
+ block=True,
+)
+manager_group_whitelist = on_command(
+ "添加群白名单", aliases={"删除群白名单"}, priority=1, permission=SUPERUSER, block=True
+)
+
+show_group_whitelist = on_command(
+ "查看群白名单", priority=1, permission=SUPERUSER, block=True
+)
+
+group_auth = on_command(
+ "添加群认证", aliases={"删除群认证"}, priority=1, permission=SUPERUSER, block=True
+)
+
+
+@del_group.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ group_id = get_message_text(event.json())
+ if group_id:
+ if is_number(group_id):
+ try:
+ await bot.set_group_leave(group_id=int(group_id))
+ logger.info(f"退出群聊 {group_id} 成功")
+ await del_group.send(f"退出群聊 {group_id} 成功", at_sender=True)
+ group_manager.delete_group(int(group_id))
+ await GroupInfo.delete_group_info(int(group_id))
+ except Exception as e:
+ logger.info(f"退出群聊 {group_id} 失败 e:{e}")
+ else:
+ await del_group.finish(f"请输入正确的群号", at_sender=True)
+ else:
+ await del_group.finish(f"请输入群号", at_sender=True)
+
+
+@add_group_level.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ group_id = 0
+ level = 0
+ if not msg:
+ await add_group_level.finish("用法:修改群权限 [group] [level]")
+ msg = msg.split(" ")
+ if len(msg) < 2:
+ await add_group_level.finish("参数不完全..[group] [level]")
+ if is_number(msg[0]) and is_number(msg[1]):
+ group_id = msg[0]
+ level = int(msg[1])
+ else:
+ await add_group_level.finish("参数错误...group和level必须是数字..")
+ old_level = group_manager.get_group_level(group_id)
+ group_manager.set_group_level(group_id, level)
+ await add_group_level.send("修改成功...", at_sender=True)
+ if level > -1:
+ await bot.send_group_msg(
+ group_id=int(group_id), message=f"管理员修改了此群权限:{old_level} -> {level}"
+ )
+ logger.info(f"{event.user_id} 修改了 {group_id} 的权限:{level}")
+
+
+@my_group_level.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ level = group_manager.get_group_level(event.group_id)
+ tmp = ""
+ data = plugins2settings_manager.get_data()
+ for module in data:
+ if data[module]["level"] > level:
+ plugin_name = data[module]["cmd"][0]
+ if plugin_name == "pixiv":
+ plugin_name = "搜图 p站排行"
+ tmp += f"{plugin_name}\n"
+ if tmp:
+ tmp = "\n目前无法使用的功能:\n" + tmp
+ await my_group_level.finish(f"当前群权限:{level}{tmp}")
+
+
+@what_up_group_level.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ await what_up_group_level.finish(
+ f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.管理员修改权限"
+ )
+
+
+@manager_group_whitelist.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json()).split()
+ all_group = [
+ g["group_id"] for g in await bot.get_group_list(self_id=int(bot.self_id))
+ ]
+ group_list = []
+ for group in msg:
+ if is_number(group) and int(group) in all_group:
+ group_list.append(int(group))
+ if group_list:
+ for group in group_list:
+ if state["_prefix"]["raw_command"] in ["添加群白名单"]:
+ group_manager.add_group_white_list(group)
+ else:
+ group_manager.delete_group_white_list(group)
+ group_list = [str(x) for x in group_list]
+ await manager_group_whitelist.send(
+ "已成功将 " + "\n".join(group_list) + " " + state["_prefix"]["raw_command"]
+ )
+ else:
+ await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
+
+
+@show_group_whitelist.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ x = group_manager.get_group_white_list()
+ x = [str(g) for g in x]
+ if x:
+ await show_group_whitelist.send("目前的群白名单:\n" + "\n".join(x))
+ else:
+ await show_group_whitelist.send("没有任何群在群白名单...")
+
+
+@group_auth.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json()).split()
+ for group_id in msg:
+ if not is_number(group_id):
+ await group_auth.send(f"{group_id}非纯数字,已跳过该项..")
+ group_id = int(group_id)
+ if state["_prefix"]["raw_command"][:2] == "添加":
+ if await GroupInfo.get_group_info(group_id):
+ await GroupInfo.set_group_flag(group_id, 1)
+ else:
+ try:
+ group_info = await bot.get_group_info(group_id=group_id)
+ except ActionFailed:
+ group_info = {
+ "group_id": group_id,
+ "group_name": "_",
+ "max_member_count": -1,
+ "member_count": -1,
+ }
+ await GroupInfo.add_group_info(
+ group_info["group_id"],
+ group_info["group_name"],
+ group_info["max_member_count"],
+ group_info["member_count"],
+ 1,
+ )
+ else:
+ if await GroupInfo.get_group_info(group_id):
+ await GroupInfo.set_group_flag(group_id, 0)
+ await group_auth.send(
+ f'已为 {group_id} {state["_prefix"]["raw_command"][:2]}群认证..'
+ )
diff --git a/basic_plugins/super_cmd/reload_setting.py b/basic_plugins/super_cmd/reload_setting.py
old mode 100644
new mode 100755
index b392f913..494ee819
--- a/basic_plugins/super_cmd/reload_setting.py
+++ b/basic_plugins/super_cmd/reload_setting.py
@@ -1,40 +1,40 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.rule import to_me
-from utils.manager import (
- plugins2cd_manager,
- plugins2settings_manager,
- plugins2block_manager,
- group_manager,
-)
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent
-
-
-__zx_plugin_name__ = "重载插件配置 [Superuser]"
-__plugin_usage__ = """
-usage:
- 重载插件配置
- 指令:
- 重载插件配置
-""".strip()
-__plugin_des__ = "重载插件配置"
-__plugin_cmd__ = [
- "重载插件配置",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-reload_plugins_manager = on_command(
- "重载插件限制", rule=to_me(), permission=SUPERUSER, priority=1, block=True
-)
-
-
-@reload_plugins_manager.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- plugins2settings_manager.reload()
- plugins2cd_manager.reload()
- plugins2block_manager.reload()
- group_manager.reload()
- await reload_plugins_manager.send("重载完成...")
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from nonebot.rule import to_me
+from utils.manager import (
+ plugins2cd_manager,
+ plugins2settings_manager,
+ plugins2block_manager,
+ group_manager,
+)
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+
+
+__zx_plugin_name__ = "重载插件配置 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 重载插件配置
+ 指令:
+ 重载插件配置
+""".strip()
+__plugin_des__ = "重载插件配置"
+__plugin_cmd__ = [
+ "重载插件配置",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+reload_plugins_manager = on_command(
+ "重载插件限制", rule=to_me(), permission=SUPERUSER, priority=1, block=True
+)
+
+
+@reload_plugins_manager.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ plugins2settings_manager.reload()
+ plugins2cd_manager.reload()
+ plugins2block_manager.reload()
+ group_manager.reload()
+ await reload_plugins_manager.send("重载完成...")
diff --git a/basic_plugins/super_cmd/set_admin_permissions.py b/basic_plugins/super_cmd/set_admin_permissions.py
old mode 100644
new mode 100755
index f075dd94..a375af6e
--- a/basic_plugins/super_cmd/set_admin_permissions.py
+++ b/basic_plugins/super_cmd/set_admin_permissions.py
@@ -1,89 +1,89 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from models.level_user import LevelUser
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, Message
-from utils.utils import get_message_at, get_message_text, is_number
-from services.log import logger
-from utils.message_builder import at
-
-__zx_plugin_name__ = "用户权限管理 [Superuser]"
-__plugin_usage__ = """
-usage:
- 增删改用户的权限
- 指令:
- 添加权限 [at] [权限]
- 添加权限 [qq] [group_id] [权限]
- 删除权限 [at]
-""".strip()
-__plugin_des__ = "增删改用户的权限"
-__plugin_cmd__ = [
- "添加权限 [at] [权限]",
- "添加权限 [qq] [group_id] [权限]",
- "删除权限 [at]",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-super_cmd = on_command(
- "添加管理",
- aliases={"删除管理", "添加权限", "删除权限"},
- priority=1,
- permission=SUPERUSER,
- block=True,
-)
-
-
-@super_cmd.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- group_id = -1
- level = 0
- try:
- args = get_message_text(event.json()).strip().split()
- qq = get_message_at(event.json())
- flag = -1
- if not qq:
- if len(args) > 2:
- if is_number(args[0]) and is_number(args[1]) and is_number(args[2]):
- qq = int(args[0])
- group_id = int(args[1])
- level = int(args[2])
- flag = 1
- else:
- await super_cmd.finish("所有参数必须是数字!", at_sender=True)
- else:
- await super_cmd.finish(
- "权限参数不完全\n\t格式:添加/删除权限 [at] [level]"
- "\n\t格式:添加/删除权限 [qq] [group] [level]",
- at_sender=True,
- )
- else:
- qq = qq[0]
- group_id = event.group_id
- flag = 2
- if state["_prefix"]["raw_command"][:2] == "添加":
- if is_number(args[0]):
- level = int(args[0])
- else:
- await super_cmd.finish("权限等级必须是数字!", at_sender=True)
- if await LevelUser.set_level(qq, group_id, level, 1):
- result = "添加管理成功, 权限: " + str(level)
- else:
- result = "管理已存在, 更新权限: " + str(level)
- else:
- if await LevelUser.delete_level(qq, event.group_id):
- result = "删除管理成功!"
- else:
- result = "该账号无管理权限!"
- if flag == 2:
- await super_cmd.send(result)
- elif flag == 1:
- await bot.send_group_msg(
- group_id=group_id,
- message=Message(f"{at(qq)}管理员修改了你的权限" f"\n--------\n你当前的权限等级:{level}"),
- )
- await super_cmd.send("修改成功")
- except Exception as e:
- await super_cmd.send("执行指令失败!")
- logger.error(f"执行指令失败 e:{e}")
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from models.level_user import LevelUser
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, Message
+from utils.utils import get_message_at, get_message_text, is_number
+from services.log import logger
+from utils.message_builder import at
+
+__zx_plugin_name__ = "用户权限管理 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 增删改用户的权限
+ 指令:
+ 添加权限 [at] [权限]
+ 添加权限 [qq] [group_id] [权限]
+ 删除权限 [at]
+""".strip()
+__plugin_des__ = "增删改用户的权限"
+__plugin_cmd__ = [
+ "添加权限 [at] [权限]",
+ "添加权限 [qq] [group_id] [权限]",
+ "删除权限 [at]",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+super_cmd = on_command(
+ "添加管理",
+ aliases={"删除管理", "添加权限", "删除权限"},
+ priority=1,
+ permission=SUPERUSER,
+ block=True,
+)
+
+
+@super_cmd.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ group_id = -1
+ level = 0
+ try:
+ args = get_message_text(event.json()).strip().split()
+ qq = get_message_at(event.json())
+ flag = -1
+ if not qq:
+ if len(args) > 2:
+ if is_number(args[0]) and is_number(args[1]) and is_number(args[2]):
+ qq = int(args[0])
+ group_id = int(args[1])
+ level = int(args[2])
+ flag = 1
+ else:
+ await super_cmd.finish("所有参数必须是数字!", at_sender=True)
+ else:
+ await super_cmd.finish(
+ "权限参数不完全\n\t格式:添加/删除权限 [at] [level]"
+ "\n\t格式:添加/删除权限 [qq] [group] [level]",
+ at_sender=True,
+ )
+ else:
+ qq = qq[0]
+ group_id = event.group_id
+ flag = 2
+ if state["_prefix"]["raw_command"][:2] == "添加":
+ if is_number(args[0]):
+ level = int(args[0])
+ else:
+ await super_cmd.finish("权限等级必须是数字!", at_sender=True)
+ if await LevelUser.set_level(qq, group_id, level, 1):
+ result = "添加管理成功, 权限: " + str(level)
+ else:
+ result = "管理已存在, 更新权限: " + str(level)
+ else:
+ if await LevelUser.delete_level(qq, event.group_id):
+ result = "删除管理成功!"
+ else:
+ result = "该账号无管理权限!"
+ if flag == 2:
+ await super_cmd.send(result)
+ elif flag == 1:
+ await bot.send_group_msg(
+ group_id=group_id,
+ message=Message(f"{at(qq)}管理员修改了你的权限" f"\n--------\n你当前的权限等级:{level}"),
+ )
+ await super_cmd.send("修改成功")
+ except Exception as e:
+ await super_cmd.send("执行指令失败!")
+ logger.error(f"执行指令失败 e:{e}")
diff --git a/basic_plugins/super_cmd/super_task_switch.py b/basic_plugins/super_cmd/super_task_switch.py
old mode 100644
new mode 100755
index 391d5778..01fb0eca
--- a/basic_plugins/super_cmd/super_task_switch.py
+++ b/basic_plugins/super_cmd/super_task_switch.py
@@ -1,56 +1,56 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent
-from nonebot.rule import to_me
-from utils.utils import get_message_text, is_number
-from services.log import logger
-from utils.manager import group_manager
-
-
-__zx_plugin_name__ = "超级用户被动开关 [Superuser]"
-__plugin_usage__ = """
-usage:
- 超级用户被动开关
- 指令:
- 开启/关闭广播通知
-""".strip()
-__plugin_des__ = "超级用户被动开关"
-__plugin_cmd__ = [
- "开启/关闭广播通知",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-oc_gb = on_command(
- "开启广播通知",
- aliases={"关闭广播通知"},
- rule=to_me(),
- permission=SUPERUSER,
- priority=1,
- block=True,
-)
-
-
-@oc_gb.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- group = get_message_text(event.json())
- if group:
- if is_number(group):
- group = int(group)
- for g in await bot.get_group_list():
- if g["group_id"] == group:
- break
- else:
- await oc_gb.finish("没有加入这个群...", at_sender=True)
- if state["_prefix"]["raw_command"] == "开启广播通知":
- logger.info(f"USER {event.user_id} 开启了 GROUP {group} 的广播")
- await oc_gb.finish(await group_manager.open_group_task(group, "broadcast",), at_sender=True)
- else:
- logger.info(f"USER {event.user_id} 关闭了 GROUP {group} 的广播")
- await oc_gb.finish(await group_manager.close_group_task(group, "broadcast"), at_sender=True)
- else:
- await oc_gb.finish("请输入正确的群号", at_sender=True)
- else:
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from nonebot.rule import to_me
+from utils.utils import get_message_text, is_number
+from services.log import logger
+from utils.manager import group_manager
+
+
+__zx_plugin_name__ = "超级用户被动开关 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 超级用户被动开关
+ 指令:
+ 开启/关闭广播通知
+""".strip()
+__plugin_des__ = "超级用户被动开关"
+__plugin_cmd__ = [
+ "开启/关闭广播通知",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+oc_gb = on_command(
+ "开启广播通知",
+ aliases={"关闭广播通知"},
+ rule=to_me(),
+ permission=SUPERUSER,
+ priority=1,
+ block=True,
+)
+
+
+@oc_gb.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ group = get_message_text(event.json())
+ if group:
+ if is_number(group):
+ group = int(group)
+ for g in await bot.get_group_list():
+ if g["group_id"] == group:
+ break
+ else:
+ await oc_gb.finish("没有加入这个群...", at_sender=True)
+ if state["_prefix"]["raw_command"] == "开启广播通知":
+ logger.info(f"USER {event.user_id} 开启了 GROUP {group} 的广播")
+ await oc_gb.finish(await group_manager.open_group_task(group, "broadcast",), at_sender=True)
+ else:
+ logger.info(f"USER {event.user_id} 关闭了 GROUP {group} 的广播")
+ await oc_gb.finish(await group_manager.close_group_task(group, "broadcast"), at_sender=True)
+ else:
+ await oc_gb.finish("请输入正确的群号", at_sender=True)
+ else:
await oc_gb.finish("请输入要关闭广播的群号", at_sender=True)
\ No newline at end of file
diff --git a/basic_plugins/super_cmd/update_friend_group_info.py b/basic_plugins/super_cmd/update_friend_group_info.py
old mode 100644
new mode 100755
index 091e89f8..273bdfe8
--- a/basic_plugins/super_cmd/update_friend_group_info.py
+++ b/basic_plugins/super_cmd/update_friend_group_info.py
@@ -1,71 +1,71 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent
-from nonebot.rule import to_me
-from utils.utils import get_bot
-from services.log import logger
-from models.group_info import GroupInfo
-from models.friend_user import FriendUser
-
-
-__zx_plugin_name__ = "更新群/好友信息 [Superuser]"
-__plugin_usage__ = """
-usage:
- 更新群/好友信息
- 指令:
- 更新群信息
- 更新好友信息
-""".strip()
-__plugin_des__ = "更新群/好友信息"
-__plugin_cmd__ = [
- "更新群信息",
- "更新好友信息",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-update_group_info = on_command(
- "更新群信息", rule=to_me(), permission=SUPERUSER, priority=1, block=True
-)
-update_friend_info = on_command(
- "更新好友信息", rule=to_me(), permission=SUPERUSER, priority=1, block=True
-)
-
-
-@update_group_info.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- num = 0
- rst = ""
- for g in gl:
- group_info = await bot.get_group_info(group_id=g)
- if await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- ):
- num += 1
- logger.info(f"自动更新群组 {g} 信息成功")
- else:
- logger.info(f"自动更新群组 {g} 信息失败")
- rst += f"{g} 更新失败\n"
- await update_group_info.send(f"成功更新了 {num} 个群的信息\n{rst[:-1]}")
-
-
-@update_friend_info.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- num = 0
- rst = ""
- fl = await get_bot().get_friend_list()
- for f in fl:
- if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
- logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
- num += 1
- else:
- logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
- rst += f'{f["user_id"]} 更新失败\n'
- await update_friend_info.send(f"成功更新了 {num} 个好友的信息\n{rst[:-1]}")
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from nonebot.rule import to_me
+from utils.utils import get_bot
+from services.log import logger
+from models.group_info import GroupInfo
+from models.friend_user import FriendUser
+
+
+__zx_plugin_name__ = "更新群/好友信息 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 更新群/好友信息
+ 指令:
+ 更新群信息
+ 更新好友信息
+""".strip()
+__plugin_des__ = "更新群/好友信息"
+__plugin_cmd__ = [
+ "更新群信息",
+ "更新好友信息",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+update_group_info = on_command(
+ "更新群信息", rule=to_me(), permission=SUPERUSER, priority=1, block=True
+)
+update_friend_info = on_command(
+ "更新好友信息", rule=to_me(), permission=SUPERUSER, priority=1, block=True
+)
+
+
+@update_group_info.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ bot = get_bot()
+ gl = await bot.get_group_list()
+ gl = [g["group_id"] for g in gl]
+ num = 0
+ rst = ""
+ for g in gl:
+ group_info = await bot.get_group_info(group_id=g)
+ if await GroupInfo.add_group_info(
+ group_info["group_id"],
+ group_info["group_name"],
+ group_info["max_member_count"],
+ group_info["member_count"],
+ ):
+ num += 1
+ logger.info(f"自动更新群组 {g} 信息成功")
+ else:
+ logger.info(f"自动更新群组 {g} 信息失败")
+ rst += f"{g} 更新失败\n"
+ await update_group_info.send(f"成功更新了 {num} 个群的信息\n{rst[:-1]}")
+
+
+@update_friend_info.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ num = 0
+ rst = ""
+ fl = await get_bot().get_friend_list()
+ for f in fl:
+ if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
+ logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
+ num += 1
+ else:
+ logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
+ rst += f'{f["user_id"]} 更新失败\n'
+ await update_friend_info.send(f"成功更新了 {num} 个好友的信息\n{rst[:-1]}")
diff --git a/basic_plugins/super_help/__init__.py b/basic_plugins/super_help/__init__.py
old mode 100644
new mode 100755
index 49aa7058..1bdbaf69
--- a/basic_plugins/super_help/__init__.py
+++ b/basic_plugins/super_help/__init__.py
@@ -1,30 +1,30 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.adapters import Bot, Event
-from nonebot.rule import to_me
-from configs.path_config import IMAGE_PATH
-from utils.message_builder import image
-from .data_source import create_help_image
-from pathlib import Path
-
-
-__zx_plugin_name__ = '超级用户帮助 [Superuser]'
-
-
-superuser_help_image = Path(IMAGE_PATH) / 'superuser_help.png'
-
-if superuser_help_image.exists():
- superuser_help_image.unlink()
-
-super_help = on_command(
- "超级用户帮助", rule=to_me(), priority=1, permission=SUPERUSER, block=True
-)
-
-
-@super_help.handle()
-async def _(bot: Bot, event: Event, state: T_State):
- if not superuser_help_image.exists():
- await create_help_image()
- x = image(superuser_help_image)
- await super_help.finish(x)
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from nonebot.adapters import Bot, Event
+from nonebot.rule import to_me
+from configs.path_config import IMAGE_PATH
+from utils.message_builder import image
+from .data_source import create_help_image
+from pathlib import Path
+
+
+__zx_plugin_name__ = '超级用户帮助 [Superuser]'
+
+
+superuser_help_image = Path(IMAGE_PATH) / 'superuser_help.png'
+
+if superuser_help_image.exists():
+ superuser_help_image.unlink()
+
+super_help = on_command(
+ "超级用户帮助", rule=to_me(), priority=1, permission=SUPERUSER, block=True
+)
+
+
+@super_help.handle()
+async def _(bot: Bot, event: Event, state: T_State):
+ if not superuser_help_image.exists():
+ await create_help_image()
+ x = image(superuser_help_image)
+ await super_help.finish(x)
diff --git a/basic_plugins/super_help/data_source.py b/basic_plugins/super_help/data_source.py
old mode 100644
new mode 100755
diff --git a/basic_plugins/update_info.py b/basic_plugins/update_info.py
old mode 100644
new mode 100755
index e86e82af..8d11d144
--- a/basic_plugins/update_info.py
+++ b/basic_plugins/update_info.py
@@ -1,35 +1,35 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, Event
-from nonebot.typing import T_State
-from utils.message_builder import image
-
-
-__zx_plugin_name__ = "更新信息"
-__plugin_usage__ = """
-usage:
- 更新信息
- 指令:
- 更新信息
-""".strip()
-__plugin_des__ = "当前版本的更新信息"
-__plugin_cmd__ = ["更新信息"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["更新信息"],
-}
-
-
-update_info = on_command("更新信息", aliases={"更新日志"}, priority=5, block=True)
-
-
-@update_info.handle()
-async def _(bot: Bot, event: Event, state: T_State):
- img = image("update_info.png")
- if img:
- await update_info.finish(image("update_info.png"))
- else:
- await update_info.finish("目前没有更新信息哦")
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, Event
+from nonebot.typing import T_State
+from utils.message_builder import image
+
+
+__zx_plugin_name__ = "更新信息"
+__plugin_usage__ = """
+usage:
+ 更新信息
+ 指令:
+ 更新信息
+""".strip()
+__plugin_des__ = "当前版本的更新信息"
+__plugin_cmd__ = ["更新信息"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["更新信息"],
+}
+
+
+update_info = on_command("更新信息", aliases={"更新日志"}, priority=5, block=True)
+
+
+@update_info.handle()
+async def _(bot: Bot, event: Event, state: T_State):
+ img = image("update_info.png")
+ if img:
+ await update_info.finish(image("update_info.png"))
+ else:
+ await update_info.finish("目前没有更新信息哦")
diff --git a/models/bag_user.py b/models/bag_user.py
old mode 100644
new mode 100755
diff --git a/models/ban_user.py b/models/ban_user.py
old mode 100644
new mode 100755
index 53f488dd..6c7322e2
--- a/models/ban_user.py
+++ b/models/ban_user.py
@@ -82,7 +82,7 @@ class BanUser(db.Model):
参数:
:param user_qq: 目标用户qq号
:param ban_level: 使用ban命令用户的权限
- :param duration: ban时长
+ :param duration: ban时长,秒
"""
query = cls.query.where((cls.user_qq == user_qq))
query = query.with_for_update()
diff --git a/models/friend_user.py b/models/friend_user.py
old mode 100644
new mode 100755
diff --git a/models/group_info.py b/models/group_info.py
old mode 100644
new mode 100755
diff --git a/models/group_member_info.py b/models/group_member_info.py
old mode 100644
new mode 100755
diff --git a/models/level_user.py b/models/level_user.py
old mode 100644
new mode 100755
diff --git a/models/sign_group_user.py b/models/sign_group_user.py
old mode 100644
new mode 100755
diff --git a/plugins/Yu-Gi-Oh/__init__.py b/plugins/Yu-Gi-Oh/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/plugins/__init__.py b/plugins/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/aconfig/__init__.py b/plugins/aconfig/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/ai/__init__.py b/plugins/ai/__init__.py
old mode 100644
new mode 100755
index fc55b73e..673844dd
--- a/plugins/ai/__init__.py
+++ b/plugins/ai/__init__.py
@@ -24,8 +24,6 @@ __plugin_version__ = 0.1
__plugin_author__ = 'HibiKier'
__plugin_settings__ = {
"level": 5,
- "default_status": True,
- "limit_superuser": False,
"cmd": ["Ai", "ai", "AI", "aI"],
}
__plugin_configs__ = {
diff --git a/plugins/ai/data_source.py b/plugins/ai/data_source.py
old mode 100644
new mode 100755
index 1cbbb2dc..13c8d630
--- a/plugins/ai/data_source.py
+++ b/plugins/ai/data_source.py
@@ -1,13 +1,12 @@
import os
import random
import re
-
-import aiohttp
-from aiohttp.client import ClientSession
+from utils.http_utils import AsyncHttpx
from configs.path_config import IMAGE_PATH, DATA_PATH
from services.log import logger
from utils.message_builder import image, face
from configs.config import Config, NICKNAME
+from .utils import ai_message_manager
try:
import ujson as json
@@ -26,7 +25,7 @@ anime_data = json.load(open(DATA_PATH + "anime.json", "r", encoding="utf8"))
async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str) -> str:
"""
- 获取 AI 返回值,顺序:图灵 -> 青云客
+ 获取 AI 返回值,顺序: 特殊回复 -> 图灵 -> 青云客
:param text: 问题
:param img_url: 图片链接
:param user_id: 用户id
@@ -34,6 +33,11 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
:return: 回答
"""
global index
+ ai_message_manager.add_message(user_id, text)
+ special_rst = await ai_message_manager.get_result(user_id, nickname)
+ if special_rst:
+ ai_message_manager.add_result(user_id, special_rst)
+ return special_rst
if index == 5:
index = 0
if len(text) < 6 and random.random() < 0.6:
@@ -41,10 +45,9 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
for key in keys:
if text.find(key) != -1:
return random.choice(anime_data[key]).replace("你", nickname)
- async with aiohttp.ClientSession() as sess:
- rst = await tu_ling(text, img_url, user_id, sess)
- if not rst:
- rst = await xie_ai(text, sess)
+ rst = await tu_ling(text, img_url, user_id)
+ if not rst:
+ rst = await xie_ai(text)
if not rst:
return no_result()
if nickname:
@@ -55,23 +58,25 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
if nickname.find("大人") == -1:
nickname += "大~人~"
rst = rst.replace("小主人", nickname).replace("小朋友", nickname)
+ ai_message_manager.add_result(user_id, rst)
+ print(ai_message_manager)
return rst
# 图灵接口
-async def tu_ling(text: str, img_url: str, user_id: int, sess: ClientSession) -> str:
+async def tu_ling(text: str, img_url: str, user_id: int) -> str:
"""
获取图灵接口的回复
:param text: 问题
:param img_url: 图片链接
:param user_id: 用户id
- :param sess: AIOHTTP SESSION
:return: 图灵回复
"""
global index
TL_KEY = Config.get_config("ai", "TL_KEY")
+ req = None
if not TL_KEY:
- return ''
+ return ""
try:
if text:
req = {
@@ -98,62 +103,59 @@ async def tu_ling(text: str, img_url: str, user_id: int, sess: ClientSession) ->
index = 0
return ""
text = ""
- async with sess.post(url, json=req) as response:
- if response.status != 200:
- return no_result()
- resp_payload = json.loads(await response.text())
- if int(resp_payload["intent"]["code"]) in [4003]:
- return ""
- if resp_payload["results"]:
- for result in resp_payload["results"]:
- if result["resultType"] == "text":
- text = result["values"]["text"]
- if "请求次数超过" in text:
- text = ""
+ response = await AsyncHttpx.post(url, json=req)
+ if response.status_code != 200:
+ return no_result()
+ resp_payload = json.loads(response.text)
+ if int(resp_payload["intent"]["code"]) in [4003]:
+ return ""
+ if resp_payload["results"]:
+ for result in resp_payload["results"]:
+ if result["resultType"] == "text":
+ text = result["values"]["text"]
+ if "请求次数超过" in text:
+ text = ""
return text
# 屑 AI
-async def xie_ai(text: str, sess: ClientSession) -> str:
+async def xie_ai(text: str) -> str:
"""
获取青云客回复
:param text: 问题
- :param sess: AIOHTTP SESSION
:return: 青云可回复
"""
- async with sess.get(
- f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}"
- ) as res:
- content = ""
- data = json.loads(await res.text())
- if data["result"] == 0:
- content = data["content"]
- if "菲菲" in content:
- content = content.replace("菲菲", NICKNAME)
- if "艳儿" in content:
- content = content.replace("艳儿", NICKNAME)
- if "公众号" in content:
- content = ""
- if "{br}" in content:
- content = content.replace("{br}", "\n")
- if "提示" in content:
- content = content[: content.find("提示")]
- if "淘宝" in content:
- return ""
- while True:
- r = re.search("{face:(.*)}", content)
- if r:
- id_ = r.group(1)
- content = content.replace(
- "{" + f"face:{id_}" + "}", str(face(int(id_)))
- )
- else:
- break
- return (
- content
- if not content and not Config.get_config("ai", "ALAPI_AI_CHECK")
- else await check_text(content, sess)
- )
+ res = await AsyncHttpx.get(f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}")
+ content = ""
+ data = json.loads(res.text)
+ if data["result"] == 0:
+ content = data["content"]
+ if "菲菲" in content:
+ content = content.replace("菲菲", NICKNAME)
+ if "艳儿" in content:
+ content = content.replace("艳儿", NICKNAME)
+ if "公众号" in content:
+ content = ""
+ if "{br}" in content:
+ content = content.replace("{br}", "\n")
+ if "提示" in content:
+ content = content[: content.find("提示")]
+ if "淘宝" in content:
+ return ""
+ while True:
+ r = re.search("{face:(.*)}", content)
+ if r:
+ id_ = r.group(1)
+ content = content.replace(
+ "{" + f"face:{id_}" + "}", str(face(int(id_)))
+ )
+ else:
+ break
+ return (
+ content
+ if not content and not Config.get_config("ai", "ALAPI_AI_CHECK")
+ else await check_text(content)
+ )
def hello() -> str:
@@ -196,21 +198,19 @@ def no_result() -> str:
)
-async def check_text(text: str, sess: ClientSession) -> str:
+async def check_text(text: str) -> str:
"""
ALAPI文本检测,主要针对青云客API,检测为恶俗文本改为无回复的回答
:param text: 回复
- :param sess: AIOHTTP SESSION
"""
if not Config.get_config("alapi", "ALAPI_TOKEN"):
return text
params = {"token": Config.get_config("alapi", "ALAPI_TOKEN"), "text": text}
try:
- async with sess.get(check_url, timeout=2, params=params) as response:
- data = await response.json()
- if data["code"] == 200:
- if data["data"]["conclusion_type"] == 2:
- return ""
+ data = (await AsyncHttpx.get(check_url, timeout=2, params=params)).json()
+ if data["code"] == 200:
+ if data["data"]["conclusion_type"] == 2:
+ return ""
except Exception as e:
logger.error(f"检测违规文本错误...{type(e)}:{e}")
return text
diff --git a/plugins/ai/utils.py b/plugins/ai/utils.py
new file mode 100755
index 00000000..ebd4f6d8
--- /dev/null
+++ b/plugins/ai/utils.py
@@ -0,0 +1,137 @@
+from utils.manager import StaticData
+from configs.config import NICKNAME
+from models.ban_user import BanUser
+from typing import Optional
+import random
+import time
+
+
+class AiMessageManager(StaticData):
+ def __init__(self):
+ super().__init__(None)
+ self._same_message = [
+ "为什么要发一样的话?",
+ "请不要再重复对我说一句话了,不然我就要生气了!",
+ "别再发这句话了,我已经知道了...",
+ "你是只会说这一句话吗?",
+ "[*],你发我也发!",
+ "[uname],[*]",
+ f"救命!有笨蛋一直给{NICKNAME}发一样的话!",
+ "这句话你已经给我发了{}次了,再发就生气!",
+ ]
+ self._repeat_message = [
+ f"请不要学{NICKNAME}说话",
+ f"为什么要一直学{NICKNAME}说话?",
+ "你再学!你再学我就生气了!",
+ f"呜呜,你是想欺负{NICKNAME}嘛..",
+ "[uname]不要再学我说话了!",
+ "再学我说话,我就把你拉进黑名单(生气",
+ "你再学![uname]是个笨蛋!",
+ "你已经学我说话{}次了!别再学了!",
+ ]
+
+ def add_message(self, user_id: int, message: str):
+ """
+ 添加用户消息
+ :param user_id: 用户id
+ :param message: 消息内容
+ """
+ if message:
+ if self._data.get(user_id) is None:
+ self._data[user_id] = {
+ "time": time.time(),
+ "message": [],
+ "result": [],
+ "repeat_count": 0,
+ }
+ if time.time() - self._data[user_id]["time"] > 60 * 10:
+ self._data[user_id]["message"].clear()
+ self._data[user_id]["time"] = time.time()
+ self._data[user_id]["message"].append(message.strip())
+
+ def add_result(self, user_id: int, message: str):
+ """
+ 添加回复用户的消息
+ :param user_id: 用户id
+ :param message: 回复消息内容
+ """
+ if message:
+ if self._data.get(user_id) is None:
+ self._data[user_id] = {
+ "time": time.time(),
+ "message": [],
+ "result": [],
+ "repeat_count": 0,
+ }
+ if time.time() - self._data[user_id]["time"] > 60 * 10:
+ self._data[user_id]["result"].clear()
+ self._data[user_id]["repeat_count"] = 0
+ self._data[user_id]["time"] = time.time()
+ self._data[user_id]["result"].append(message.strip())
+
+ async def get_result(self, user_id: int, nickname: str) -> Optional[str]:
+ """
+ 特殊消息特殊回复
+ :param user_id: 用户id
+ :param nickname: 用户昵称
+ """
+ if len(self._data[user_id]["message"]) < 2:
+ return None
+ msg = await self._get_user_repeat_message_result(user_id)
+ if not msg:
+ msg = await self._get_user_same_message_result(user_id)
+ if msg:
+ if "[uname]" in msg:
+ msg = msg.replace("[uname]", nickname)
+ if not msg.startswith("生气了!你好烦,闭嘴!") and "[*]" in msg:
+ msg = msg.replace("[*]", self._data[user_id]["message"][-1])
+ return msg
+
+ async def _get_user_same_message_result(self, user_id: int) -> Optional[str]:
+ """
+ 重复消息回复
+ :param user_id: 用户id
+ """
+ msg = self._data[user_id]["message"][-1]
+ cnt = 0
+ _tmp = self._data[user_id]["message"][:-1]
+ _tmp.reverse()
+ for s in _tmp:
+ if s == msg:
+ cnt += 1
+ else:
+ break
+ if cnt > 1:
+ if random.random() < 0.5 and cnt > 3:
+ rand = random.randint(60, 300)
+ await BanUser.ban(user_id, 9, rand)
+ self._data[user_id]["message"].clear()
+ return f"生气了!你好烦,闭嘴!给我老实安静{rand}秒"
+ return random.choice(self._same_message).format(cnt)
+ return None
+
+ async def _get_user_repeat_message_result(self, user_id: int) -> Optional[str]:
+ """
+ 复读真寻的消息回复
+ :param user_id: 用户id
+ """
+ msg = self._data[user_id]["message"][-1]
+ if self._data[user_id]["result"]:
+ rst = self._data[user_id]["result"][-1]
+ else:
+ return None
+ if msg == rst:
+ self._data[user_id]["repeat_count"] += 1
+ cnt = self._data[user_id]["repeat_count"]
+ if cnt > 1:
+ if random.random() < 0.5 and cnt > 3:
+ rand = random.randint(60, 300)
+ await BanUser.ban(user_id, 9, rand)
+ self._data[user_id]["result"].clear()
+ self._data[user_id]["repeat_count"] = 0
+ return f"生气了!你好烦,闭嘴!给我老实安静{rand}秒"
+ return random.choice(self._repeat_message).format(cnt)
+ return None
+
+
+ai_message_manager = AiMessageManager()
diff --git a/plugins/alapi/__init__.py b/plugins/alapi/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/alapi/comments_163.py b/plugins/alapi/comments_163.py
old mode 100644
new mode 100755
index b88cc643..ac43c1d2
--- a/plugins/alapi/comments_163.py
+++ b/plugins/alapi/comments_163.py
@@ -1,46 +1,46 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.typing import T_State
-from .data_source import get_data
-from services.log import logger
-
-__zx_plugin_name__ = "网易云热评"
-__plugin_usage__ = """
-usage:
- 到点了,还是防不了下塔
- 指令:
- 网易云热评/到点了/12点了
-""".strip()
-__plugin_des__ = "生了个人,我很抱歉"
-__plugin_cmd__ = ["网易云热评", "到点了", "12点了"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["网易云热评", "网易云评论", "到点了", "12点了"],
-}
-
-
-comments_163 = on_command(
- "网易云热评", aliases={"网易云评论", "到点了", "12点了"}, priority=5, block=True
-)
-
-
-comments_163_url = "https://v2.alapi.cn/api/comment"
-
-
-@comments_163.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- data, code = await get_data(comments_163_url)
- if code != 200:
- await comments_163.finish(data, at_sender=True)
- data = data["data"]
- comment = data["comment_content"]
- song_name = data["title"]
- await comments_163.send(f"{comment}\n\t——《{song_name}》")
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送网易云热评: {comment} \n\t\t————{song_name}"
- )
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot.typing import T_State
+from .data_source import get_data
+from services.log import logger
+
+__zx_plugin_name__ = "网易云热评"
+__plugin_usage__ = """
+usage:
+ 到点了,还是防不了下塔
+ 指令:
+ 网易云热评/到点了/12点了
+""".strip()
+__plugin_des__ = "生了个人,我很抱歉"
+__plugin_cmd__ = ["网易云热评", "到点了", "12点了"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["网易云热评", "网易云评论", "到点了", "12点了"],
+}
+
+
+comments_163 = on_command(
+ "网易云热评", aliases={"网易云评论", "到点了", "12点了"}, priority=5, block=True
+)
+
+
+comments_163_url = "https://v2.alapi.cn/api/comment"
+
+
+@comments_163.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ data, code = await get_data(comments_163_url)
+ if code != 200:
+ await comments_163.finish(data, at_sender=True)
+ data = data["data"]
+ comment = data["comment_content"]
+ song_name = data["title"]
+ await comments_163.send(f"{comment}\n\t——《{song_name}》")
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送网易云热评: {comment} \n\t\t————{song_name}"
+ )
diff --git a/plugins/alapi/cover.py b/plugins/alapi/cover.py
old mode 100644
new mode 100755
index 8d0ce8c9..9f83a452
--- a/plugins/alapi/cover.py
+++ b/plugins/alapi/cover.py
@@ -1,48 +1,48 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
-from nonebot.typing import T_State
-from utils.message_builder import image
-from utils.utils import get_message_text
-from .data_source import get_data
-from services.log import logger
-
-__zx_plugin_name__ = "b封面"
-__plugin_usage__ = """
-usage:
- b封面 [链接/av/bv/cv/直播id]
- 示例:b封面 av86863038
-""".strip()
-__plugin_des__ = "快捷的b站视频封面获取方式"
-__plugin_cmd__ = ["b封面/B封面"]
-__plugin_type__ = ("一些工具",)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["b封面", "B封面"],
-}
-
-
-cover = on_command("b封面", aliases={"B封面"}, priority=5, block=True)
-
-
-cover_url = "https://v2.alapi.cn/api/bilibili/cover"
-
-
-@cover.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- params = {"c": msg}
- data, code = await get_data(cover_url, params)
- if code != 200:
- await cover.finish(data, at_sender=True)
- data = data["data"]
- title = data["title"]
- img = data["cover"]
- await cover.send(Message(f"title:{title}\n{image(img)}"))
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 获取b站封面: {title} url:{img}"
- )
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
+from nonebot.typing import T_State
+from utils.message_builder import image
+from utils.utils import get_message_text
+from .data_source import get_data
+from services.log import logger
+
+__zx_plugin_name__ = "b封面"
+__plugin_usage__ = """
+usage:
+ b封面 [链接/av/bv/cv/直播id]
+ 示例:b封面 av86863038
+""".strip()
+__plugin_des__ = "快捷的b站视频封面获取方式"
+__plugin_cmd__ = ["b封面/B封面"]
+__plugin_type__ = ("一些工具",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["b封面", "B封面"],
+}
+
+
+cover = on_command("b封面", aliases={"B封面"}, priority=5, block=True)
+
+
+cover_url = "https://v2.alapi.cn/api/bilibili/cover"
+
+
+@cover.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ params = {"c": msg}
+ data, code = await get_data(cover_url, params)
+ if code != 200:
+ await cover.finish(data, at_sender=True)
+ data = data["data"]
+ title = data["title"]
+ img = data["cover"]
+ await cover.send(Message(f"title:{title}\n{image(img)}"))
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 获取b站封面: {title} url:{img}"
+ )
diff --git a/plugins/alapi/data_source.py b/plugins/alapi/data_source.py
old mode 100644
new mode 100755
index 0571e802..ad853dec
--- a/plugins/alapi/data_source.py
+++ b/plugins/alapi/data_source.py
@@ -1,51 +1,49 @@
-from nonebot.adapters.cqhttp import MessageSegment
-from utils.image_utils import CreateImg
-from utils.message_builder import image
-from configs.path_config import IMAGE_PATH
-from typing import Optional
-from configs.config import Config
-import aiohttp
-
-
-async def get_data(url: str, params: Optional[dict] = None) -> "Union[dict, str], int":
- """
- 获取ALAPI数据
- :param url: 请求链接
- :param params: 参数
- """
- if not params:
- params = {}
- params["token"] = Config.get_config("alapi", "ALAPI_TOKEN")
- async with aiohttp.ClientSession() as session:
- try:
- async with session.get(url, timeout=2, params=params) as response:
- data = await response.json()
- if data["code"] == 200:
- if not data["data"]:
- return "没有搜索到...", 997
- return data, 200
- else:
- return f'发生了错误...code:{data["code"]}', 999
- except TimeoutError:
- return "超时了....", 998
-
-
-def gen_wbtop_pic(data: dict) -> MessageSegment:
- """
- 生成微博热搜图片
- :param data: 微博热搜数据
- """
- bk = CreateImg(700, 32 * 50 + 280, 700, 32, color="#797979")
- wbtop_bk = CreateImg(700, 280, background=f"{IMAGE_PATH}/other/webtop.png")
- bk.paste(wbtop_bk)
- text_bk = CreateImg(700, 32 * 50, 700, 32, color="#797979")
- for i, data in enumerate(data):
- title = f"{i+1}. {data['hot_word']}"
- hot = data["hot_word_num"]
- img = CreateImg(700, 30, font_size=20)
- w, h = img.getsize(title)
- img.text((10, int((30 - h) / 2)), title)
- img.text((580, int((30 - h) / 2)), hot)
- text_bk.paste(img)
- bk.paste(text_bk, (0, 280))
- return image(b64=bk.pic2bs4())
+from nonebot.adapters.cqhttp import MessageSegment
+from utils.image_utils import CreateImg
+from utils.message_builder import image
+from configs.path_config import IMAGE_PATH
+from typing import Optional
+from configs.config import Config
+from utils.http_utils import AsyncHttpx
+
+
+async def get_data(url: str, params: Optional[dict] = None) -> "Union[dict, str], int":
+ """
+ 获取ALAPI数据
+ :param url: 请求链接
+ :param params: 参数
+ """
+ if not params:
+ params = {}
+ params["token"] = Config.get_config("alapi", "ALAPI_TOKEN")
+ try:
+ data = (await AsyncHttpx.get(url, params=params, timeout=5)).json()
+ if data["code"] == 200:
+ if not data["data"]:
+ return "没有搜索到...", 997
+ return data, 200
+ else:
+ return f'发生了错误...code:{data["code"]}', 999
+ except TimeoutError:
+ return "超时了....", 998
+
+
+def gen_wbtop_pic(data: dict) -> MessageSegment:
+ """
+ 生成微博热搜图片
+ :param data: 微博热搜数据
+ """
+ bk = CreateImg(700, 32 * 50 + 280, 700, 32, color="#797979")
+ wbtop_bk = CreateImg(700, 280, background=f"{IMAGE_PATH}/other/webtop.png")
+ bk.paste(wbtop_bk)
+ text_bk = CreateImg(700, 32 * 50, 700, 32, color="#797979")
+ for i, data in enumerate(data):
+ title = f"{i+1}. {data['hot_word']}"
+ hot = data["hot_word_num"]
+ img = CreateImg(700, 30, font_size=20)
+ w, h = img.getsize(title)
+ img.text((10, int((30 - h) / 2)), title)
+ img.text((580, int((30 - h) / 2)), hot)
+ text_bk.paste(img)
+ bk.paste(text_bk, (0, 280))
+ return image(b64=bk.pic2bs4())
diff --git a/plugins/alapi/jitang.py b/plugins/alapi/jitang.py
new file mode 100755
index 00000000..3fe58ab7
--- /dev/null
+++ b/plugins/alapi/jitang.py
@@ -0,0 +1,48 @@
+from nonebot import on_command
+from services.log import logger
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot.typing import T_State
+from utils.http_utils import AsyncHttpx
+from configs.config import Config
+from .data_source import get_data
+
+
+__zx_plugin_name__ = "鸡汤"
+__plugin_usage__ = """
+usage:
+ 不喝点什么感觉有点不舒服
+ 指令:
+ 鸡汤
+""".strip()
+__plugin_des__ = "喏,亲手为你煮的鸡汤"
+__plugin_cmd__ = ["鸡汤"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["鸡汤", "毒鸡汤"],
+}
+
+url = "https://v2.alapi.cn/api/soul"
+
+
+jitang = on_command("鸡汤", aliases={"毒鸡汤"}, priority=5, block=True)
+
+
+@jitang.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ try:
+ data, code = await get_data(url)
+ if code != 200:
+ await jitang.finish(data, at_sender=True)
+ await jitang.send(data["data"]["content"])
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送鸡汤:" + data["data"]["content"]
+ )
+ except Exception as e:
+ await jitang.send("鸡汤煮坏掉了...")
+ logger.error(f"鸡汤煮坏掉了 {type(e)}:{e}")
diff --git a/plugins/alapi/poetry.py b/plugins/alapi/poetry.py
old mode 100644
new mode 100755
index 05395c2c..8773117b
--- a/plugins/alapi/poetry.py
+++ b/plugins/alapi/poetry.py
@@ -1,42 +1,42 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.typing import T_State
-from services.log import logger
-from .data_source import get_data
-
-__zx_plugin_name__ = "古诗"
-__plugin_usage__ = """usage:
- 平白无故念首诗
- 示例:念诗/来首诗/念首诗
-"""
-__plugin_des__ = "为什么突然文艺起来了!"
-__plugin_cmd__ = ["念诗/来首诗/念首诗"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["念诗", "来首诗", "念首诗"],
-}
-
-poetry = on_command("念诗", aliases={"来首诗", "念首诗"}, priority=5, block=True)
-
-
-poetry_url = "https://v2.alapi.cn/api/shici"
-
-
-@poetry.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- data, code = await get_data(poetry_url)
- if code != 200:
- await poetry.finish(data, at_sender=True)
- data = data["data"]
- content = data["content"]
- title = data["origin"]
- author = data["author"]
- await poetry.send(f"{content}\n\t——{author}《{title}》")
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送古诗: f'{content}\n\t--{author}《{title}》'"
- )
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot.typing import T_State
+from services.log import logger
+from .data_source import get_data
+
+__zx_plugin_name__ = "古诗"
+__plugin_usage__ = """usage:
+ 平白无故念首诗
+ 示例:念诗/来首诗/念首诗
+"""
+__plugin_des__ = "为什么突然文艺起来了!"
+__plugin_cmd__ = ["念诗/来首诗/念首诗"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["念诗", "来首诗", "念首诗"],
+}
+
+poetry = on_command("念诗", aliases={"来首诗", "念首诗"}, priority=5, block=True)
+
+
+poetry_url = "https://v2.alapi.cn/api/shici"
+
+
+@poetry.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ data, code = await get_data(poetry_url)
+ if code != 200:
+ await poetry.finish(data, at_sender=True)
+ data = data["data"]
+ content = data["content"]
+ title = data["origin"]
+ author = data["author"]
+ await poetry.send(f"{content}\n\t——{author}《{title}》")
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送古诗: f'{content}\n\t--{author}《{title}》'"
+ )
diff --git a/plugins/alapi/wbtop.py b/plugins/alapi/wbtop.py
old mode 100644
new mode 100755
index e367e533..9d7ced17
--- a/plugins/alapi/wbtop.py
+++ b/plugins/alapi/wbtop.py
@@ -1,76 +1,71 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.typing import T_State
-from services.log import logger
-from .data_source import get_data, gen_wbtop_pic
-from utils.browser import get_browser
-from utils.utils import get_message_text, is_number
-from configs.path_config import IMAGE_PATH
-from utils.message_builder import image
-import asyncio
-
-__zx_plugin_name__ = '微博热搜'
-__plugin_usage__ = """
-usage:
- 在QQ上吃个瓜
- 指令:
- 微博热搜:发送实时热搜
- 微博热搜 [id]:截图该热搜页面
- 示例:微博热搜 5
-""".strip()
-__plugin_des__ = '刚买完瓜,在吃瓜现场'
-__plugin_cmd__ = ['微博热搜', '微博热搜 [id]']
-__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ['微博热搜'],
-}
-
-wbtop = on_command("wbtop", aliases={'微博热搜'}, priority=5, block=True)
-
-
-wbtop_url = 'https://v2.alapi.cn/api/new/wbtop'
-
-wbtop_data = []
-
-
-@wbtop.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- global wbtop_data
- msg = get_message_text(event.json())
- if not wbtop_data or not msg:
- data, code = await get_data(wbtop_url)
- if code != 200:
- await wbtop.finish(data, at_sender=True)
- wbtop_data = data['data']
- if not msg:
- img = await asyncio.get_event_loop().run_in_executor(None, gen_wbtop_pic, wbtop_data)
- await wbtop.send(img)
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查询微博热搜")
- if is_number(msg) and 0 < int(msg) <= 50:
- url = wbtop_data[int(msg) - 1]['url']
- browser = await get_browser()
- page = None
- try:
- if not browser:
- logger.warning('获取 browser 失败,请部署至 linux 环境....')
- await wbtop.finish('获取 browser 对象失败...')
- page = await browser.new_page()
- await page.goto(url, wait_until='networkidle', timeout=10000)
- await page.set_viewport_size({"width": 2560, "height": 1080})
- await asyncio.sleep(5)
- div = await page.query_selector("#pl_feedlist_index")
- await div.screenshot(path=f'{IMAGE_PATH}/temp/wbtop_{event.user_id}.png', timeout=100000)
- await page.close()
- await wbtop.send(image(f'wbtop_{event.user_id}.png', 'temp'))
- except Exception as e:
- logger.error(f'微博热搜截图出错... {type(e)}: {e}')
- if page:
- await page.close()
- await wbtop.send('发生了一些错误.....')
-
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot.typing import T_State
+from services.log import logger
+from .data_source import get_data, gen_wbtop_pic
+from utils.utils import get_message_text, is_number
+from configs.path_config import IMAGE_PATH
+from utils.message_builder import image
+from utils.http_utils import AsyncPlaywright
+import asyncio
+
+__zx_plugin_name__ = "微博热搜"
+__plugin_usage__ = """
+usage:
+ 在QQ上吃个瓜
+ 指令:
+ 微博热搜:发送实时热搜
+ 微博热搜 [id]:截图该热搜页面
+ 示例:微博热搜 5
+""".strip()
+__plugin_des__ = "刚买完瓜,在吃瓜现场"
+__plugin_cmd__ = ["微博热搜", "微博热搜 [id]"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["微博热搜"],
+}
+
+wbtop = on_command("wbtop", aliases={"微博热搜"}, priority=5, block=True)
+
+
+wbtop_url = "https://v2.alapi.cn/api/new/wbtop"
+
+wbtop_data = []
+
+
+@wbtop.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ global wbtop_data
+ msg = get_message_text(event.json())
+ if not wbtop_data or not msg:
+ data, code = await get_data(wbtop_url)
+ if code != 200:
+ await wbtop.finish(data, at_sender=True)
+ wbtop_data = data["data"]
+ if not msg:
+ img = await asyncio.get_event_loop().run_in_executor(
+ None, gen_wbtop_pic, wbtop_data
+ )
+ await wbtop.send(img)
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 查询微博热搜"
+ )
+ if is_number(msg) and 0 < int(msg) <= 50:
+ url = wbtop_data[int(msg) - 1]["url"]
+ try:
+ await wbtop.send("开始截取数据...")
+ img = await AsyncPlaywright.screenshot(
+ url,
+ f"{IMAGE_PATH}/temp/wbtop_{event.user_id}.png",
+ "#pl_feedlist_index",
+ sleep=5
+ )
+ await wbtop.send(img)
+ except Exception as e:
+ logger.error(f"微博热搜截图出错... {type(e)}: {e}")
+ await wbtop.send("发生了一些错误.....")
diff --git a/plugins/bilibili_sub/__init__.py b/plugins/bilibili_sub/__init__.py
old mode 100644
new mode 100755
index 6ee0138c..32697051
--- a/plugins/bilibili_sub/__init__.py
+++ b/plugins/bilibili_sub/__init__.py
@@ -1,235 +1,236 @@
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
-from .data_source import (
- add_live_sub,
- delete_sub,
- add_up_sub,
- add_season_sub,
- get_media_id,
- get_sub_status,
- SubManager,
- BilibiliSub
-)
-from models.level_user import LevelUser
-from configs.config import Config
-from utils.utils import get_message_text, is_number, scheduler, get_bot
-from typing import Optional
-from services.log import logger
-from nonebot import Driver
-import nonebot
-
-__zx_plugin_name__ = "B站订阅"
-__plugin_usage__ = """
-usage:
- B站直播,番剧,UP动态开播等提醒
- 主播订阅相当于 直播间订阅 + UP订阅
- 指令:[示例Id乱打的,仅做示例]
- 添加订阅 ['主播'/'UP'/'番剧'] [id/链接/番名]
- 删除订阅 [id]
- 查看订阅
- 示例:添加订阅主播 2345344 <-(直播房间id)
- 示例:添加订阅UP 2355543 <-(个人主页id)
- 示例:添加订阅番剧 史莱姆 <-(支持模糊搜索)
- 示例:添加订阅番剧 125344 <-(番剧id)
- 示例:删除订阅 2324344 <-(任意id,通过查看订阅获取)
-""".strip()
-__plugin_des__ = "非常便利的B站订阅通知"
-__plugin_cmd__ = ["添加订阅 [主播/UP/番剧] [id/链接/番名]", "删除订阅 [id]", "查看订阅"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["B站订阅", "b站订阅", "添加订阅", "删除订阅", "查看订阅"],
-}
-__plugin_configs__ = {
- "GROUP_BILIBILI_SUB_LEVEL": {
- "value": 5,
- "help": "群内bilibili订阅需要管理的权限",
- "default_value": 5,
- }
-}
-
-add_sub = on_command("添加订阅", priority=5, block=True)
-del_sub = on_command("删除订阅", priority=5, block=True)
-show_sub_info = on_command("查看订阅", priority=5, block=True)
-
-driver: Driver = nonebot.get_driver()
-
-
-sub_manager: Optional[SubManager] = None
-
-
-@driver.on_startup
-async def _():
- global sub_manager
- sub_manager = SubManager()
-
-
-@add_sub.args_parser
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- season_data = state["season_data"]
- msg = get_message_text(event.json())
- if not is_number(msg) or int(msg) < 1 or int(msg) > len(season_data):
- await add_sub.reject("Id必须为数字且在范围内!请重新输入...")
- state["id"] = season_data[int(msg) - 1]["media_id"]
-
-
-@add_sub.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json()).split()
- if len(msg) < 2:
- await add_sub.finish("参数不完全,请查看订阅帮助...")
- sub_type = msg[0]
- id_ = ""
- if isinstance(event, GroupMessageEvent):
- if not await LevelUser.check_level(
- event.user_id,
- event.group_id,
- Config.get_config("bilibili_sub", "GROUP_BILIBILI_SUB_LEVEL"),
- ):
- await add_sub.finish(
- f"您的权限不足,群内订阅的需要 {Config.get_config('bilibili_sub', 'GROUP_BILIBILI_SUB_LEVEL')} 级权限..",
- at_sender=True,
- )
- sub_user = f"{event.user_id}:{event.group_id}"
- else:
- sub_user = f"{event.user_id}"
- state["sub_type"] = sub_type
- state["sub_user"] = sub_user
- if len(msg) > 1:
- if "http" in msg[1]:
- msg[1] = msg[1].split("?")[0]
- msg[1] = msg[1][:-1] if msg[1][-1] == "/" else msg[1]
- msg[1] = msg[1].split("/")[-1]
- id_ = msg[1][2:] if msg[1].startswith("md") else msg[1]
- if not is_number(id_):
- if sub_type in ["season", "动漫", "番剧"]:
- rst = "*以为您找到以下番剧,请输入Id选择:*\n"
- state["season_data"] = await get_media_id(id_)
- if len(state["season_data"]) == 0:
- await add_sub.finish(f"未找到番剧:{msg}")
- for i, x in enumerate(state["season_data"]):
- rst += f'{i + 1}.{state["season_data"][x]["title"]}\n----------\n'
- await add_sub.send("\n".join(rst.split("\n")[:-1]))
- else:
- await add_sub.finish("Id 必须为全数字!")
- else:
- state["id"] = int(id_)
-
-
-@add_sub.got("id")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- sub_type = state["sub_type"]
- sub_user = state["sub_user"]
- id_ = state["id"]
- if sub_type in ["主播", "直播"]:
- await add_sub.send(await add_live_sub(id_, sub_user))
- elif sub_type.lower() in ["up", "用户"]:
- await add_sub.send(await add_up_sub(id_, sub_user))
- elif sub_type in ["season", "动漫", "番剧"]:
- await add_sub.send(await add_season_sub(id_, sub_user))
- else:
- await add_sub.finish("参数错误,第一参数必须为:主播/up/番剧!")
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 添加订阅:{sub_type} -> {sub_user} -> {id_}"
- )
-
-
-@del_sub.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if not is_number(msg):
- await del_sub.finish("Id必须为数字!", at_sender=True)
- id_ = (
- f"{event.user_id}:{event.group_id}"
- if isinstance(event, GroupMessageEvent)
- else f"{event.user_id}"
- )
- if await BilibiliSub.delete_bilibili_sub(int(msg), id_):
- await del_sub.send(f"删除订阅id:{msg} 成功...")
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 删除订阅 {id_}"
- )
- else:
- await del_sub.send(f"删除订阅id:{msg} 失败...")
-
-
-@show_sub_info.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- id_ = (
- f"{event.user_id}:{event.group_id}"
- if isinstance(event, GroupMessageEvent)
- else f"{event.user_id}"
- )
- data = await BilibiliSub.get_sub_data(id_)
- live_rst = ""
- up_rst = ""
- season_rst = ""
- for x in data:
- if x.sub_type == "live":
- live_rst += (
- f"\t直播间id:{x.sub_id}\n" f"\t名称:{x.uname}\n" f"------------------\n"
- )
- if x.sub_type == "up":
- up_rst += f"\tUP:{x.uname}\n" f"\tuid:{x.uid}\n" f"------------------\n"
- if x.sub_type == "season":
- season_rst += (
- f"\t番名:{x.season_name}\n"
- f"\t当前集数:{x.season_current_episode}\n"
- f"------------------\n"
- )
- live_rst = "当前订阅的直播:\n" + live_rst if live_rst else live_rst
- up_rst = "当前订阅的UP:\n" + up_rst if up_rst else up_rst
- season_rst = "当前订阅的番剧:\n" + season_rst if season_rst else season_rst
- if not live_rst and not up_rst and not season_rst:
- live_rst = "您目前没有任何订阅..."
- await show_sub_info.send(live_rst + up_rst + season_rst)
-
-
-# 推送
-@scheduler.scheduled_job(
- "interval",
- seconds=30,
-)
-async def _():
- bot = get_bot()
- sub = None
- if bot:
- try:
- await sub_manager.reload_sub_data()
- sub = await sub_manager.random_sub_data()
- if sub:
- rst = await get_sub_status(sub.sub_id, sub.sub_type)
- await send_sub_msg(rst, sub, bot)
- if sub.sub_type == "live":
- rst = await get_sub_status(sub.sub_id, "up")
- await send_sub_msg(rst, sub, bot)
- except Exception as e:
- logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id if sub else 0} {type(e)}:{e}")
-
-
-async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
- """
- 推送信息
- :param rst: 回复
- :param sub: BilibiliSub
- :param bot: Bot
- """
- if rst:
- for x in sub.sub_users.split(",")[:-1]:
- try:
- if ":" in x:
- await bot.send_group_msg(
- group_id=int(x.split(":")[1]), message=Message(rst)
- )
- else:
- await bot.send_private_msg(user_id=int(x), message=Message(rst))
- except Exception as e:
- logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id} {type(e)}:{e}")
+from nonebot import on_command
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
+from .data_source import (
+ add_live_sub,
+ delete_sub,
+ add_up_sub,
+ add_season_sub,
+ get_media_id,
+ get_sub_status,
+ SubManager,
+ BilibiliSub
+)
+from models.level_user import LevelUser
+from configs.config import Config
+from utils.utils import get_message_text, is_number, scheduler, get_bot
+from typing import Optional
+from services.log import logger
+from nonebot import Driver
+import nonebot
+
+__zx_plugin_name__ = "B站订阅"
+__plugin_usage__ = """
+usage:
+ B站直播,番剧,UP动态开播等提醒
+ 主播订阅相当于 直播间订阅 + UP订阅
+ 指令:[示例Id乱打的,仅做示例]
+ 添加订阅 ['主播'/'UP'/'番剧'] [id/链接/番名]
+ 删除订阅 [id]
+ 查看订阅
+ 示例:添加订阅主播 2345344 <-(直播房间id)
+ 示例:添加订阅UP 2355543 <-(个人主页id)
+ 示例:添加订阅番剧 史莱姆 <-(支持模糊搜索)
+ 示例:添加订阅番剧 125344 <-(番剧id)
+ 示例:删除订阅 2324344 <-(任意id,通过查看订阅获取)
+""".strip()
+__plugin_des__ = "非常便利的B站订阅通知"
+__plugin_cmd__ = ["添加订阅 [主播/UP/番剧] [id/链接/番名]", "删除订阅 [id]", "查看订阅"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["B站订阅", "b站订阅", "添加订阅", "删除订阅", "查看订阅"],
+}
+__plugin_configs__ = {
+ "GROUP_BILIBILI_SUB_LEVEL": {
+ "value": 5,
+ "help": "群内bilibili订阅需要管理的权限",
+ "default_value": 5,
+ }
+}
+
+add_sub = on_command("添加订阅", priority=5, block=True)
+del_sub = on_command("删除订阅", priority=5, block=True)
+show_sub_info = on_command("查看订阅", priority=5, block=True)
+
+driver: Driver = nonebot.get_driver()
+
+
+sub_manager: Optional[SubManager] = None
+
+
+@driver.on_startup
+async def _():
+ global sub_manager
+ sub_manager = SubManager()
+
+
+@add_sub.args_parser
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ season_data = state["season_data"]
+ msg = get_message_text(event.json())
+ if not is_number(msg) or int(msg) < 1 or int(msg) > len(season_data):
+ await add_sub.reject("Id必须为数字且在范围内!请重新输入...")
+ state["id"] = season_data[int(msg) - 1]["media_id"]
+
+
+@add_sub.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json()).split()
+ if len(msg) < 2:
+ await add_sub.finish("参数不完全,请查看订阅帮助...")
+ sub_type = msg[0]
+ id_ = ""
+ if isinstance(event, GroupMessageEvent):
+ if not await LevelUser.check_level(
+ event.user_id,
+ event.group_id,
+ Config.get_config("bilibili_sub", "GROUP_BILIBILI_SUB_LEVEL"),
+ ):
+ await add_sub.finish(
+ f"您的权限不足,群内订阅的需要 {Config.get_config('bilibili_sub', 'GROUP_BILIBILI_SUB_LEVEL')} 级权限..",
+ at_sender=True,
+ )
+ sub_user = f"{event.user_id}:{event.group_id}"
+ else:
+ sub_user = f"{event.user_id}"
+ state["sub_type"] = sub_type
+ state["sub_user"] = sub_user
+ if len(msg) > 1:
+ if "http" in msg[1]:
+ msg[1] = msg[1].split("?")[0]
+ msg[1] = msg[1][:-1] if msg[1][-1] == "/" else msg[1]
+ msg[1] = msg[1].split("/")[-1]
+ id_ = msg[1][2:] if msg[1].startswith("md") else msg[1]
+ if not is_number(id_):
+ if sub_type in ["season", "动漫", "番剧"]:
+ rst = "*以为您找到以下番剧,请输入Id选择:*\n"
+ state["season_data"] = await get_media_id(id_)
+ if len(state["season_data"]) == 0:
+ await add_sub.finish(f"未找到番剧:{msg}")
+ for i, x in enumerate(state["season_data"]):
+ rst += f'{i + 1}.{state["season_data"][x]["title"]}\n----------\n'
+ await add_sub.send("\n".join(rst.split("\n")[:-1]))
+ else:
+ await add_sub.finish("Id 必须为全数字!")
+ else:
+ state["id"] = int(id_)
+
+
+@add_sub.got("id")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ sub_type = state["sub_type"]
+ sub_user = state["sub_user"]
+ id_ = state["id"]
+ if sub_type in ["主播", "直播"]:
+ await add_sub.send(await add_live_sub(id_, sub_user))
+ elif sub_type.lower() in ["up", "用户"]:
+ await add_sub.send(await add_up_sub(id_, sub_user))
+ elif sub_type in ["season", "动漫", "番剧"]:
+ await add_sub.send(await add_season_sub(id_, sub_user))
+ else:
+ await add_sub.finish("参数错误,第一参数必须为:主播/up/番剧!")
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 添加订阅:{sub_type} -> {sub_user} -> {id_}"
+ )
+
+
+@del_sub.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if not is_number(msg):
+ await del_sub.finish("Id必须为数字!", at_sender=True)
+ id_ = (
+ f"{event.user_id}:{event.group_id}"
+ if isinstance(event, GroupMessageEvent)
+ else f"{event.user_id}"
+ )
+ if await BilibiliSub.delete_bilibili_sub(int(msg), id_):
+ await del_sub.send(f"删除订阅id:{msg} 成功...")
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 删除订阅 {id_}"
+ )
+ else:
+ await del_sub.send(f"删除订阅id:{msg} 失败...")
+
+
+@show_sub_info.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ id_ = (
+ f"{event.user_id}:{event.group_id}"
+ if isinstance(event, GroupMessageEvent)
+ else f"{event.user_id}"
+ )
+ data = await BilibiliSub.get_sub_data(id_)
+ live_rst = ""
+ up_rst = ""
+ season_rst = ""
+ for x in data:
+ if x.sub_type == "live":
+ live_rst += (
+ f"\t直播间id:{x.sub_id}\n" f"\t名称:{x.uname}\n" f"------------------\n"
+ )
+ if x.sub_type == "up":
+ up_rst += f"\tUP:{x.uname}\n" f"\tuid:{x.uid}\n" f"------------------\n"
+ if x.sub_type == "season":
+ season_rst += (
+ f"\t番名:{x.season_name}\n"
+ f"\t当前集数:{x.season_current_episode}\n"
+ f"------------------\n"
+ )
+ live_rst = "当前订阅的直播:\n" + live_rst if live_rst else live_rst
+ up_rst = "当前订阅的UP:\n" + up_rst if up_rst else up_rst
+ season_rst = "当前订阅的番剧:\n" + season_rst if season_rst else season_rst
+ if not live_rst and not up_rst and not season_rst:
+ live_rst = "您目前没有任何订阅..."
+ await show_sub_info.send(live_rst + up_rst + season_rst)
+
+
+# 推送
+@scheduler.scheduled_job(
+ "interval",
+ seconds=30,
+)
+async def _():
+ bot = get_bot()
+ sub = None
+ if bot:
+ try:
+ await sub_manager.reload_sub_data()
+ sub = await sub_manager.random_sub_data()
+ if sub:
+ logger.info(f"Bilibili订阅开始检测:{sub.sub_id}")
+ rst = await get_sub_status(sub.sub_id, sub.sub_type)
+ await send_sub_msg(rst, sub, bot)
+ if sub.sub_type == "live":
+ rst = await get_sub_status(sub.sub_id, "up")
+ await send_sub_msg(rst, sub, bot)
+ except Exception as e:
+ logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id if sub else 0} {type(e)}:{e}")
+
+
+async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
+ """
+ 推送信息
+ :param rst: 回复
+ :param sub: BilibiliSub
+ :param bot: Bot
+ """
+ if rst:
+ for x in sub.sub_users.split(",")[:-1]:
+ try:
+ if ":" in x:
+ await bot.send_group_msg(
+ group_id=int(x.split(":")[1]), message=Message(rst)
+ )
+ else:
+ await bot.send_private_msg(user_id=int(x), message=Message(rst))
+ except Exception as e:
+ logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id} {type(e)}:{e}")
diff --git a/plugins/bilibili_sub/data_source.py b/plugins/bilibili_sub/data_source.py
old mode 100644
new mode 100755
index 3261df3e..df1dd841
--- a/plugins/bilibili_sub/data_source.py
+++ b/plugins/bilibili_sub/data_source.py
@@ -1,394 +1,391 @@
-from bilibili_api.exceptions.ResponseCodeException import ResponseCodeException
-from utils.manager import resources_manager
-from asyncio.exceptions import TimeoutError
-from .model import BilibiliSub
-from bilibili_api.live import LiveRoom
-from bilibili_api import bangumi
-from utils.message_builder import image
-from bilibili_api.user import User
-from bilibili_api import user
-from typing import Optional
-from pathlib import Path
-from configs.path_config import IMAGE_PATH
-from datetime import datetime
-from utils.browser import get_browser
-from services.db_context import db
-from services.log import logger
-import aiohttp
-import random
-
-
-bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
-
-dynamic_path = Path(IMAGE_PATH) / "bilibili_sub" / "dynamic"
-dynamic_path.mkdir(exist_ok=True, parents=True)
-
-
-resources_manager.add_temp_dir(dynamic_path)
-
-
-async def add_live_sub(live_id: int, sub_user: str) -> str:
- """
- 添加直播订阅
- :param live_id: 直播房间号
- :param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
- :return:
- """
- try:
- async with db.transaction():
- try:
- live = LiveRoom(live_id)
- live_info = (await live.get_room_info())["room_info"]
- except ResponseCodeException:
- return f"未找到房间号Id:{live_id} 的信息,请检查Id是否正确"
- uid = live_info["uid"]
- room_id = live_info["room_id"]
- short_id = live_info["short_id"]
- title = live_info["title"]
- live_status = live_info["live_status"]
- if await BilibiliSub.add_bilibili_sub(
- room_id,
- "live",
- sub_user,
- uid=uid,
- live_short_id=short_id,
- live_status=live_status,
- ):
- await _get_up_status(live_id)
- uname = (await BilibiliSub.get_sub(live_id)).uname
- return (
- "已成功订阅主播:\n"
- f"\ttitle:{title}\n"
- f"\tname: {uname}\n"
- f"\tlive_id:{live_id}\n"
- f"\tuid:{uid}"
- )
- else:
- return "添加订阅失败..."
- except Exception as e:
- logger.error(f"订阅主播live_id:{live_id} 发生了错误 {type(e)}:{e}")
- return "添加订阅失败..."
-
-
-async def add_up_sub(uid: int, sub_user: str) -> str:
- """
- 添加订阅 UP
- :param uid: UP uid
- :param sub_user: 订阅用户
- """
- try:
- async with db.transaction():
- try:
- u = user.User(uid)
- user_info = await u.get_user_info()
- except ResponseCodeException:
- return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
- uname = user_info["name"]
- dynamic_info = await u.get_dynamics(0)
- dynamic_upload_time = 0
- if dynamic_info.get("cards"):
- dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
- video_info = await u.get_videos()
- latest_video_created = 0
- if video_info["list"].get("vlist"):
- latest_video_created = video_info["list"]["vlist"][0]["created"]
- if await BilibiliSub.add_bilibili_sub(
- uid,
- "up",
- sub_user,
- uid=uid,
- uname=uname,
- dynamic_upload_time=dynamic_upload_time,
- latest_video_created=latest_video_created,
- ):
- return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
- else:
- return "添加订阅失败..."
- except Exception as e:
- logger.error(f"订阅Up uid:{uid} 发生了错误 {type(e)}:{e}")
- return "添加订阅失败..."
-
-
-async def add_season_sub(media_id: int, sub_user: str) -> str:
- """
- 添加订阅 UP
- :param media_id: 番剧 media_id
- :param sub_user: 订阅用户
- """
- try:
- async with db.transaction():
- try:
- season_info = await bangumi.get_meta(media_id)
- except ResponseCodeException:
- return f"未找到media_id:{media_id} 的信息,请检查Id是否正确"
- season_id = season_info["media"]["season_id"]
- season_current_episode = season_info["media"]["new_ep"]["index"]
- season_name = season_info["media"]["title"]
- if await BilibiliSub.add_bilibili_sub(
- media_id,
- "season",
- sub_user,
- season_name=season_name,
- season_id=season_id,
- season_current_episode=season_current_episode,
- ):
- return (
- "已成功订阅番剧:\n"
- f"\ttitle: {season_name}\n"
- f"\tcurrent_episode: {season_current_episode}"
- )
- else:
- return "添加订阅失败..."
- except Exception as e:
- logger.error(f"订阅番剧 media_id:{media_id} 发生了错误 {type(e)}:{e}")
- return "添加订阅失败..."
-
-
-async def delete_sub(sub_id: str, sub_user: str) -> str:
- """
- 删除订阅
- :param sub_id: 订阅 id
- :param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
- """
- if await BilibiliSub.delete_bilibili_sub(sub_id, sub_user):
- return f"已成功取消订阅:{sub_id}"
- else:
- return f"取消订阅:{sub_id} 失败,请检查是否订阅过该Id...."
-
-
-async def get_media_id(keyword: str) -> dict:
- """
- 获取番剧的 media_id
- :param keyword: 番剧名称
- """
- params = {"keyword": keyword}
- async with aiohttp.ClientSession() as session:
- for _ in range(3):
- try:
- _season_data = {}
- async with session.get(
- bilibili_search_url, timeout=5, params=params
- ) as response:
- if response.status == 200:
- data = await response.json()
- if data.get("data"):
- for item in data["data"]["result"]:
- if item["result_type"] == "media_bangumi":
- idx = 0
- for x in item["data"]:
- _season_data[idx] = {
- "media_id": x["media_id"],
- "title": x["title"]
- .replace('', "")
- .replace("", ""),
- }
- idx += 1
- return _season_data
- except TimeoutError:
- pass
- return {}
-
-
-async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
- """
- 获取订阅状态
- :param id_: 订阅 id
- :param sub_type: 订阅类型
- :return:
- """
- try:
- if sub_type == "live":
- return await _get_live_status(id_)
- elif sub_type == "up":
- return await _get_up_status(id_)
- elif sub_type == "season":
- return await _get_season_status(id_)
- except ResponseCodeException:
- return "获取信息失败...请检查订阅Id是否存在或稍后再试..."
- # except Exception as e:
- # logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
- # return "发生了预料之外的错误..请稍后再试或联系管理员....."
-
-
-async def _get_live_status(id_: int) -> Optional[str]:
- """
- 获取直播订阅状态
- :param id_: 直播间 id
- """
- live = LiveRoom(id_)
- live_info = (await live.get_room_info())["room_info"]
- title = live_info["title"]
- room_id = live_info["room_id"]
- live_status = live_info["live_status"]
- cover = live_info["cover"]
- sub = await BilibiliSub.get_sub(id_)
- if sub.live_status != live_status:
- await BilibiliSub.update_sub_info(id_, live_status=live_status)
- if sub.live_status == 0 and live_status == 1:
- return (
- f"{image(cover)}\n"
- f"{sub.uname} 开播啦!\n"
- f"标题:{title}\n"
- f"直链:https://live.bilibili.com/{room_id}"
- )
- return None
-
-
-async def _get_up_status(id_: int) -> Optional[str]:
- """
- 获取用户投稿状态
- :param id_: 用户 id
- :return:
- """
- _user = await BilibiliSub.get_sub(id_)
- u = user.User(_user.uid)
- user_info = await u.get_user_info()
- uname = user_info["name"]
- video_info = await u.get_videos()
- latest_video_created = 0
- video = None
- if _user.uname != uname:
- await BilibiliSub.update_sub_info(id_, uname=uname)
- dynamic_img, dynamic_upload_time = await get_user_dynamic(u, _user)
- if video_info["list"].get("vlist"):
- video = video_info["list"]["vlist"][0]
- latest_video_created = video["created"]
- rst = ""
- if dynamic_img:
- await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time)
- rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n"
- if _user.latest_video_created != latest_video_created and video:
- rst = rst + "-------------\n" if rst else rst
- await BilibiliSub.update_sub_info(
- id_, latest_video_created=latest_video_created
- )
- rst += (
- f'{image(video["pic"])}\n'
- f"{uname} 投稿了新视频啦\n"
- f'标题:{video["title"]}\n'
- f'Bvid:{video["bvid"]}\n'
- f'直链:https://www.bilibili.com/video/{video["bvid"]}'
- )
- rst = None if rst == "-------------\n" else rst
- return rst
-
-
-async def _get_season_status(id_) -> Optional[str]:
- """
- 获取 番剧 更新状态
- :param id_: 番剧 id
- """
- season_info = await bangumi.get_meta(id_)
- title = season_info["media"]["title"]
- _idx = (await BilibiliSub.get_sub(id_)).season_current_episode
- new_ep = season_info["media"]["new_ep"]["index"]
- if new_ep != _idx:
- await BilibiliSub.update_sub_info(
- id_, season_current_episode=new_ep, season_update_time=datetime.now()
- )
- return (
- f'{image(season_info["media"]["cover"])}\n'
- f"[{title}]更新啦\n"
- f"最新集数:{new_ep}"
- )
- return None
-
-
-async def get_user_dynamic(
- u: User, local_user: BilibiliSub
-) -> "Optional[MessageSegment], int":
- """
- 获取用户动态
- :param u: 用户类
- :param local_user: 数据库存储的用户数据
- :return: 最新动态截图与时间
- """
- dynamic_info = await u.get_dynamics(0)
- browser = await get_browser()
- if dynamic_info.get("cards") and browser:
- dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
- if local_user.dynamic_upload_time != dynamic_upload_time:
- page = await browser.new_page()
- await page.goto(
- f"https://space.bilibili.com/{local_user.uid}/dynamic",
- wait_until="networkidle",
- timeout=10000,
- )
- await page.set_viewport_size({"width": 2560, "height": 1080})
- # 删除置顶
- await page.evaluate(
- """
- xs = document.getElementsByClassName('first-card-with-title');
- for (x of xs) {
- x.remove();
- }
- """
- )
- card = await page.query_selector(".card")
- # 截图并保存
- await card.screenshot(
- path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
- timeout=100000,
- )
- await page.close()
- return (
- image(
- f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
- "bilibili_sub/dynamic",
- ),
- dynamic_upload_time,
- )
- return None, None
-
-
-class SubManager:
- def __init__(self):
- self.live_data = []
- self.up_data = []
- self.season_data = []
- self.current_index = -1
-
- async def reload_sub_data(self):
- """
- 重载数据
- """
- if not self.live_data or not self.up_data or not self.season_data:
- (
- _live_data,
- _up_data,
- _season_data,
- ) = await BilibiliSub.get_all_sub_data()
- if not self.live_data:
- self.live_data = _live_data
- if not self.up_data:
- self.up_data = _up_data
- if not self.season_data:
- self.season_data = _season_data
-
- async def random_sub_data(self) -> Optional[BilibiliSub]:
- """
- 随机获取一条数据
- :return:
- """
- sub = None
- if not self.live_data and not self.up_data and not self.season_data:
- return sub
- self.current_index += 1
- if self.current_index == 0:
- if self.live_data:
- sub = random.choice(self.live_data)
- self.live_data.remove(sub)
- elif self.current_index == 1:
- if self.up_data:
- sub = random.choice(self.up_data)
- self.up_data.remove(sub)
- elif self.current_index == 2:
- if self.season_data:
- sub = random.choice(self.season_data)
- self.season_data.remove(sub)
- else:
- self.current_index = -1
- if sub:
- return sub
- await self.reload_sub_data()
- return await self.random_sub_data()
+from bilibili_api.exceptions.ResponseCodeException import ResponseCodeException
+from utils.manager import resources_manager
+from asyncio.exceptions import TimeoutError
+from .model import BilibiliSub
+from bilibili_api.live import LiveRoom
+from bilibili_api import bangumi
+from utils.message_builder import image
+from bilibili_api.user import User
+from bilibili_api import user
+from typing import Optional
+from pathlib import Path
+from configs.path_config import IMAGE_PATH
+from datetime import datetime
+from utils.browser import get_browser
+from services.db_context import db
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+import random
+
+
+bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
+
+dynamic_path = Path(IMAGE_PATH) / "bilibili_sub" / "dynamic"
+dynamic_path.mkdir(exist_ok=True, parents=True)
+
+
+resources_manager.add_temp_dir(dynamic_path)
+
+
+async def add_live_sub(live_id: int, sub_user: str) -> str:
+ """
+ 添加直播订阅
+ :param live_id: 直播房间号
+ :param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
+ :return:
+ """
+ try:
+ async with db.transaction():
+ try:
+ live = LiveRoom(live_id)
+ live_info = (await live.get_room_info())["room_info"]
+ except ResponseCodeException:
+ return f"未找到房间号Id:{live_id} 的信息,请检查Id是否正确"
+ uid = live_info["uid"]
+ room_id = live_info["room_id"]
+ short_id = live_info["short_id"]
+ title = live_info["title"]
+ live_status = live_info["live_status"]
+ if await BilibiliSub.add_bilibili_sub(
+ room_id,
+ "live",
+ sub_user,
+ uid=uid,
+ live_short_id=short_id,
+ live_status=live_status,
+ ):
+ await _get_up_status(live_id)
+ uname = (await BilibiliSub.get_sub(live_id)).uname
+ return (
+ "已成功订阅主播:\n"
+ f"\ttitle:{title}\n"
+ f"\tname: {uname}\n"
+ f"\tlive_id:{live_id}\n"
+ f"\tuid:{uid}"
+ )
+ else:
+ return "添加订阅失败..."
+ except Exception as e:
+ logger.error(f"订阅主播live_id:{live_id} 发生了错误 {type(e)}:{e}")
+ return "添加订阅失败..."
+
+
+async def add_up_sub(uid: int, sub_user: str) -> str:
+ """
+ 添加订阅 UP
+ :param uid: UP uid
+ :param sub_user: 订阅用户
+ """
+ try:
+ async with db.transaction():
+ try:
+ u = user.User(uid)
+ user_info = await u.get_user_info()
+ except ResponseCodeException:
+ return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
+ uname = user_info["name"]
+ dynamic_info = await u.get_dynamics(0)
+ dynamic_upload_time = 0
+ if dynamic_info.get("cards"):
+ dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
+ video_info = await u.get_videos()
+ latest_video_created = 0
+ if video_info["list"].get("vlist"):
+ latest_video_created = video_info["list"]["vlist"][0]["created"]
+ if await BilibiliSub.add_bilibili_sub(
+ uid,
+ "up",
+ sub_user,
+ uid=uid,
+ uname=uname,
+ dynamic_upload_time=dynamic_upload_time,
+ latest_video_created=latest_video_created,
+ ):
+ return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
+ else:
+ return "添加订阅失败..."
+ except Exception as e:
+ logger.error(f"订阅Up uid:{uid} 发生了错误 {type(e)}:{e}")
+ return "添加订阅失败..."
+
+
+async def add_season_sub(media_id: int, sub_user: str) -> str:
+ """
+ 添加订阅 UP
+ :param media_id: 番剧 media_id
+ :param sub_user: 订阅用户
+ """
+ try:
+ async with db.transaction():
+ try:
+ season_info = await bangumi.get_meta(media_id)
+ except ResponseCodeException:
+ return f"未找到media_id:{media_id} 的信息,请检查Id是否正确"
+ season_id = season_info["media"]["season_id"]
+ season_current_episode = season_info["media"]["new_ep"]["index"]
+ season_name = season_info["media"]["title"]
+ if await BilibiliSub.add_bilibili_sub(
+ media_id,
+ "season",
+ sub_user,
+ season_name=season_name,
+ season_id=season_id,
+ season_current_episode=season_current_episode,
+ ):
+ return (
+ "已成功订阅番剧:\n"
+ f"\ttitle: {season_name}\n"
+ f"\tcurrent_episode: {season_current_episode}"
+ )
+ else:
+ return "添加订阅失败..."
+ except Exception as e:
+ logger.error(f"订阅番剧 media_id:{media_id} 发生了错误 {type(e)}:{e}")
+ return "添加订阅失败..."
+
+
+async def delete_sub(sub_id: str, sub_user: str) -> str:
+ """
+ 删除订阅
+ :param sub_id: 订阅 id
+ :param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
+ """
+ if await BilibiliSub.delete_bilibili_sub(int(sub_id), sub_user):
+ return f"已成功取消订阅:{sub_id}"
+ else:
+ return f"取消订阅:{sub_id} 失败,请检查是否订阅过该Id...."
+
+
+async def get_media_id(keyword: str) -> dict:
+ """
+ 获取番剧的 media_id
+ :param keyword: 番剧名称
+ """
+ params = {"keyword": keyword}
+ for _ in range(3):
+ try:
+ _season_data = {}
+ response = await AsyncHttpx.get(bilibili_search_url, params=params, timeout=5)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("data"):
+ for item in data["data"]["result"]:
+ if item["result_type"] == "media_bangumi":
+ idx = 0
+ for x in item["data"]:
+ _season_data[idx] = {
+ "media_id": x["media_id"],
+ "title": x["title"]
+ .replace('', "")
+ .replace("", ""),
+ }
+ idx += 1
+ return _season_data
+ except TimeoutError:
+ pass
+ return {}
+
+
+async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
+ """
+ 获取订阅状态
+ :param id_: 订阅 id
+ :param sub_type: 订阅类型
+ :return:
+ """
+ try:
+ if sub_type == "live":
+ return await _get_live_status(id_)
+ elif sub_type == "up":
+ return await _get_up_status(id_)
+ elif sub_type == "season":
+ return await _get_season_status(id_)
+ except ResponseCodeException:
+ return "获取信息失败...请检查订阅Id是否存在或稍后再试..."
+ # except Exception as e:
+ # logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
+ # return "发生了预料之外的错误..请稍后再试或联系管理员....."
+
+
+async def _get_live_status(id_: int) -> Optional[str]:
+ """
+ 获取直播订阅状态
+ :param id_: 直播间 id
+ """
+ live = LiveRoom(id_)
+ live_info = (await live.get_room_info())["room_info"]
+ title = live_info["title"]
+ room_id = live_info["room_id"]
+ live_status = live_info["live_status"]
+ cover = live_info["cover"]
+ sub = await BilibiliSub.get_sub(id_)
+ if sub.live_status != live_status:
+ await BilibiliSub.update_sub_info(id_, live_status=live_status)
+ if sub.live_status == 0 and live_status == 1:
+ return (
+ f"{image(cover)}\n"
+ f"{sub.uname} 开播啦!\n"
+ f"标题:{title}\n"
+ f"直链:https://live.bilibili.com/{room_id}"
+ )
+ return None
+
+
+async def _get_up_status(id_: int) -> Optional[str]:
+ """
+ 获取用户投稿状态
+ :param id_: 用户 id
+ :return:
+ """
+ _user = await BilibiliSub.get_sub(id_)
+ u = user.User(_user.uid)
+ user_info = await u.get_user_info()
+ uname = user_info["name"]
+ video_info = await u.get_videos()
+ latest_video_created = 0
+ video = None
+ if _user.uname != uname:
+ await BilibiliSub.update_sub_info(id_, uname=uname)
+ dynamic_img, dynamic_upload_time = await get_user_dynamic(u, _user)
+ if video_info["list"].get("vlist"):
+ video = video_info["list"]["vlist"][0]
+ latest_video_created = video["created"]
+ rst = ""
+ if dynamic_img:
+ await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time)
+ rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n"
+ if _user.latest_video_created != latest_video_created and video:
+ rst = rst + "-------------\n" if rst else rst
+ await BilibiliSub.update_sub_info(
+ id_, latest_video_created=latest_video_created
+ )
+ rst += (
+ f'{image(video["pic"])}\n'
+ f"{uname} 投稿了新视频啦\n"
+ f'标题:{video["title"]}\n'
+ f'Bvid:{video["bvid"]}\n'
+ f'直链:https://www.bilibili.com/video/{video["bvid"]}'
+ )
+ rst = None if rst == "-------------\n" else rst
+ return rst
+
+
+async def _get_season_status(id_) -> Optional[str]:
+ """
+ 获取 番剧 更新状态
+ :param id_: 番剧 id
+ """
+ season_info = await bangumi.get_meta(id_)
+ title = season_info["media"]["title"]
+ _idx = (await BilibiliSub.get_sub(id_)).season_current_episode
+ new_ep = season_info["media"]["new_ep"]["index"]
+ if new_ep != _idx:
+ await BilibiliSub.update_sub_info(
+ id_, season_current_episode=new_ep, season_update_time=datetime.now()
+ )
+ return (
+ f'{image(season_info["media"]["cover"])}\n'
+ f"[{title}]更新啦\n"
+ f"最新集数:{new_ep}"
+ )
+ return None
+
+
+async def get_user_dynamic(
+ u: User, local_user: BilibiliSub
+) -> "Optional[MessageSegment], int":
+ """
+ 获取用户动态
+ :param u: 用户类
+ :param local_user: 数据库存储的用户数据
+ :return: 最新动态截图与时间
+ """
+ dynamic_info = await u.get_dynamics(0)
+ browser = await get_browser()
+ if dynamic_info.get("cards") and browser:
+ dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
+ if local_user.dynamic_upload_time != dynamic_upload_time:
+ page = await browser.new_page()
+ await page.goto(
+ f"https://space.bilibili.com/{local_user.uid}/dynamic",
+ wait_until="networkidle",
+ timeout=10000,
+ )
+ await page.set_viewport_size({"width": 2560, "height": 1080})
+ # 删除置顶
+ await page.evaluate(
+ """
+ xs = document.getElementsByClassName('first-card-with-title');
+ for (x of xs) {
+ x.remove();
+ }
+ """
+ )
+ card = await page.query_selector(".card")
+ # 截图并保存
+ await card.screenshot(
+ path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
+ timeout=100000,
+ )
+ await page.close()
+ return (
+ image(
+ f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
+ "bilibili_sub/dynamic",
+ ),
+ dynamic_upload_time,
+ )
+ return None, None
+
+
+class SubManager:
+ def __init__(self):
+ self.live_data = []
+ self.up_data = []
+ self.season_data = []
+ self.current_index = -1
+
+ async def reload_sub_data(self):
+ """
+ 重载数据
+ """
+ if not self.live_data or not self.up_data or not self.season_data:
+ (
+ _live_data,
+ _up_data,
+ _season_data,
+ ) = await BilibiliSub.get_all_sub_data()
+ if not self.live_data:
+ self.live_data = _live_data
+ if not self.up_data:
+ self.up_data = _up_data
+ if not self.season_data:
+ self.season_data = _season_data
+
+ async def random_sub_data(self) -> Optional[BilibiliSub]:
+ """
+ 随机获取一条数据
+ :return:
+ """
+ sub = None
+ if not self.live_data and not self.up_data and not self.season_data:
+ return sub
+ self.current_index += 1
+ if self.current_index == 0:
+ if self.live_data:
+ sub = random.choice(self.live_data)
+ self.live_data.remove(sub)
+ elif self.current_index == 1:
+ if self.up_data:
+ sub = random.choice(self.up_data)
+ self.up_data.remove(sub)
+ elif self.current_index == 2:
+ if self.season_data:
+ sub = random.choice(self.season_data)
+ self.season_data.remove(sub)
+ else:
+ self.current_index = -1
+ if sub:
+ return sub
+ await self.reload_sub_data()
+ return await self.random_sub_data()
diff --git a/plugins/bilibili_sub/model.py b/plugins/bilibili_sub/model.py
old mode 100644
new mode 100755
index f201c575..777cebf4
--- a/plugins/bilibili_sub/model.py
+++ b/plugins/bilibili_sub/model.py
@@ -1,249 +1,249 @@
-from services.log import logger
-from services.db_context import db
-from datetime import datetime
-from typing import Optional, List
-
-
-class BilibiliSub(db.Model):
- __tablename__ = "bilibili_sub"
-
- id = db.Column(db.Integer(), primary_key=True)
- sub_id = db.Column(db.Integer(), nullable=False)
- sub_type = db.Column(db.String(), nullable=False)
- # 订阅用户
- sub_users = db.Column(db.String(), nullable=False)
- # 直播
- live_short_id = db.Column(db.Integer())
- live_status = db.Column(db.Integer)
- # 主播/UP
- uid = db.Column(db.BigInteger())
- uname = db.Column(db.String())
- latest_video_created = db.Column(db.BigInteger()) # 视频上传时间
- dynamic_upload_time = db.Column(db.BigInteger(), default=0) # 动态发布时间
- # 番剧
- season_name = db.Column(db.String())
- season_id = db.Column(db.Integer())
- season_current_episode = db.Column(db.String())
- season_update_time = db.Column(db.DateTime())
-
- _idx1 = db.Index("bilibili_sub_idx1", "sub_id", "sub_type", unique=True)
-
- @classmethod
- async def add_bilibili_sub(
- cls,
- sub_id: int,
- sub_type: str,
- sub_user: str,
- *,
- live_short_id: Optional[int] = None,
- live_status: Optional[int] = None,
- dynamic_upload_time: Optional[int] = None,
- uid: Optional[int] = None,
- uname: Optional[str] = None,
- latest_video_created: Optional[int] = None,
- season_name: Optional[str] = None,
- season_id: Optional[int] = None,
- season_current_episode: Optional[str] = None,
- season_update_time: Optional[datetime] = None,
- ) -> bool:
- """
- 说明:
- 添加订阅
- 参数:
- :param sub_id: 订阅名称,房间号,番剧号等
- :param sub_type: 订阅类型
- :param sub_user: 订阅此条目的用户
- :param live_short_id: 直接短 id
- :param live_status: 主播开播状态
- :param dynamic_upload_time: 主播/UP最新动态时间
- :param uid: 主播/UP uid
- :param uname: 用户名称
- :param latest_video_created: 最新视频上传时间
- :param season_name: 番剧名称
- :param season_id: 番剧 season_id
- :param season_current_episode: 番剧最新集数
- :param season_update_time: 番剧更新时间
- """
- try:
- async with db.transaction():
- query = (
- await cls.query.where(cls.sub_id == sub_id)
- .with_for_update()
- .gino.first()
- )
- sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
- if query:
- if sub_user not in query.sub_users:
- sub_users = query.sub_users + sub_user
- await query.update(sub_users=sub_users).apply()
- else:
- sub = await cls.create(
- sub_id=sub_id, sub_type=sub_type, sub_users=sub_user
- )
- await sub.update(
- live_short_id=live_short_id
- if live_short_id
- else sub.live_short_id,
- live_status=live_status if live_status else sub.live_status,
- dynamic_upload_time=dynamic_upload_time
- if dynamic_upload_time
- else sub.dynamic_upload_time,
- uid=uid if uid else sub.uid,
- uname=uname if uname else sub.uname,
- latest_video_created=latest_video_created
- if latest_video_created
- else sub.latest_video_created,
- season_update_time=season_update_time
- if season_update_time
- else sub.season_update_time,
- season_current_episode=season_current_episode
- if season_current_episode
- else sub.season_current_episode,
- season_id=season_id if season_id else sub.season_id,
- season_name=season_name if season_name else sub.season_name,
- ).apply()
- return True
- except Exception as e:
- logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
- return False
-
- @classmethod
- async def delete_bilibili_sub(cls, sub_id: int, sub_user: str) -> bool:
- """
- 说明:
- 删除订阅
- 参数:
- :param sub_id: 订阅名称
- :param sub_user: 删除此条目的用户
- """
- try:
- async with db.transaction():
- query = (
- await cls.query.where(
- (cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user))
- )
- .with_for_update()
- .gino.first()
- )
- if not query:
- return False
- await query.update(
- sub_users=query.sub_users.replace(f"{sub_user},", "")
- ).apply()
- if not query.sub_users.strip():
- await query.delete()
- return True
- except Exception as e:
- logger.info(f"bilibili_sub 删除订阅错误 {type(e)}: {e}")
- return False
-
- @classmethod
- async def get_sub(cls, sub_id: int) -> Optional["BilibiliSub"]:
- """
- 说明:
- 获取订阅对象
- 参数:
- :param sub_id: 订阅 id
- """
- return await cls.query.where(cls.sub_id == sub_id).gino.first()
-
- @classmethod
- async def get_sub_data(cls, id_: str) -> List["BilibiliSub"]:
- """
- 获取 id_ 订阅的所有内容
- :param id_: id
- """
- query = cls.query.where(cls.sub_users.contains(id_))
- return await query.gino.all()
-
- @classmethod
- async def update_sub_info(
- cls,
- sub_id: int,
- *,
- live_short_id: Optional[int] = None,
- live_status: Optional[int] = None,
- dynamic_upload_time: Optional[int] = None,
- uid: Optional[int] = None,
- uname: Optional[str] = None,
- latest_video_created: Optional[int] = None,
- season_name: Optional[str] = None,
- season_id: Optional[int] = None,
- season_current_episode: Optional[str] = None,
- season_update_time: Optional[datetime] = None,
- ) -> bool:
- """
- 说明:
- 更新订阅信息
- 参数:
- :param sub_id: 订阅名称,房间号,番剧号等
- :param live_short_id: 直接短 id
- :param live_status: 主播开播状态
- :param dynamic_upload_time: 主播/UP最新动态时间
- :param uid: 主播/UP uid
- :param uname: 用户名称
- :param latest_video_created: 最新视频上传时间
- :param season_name: 番剧名称
- :param season_id: 番剧 season_id
- :param season_current_episode: 番剧最新集数
- :param season_update_time: 番剧更新时间
- """
- try:
- async with db.transaction():
- sub = (
- await cls.query.where(cls.sub_id == sub_id)
- .with_for_update()
- .gino.first()
- )
- if sub:
- await sub.update(
- live_short_id=live_short_id
- if live_short_id is not None
- else sub.live_short_id,
- live_status=live_status
- if live_status is not None
- else sub.live_status,
- dynamic_upload_time=dynamic_upload_time
- if dynamic_upload_time is not None
- else sub.dynamic_upload_time,
- uid=uid if uid is not None else sub.uid,
- uname=uname if uname is not None else sub.uname,
- latest_video_created=latest_video_created
- if latest_video_created is not None
- else sub.latest_video_created,
- season_update_time=season_update_time
- if season_update_time is not None
- else sub.season_update_time,
- season_current_episode=season_current_episode
- if season_current_episode is not None
- else sub.season_current_episode,
- season_id=season_id if season_id is not None else sub.season_id,
- season_name=season_name
- if season_name is not None
- else sub.season_name,
- ).apply()
- return True
- except Exception as e:
- logger.info(f"bilibili_sub 更新订阅错误 {type(e)}: {e}")
- return False
-
- @classmethod
- async def get_all_sub_data(
- cls,
- ) -> "List[BilibiliSub], List[BilibiliSub], List[BilibiliSub]":
- """
- 说明:
- 分类获取所有数据
- """
- live_data = []
- up_data = []
- season_data = []
- query = await cls.query.gino.all()
- for x in query:
- if x.sub_type == "live":
- live_data.append(x)
- if x.sub_type == "up":
- up_data.append(x)
- if x.sub_type == "season":
- season_data.append(x)
- return live_data, up_data, season_data
+from services.log import logger
+from services.db_context import db
+from datetime import datetime
+from typing import Optional, List
+
+
+class BilibiliSub(db.Model):
+ __tablename__ = "bilibili_sub"
+
+ id = db.Column(db.Integer(), primary_key=True)
+ sub_id = db.Column(db.Integer(), nullable=False)
+ sub_type = db.Column(db.String(), nullable=False)
+ # 订阅用户
+ sub_users = db.Column(db.String(), nullable=False)
+ # 直播
+ live_short_id = db.Column(db.Integer())
+ live_status = db.Column(db.Integer)
+ # 主播/UP
+ uid = db.Column(db.BigInteger())
+ uname = db.Column(db.String())
+ latest_video_created = db.Column(db.BigInteger()) # 视频上传时间
+ dynamic_upload_time = db.Column(db.BigInteger(), default=0) # 动态发布时间
+ # 番剧
+ season_name = db.Column(db.String())
+ season_id = db.Column(db.Integer())
+ season_current_episode = db.Column(db.String())
+ season_update_time = db.Column(db.DateTime())
+
+ _idx1 = db.Index("bilibili_sub_idx1", "sub_id", "sub_type", unique=True)
+
+ @classmethod
+ async def add_bilibili_sub(
+ cls,
+ sub_id: int,
+ sub_type: str,
+ sub_user: str,
+ *,
+ live_short_id: Optional[int] = None,
+ live_status: Optional[int] = None,
+ dynamic_upload_time: Optional[int] = None,
+ uid: Optional[int] = None,
+ uname: Optional[str] = None,
+ latest_video_created: Optional[int] = None,
+ season_name: Optional[str] = None,
+ season_id: Optional[int] = None,
+ season_current_episode: Optional[str] = None,
+ season_update_time: Optional[datetime] = None,
+ ) -> bool:
+ """
+ 说明:
+ 添加订阅
+ 参数:
+ :param sub_id: 订阅名称,房间号,番剧号等
+ :param sub_type: 订阅类型
+ :param sub_user: 订阅此条目的用户
+ :param live_short_id: 直接短 id
+ :param live_status: 主播开播状态
+ :param dynamic_upload_time: 主播/UP最新动态时间
+ :param uid: 主播/UP uid
+ :param uname: 用户名称
+ :param latest_video_created: 最新视频上传时间
+ :param season_name: 番剧名称
+ :param season_id: 番剧 season_id
+ :param season_current_episode: 番剧最新集数
+ :param season_update_time: 番剧更新时间
+ """
+ try:
+ async with db.transaction():
+ query = (
+ await cls.query.where(cls.sub_id == sub_id)
+ .with_for_update()
+ .gino.first()
+ )
+ sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
+ if query:
+ if sub_user not in query.sub_users:
+ sub_users = query.sub_users + sub_user
+ await query.update(sub_users=sub_users).apply()
+ else:
+ sub = await cls.create(
+ sub_id=sub_id, sub_type=sub_type, sub_users=sub_user
+ )
+ await sub.update(
+ live_short_id=live_short_id
+ if live_short_id
+ else sub.live_short_id,
+ live_status=live_status if live_status else sub.live_status,
+ dynamic_upload_time=dynamic_upload_time
+ if dynamic_upload_time
+ else sub.dynamic_upload_time,
+ uid=uid if uid else sub.uid,
+ uname=uname if uname else sub.uname,
+ latest_video_created=latest_video_created
+ if latest_video_created
+ else sub.latest_video_created,
+ season_update_time=season_update_time
+ if season_update_time
+ else sub.season_update_time,
+ season_current_episode=season_current_episode
+ if season_current_episode
+ else sub.season_current_episode,
+ season_id=season_id if season_id else sub.season_id,
+ season_name=season_name if season_name else sub.season_name,
+ ).apply()
+ return True
+ except Exception as e:
+ logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
+ return False
+
+ @classmethod
+ async def delete_bilibili_sub(cls, sub_id: int, sub_user: str) -> bool:
+ """
+ 说明:
+ 删除订阅
+ 参数:
+ :param sub_id: 订阅名称
+ :param sub_user: 删除此条目的用户
+ """
+ try:
+ async with db.transaction():
+ query = (
+ await cls.query.where(
+ (cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user))
+ )
+ .with_for_update()
+ .gino.first()
+ )
+ if not query:
+ return False
+ await query.update(
+ sub_users=query.sub_users.replace(f"{sub_user},", "")
+ ).apply()
+ if not query.sub_users.strip():
+ await query.delete()
+ return True
+ except Exception as e:
+ logger.info(f"bilibili_sub 删除订阅错误 {type(e)}: {e}")
+ return False
+
+ @classmethod
+ async def get_sub(cls, sub_id: int) -> Optional["BilibiliSub"]:
+ """
+ 说明:
+ 获取订阅对象
+ 参数:
+ :param sub_id: 订阅 id
+ """
+ return await cls.query.where(cls.sub_id == sub_id).gino.first()
+
+ @classmethod
+ async def get_sub_data(cls, id_: str) -> List["BilibiliSub"]:
+ """
+ 获取 id_ 订阅的所有内容
+ :param id_: id
+ """
+ query = cls.query.where(cls.sub_users.contains(id_))
+ return await query.gino.all()
+
+ @classmethod
+ async def update_sub_info(
+ cls,
+ sub_id: int,
+ *,
+ live_short_id: Optional[int] = None,
+ live_status: Optional[int] = None,
+ dynamic_upload_time: Optional[int] = None,
+ uid: Optional[int] = None,
+ uname: Optional[str] = None,
+ latest_video_created: Optional[int] = None,
+ season_name: Optional[str] = None,
+ season_id: Optional[int] = None,
+ season_current_episode: Optional[str] = None,
+ season_update_time: Optional[datetime] = None,
+ ) -> bool:
+ """
+ 说明:
+ 更新订阅信息
+ 参数:
+ :param sub_id: 订阅名称,房间号,番剧号等
+ :param live_short_id: 直接短 id
+ :param live_status: 主播开播状态
+ :param dynamic_upload_time: 主播/UP最新动态时间
+ :param uid: 主播/UP uid
+ :param uname: 用户名称
+ :param latest_video_created: 最新视频上传时间
+ :param season_name: 番剧名称
+ :param season_id: 番剧 season_id
+ :param season_current_episode: 番剧最新集数
+ :param season_update_time: 番剧更新时间
+ """
+ try:
+ async with db.transaction():
+ sub = (
+ await cls.query.where(cls.sub_id == sub_id)
+ .with_for_update()
+ .gino.first()
+ )
+ if sub:
+ await sub.update(
+ live_short_id=live_short_id
+ if live_short_id is not None
+ else sub.live_short_id,
+ live_status=live_status
+ if live_status is not None
+ else sub.live_status,
+ dynamic_upload_time=dynamic_upload_time
+ if dynamic_upload_time is not None
+ else sub.dynamic_upload_time,
+ uid=uid if uid is not None else sub.uid,
+ uname=uname if uname is not None else sub.uname,
+ latest_video_created=latest_video_created
+ if latest_video_created is not None
+ else sub.latest_video_created,
+ season_update_time=season_update_time
+ if season_update_time is not None
+ else sub.season_update_time,
+ season_current_episode=season_current_episode
+ if season_current_episode is not None
+ else sub.season_current_episode,
+ season_id=season_id if season_id is not None else sub.season_id,
+ season_name=season_name
+ if season_name is not None
+ else sub.season_name,
+ ).apply()
+ return True
+ except Exception as e:
+ logger.info(f"bilibili_sub 更新订阅错误 {type(e)}: {e}")
+ return False
+
+ @classmethod
+ async def get_all_sub_data(
+ cls,
+ ) -> "List[BilibiliSub], List[BilibiliSub], List[BilibiliSub]":
+ """
+ 说明:
+ 分类获取所有数据
+ """
+ live_data = []
+ up_data = []
+ season_data = []
+ query = await cls.query.gino.all()
+ for x in query:
+ if x.sub_type == "live":
+ live_data.append(x)
+ if x.sub_type == "up":
+ up_data.append(x)
+ if x.sub_type == "season":
+ season_data.append(x)
+ return live_data, up_data, season_data
diff --git a/plugins/bilibili_sub/utils.py b/plugins/bilibili_sub/utils.py
old mode 100644
new mode 100755
index 89325453..869944f2
--- a/plugins/bilibili_sub/utils.py
+++ b/plugins/bilibili_sub/utils.py
@@ -1,72 +1,71 @@
-from utils.image_utils import CreateImg
-from configs.path_config import IMAGE_PATH
-from pathlib import Path
-from bilibili_api import user
-from io import BytesIO
-import aiohttp
-
-
-BORDER_PATH = Path(IMAGE_PATH) / 'border'
-BORDER_PATH.mkdir(parents=True, exist_ok=True)
-
-
-async def get_pic(url: str) -> bytes:
- """
- 获取图像
- :param url: 图像链接
- :return: 图像二进制
- """
- async with aiohttp.ClientSession() as session:
- async with session.get(url, timeout=2) as response:
- return await response.read()
-
-
-async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des: str):
- """
- 生成主播简介图片
- :param uid: 主播 uid
- :param title: 直播间标题
- :param cover: 直播封面
- :param tags: 直播标签
- :param des: 直播简介
- :return:
- """
- u = user.User(uid)
- user_info = await u.get_user_info()
- name = user_info['name']
- sex = user_info['sex']
- face = user_info['face']
- sign = user_info['sign']
- ava = CreateImg(100, 100, background=BytesIO(await get_pic(face)))
- ava.circle()
- cover = CreateImg(470, 265, background=BytesIO(await get_pic(cover)))
- print()
-
-
-def _create_live_des_image(title: str, cover: CreateImg, tags: str, des: str, user_name: str, sex: str, sign: str, ava: CreateImg):
- """
- 生成主播简介图片
- :param title: 直播间标题
- :param cover: 直播封面
- :param tags: 直播标签
- :param des: 直播简介
- :param user_name: 主播名称
- :param sex: 主播性别
- :param sign: 主播签名
- :param ava: 主播头像
- :return:
- """
- border = BORDER_PATH / '0.png'
- border_img = None
- if border.exists():
- border_img = CreateImg(1772, 2657, background=border)
- bk = CreateImg(1772, 2657, font_size=30)
- bk.paste(cover, (0, 100), center_type='by_width')
-
-
-
-
-
-
-
-
+from utils.image_utils import CreateImg
+from configs.path_config import IMAGE_PATH
+from utils.http_utils import AsyncHttpx
+from pathlib import Path
+from bilibili_api import user
+from io import BytesIO
+
+
+BORDER_PATH = Path(IMAGE_PATH) / "border"
+BORDER_PATH.mkdir(parents=True, exist_ok=True)
+
+
+async def get_pic(url: str) -> bytes:
+ """
+ 获取图像
+ :param url: 图像链接
+ :return: 图像二进制
+ """
+ return (await AsyncHttpx.get(url, timeout=10)).content
+
+
+async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des: str):
+ """
+ 生成主播简介图片
+ :param uid: 主播 uid
+ :param title: 直播间标题
+ :param cover: 直播封面
+ :param tags: 直播标签
+ :param des: 直播简介
+ :return:
+ """
+ u = user.User(uid)
+ user_info = await u.get_user_info()
+ name = user_info["name"]
+ sex = user_info["sex"]
+ face = user_info["face"]
+ sign = user_info["sign"]
+ ava = CreateImg(100, 100, background=BytesIO(await get_pic(face)))
+ ava.circle()
+ cover = CreateImg(470, 265, background=BytesIO(await get_pic(cover)))
+ print()
+
+
+def _create_live_des_image(
+ title: str,
+ cover: CreateImg,
+ tags: str,
+ des: str,
+ user_name: str,
+ sex: str,
+ sign: str,
+ ava: CreateImg,
+):
+ """
+ 生成主播简介图片
+ :param title: 直播间标题
+ :param cover: 直播封面
+ :param tags: 直播标签
+ :param des: 直播简介
+ :param user_name: 主播名称
+ :param sex: 主播性别
+ :param sign: 主播签名
+ :param ava: 主播头像
+ :return:
+ """
+ border = BORDER_PATH / "0.png"
+ border_img = None
+ if border.exists():
+ border_img = CreateImg(1772, 2657, background=border)
+ bk = CreateImg(1772, 2657, font_size=30)
+ bk.paste(cover, (0, 100), center_type="by_width")
diff --git a/plugins/bt/__init__.py b/plugins/bt/__init__.py
old mode 100644
new mode 100755
index d155550e..baecd6e3
--- a/plugins/bt/__init__.py
+++ b/plugins/bt/__init__.py
@@ -7,7 +7,6 @@ from nonebot.adapters.cqhttp import PrivateMessageEvent
from utils.utils import get_message_text
from nonebot.adapters.cqhttp.permission import PRIVATE
from asyncio.exceptions import TimeoutError
-from aiohttp.client_exceptions import ServerDisconnectedError
__zx_plugin_name__ = "磁力搜索"
__plugin_usage__ = """
@@ -89,11 +88,9 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
send_flag = True
except TimeoutError:
await bt.finish(f"搜索 {keyword} 超时...")
- except ServerDisconnectedError:
- await bt.finish(f"搜索 {keyword} 连接失败")
except Exception as e:
await bt.finish(f"bt 其他未知错误..")
- logger.error(f"bt 错误 e:{e}")
+ logger.error(f"bt 错误 {type(e)}:{e}")
if not send_flag:
await bt.send(f"{keyword} 未搜索到...")
logger.info(f"USER {event.user_id} BT搜索 {keyword} 第 {page} 页")
diff --git a/plugins/bt/data_source.py b/plugins/bt/data_source.py
old mode 100644
new mode 100755
index 3ea7270e..ddec06f5
--- a/plugins/bt/data_source.py
+++ b/plugins/bt/data_source.py
@@ -1,8 +1,6 @@
-from utils.user_agent import get_user_agent
-import aiohttp
+from utils.http_utils import AsyncHttpx
from configs.config import Config
from bs4 import BeautifulSoup
-from utils.utils import get_local_proxy
import platform
if platform.system() == "Windows":
@@ -15,36 +13,39 @@ url = "http://www.eclzz.world"
async def get_bt_info(keyword: str, page: str):
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(
- f"{url}/s/{keyword}_rel_{page}.html", proxy=get_local_proxy(), timeout=5
- ) as response:
- text = await response.text()
- if text.find("大约0条结果") != -1:
- return
- soup = BeautifulSoup(text, "lxml")
- item_lst = soup.find_all("div", {"class": "search-item"})
- bt_max_num = Config.get_config("bt", "BT_MAX_NUM")
- bt_max_num = bt_max_num if bt_max_num < len(item_lst) else len(item_lst)
- for item in item_lst[:bt_max_num]:
- divs = item.find_all("div")
- title = (
- str(divs[0].find("a").text)
- .replace("", "")
- .replace("", "")
- .strip()
- )
- spans = divs[2].find_all("span")
- itype = spans[0].text
- create_time = spans[1].find("b").text
- file_size = spans[2].find("b").text
- link = await get_download_link(divs[0].find("a")["href"], session)
- yield title, itype, create_time, file_size, link
+ """
+ 获取资源信息
+ :param keyword: 关键词
+ :param page: 页数
+ """
+ text = (await AsyncHttpx.get(f"{url}/s/{keyword}_rel_{page}.html", timeout=5)).text
+ if text.find("大约0条结果") != -1:
+ return
+ soup = BeautifulSoup(text, "lxml")
+ item_lst = soup.find_all("div", {"class": "search-item"})
+ bt_max_num = Config.get_config("bt", "BT_MAX_NUM")
+ bt_max_num = bt_max_num if bt_max_num < len(item_lst) else len(item_lst)
+ for item in item_lst[:bt_max_num]:
+ divs = item.find_all("div")
+ title = (
+ str(divs[0].find("a").text)
+ .replace("", "")
+ .replace("", "")
+ .strip()
+ )
+ spans = divs[2].find_all("span")
+ itype = spans[0].text
+ create_time = spans[1].find("b").text
+ file_size = spans[2].find("b").text
+ link = await get_download_link(divs[0].find("a")["href"])
+ yield title, itype, create_time, file_size, link
-async def get_download_link(_url: str, session) -> str:
- async with session.get(
- f"{url}{_url}", proxy=get_local_proxy(), timeout=30
- ) as response:
- soup = BeautifulSoup(await response.text(), "lxml")
- return soup.find("a", {"id": "down-url"})["href"]
+async def get_download_link(_url: str) -> str:
+ """
+ 获取资源下载地址
+ :param _url: 链接
+ """
+ text = (await AsyncHttpx.get(f"{url}{_url}")).text
+ soup = BeautifulSoup(text, "lxml")
+ return soup.find("a", {"id": "down-url"})["href"]
diff --git a/plugins/c_song/__init__.py b/plugins/c_song/__init__.py
old mode 100644
new mode 100755
index c2195941..d398d59a
--- a/plugins/c_song/__init__.py
+++ b/plugins/c_song/__init__.py
@@ -1,57 +1,57 @@
-from .music_163 import get_song_id, get_song_info
-from nonebot.adapters.cqhttp import Bot, Event, GroupMessageEvent
-from nonebot.typing import T_State
-from services.log import logger
-from nonebot import on_command
-
-
-__zx_plugin_name__ = "点歌"
-__plugin_usage__ = """
-usage:
- 在线点歌
- 指令:
- 点歌 [歌名]
-""".strip()
-__plugin_des__ = "为你点播了一首曾经的歌"
-__plugin_cmd__ = ["点歌 [歌名]"]
-__plugin_type__ = ("一些工具",)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["点歌"],
-}
-
-
-songpicker = on_command("点歌", priority=5, block=True)
-
-
-@songpicker.handle()
-async def handle_first_receive(bot: Bot, event: Event, state: T_State):
- args = str(event.get_message()).strip()
- if args:
- state["song_name"] = args
-
-
-@songpicker.got("song_name", prompt="歌名是?")
-async def _(bot: Bot, event: Event, state: T_State):
- song = state["song_name"]
- song_id = await get_song_id(song)
- if not song_id:
- await songpicker.finish("没有找到这首歌!", at_sender=True)
- for _ in range(3):
- song_content = [{"type": "music", "data": {"type": 163, "id": song_id}}]
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 点歌 :{song}"
- )
- await songpicker.finish(song_content)
- else:
- await songpicker.finish("网易云繁忙...")
-
-
-
-
+from .music_163 import get_song_id, get_song_info
+from nonebot.adapters.cqhttp import Bot, Event, GroupMessageEvent
+from nonebot.typing import T_State
+from services.log import logger
+from nonebot import on_command
+
+
+__zx_plugin_name__ = "点歌"
+__plugin_usage__ = """
+usage:
+ 在线点歌
+ 指令:
+ 点歌 [歌名]
+""".strip()
+__plugin_des__ = "为你点播了一首曾经的歌"
+__plugin_cmd__ = ["点歌 [歌名]"]
+__plugin_type__ = ("一些工具",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["点歌"],
+}
+
+
+music = on_command("点歌", priority=5, block=True)
+
+
+@music.handle()
+async def handle_first_receive(bot: Bot, event: Event, state: T_State):
+ args = str(event.get_message()).strip()
+ if args:
+ state["song_name"] = args
+
+
+@music.got("song_name", prompt="歌名是?")
+async def _(bot: Bot, event: Event, state: T_State):
+ song = state["song_name"]
+ song_id = await get_song_id(song)
+ if not song_id:
+ await music.finish("没有找到这首歌!", at_sender=True)
+ for _ in range(3):
+ song_content = [{"type": "music", "data": {"type": 163, "id": song_id}}]
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 点歌 :{song}"
+ )
+ await music.finish(song_content)
+ else:
+ await music.finish("网易云繁忙...")
+
+
+
+
diff --git a/plugins/c_song/music_163.py b/plugins/c_song/music_163.py
old mode 100644
new mode 100755
index 0202313b..8552d06f
--- a/plugins/c_song/music_163.py
+++ b/plugins/c_song/music_163.py
@@ -1,47 +1,38 @@
-import aiohttp
-import json
-
-
-headers = {"referer": "http://music.163.com"}
-cookies = {"appver": "2.0.2"}
-
-
-async def search_song(song_name: str):
- async with aiohttp.ClientSession(
- headers=headers, cookies=cookies
- ) as session:
- async with session.post(
- f"http://music.163.com/api/search/get/",
- data={"s": song_name, "limit": 1, "type": 1, "offset": 0},
- ) as r:
- if r.status != 200:
- return None
- r = await r.text()
- return json.loads(r)
-
-
-async def get_song_id(songName: str) -> int:
- """
- 根据用户输入的songName 获取候选songId列表 [默认songId数量:5]
- """
- r = await search_song(songName)
- return r["result"]["songs"][0]["id"]
-
-
-async def get_song_info(songId: int):
- """
- 获取歌曲信息
- """
- async with aiohttp.ClientSession(
- headers=headers, cookies=cookies
- ) as session:
- async with session.post(
- f"http://music.163.com/api/song/detail/?id={songId}&ids=%5B{songId}%5D",
- ) as r:
- if r.status != 200:
- return None
- r = await r.text()
- return json.loads(r)
-
-
-
+from utils.http_utils import AsyncHttpx
+import json
+
+
+headers = {"referer": "http://music.163.com"}
+cookies = {"appver": "2.0.2"}
+
+
+async def search_song(song_name: str):
+ """
+ 搜索歌曲
+ :param song_name: 歌名
+ """
+ r = await AsyncHttpx.post(
+ f"http://music.163.com/api/search/get/",
+ data={"s": song_name, "limit": 1, "type": 1, "offset": 0},
+ )
+ if r.status_code != 200:
+ return None
+ return json.loads(r.text)
+
+
+async def get_song_id(song_name: str) -> int:
+ """ """
+ r = await search_song(song_name)
+ return r["result"]["songs"][0]["id"]
+
+
+async def get_song_info(songId: int):
+ """
+ 获取歌曲信息
+ """
+ r = await AsyncHttpx.post(
+ f"http://music.163.com/api/song/detail/?id={songId}&ids=%5B{songId}%5D",
+ )
+ if r.status_code != 200:
+ return None
+ return json.loads(r.text)
diff --git a/plugins/check/__init__.py b/plugins/check/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/check/data_source.py b/plugins/check/data_source.py
old mode 100644
new mode 100755
index 81b156ee..c77865cf
--- a/plugins/check/data_source.py
+++ b/plugins/check/data_source.py
@@ -1,11 +1,7 @@
import psutil
-import aiohttp
import time
from datetime import datetime
-from utils.user_agent import get_user_agent
-from asyncio.exceptions import TimeoutError
-from aiohttp.client_exceptions import ClientConnectorError
-from utils.utils import get_local_proxy
+from utils.http_utils import AsyncHttpx
from utils.image_utils import CreateImg
from configs.path_config import IMAGE_PATH
from pathlib import Path
@@ -34,23 +30,16 @@ class Check:
self.disk = psutil.disk_usage("/").percent
async def check_network(self):
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- try:
- async with session.get(
- "https://www.baidu.com/", proxy=get_local_proxy(), timeout=3
- ) as response:
- pass
- except (TimeoutError, ClientConnectorError) as e:
- logger.warning(f"访问BaiDu失败... e: {e}")
- self.baidu = 404
- try:
- async with session.get(
- "https://www.google.com/", proxy=get_local_proxy(), timeout=3
- ) as response:
- pass
- except (TimeoutError, ClientConnectorError) as e:
- logger.warning(f"访问Google失败... e: {e}")
- self.google = 404
+ try:
+ await AsyncHttpx.get("https://www.baidu.com/", timeout=5)
+ except Exception as e:
+ logger.warning(f"访问BaiDu失败... {type(e)}: {e}")
+ self.baidu = 404
+ try:
+ await AsyncHttpx.get("https://www.google.com/", timeout=5)
+ except Exception as e:
+ logger.warning(f"访问Google失败... {type(e)}: {e}")
+ self.google = 404
def check_user(self):
rst = ""
diff --git a/plugins/check_zhenxun_update/__init__.py b/plugins/check_zhenxun_update/__init__.py
old mode 100644
new mode 100755
index 1014025b..ff590e40
--- a/plugins/check_zhenxun_update/__init__.py
+++ b/plugins/check_zhenxun_update/__init__.py
@@ -1,126 +1,126 @@
-from nonebot.adapters.cqhttp import Bot, MessageEvent
-from nonebot.typing import T_State
-from nonebot.permission import SUPERUSER
-from nonebot import on_command
-from .data_source import check_update, get_latest_version_data
-from services.log import logger
-from utils.utils import scheduler, get_bot
-from pathlib import Path
-from configs.config import Config
-from nonebot.rule import to_me
-import platform
-import os
-
-
-__zx_plugin_name__ = "自动更新 [Superuser]"
-__plugin_usage__ = """
-usage:
- 检查更新真寻最新版本,包括了自动更新
- 指令:
- 检查更新真寻
- 重启
-""".strip()
-__plugin_des__ = "就算是真寻也会成长的"
-__plugin_cmd__ = ["检查更新真寻", "重启"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_configs__ = {
- "AUTO_UPDATE_ZHENXUN": {
- "value": False,
- "help": "真寻是否自动检查更新",
- "default": False,
- }
-}
-
-update_zhenxun = on_command("检查更新真寻", permission=SUPERUSER, priority=1, block=True)
-
-restart = on_command(
- "重启",
- aliases={"restart"},
- permission=SUPERUSER,
- rule=to_me(),
- priority=1,
- block=True,
-)
-
-
-@update_zhenxun.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- try:
- code, error = await check_update(bot)
- if error:
- logger.error(f"更新真寻未知错误 {error}")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]), message=f"更新真寻未知错误 {error}"
- )
- except Exception as e:
- logger.error(f"更新真寻未知错误 {type(e)}:{e}")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"更新真寻未知错误 {type(e)}:{e}",
- )
- else:
- if code == 200:
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]), message=f"更新完毕,请重启真寻...."
- )
-
-
-@restart.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if str(platform.system()).lower() == "windows":
- await restart.finish("暂无windows重启脚本...")
-
-
-@restart.got("flag", prompt="确定是否重启真寻?(重启失败咱们将失去联系,请谨慎!)")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- flag = state["flag"]
- if flag.lower() in ["true", "是", "好", "确定", "确定是"]:
- await restart.send("开始重启真寻..请稍等...")
- open("is_restart", "w")
- os.system("./restart.sh")
- else:
- await restart.send("已取消操作...")
-
-
-@scheduler.scheduled_job(
- "cron",
- hour=12,
- minute=0,
-)
-async def _():
- if Config.get_config("check_zhenxun_update", "AUTO_UPDATE_ZHENXUN"):
- _version = "v0.0.0"
- _version_file = Path() / "__version__"
- if _version_file.exists():
- _version = (
- open(_version_file, "r", encoding="utf8")
- .readline()
- .split(":")[-1]
- .strip()
- )
- data = await get_latest_version_data()
- if data:
- latest_version = data["name"]
- if _version != latest_version:
- bot = get_bot()
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"检测到真寻版本更新\n"
- f"当前版本:{_version},最新版本:{latest_version}\n"
- f"尝试自动更新...",
- )
- try:
- code = await check_update(bot)
- except Exception as e:
- logger.error(f"更新真寻未知错误 {type(e)}:{e}")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"更新真寻未知错误 {type(e)}:{e}\n",
- )
- else:
- if code == 200:
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"更新完毕,请重启真寻....",
- )
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from nonebot.typing import T_State
+from nonebot.permission import SUPERUSER
+from nonebot import on_command
+from .data_source import check_update, get_latest_version_data
+from services.log import logger
+from utils.utils import scheduler, get_bot
+from pathlib import Path
+from configs.config import Config
+from nonebot.rule import to_me
+import platform
+import os
+
+
+__zx_plugin_name__ = "自动更新 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 检查更新真寻最新版本,包括了自动更新
+ 指令:
+ 检查更新真寻
+ 重启
+""".strip()
+__plugin_des__ = "就算是真寻也会成长的"
+__plugin_cmd__ = ["检查更新真寻", "重启"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_configs__ = {
+ "AUTO_UPDATE_ZHENXUN": {
+ "value": False,
+ "help": "真寻是否自动检查更新",
+ "default": False,
+ }
+}
+
+update_zhenxun = on_command("检查更新真寻", permission=SUPERUSER, priority=1, block=True)
+
+restart = on_command(
+ "重启",
+ aliases={"restart"},
+ permission=SUPERUSER,
+ rule=to_me(),
+ priority=1,
+ block=True,
+)
+
+
+@update_zhenxun.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ try:
+ code, error = await check_update(bot)
+ if error:
+ logger.error(f"更新真寻未知错误 {error}")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]), message=f"更新真寻未知错误 {error}"
+ )
+ except Exception as e:
+ logger.error(f"更新真寻未知错误 {type(e)}:{e}")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"更新真寻未知错误 {type(e)}:{e}",
+ )
+ else:
+ if code == 200:
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]), message=f"更新完毕,请重启真寻...."
+ )
+
+
+@restart.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if str(platform.system()).lower() == "windows":
+ await restart.finish("暂无windows重启脚本...")
+
+
+@restart.got("flag", prompt="确定是否重启真寻?(重启失败咱们将失去联系,请谨慎!)")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ flag = state["flag"]
+ if flag.lower() in ["true", "是", "好", "确定", "确定是"]:
+ await restart.send("开始重启真寻..请稍等...")
+ open("is_restart", "w")
+ os.system("./restart.sh")
+ else:
+ await restart.send("已取消操作...")
+
+
+@scheduler.scheduled_job(
+ "cron",
+ hour=12,
+ minute=0,
+)
+async def _():
+ if Config.get_config("check_zhenxun_update", "AUTO_UPDATE_ZHENXUN"):
+ _version = "v0.0.0"
+ _version_file = Path() / "__version__"
+ if _version_file.exists():
+ _version = (
+ open(_version_file, "r", encoding="utf8")
+ .readline()
+ .split(":")[-1]
+ .strip()
+ )
+ data = await get_latest_version_data()
+ if data:
+ latest_version = data["name"]
+ if _version != latest_version:
+ bot = get_bot()
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"检测到真寻版本更新\n"
+ f"当前版本:{_version},最新版本:{latest_version}\n"
+ f"尝试自动更新...",
+ )
+ try:
+ code = await check_update(bot)
+ except Exception as e:
+ logger.error(f"更新真寻未知错误 {type(e)}:{e}")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"更新真寻未知错误 {type(e)}:{e}\n",
+ )
+ else:
+ if code == 200:
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"更新完毕,请重启真寻....",
+ )
diff --git a/plugins/check_zhenxun_update/data_source.py b/plugins/check_zhenxun_update/data_source.py
old mode 100644
new mode 100755
index c240fefe..bf7ac1a1
--- a/plugins/check_zhenxun_update/data_source.py
+++ b/plugins/check_zhenxun_update/data_source.py
@@ -1,231 +1,212 @@
-from aiohttp.client_exceptions import ClientConnectorError
-from nonebot.adapters.cqhttp import Bot, Message
-from utils.user_agent import get_user_agent
-from utils.utils import get_local_proxy
-from utils.image_utils import CreateImg
-from configs.path_config import IMAGE_PATH
-from utils.message_builder import image
-from typing import List
-from services.log import logger
-from pathlib import Path
-import ujson as json
-import nonebot
-import asyncio
-import aiofiles
-import aiohttp
-import platform
-import tarfile
-import shutil
-import os
-
-if str(platform.system()).lower() == "windows":
- policy = asyncio.WindowsSelectorEventLoopPolicy()
- asyncio.set_event_loop_policy(policy)
-
-
-driver = nonebot.get_driver()
-
-release_url = "https://api.github.com/repos/HibiKier/zhenxun_bot/releases/latest"
-
-_version_file = Path() / "__version__"
-zhenxun_latest_tar_gz = Path() / "zhenxun_latest_file.tar.gz"
-temp_dir = Path() / "temp"
-backup_dir = Path() / "backup"
-
-
-@driver.on_bot_connect
-async def remind(bot: Bot):
- if str(platform.system()).lower() != "windows":
- restart = Path() / "restart.sh"
- if not restart.exists():
- with open(restart, "w", encoding="utf8") as f:
- f.write(
- f"pid=$(netstat -tunlp | grep "
- + str(bot.config.port)
- + " | awk '{print $7}')\n"
- "pid=${pid%/*}\n"
- "kill -9 $pid\n"
- "sleep 3\n"
- "python3 bot.py"
- )
- os.system("chmod +x ./restart.sh")
- logger.info("已自动生成 restart.sh(重启) 文件,请检查脚本是否与本地指令符合...")
- is_restart_file = Path() / "is_restart"
- if is_restart_file.exists():
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"真寻重启完毕...",
- )
- is_restart_file.unlink()
-
-
-async def check_update(bot: Bot) -> 'int, str':
- logger.info("开始检查更新真寻酱....")
- _version = "v0.0.0"
- if _version_file.exists():
- _version = (
- open(_version_file, "r", encoding="utf8").readline().split(":")[-1].strip()
- )
- data = await get_latest_version_data()
- if data:
- latest_version = data["name"]
- if _version != latest_version:
- tar_gz_url = data["tarball_url"]
- logger.info(f"检测真寻已更新,当前版本:{_version},最新版本:{latest_version}")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"检测真寻已更新,当前版本:{_version},最新版本:{latest_version}\n" f"开始更新.....",
- )
- logger.info(f"开始下载真寻最新版文件....")
- if await download_latest_file(tar_gz_url):
- logger.info("下载真寻最新版文件完成....")
- error = await asyncio.get_event_loop().run_in_executor(
- None, _file_handle, latest_version
- )
- if error:
- return 998, error
- logger.info("真寻更新完毕,清理文件完成....")
- logger.info("开始获取真寻更新日志.....")
- update_info = data["body"]
- width = 0
- height = len(update_info.split('\n')) * 24
- A = CreateImg(width, height, font_size=20)
- for m in update_info.split('\n'):
- w, h = A.getsize(m)
- if w > width:
- width = w
- A = CreateImg(width + 50, height, font_size=20)
- A.text((10, 10), update_info)
- A.save(f'{IMAGE_PATH}/update_info.png')
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=Message(f"真寻更新完成,版本:{_version} -> {latest_version}\n"
- f"更新日期:{data['created_at']}\n"
- f"更新日志:\n"
- f"{image('update_info.png')}"),
- )
- return 200, ''
- else:
- logger.warning(f"下载真寻最新版本失败...版本号:{latest_version}")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"下载真寻最新版本失败...版本号:{latest_version}.",
- )
- else:
- logger.info(f"自动获取真寻版本成功:{latest_version},当前版本为最新版,无需更新...")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"自动获取真寻版本成功:{latest_version},当前版本为最新版,无需更新...",
- )
- else:
- logger.warning("自动获取真寻版本失败....")
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]), message=f"自动获取真寻版本失败...."
- )
- return 999, ''
-
-
-def _file_handle(latest_version: str) -> str:
- if not temp_dir.exists():
- temp_dir.mkdir(exist_ok=True, parents=True)
- if backup_dir.exists():
- shutil.rmtree(backup_dir)
- tf = None
- error = ''
- try:
- backup_dir.mkdir(exist_ok=True, parents=True)
- logger.info("开始解压真寻文件压缩包....")
- tf = tarfile.open(zhenxun_latest_tar_gz)
- tf.extractall(temp_dir)
- logger.info("解压真寻文件压缩包完成....")
- zhenxun_latest_file = Path(temp_dir) / os.listdir(temp_dir)[0]
- update_info_file = Path(zhenxun_latest_file) / "update_info.json"
- update_info = json.load(open(update_info_file, "r", encoding="utf8"))
- update_file = update_info["update_file"]
- add_file = update_info["add_file"]
- delete_file = update_info["delete_file"]
- config_file = Path() / "configs" / "config.py"
- config_path_file = Path() / "configs" / "config_path.py"
- for file in delete_file + update_file:
- file = Path() / file
- backup_file = Path(backup_dir) / file
- if file.exists():
- backup_file.parent.mkdir(parents=True, exist_ok=True)
- if backup_file.exists():
- backup_file.unlink()
- if file not in [config_file, config_path_file]:
- os.rename(file.absolute(), backup_file.absolute())
- else:
- with open(file, "r", encoding="utf8") as rf:
- data = rf.read()
- with open(backup_file, "w", encoding="utf8") as wf:
- wf.write(data)
- logger.info(f"已备份文件:{file}")
- for file in add_file + update_file:
- new_file = Path(zhenxun_latest_file) / file
- old_file = Path() / file
- if old_file not in [config_file, config_path_file]:
- if not old_file.exists() and new_file.exists():
- os.rename(new_file.absolute(), old_file.absolute())
- logger.info(f"已更新文件:{file}")
- else:
- tmp = ""
- new_lines = open(new_file, "r", encoding="utf8").readlines()
- old_lines = open(old_file, "r", encoding="utf8").readlines()
- for nl in new_lines:
- tmp += check_old_lines(old_lines, nl)
- with open(file, "w", encoding="utf8") as f:
- f.write(tmp)
- except Exception as e:
- error = f'{type(e)}:{e}'
- if tf:
- tf.close()
- if temp_dir.exists():
- shutil.rmtree(temp_dir)
- if zhenxun_latest_tar_gz.exists():
- zhenxun_latest_tar_gz.unlink()
- local_update_info_file = Path() / "update_info.json"
- if local_update_info_file.exists():
- local_update_info_file.unlink()
- with open(_version_file, "w", encoding="utf8") as f:
- f.write(f"__version__: {latest_version}")
- return error
-
-
-# 获取最新版本号
-async def get_latest_version_data() -> dict:
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- for _ in range(3):
- try:
- async with session.get(release_url, proxy=get_local_proxy()) as res:
- if res.status == 200:
- return await res.json()
- except (TimeoutError, ClientConnectorError):
- pass
- return {}
-
-
-# 下载文件
-async def download_latest_file(url_: str) -> bool:
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- for _ in range(3):
- try:
- async with session.get(url_, proxy=get_local_proxy()) as res:
- if res.status == 200:
- async with aiofiles.open(zhenxun_latest_tar_gz, "wb") as f:
- await f.write(await res.read())
- return True
- except (TimeoutError, ClientConnectorError):
- pass
- return False
-
-
-# 逐行检测
-def check_old_lines(lines: List[str], line: str) -> str:
- if "=" not in line:
- return line
- for l in lines:
- if "=" in l and l.split("=")[0].strip() == line.split("=")[0].strip():
- if l.split("=")[1].strip() == 'None':
- return l
- return line
+from nonebot.adapters.cqhttp import Bot, Message
+from utils.image_utils import CreateImg
+from configs.path_config import IMAGE_PATH
+from utils.message_builder import image
+from utils.http_utils import AsyncHttpx
+from typing import List
+from services.log import logger
+from pathlib import Path
+import ujson as json
+import nonebot
+import asyncio
+import platform
+import tarfile
+import shutil
+import os
+
+if str(platform.system()).lower() == "windows":
+ policy = asyncio.WindowsSelectorEventLoopPolicy()
+ asyncio.set_event_loop_policy(policy)
+
+
+driver = nonebot.get_driver()
+
+release_url = "https://api.github.com/repos/HibiKier/zhenxun_bot/releases/latest"
+
+_version_file = Path() / "__version__"
+zhenxun_latest_tar_gz = Path() / "zhenxun_latest_file.tar.gz"
+temp_dir = Path() / "temp"
+backup_dir = Path() / "backup"
+
+
+@driver.on_bot_connect
+async def remind(bot: Bot):
+ if str(platform.system()).lower() != "windows":
+ restart = Path() / "restart.sh"
+ if not restart.exists():
+ with open(restart, "w", encoding="utf8") as f:
+ f.write(
+ f"pid=$(netstat -tunlp | grep "
+ + str(bot.config.port)
+ + " | awk '{print $7}')\n"
+ "pid=${pid%/*}\n"
+ "kill -9 $pid\n"
+ "sleep 3\n"
+ "python3 bot.py"
+ )
+ os.system("chmod +x ./restart.sh")
+ logger.info("已自动生成 restart.sh(重启) 文件,请检查脚本是否与本地指令符合...")
+ is_restart_file = Path() / "is_restart"
+ if is_restart_file.exists():
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"真寻重启完毕...",
+ )
+ is_restart_file.unlink()
+
+
+async def check_update(bot: Bot) -> 'int, str':
+ logger.info("开始检查更新真寻酱....")
+ _version = "v0.0.0"
+ if _version_file.exists():
+ _version = (
+ open(_version_file, "r", encoding="utf8").readline().split(":")[-1].strip()
+ )
+ data = await get_latest_version_data()
+ if data:
+ latest_version = data["name"]
+ if _version != latest_version:
+ tar_gz_url = data["tarball_url"]
+ logger.info(f"检测真寻已更新,当前版本:{_version},最新版本:{latest_version}")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"检测真寻已更新,当前版本:{_version},最新版本:{latest_version}\n" f"开始更新.....",
+ )
+ logger.info(f"开始下载真寻最新版文件....")
+ if await AsyncHttpx.download_file(tar_gz_url, zhenxun_latest_tar_gz):
+ logger.info("下载真寻最新版文件完成....")
+ error = await asyncio.get_event_loop().run_in_executor(
+ None, _file_handle, latest_version
+ )
+ if error:
+ return 998, error
+ logger.info("真寻更新完毕,清理文件完成....")
+ logger.info("开始获取真寻更新日志.....")
+ update_info = data["body"]
+ width = 0
+ height = len(update_info.split('\n')) * 24
+ A = CreateImg(width, height, font_size=20)
+ for m in update_info.split('\n'):
+ w, h = A.getsize(m)
+ if w > width:
+ width = w
+ A = CreateImg(width + 50, height, font_size=20)
+ A.text((10, 10), update_info)
+ A.save(f'{IMAGE_PATH}/update_info.png')
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=Message(f"真寻更新完成,版本:{_version} -> {latest_version}\n"
+ f"更新日期:{data['created_at']}\n"
+ f"更新日志:\n"
+ f"{image('update_info.png')}"),
+ )
+ return 200, ''
+ else:
+ logger.warning(f"下载真寻最新版本失败...版本号:{latest_version}")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"下载真寻最新版本失败...版本号:{latest_version}.",
+ )
+ else:
+ logger.info(f"自动获取真寻版本成功:{latest_version},当前版本为最新版,无需更新...")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"自动获取真寻版本成功:{latest_version},当前版本为最新版,无需更新...",
+ )
+ else:
+ logger.warning("自动获取真寻版本失败....")
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]), message=f"自动获取真寻版本失败...."
+ )
+ return 999, ''
+
+
+def _file_handle(latest_version: str) -> str:
+ if not temp_dir.exists():
+ temp_dir.mkdir(exist_ok=True, parents=True)
+ if backup_dir.exists():
+ shutil.rmtree(backup_dir)
+ tf = None
+ error = ''
+ try:
+ backup_dir.mkdir(exist_ok=True, parents=True)
+ logger.info("开始解压真寻文件压缩包....")
+ tf = tarfile.open(zhenxun_latest_tar_gz)
+ tf.extractall(temp_dir)
+ logger.info("解压真寻文件压缩包完成....")
+ zhenxun_latest_file = Path(temp_dir) / os.listdir(temp_dir)[0]
+ update_info_file = Path(zhenxun_latest_file) / "update_info.json"
+ update_info = json.load(open(update_info_file, "r", encoding="utf8"))
+ update_file = update_info["update_file"]
+ add_file = update_info["add_file"]
+ delete_file = update_info["delete_file"]
+ config_file = Path() / "configs" / "config.py"
+ config_path_file = Path() / "configs" / "config_path.py"
+ for file in delete_file + update_file:
+ file = Path() / file
+ backup_file = Path(backup_dir) / file
+ if file.exists():
+ backup_file.parent.mkdir(parents=True, exist_ok=True)
+ if backup_file.exists():
+ backup_file.unlink()
+ if file not in [config_file, config_path_file]:
+ os.rename(file.absolute(), backup_file.absolute())
+ else:
+ with open(file, "r", encoding="utf8") as rf:
+ data = rf.read()
+ with open(backup_file, "w", encoding="utf8") as wf:
+ wf.write(data)
+ logger.info(f"已备份文件:{file}")
+ for file in add_file + update_file:
+ new_file = Path(zhenxun_latest_file) / file
+ old_file = Path() / file
+ if old_file not in [config_file, config_path_file]:
+ if not old_file.exists() and new_file.exists():
+ os.rename(new_file.absolute(), old_file.absolute())
+ logger.info(f"已更新文件:{file}")
+ else:
+ tmp = ""
+ new_lines = open(new_file, "r", encoding="utf8").readlines()
+ old_lines = open(old_file, "r", encoding="utf8").readlines()
+ for nl in new_lines:
+ tmp += check_old_lines(old_lines, nl)
+ with open(file, "w", encoding="utf8") as f:
+ f.write(tmp)
+ except Exception as e:
+ error = f'{type(e)}:{e}'
+ if tf:
+ tf.close()
+ if temp_dir.exists():
+ shutil.rmtree(temp_dir)
+ if zhenxun_latest_tar_gz.exists():
+ zhenxun_latest_tar_gz.unlink()
+ local_update_info_file = Path() / "update_info.json"
+ if local_update_info_file.exists():
+ local_update_info_file.unlink()
+ with open(_version_file, "w", encoding="utf8") as f:
+ f.write(f"__version__: {latest_version}")
+ return error
+
+
+# 获取最新版本号
+async def get_latest_version_data() -> dict:
+ for _ in range(3):
+ try:
+ res = await AsyncHttpx.get(release_url)
+ if res.status_code == 200:
+ return res.json()
+ except TimeoutError:
+ pass
+ except Exception as e:
+ logger.error(f"检查更新真寻获取版本失败 {type(e)}:{e}")
+ return {}
+
+
+# 逐行检测
+def check_old_lines(lines: List[str], line: str) -> str:
+ if "=" not in line:
+ return line
+ for l in lines:
+ if "=" in l and l.split("=")[0].strip() == line.split("=")[0].strip():
+ return l
+ return line
diff --git a/plugins/coser/__init__.py b/plugins/coser/__init__.py
old mode 100644
new mode 100755
index 1d67c019..947dc567
--- a/plugins/coser/__init__.py
+++ b/plugins/coser/__init__.py
@@ -1,13 +1,8 @@
from nonebot import on_command
from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from services.log import logger
-from asyncio.exceptions import TimeoutError
+from nonebot.adapters.cqhttp import Bot, MessageEvent
from utils.message_builder import image
-from configs.path_config import IMAGE_PATH
-from utils.utils import get_local_proxy
-import aiohttp
-import aiofiles
+from services.log import logger
__zx_plugin_name__ = "coser"
__plugin_usage__ = """
@@ -32,38 +27,13 @@ coser = on_command(
)
-url = "http://ovooa.com/API/cosplay/api.php"
+url = "http://iw233.cn/API/cos.php"
@coser.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
- async with aiohttp.ClientSession() as session:
- try:
- for _ in range(3):
- try:
- async with session.get(url, proxy=get_local_proxy(), timeout=2, verify_ssl=False) as response:
- _url = (await response.json())['text']
- async with session.get(
- _url, timeout=5, proxy=get_local_proxy(), verify_ssl=False
- ) as res:
- if res.status == 200:
- async with aiofiles.open(
- f"{IMAGE_PATH}/temp/{event.user_id}_coser.jpg", "wb"
- ) as f:
- await f.write(await res.read())
- logger.info(
- f"(USER {event.user_id}, "
- f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送COSER"
- )
- await coser.send(
- image(f"{event.user_id}_coser.jpg", "temp")
- )
- break
- except (TimeoutError, KeyError):
- pass
- else:
- await coser.send("你cos给我看!")
- except Exception as e:
- await coser.send("发生了预料之外的错误..请稍后再试或联系管理员修复...")
- logger.error(f"coser 发送了未知错误 {type(e)}:{e}")
+ try:
+ await coser.send(image(url))
+ except Exception as e:
+ await coser.send("你cos给我看!")
+ logger.error(f"coser 发送了未知错误 {type(e)}:{e}")
diff --git a/plugins/csgo/__init__.py b/plugins/csgo/__init__.py
deleted file mode 100644
index e955a89f..00000000
--- a/plugins/csgo/__init__.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
-from utils.utils import get_message_text, is_number
-from .data_source import get_csgola_data, get_5e_data
-from services.log import logger
-
-
-__zx_plugin_name__ = "cs国服/平台信息查找"
-__plugin_usage__ = """
-usage:
- 快速查询csgo战绩和数据
- 指令:
- cs国服查询 [steam主页个人id]
- 5e查询 [5e战绩个人名称]
- 示例:cs国服查询 23848238483
- 示例:5e查询 poster
-"""
-__plugin_des__ = "什么?你也是rush B玩家?"
-__plugin_cmd__ = ["cs国服查询 [steam主页个人id]", "5e查询 [5e战绩个人名称]"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["csgo战绩查询", "cs国服查询", "5e查询"],
-}
-
-csgola = on_command("cs国服查询", priority=5, block=True)
-
-csgo5e = on_command("5e查询", priority=5, block=True)
-
-
-@csgola.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if "http" in msg:
- msg = msg[:-1] if msg[-1] == "/" else msg
- msg = msg.split("/")[-1]
- if not is_number(msg):
- await csgola.finish("Id必须为数字!", at_sender=True)
- await csgola.send("开始查找...")
- img, code = await get_csgola_data(int(msg))
- if code == 200:
- await csgola.send(img, at_sender=True)
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查询csgo国服战绩:{msg}"
- )
- else:
- await csgola.send(img, at_sender=True)
-
-
-@csgo5e.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- await csgola.send("开始查找...")
- img, code = await get_5e_data(msg)
- if code == 200:
- await csgo5e.send(img, at_sender=True)
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查询csgo国服战绩:{msg}"
- )
- else:
- await csgo5e.send(img, at_sender=True)
diff --git a/plugins/csgo/data_source.py b/plugins/csgo/data_source.py
deleted file mode 100644
index b6c6969e..00000000
--- a/plugins/csgo/data_source.py
+++ /dev/null
@@ -1,130 +0,0 @@
-from configs.path_config import IMAGE_PATH
-from utils.image_utils import CreateImg
-from utils.message_builder import image
-from services.log import logger
-from utils.browser import get_browser
-from playwright._impl._api_types import TimeoutError
-
-csgola_url = "https://www.csgola.com/player/"
-_5e_url = "https://arena.5eplay.com/data/player/"
-
-
-async def get_csgola_data(uid: int) -> "str, int":
- page = None
- try:
- browser = await get_browser()
- if not browser:
- return "", 997
- page = await browser.new_page()
- for _ in range(3):
- try:
- await page.goto(f"{csgola_url}{uid}", wait_until="networkidle", timeout=10000)
- break
- except TimeoutError:
- pass
- else:
- return '连接超时...', 995
- await page.set_viewport_size({"width": 2560, "height": 1080})
-
- data = await page.query_selector_all(".panel-body")
- if not data:
- return "未查询到该Id....", 999
- await data[0].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_1.png", timeout=100000)
- await data[3].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_2.png", timeout=100000)
- await data[5].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_3.png", timeout=100000)
- await data[7].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_5.png", timeout=100000)
-
- ava = await page.query_selector("div.container:nth-child(4) > div:nth-child(1)")
- await ava.screenshot(path=f"{IMAGE_PATH}/temp/{uid}_0.png", timeout=100000)
-
- weapon_data = await page.query_selector(".gun-stats-sec")
- await weapon_data.screenshot(
- path=f"{IMAGE_PATH}/temp/{uid}_4.png", timeout=100000
- )
-
- ava = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_0.png")
- statistical_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_1.png")
- combined_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_2.png")
- detailed_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_3.png")
- weapon_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_4.png")
- map_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_5.png")
- if statistical_data.h > 300:
- statistical_data.crop((0, 0, statistical_data.w, 300))
- if combined_data.h > 260:
- combined_data.crop((0, 0, combined_data.w, 260))
- if detailed_data.h > 400:
- detailed_data.crop((0, 0, detailed_data.w, 400))
- weapon_data.crop((0, 100, weapon_data.w, weapon_data.h))
- map_data.crop((0, 310, map_data.w, map_data.h))
- height = (
- ava.h
- + statistical_data.h
- + combined_data.h
- + detailed_data.h
- + weapon_data.h
- + map_data.h
- )
- bk = CreateImg(1168, height)
- current_h = 0
- for img in [
- ava,
- statistical_data,
- combined_data,
- detailed_data,
- weapon_data,
- map_data,
- ]:
- bk.paste(img, (0, current_h))
- current_h += img.h
- bk.save(f"{IMAGE_PATH}/temp/csgo_{uid}.png")
- except Exception as e:
- logger.error(f"生成csgola图片错误 {type(e)}:{e}")
- if page:
- await page.close()
- return "发生了错误....", 998
- if page:
- await page.close()
- return image(f"csgo_{uid}.png", "temp"), 200
-
-
-async def get_5e_data(uname: str) -> "str, int":
- page = None
- try:
- browser = await get_browser()
- if not browser:
- return "", 997
- page = await browser.new_page()
- await page.goto(f"{_5e_url}{uname}", wait_until="networkidle", timeout=10000)
- if "HTTP ERROR 404" in await page.content():
- return "未查询到该玩家...", 999
- await page.set_viewport_size({"width": 2560, "height": 1080})
- body = await page.query_selector("body")
- await body.screenshot(
- path=f"{IMAGE_PATH}/temp/csgo_{uname}_0.png", timeout=100000
- )
- await page.click("a.match-tab-item:nth-child(2)")
- body = await page.query_selector("body")
- await body.screenshot(
- path=f"{IMAGE_PATH}/temp/csgo_{uname}_1.png", timeout=100000
- )
- await page.click("a.match-tab-item:nth-child(1)")
- body = await page.query_selector("body")
- await body.screenshot(
- path=f"{IMAGE_PATH}/temp/csgo_{uname}_2.png", timeout=100000
- )
- bk = CreateImg(1344 * 3, 2307)
- current_w = 0
- for i in range(3):
- body = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/csgo_{uname}_{i}.png")
- body.crop((600, 90, body.w - 600, body.h - 410))
- bk.paste(body, (current_w, 0))
- current_w += 1344
- bk.save(f"{IMAGE_PATH}/temp/csgo_{uname}.png")
- except Exception as e:
- logger.error(f"生成5e图片错误 {type(e)}:{e}")
- if page:
- await page.close()
- return "发生了错误...", 998
- if page:
- await page.close()
- return image(f"csgo_{uname}.png", "temp"), 200
diff --git a/plugins/dialogue/__init__.py b/plugins/dialogue/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/__init__.py b/plugins/draw_card/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/announcement.py b/plugins/draw_card/announcement.py
old mode 100644
new mode 100755
index 819fc8d5..42abc559
--- a/plugins/draw_card/announcement.py
+++ b/plugins/draw_card/announcement.py
@@ -1,11 +1,11 @@
-import aiohttp
from bs4 import BeautifulSoup
-import re
from datetime import datetime, timedelta
from .config import DRAW_PATH
from pathlib import Path
from asyncio.exceptions import TimeoutError
from services.log import logger
+from utils.http_utils import AsyncHttpx
+import re
try:
import ujson as json
except ModuleNotFoundError:
@@ -66,16 +66,14 @@ class PrtsAnnouncement:
self.game_name = '明日方舟'
async def _get_announcement_text(self):
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(prts_url, timeout=7) as res:
- soup = BeautifulSoup(await res.text(), 'lxml')
- ol = soup.find('ol', {'class': 'articleList active', 'data-category-key': 'LATEST'})
- for li in ol:
- itype = li.find('span', {'class': 'articleItemCate'}).text
- if itype == '活动':
- a = li.find('a')['href']
- async with session.get(f'https://ak.hypergryph.com{a}', headers=headers, timeout=7) as res:
- return await res.text()
+ text = (await AsyncHttpx.get(prts_url)).text
+ soup = BeautifulSoup(text, 'lxml')
+ ol = soup.find('ol', {'class': 'articleList active', 'data-category-key': 'LATEST'})
+ for li in ol:
+ itype = li.find('span', {'class': 'articleItemCate'}).text
+ if itype == '活动':
+ a = li.find('a')['href']
+ return (await AsyncHttpx.get(f'https://ak.hypergryph.com{a}')).text
async def update_up_char(self):
prts_up_char.parent.mkdir(parents=True, exist_ok=True)
@@ -147,9 +145,7 @@ class GenshinAnnouncement:
self.game_name = '原神'
async def _get_announcement_text(self):
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(genshin_url, timeout=7) as res:
- return await res.text()
+ return (await AsyncHttpx.get(genshin_url)).text
async def update_up_char(self):
genshin_up_char.parent.mkdir(exist_ok=True, parents=True)
@@ -218,21 +214,20 @@ class PrettyAnnouncement:
self.game_name = '赛马娘'
async def _get_announcement_text(self):
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(pretty_url, timeout=7) as res:
- soup = BeautifulSoup(await res.text(), 'lxml')
- divs = soup.find('div', {'id': 'mw-content-text'}).find('div').find_all('div')
- for div in divs:
- a = div.find('a')
- try:
- title = a['title']
- except (KeyError, TypeError):
- continue
- if title.find('新角色追加') != -1:
- url = a['href']
- break
- async with session.get(f'https://wiki.biligame.com/{url}', timeout=7) as res:
- return await res.text(), title[:-2]
+ text = (await AsyncHttpx.get(pretty_url)).text
+ soup = BeautifulSoup(text, 'lxml')
+ divs = soup.find('div', {'id': 'mw-content-text'}).find('div').find_all('div')
+ title = " "
+ for div in divs:
+ a = div.find('a')
+ try:
+ title = a['title']
+ except (KeyError, TypeError):
+ continue
+ if title.find('新角色追加') != -1:
+ url = a['href']
+ break
+ return (await AsyncHttpx.get(f'https://wiki.biligame.com/{url}')).text, title[:-2]
async def update_up_char(self):
pretty_up_char.parent.mkdir(exist_ok=True, parents=True)
@@ -343,9 +338,7 @@ class GuardianAnnouncement:
self.game_name = '坎公骑冠剑'
async def _get_announcement_text(self):
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(guardian_url, timeout=7) as res:
- return await res.text()
+ return (await AsyncHttpx.get(guardian_url)).text
async def update_up_char(self):
data = {
diff --git a/plugins/draw_card/async_update_game_info.py b/plugins/draw_card/async_update_game_info.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/azur_handle.py b/plugins/draw_card/azur_handle.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/config.py b/plugins/draw_card/config.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/fgo_handle.py b/plugins/draw_card/fgo_handle.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/genshin_handle.py b/plugins/draw_card/genshin_handle.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/guardian_handle.py b/plugins/draw_card/guardian_handle.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/init_card_pool.py b/plugins/draw_card/init_card_pool.py
old mode 100644
new mode 100755
index 797659e9..f875b02a
--- a/plugins/draw_card/init_card_pool.py
+++ b/plugins/draw_card/init_card_pool.py
@@ -2,6 +2,7 @@ from typing import Any
from .config import DATA_PATH
from utils.utils import is_number
from pathlib import Path
+from services.log import logger
try:
import ujson as json
except ModuleNotFoundError:
@@ -27,8 +28,11 @@ def init_game_pool(game: str, data: dict, Operator: Any):
limited = True
if key.find('阿米娅') != -1:
continue
- tmp_lst.append(Operator(name=key, star=int(data[key]['星级']),
- limited=limited, recruit_only=recruit_only, event_only=event_only))
+ try:
+ tmp_lst.append(Operator(name=key, star=int(data[key]['星级']),
+ limited=limited, recruit_only=recruit_only, event_only=event_only))
+ except Exception as e:
+ logger.warning(f"明日方舟导入角色 {key} 数据错误:{type(e)}:{e}")
if game == 'genshin':
for key in data.keys():
if key.find('旅行者') != -1:
@@ -36,17 +40,26 @@ def init_game_pool(game: str, data: dict, Operator: Any):
limited = False
if data[key]['常驻/限定'] == '限定UP':
limited = True
- tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited))
+ try:
+ tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited))
+ except Exception as e:
+ logger.warning(f"原神导入角色 {key} 数据错误:{type(e)}:{e}")
if game == 'genshin_arms':
for key in data.keys():
if data[key]['获取途径'].find('祈愿') != -1:
limited = False
if data[key]['获取途径'].find('限定祈愿') != -1:
limited = True
- tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited))
+ try:
+ tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited))
+ except Exception as e:
+ logger.warning(f"原神导入武器 {key} 数据错误:{type(e)}:{e}")
if game == 'pretty':
for key in data.keys():
- tmp_lst.append(Operator(name=key, star=data[key]['初始星级'], limited=False))
+ try:
+ tmp_lst.append(Operator(name=key, star=data[key]['初始星级'], limited=False))
+ except Exception as e:
+ logger.warning(f"赛马娘导入角色 {key} 数据错误:{type(e)}:{e}")
if game == 'pretty_card':
for key in data.keys():
limited = False
@@ -54,7 +67,10 @@ def init_game_pool(game: str, data: dict, Operator: Any):
limited = True
if not data[key]['获取方式']:
limited = False
- tmp_lst.append(Operator(name=data[key]['中文名'], star=len(data[key]['稀有度']), limited=limited))
+ try:
+ tmp_lst.append(Operator(name=data[key]['中文名'], star=len(data[key]['稀有度']), limited=limited))
+ except Exception as e:
+ logger.warning(f"赛马娘导入卡片 {key} 数据错误:{type(e)}:{e}")
if game in ['guardian', 'guardian_arms']:
for key in data.keys():
tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=False))
@@ -63,15 +79,21 @@ def init_game_pool(game: str, data: dict, Operator: Any):
limited = False
if key.find('(') != -1:
limited = True
- tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited))
+ try:
+ tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited))
+ except Exception as e:
+ logger.warning(f"公主连接导入角色 {key} 数据错误:{type(e)}:{e}")
if game == 'azur':
for key in data.keys():
if is_number(data[key]['星级']):
limited = False
if '可以建造' not in data[key]['获取途径']:
limited = True
- tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']),
- limited=limited, itype=data[key]['类型']))
+ try:
+ tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']),
+ limited=limited, itype=data[key]['类型']))
+ except Exception as e:
+ logger.warning(f"碧蓝航线导入角色 {key} 数据错误:{type(e)}:{e}")
if game in ['fgo', 'fgo_card']:
for key in data.keys():
limited = False
@@ -80,14 +102,20 @@ def init_game_pool(game: str, data: dict, Operator: Any):
limited = True
except KeyError:
pass
- tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited))
+ try:
+ tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited))
+ except Exception as e:
+ logger.warning(f"FGO导入角色 {key} 数据错误:{type(e)}:{e}")
if game == 'onmyoji':
for key in data.keys():
limited = False
if key in ['奴良陆生', '卖药郎', '鬼灯', '阿香', '蜜桃&芥子', '犬夜叉', '杀生丸', '桔梗', '朽木露琪亚', '黑崎一护',
'灶门祢豆子', '灶门炭治郎']:
limited = True
- tmp_lst.append(Operator(name=data[key]['名称'], star=data[key]['星级'], limited=limited))
+ try:
+ tmp_lst.append(Operator(name=data[key]['名称'], star=data[key]['星级'], limited=limited))
+ except Exception as e:
+ logger.warning(f"阴阳师导入角色 {key} 数据错误:{type(e)}:{e}")
# print(tmp_lst)
char_name_lst = [x.name for x in tmp_lst]
up_char_file = Path(f'{DATA_PATH}/draw_card/draw_card_up/{game.split("_")[0]}_up_char.json')
diff --git a/plugins/draw_card/onmyoji_handle.py b/plugins/draw_card/onmyoji_handle.py
old mode 100644
new mode 100755
index ca02803f..7b468f0a
--- a/plugins/draw_card/onmyoji_handle.py
+++ b/plugins/draw_card/onmyoji_handle.py
@@ -6,7 +6,6 @@ from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max
from .config import ONMYOJI_SR, ONMYOJI_SSR, ONMYOJI_SP, ONMYOJI_R, DRAW_PATH, ONMYOJI_FLAG
from dataclasses import dataclass
from .init_card_pool import init_game_pool
-import nonebot
try:
import ujson as json
except ModuleNotFoundError:
diff --git a/plugins/draw_card/pcr_handle.py b/plugins/draw_card/pcr_handle.py
old mode 100644
new mode 100755
index 524062fc..c48c8a5a
--- a/plugins/draw_card/pcr_handle.py
+++ b/plugins/draw_card/pcr_handle.py
@@ -1,7 +1,5 @@
import ujson as json
-import os
from nonebot.adapters.cqhttp import MessageSegment
-import nonebot
import random
from .update_game_info import update_info
from .update_game_simple_info import update_simple_info
@@ -10,7 +8,6 @@ from .config import PCR_TWO_P, PCR_THREE_P, PCR_ONE_P, DRAW_PATH, PCR_FLAG, PCR_
from dataclasses import dataclass
from .init_card_pool import init_game_pool
-driver: nonebot.Driver = nonebot.get_driver()
ALL_CHAR = []
diff --git a/plugins/draw_card/pretty_handle.py b/plugins/draw_card/pretty_handle.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/prts_handle.py b/plugins/draw_card/prts_handle.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/rule.py b/plugins/draw_card/rule.py
old mode 100644
new mode 100755
diff --git a/plugins/draw_card/update_game_info.py b/plugins/draw_card/update_game_info.py
old mode 100644
new mode 100755
index af11eb7c..1b588a1d
--- a/plugins/draw_card/update_game_info.py
+++ b/plugins/draw_card/update_game_info.py
@@ -1,13 +1,11 @@
-#coding:utf-8
-import aiohttp
from .config import DRAW_PATH
from asyncio.exceptions import TimeoutError
from bs4 import BeautifulSoup
-import asyncio
from .util import download_img
from urllib.parse import unquote
from services.log import logger
from .util import remove_prohibited_str
+from utils.http_utils import AsyncHttpx
import bs4
import re
try:
@@ -26,40 +24,39 @@ async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict
except (ValueError, FileNotFoundError):
data = {}
try:
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(url, timeout=7) as response:
- soup = BeautifulSoup(await response.text(), 'lxml')
- _tbody = get_tbody(soup, game_name, url)
- trs = _tbody.find_all('tr')
- att_dict, start_index, index = init_attr(game_name)
- if game_name == 'guardian':
- start_index = 1
- if game_name == 'azur':
- start_index = 0
- for th in trs[0].find_all('th')[start_index:]:
- text = th.text
- if text[-1] == '\n':
- text = text[:-1]
- att_dict[text] = index
- index += 1
- for tr in trs[1:]:
- member_dict = {}
- tds = tr.find_all('td')
- if not info_list:
- info_list = att_dict.keys()
- for key in info_list:
- key, attr = parse_key(key, game_name)
- td = tds[att_dict[key]]
- last_tag = unquote(_find_last_tag(td, attr, game_name), 'utf-8')
- member_dict[key] = last_tag
- member_dict = intermediate_check(member_dict, key, game_name, td)
- avatar_img = await _modify_avatar_url(session, game_name, member_dict["名称"])
- member_dict['头像'] = avatar_img if avatar_img else member_dict['头像']
- member_dict, name = replace_update_name(member_dict, game_name)
- await download_img(member_dict['头像'], game_name, name)
- data[name] = member_dict
- logger.info(f'{name} is update...')
- data = await _last_check(data, game_name, session)
+ text = (await AsyncHttpx.get(url)).text
+ soup = BeautifulSoup(text, 'lxml')
+ _tbody = get_tbody(soup, game_name, url)
+ trs = _tbody.find_all('tr')
+ att_dict, start_index, index = init_attr(game_name)
+ if game_name == 'guardian':
+ start_index = 1
+ if game_name == 'azur':
+ start_index = 0
+ for th in trs[0].find_all('th')[start_index:]:
+ text = th.text
+ if text[-1] == '\n':
+ text = text[:-1]
+ att_dict[text] = index
+ index += 1
+ for tr in trs[1:]:
+ member_dict = {}
+ tds = tr.find_all('td')
+ if not info_list:
+ info_list = att_dict.keys()
+ for key in info_list:
+ key, attr = parse_key(key, game_name)
+ td = tds[att_dict[key]]
+ last_tag = unquote(_find_last_tag(td, attr, game_name), 'utf-8')
+ member_dict[key] = last_tag
+ member_dict = intermediate_check(member_dict, key, game_name, td)
+ avatar_img = await _modify_avatar_url(game_name, member_dict["名称"])
+ member_dict['头像'] = avatar_img if avatar_img else member_dict['头像']
+ member_dict, name = replace_update_name(member_dict, game_name)
+ await download_img(member_dict['头像'], game_name, name)
+ data[name] = member_dict
+ logger.info(f'{name} is update...')
+ data = await _last_check(data, game_name)
except TimeoutError:
logger.warning(f'更新 {game_name} 超时...')
return {}, 999
@@ -97,7 +94,7 @@ def _find_last_tag(element: bs4.element.Tag, attr: str, game_name: str) -> str:
# 获取大图(小图快爬)
-async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, char_name: str):
+async def _modify_avatar_url(game_name: str, char_name: str):
# if game_name == 'prts':
# async with session.get(f'https://wiki.biligame.com/arknights/{char_name}', timeout=7) as res:
# soup = BeautifulSoup(await res.text(), 'lxml')
@@ -109,10 +106,10 @@ async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, cha
if game_name == 'genshin':
return None
if game_name == 'pretty_card':
- async with session.get(f'https://wiki.biligame.com/umamusume/{char_name}', timeout=7) as res:
- soup = BeautifulSoup(await res.text(), 'lxml')
- img_url = soup.find('div', {'class': 'support_card-left'}).find('div').find('img').get('src')
- return img_url
+ text = (await AsyncHttpx.get(f'https://wiki.biligame.com/umamusume/{char_name}')).text
+ soup = BeautifulSoup(text, 'lxml')
+ img_url = soup.find('div', {'class': 'support_card-left'}).find('div').find('img').get('src')
+ return img_url
if game_name == 'guardian':
# 未上传图片太多,换成像素图
# async with session.get(f'https://wiki.biligame.com/gt/{char_name}', timeout=7) as res:
@@ -130,7 +127,7 @@ async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, cha
# 数据最后处理(是否需要额外数据或处理数据)
-async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession):
+async def _last_check(data: dict, game_name: str):
# if game_name == 'prts':
# url = 'https://wiki.biligame.com/arknights/'
# tasks = []
@@ -142,23 +139,23 @@ async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession
# data[key]['获取途径'] = x[key]['获取途径']
if game_name == 'genshin':
for key in data.keys():
- async with session.get(f'https://wiki.biligame.com/ys/{key}', timeout=7) as res:
- soup = BeautifulSoup(await res.text(), 'lxml')
- _trs = ''
- for table in soup.find_all('table', {'class': 'wikitable'}):
- if str(table).find('常驻/限定') != -1:
- _trs = table.find('tbody').find_all('tr')
- break
- for tr in _trs:
- data[key]['常驻/限定'] = '未知'
- if str(tr).find('限定UP') != -1:
- data[key]['常驻/限定'] = '限定UP'
- logger.info(f'原神获取额外数据 {key}...{data[key]["常驻/限定"]}')
- break
- elif str(tr).find('常驻UP') != -1:
- data[key]['常驻/限定'] = '常驻UP'
- logger.info(f'原神获取额外数据 {key}...{data[key]["常驻/限定"]}')
- break
+ text = (await AsyncHttpx.get(f'https://wiki.biligame.com/ys/{key}')).text
+ soup = BeautifulSoup(text, 'lxml')
+ _trs = ''
+ for table in soup.find_all('table', {'class': 'wikitable'}):
+ if str(table).find('常驻/限定') != -1:
+ _trs = table.find('tbody').find_all('tr')
+ break
+ for tr in _trs:
+ data[key]['常驻/限定'] = '未知'
+ if str(tr).find('限定UP') != -1:
+ data[key]['常驻/限定'] = '限定UP'
+ logger.info(f'原神获取额外数据 {key}...{data[key]["常驻/限定"]}')
+ break
+ elif str(tr).find('常驻UP') != -1:
+ data[key]['常驻/限定'] = '常驻UP'
+ logger.info(f'原神获取额外数据 {key}...{data[key]["常驻/限定"]}')
+ break
if game_name == 'pretty':
for keys in data.keys():
for key in data[keys].keys():
diff --git a/plugins/draw_card/update_game_requests_info.py b/plugins/draw_card/update_game_requests_info.py
old mode 100644
new mode 100755
index 68af67dc..30032edb
--- a/plugins/draw_card/update_game_requests_info.py
+++ b/plugins/draw_card/update_game_requests_info.py
@@ -1,58 +1,59 @@
-import aiohttp
from .config import DRAW_PATH, SEMAPHORE
from asyncio.exceptions import TimeoutError
from .util import download_img
from bs4 import BeautifulSoup
from .util import remove_prohibited_str
+from utils.http_utils import AsyncHttpx
from services.log import logger
import asyncio
+
try:
import ujson as json
except ModuleNotFoundError:
import json
-headers = {'User-Agent': '"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"'}
+headers = {
+ "User-Agent": '"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"'
+}
async def update_requests_info(game_name: str):
try:
- with open(DRAW_PATH + f'{game_name}.json', 'r', encoding='utf8') as f:
+ with open(DRAW_PATH + f"{game_name}.json", "r", encoding="utf8") as f:
data = json.load(f)
except (ValueError, FileNotFoundError):
data = {}
try:
- async with aiohttp.ClientSession(headers=headers) as session:
- if game_name in ['fgo', 'fgo_card']:
- if game_name == 'fgo':
- url = 'http://fgo.vgtime.com/servant/ajax?card=&wd=&ids=&sort=12777&o=desc&pn='
- else:
- url = 'http://fgo.vgtime.com/equipment/ajax?wd=&ids=&sort=12958&o=desc&pn='
- for i in range(9999):
- async with session.get(f'{url}{i}', timeout=7) as response:
- fgo_data = json.loads(await response.text())
- if int(fgo_data['nums']) == 0:
- break
- for x in fgo_data['data']:
- x['name'] = remove_prohibited_str(x['name'])
- key = x['name']
- data = add_to_data(data, x, game_name)
- await download_img(data[key]['头像'], game_name, key)
- logger.info(f'{key} is update...')
- if game_name == 'onmyoji':
- url = 'https://yys.res.netease.com/pc/zt/20161108171335/js/app/all_shishen.json?v74='
- async with session.get(f'{url}', timeout=7) as response:
- onmyoji_data = await response.json()
- for x in onmyoji_data:
- x['name'] = remove_prohibited_str(x['name'])
- key = x['name']
- data = add_to_data(data, x, game_name)
- logger.info(f'{key} is update...')
- data = await _last_check(data, game_name, session)
+ if game_name in ["fgo", "fgo_card"]:
+ if game_name == "fgo":
+ url = "http://fgo.vgtime.com/servant/ajax?card=&wd=&ids=&sort=12777&o=desc&pn="
+ else:
+ url = "http://fgo.vgtime.com/equipment/ajax?wd=&ids=&sort=12958&o=desc&pn="
+ for i in range(9999):
+ text = (await AsyncHttpx.get(f"{url}{i}")).text
+ fgo_data = json.loads(text)
+ if int(fgo_data["nums"]) == 0:
+ break
+ for x in fgo_data["data"]:
+ x["name"] = remove_prohibited_str(x["name"])
+ key = x["name"]
+ data = add_to_data(data, x, game_name)
+ await download_img(data[key]["头像"], game_name, key)
+ logger.info(f"{key} is update...")
+ if game_name == "onmyoji":
+ url = "https://yys.res.netease.com/pc/zt/20161108171335/js/app/all_shishen.json?v74="
+ onmyoji_data = (await AsyncHttpx.get(f"{url}")).json()
+ for x in onmyoji_data:
+ x["name"] = remove_prohibited_str(x["name"])
+ key = x["name"]
+ data = add_to_data(data, x, game_name)
+ logger.info(f"{key} is update...")
+ data = await _last_check(data, game_name)
except TimeoutError:
- logger.warning(f'更新 {game_name} 超时...')
+ logger.warning(f"更新 {game_name} 超时...")
return {}, 999
- with open(DRAW_PATH + f'{game_name}.json', 'w', encoding='utf8') as wf:
+ with open(DRAW_PATH + f"{game_name}.json", "w", encoding="utf8") as wf:
json.dump(data, wf, ensure_ascii=False, indent=4)
return data, 200
@@ -60,91 +61,95 @@ async def update_requests_info(game_name: str):
# 添加到字典
def add_to_data(data: dict, x: dict, game_name: str) -> dict:
member_dict = {}
- if game_name == 'fgo':
+ if game_name == "fgo":
member_dict = {
- 'id': x['id'],
- 'card_id': x['charid'],
- '头像': x['icon'],
- '名称': x['name'],
- '职阶': x['classes'],
- '星级': x['star'],
- 'hp': x['lvmax4hp'],
- 'atk': x['lvmax4atk'],
- 'card_quick': x['cardquick'],
- 'card_arts': x['cardarts'],
- 'card_buster': x['cardbuster'],
- '宝具': x['tprop'],
+ "id": x["id"],
+ "card_id": x["charid"],
+ "头像": x["icon"],
+ "名称": x["name"],
+ "职阶": x["classes"],
+ "星级": x["star"],
+ "hp": x["lvmax4hp"],
+ "atk": x["lvmax4atk"],
+ "card_quick": x["cardquick"],
+ "card_arts": x["cardarts"],
+ "card_buster": x["cardbuster"],
+ "宝具": x["tprop"],
}
- if game_name == 'fgo_card':
+ if game_name == "fgo_card":
member_dict = {
- 'id': x['id'],
- 'card_id': x['equipid'],
- '头像': x['icon'],
- '名称': x['name'],
- '星级': x['star'],
- 'hp': x['lvmax_hp'],
- 'atk': x['lvmax_atk'],
- 'skill_e': x['skill_e'].split('
')[: -1],
+ "id": x["id"],
+ "card_id": x["equipid"],
+ "头像": x["icon"],
+ "名称": x["name"],
+ "星级": x["star"],
+ "hp": x["lvmax_hp"],
+ "atk": x["lvmax_atk"],
+ "skill_e": x["skill_e"].split("
")[:-1],
}
- if game_name == 'onmyoji':
+ if game_name == "onmyoji":
member_dict = {
- 'id': x['id'],
- '名称': x['name'],
- '星级': x['level'],
+ "id": x["id"],
+ "名称": x["name"],
+ "星级": x["level"],
}
- data[member_dict['名称']] = member_dict
+ data[member_dict["名称"]] = member_dict
return data
# 获取额外数据
-async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession) -> dict:
- if game_name == 'fgo':
- url = 'http://fgo.vgtime.com/servant/'
+async def _last_check(data: dict, game_name: str) -> dict:
+ if game_name == "fgo":
+ url = "http://fgo.vgtime.com/servant/"
tasks = []
semaphore = asyncio.Semaphore(SEMAPHORE)
for key in data.keys():
- tasks.append(asyncio.ensure_future(_async_update_fgo_extra_info(url, key, data[key]['id'], session, semaphore)))
+ tasks.append(
+ asyncio.ensure_future(
+ _async_update_fgo_extra_info(url, key, data[key]["id"], semaphore)
+ )
+ )
asyResult = await asyncio.gather(*tasks)
for x in asyResult:
for key in x.keys():
- data[key]['入手方式'] = x[key]['入手方式']
- if game_name == 'onmyoji':
- url = 'https://yys.163.com/shishen/{}.html'
+ data[key]["入手方式"] = x[key]["入手方式"]
+ if game_name == "onmyoji":
+ url = "https://yys.163.com/shishen/{}.html"
for key in data.keys():
- async with session.get(f'{url.format(data[key]["id"])}', timeout=7) as response:
- soup = BeautifulSoup(await response.text(), 'lxml')
- data[key]['头像'] = "https:" + soup.find('div', {'class': 'pic_wrap'}).find('img')['src']
- await download_img(data[key]['头像'], game_name, key)
+ text = (await AsyncHttpx.get(f'{url.format(data[key]["id"])}')).text
+ soup = BeautifulSoup(text, "lxml")
+ data[key]["头像"] = (
+ "https:" + soup.find("div", {"class": "pic_wrap"}).find("img")["src"]
+ )
+ await download_img(data[key]["头像"], game_name, key)
return data
-async def _async_update_fgo_extra_info(url: str, key: str, _id: str, session: aiohttp.ClientSession, semaphore):
+async def _async_update_fgo_extra_info(url: str, key: str, _id: str, semaphore):
# 防止访问超时
async with semaphore:
for i in range(10):
try:
- async with session.get(f'{url}{_id}', timeout=7) as response:
- soup = BeautifulSoup(await response.text(), 'lxml')
- obtain = soup.find('table', {'class': 'uk-table uk-codex-table'}).find_all('td')[-1].text
- if obtain.find('限时活动免费获取 活动结束后无法获得') != -1:
- obtain = ['活动获取']
- elif obtain.find('非限时UP无法获得') != -1:
- obtain = ['限时召唤']
+ text = (await AsyncHttpx.get(f"{url}{_id}")).text
+ soup = BeautifulSoup(text, "lxml")
+ obtain = (
+ soup.find("table", {"class": "uk-table uk-codex-table"})
+ .find_all("td")[-1]
+ .text
+ )
+ if obtain.find("限时活动免费获取 活动结束后无法获得") != -1:
+ obtain = ["活动获取"]
+ elif obtain.find("非限时UP无法获得") != -1:
+ obtain = ["限时召唤"]
+ else:
+ if obtain.find("&") != -1:
+ obtain = obtain.strip().split("&")
else:
- if obtain.find('&') != -1:
- obtain = obtain.strip().split('&')
- else:
- obtain = obtain.strip().split(' ')
- logger.info(f'Fgo获取额外信息 {key}....{obtain}')
- x = {key: {}}
- x[key]['入手方式'] = obtain
- return x
+ obtain = obtain.strip().split(" ")
+ logger.info(f"Fgo获取额外信息 {key}....{obtain}")
+ x = {key: {}}
+ x[key]["入手方式"] = obtain
+ return x
except TimeoutError:
- logger.warning(f'访问{url}{_id} 第 {i}次 超时...已再次访问')
+ logger.warning(f"访问{url}{_id} 第 {i}次 超时...已再次访问")
return {}
-
-
-
-
-
-
diff --git a/plugins/draw_card/update_game_simple_info.py b/plugins/draw_card/update_game_simple_info.py
old mode 100644
new mode 100755
index c708e6f5..df684166
--- a/plugins/draw_card/update_game_simple_info.py
+++ b/plugins/draw_card/update_game_simple_info.py
@@ -1,4 +1,3 @@
-import aiohttp
from .config import DRAW_PATH, SEMAPHORE
from asyncio.exceptions import TimeoutError
from bs4 import BeautifulSoup
@@ -6,6 +5,7 @@ from .util import download_img
from .util import remove_prohibited_str
from urllib.parse import unquote
from services.log import logger
+from utils.http_utils import AsyncHttpx
import bs4
import asyncio
@@ -24,19 +24,21 @@ async def update_simple_info(url: str, game_name: str) -> 'dict, int':
except (ValueError, FileNotFoundError):
data = {}
try:
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(url, timeout=7) as response:
- soup = BeautifulSoup(await response.text(), 'lxml')
- divs = get_char_divs(soup, game_name)
- for div in divs:
- type_lst = get_type_lst(div, game_name)
- index = 0
- for char_lst in type_lst:
- contents = get_char_lst_contents(char_lst, game_name)
- for char in contents:
- data = await retrieve_char_data(char, game_name, data, index)
- index += 1
- data = await _last_check(data, game_name, session)
+ text = (await AsyncHttpx.get(url)).text
+ soup = BeautifulSoup(text, 'lxml')
+ divs = get_char_divs(soup, game_name)
+ for div in divs:
+ type_lst = get_type_lst(div, game_name)
+ index = 0
+ for char_lst in type_lst:
+ try:
+ contents = get_char_lst_contents(char_lst, game_name)
+ except AttributeError:
+ continue
+ for char in contents[1:]:
+ data = await retrieve_char_data(char, game_name, data, index)
+ index += 1
+ data = await _last_check(data, game_name)
except TimeoutError:
logger.warning(f'更新 {game_name} 超时...')
return {}, 999
@@ -71,7 +73,7 @@ def get_char_lst_contents(char_lst: bs4.element.Tag, game_name: str):
# 额外数据
-async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession) -> dict:
+async def _last_check(data: dict, game_name: str) -> dict:
if game_name == 'azur':
idx = 1
for url in [
@@ -91,7 +93,7 @@ async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession
tasks = []
semaphore = asyncio.Semaphore(SEMAPHORE)
for key in data.keys():
- tasks.append(asyncio.ensure_future(_async_update_azur_extra_info(key, session, semaphore)))
+ tasks.append(asyncio.ensure_future(_async_update_azur_extra_info(key, semaphore)))
asyResult = await asyncio.gather(*tasks)
for x in asyResult:
for key in x.keys():
@@ -125,10 +127,11 @@ async def retrieve_char_data(char: bs4.element.Tag, game_name: str, data: dict,
'名称': remove_prohibited_str(char.find('a')['title']),
'星级': 3 - index}
if game_name == 'azur':
- char = char.find('td').find('div')
+ print(char)
+ char = char.find('div').find('div').find('div').find('div')
avatar_img = char.find('a').find('img')
try:
- member_dict['名称'] = remove_prohibited_str(str(avatar_img['alt'])[: str(avatar_img['alt']).find('头像')])
+ member_dict['名称'] = remove_prohibited_str(char.find('a')['title'])
except TypeError:
member_dict['名称'] = char.find('a')['title'][:-4]
try:
@@ -138,7 +141,7 @@ async def retrieve_char_data(char: bs4.element.Tag, game_name: str, data: dict,
except TypeError:
member_dict['头像'] = "img link not find..."
logger.warning(f'{member_dict["名称"]} 图片缺失....')
- star = char.find('div').find('img')['alt']
+ star = char.find('img')['alt']
if star == '舰娘头像外框普通.png':
star = 1
elif star == '舰娘头像外框稀有.png':
@@ -161,28 +164,28 @@ async def retrieve_char_data(char: bs4.element.Tag, game_name: str, data: dict,
return data
-async def _async_update_azur_extra_info(key: str, session: aiohttp.ClientSession, semaphore):
+async def _async_update_azur_extra_info(key: str, semaphore):
if key[-1] == '改':
return {key: {'获取途径': ['无法建造']}}
async with semaphore:
for i in range(20):
try:
- async with session.get(f'https://wiki.biligame.com/blhx/{key}', timeout=7) as res:
- soup = BeautifulSoup(await res.text(), 'lxml')
- try:
- construction_time = str(soup.find('table', {'class': 'wikitable sv-general'}).find('tbody'))
- x = {key: {'获取途径': []}}
- if construction_time.find('无法建造') != -1:
- x[key]['获取途径'].append('无法建造')
- elif construction_time.find('活动已关闭') != -1:
- x[key]['获取途径'].append('活动限定')
- else:
- x[key]['获取途径'].append('可以建造')
- logger.info(f'碧蓝航线获取额外信息 {key}...{x[key]["获取途径"]}')
- except AttributeError:
- x = {key: {'获取途径': []}}
- logger.warning(f'碧蓝航线获取额外信息错误 {key}...{[]}')
- return x
+ text = (await AsyncHttpx.get(f'https://wiki.biligame.com/blhx/{key}')).text
+ soup = BeautifulSoup(text, 'lxml')
+ try:
+ construction_time = str(soup.find('table', {'class': 'wikitable sv-general'}).find('tbody'))
+ x = {key: {'获取途径': []}}
+ if construction_time.find('无法建造') != -1:
+ x[key]['获取途径'].append('无法建造')
+ elif construction_time.find('活动已关闭') != -1:
+ x[key]['获取途径'].append('活动限定')
+ else:
+ x[key]['获取途径'].append('可以建造')
+ logger.info(f'碧蓝航线获取额外信息 {key}...{x[key]["获取途径"]}')
+ except AttributeError:
+ x = {key: {'获取途径': []}}
+ logger.warning(f'碧蓝航线获取额外信息错误 {key}...{[]}')
+ return x
except TimeoutError:
logger.warning(f'访问 https://wiki.biligame.com/blhx/{key} 第 {i}次 超时...已再次访问')
return {}
diff --git a/plugins/draw_card/util.py b/plugins/draw_card/util.py
old mode 100644
new mode 100755
index 07c267ce..0f8bf8cf
--- a/plugins/draw_card/util.py
+++ b/plugins/draw_card/util.py
@@ -1,13 +1,9 @@
-
-import aiohttp
-import aiofiles
-from asyncio.exceptions import TimeoutError
-from aiohttp.client_exceptions import InvalidURL
from nonebot.adapters.cqhttp import MessageSegment
from typing import List, Union, Set
from pathlib import Path
from .config import path_dict
from configs.path_config import IMAGE_PATH
+from utils.http_utils import AsyncHttpx
import nonebot
import pypinyin
from utils.image_utils import CreateImg
@@ -54,21 +50,12 @@ async def download_img(url: str, path: str, name: str) -> bool:
if not file.exists():
file.parent.mkdir(exist_ok=True, parents=True)
try:
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(url, timeout=7) as response:
- async with aiofiles.open(IMAGE_PATH + f'/draw_card/{path}/{codename}.png', 'wb') as f:
- await f.write(await response.read())
- logger.info(f'下载 {path_dict[path]} 图片成功,名称:{name},url:{url}')
- return True
- except TimeoutError:
- logger.warning(f'下载 {path_dict[path]} 图片超时,名称:{name},url:{url}')
- return False
- except InvalidURL:
- logger.warning(f'下载 {path_dict[path]} 链接错误,名称:{name},url:{url}')
- return False
- else:
- # logger.info(f'{path_dict[path]} 图片 {name} 已存在')
- return False
+ if await AsyncHttpx.download_file(url, IMAGE_PATH + f'/draw_card/{path}/{codename}.png'):
+ logger.info(f'下载 {path_dict[path]} 图片成功,名称:{name},url:{url}')
+ return True
+ except Exception as e:
+ logger.warning(f'下载 {path_dict[path]} 链接错误 {type(e)}:{e},名称:{name},url:{url}')
+ return False
@driver.on_startup
diff --git a/plugins/epic/__init__.py b/plugins/epic/__init__.py
old mode 100644
new mode 100755
index 9065a091..a2fa2c2a
--- a/plugins/epic/__init__.py
+++ b/plugins/epic/__init__.py
@@ -15,7 +15,7 @@ usage:
""".strip()
__plugin_des__ = "可以不玩,不能没有,每日白嫖"
__plugin_cmd__ = ["epic"]
-__plugin_version__ = 0.2
+__plugin_version__ = 0.1
__plugin_author__ = "AkashiCoin"
__plugin_settings__ = {
"level": 5,
diff --git a/plugins/epic/data_source.py b/plugins/epic/data_source.py
old mode 100644
new mode 100755
index ed78181a..074a01c8
--- a/plugins/epic/data_source.py
+++ b/plugins/epic/data_source.py
@@ -32,11 +32,11 @@ async def get_epic_game():
"withPromotions": True,
},
}
- async with AsyncClient(proxies={"all://": None}) as client:
+ async with AsyncClient(headers=headers) as client:
try:
- res = await client.post(epic_url, headers=headers, json=data, timeout=10.0)
- resJson = res.json()
- games = resJson["data"]["Catalog"]["searchStore"]["elements"]
+ res = await client.post(epic_url, json=data, timeout=10.0)
+ res_json = res.json()
+ games = res_json["data"]["Catalog"]["searchStore"]["elements"]
return games
except Exception as e:
logger.error(str(e))
@@ -53,60 +53,89 @@ async def get_epic_free(bot: Bot, event: Event):
else:
msg_list = []
for game in games:
+ game_name = game["title"]
+ game_corp = game["seller"]["name"]
+ game_price = game["price"]["totalPrice"]["fmtPrice"]["originalPrice"]
+ # 赋初值以避免 local variable referenced before assignment
+ game_dev, game_pub, game_thumbnail = (None, None, None)
try:
- msg = ""
- game_name = game["title"]
- game_corp = game["seller"]["name"]
- game_price = game["price"]["totalPrice"]["fmtPrice"]["originalPrice"]
game_promotions = game["promotions"]["promotionalOffers"]
upcoming_promotions = game["promotions"]["upcomingPromotionalOffers"]
if not game_promotions and upcoming_promotions:
- continue
- else:
- for image in game["keyImages"]:
- game_thumbnail = (
- image["url"] if image["type"] == "Thumbnail" else None
- )
- for pair in game["customAttributes"]:
- game_dev = (
- pair["value"]
- if pair["key"] == "developerName"
- else game_corp
- )
- game_pub = (
- pair["value"]
- if pair["key"] == "publisherName"
- else game_corp
- )
- game_desp = game["description"]
- end_date = ""
- if len(game["promotions"]["promotionalOffers"]) != 0:
- end_date_iso = game["promotions"]["promotionalOffers"][0][
- "promotionalOffers"
- ][0]["endDate"][:-1]
- end_date = datetime.fromisoformat(end_date_iso).strftime(
- "%b.%d %H:%M"
- )
- # API 返回不包含游戏商店 URL,此处自行拼接,可能出现少数游戏 404 请反馈
- game_url = f"https://www.epicgames.com/store/zh-CN/p/{game['productSlug'].replace('/home', '')}"
- msg = (
- f"[CQ:image,file={game_thumbnail}]\n\n"
- if game_thumbnail
- else ""
+ # 促销暂未上线,但即将上线
+ promotion_data = upcoming_promotions[0]["promotionalOffers"][0]
+ start_date_iso, end_date_iso = (
+ promotion_data["startDate"][:-1],
+ promotion_data["endDate"][:-1],
)
- msg += f"FREE now :: {game_name} ({game_price})\n\n{game_desp}\n\n"
- msg += (
- f"游戏由 {game_pub} 发售,"
- if game_dev == game_pub
- else f"游戏由 {game_dev} 开发、{game_pub} 出版,"
+ # 删除字符串中最后一个 "Z" 使 Python datetime 可处理此时间
+ start_date = datetime.fromisoformat(start_date_iso).strftime(
+ "%b.%d %H:%M"
+ )
+ end_date = datetime.fromisoformat(end_date_iso).strftime(
+ "%b.%d %H:%M"
)
- msg += f"将在 UTC 时间 {end_date} 结束免费游玩,戳链接领取吧~\n{game_url}"
- _message = msg
if isinstance(event, GroupMessageEvent):
+ _message = "\n由 {} 公司发行的游戏 {} ({}) 在 UTC 时间 {} 即将推出免费游玩,预计截至 {}。".format(
+ game_corp, game_name, game_price, start_date, end_date
+ )
data = {
"type": "node",
"data": {
- "name": f"{NICKNAME}",
+ "name": f"这里是{NICKNAME}酱",
+ "uin": f"{bot.self_id}",
+ "content": _message,
+ },
+ }
+ msg_list.append(data)
+ else:
+ msg = "\n由 {} 公司发行的游戏 {} ({}) 在 UTC 时间 {} 即将推出免费游玩,预计截至 {}。".format(
+ game_corp, game_name, game_price, start_date, end_date
+ )
+ msg_list.append(msg)
+ else:
+ for image in game["keyImages"]:
+ if image["type"] == "Thumbnail":
+ game_thumbnail = image["url"]
+ for pair in game["customAttributes"]:
+ if pair["key"] == "developerName":
+ game_dev = pair["value"]
+ if pair["key"] == "publisherName":
+ game_pub = pair["value"]
+ # 如 game['customAttributes'] 未找到则均使用 game_corp 值
+ game_dev = game_dev if game_dev is not None else game_corp
+ game_pub = game_pub if game_pub is not None else game_corp
+ game_desp = game["description"]
+ end_date_iso = game["promotions"]["promotionalOffers"][0][
+ "promotionalOffers"
+ ][0]["endDate"][:-1]
+ end_date = datetime.fromisoformat(end_date_iso).strftime(
+ "%b.%d %H:%M"
+ )
+ # API 返回不包含游戏商店 URL,此处自行拼接,可能出现少数游戏 404 请反馈
+ game_url_part = (
+ (game["productSlug"].replace("/home", ""))
+ if ("/home" in game["productSlug"])
+ else game["productSlug"]
+ )
+ game_url = "https://www.epicgames.com/store/zh-CN/p/{}".format(
+ game_url_part
+ )
+ if isinstance(event, GroupMessageEvent):
+ _message = "[CQ:image,file={}]\n\nFREE now :: {} ({})\n{}\n此游戏由 {} 开发、{} 发行,将在 UTC 时间 {} 结束免费游玩,戳链接速度加入你的游戏库吧~\n{}\n".format(
+ game_thumbnail,
+ game_name,
+ game_price,
+ game_desp,
+ game_dev,
+ game_pub,
+ end_date,
+ game_url,
+ )
+ data = {
+ "type": "node",
+ "data": {
+ "name": f"这里是{NICKNAME}酱",
"uin": f"{bot.self_id}",
"content": _message,
},
diff --git a/plugins/fake_msg.py b/plugins/fake_msg.py
old mode 100644
new mode 100755
diff --git a/plugins/fudu.py b/plugins/fudu.py
old mode 100644
new mode 100755
index 56423c4c..8e483e9e
--- a/plugins/fudu.py
+++ b/plugins/fudu.py
@@ -4,12 +4,11 @@ from utils.image_utils import get_img_hash
import random
from utils.message_builder import image
from nonebot import on_message
-from utils.utils import get_message_text, get_message_imgs, get_local_proxy
+from utils.utils import get_message_text, get_message_imgs
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
-import aiohttp
-import aiofiles
from configs.config import Config
+from utils.http_utils import AsyncHttpx
from utils.manager import group_manager
from services.log import logger
@@ -121,14 +120,13 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
async def get_fudu_img_hash(url, group_id):
try:
- async with aiohttp.ClientSession() as session:
- async with session.get(url, proxy=get_local_proxy(), timeout=5) as response:
- async with aiofiles.open(
- IMAGE_PATH + f"temp/compare_{group_id}_img.jpg", "wb"
- ) as f:
- await f.write(await response.read())
- img_hash = get_img_hash(IMAGE_PATH + f"temp/compare_{group_id}_img.jpg")
- return str(img_hash)
+ if await AsyncHttpx.download_file(
+ url, IMAGE_PATH + f"temp/compare_{group_id}_img.jpg"
+ ):
+ img_hash = get_img_hash(IMAGE_PATH + f"temp/compare_{group_id}_img.jpg")
+ return str(img_hash)
+ else:
+ logger.warning(f"复读下载图片失败...")
except Exception as e:
logger.warning(f"复读读取图片Hash出错 {type(e)}:{e}")
return ""
diff --git a/plugins/genshin/__init__.py b/plugins/genshin/__init__.py
old mode 100644
new mode 100755
index d16bafc6..2d21e611
--- a/plugins/genshin/__init__.py
+++ b/plugins/genshin/__init__.py
@@ -1,3 +1,4 @@
import nonebot
nonebot.load_plugins("plugins/genshin")
+
diff --git a/plugins/genshin/almanac/__init__.py b/plugins/genshin/almanac/__init__.py
old mode 100644
new mode 100755
index 94785243..a8c49454
--- a/plugins/genshin/almanac/__init__.py
+++ b/plugins/genshin/almanac/__init__.py
@@ -38,12 +38,15 @@ ALC_PATH.mkdir(parents=True, exist_ok=True)
@almanac.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
alc_img = await get_alc_image(ALC_PATH)
- mes = alc_img + "\n ※ 黄历数据来源于 genshin.pub"
- await almanac.send(mes)
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送查看原神黄历"
- )
+ if alc_img:
+ mes = alc_img + "\n ※ 黄历数据来源于 genshin.pub"
+ await almanac.send(mes)
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送查看原神黄历"
+ )
+ else:
+ await almanac.send("黄历图片下载失败...")
@scheduler.scheduled_job(
@@ -58,7 +61,8 @@ async def _():
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
alc_img = await get_alc_image(ALC_PATH)
- mes = alc_img + "\n ※ 黄历数据来源于 genshin.pub"
- for gid in gl:
- if await group_manager.check_group_task_status(gid, "genshin_alc"):
- await bot.send_group_msg(group_id=int(gid), message=mes)
+ if alc_img:
+ mes = alc_img + "\n ※ 黄历数据来源于 genshin.pub"
+ for gid in gl:
+ if await group_manager.check_group_task_status(gid, "genshin_alc"):
+ await bot.send_group_msg(group_id=int(gid), message=mes)
diff --git a/plugins/genshin/almanac/data_source.py b/plugins/genshin/almanac/data_source.py
old mode 100644
new mode 100755
index c9cec6f4..85dc2e58
--- a/plugins/genshin/almanac/data_source.py
+++ b/plugins/genshin/almanac/data_source.py
@@ -1,43 +1,26 @@
-from utils.browser import get_browser
-from utils.message_builder import image
-from datetime import datetime
-from services.log import logger
-from pathlib import Path
-import os
-
-url = "https://genshin.pub"
-
-
-async def get_alc_image(path: Path):
- date = datetime.now().date()
- for file in os.listdir(path):
- if f'{date}.png' != file:
- file = path / file
- file.unlink()
- if f'{date}.png' in os.listdir(path):
- return image(f'{date}.png', 'genshin/alc')
- page = None
- try:
- browser = await get_browser()
- page = await browser.new_page()
- await page.goto(url, wait_until="networkidle", timeout=10000)
- await page.set_viewport_size({"width": 2560, "height": 1080})
- card = await page.query_selector('.GSAlmanacs_gs_almanacs__3qT_A')
- await card.screenshot(path=path / f'{date}.png', timeout=100000)
- except Exception as e:
- logger.error(f'获取原神黄历发生错误..{type(e)}: {e}')
- finally:
- if page:
- await page.close()
- return image(f'{date}.png', 'genshin/alc')
-
-
-
-
-
-
-
-
-
-
-
+from utils.message_builder import image
+from datetime import datetime
+from pathlib import Path
+from utils.http_utils import AsyncPlaywright
+from nonebot.adapters.cqhttp import MessageSegment
+from typing import Optional
+import os
+
+url = "https://genshin.pub"
+
+
+async def get_alc_image(path: Path) -> Optional[MessageSegment]:
+ """
+ 截取黄历
+ :param path: 存储路径
+ """
+ date = datetime.now().date()
+ for file in os.listdir(path):
+ if f"{date}.png" != file:
+ file = path / file
+ file.unlink()
+ if f"{date}.png" in os.listdir(path):
+ return image(f"{date}.png", "genshin/alc")
+ return await AsyncPlaywright.screenshot(
+ url, path / f"{date}.png", ".GSAlmanacs_gs_almanacs__3qT_A"
+ )
diff --git a/plugins/genshin/material_remind/__init__.py b/plugins/genshin/material_remind/__init__.py
old mode 100644
new mode 100755
index c54bef37..54925dde
--- a/plugins/genshin/material_remind/__init__.py
+++ b/plugins/genshin/material_remind/__init__.py
@@ -1,6 +1,6 @@
from nonebot import on_command, Driver
from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, Message
+from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
from utils.message_builder import image
from utils.image_utils import CreateImg
from utils.browser import get_browser
@@ -59,7 +59,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
)
)
logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送查看今日素材"
)
diff --git a/plugins/genshin/qiu_qiu_translation/__init__.py b/plugins/genshin/qiu_qiu_translation/__init__.py
deleted file mode 100644
index 512639a6..00000000
--- a/plugins/genshin/qiu_qiu_translation/__init__.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from .qiu_translation import qiu_qiu_word_translation, qiu_qiu_phrase_translation
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.typing import T_State
-from nonebot import on_command
-from utils.utils import get_message_text
-from services.log import logger
-
-__zx_plugin_name__ = "丘丘语翻译"
-__plugin_usage__ = """
-usage:
- 异世界旅游小助手,仅支持丘丘语翻译至中文
- 指令:
- 丘丘语翻译/丘丘一下 [文本]
-""".strip()
-__plugin_des__ = "其实我听得懂丘丘人讲话"
-__plugin_cmd__ = ["丘丘语翻译/丘丘一下 [文本]"]
-__plugin_type__ = ("原神相关",)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["丘丘语翻译", "丘丘一下"],
-}
-
-qiuqiu = on_command("丘丘语翻译", aliases={"丘丘一下", "丘丘翻译"}, priority=5, block=True)
-
-suffix = "\n※ 只能从丘丘语翻译为中文,不能反向翻译\n" "※ 注意空格,不要加入任何标点符号\n" "※ 翻译数据来源于 米游社论坛"
-
-
-@qiuqiu.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- txt = get_message_text(event.json()).lower()
- if txt == "":
- return
- mes = qiu_qiu_phrase_translation(txt)
- if not mes:
- mes = qiu_qiu_word_translation(txt)
- mes += suffix
- # print(mes)
- await qiuqiu.send(mes, at_sender=True)
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送丘丘翻译:" + txt
- )
diff --git a/plugins/genshin/qiu_qiu_translation/qiu_qiu_dictionary.json b/plugins/genshin/qiu_qiu_translation/qiu_qiu_dictionary.json
deleted file mode 100644
index 08d0f329..00000000
--- a/plugins/genshin/qiu_qiu_translation/qiu_qiu_dictionary.json
+++ /dev/null
@@ -1,127 +0,0 @@
-{
- "word": {
-
- "a": "啊",
-
- "beru": "做",
- "biadam": "找死啊",
- "biat": "暴揍",
- "buka": "肚子",
-
- "celi": "元素",
-
- "dada": "厉害",
- "dala": "什么",
- "domu": "跳舞",
-
- "eleka": "此时此刻",
-
- "guru": "咕",
- "gusha": "草",
-
- "ika": "敌人",
-
- "kundela": "活着",
- "kuzi": "强大",
- "kucha": "吃草",
-
- "la": "啦~",
- "lata": "水元素",
-
- "mani": "给予",
- "mi": "我",
- "mimi": "我们",
- "mita": "肉类",
- "mosi": "吃",
- "movo": "带来",
- "muhe": "胜利",
-
- "ni": "风",
- "nini": "风暴",
- "nunu": "睡觉",
- "nye": "不",
-
- "odomu": "朋友",
- "olah": "你好",
-
- "plata": "盾牌",
- "pupu": "噗噗",
-
- "sada": "唱歌",
- "shato": "伴随",
- "si": "什么",
-
- "tomo": "感激",
- "todo": "放心",
- "tiga": "矿石",
-
- "upa": "聚集",
- "unu": "乌努",
-
- "valo": "谢谢你",
- "vin": "酒",
-
- "ya": "人",
- "yaya": "人们",
- "ye": "家伙",
- "yeye": "这些家伙",
- "yo": "你",
- "yoyo": "你们",
-
- "zido": "杀死"
-
- },
- "phrase": {
- "beru si": "做什么",
- "biadam": "可恶啊,找死啊,愤怒语气",
- "biat": "打爆,暴揍;可恶的",
-
- "dada": " 极好的,厉害的",
- "dala": "表示疑问,不明白的集合,翻译为哪个,什么",
-
- "guru-guru": "拟声词,形容肚子咕咕叫的声音,饥饿",
- "guru guru": "拟声词,形容肚子咕咕叫的声音,饥饿",
- "gusha": "植物类食物,不怎么好的,难过的",
-
- "kucha pupu": "拟声词,吃草时候的拟声词,咯吱噗噗,形容吃草吃得香,贬义",
-
- "mita": "肉类,好的,好东西,有时代丘丘人,丘丘人部落,好肉族",
- "mosi mita": "吃肉,表示开心",
- "mosi gusha": "吃草,表示难过",
- "movo": "带来,搬运;可引申为收获,丰收",
- "muhe": "胜利,战胜;成功的",
-
- "nini": "大量风元素,风暴,狂风",
- "nye": "表示否定,没有了,不是",
-
- "pupu":"拟声词,噗噗,表示嘲讽",
-
- "sada": "唱歌,歌颂",
- "shato": "乘着,伴随着",
-
- "upa": "凝聚,聚集,集合;聚落,部落",
- "unu": "乌努,丘丘人所崇拜的神灵",
-
- "valo": "谢谢你,不客气/再见",
- "vin": "酒的,喝酒有关的,酒桶盖子",
-
- "ya": "特指人类,一个人类",
- "yaya": "人类的复数 ,大群人类",
- "ye": "你这个家伙,蔑称;或用于地位高者对地位低者的称呼",
- "yeye": "你们这些家伙,蔑称,ye的复数",
- "yo": "你,友善称呼",
- "yoyo": "你们,yo的复数,友善称呼ye",
-
-
-
- "nye mita da ye mosi zido": "再见,一路平安",
- "vin plata dada": "你的酒桶盾牌真不错",
- "kucha pupu gucha ye": "你咯吱噗噗的吃草的样子真的好搞笑",
- "mani nini biaodomu": "愿风暴给予你死亡",
- "celi dada mimi nunu": "赞美元素,我们睡觉吧",
- "muhe ye": "你们是不可战胜的",
- "ye dada": "你们可真棒",
- "ye yika": "你们是敌人",
- "nini zido": "愿风暴杀死你"
- }
-}
\ No newline at end of file
diff --git a/plugins/genshin/qiu_qiu_translation/qiu_translation.py b/plugins/genshin/qiu_qiu_translation/qiu_translation.py
deleted file mode 100644
index 45c236f4..00000000
--- a/plugins/genshin/qiu_qiu_translation/qiu_translation.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import json
-import os
-
-FILE_PATH = os.path.dirname(__file__)
-
-QIU_QIU_WORD = {}
-QIU_QIU_PHRASE = {}
-
-with open(
- os.path.join(FILE_PATH, "qiu_qiu_dictionary.json"), "r", encoding="UTF-8"
-) as f:
- data = json.load(f)
- QIU_QIU_WORD = data["word"]
- QIU_QIU_PHRASE = data["phrase"]
-
-
-def compare_words(word):
- # 比对word库是否有匹配的单词,有的话返回翻译,没有返回原词
- if word in QIU_QIU_WORD:
- return QIU_QIU_WORD[word]
-
- return word
-
-
-def compare_phrase(phrase):
- # 比对phrase库是否有匹配的单词,有的话返回翻译,没有的话匹配word库,都没有返回原词
- if phrase in QIU_QIU_PHRASE:
- return QIU_QIU_PHRASE[phrase]
- if phrase in QIU_QIU_WORD:
- return QIU_QIU_WORD[phrase]
-
- return phrase
-
-
-def qiu_qiu_word_translation(txt: str):
- # 对语句按空格分隔替换单词翻译
- txt_list = txt.split(" ")
- mes = "你查询的的丘丘语意思为:\n"
-
- for word in txt_list:
- tra_word = compare_words(word)
-
- if tra_word == word:
- # 如果是原词表示没有翻译,前后加空格接回语句里
- if not mes[-1] == " ":
- mes += " "
- mes += tra_word
- mes += " "
- else:
- mes += tra_word
- mes += "\n"
- return mes
-
-
-def qiu_qiu_phrase_translation(phrase):
- # 语句翻译,先看phrase库是不是有匹配的语句
- # 没有的话把单词拆开返回单词的意思
- tra_phrase = compare_phrase(phrase)
- if tra_phrase != phrase:
- return f"\n翻译丘丘语意思为:\n【{tra_phrase}】\n"
-
- txt_list = phrase.split(" ")
- mes = "没有查到这句丘丘语,以下是单词的翻译\n"
- for word in txt_list:
- if word == " ":
- continue
- tra_word = compare_phrase(word)
- if tra_word == word:
- mes += f"{word} : 没有这个词的翻译\n"
- else:
- mes += f"{word} : {tra_word}\n"
-
- return mes
diff --git a/plugins/genshin/query_resource_points/__init__.py b/plugins/genshin/query_resource_points/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/genshin/query_resource_points/map.py b/plugins/genshin/query_resource_points/map.py
old mode 100644
new mode 100755
index 6efcc1e0..449dbfc4
--- a/plugins/genshin/query_resource_points/map.py
+++ b/plugins/genshin/query_resource_points/map.py
@@ -1,266 +1,266 @@
-from pathlib import Path
-from configs.path_config import IMAGE_PATH, TEXT_PATH
-from utils.image_utils import CreateImg
-from typing import Tuple, List
-from math import sqrt, pow
-import random
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-icon_path = Path(IMAGE_PATH) / "genshin" / "genshin_icon"
-map_path = Path(IMAGE_PATH) / "genshin" / "map" / "map.png"
-resource_label_file = Path(TEXT_PATH) / "genshin" / "resource_label_file.json"
-resource_point_file = Path(TEXT_PATH) / "genshin" / "resource_point_file.json"
-
-
-class Map:
- """
- 原神资源生成类
- """
-
- def __init__(
- self,
- resource_name: str,
- center_point: Tuple[int, int],
- deviation: Tuple[int, int] = (25, 51),
- padding: int = 100,
- planning_route: bool = False,
- ratio: float = 1,
- ):
- """
- 参数:
- :param resource_name: 资源名称
- :param center_point: 中心点
- :param deviation: 坐标误差
- :param padding: 截图外边距
- :param planning_route: 是否规划最佳线路
- :param ratio: 压缩比率
- """
- self.map = CreateImg(0, 0, background=map_path)
- self.resource_name = resource_name
- self.center_x = center_point[0]
- self.center_y = center_point[1]
- self.deviation = deviation
- self.padding = int(padding * ratio)
- self.planning_route = planning_route
- self.ratio = ratio
-
- self.deviation = (
- int(self.deviation[0] * ratio),
- int(self.deviation[1] * ratio),
- )
-
- data = json.load(open(resource_label_file, "r", encoding="utf8"))
- # 资源 id
- self.resource_id = [
- data[x]["id"]
- for x in data
- if x != "CENTER_POINT" and data[x]["name"] == resource_name
- ][0]
- # 传送锚点 id
- self.teleport_anchor_id = [
- data[x]["id"]
- for x in data
- if x != "CENTER_POINT" and data[x]["name"] == "传送锚点"
- ][0]
- # 神像 id
- self.teleport_god_id = [
- data[x]["id"]
- for x in data
- if x != "CENTER_POINT" and data[x]["name"] == "七天神像"
- ][0]
- # 资源坐标
- data = json.load(open(resource_point_file, "r", encoding="utf8"))
- self.resource_point = [
- Resources(
- int((self.center_x + data[x]["x_pos"]) * ratio),
- int((self.center_y + data[x]["y_pos"]) * ratio),
- )
- for x in data
- if x != "CENTER_POINT" and data[x]["label_id"] == self.resource_id
- ]
- # 传送锚点坐标
- self.teleport_anchor_point = [
- Resources(
- int((self.center_x + data[x]["x_pos"]) * ratio),
- int((self.center_y + data[x]["y_pos"]) * ratio),
- )
- for x in data
- if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_anchor_id
- ]
- # 神像坐标
- self.teleport_god_point = [
- Resources(
- int((self.center_x + data[x]["x_pos"]) * ratio),
- int((self.center_y + data[x]["y_pos"]) * ratio),
- )
- for x in data
- if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_god_id
- ]
-
- # 将地图上生成资源图标
- def generate_resource_icon_in_map(self) -> int:
- x_list = [x.x for x in self.resource_point]
- y_list = [x.y for x in self.resource_point]
- min_width = min(x_list) - self.padding
- max_width = max(x_list) + self.padding
- min_height = min(y_list) - self.padding
- max_height = max(y_list) + self.padding
- self._generate_transfer_icon((min_width, min_height, max_width, max_height))
- for res in self.resource_point:
- icon = self._get_icon_image(self.resource_id)
- self.map.paste(
- icon, (res.x - self.deviation[0], res.y - self.deviation[1]), True
- )
- if self.planning_route:
- self._generate_best_route()
- self.map.crop((min_width, min_height, max_width, max_height))
- rand = random.randint(1, 10000)
- self.map.save(f"{IMAGE_PATH}/temp/genshin_map_{rand}.png")
- return rand
-
- # 资源数量
- def get_resource_count(self) -> int:
- return len(self.resource_point)
-
- # 生成传送锚点和神像
- def _generate_transfer_icon(self, box: Tuple[int, int, int, int]):
- min_width, min_height, max_width, max_height = box
- for resources in [self.teleport_anchor_point, self.teleport_god_point]:
- id_ = (
- self.teleport_anchor_id
- if resources == self.teleport_anchor_point
- else self.teleport_god_id
- )
- for res in resources:
- if min_width < res.x < max_width and min_height < res.y < max_height:
- icon = self._get_icon_image(id_)
- self.map.paste(
- icon,
- (res.x - self.deviation[0], res.y - self.deviation[1]),
- True,
- )
-
- # 生成最优路线(说是最优其实就是直线最短)
- def _generate_best_route(self):
- line_points = []
- teleport_list = self.teleport_anchor_point + self.teleport_god_point
- for teleport in teleport_list:
- current_res, res_min_distance = teleport.get_resource_distance(self.resource_point)
- current_teleport, teleport_min_distance = current_res.get_resource_distance(teleport_list)
- if current_teleport == teleport:
- self.map.line(
- (current_teleport.x, current_teleport.y, current_res.x, current_res.y), (255, 0, 0), width=1
- )
- is_used_res_points = []
- for res in self.resource_point:
- if res in is_used_res_points:
- continue
- current_teleport, teleport_min_distance = res.get_resource_distance(teleport_list)
- current_res, res_min_distance = res.get_resource_distance(self.resource_point)
- if teleport_min_distance < res_min_distance:
- self.map.line(
- (current_teleport.x, current_teleport.y, res.x, res.y), (255, 0, 0), width=1
- )
- else:
- is_used_res_points.append(current_res)
- self.map.line(
- (current_res.x, current_res.y, res.x, res.y), (255, 0, 0), width=1
- )
- res_cp = self.resource_point[:]
- res_cp.remove(current_res)
- # for _ in res_cp:
- current_teleport_, teleport_min_distance = res.get_resource_distance(teleport_list)
- current_res, res_min_distance = res.get_resource_distance(res_cp)
- if teleport_min_distance < res_min_distance:
- self.map.line(
- (current_teleport.x, current_teleport.y, res.x, res.y), (255, 0, 0), width=1
- )
- else:
- self.map.line(
- (current_res.x, current_res.y, res.x, res.y), (255, 0, 0), width=1
- )
- is_used_res_points.append(current_res)
- is_used_res_points.append(res)
-
- # resources_route = []
- # # 先连上最近的资源路径
- # for res in self.resource_point:
- # # 拿到最近的资源
- # current_res, _ = res.get_resource_distance(
- # self.resource_point
- # + self.teleport_anchor_point
- # + self.teleport_god_point
- # )
- # self.map.line(
- # (current_res.x, current_res.y, res.x, res.y), (255, 0, 0), width=1
- # )
- # resources_route.append((current_res, res))
- # teleport_list = self.teleport_anchor_point + self.teleport_god_point
- # for res1, res2 in resources_route:
- # point_list = [x for x in resources_route if res1 in x or res2 in x]
- # if not list(set(point_list).intersection(set(teleport_list))):
- # if res1 not in teleport_list and res2 not in teleport_list:
- # # while True:
- # # tmp = [x for x in point_list]
- # # break
- # teleport1, distance1 = res1.get_resource_distance(teleport_list)
- # teleport2, distance2 = res2.get_resource_distance(teleport_list)
- # if distance1 > distance2:
- # self.map.line(
- # (teleport1.x, teleport1.y, res1.x, res1.y),
- # (255, 0, 0),
- # width=1,
- # )
- # else:
- # self.map.line(
- # (teleport2.x, teleport2.y, res2.x, res2.y),
- # (255, 0, 0),
- # width=1,
- # )
-
- # self.map.line(xy, (255, 0, 0), width=3)
-
- # 获取资源图标
- def _get_icon_image(self, id_: int) -> "CreateImg":
- icon = icon_path / f"{id_}.png"
- if icon.exists():
- return CreateImg(
- int(50 * self.ratio), int(50 * self.ratio), background=icon
- )
- return CreateImg(
- int(50 * self.ratio),
- int(50 * self.ratio),
- background=f"{icon_path}/box.png",
- )
-
- # def _get_shortest_path(self, res: 'Resources', res_2: 'Resources'):
-
-
-# 资源类
-class Resources:
- def __init__(self, x: int, y: int):
- self.x = x
- self.y = y
-
- def get_distance(self, x: int, y: int):
- return int(sqrt(pow(abs(self.x - x), 2) + pow(abs(self.y - y), 2)))
-
- # 拿到资源在该列表中的最短路径
- def get_resource_distance(self, resources: List["Resources"]) -> "Resources, int":
- current_res = None
- min_distance = 999999
- for res in resources:
- distance = self.get_distance(res.x, res.y)
- if distance < min_distance and res != self:
- current_res = res
- min_distance = distance
- return current_res, min_distance
-
-
-
-
-
+from pathlib import Path
+from configs.path_config import IMAGE_PATH, TEXT_PATH
+from utils.image_utils import CreateImg
+from typing import Tuple, List
+from math import sqrt, pow
+import random
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+icon_path = Path(IMAGE_PATH) / "genshin" / "genshin_icon"
+map_path = Path(IMAGE_PATH) / "genshin" / "map" / "map.png"
+resource_label_file = Path(TEXT_PATH) / "genshin" / "resource_label_file.json"
+resource_point_file = Path(TEXT_PATH) / "genshin" / "resource_point_file.json"
+
+
+class Map:
+ """
+ 原神资源生成类
+ """
+
+ def __init__(
+ self,
+ resource_name: str,
+ center_point: Tuple[int, int],
+ deviation: Tuple[int, int] = (25, 51),
+ padding: int = 100,
+ planning_route: bool = False,
+ ratio: float = 1,
+ ):
+ """
+ 参数:
+ :param resource_name: 资源名称
+ :param center_point: 中心点
+ :param deviation: 坐标误差
+ :param padding: 截图外边距
+ :param planning_route: 是否规划最佳线路
+ :param ratio: 压缩比率
+ """
+ self.map = CreateImg(0, 0, background=map_path)
+ self.resource_name = resource_name
+ self.center_x = center_point[0]
+ self.center_y = center_point[1]
+ self.deviation = deviation
+ self.padding = int(padding * ratio)
+ self.planning_route = planning_route
+ self.ratio = ratio
+
+ self.deviation = (
+ int(self.deviation[0] * ratio),
+ int(self.deviation[1] * ratio),
+ )
+
+ data = json.load(open(resource_label_file, "r", encoding="utf8"))
+ # 资源 id
+ self.resource_id = [
+ data[x]["id"]
+ for x in data
+ if x != "CENTER_POINT" and data[x]["name"] == resource_name
+ ][0]
+ # 传送锚点 id
+ self.teleport_anchor_id = [
+ data[x]["id"]
+ for x in data
+ if x != "CENTER_POINT" and data[x]["name"] == "传送锚点"
+ ][0]
+ # 神像 id
+ self.teleport_god_id = [
+ data[x]["id"]
+ for x in data
+ if x != "CENTER_POINT" and data[x]["name"] == "七天神像"
+ ][0]
+ # 资源坐标
+ data = json.load(open(resource_point_file, "r", encoding="utf8"))
+ self.resource_point = [
+ Resources(
+ int((self.center_x + data[x]["x_pos"]) * ratio),
+ int((self.center_y + data[x]["y_pos"]) * ratio),
+ )
+ for x in data
+ if x != "CENTER_POINT" and data[x]["label_id"] == self.resource_id
+ ]
+ # 传送锚点坐标
+ self.teleport_anchor_point = [
+ Resources(
+ int((self.center_x + data[x]["x_pos"]) * ratio),
+ int((self.center_y + data[x]["y_pos"]) * ratio),
+ )
+ for x in data
+ if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_anchor_id
+ ]
+ # 神像坐标
+ self.teleport_god_point = [
+ Resources(
+ int((self.center_x + data[x]["x_pos"]) * ratio),
+ int((self.center_y + data[x]["y_pos"]) * ratio),
+ )
+ for x in data
+ if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_god_id
+ ]
+
+ # 将地图上生成资源图标
+ def generate_resource_icon_in_map(self) -> int:
+ x_list = [x.x for x in self.resource_point]
+ y_list = [x.y for x in self.resource_point]
+ min_width = min(x_list) - self.padding
+ max_width = max(x_list) + self.padding
+ min_height = min(y_list) - self.padding
+ max_height = max(y_list) + self.padding
+ self._generate_transfer_icon((min_width, min_height, max_width, max_height))
+ for res in self.resource_point:
+ icon = self._get_icon_image(self.resource_id)
+ self.map.paste(
+ icon, (res.x - self.deviation[0], res.y - self.deviation[1]), True
+ )
+ if self.planning_route:
+ self._generate_best_route()
+ self.map.crop((min_width, min_height, max_width, max_height))
+ rand = random.randint(1, 10000)
+ self.map.save(f"{IMAGE_PATH}/temp/genshin_map_{rand}.png")
+ return rand
+
+ # 资源数量
+ def get_resource_count(self) -> int:
+ return len(self.resource_point)
+
+ # 生成传送锚点和神像
+ def _generate_transfer_icon(self, box: Tuple[int, int, int, int]):
+ min_width, min_height, max_width, max_height = box
+ for resources in [self.teleport_anchor_point, self.teleport_god_point]:
+ id_ = (
+ self.teleport_anchor_id
+ if resources == self.teleport_anchor_point
+ else self.teleport_god_id
+ )
+ for res in resources:
+ if min_width < res.x < max_width and min_height < res.y < max_height:
+ icon = self._get_icon_image(id_)
+ self.map.paste(
+ icon,
+ (res.x - self.deviation[0], res.y - self.deviation[1]),
+ True,
+ )
+
+ # 生成最优路线(说是最优其实就是直线最短)
+ def _generate_best_route(self):
+ line_points = []
+ teleport_list = self.teleport_anchor_point + self.teleport_god_point
+ for teleport in teleport_list:
+ current_res, res_min_distance = teleport.get_resource_distance(self.resource_point)
+ current_teleport, teleport_min_distance = current_res.get_resource_distance(teleport_list)
+ if current_teleport == teleport:
+ self.map.line(
+ (current_teleport.x, current_teleport.y, current_res.x, current_res.y), (255, 0, 0), width=1
+ )
+ is_used_res_points = []
+ for res in self.resource_point:
+ if res in is_used_res_points:
+ continue
+ current_teleport, teleport_min_distance = res.get_resource_distance(teleport_list)
+ current_res, res_min_distance = res.get_resource_distance(self.resource_point)
+ if teleport_min_distance < res_min_distance:
+ self.map.line(
+ (current_teleport.x, current_teleport.y, res.x, res.y), (255, 0, 0), width=1
+ )
+ else:
+ is_used_res_points.append(current_res)
+ self.map.line(
+ (current_res.x, current_res.y, res.x, res.y), (255, 0, 0), width=1
+ )
+ res_cp = self.resource_point[:]
+ res_cp.remove(current_res)
+ # for _ in res_cp:
+ current_teleport_, teleport_min_distance = res.get_resource_distance(teleport_list)
+ current_res, res_min_distance = res.get_resource_distance(res_cp)
+ if teleport_min_distance < res_min_distance:
+ self.map.line(
+ (current_teleport.x, current_teleport.y, res.x, res.y), (255, 0, 0), width=1
+ )
+ else:
+ self.map.line(
+ (current_res.x, current_res.y, res.x, res.y), (255, 0, 0), width=1
+ )
+ is_used_res_points.append(current_res)
+ is_used_res_points.append(res)
+
+ # resources_route = []
+ # # 先连上最近的资源路径
+ # for res in self.resource_point:
+ # # 拿到最近的资源
+ # current_res, _ = res.get_resource_distance(
+ # self.resource_point
+ # + self.teleport_anchor_point
+ # + self.teleport_god_point
+ # )
+ # self.map.line(
+ # (current_res.x, current_res.y, res.x, res.y), (255, 0, 0), width=1
+ # )
+ # resources_route.append((current_res, res))
+ # teleport_list = self.teleport_anchor_point + self.teleport_god_point
+ # for res1, res2 in resources_route:
+ # point_list = [x for x in resources_route if res1 in x or res2 in x]
+ # if not list(set(point_list).intersection(set(teleport_list))):
+ # if res1 not in teleport_list and res2 not in teleport_list:
+ # # while True:
+ # # tmp = [x for x in point_list]
+ # # break
+ # teleport1, distance1 = res1.get_resource_distance(teleport_list)
+ # teleport2, distance2 = res2.get_resource_distance(teleport_list)
+ # if distance1 > distance2:
+ # self.map.line(
+ # (teleport1.x, teleport1.y, res1.x, res1.y),
+ # (255, 0, 0),
+ # width=1,
+ # )
+ # else:
+ # self.map.line(
+ # (teleport2.x, teleport2.y, res2.x, res2.y),
+ # (255, 0, 0),
+ # width=1,
+ # )
+
+ # self.map.line(xy, (255, 0, 0), width=3)
+
+ # 获取资源图标
+ def _get_icon_image(self, id_: int) -> "CreateImg":
+ icon = icon_path / f"{id_}.png"
+ if icon.exists():
+ return CreateImg(
+ int(50 * self.ratio), int(50 * self.ratio), background=icon
+ )
+ return CreateImg(
+ int(50 * self.ratio),
+ int(50 * self.ratio),
+ background=f"{icon_path}/box.png",
+ )
+
+ # def _get_shortest_path(self, res: 'Resources', res_2: 'Resources'):
+
+
+# 资源类
+class Resources:
+ def __init__(self, x: int, y: int):
+ self.x = x
+ self.y = y
+
+ def get_distance(self, x: int, y: int):
+ return int(sqrt(pow(abs(self.x - x), 2) + pow(abs(self.y - y), 2)))
+
+ # 拿到资源在该列表中的最短路径
+ def get_resource_distance(self, resources: List["Resources"]) -> "Resources, int":
+ current_res = None
+ min_distance = 999999
+ for res in resources:
+ distance = self.get_distance(res.x, res.y)
+ if distance < min_distance and res != self:
+ current_res = res
+ min_distance = distance
+ return current_res, min_distance
+
+
+
+
+
diff --git a/plugins/genshin/query_resource_points/query_resource.py b/plugins/genshin/query_resource_points/query_resource.py
old mode 100644
new mode 100755
index e7fc3ed2..958546a0
--- a/plugins/genshin/query_resource_points/query_resource.py
+++ b/plugins/genshin/query_resource_points/query_resource.py
@@ -3,18 +3,15 @@ from configs.path_config import IMAGE_PATH, TEXT_PATH
from PIL.Image import UnidentifiedImageError
from utils.message_builder import image
from services.log import logger
-from .map import Map
from utils.image_utils import CreateImg
-import asyncio
-from pathlib import Path
from asyncio.exceptions import TimeoutError
from asyncio import Semaphore
-from aiohttp.client import ClientSession
-from utils.user_agent import get_user_agent
from utils.image_utils import is_valid
+from utils.http_utils import AsyncHttpx
+from pathlib import Path
+from .map import Map
+import asyncio
import nonebot
-import aiohttp
-import aiofiles
import os
try:
@@ -96,130 +93,126 @@ async def init(flag: bool = False):
global CENTER_POINT, resource_name_list
try:
semaphore = asyncio.Semaphore(10)
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- await download_map_init(session, semaphore, MAP_RATIO, flag)
- await download_resource_data(session, semaphore)
- await download_resource_type(session)
- if not CENTER_POINT:
- CENTER_POINT = json.load(open(resource_label_file, "r", encoding="utf8"))[
- "CENTER_POINT"
- ]
- with open(resource_type_file, "r", encoding="utf8") as f:
- data = json.load(f)
- for id_ in data:
- for x in data[id_]["children"]:
- resource_name_list.append(x["name"])
+ await download_map_init(semaphore, flag)
+ await download_resource_data(semaphore)
+ await download_resource_type()
+ if not CENTER_POINT:
+ CENTER_POINT = json.load(open(resource_label_file, "r", encoding="utf8"))[
+ "CENTER_POINT"
+ ]
+ with open(resource_type_file, "r", encoding="utf8") as f:
+ data = json.load(f)
+ for id_ in data:
+ for x in data[id_]["children"]:
+ resource_name_list.append(x["name"])
except TimeoutError:
logger.warning('原神资源查询信息初始化超时....')
pass
# 图标及位置资源
-async def download_resource_data(session: ClientSession, semaphore: Semaphore):
+async def download_resource_data(semaphore: Semaphore):
icon_path.mkdir(parents=True, exist_ok=True)
resource_label_file.parent.mkdir(parents=True, exist_ok=True)
try:
- async with session.get(POINT_LIST_URL, timeout=5) as response:
- if response.status == 200:
- data = await response.json()
- if data["message"] == "OK":
- data = data["data"]
- for lst in ["label_list", "point_list"]:
- resource_data = {"CENTER_POINT": CENTER_POINT}
- tasks = []
- file = (
- resource_label_file
- if lst == "label_list"
- else resource_point_file
- )
- for x in data[lst]:
- id_ = x["id"]
- if lst == "label_list":
- img_url = x["icon"]
- tasks.append(
- asyncio.ensure_future(
- download_image(
- img_url,
- f"{icon_path}/{id_}.png",
- session,
- semaphore,
- True,
- )
+ response = await AsyncHttpx.get(POINT_LIST_URL)
+ if response.status_code == 200:
+ data = response.json()
+ if data["message"] == "OK":
+ data = data["data"]
+ for lst in ["label_list", "point_list"]:
+ resource_data = {"CENTER_POINT": CENTER_POINT}
+ tasks = []
+ file = (
+ resource_label_file
+ if lst == "label_list"
+ else resource_point_file
+ )
+ for x in data[lst]:
+ id_ = x["id"]
+ if lst == "label_list":
+ img_url = x["icon"]
+ tasks.append(
+ asyncio.ensure_future(
+ download_image(
+ img_url,
+ f"{icon_path}/{id_}.png",
+ semaphore,
+ True,
)
)
- resource_data[id_] = x
- await asyncio.gather(*tasks)
- with open(file, "w", encoding="utf8") as f:
- json.dump(resource_data, f, ensure_ascii=False, indent=4)
- else:
- logger.warning(f'获取原神资源失败 msg: {data["message"]}')
+ )
+ resource_data[id_] = x
+ await asyncio.gather(*tasks)
+ with open(file, "w", encoding="utf8") as f:
+ json.dump(resource_data, f, ensure_ascii=False, indent=4)
else:
- logger.warning(f"获取原神资源失败 code:{response.status}")
+ logger.warning(f'获取原神资源失败 msg: {data["message"]}')
+ else:
+ logger.warning(f"获取原神资源失败 code:{response.status_code}")
except TimeoutError:
logger.warning("获取原神资源数据超时...已再次尝试...")
- await download_resource_data(session, semaphore)
+ await download_resource_data(semaphore)
# 下载原神地图并拼图
async def download_map_init(
- session: ClientSession, semaphore: Semaphore, ratio: float = 1, flag: bool = False
+ semaphore: Semaphore, flag: bool = False
):
global CENTER_POINT, MAP_RATIO
map_path.mkdir(exist_ok=True, parents=True)
_map = map_path / "map.png"
if _map.exists() and os.path.getsize(_map) > 1024 * 1024 * 30:
_map.unlink()
- async with session.get(MAP_URL, timeout=5) as response:
- if response.status == 200:
- data = await response.json()
- if data["message"] == "OK":
- data = json.loads(data["data"]["info"]["detail"])
- CENTER_POINT = (data["origin"][0], data["origin"][1])
- if not _map.exists():
- # padding_w, padding_h = data['padding']
- data = data["slices"]
- idx = 0
- for _map_data in data[0]:
- map_url = _map_data['url']
- await download_image(
- map_url,
- f"{map_path}/{idx}.png",
- session,
- semaphore,
- force_flag=flag,
- )
- idx += 1
- _w, h = CreateImg(0, 0, background=f"{map_path}/0.png", ratio=MAP_RATIO).size
- w = _w * len(os.listdir(map_path))
- map_file = CreateImg(w, h, _w, h, ratio=MAP_RATIO)
- for i in range(idx):
- map_file.paste(CreateImg(0, 0, background=f"{map_path}/{i}.png", ratio=MAP_RATIO))
- map_file.save(f"{map_path}/map.png")
- else:
- logger.warning(f'获取原神地图失败 msg: {data["message"]}')
+ response = await AsyncHttpx.get(MAP_URL)
+ if response.status_code == 200:
+ data = response.json()
+ if data["message"] == "OK":
+ data = json.loads(data["data"]["info"]["detail"])
+ CENTER_POINT = (data["origin"][0], data["origin"][1])
+ if not _map.exists():
+ data = data["slices"]
+ idx = 0
+ for _map_data in data[0]:
+ map_url = _map_data['url']
+ await download_image(
+ map_url,
+ f"{map_path}/{idx}.png",
+ semaphore,
+ force_flag=flag,
+ )
+ idx += 1
+ _w, h = CreateImg(0, 0, background=f"{map_path}/0.png", ratio=MAP_RATIO).size
+ w = _w * len(os.listdir(map_path))
+ map_file = CreateImg(w, h, _w, h, ratio=MAP_RATIO)
+ for i in range(idx):
+ map_file.paste(CreateImg(0, 0, background=f"{map_path}/{i}.png", ratio=MAP_RATIO))
+ map_file.save(f"{map_path}/map.png")
else:
- logger.warning(f"获取原神地图失败 code:{response.status}")
+ logger.warning(f'获取原神地图失败 msg: {data["message"]}')
+ else:
+ logger.warning(f"获取原神地图失败 code:{response.status}")
# 下载资源类型数据
-async def download_resource_type(session: ClientSession):
+async def download_resource_type():
resource_type_file.parent.mkdir(parents=True, exist_ok=True)
- async with session.get(LABEL_URL, timeout=5) as response:
- if response.status == 200:
- data = await response.json()
- if data["message"] == "OK":
- data = data["data"]["tree"]
- resource_data = {}
- for x in data:
- id_ = x["id"]
- resource_data[id_] = x
- with open(resource_type_file, "w", encoding="utf8") as f:
- json.dump(resource_data, f, ensure_ascii=False, indent=4)
- logger.info(f"更新原神资源类型成功...")
- else:
- logger.warning(f'获取原神资源类型失败 msg: {data["message"]}')
+ response = await AsyncHttpx.get(LABEL_URL)
+ if response.status_code == 200:
+ data = response.json()
+ if data["message"] == "OK":
+ data = data["data"]["tree"]
+ resource_data = {}
+ for x in data:
+ id_ = x["id"]
+ resource_data[id_] = x
+ with open(resource_type_file, "w", encoding="utf8") as f:
+ json.dump(resource_data, f, ensure_ascii=False, indent=4)
+ logger.info(f"更新原神资源类型成功...")
else:
- logger.warning(f"获取原神资源类型失败 code:{response.status}")
+ logger.warning(f'获取原神资源类型失败 msg: {data["message"]}')
+ else:
+ logger.warning(f"获取原神资源类型失败 code:{response.status_code}")
# 初始化资源图标
@@ -239,7 +232,6 @@ def gen_icon(icon: str):
async def download_image(
img_url: str,
path: str,
- session: ClientSession,
semaphore: Semaphore,
gen_flag: bool = False,
force_flag: bool = False,
@@ -247,15 +239,12 @@ async def download_image(
async with semaphore:
try:
if not os.path.exists(path) or not is_valid or force_flag:
- async with session.get(img_url, timeout=5) as response:
- async with aiofiles.open(path, "wb") as f:
- await f.write(await response.read())
- logger.info(f"下载原神资源图标:{img_url}")
- if gen_flag:
- gen_icon(path)
- except TimeoutError:
- logger.warning("下载原神资源图片超时...已再次尝试...")
- await download_image(img_url, path, session, semaphore, gen_flag)
+ if await AsyncHttpx.download_file(img_url, path):
+ logger.info(f"下载原神资源图标:{img_url}")
+ if gen_flag:
+ gen_icon(path)
+ else:
+ logger.info(f"下载原神资源图标:{img_url} 失败,等待下次更新...")
except UnidentifiedImageError:
logger.warning(f"原神图片打开错误..已删除,等待下次更新... file: {path}")
if os.path.exists(path):
diff --git a/plugins/shop/gold_redbag/__init__.py b/plugins/gold_redbag/__init__.py
old mode 100644
new mode 100755
similarity index 98%
rename from plugins/shop/gold_redbag/__init__.py
rename to plugins/gold_redbag/__init__.py
index 2c20c7a3..2ffae551
--- a/plugins/shop/gold_redbag/__init__.py
+++ b/plugins/gold_redbag/__init__.py
@@ -25,6 +25,7 @@ from nonebot.rule import to_me
from datetime import datetime, timedelta
from configs.config import NICKNAME
from apscheduler.jobstores.base import JobLookupError
+from nonebot.adapters.cqhttp.exception import ActionFailed
import random
import time
@@ -320,7 +321,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
b64=await generate_send_redbag_pic(int(bot.self_id), greetings)
),
)
- except AttributeError:
+ except ActionFailed:
+ logger.warning(f"节日红包 GROUP {g} 发送失败..")
pass
diff --git a/plugins/shop/gold_redbag/data_source.py b/plugins/gold_redbag/data_source.py
old mode 100644
new mode 100755
similarity index 86%
rename from plugins/shop/gold_redbag/data_source.py
rename to plugins/gold_redbag/data_source.py
index 46640295..44dd159f
--- a/plugins/shop/gold_redbag/data_source.py
+++ b/plugins/gold_redbag/data_source.py
@@ -1,12 +1,11 @@
from models.bag_user import BagUser
-from utils.utils import is_number, get_local_proxy
+from utils.utils import is_number, get_local_proxy, get_user_avatar
from utils.image_utils import CreateImg
from utils.user_agent import get_user_agent
from configs.path_config import IMAGE_PATH
-from ..models.redbag_user import RedbagUser
+from .model import RedbagUser
import random
import os
-import aiohttp
from io import BytesIO
import asyncio
@@ -47,7 +46,7 @@ async def open_redbag(user_id: int, group_id: int, redbag_data: dict):
async def generate_send_redbag_pic(user_id: int, msg: str = '恭喜发财 大吉大利'):
random_redbag = random.choice(os.listdir(f"{IMAGE_PATH}/prts/redbag_2"))
redbag = CreateImg(0, 0, font_size=38, background=f'{IMAGE_PATH}/prts/redbag_2/{random_redbag}')
- ava = CreateImg(65, 65, background=BytesIO(await get_pic(user_id)))
+ ava = CreateImg(65, 65, background=BytesIO(await get_user_avatar(user_id)))
await asyncio.get_event_loop().run_in_executor(None, ava.circle)
redbag.text((int((redbag.size[0] - redbag.getsize(msg)[0]) / 2), 210), msg, (240, 218, 164))
redbag.paste(ava, (int((redbag.size[0] - ava.size[0])/2), 130), True)
@@ -59,14 +58,6 @@ async def generate_open_redbag_pic(user_id: int, send_user_nickname: str, amount
return await asyncio.create_task(_generate_open_redbag_pic(user_id, send_user_nickname, amount, text))
-# 获取QQ头像
-async def get_pic(qq):
- url = f'http://q1.qlogo.cn/g?b=qq&nk={qq}&s=160'
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(url, proxy=get_local_proxy(), timeout=5) as response:
- return await response.read()
-
-
# 开红包图片
async def _generate_open_redbag_pic(user_id: int, send_user_nickname: str, amount: int, text: str):
send_user_nickname += '的红包'
@@ -75,7 +66,7 @@ async def _generate_open_redbag_pic(user_id: int, send_user_nickname: str, amoun
size = CreateImg(0, 0, font_size=50).getsize(send_user_nickname)
# QQ头像
ava_bk = CreateImg(100 + size[0], 66, color='white', font_size=50)
- ava = CreateImg(66, 66, background=BytesIO(await get_pic(user_id)))
+ ava = CreateImg(66, 66, background=BytesIO(await get_user_avatar(user_id)))
ava_bk.paste(ava)
ava_bk.text((100, 7), send_user_nickname)
# ava_bk.show()
diff --git a/plugins/shop/models/redbag_user.py b/plugins/gold_redbag/model.py
old mode 100644
new mode 100755
similarity index 100%
rename from plugins/shop/models/redbag_user.py
rename to plugins/gold_redbag/model.py
diff --git a/plugins/group_last_chat/__init__.py b/plugins/group_last_chat/__init__.py
old mode 100644
new mode 100755
index b741ae43..ab7a3e55
--- a/plugins/group_last_chat/__init__.py
+++ b/plugins/group_last_chat/__init__.py
@@ -1,35 +1,35 @@
-from nonebot import on_message
-from nonebot.adapters.cqhttp.permission import GROUP
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
-import time
-from .data_source import cancel_all_notice, save_data, get_data, set_data_value
-from services.log import logger
-
-
-__zx_plugin_name__ = "群聊最后聊天时间记录 [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-last_chat = on_message(priority=1, block=False, permission=GROUP)
-
-
-@last_chat.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- time_data = await get_data()
- set_data_value(event.group_id, time.time())
- if event.group_id in time_data["_group"]:
- time_data["_group"].remove(event.group_id)
- set_data_value("_group", time_data["_group"])
- for key in time_data.keys():
- if key not in ["check_time", "_group"]:
- if key not in time_data["_group"]:
- if time.time() - time_data[key] > 60 * 60 * 36:
- await cancel_all_notice(key)
- time_data["_group"].append(key)
- set_data_value("_group", time_data["_group"])
- logger.info(f"GROUP {event.group_id} 因群内发言时间大于36小时被取消全部通知")
- if time.time() - time_data["check_time"] > 60 * 60 * 1:
- set_data_value("check_time", time.time())
- save_data()
+from nonebot import on_message
+from nonebot.adapters.cqhttp.permission import GROUP
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
+from .data_source import cancel_all_notice, save_data, get_data, set_data_value
+from services.log import logger
+import time
+
+
+__zx_plugin_name__ = "群聊最后聊天时间记录 [Hidden]"
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+last_chat = on_message(priority=1, block=False, permission=GROUP)
+
+
+@last_chat.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ time_data = await get_data()
+ set_data_value(event.group_id, time.time())
+ if event.group_id in time_data["_group"]:
+ time_data["_group"].remove(event.group_id)
+ set_data_value("_group", time_data["_group"])
+ for key in time_data.keys():
+ if key not in ["check_time", "_group"]:
+ if key not in time_data["_group"]:
+ if time.time() - time_data[key] > 60 * 60 * 36:
+ await cancel_all_notice(key)
+ time_data["_group"].append(key)
+ set_data_value("_group", time_data["_group"])
+ logger.info(f"GROUP {event.group_id} 因群内发言时间大于36小时被取消全部通知")
+ if time.time() - time_data["check_time"] > 60 * 60 * 1:
+ set_data_value("check_time", time.time())
+ save_data()
diff --git a/plugins/group_last_chat/data_source.py b/plugins/group_last_chat/data_source.py
old mode 100644
new mode 100755
index 924f81d1..9984e20d
--- a/plugins/group_last_chat/data_source.py
+++ b/plugins/group_last_chat/data_source.py
@@ -1,67 +1,67 @@
-from configs.path_config import DATA_PATH
-from utils.utils import get_bot
-from datetime import datetime
-import time
-from services.log import logger
-from utils.manager import group_manager
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-time_data = {}
-
-
-async def init():
- global time_data
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- data = read_data("group_last_chat_time.json")
- for g in gl:
- if not data.get(g):
- time_data[g] = time.time()
- if not time_data.get("check_time"):
- time_data["check_time"] = time.time()
- if not time_data.get("_group"):
- time_data["_group"] = []
- save_data()
- return time_data
-
-
-def read_data(file_name: str):
- try:
- with open(DATA_PATH + file_name, "r", encoding="utf8") as f:
- return json.load(f)
- except (ValueError, FileNotFoundError):
- return {}
-
-
-def save_data():
- with open(DATA_PATH + "group_last_chat_time.json", "w") as f:
- json.dump(time_data, f, indent=4)
- logger.info(
- f'自动存储 group_last_chat_time.json 时间:{str(datetime.now()).split(".")[0]}'
- )
-
-
-# 取消全部通知
-async def cancel_all_notice(group_id):
- group_id = int(group_id)
- for command in group_manager.get_task_data():
- if await group_manager.check_group_task_status(group_id, command):
- await group_manager.close_group_task(group_id, command)
- logger.info(f"关闭了 {group_id} 群的全部通知")
-
-
-async def get_data():
- global time_data
- if not time_data:
- time_data = await init()
- return time_data
-
-
-def set_data_value(key, value):
- global time_data
- time_data[key] = value
+from configs.path_config import DATA_PATH
+from utils.utils import get_bot
+from datetime import datetime
+import time
+from services.log import logger
+from utils.manager import group_manager
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+time_data = {}
+
+
+async def init():
+ global time_data
+ bot = get_bot()
+ gl = await bot.get_group_list()
+ gl = [g["group_id"] for g in gl]
+ data = read_data("group_last_chat_time.json")
+ for g in gl:
+ if not data.get(g):
+ time_data[g] = time.time()
+ if not time_data.get("check_time"):
+ time_data["check_time"] = time.time()
+ if not time_data.get("_group"):
+ time_data["_group"] = []
+ save_data()
+ return time_data
+
+
+def read_data(file_name: str):
+ try:
+ with open(DATA_PATH + file_name, "r", encoding="utf8") as f:
+ return json.load(f)
+ except (ValueError, FileNotFoundError):
+ return {}
+
+
+def save_data():
+ with open(DATA_PATH + "group_last_chat_time.json", "w") as f:
+ json.dump(time_data, f, indent=4)
+ logger.info(
+ f'自动存储 group_last_chat_time.json 时间:{str(datetime.now()).split(".")[0]}'
+ )
+
+
+# 取消全部通知
+async def cancel_all_notice(group_id):
+ group_id = int(group_id)
+ for command in group_manager.get_task_data():
+ if await group_manager.check_group_task_status(group_id, command):
+ await group_manager.close_group_task(group_id, command)
+ logger.info(f"关闭了 {group_id} 群的全部通知")
+
+
+async def get_data():
+ global time_data
+ if not time_data:
+ time_data = await init()
+ return time_data
+
+
+def set_data_value(key, value):
+ global time_data
+ time_data[key] = value
diff --git a/plugins/group_welcome_msg.py b/plugins/group_welcome_msg.py
old mode 100644
new mode 100755
diff --git a/plugins/image_management/__init__.py b/plugins/image_management/__init__.py
old mode 100644
new mode 100755
index 1e5ef28d..81121c6e
--- a/plugins/image_management/__init__.py
+++ b/plugins/image_management/__init__.py
@@ -21,7 +21,7 @@ Config.add_plugin_config(
)
Config.add_plugin_config(
- "image_management:delete_img",
+ "image_management:delete_image",
"DELETE_IMAGE_LEVEL [LEVEL]",
7,
help_="删除图库图片需要的管理员等级",
@@ -29,7 +29,7 @@ Config.add_plugin_config(
)
Config.add_plugin_config(
- "image_management:move_img",
+ "image_management:move_image",
"MOVE_IMAGE_LEVEL [LEVEL]",
7,
help_="移动图库图片需要的管理员等级",
@@ -37,7 +37,7 @@ Config.add_plugin_config(
)
Config.add_plugin_config(
- "image_management:upload_img",
+ "image_management:upload_image",
"UPLOAD_IMAGE_LEVEL [LEVEL]",
6,
help_="上传图库图片需要的管理员等级",
diff --git a/plugins/image_management/delete_img/__init__.py b/plugins/image_management/delete_image/__init__.py
old mode 100644
new mode 100755
similarity index 97%
rename from plugins/image_management/delete_img/__init__.py
rename to plugins/image_management/delete_image/__init__.py
index e7d9b70c..45b08da3
--- a/plugins/image_management/delete_img/__init__.py
+++ b/plugins/image_management/delete_image/__init__.py
@@ -1,96 +1,96 @@
-from configs.path_config import IMAGE_PATH, TEMP_PATH
-from utils.message_builder import image
-from services.log import logger
-from nonebot import on_command
-from nonebot.rule import to_me
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from utils.utils import is_number, cn2py, get_message_text
-from configs.config import Config
-from pathlib import Path
-import os
-
-__zx_plugin_name__ = "删除图片 [Admin]"
-__plugin_usage__ = """
-usage:
- 删除图库指定图片
- 指令:
- 删除图片 [图库] [id]
- 查看图库
- 示例:删除图片 美图 666
-""".strip()
-__plugin_des__ = "不好看的图片删掉删掉!"
-__plugin_cmd__ = ["删除图片 [图库] [id]", "查看公开图库"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "admin_level": Config.get_config("image_management", "DELETE_IMAGE_LEVEL")
-}
-
-
-delete_img = on_command("删除图片", priority=5, rule=to_me(), block=True)
-
-
-@delete_img.args_parser
-async def parse(bot: Bot, event: MessageEvent, state: T_State):
- if get_message_text(event.json()) in ["取消", "算了"]:
- await delete_img.finish("已取消操作..", at_sender=True)
- if state["_current_key"] in ["path"]:
- if get_message_text(event.json()) not in Config.get_config("image_management", "IMAGE_DIR_LIST"):
- await delete_img.reject("此目录不正确,请重新输入目录!")
- state[state["_current_key"]] = get_message_text(event.json())
- if state["_current_key"] == "id":
- if not is_number(get_message_text(event.json())):
- await delete_img.reject("id不正确!请重新输入数字...")
- state[state["_current_key"]] = get_message_text(event.json())
-
-
-@delete_img.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- raw_arg = get_message_text(event.json()).strip()
- if raw_arg:
- args = raw_arg.split(" ")
- if args[0] in ["帮助"]:
- await delete_img.finish(__plugin_usage__)
- if len(args) >= 2 and args[0] in Config.get_config("image_management", "IMAGE_DIR_LIST") and is_number(args[1]):
- state["path"] = args[0]
- state["id"] = args[1]
-
-
-@delete_img.got("path", prompt="请输入要删除的目标图库?")
-@delete_img.got("id", prompt="请输入要删除的图片id?")
-async def arg_handle(bot: Bot, event: MessageEvent, state: T_State):
- path = cn2py(state["path"])
- img_id = state["id"]
- # path = IMAGE_PATH + path
- path = Path(IMAGE_PATH) / path
- temp = Path(IMAGE_PATH) / "temp"
- max_id = len(os.listdir(path)) - 1
- if int(img_id) > max_id or int(img_id) < 0:
- await delete_img.finish(f"Id超过上下限,上限:{max_id}", at_sender=True)
- try:
- if os.path.exists(temp / "delete.jpg"):
- os.remove(temp / "delete.jpg")
- logger.info("删除图片 delete.jpg 成功")
- except Exception as e:
- logger.warning(f"删除图片 delete.jpg 失败 e{e}")
- try:
- os.rename(path / f"{img_id}.jpg", temp / "delete.jpg")
- logger.info(f"移动 {path}/{img_id}.jpg 移动成功")
- except Exception as e:
- logger.warning(f"{path}/{img_id}.jpg --> 移动失败 e:{e}")
- if not os.path.exists(path / f"{img_id}.jpg"):
- try:
- if int(img_id) != max_id:
- os.rename(path / f"{max_id}.jpg", path / f"{img_id}.jpg")
- except FileExistsError as e:
- logger.error(f"{path}/{max_id}.jpg 替换 {path}/{img_id}.jpg 失败 e:{e}")
- logger.info(f"{path}/{max_id}.jpg 替换 {path}/{img_id}.jpg 成功")
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}"
- f" -> id: {img_id} 删除成功"
- )
- await delete_img.finish(
- f"id: {img_id} 删除成功" + image("delete.jpg", TEMP_PATH), at_sender=True
- )
- await delete_img.finish(f"id: {img_id} 删除失败!")
+from configs.path_config import IMAGE_PATH, TEMP_PATH
+from utils.message_builder import image
+from services.log import logger
+from nonebot import on_command
+from nonebot.rule import to_me
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from utils.utils import is_number, cn2py, get_message_text
+from configs.config import Config
+from pathlib import Path
+import os
+
+__zx_plugin_name__ = "删除图片 [Admin]"
+__plugin_usage__ = """
+usage:
+ 删除图库指定图片
+ 指令:
+ 删除图片 [图库] [id]
+ 查看图库
+ 示例:删除图片 美图 666
+""".strip()
+__plugin_des__ = "不好看的图片删掉删掉!"
+__plugin_cmd__ = ["删除图片 [图库] [id]", "查看公开图库"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "admin_level": Config.get_config("image_management", "DELETE_IMAGE_LEVEL")
+}
+
+
+delete_img = on_command("删除图片", priority=5, rule=to_me(), block=True)
+
+
+@delete_img.args_parser
+async def parse(bot: Bot, event: MessageEvent, state: T_State):
+ if get_message_text(event.json()) in ["取消", "算了"]:
+ await delete_img.finish("已取消操作..", at_sender=True)
+ if state["_current_key"] in ["path"]:
+ if get_message_text(event.json()) not in Config.get_config("image_management", "IMAGE_DIR_LIST"):
+ await delete_img.reject("此目录不正确,请重新输入目录!")
+ state[state["_current_key"]] = get_message_text(event.json())
+ if state["_current_key"] == "id":
+ if not is_number(get_message_text(event.json())):
+ await delete_img.reject("id不正确!请重新输入数字...")
+ state[state["_current_key"]] = get_message_text(event.json())
+
+
+@delete_img.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ raw_arg = get_message_text(event.json()).strip()
+ if raw_arg:
+ args = raw_arg.split(" ")
+ if args[0] in ["帮助"]:
+ await delete_img.finish(__plugin_usage__)
+ if len(args) >= 2 and args[0] in Config.get_config("image_management", "IMAGE_DIR_LIST") and is_number(args[1]):
+ state["path"] = args[0]
+ state["id"] = args[1]
+
+
+@delete_img.got("path", prompt="请输入要删除的目标图库?")
+@delete_img.got("id", prompt="请输入要删除的图片id?")
+async def arg_handle(bot: Bot, event: MessageEvent, state: T_State):
+ path = cn2py(state["path"])
+ img_id = state["id"]
+ # path = IMAGE_PATH + path
+ path = Path(IMAGE_PATH) / path
+ temp = Path(IMAGE_PATH) / "temp"
+ max_id = len(os.listdir(path)) - 1
+ if int(img_id) > max_id or int(img_id) < 0:
+ await delete_img.finish(f"Id超过上下限,上限:{max_id}", at_sender=True)
+ try:
+ if os.path.exists(temp / "delete.jpg"):
+ os.remove(temp / "delete.jpg")
+ logger.info("删除图片 delete.jpg 成功")
+ except Exception as e:
+ logger.warning(f"删除图片 delete.jpg 失败 e{e}")
+ try:
+ os.rename(path / f"{img_id}.jpg", temp / "delete.jpg")
+ logger.info(f"移动 {path}/{img_id}.jpg 移动成功")
+ except Exception as e:
+ logger.warning(f"{path}/{img_id}.jpg --> 移动失败 e:{e}")
+ if not os.path.exists(path / f"{img_id}.jpg"):
+ try:
+ if int(img_id) != max_id:
+ os.rename(path / f"{max_id}.jpg", path / f"{img_id}.jpg")
+ except FileExistsError as e:
+ logger.error(f"{path}/{max_id}.jpg 替换 {path}/{img_id}.jpg 失败 e:{e}")
+ logger.info(f"{path}/{max_id}.jpg 替换 {path}/{img_id}.jpg 成功")
+ logger.info(
+ f"USER {event.user_id} GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}"
+ f" -> id: {img_id} 删除成功"
+ )
+ await delete_img.finish(
+ f"id: {img_id} 删除成功" + image("delete.jpg", TEMP_PATH), at_sender=True
+ )
+ await delete_img.finish(f"id: {img_id} 删除失败!")
diff --git a/plugins/image_management/move_img/__init__.py b/plugins/image_management/move_image/__init__.py
old mode 100644
new mode 100755
similarity index 97%
rename from plugins/image_management/move_img/__init__.py
rename to plugins/image_management/move_image/__init__.py
index 90a177f2..8522f213
--- a/plugins/image_management/move_img/__init__.py
+++ b/plugins/image_management/move_image/__init__.py
@@ -1,105 +1,105 @@
-import os
-from services.log import logger
-from nonebot import on_command
-from nonebot.rule import to_me
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from configs.config import Config
-from utils.utils import is_number, cn2py
-from configs.path_config import IMAGE_PATH
-from pathlib import Path
-
-
-__zx_plugin_name__ = "移动图片 [Admin]"
-__plugin_usage__ = """
-usage:
- 图库间的图片移动操作
- 指令:
- 移动图片 [源图库] [目标图库] [id]
- 查看图库
- 示例:移动图片 萝莉 美图 234
-""".strip()
-__plugin_des__ = "图库间的图片移动操作"
-__plugin_cmd__ = ["移动图片 [源图库] [目标图库] [id]", "查看公开图库"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "admin_level": Config.get_config("image_management", "MOVE_IMAGE_LEVEL")
-}
-
-
-move_img = on_command("移动图片", priority=5, rule=to_me(), block=True)
-
-
-@move_img.args_parser
-async def parse(bot: Bot, event: MessageEvent, state: T_State):
- if str(event.get_message()) in ["取消", "算了"]:
- await move_img.finish("已取消操作..", at_sender=True)
- if state["_current_key"] in ["source_path", "destination_path"]:
- if str(event.get_message()) not in Config.get_config(
- "image_management", "IMAGE_DIR_LIST"
- ):
- await move_img.reject("此目录不正确,请重新输入目录!")
- state[state["_current_key"]] = str(event.get_message())
- if state["_current_key"] == "id":
- if not is_number(str(event.get_message())):
- await move_img.reject("id不正确!请重新输入数字...")
- state[state["_current_key"]] = str(event.get_message())
-
-
-@move_img.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- raw_arg = str(event.get_message()).strip()
- if raw_arg:
- args = raw_arg.split(" ")
- if args[0] in ["帮助"]:
- await move_img.finish(__plugin_usage__)
- if (
- len(args) >= 3
- and args[0] in Config.get_config("image_management", "IMAGE_DIR_LIST")
- and args[1] in Config.get_config("image_management", "IMAGE_DIR_LIST")
- and is_number(args[2])
- ):
- state["source_path"] = args[0]
- state["destination_path"] = args[1]
- state["id"] = args[2]
- else:
- await move_img.finish("参数错误,请重试", at_sender=True)
-
-
-@move_img.got("source_path", prompt="要从哪个图库移出?")
-@move_img.got("destination_path", prompt="要移动到哪个图库?")
-@move_img.got("id", prompt="要移动的图片id是?")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- img_id = state["id"]
- source_path = Path(IMAGE_PATH) / cn2py(state["source_path"])
- destination_path = Path(IMAGE_PATH) / cn2py(state["destination_path"])
- destination_path.mkdir(parents=True, exist_ok=True)
- max_id = len(os.listdir(source_path)) - 1
- des_max_id = len(os.listdir(destination_path))
- if int(img_id) > max_id or int(img_id) < 0:
- await move_img.finish(f"Id超过上下限,上限:{max_id}", at_sender=True)
- try:
- os.rename(source_path / f"{img_id}.jpg", destination_path / f"{des_max_id}.jpg")
- logger.info(
- f"移动 {source_path}/{img_id}.jpg ---> {destination_path}/{des_max_id} 移动成功"
- )
- except Exception as e:
- logger.warning(
- f"移动 {source_path}/{img_id}.jpg ---> {destination_path}/{des_max_id} 移动失败 e:{e}"
- )
- await move_img.finish(f"移动图片id:{img_id} 失败了...", at_sender=True)
- if max_id > 0:
- try:
- os.rename(source_path / f"{max_id}.jpg", source_path / f"{img_id}.jpg")
- logger.info(f"{source_path}/{max_id}.jpg 替换 {source_path}/{img_id}.jpg 成功")
- except Exception as e:
- logger.warning(
- f"{source_path}/{max_id}.jpg 替换 {source_path}/{img_id}.jpg 失败 e:{e}"
- )
- await move_img.finish(f"替换图片id:{max_id} -> {img_id} 失败了...", at_sender=True)
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'} ->"
- f" {source_path} --> {destination_path} (id:{img_id}) 移动图片成功"
- )
- await move_img.finish(f"移动图片 id:{img_id} --> id:{des_max_id}成功", at_sender=True)
+import os
+from services.log import logger
+from nonebot import on_command
+from nonebot.rule import to_me
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from configs.config import Config
+from utils.utils import is_number, cn2py
+from configs.path_config import IMAGE_PATH
+from pathlib import Path
+
+
+__zx_plugin_name__ = "移动图片 [Admin]"
+__plugin_usage__ = """
+usage:
+ 图库间的图片移动操作
+ 指令:
+ 移动图片 [源图库] [目标图库] [id]
+ 查看图库
+ 示例:移动图片 萝莉 美图 234
+""".strip()
+__plugin_des__ = "图库间的图片移动操作"
+__plugin_cmd__ = ["移动图片 [源图库] [目标图库] [id]", "查看公开图库"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "admin_level": Config.get_config("image_management", "MOVE_IMAGE_LEVEL")
+}
+
+
+move_img = on_command("移动图片", priority=5, rule=to_me(), block=True)
+
+
+@move_img.args_parser
+async def parse(bot: Bot, event: MessageEvent, state: T_State):
+ if str(event.get_message()) in ["取消", "算了"]:
+ await move_img.finish("已取消操作..", at_sender=True)
+ if state["_current_key"] in ["source_path", "destination_path"]:
+ if str(event.get_message()) not in Config.get_config(
+ "image_management", "IMAGE_DIR_LIST"
+ ):
+ await move_img.reject("此目录不正确,请重新输入目录!")
+ state[state["_current_key"]] = str(event.get_message())
+ if state["_current_key"] == "id":
+ if not is_number(str(event.get_message())):
+ await move_img.reject("id不正确!请重新输入数字...")
+ state[state["_current_key"]] = str(event.get_message())
+
+
+@move_img.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ raw_arg = str(event.get_message()).strip()
+ if raw_arg:
+ args = raw_arg.split(" ")
+ if args[0] in ["帮助"]:
+ await move_img.finish(__plugin_usage__)
+ if (
+ len(args) >= 3
+ and args[0] in Config.get_config("image_management", "IMAGE_DIR_LIST")
+ and args[1] in Config.get_config("image_management", "IMAGE_DIR_LIST")
+ and is_number(args[2])
+ ):
+ state["source_path"] = args[0]
+ state["destination_path"] = args[1]
+ state["id"] = args[2]
+ else:
+ await move_img.finish("参数错误,请重试", at_sender=True)
+
+
+@move_img.got("source_path", prompt="要从哪个图库移出?")
+@move_img.got("destination_path", prompt="要移动到哪个图库?")
+@move_img.got("id", prompt="要移动的图片id是?")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ img_id = state["id"]
+ source_path = Path(IMAGE_PATH) / cn2py(state["source_path"])
+ destination_path = Path(IMAGE_PATH) / cn2py(state["destination_path"])
+ destination_path.mkdir(parents=True, exist_ok=True)
+ max_id = len(os.listdir(source_path)) - 1
+ des_max_id = len(os.listdir(destination_path))
+ if int(img_id) > max_id or int(img_id) < 0:
+ await move_img.finish(f"Id超过上下限,上限:{max_id}", at_sender=True)
+ try:
+ os.rename(source_path / f"{img_id}.jpg", destination_path / f"{des_max_id}.jpg")
+ logger.info(
+ f"移动 {source_path}/{img_id}.jpg ---> {destination_path}/{des_max_id} 移动成功"
+ )
+ except Exception as e:
+ logger.warning(
+ f"移动 {source_path}/{img_id}.jpg ---> {destination_path}/{des_max_id} 移动失败 e:{e}"
+ )
+ await move_img.finish(f"移动图片id:{img_id} 失败了...", at_sender=True)
+ if max_id > 0:
+ try:
+ os.rename(source_path / f"{max_id}.jpg", source_path / f"{img_id}.jpg")
+ logger.info(f"{source_path}/{max_id}.jpg 替换 {source_path}/{img_id}.jpg 成功")
+ except Exception as e:
+ logger.warning(
+ f"{source_path}/{max_id}.jpg 替换 {source_path}/{img_id}.jpg 失败 e:{e}"
+ )
+ await move_img.finish(f"替换图片id:{max_id} -> {img_id} 失败了...", at_sender=True)
+ logger.info(
+ f"USER {event.user_id} GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'} ->"
+ f" {source_path} --> {destination_path} (id:{img_id}) 移动图片成功"
+ )
+ await move_img.finish(f"移动图片 id:{img_id} --> id:{des_max_id}成功", at_sender=True)
diff --git a/plugins/image_management/send_img/__init__.py b/plugins/image_management/send_image/__init__.py
old mode 100644
new mode 100755
similarity index 97%
rename from plugins/image_management/send_img/__init__.py
rename to plugins/image_management/send_image/__init__.py
index 57f9e1f9..26e20294
--- a/plugins/image_management/send_img/__init__.py
+++ b/plugins/image_management/send_image/__init__.py
@@ -1,124 +1,124 @@
-from nonebot import on_command, on_keyword, on_regex
-from configs.path_config import IMAGE_PATH
-from utils.message_builder import image
-from utils.utils import get_message_text, is_number
-from services.log import logger
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from utils.utils import FreqLimiter, cn2py
-from configs.config import Config
-from utils.manager import group_manager, withdraw_message_manager
-import random
-import os
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-__zx_plugin_name__ = "发送本地图库图片"
-__plugin_usage__ = f"""
-usage:
- 发送指定图库下的随机或指定id图片
- 指令:
- {Config.get_config("image_management", "IMAGE_DIR_LIST")} ?[id]
- 示例:美图
- 示例: 萝莉 2
-""".strip()
-__plugin_des__ = "让看看我的私藏,指[图片]"
-__plugin_cmd__ = Config.get_config("image_management", "IMAGE_DIR_LIST")
-__plugin_type__ = ("来点好康的",)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["发送图片"] + Config.get_config("image_management", "IMAGE_DIR_LIST"),
-}
-__plugin_task__ = {"pa": "丢人爬"}
-__plugin_resources__ = {
- "pa": IMAGE_PATH
-}
-
-_flmt = FreqLimiter(1)
-
-cmd = set(Config.get_config("image_management", "IMAGE_DIR_LIST"))
-
-# print(cmd)
-
-send_img = on_command("img", aliases=cmd, priority=5, block=True)
-pa = on_keyword({"丢人爬", "爪巴"}, priority=5, block=True)
-pa_reg = on_regex("^爬$", priority=5, block=True)
-
-search_url = "https://api.fantasyzone.cc/tu/search.php"
-
-
-@send_img.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- img_id = get_message_text(event.json())
- path = cn2py(state["_prefix"]["raw_command"]) + "/"
- if state["_prefix"]["raw_command"] in Config.get_config(
- "image_management", "IMAGE_DIR_LIST"
- ):
- if not os.path.exists(f"{IMAGE_PATH}/{path}/"):
- os.mkdir(f"{IMAGE_PATH}/{path}/")
- length = len(os.listdir(IMAGE_PATH + path))
- if length == 0:
- logger.warning(f"图库 {path} 为空,调用取消!")
- await send_img.finish("该图库中没有图片噢")
- index = img_id if img_id else str(random.randint(0, length))
- if not is_number(index):
- return
- if int(index) > length - 1 or int(index) < 0:
- await send_img.finish(f"超过当前上下限!({length - 1})")
- result = image(f"{index}.jpg", path)
- if result:
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 发送{path}:"
- + result
- )
- msg_id = await send_img.send(f"id:{index}" + result)
- withdraw_message_manager.withdraw_message(
- event,
- msg_id,
- Config.get_config("image_management", "WITHDRAW_IMAGE_MESSAGE"),
- )
- else:
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 发送 {path} 失败"
- )
- await send_img.finish(f"不想给你看Ov|")
-
-
-@pa.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if (
- isinstance(event, GroupMessageEvent)
- and not await group_manager.check_group_task_status(event.group_id, "pa")
- or get_message_text(event.json()).startswith("开启")
- or get_message_text(event.json()).startswith("关闭")
- ):
- return
- msg = get_message_text(event.json())
- if not msg or str(event.get_message()[:2]) in ["开启", "关闭"]:
- return
- if _flmt.check(event.user_id):
- _flmt.start_cd(event.user_id)
- await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
-
-
-@pa_reg.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if (
- isinstance(event, GroupMessageEvent)
- and not await group_manager.check_group_task_status(event.group_id, "pa")
- or get_message_text(event.json()).startswith("开启")
- or get_message_text(event.json()).startswith("关闭")
- ):
- return
- if _flmt.check(event.user_id):
- _flmt.start_cd(event.user_id)
- await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
+from nonebot import on_command, on_keyword, on_regex
+from configs.path_config import IMAGE_PATH
+from utils.message_builder import image
+from utils.utils import get_message_text, is_number
+from services.log import logger
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from utils.utils import FreqLimiter, cn2py
+from configs.config import Config
+from utils.manager import group_manager, withdraw_message_manager
+import random
+import os
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+__zx_plugin_name__ = "发送本地图库图片"
+__plugin_usage__ = f"""
+usage:
+ 发送指定图库下的随机或指定id图片
+ 指令:
+ {Config.get_config("image_management", "IMAGE_DIR_LIST")} ?[id]
+ 示例:美图
+ 示例: 萝莉 2
+""".strip()
+__plugin_des__ = "让看看我的私藏,指[图片]"
+__plugin_cmd__ = Config.get_config("image_management", "IMAGE_DIR_LIST")
+__plugin_type__ = ("来点好康的",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["发送图片"] + Config.get_config("image_management", "IMAGE_DIR_LIST"),
+}
+__plugin_task__ = {"pa": "丢人爬"}
+__plugin_resources__ = {
+ "pa": IMAGE_PATH
+}
+
+_flmt = FreqLimiter(1)
+
+cmd = set(Config.get_config("image_management", "IMAGE_DIR_LIST"))
+
+# print(cmd)
+
+send_img = on_command("img", aliases=cmd, priority=5, block=True)
+pa = on_keyword({"丢人爬", "爪巴"}, priority=5, block=True)
+pa_reg = on_regex("^爬$", priority=5, block=True)
+
+search_url = "https://api.fantasyzone.cc/tu/search.php"
+
+
+@send_img.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ img_id = get_message_text(event.json())
+ path = cn2py(state["_prefix"]["raw_command"]) + "/"
+ if state["_prefix"]["raw_command"] in Config.get_config(
+ "image_management", "IMAGE_DIR_LIST"
+ ):
+ if not os.path.exists(f"{IMAGE_PATH}/{path}/"):
+ os.mkdir(f"{IMAGE_PATH}/{path}/")
+ length = len(os.listdir(IMAGE_PATH + path))
+ if length == 0:
+ logger.warning(f"图库 {path} 为空,调用取消!")
+ await send_img.finish("该图库中没有图片噢")
+ index = img_id if img_id else str(random.randint(0, length))
+ if not is_number(index):
+ return
+ if int(index) > length - 1 or int(index) < 0:
+ await send_img.finish(f"超过当前上下限!({length - 1})")
+ result = image(f"{index}.jpg", path)
+ if result:
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 发送{path}:"
+ + result
+ )
+ msg_id = await send_img.send(f"id:{index}" + result)
+ withdraw_message_manager.withdraw_message(
+ event,
+ msg_id,
+ Config.get_config("image_management", "WITHDRAW_IMAGE_MESSAGE"),
+ )
+ else:
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 发送 {path} 失败"
+ )
+ await send_img.finish(f"不想给你看Ov|")
+
+
+@pa.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if (
+ isinstance(event, GroupMessageEvent)
+ and not await group_manager.check_group_task_status(event.group_id, "pa")
+ or get_message_text(event.json()).startswith("开启")
+ or get_message_text(event.json()).startswith("关闭")
+ ):
+ return
+ msg = get_message_text(event.json())
+ if not msg or str(event.get_message()[:2]) in ["开启", "关闭"]:
+ return
+ if _flmt.check(event.user_id):
+ _flmt.start_cd(event.user_id)
+ await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
+
+
+@pa_reg.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if (
+ isinstance(event, GroupMessageEvent)
+ and not await group_manager.check_group_task_status(event.group_id, "pa")
+ or get_message_text(event.json()).startswith("开启")
+ or get_message_text(event.json()).startswith("关闭")
+ ):
+ return
+ if _flmt.check(event.user_id):
+ _flmt.start_cd(event.user_id)
+ await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
diff --git a/plugins/image_management/upload_img/__init__.py b/plugins/image_management/upload_image/__init__.py
old mode 100644
new mode 100755
similarity index 97%
rename from plugins/image_management/upload_img/__init__.py
rename to plugins/image_management/upload_image/__init__.py
index cc2f5908..dbe3ce82
--- a/plugins/image_management/upload_img/__init__.py
+++ b/plugins/image_management/upload_image/__init__.py
@@ -1,127 +1,126 @@
-from nonebot import on_command
-from nonebot.rule import to_me
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-
-from configs.config import Config
-from utils.utils import get_message_imgs, get_message_text
-from .data_source import upload_image_to_local
-
-
-__zx_plugin_name__ = "上传图片 [Admin]"
-__plugin_usage__ = """
-usage:
- 上传图片至指定图库
- 指令:
- 查看图库
- 上传图片 [图库] [图片]
- 连续上传图片 [图库]
- 示例:上传图片 美图 [图片]
- * 连续上传图片可以通过发送 “stop” 表示停止收集发送的图片,可以开始上传 *
-""".strip()
-__plugin_des__ = "指定图库图片上传"
-__plugin_cmd__ = ["上传图片 [图库] [图片]", "连续上传图片 [图库]", "查看公开图库"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {"admin_level": Config.get_config("image_management", "DELETE_IMAGE_LEVEL")}
-
-upload_img = on_command("上传图片", rule=to_me(), priority=5, block=True)
-
-continuous_upload_img = on_command("连续上传图片", rule=to_me(), priority=5, block=True)
-
-show_gallery = on_command("查看公开图库", priority=1, block=True)
-
-
-@show_gallery.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- x = '公开图库列表:\n'
- for i, e in enumerate(Config.get_config("image_management", "IMAGE_DIR_LIST")):
- x += f'\t{i+1}.{e}\n'
- await show_gallery.send(x[:-1])
-
-
-@upload_img.args_parser
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if msg in ["取消", "算了"]:
- await upload_img.finish("已取消操作..", at_sender=True)
- if state["_current_key"] in ["path"]:
- if msg not in Config.get_config("image_management", "IMAGE_DIR_LIST"):
- await upload_img.reject("此目录不正确,请重新输入目录!")
- state["path"] = msg
- if state["_current_key"] in ["imgs"]:
- if not get_message_imgs(event.json()):
- await upload_img.reject("图呢图呢图呢图呢!GKD!")
- state["imgs"] = get_message_imgs(event.json())
-
-
-@upload_img.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- raw_arg = get_message_text(event.json())
- img_list = get_message_imgs(event.json())
- if raw_arg:
- if raw_arg in Config.get_config("image_management", "IMAGE_DIR_LIST"):
- state["path"] = raw_arg
- if img_list:
- state["imgs"] = img_list
-
-
-@upload_img.got("path", prompt="要将图片上传至什么图库呢?")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- pass
-
-
-@upload_img.got("imgs", prompt="图呢图呢图呢图呢!GKD!")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- path = state["path"]
- img_list = state["imgs"]
- group_id = 0
- if isinstance(event, GroupMessageEvent):
- group_id = event.group_id
- await upload_img.send(
- await upload_image_to_local(img_list, path, event.user_id, group_id)
- )
-
-
-@continuous_upload_img.args_parser
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if str(event.get_message()) in ["取消", "算了"]:
- await continuous_upload_img.finish("已取消操作..", at_sender=True)
- if state["_current_key"] in ["path"]:
- if str(event.get_message()) not in Config.get_config("image_management", "IMAGE_DIR_LIST"):
- await continuous_upload_img.reject("此目录不正确,请重新输入目录!")
- state[state["_current_key"]] = str(event.get_message())
- else:
- if get_message_text(event.json()) not in ["stop"]:
- img = get_message_imgs(event.json())
- if img:
- state["tmp"].extend(img)
- await continuous_upload_img.reject("图再来!!")
- else:
- state["imgs"] = state["tmp"]
-
-
-@continuous_upload_img.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- path = get_message_imgs(event.json())
- if path in Config.get_config("image_management", "IMAGE_DIR_LIST"):
- state["path"] = path
- await continuous_upload_img.send("图来!!")
- state["tmp"] = []
-
-
-@continuous_upload_img.got("path", prompt="要将图片上传至什么图库呢?")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- pass
-
-
-@continuous_upload_img.got("imgs", prompt="图呢图呢图呢图呢!GKD!")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- path = state["path"]
- img_list = state["imgs"]
- group_id = 0
- if isinstance(event, GroupMessageEvent):
- group_id = event.group_id
- await continuous_upload_img.send(
- await upload_image_to_local(img_list, path, event.user_id, group_id)
- )
+from nonebot import on_command
+from nonebot.rule import to_me
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from configs.config import Config
+from utils.utils import get_message_imgs, get_message_text
+from .data_source import upload_image_to_local
+
+
+__zx_plugin_name__ = "上传图片 [Admin]"
+__plugin_usage__ = """
+usage:
+ 上传图片至指定图库
+ 指令:
+ 查看图库
+ 上传图片 [图库] [图片]
+ 连续上传图片 [图库]
+ 示例:上传图片 美图 [图片]
+ * 连续上传图片可以通过发送 “stop” 表示停止收集发送的图片,可以开始上传 *
+""".strip()
+__plugin_des__ = "指定图库图片上传"
+__plugin_cmd__ = ["上传图片 [图库] [图片]", "连续上传图片 [图库]", "查看公开图库"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {"admin_level": Config.get_config("image_management", "DELETE_IMAGE_LEVEL")}
+
+upload_img = on_command("上传图片", rule=to_me(), priority=5, block=True)
+
+continuous_upload_img = on_command("连续上传图片", rule=to_me(), priority=5, block=True)
+
+show_gallery = on_command("查看公开图库", priority=1, block=True)
+
+
+@show_gallery.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ x = '公开图库列表:\n'
+ for i, e in enumerate(Config.get_config("image_management", "IMAGE_DIR_LIST")):
+ x += f'\t{i+1}.{e}\n'
+ await show_gallery.send(x[:-1])
+
+
+@upload_img.args_parser
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if msg in ["取消", "算了"]:
+ await upload_img.finish("已取消操作..", at_sender=True)
+ if state["_current_key"] in ["path"]:
+ if msg not in Config.get_config("image_management", "IMAGE_DIR_LIST"):
+ await upload_img.reject("此目录不正确,请重新输入目录!")
+ state["path"] = msg
+ if state["_current_key"] in ["imgs"]:
+ if not get_message_imgs(event.json()):
+ await upload_img.reject("图呢图呢图呢图呢!GKD!")
+ state["imgs"] = get_message_imgs(event.json())
+
+
+@upload_img.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ raw_arg = get_message_text(event.json())
+ img_list = get_message_imgs(event.json())
+ if raw_arg:
+ if raw_arg in Config.get_config("image_management", "IMAGE_DIR_LIST"):
+ state["path"] = raw_arg
+ if img_list:
+ state["imgs"] = img_list
+
+
+@upload_img.got("path", prompt="要将图片上传至什么图库呢?")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ pass
+
+
+@upload_img.got("imgs", prompt="图呢图呢图呢图呢!GKD!")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ path = state["path"]
+ img_list = state["imgs"]
+ group_id = 0
+ if isinstance(event, GroupMessageEvent):
+ group_id = event.group_id
+ await upload_img.send(
+ await upload_image_to_local(img_list, path, event.user_id, group_id)
+ )
+
+
+@continuous_upload_img.args_parser
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if str(event.get_message()) in ["取消", "算了"]:
+ await continuous_upload_img.finish("已取消操作..", at_sender=True)
+ if state["_current_key"] in ["path"]:
+ if str(event.get_message()) not in Config.get_config("image_management", "IMAGE_DIR_LIST"):
+ await continuous_upload_img.reject("此目录不正确,请重新输入目录!")
+ state[state["_current_key"]] = str(event.get_message())
+ else:
+ if get_message_text(event.json()) not in ["stop"]:
+ img = get_message_imgs(event.json())
+ if img:
+ state["tmp"].extend(img)
+ await continuous_upload_img.reject("图再来!!")
+ else:
+ state["imgs"] = state["tmp"]
+
+
+@continuous_upload_img.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ path = get_message_imgs(event.json())
+ if path in Config.get_config("image_management", "IMAGE_DIR_LIST"):
+ state["path"] = path
+ await continuous_upload_img.send("图来!!")
+ state["tmp"] = []
+
+
+@continuous_upload_img.got("path", prompt="要将图片上传至什么图库呢?")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ pass
+
+
+@continuous_upload_img.got("imgs", prompt="图呢图呢图呢图呢!GKD!")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ path = state["path"]
+ img_list = state["imgs"]
+ group_id = 0
+ if isinstance(event, GroupMessageEvent):
+ group_id = event.group_id
+ await continuous_upload_img.send(
+ await upload_image_to_local(img_list, path, event.user_id, group_id)
+ )
diff --git a/plugins/image_management/upload_img/data_source.py b/plugins/image_management/upload_image/data_source.py
old mode 100644
new mode 100755
similarity index 50%
rename from plugins/image_management/upload_img/data_source.py
rename to plugins/image_management/upload_image/data_source.py
index 7123d04b..3ce0a399
--- a/plugins/image_management/upload_img/data_source.py
+++ b/plugins/image_management/upload_image/data_source.py
@@ -1,51 +1,42 @@
-from configs.config import NICKNAME
-from typing import List
-from configs.path_config import IMAGE_PATH
-from services.log import logger
-from utils.utils import cn2py
-from pathlib import Path
-import aiofiles
-import aiohttp
-import os
-
-
-async def upload_image_to_local(
- img_list: List[str], path: str, user_id: int, group_id: int = 0
-) -> str:
- _path = path
- path = Path(IMAGE_PATH) / cn2py(path)
- path.mkdir(parents=True, exist_ok=True)
- img_id = len(os.listdir(path))
- failed_list = []
- success_id = ""
- async with aiohttp.ClientSession() as session:
- for img_url in img_list:
- try:
- async with session.get(img_url, timeout=7) as response:
- if response.status == 200:
- async with aiofiles.open(path / f"{img_id}.jpg", "wb") as f:
- await f.write(await response.read())
- success_id += str(img_id) + ","
- img_id += 1
- else:
- failed_list.append(img_url)
- logger.warning(f"图片:{img_url} 下载失败....")
- except TimeoutError as e:
- logger.warning(f"图片:{img_url} 下载超时....e:{e}")
- if img_url not in failed_list:
- failed_list.append(img_url)
- failed_result = ""
- for img in failed_list:
- failed_result += str(img) + "\n"
- logger.info(
- f"USER {user_id} GROUP {group_id}"
- f" 上传图片至 {_path} 共 {len(img_list)} 张,失败 {len(failed_list)} 张,id={success_id[:-1]}"
- )
- if failed_list:
- return (
- f"这次一共为 {_path}库 添加了 {len(img_list) - len(failed_list)} 张图片\n"
- f"依次的Id为:{success_id[:-1]}\n上传失败:{failed_result[:-1]}\n{NICKNAME}感谢您对图库的扩充!WW"
- )
- else:
- return f"这次一共为 {_path}库 添加了 {len(img_list)} 张图片\n依次的Id为:" \
- f"{success_id[:-1]}\n{NICKNAME}感谢您对图库的扩充!WW"
+from configs.config import NICKNAME
+from typing import List
+from configs.path_config import IMAGE_PATH
+from services.log import logger
+from utils.utils import cn2py
+from pathlib import Path
+from utils.http_utils import AsyncHttpx
+import os
+
+
+async def upload_image_to_local(
+ img_list: List[str], path: str, user_id: int, group_id: int = 0
+) -> str:
+ _path = path
+ path = Path(IMAGE_PATH) / cn2py(path)
+ path.mkdir(parents=True, exist_ok=True)
+ img_id = len(os.listdir(path))
+ failed_list = []
+ success_id = ""
+ for img_url in img_list:
+ if await AsyncHttpx.download_file(img_url, path / f"{img_id}.jpg"):
+ success_id += str(img_id) + ","
+ img_id += 1
+ else:
+ failed_list.append(img_url)
+ failed_result = ""
+ for img in failed_list:
+ failed_result += str(img) + "\n"
+ logger.info(
+ f"USER {user_id} GROUP {group_id}"
+ f" 上传图片至 {_path} 共 {len(img_list)} 张,失败 {len(failed_list)} 张,id={success_id[:-1]}"
+ )
+ if failed_list:
+ return (
+ f"这次一共为 {_path}库 添加了 {len(img_list) - len(failed_list)} 张图片\n"
+ f"依次的Id为:{success_id[:-1]}\n上传失败:{failed_result[:-1]}\n{NICKNAME}感谢您对图库的扩充!WW"
+ )
+ else:
+ return (
+ f"这次一共为 {_path}库 添加了 {len(img_list)} 张图片\n依次的Id为:"
+ f"{success_id[:-1]}\n{NICKNAME}感谢您对图库的扩充!WW"
+ )
diff --git a/plugins/jitang.py b/plugins/jitang.py
deleted file mode 100644
index a3663741..00000000
--- a/plugins/jitang.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from nonebot import on_command
-from utils.user_agent import get_user_agent
-from services.log import logger
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.typing import T_State
-import aiohttp
-from asyncio.exceptions import TimeoutError
-from configs.config import Config
-
-
-__zx_plugin_name__ = "鸡汤"
-__plugin_usage__ = """
-usage:
- 不喝点什么感觉有点不舒服
- 指令:
- 鸡汤
-""".strip()
-__plugin_des__ = "喏,亲手为你煮的鸡汤"
-__plugin_cmd__ = ["鸡汤"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["鸡汤", "毒鸡汤"],
-}
-
-url = "https://v2.alapi.cn/api/soul"
-
-
-jitang = on_command("鸡汤", aliases={"毒鸡汤"}, priority=5, block=True)
-
-
-@jitang.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- params = {"format": "json", "token": f"{Config.get_config('alapi', 'ALAPI_TOKEN')}"}
- try:
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(url, timeout=7, params=params) as response:
- if response.status == 200:
- data = await response.json()
- await jitang.send(data["data"]["content"])
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送鸡汤:" + data["data"]["content"]
- )
- else:
- await jitang.send("鸡汤煮坏掉了...")
- except TimeoutError:
- await jitang.send("鸡汤煮超时了##", at_sender=True)
diff --git a/plugins/luxun/__init__.py b/plugins/luxun/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/mute.py b/plugins/mute.py
old mode 100644
new mode 100755
index 0cd87fc7..4cf1d569
--- a/plugins/mute.py
+++ b/plugins/mute.py
@@ -1,17 +1,16 @@
from nonebot import on_message, on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.adapters.cqhttp.permission import GROUP
-from utils.utils import get_message_text, is_number, get_message_imgs, get_local_proxy
+from utils.utils import get_message_text, is_number, get_message_imgs
from nonebot.typing import T_State
-from asyncio.exceptions import TimeoutError
-import time
from nonebot.adapters.cqhttp.exception import ActionFailed
-from configs.path_config import DATA_PATH, IMAGE_PATH
+from configs.path_config import DATA_PATH, TEMP_PATH
from utils.image_utils import get_img_hash
from services.log import logger
from configs.config import NICKNAME, Config
-import aiohttp
-import aiofiles
+from utils.http_utils import AsyncHttpx
+from pathlib import Path
+import time
try:
import ujson as json
@@ -36,25 +35,13 @@ __plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {"admin_level": Config.get_config("mute", "MUTE_LEVEL")}
__plugin_configs__ = {
- "MUTE_LEVEL [LEVEL]": {
- "value": 5,
- "help": "更改禁言设置的管理权限",
- "default_value": 5
- },
- "MUTE_DEFAULT_COUNT": {
- "value": 10,
- "help": "刷屏禁言默认检测次数",
- "default_value": 10
- },
- "MUTE_DEFAULT_TIME": {
- "value": 7,
- "help": "刷屏检测默认规定时间",
- "default_value": 7
- },
+ "MUTE_LEVEL [LEVEL]": {"value": 5, "help": "更改禁言设置的管理权限", "default_value": 5},
+ "MUTE_DEFAULT_COUNT": {"value": 10, "help": "刷屏禁言默认检测次数", "default_value": 10},
+ "MUTE_DEFAULT_TIME": {"value": 7, "help": "刷屏检测默认规定时间", "default_value": 7},
"MUTE_DEFAULT_DURATION": {
"value": 10,
"help": "刷屏检测默禁言时长(分钟)",
- "default_value": 10
+ "default_value": 10,
},
}
@@ -85,18 +72,11 @@ def save_data():
async def download_img_and_hash(url, group_id):
- try:
- async with aiohttp.ClientSession() as session:
- async with session.get(
- url, proxy=get_local_proxy(), timeout=10
- ) as response:
- async with aiofiles.open(
- IMAGE_PATH + f"temp/mute_{group_id}_img.jpg", "wb"
- ) as f:
- await f.write(await response.read())
- return str(get_img_hash(IMAGE_PATH + f"temp/mute_{group_id}_img.jpg"))
- except TimeoutError:
- return ""
+ if await AsyncHttpx.download_file(
+ url, Path(TEMP_PATH) / f"mute_{group_id}_img.jpg"
+ ):
+ return str(get_img_hash(Path(TEMP_PATH) / f"mute_{group_id}_img.jpg"))
+ return ""
mute_dict = {}
diff --git a/plugins/my_info.py b/plugins/my_info.py
old mode 100644
new mode 100755
diff --git a/plugins/nbnhhsh.py b/plugins/nbnhhsh.py
old mode 100644
new mode 100755
index 2d0da4cc..469e620a
--- a/plugins/nbnhhsh.py
+++ b/plugins/nbnhhsh.py
@@ -1,66 +1,63 @@
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from utils.utils import get_message_text
-from services.log import logger
-import ujson as json
-import aiohttp
-
-
-__zx_plugin_name__ = "能不能好好说话"
-__plugin_usage__ = """
-usage:
- 说人话
- 指令:
- nbnhhsh [文本]
-""".strip()
-__plugin_des__ = "能不能好好说话,说人话"
-__plugin_cmd__ = ["nbnhhsh [文本]"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["能不能好好说话", "nbnhhsh"],
-}
-
-HHSH_GUESS_URL = "https://lab.magiconch.com/api/nbnhhsh/guess"
-
-nbnhhsh = on_command("nbnhhsh", aliases={"能不能好好说话"}, priority=5, block=True)
-
-
-@nbnhhsh.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if not msg:
- await nbnhhsh.finish('没话说就别说话!')
- async with aiohttp.ClientSession(
- headers={"content-type": "application/json"}
- ) as session:
- async with session.post(
- HHSH_GUESS_URL, data=json.dumps({"text": msg}), timeout=5
- ) as response:
- if response.status == 200:
- try:
- data = await response.json()
- tmp = ""
- rst = ""
- for x in data:
- trans = ""
- if x.get("trans"):
- trans = x["trans"][0]
- elif x.get("inputting"):
- trans = ",".join(x["inputting"])
- tmp += f'{x["name"]} -> {trans}\n'
- rst += trans
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送能不能好好说话: {msg} -> {rst}"
- )
- await nbnhhsh.send(f"{tmp}={rst}", at_sender=True)
- except (IndexError, KeyError):
- await nbnhhsh.finish("没有找到对应的翻译....")
- else:
- await nbnhhsh.finish("网络访问失败了....")
+from nonebot import on_command
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from utils.utils import get_message_text
+from utils.http_utils import AsyncHttpx
+from services.log import logger
+import ujson as json
+
+
+__zx_plugin_name__ = "能不能好好说话"
+__plugin_usage__ = """
+usage:
+ 说人话
+ 指令:
+ nbnhhsh [文本]
+""".strip()
+__plugin_des__ = "能不能好好说话,说人话"
+__plugin_cmd__ = ["nbnhhsh [文本]"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["能不能好好说话", "nbnhhsh"],
+}
+
+HHSH_GUESS_URL = "https://lab.magiconch.com/api/nbnhhsh/guess"
+
+nbnhhsh = on_command("nbnhhsh", aliases={"能不能好好说话"}, priority=5, block=True)
+
+
+@nbnhhsh.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if not msg:
+ await nbnhhsh.finish("没话说就别说话!")
+ response = await AsyncHttpx.post(
+ HHSH_GUESS_URL,
+ data=json.dumps({"text": msg}),
+ timeout=5,
+ headers={"content-type": "application/json"},
+ )
+ try:
+ data = response.json()
+ tmp = ""
+ rst = ""
+ for x in data:
+ trans = ""
+ if x.get("trans"):
+ trans = x["trans"][0]
+ elif x.get("inputting"):
+ trans = ",".join(x["inputting"])
+ tmp += f'{x["name"]} -> {trans}\n'
+ rst += trans
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送能不能好好说话: {msg} -> {rst}"
+ )
+ await nbnhhsh.send(f"{tmp}={rst}", at_sender=True)
+ except (IndexError, KeyError):
+ await nbnhhsh.finish("没有找到对应的翻译....")
diff --git a/plugins/nonebot_plugin_picsearcher/__init__.py b/plugins/nonebot_plugin_picsearcher/__init__.py
old mode 100644
new mode 100755
index 9810adac..21eb8617
--- a/plugins/nonebot_plugin_picsearcher/__init__.py
+++ b/plugins/nonebot_plugin_picsearcher/__init__.py
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from typing import Dict
-from aiohttp.client_exceptions import ClientError
from nonebot.plugin import on_command, on_message
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from nonebot.typing import T_State
@@ -127,8 +126,8 @@ async def get_setu(bot: Bot, event: MessageEvent, state: T_State):
except IndexError:
# await bot.send(event, traceback.format_exc())
await setu.finish("参数错误")
- except ClientError:
- await setu.finish("连接失败")
+ # except ClientError:
+ # await setu.finish("连接失败")
pic_map: Dict[str, str] = {} # 保存这个群的其阿金一张色图 {"123456":http://xxx"}
@@ -174,7 +173,8 @@ async def handle_previous(bot: Bot, event: GroupMessageEvent, state: T_State):
idx += 1
except IndexError:
await previous.finish("参数错误")
- except ClientError:
- await previous.finish("连接错误")
except KeyError:
await previous.finish("没有图啊QAQ")
+ except Exception as e:
+ logger.error(f"识图未知错误 {type(e)}:{e}")
+ await previous.finish("未知错误...")
diff --git a/plugins/nonebot_plugin_picsearcher/ascii2d.py b/plugins/nonebot_plugin_picsearcher/ascii2d.py
old mode 100644
new mode 100755
diff --git a/plugins/nonebot_plugin_picsearcher/ex.py b/plugins/nonebot_plugin_picsearcher/ex.py
old mode 100644
new mode 100755
diff --git a/plugins/nonebot_plugin_picsearcher/formdata.py b/plugins/nonebot_plugin_picsearcher/formdata.py
old mode 100644
new mode 100755
diff --git a/plugins/nonebot_plugin_picsearcher/iqdb.py b/plugins/nonebot_plugin_picsearcher/iqdb.py
old mode 100644
new mode 100755
diff --git a/plugins/nonebot_plugin_picsearcher/saucenao.py b/plugins/nonebot_plugin_picsearcher/saucenao.py
old mode 100644
new mode 100755
index 8b60838a..f359b19d
--- a/plugins/nonebot_plugin_picsearcher/saucenao.py
+++ b/plugins/nonebot_plugin_picsearcher/saucenao.py
@@ -79,7 +79,7 @@ async def get_pic_from_url(url: str):
data = FormData(boundary="----WebKitFormBoundaryPpuR3EZ1Ap2pXv8W")
data.add_field(name="file", value=content, content_type="image/jpeg",
filename="blob")
- async with session.post("https://saucenao.com/search.php", data=data, headers=header) as res:
+ async with session.post("https://saucenao.com/search.php", proxy=get_local_proxy(), data=data, headers=header) as res:
html = await res.text()
image_data = [each for each in parse_html(html)]
return image_data
diff --git a/plugins/nonebot_plugin_picsearcher/trace.py b/plugins/nonebot_plugin_picsearcher/trace.py
old mode 100644
new mode 100755
diff --git a/plugins/nonebot_plugin_picsearcher/yandex.py b/plugins/nonebot_plugin_picsearcher/yandex.py
old mode 100644
new mode 100755
diff --git a/plugins/one_friend/__init__.py b/plugins/one_friend/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/open_cases/__init__.py b/plugins/open_cases/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/open_cases/config.py b/plugins/open_cases/config.py
old mode 100644
new mode 100755
diff --git a/plugins/open_cases/models/__init__.py b/plugins/open_cases/models/__init__.py
old mode 100644
new mode 100755
index a944b2fd..acf2ed1e
--- a/plugins/open_cases/models/__init__.py
+++ b/plugins/open_cases/models/__init__.py
@@ -1,2 +1,2 @@
-from .open_cases_user import *
-from .buff_prices import *
+from .open_cases_user import *
+from .buff_prices import *
diff --git a/plugins/open_cases/models/buff_prices.py b/plugins/open_cases/models/buff_prices.py
old mode 100644
new mode 100755
diff --git a/plugins/open_cases/models/open_cases_user.py b/plugins/open_cases/models/open_cases_user.py
old mode 100644
new mode 100755
diff --git a/plugins/open_cases/open_cases_c.py b/plugins/open_cases/open_cases_c.py
old mode 100644
new mode 100755
diff --git a/plugins/open_cases/utils.py b/plugins/open_cases/utils.py
old mode 100644
new mode 100755
index 5c534a62..cb5b4d71
--- a/plugins/open_cases/utils.py
+++ b/plugins/open_cases/utils.py
@@ -1,10 +1,8 @@
from .models.buff_prices import BuffPrice
from services.db_context import db
from datetime import datetime, timedelta
-from utils.user_agent import get_user_agent
from configs.path_config import IMAGE_PATH
-import aiohttp
-import aiofiles
+from utils.http_utils import AsyncHttpx
from .models.open_cases_user import OpenCasesUser
import os
from services.log import logger
@@ -43,127 +41,119 @@ async def util_get_buff_price(case_name: str = "狂牙大行动") -> str:
CASE_PINK = eval(case + "_CASE_PINK")
CASE_PURPLE = eval(case + "_CASE_PURPLE")
CASE_BLUE = eval(case + "_CASE_BLUE")
- async with aiohttp.ClientSession(
- cookies=cookie, headers=get_user_agent()
- ) as session:
- for total_list in [CASE_KNIFE, CASE_RED, CASE_PINK, CASE_PURPLE, CASE_BLUE]:
- for skin in total_list:
- if skin in [
- "蝴蝶刀 | 无涂装",
- "求生匕首 | 无涂装",
- "流浪者匕首 | 无涂装",
- "系绳匕首 | 无涂装",
- "骷髅匕首 | 无涂装",
- ]:
- skin = skin.split("|")[0].strip()
- async with db.transaction():
- name_list = []
- price_list = []
- parameter = {"game": "csgo", "page_num": "1", "search": skin}
- try:
- async with session.get(
- url,
- proxy=Config.get_config("open_cases", "BUFF_PROXY"),
- params=parameter,
- timeout=20,
- ) as response:
- if response.status == 200:
- data = (await response.json())["data"]
- total_page = data["total_page"]
- data = data["items"]
- flag = False
- if (
- skin.find("|") == -1
- ): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
- for i in range(1, total_page + 1):
- name_list = []
- price_list = []
- parameter = {
- "game": "csgo",
- "page_num": f"{i}",
- "search": skin,
- }
- async with session.get(
- url, params=parameter, timeout=20
- ) as res:
- data = (await response.json())["data"][
- "items"
- ]
- for j in range(len(data)):
- if data[j]["name"] in [f"{skin}(★)"]:
- name = data[j]["name"]
- price = data[j][
- "sell_reference_price"
- ]
- name_list.append(
- name.split("(")[0].strip()
- + " | 无涂装"
- )
- price_list.append(price)
- flag = True
- break
- if flag:
- break
- else:
- try:
- for _ in range(total_page):
- for i in range(len(data)):
- name = data[i]["name"]
- price = data[i]["sell_reference_price"]
- name_list.append(name)
- price_list.append(price)
- except Exception as e:
- failed_list.append(skin)
- logger.warning(f"{skin}更新失败")
- else:
+ for total_list in [CASE_KNIFE, CASE_RED, CASE_PINK, CASE_PURPLE, CASE_BLUE]:
+ for skin in total_list:
+ if skin in [
+ "蝴蝶刀 | 无涂装",
+ "求生匕首 | 无涂装",
+ "流浪者匕首 | 无涂装",
+ "系绳匕首 | 无涂装",
+ "骷髅匕首 | 无涂装",
+ ]:
+ skin = skin.split("|")[0].strip()
+ async with db.transaction():
+ name_list = []
+ price_list = []
+ parameter = {"game": "csgo", "page_num": "1", "search": skin}
+ try:
+ response = await AsyncHttpx.get(url, proxy=Config.get_config("open_cases", "BUFF_PROXY"),
+ params=parameter,
+ cookies=cookie,)
+ if response.status_code == 200:
+ data = response.json()["data"]
+ total_page = data["total_page"]
+ data = data["items"]
+ flag = False
+ if (
+ skin.find("|") == -1
+ ): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
+ for i in range(1, total_page + 1):
+ name_list = []
+ price_list = []
+ parameter = {
+ "game": "csgo",
+ "page_num": f"{i}",
+ "search": skin,
+ }
+ res = await AsyncHttpx.get(url, params=parameter)
+ data = res.json()["data"][
+ "items"
+ ]
+ for j in range(len(data)):
+ if data[j]["name"] in [f"{skin}(★)"]:
+ name = data[j]["name"]
+ price = data[j][
+ "sell_reference_price"
+ ]
+ name_list.append(
+ name.split("(")[0].strip()
+ + " | 无涂装"
+ )
+ price_list.append(price)
+ flag = True
+ break
+ if flag:
+ break
+ else:
+ try:
+ for _ in range(total_page):
+ for i in range(len(data)):
+ name = data[i]["name"]
+ price = data[i]["sell_reference_price"]
+ name_list.append(name)
+ price_list.append(price)
+ except Exception as e:
failed_list.append(skin)
logger.warning(f"{skin}更新失败")
- except Exception:
+ else:
failed_list.append(skin)
logger.warning(f"{skin}更新失败")
+ except Exception:
+ failed_list.append(skin)
+ logger.warning(f"{skin}更新失败")
+ continue
+ for i in range(len(name_list)):
+ name = name_list[i].strip()
+ price = float(price_list[i])
+ if name.find("(★)") != -1:
+ name = name[: name.find("(")] + name[name.find(")") + 1 :]
+ if name.find("消音") != -1 and name.find("(S") != -1:
+ name = name.split("(")[0][:-4] + "(" + name.split("(")[1]
+ name = (
+ name.split("|")[0].strip()
+ + " | "
+ + name.split("|")[1].strip()
+ )
+ elif name.find("消音") != -1:
+ name = (
+ name.split("|")[0][:-5].strip()
+ + " | "
+ + name.split("|")[1].strip()
+ )
+ if name.find(" 18 ") != -1 and name.find("(S") != -1:
+ name = name.split("(")[0][:-5] + "(" + name.split("(")[1]
+ name = (
+ name.split("|")[0].strip()
+ + " | "
+ + name.split("|")[1].strip()
+ )
+ elif name.find(" 18 ") != -1:
+ name = (
+ name.split("|")[0][:-6].strip()
+ + " | "
+ + name.split("|")[1].strip()
+ )
+ dbskin = await BuffPrice.ensure(name, True)
+ if (
+ dbskin.update_date + timedelta(8)
+ ).date() == datetime.now().date():
continue
- for i in range(len(name_list)):
- name = name_list[i].strip()
- price = float(price_list[i])
- if name.find("(★)") != -1:
- name = name[: name.find("(")] + name[name.find(")") + 1 :]
- if name.find("消音") != -1 and name.find("(S") != -1:
- name = name.split("(")[0][:-4] + "(" + name.split("(")[1]
- name = (
- name.split("|")[0].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- elif name.find("消音") != -1:
- name = (
- name.split("|")[0][:-5].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- if name.find(" 18 ") != -1 and name.find("(S") != -1:
- name = name.split("(")[0][:-5] + "(" + name.split("(")[1]
- name = (
- name.split("|")[0].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- elif name.find(" 18 ") != -1:
- name = (
- name.split("|")[0][:-6].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- dbskin = await BuffPrice.ensure(name, True)
- if (
- dbskin.update_date + timedelta(8)
- ).date() == datetime.now().date():
- continue
- await dbskin.update(
- case_id=case_id,
- skin_price=price,
- update_date=datetime.now(),
- ).apply()
- logger.info(f"{name_list[i]}---------->成功更新")
+ await dbskin.update(
+ case_id=case_id,
+ skin_price=price,
+ update_date=datetime.now(),
+ ).apply()
+ logger.info(f"{name_list[i]}---------->成功更新")
result = None
if failed_list:
result = ""
@@ -187,112 +177,88 @@ async def util_get_buff_img(case_name: str = "狂牙大行动") -> str:
CASE_PINK = eval(case + "_CASE_PINK")
CASE_PURPLE = eval(case + "_CASE_PURPLE")
CASE_BLUE = eval(case + "_CASE_BLUE")
- async with aiohttp.ClientSession(
- cookies=cookie, headers=get_user_agent()
- ) as session:
- for total_list in [CASE_KNIFE, CASE_RED, CASE_PINK, CASE_PURPLE, CASE_BLUE]:
- for skin in total_list:
- parameter = {"game": "csgo", "page_num": "1", "search": skin}
- if skin in [
- "蝴蝶刀 | 无涂装",
- "求生匕首 | 无涂装",
- "流浪者匕首 | 无涂装",
- "系绳匕首 | 无涂装",
- "骷髅匕首 | 无涂装",
- ]:
- skin = skin.split("|")[0].strip()
- logger.info(f"开始更新----->{skin}")
- skin_name = ""
- # try:
- async with session.get(
- url,
- proxy=Config.get_config("open_cases", "BUFF_PROXY"),
- params=parameter,
- timeout=20,
- ) as response:
- if response.status == 200:
- data = (await response.json())["data"]
- total_page = data["total_page"]
- flag = False
- if (
- skin.find("|") == -1
- ): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
- for i in range(1, total_page + 1):
- async with session.get(
- url, params=parameter, timeout=20
- ) as res:
- data = (await response.json())["data"]["items"]
- for j in range(len(data)):
- if data[j]["name"] in [f"{skin}(★)"]:
- img_url = data[j]["goods_info"]["icon_url"]
- for k in pypinyin.pinyin(
- skin + "无涂装", style=pypinyin.NORMAL
- ):
- skin_name += "".join(k)
- async with aiofiles.open(
- IMAGE_PATH + path + skin_name + ".png",
- "wb",
- ) as f:
- logger.info(f"------->开始写入{skin}")
- async with session.get(
- img_url, timeout=7
- ) as res:
- await f.write(await res.read())
- flag = True
- break
- if flag:
- break
- else:
- img_url = (await response.json())["data"]["items"][0][
- "goods_info"
- ]["icon_url"]
- for i in pypinyin.pinyin(
- skin.replace("|", "-").strip(), style=pypinyin.NORMAL
- ):
- skin_name += "".join(i)
- async with aiofiles.open(
- IMAGE_PATH + path + skin_name + ".png", "wb"
- ) as f:
- logger.info(f"------->开始写入 {skin}")
- async with session.get(img_url, timeout=7) as res:
- await f.write(await res.read())
+ for total_list in [CASE_KNIFE, CASE_RED, CASE_PINK, CASE_PURPLE, CASE_BLUE]:
+ for skin in total_list:
+ parameter = {"game": "csgo", "page_num": "1", "search": skin}
+ if skin in [
+ "蝴蝶刀 | 无涂装",
+ "求生匕首 | 无涂装",
+ "流浪者匕首 | 无涂装",
+ "系绳匕首 | 无涂装",
+ "骷髅匕首 | 无涂装",
+ ]:
+ skin = skin.split("|")[0].strip()
+ logger.info(f"开始更新----->{skin}")
+ skin_name = ""
+ # try:
+ response = await AsyncHttpx.get(url, proxy=Config.get_config("open_cases", "BUFF_PROXY"), params=parameter)
+ if response.status_code == 200:
+ data = response.json()["data"]
+ total_page = data["total_page"]
+ flag = False
+ if (
+ skin.find("|") == -1
+ ): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
+ for i in range(1, total_page + 1):
+ res = await AsyncHttpx.get(url, params=parameter)
+ data = res.json()["data"]["items"]
+ for j in range(len(data)):
+ if data[j]["name"] in [f"{skin}(★)"]:
+ img_url = data[j]["goods_info"]["icon_url"]
+ for k in pypinyin.pinyin(
+ skin + "无涂装", style=pypinyin.NORMAL
+ ):
+ skin_name += "".join(k)
+ await AsyncHttpx.download_file(img_url, IMAGE_PATH + path + skin_name + ".png")
+ flag = True
+ break
+ if flag:
+ break
+ else:
+ img_url = (await response.json())["data"]["items"][0][
+ "goods_info"
+ ]["icon_url"]
+ for i in pypinyin.pinyin(
+ skin.replace("|", "-").strip(), style=pypinyin.NORMAL
+ ):
+ skin_name += "".join(i)
+ if await AsyncHttpx.download_file(img_url, IMAGE_PATH + path + skin_name + ".png"):
+ logger.info(f"------->写入 {skin} 成功")
+ else:
+ logger.info(f"------->写入 {skin} 失败")
result = None
if error_list:
result = ""
- for errskin in error_list:
- result += errskin + "\n"
+ for err_skin in error_list:
+ result += err_skin + "\n"
return result[:-1] if result else "更新图片成功"
-async def get_price(dname):
+async def get_price(d_name):
cookie = {"session": Config.get_config("open_cases", "COOKIE")}
name_list = []
price_list = []
- parameter = {"game": "csgo", "page_num": "1", "search": dname}
+ parameter = {"game": "csgo", "page_num": "1", "search": d_name}
try:
- async with aiohttp.ClientSession(
- cookies=cookie, headers=get_user_agent()
- ) as session:
- async with session.get(url, params=parameter, timeout=7) as response:
- if response.status == 200:
- try:
- data = (await response.json())["data"]
- total_page = data["total_page"]
- data = data["items"]
- for _ in range(total_page):
- for i in range(len(data)):
- name = data[i]["name"]
- price = data[i]["sell_reference_price"]
- name_list.append(name)
- price_list.append(price)
- except Exception as e:
- return "没有查询到...", 998
- else:
- return "访问失败!", response.status
+ response = await AsyncHttpx.get(url, cookies=cookie, params=parameter)
+ if response.status_code == 200:
+ try:
+ data = response.json()["data"]
+ total_page = data["total_page"]
+ data = data["items"]
+ for _ in range(total_page):
+ for i in range(len(data)):
+ name = data[i]["name"]
+ price = data[i]["sell_reference_price"]
+ name_list.append(name)
+ price_list.append(price)
+ except Exception as e:
+ return "没有查询到...", 998
+ else:
+ return "访问失败!", response.status_code
except TimeoutError as e:
return "访问超时! 请重试或稍后再试!", 997
- result = f"皮肤: {dname}({len(name_list)})\n"
- # result = "皮肤: " + dname + "\n"
+ result = f"皮肤: {d_name}({len(name_list)})\n"
for i in range(len(name_list)):
result += name_list[i] + ": " + price_list[i] + "\n"
return result[:-1], 999
diff --git a/plugins/parse_bilibili_json.py b/plugins/parse_bilibili_json.py
old mode 100644
new mode 100755
index 34776f38..82172717
--- a/plugins/parse_bilibili_json.py
+++ b/plugins/parse_bilibili_json.py
@@ -11,9 +11,9 @@ from nonebot.adapters.cqhttp.exception import ActionFailed
from utils.image_utils import CreateImg
from utils.browser import get_browser
from configs.path_config import IMAGE_PATH
+from utils.http_utils import AsyncHttpx
import asyncio
import time
-import aiohttp
from bilibili_api import settings
from utils.manager import group_manager
import ujson as json
@@ -51,17 +51,12 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if data:
# 转发视频
if data.get("desc") == "哔哩哔哩":
- async with aiohttp.ClientSession(
- headers=get_user_agent()
- ) as session:
- async with session.get(
- data["meta"]["detail_1"]["qqdocurl"],
- proxy=get_local_proxy(),
- timeout=7,
- ) as response:
- url = str(response.url).split("?")[0]
- bvid = url.split("/")[-1]
- vd_info = await video.Video(bvid=bvid).get_info()
+ response = await AsyncHttpx.get(
+ data["meta"]["detail_1"]["qqdocurl"], timeout=7
+ )
+ url = str(response.url).split("?")[0]
+ bvid = url.split("/")[-1]
+ vd_info = await video.Video(bvid=bvid).get_info()
# 转发专栏
if (
data.get("meta")
diff --git a/plugins/pid_search.py b/plugins/pid_search.py
old mode 100644
new mode 100755
index 80e6701f..43bf19b8
--- a/plugins/pid_search.py
+++ b/plugins/pid_search.py
@@ -1,124 +1,106 @@
-from asyncio.exceptions import TimeoutError
-
-import aiofiles
-import aiohttp
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
-from nonebot.typing import T_State
-
-from configs.path_config import IMAGE_PATH
-from services.log import logger
-from utils.message_builder import image
-from utils.utils import get_message_text, is_number
-from utils.manager import withdraw_message_manager
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-__zx_plugin_name__ = "pid搜索"
-__plugin_usage__ = """
-usage:
- 通过 pid 搜索图片
- 指令:
- p搜 [pid]
-""".strip()
-__plugin_des__ = "通过 pid 搜索图片"
-__plugin_cmd__ = ["p搜 [pid]"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["p搜"],
-}
-
-pid_search = on_command("p搜", aliases={"pixiv搜", "P搜"}, priority=5, block=True)
-
-url = "https://api.fantasyzone.cc/tu/search.php"
-
-
-@pid_search.args_parser
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- pid = get_message_text(event.json())
- if pid:
- if pid in ["取消", "算了"]:
- await pid_search.finish("已取消操作...")
- if not is_number(pid):
- await pid_search.reject("笨蛋,重新输入数!字!", at_sender=True)
- state["pid"] = pid
-
-
-@pid_search.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- pid = get_message_text(event.json())
- if pid:
- state["pid"] = pid
-
-
-@pid_search.got("pid", prompt="需要查询的图片PID是?")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- pid = state["pid"]
- params = {
- "id": pid,
- "p": 1,
- }
- async with aiohttp.ClientSession() as session:
- for _ in range(10):
- try:
- async with session.get(url, timeout=2, params=params) as response:
- data = json.loads(await response.text())
- except TimeoutError:
- pass
- else:
- if not data["width"] and not data["height"]:
- await pid_search.finish(f"没有搜索到 PID:{pid} 的图片", at_sender=True)
- pid = data["id"]
- title = data["title"]
- author = data["userName"]
- author_id = data["userId"]
- img_url = data["url"]
- for _ in range(5):
- try:
- await download_pic(img_url, event.user_id)
- except TimeoutError:
- pass
- else:
- break
- else:
- await pid_search.finish("图片下载失败了....", at_sender=True)
- tmp = ""
- if isinstance(event, GroupMessageEvent):
- tmp = "\n【注】将在30后撤回......"
- msg_id = await pid_search.send(
- Message(
- f"title:{title}\n"
- f"pid:{pid}\n"
- f"author:{author}\n"
- f"author_id:{author_id}\n"
- f'{image(f"pid_search_{event.user_id}.png", "temp")}'
- f"{tmp}"
- )
- )
- logger.info(
- f"(USER {event.user_id}, "
- f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查询图片 PID:{pid}"
- )
- if isinstance(event, GroupMessageEvent):
- withdraw_message_manager.append((msg_id, 30))
- break
- else:
- await pid_search.finish("图片下载失败了....", at_sender=True)
-
-
-async def download_pic(img_url: str, user_id: int):
- async with aiohttp.ClientSession() as session:
- async with session.get(img_url, timeout=2) as res:
- async with aiofiles.open(
- f"{IMAGE_PATH}/temp/pid_search_{user_id}.png", "wb"
- ) as f:
- await f.write(await res.read())
+from asyncio.exceptions import TimeoutError
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
+from nonebot.typing import T_State
+from configs.path_config import TEMP_PATH
+from services.log import logger
+from utils.message_builder import image
+from utils.utils import get_message_text, is_number
+from utils.manager import withdraw_message_manager
+from utils.http_utils import AsyncHttpx
+from pathlib import Path
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+__zx_plugin_name__ = "pid搜索"
+__plugin_usage__ = """
+usage:
+ 通过 pid 搜索图片
+ 指令:
+ p搜 [pid]
+""".strip()
+__plugin_des__ = "通过 pid 搜索图片"
+__plugin_cmd__ = ["p搜 [pid]"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["p搜"],
+}
+
+pid_search = on_command("p搜", aliases={"pixiv搜", "P搜"}, priority=5, block=True)
+
+url = "https://api.fantasyzone.cc/tu/search.php"
+
+
+@pid_search.args_parser
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ pid = get_message_text(event.json())
+ if pid:
+ if pid in ["取消", "算了"]:
+ await pid_search.finish("已取消操作...")
+ if not is_number(pid):
+ await pid_search.reject("笨蛋,重新输入数!字!", at_sender=True)
+ state["pid"] = pid
+
+
+@pid_search.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ pid = get_message_text(event.json())
+ if pid:
+ state["pid"] = pid
+
+
+@pid_search.got("pid", prompt="需要查询的图片PID是?")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ pid = state["pid"]
+ params = {
+ "id": pid,
+ "p": 1,
+ }
+ for _ in range(10):
+ try:
+ data = (await AsyncHttpx.get(url, params=params, timeout=5)).json()
+ except TimeoutError:
+ pass
+ else:
+ if not data["width"] and not data["height"]:
+ await pid_search.finish(f"没有搜索到 PID:{pid} 的图片", at_sender=True)
+ pid = data["id"]
+ title = data["title"]
+ author = data["userName"]
+ author_id = data["userId"]
+ img_url = data["url"]
+ if not await AsyncHttpx.download_file(
+ img_url, Path(TEMP_PATH) / f"pid_search_{event.user_id}.png"
+ ):
+ await pid_search.finish("图片下载失败了....", at_sender=True)
+ tmp = ""
+ if isinstance(event, GroupMessageEvent):
+ tmp = "\n【注】将在30后撤回......"
+ msg_id = await pid_search.send(
+ Message(
+ f"title:{title}\n"
+ f"pid:{pid}\n"
+ f"author:{author}\n"
+ f"author_id:{author_id}\n"
+ f'{image(f"pid_search_{event.user_id}.png", "temp")}'
+ f"{tmp}"
+ )
+ )
+ logger.info(
+ f"(USER {event.user_id}, "
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 查询图片 PID:{pid}"
+ )
+ if isinstance(event, GroupMessageEvent):
+ withdraw_message_manager.append((msg_id, 30))
+ break
+ else:
+ await pid_search.finish("图片下载失败了....", at_sender=True)
diff --git a/plugins/pix_gallery/__init__.py b/plugins/pix_gallery/__init__.py
old mode 100644
new mode 100755
index 15e42178..54bd7414
--- a/plugins/pix_gallery/__init__.py
+++ b/plugins/pix_gallery/__init__.py
@@ -1,62 +1,135 @@
-from configs.config import Config
-import nonebot
-
-
-__zx_plugin_name__ = "更新扩展图库Omega [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-Config.add_plugin_config(
- "hibiapi",
- "HIBIAPI",
- "https://api.obfs.dev",
- help_="如果没有自建或其他hibiapi请不要修改",
- default_value="https://api.obfs.dev",
-)
-Config.add_plugin_config(
- "pixiv",
- "PIXIV_NGINX_URL",
- "i.pixiv.re",
- help_="Pixiv反向代理"
-)
-Config.add_plugin_config(
- "pix",
- "PIX_IMAGE_SIZE",
- "master",
- name="PIX图库",
- help_="PIX图库下载的画质 可能的值:original:原图,master:缩略图(加快发送速度)",
- default_value="master"
-)
-Config.add_plugin_config(
- "pix",
- "SEARCH_HIBIAPI_BOOKMARKS",
- 5000,
- help_="最低收藏,PIX使用HIBIAPI搜索图片时达到最低收藏才会添加至图库",
- default_value=5000
-)
-Config.add_plugin_config(
- "pix",
- "WITHDRAW_PIX_MESSAGE",
- (0, 1),
- help_="自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
- default_value=(0, 1)
-)
-Config.add_plugin_config(
- "pix",
- "PIX_OMEGA_PIXIV_RATIO",
- (10, 0),
- help_="PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1:PIX图库 参2:OmegaPixivIllusts扩展图库(没有此图库请设置为0)",
- default_value=(10, 0)
-)
-Config.add_plugin_config(
- "pix",
- "TIMEOUT",
- 10,
- help_="下载图片超时限制(秒)",
- default_value=10
-)
-
-nonebot.load_plugins("plugins/pix_gallery")
-
-
+from configs.config import Config
+from services.log import logger
+from .model.omega_pixiv_illusts import OmegaPixivIllusts
+from pathlib import Path
+from nonebot import Driver
+from typing import List
+from datetime import datetime
+import nonebot
+import asyncio
+import os
+
+
+__zx_plugin_name__ = "更新扩展图库Omega [Hidden]"
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+Config.add_plugin_config(
+ "hibiapi",
+ "HIBIAPI",
+ "https://api.obfs.dev",
+ help_="如果没有自建或其他hibiapi请不要修改",
+ default_value="https://api.obfs.dev",
+)
+Config.add_plugin_config(
+ "pixiv",
+ "PIXIV_NGINX_URL",
+ "i.pixiv.re",
+ help_="Pixiv反向代理"
+)
+Config.add_plugin_config(
+ "pix",
+ "PIX_IMAGE_SIZE",
+ "master",
+ name="PIX图库",
+ help_="PIX图库下载的画质 可能的值:original:原图,master:缩略图(加快发送速度)",
+ default_value="master"
+)
+Config.add_plugin_config(
+ "pix",
+ "SEARCH_HIBIAPI_BOOKMARKS",
+ 5000,
+ help_="最低收藏,PIX使用HIBIAPI搜索图片时达到最低收藏才会添加至图库",
+ default_value=5000
+)
+Config.add_plugin_config(
+ "pix",
+ "WITHDRAW_PIX_MESSAGE",
+ (0, 1),
+ help_="自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
+ default_value=(0, 1)
+)
+Config.add_plugin_config(
+ "pix",
+ "PIX_OMEGA_PIXIV_RATIO",
+ (10, 0),
+ help_="PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1:PIX图库 参2:OmegaPixivIllusts扩展图库(没有此图库请设置为0)",
+ default_value=(10, 0)
+)
+Config.add_plugin_config(
+ "pix",
+ "TIMEOUT",
+ 10,
+ help_="下载图片超时限制(秒)",
+ default_value=10
+)
+
+nonebot.load_plugins("plugins/pix_gallery")
+
+driver: Driver = nonebot.get_driver()
+
+
+@driver.on_startup
+async def _init_omega_pixiv_illusts():
+ omega_pixiv_illusts = None
+ for file in os.listdir("."):
+ if "omega_pixiv_illusts" in file and ".sql" in file:
+ omega_pixiv_illusts = Path() / file
+ if omega_pixiv_illusts:
+ with open(omega_pixiv_illusts, "r", encoding="utf8") as f:
+ lines = f.readlines()
+ tasks = []
+ length = len([x for x in lines if "INSERT INTO" in x.upper()])
+ all_pid = await OmegaPixivIllusts.get_all_pid()
+ index = 0
+ logger.info("检测到OmegaPixivIllusts数据库,准备开始更新....")
+ for line in lines:
+ if "INSERT INTO" in line.upper():
+ index += 1
+ tasks.append(
+ asyncio.ensure_future(_tasks(line, all_pid, length, index))
+ )
+ await asyncio.gather(*tasks)
+ omega_pixiv_illusts.unlink()
+
+
+async def _tasks(line: str, all_pid: List[int], length: int, index: int):
+ data = line.split("VALUES", maxsplit=1)[-1].strip()
+ if data.startswith("("):
+ data = data[1:]
+ if data.endswith(");"):
+ data = data[:-2]
+ x = data.split(maxsplit=3)
+ pid = int(x[1][:-1].strip())
+ if pid in all_pid:
+ logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
+ return
+ uid = int(x[2][:-1].strip())
+ x = x[3].split(", '")
+ title = x[0].strip()[1:-1]
+ tmp = x[1].split(", ")
+ author = tmp[0].strip()[:-1]
+ nsfw_tag = int(tmp[1])
+ width = int(tmp[2])
+ height = int(tmp[3])
+ tags = x[2][:-1]
+ url = x[3][:-1]
+ if await OmegaPixivIllusts.add_image_data(
+ pid,
+ title,
+ width,
+ height,
+ url,
+ uid,
+ author,
+ nsfw_tag,
+ tags,
+ datetime.min,
+ datetime.min,
+ ):
+ logger.info(
+ f"成功添加OmegaPixivIllusts图库数据 pid:{pid} 本次预计存储 {length} 张,已更新第 {index} 张"
+ )
+ else:
+ logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
diff --git a/plugins/pix_gallery/data_source.py b/plugins/pix_gallery/data_source.py
old mode 100644
new mode 100755
index a85e8bde..02788b8b
--- a/plugins/pix_gallery/data_source.py
+++ b/plugins/pix_gallery/data_source.py
@@ -1,452 +1,392 @@
-from aiohttp.client_exceptions import (
- ClientOSError,
- ServerDisconnectedError,
- ClientConnectorError,
-)
-from asyncpg.exceptions import UniqueViolationError
-from .model.omega_pixiv_illusts import OmegaPixivIllusts
-from asyncio.locks import Semaphore
-from aiohttp import ClientPayloadError
-from aiohttp.client import ClientSession
-from asyncio.exceptions import TimeoutError
-from .model.pixiv import Pixiv
-from typing import List
-from utils.utils import get_local_proxy, change_picture_links
-from utils.image_utils import CreateImg
-from services.log import logger
-from configs.config import Config
-from configs.path_config import TEMP_PATH
-import platform
-import aiohttp
-import asyncio
-import aiofiles
-import math
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-if str(platform.system()).lower() == "windows":
- policy = asyncio.WindowsSelectorEventLoopPolicy()
- asyncio.set_event_loop_policy(policy)
-
-headers = {
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
- " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
- "Referer": "https://www.pixiv.net",
-}
-
-HIBIAPI = None
-
-
-async def start_update_image_url(
- current_keyword: List[str], black_pid: List[str]
-) -> "int, int":
- """
- 开始更新图片url
- :param current_keyword: 关键词
- :param black_pid: 黑名单pid
- :return: pid数量和图片数量
- """
- global HIBIAPI
- pid_count = 0
- pic_count = 0
- tasks = []
- semaphore = asyncio.Semaphore(10)
- if not HIBIAPI:
- HIBIAPI = Config.get_config("hibiapi", "HIBIAPI")
- HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] == "/" else HIBIAPI
- async with aiohttp.ClientSession(headers=headers) as session:
- for keyword in current_keyword:
- for page in range(1, 110):
- if keyword.startswith("uid:"):
- url = f"{HIBIAPI}/api/pixiv/member_illust"
- params = {"id": keyword[4:], "page": page}
- if page == 30:
- break
- elif keyword.startswith("pid:"):
- url = f"{HIBIAPI}/api/pixiv/illust"
- params = {"id": keyword[4:]}
- else:
- url = f"{HIBIAPI}/api/pixiv/search"
- params = {"word": keyword, "page": page}
- tasks.append(
- asyncio.ensure_future(
- search_image(
- url, keyword, params, semaphore, session, page, black_pid
- )
- )
- )
- if keyword.startswith("pid:"):
- break
- result = await asyncio.gather(*tasks)
- for x in result:
- pid_count += x[0]
- pic_count += x[1]
- return pid_count, pic_count
-
-
-async def search_image(
- url: str,
- keyword: str,
- params: dict,
- semaphore: Semaphore,
- session: ClientSession,
- page: int = 1,
- black: List[str] = None,
-) -> "int, int":
- """
- 搜索图片
- :param url: 搜索url
- :param keyword: 关键词
- :param params: params参数
- :param semaphore: semaphore
- :param session: session
- :param page: 页面
- :param black: pid黑名单
- :return: pid数量和图片数量
- """
- tmp_pid = []
- pic_count = 0
- pid_count = 0
- async with semaphore:
- try:
- async with session.get(
- url,
- params=params,
- proxy=get_local_proxy(),
- ) as response:
- data = await response.json()
- if (
- not data
- or data.get("error")
- or (not data.get("illusts") and not data.get("illust"))
- ):
- return 0, 0
- if url != f"{HIBIAPI}/api/pixiv/illust":
- logger.info(f'{keyword}: 获取数据成功...数据总量:{len(data["illusts"])}')
- data = data["illusts"]
- else:
- logger.info(f'获取数据成功...PID:{params.get("id")}')
- data = [data["illust"]]
- img_data = {}
- for x in data:
- pid = x["id"]
- title = x["title"]
- width = x["width"]
- height = x["height"]
- view = x["total_view"]
- bookmarks = x["total_bookmarks"]
- uid = x["user"]["id"]
- author = x["user"]["name"]
- tags = []
- for tag in x["tags"]:
- for i in tag:
- if tag[i]:
- tags.append(tag[i])
- img_urls = []
- if x["page_count"] == 1:
- img_urls.append(x["meta_single_page"]["original_image_url"])
- else:
- for urls in x["meta_pages"]:
- img_urls.append(urls["image_urls"]["original"])
- if (
- (
- bookmarks
- >= Config.get_config("pix", "SEARCH_HIBIAPI_BOOKMARKS")
- or (
- url == f"{HIBIAPI}/api/pixiv/member_illust"
- and bookmarks >= 1500
- )
- or (url == f"{HIBIAPI}/api/pixiv/illust")
- )
- and len(img_urls) < 10
- and _check_black(img_urls, black)
- ):
- img_data[pid] = {
- "pid": pid,
- "title": title,
- "width": width,
- "height": height,
- "view": view,
- "bookmarks": bookmarks,
- "img_urls": img_urls,
- "uid": uid,
- "author": author,
- "tags": tags,
- }
- else:
- continue
- for x in img_data.keys():
- data = img_data[x]
- for img_url in data["img_urls"]:
- img_p = img_url[img_url.rfind("_") + 1 : img_url.rfind(".")]
- try:
- if await Pixiv.add_image_data(
- data["pid"],
- data["title"],
- data["width"],
- data["height"],
- data["view"],
- data["bookmarks"],
- img_url,
- img_p,
- data["uid"],
- data["author"],
- ",".join(data["tags"]),
- ):
- if data["pid"] not in tmp_pid:
- pid_count += 1
- tmp_pid.append(data["pid"])
- pic_count += 1
- logger.info(f'存储图片PID:{data["pid"]} IMG_P:{img_p}')
- except UniqueViolationError:
- logger.warning(f'{data["pid"]} | {img_url} 已存在...')
- except (ServerDisconnectedError, ClientConnectorError, ClientOSError):
- logger.warning("搜索图片服务被关闭,再次调用....")
- await search_image(url, keyword, params, semaphore, session, page, black)
- return pid_count, pic_count
-
-
-# 下载图片
-async def download_image(img_url: str, session: ClientSession, _count: int = 1):
- """
- 下载图片
- :param img_url: 图片url
- :param session: session
- :param _count: 次数
- """
- try:
- async with session.get(img_url, proxy=get_local_proxy()) as response:
- logger.info(f"下载图片 --> {img_url}")
- async with aiofiles.open(f'tmp/{img_url.split("/")[-1]}', "wb") as f:
- await f.write(await response.read())
- except ServerDisconnectedError:
- logger.warning(f"下载图片服务被关闭,第 {_count} 次调用....")
- await download_image(img_url, session, _count + 1)
- except ClientOSError:
- logger.warning(f"远程连接被关闭,第 {_count} 次调用....")
- ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
- if ws_url:
- img_url = img_url.replace("i.pximg.net", ws_url)
- await download_image(img_url, session, _count + 1)
- except TimeoutError:
- logger.warning(f"下载或写入超时,第 {_count} 次调用....")
- await download_image(img_url, session, _count + 1)
- except ClientPayloadError:
- pass
-
-
-async def get_image(img_url: str, user_id: int) -> str:
- """
- 下载图片
- :param img_url:
- :param user_id:
- :return: 图片名称
- """
- global HIBIAPI
- if not HIBIAPI:
- HIBIAPI = Config.get_config("hibiapi", "HIBIAPI")
- HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] == "/" else HIBIAPI
- async with aiohttp.ClientSession(headers=headers) as session:
- if "https://www.pixiv.net/artworks" in img_url:
- pid = img_url.rsplit("/", maxsplit=1)[-1]
- params = {"id": pid}
- for _ in range(3):
- try:
- async with session.get(
- f"{HIBIAPI}/api/pixiv/illust",
- params=params,
- proxy=get_local_proxy(),
- ) as response:
- if response.status == 200:
- data = await response.json()
- if data.get("illust"):
- if data["illust"]["page_count"] == 1:
- img_url = data["illust"]["meta_single_page"][
- "original_image_url"
- ]
- else:
- img_url = data["illust"]["meta_pages"][0][
- "image_urls"
- ]["original"]
- break
- except (ClientConnectorError, TimeoutError):
- pass
- old_img_url = img_url
- img_url = change_picture_links(
- img_url, Config.get_config("pix", "PIX_IMAGE_SIZE")
- )
- ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
- if ws_url:
- if ws_url.startswith("http"):
- ws_url = ws_url.split("//")[-1]
- img_url = img_url.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
- for _ in range(3):
- try:
- async with session.get(
- img_url,
- proxy=get_local_proxy(),
- timeout=Config.get_config("pix", "TIMEOUT"),
- ) as response:
- if response.status == 404:
- img_url = old_img_url
- continue
- async with aiofiles.open(
- f"{TEMP_PATH}/pix_{user_id}_{img_url[-10:-4]}.jpg", "wb"
- ) as f:
- await f.write(await response.read())
- return f"pix_{user_id}_{img_url[-10:-4]}.jpg"
- except (ClientConnectorError, TimeoutError):
- pass
-
-
-async def uid_pid_exists(id_: str) -> bool:
- """
- 检测 pid/uid 是否有效
- :param id_: pid/uid
- """
- if id_.startswith("uid:"):
- url = f"{HIBIAPI}/api/pixiv/member"
- elif id_.startswith("pid:"):
- url = f"{HIBIAPI}/api/pixiv/illust"
- else:
- return False
- params = {"id": int(id_[4:])}
- async with aiohttp.ClientSession(headers=headers) as session:
- async with session.get(url, params=params, proxy=get_local_proxy()) as response:
- data = await response.json()
- if data.get("error"):
- return False
- return True
-
-
-async def get_keyword_num(keyword: str) -> "int, int, int, int, int":
- """
- 查看图片相关 tag 数量
- :param keyword: 关键词tag
- """
- count, r18_count = await Pixiv.get_keyword_num(keyword.split())
- count_, setu_count, r18_count_ = await OmegaPixivIllusts.get_keyword_num(
- keyword.split()
- )
- return count, r18_count, count_, setu_count, r18_count_
-
-
-async def remove_image(pid: int, img_p: str) -> bool:
- """
- 删除置顶图片
- :param pid: pid
- :param img_p: 图片 p 如 p0,p1 等
- """
- if img_p:
- if "p" not in img_p:
- img_p = f"p{img_p}"
- return await Pixiv.remove_image_data(pid, img_p)
-
-
-def gen_keyword_pic(
- _pass_keyword: List[str], not_pass_keyword: List[str], is_superuser: bool
-):
- """
- 已通过或未通过的所有关键词/uid/pid
- :param _pass_keyword: 通过列表
- :param not_pass_keyword: 未通过列表
- :param is_superuser: 是否超级用户
- """
- _keyword = [
- x
- for x in _pass_keyword
- if not x.startswith("uid:")
- and not x.startswith("pid:")
- and not x.startswith("black:")
- ]
- _uid = [x for x in _pass_keyword if x.startswith("uid:")]
- _pid = [x for x in _pass_keyword if x.startswith("pid:")]
- _n_keyword = [
- x
- for x in not_pass_keyword
- if not x.startswith("uid:")
- and not x.startswith("pid:")
- and not x.startswith("black:")
- ]
- _n_uid = [
- x
- for x in not_pass_keyword
- if x.startswith("uid:") and not x.startswith("black:")
- ]
- _n_pid = [
- x
- for x in not_pass_keyword
- if x.startswith("pid:") and not x.startswith("black:")
- ]
- img_width = 0
- img_data = {
- "_keyword": {"width": 0, "data": _keyword},
- "_uid": {"width": 0, "data": _uid},
- "_pid": {"width": 0, "data": _pid},
- "_n_keyword": {"width": 0, "data": _n_keyword},
- "_n_uid": {"width": 0, "data": _n_uid},
- "_n_pid": {"width": 0, "data": _n_pid},
- }
- for x in list(img_data.keys()):
- img_data[x]["width"] = math.ceil(len(img_data[x]["data"]) / 40)
- img_width += img_data[x]["width"] * 200
- if not is_superuser:
- img_width = (
- img_width
- - (
- img_data["_n_keyword"]["width"]
- + img_data["_n_uid"]["width"]
- + img_data["_n_pid"]["width"]
- )
- * 200
- )
- del img_data["_n_keyword"]
- del img_data["_n_pid"]
- del img_data["_n_uid"]
- current_width = 0
- A = CreateImg(img_width, 1100)
- for x in list(img_data.keys()):
- if img_data[x]["data"]:
- img = CreateImg(img_data[x]["width"] * 200, 1100, 200, 1100, font_size=40)
- start_index = 0
- end_index = 40
- total_index = img_data[x]["width"] * 40
- for _ in range(img_data[x]["width"]):
- tmp = CreateImg(198, 1100, font_size=20)
- text_img = CreateImg(198, 100, font_size=50)
- key_str = "\n".join(
- [key for key in img_data[x]["data"][start_index:end_index]]
- )
- tmp.text((10, 100), key_str)
- if x.find("_n") == -1:
- text_img.text((24, 24), "已收录")
- else:
- text_img.text((24, 24), "待收录")
- tmp.paste(text_img, (0, 0))
- start_index += 40
- end_index = (
- end_index + 40 if end_index + 40 <= total_index else total_index
- )
- background_img = CreateImg(200, 1100, color="#FFE4C4")
- background_img.paste(tmp, (1, 1))
- img.paste(background_img)
- A.paste(img, (current_width, 0))
- current_width += img_data[x]["width"] * 200
- return A.pic2bs4()
-
-
-def _check_black(img_urls: List[str], black: List[str]) -> bool:
- """
- 检测pid是否在黑名单中
- :param img_urls: 图片img列表
- :param black: 黑名单
- :return:
- """
- for b in black:
- for img_url in img_urls:
- if b in img_url:
- return False
- return True
+from asyncpg.exceptions import UniqueViolationError
+from .model.omega_pixiv_illusts import OmegaPixivIllusts
+from asyncio.locks import Semaphore
+from asyncio.exceptions import TimeoutError
+from .model.pixiv import Pixiv
+from typing import List, Optional
+from utils.utils import change_pixiv_image_links
+from utils.image_utils import CreateImg
+from utils.http_utils import AsyncHttpx
+from services.log import logger
+from configs.config import Config
+from configs.path_config import TEMP_PATH
+import aiofiles
+import platform
+import asyncio
+import math
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+if str(platform.system()).lower() == "windows":
+ policy = asyncio.WindowsSelectorEventLoopPolicy()
+ asyncio.set_event_loop_policy(policy)
+
+headers = {
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
+ " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
+ "Referer": "https://www.pixiv.net",
+}
+
+HIBIAPI = None
+
+
+async def start_update_image_url(
+ current_keyword: List[str], black_pid: List[str]
+) -> "int, int":
+ """
+ 开始更新图片url
+ :param current_keyword: 关键词
+ :param black_pid: 黑名单pid
+ :return: pid数量和图片数量
+ """
+ global HIBIAPI
+ pid_count = 0
+ pic_count = 0
+ tasks = []
+ semaphore = asyncio.Semaphore(10)
+ if not HIBIAPI:
+ HIBIAPI = Config.get_config("hibiapi", "HIBIAPI")
+ HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] else HIBIAPI
+ for keyword in current_keyword:
+ for page in range(1, 110):
+ if keyword.startswith("uid:"):
+ url = f"{HIBIAPI}/api/pixiv/member_illust"
+ params = {"id": keyword[4:], "page": page}
+ if page == 30:
+ break
+ elif keyword.startswith("pid:"):
+ url = f"{HIBIAPI}/api/pixiv/illust"
+ params = {"id": keyword[4:]}
+ else:
+ url = f"{HIBIAPI}/api/pixiv/search"
+ params = {"word": keyword, "page": page}
+ tasks.append(
+ asyncio.ensure_future(
+ search_image(
+ url, keyword, params, semaphore, page, black_pid
+ )
+ )
+ )
+ if keyword.startswith("pid:"):
+ break
+ result = await asyncio.gather(*tasks)
+ for x in result:
+ pid_count += x[0]
+ pic_count += x[1]
+ return pid_count, pic_count
+
+
+async def search_image(
+ url: str,
+ keyword: str,
+ params: dict,
+ semaphore: Semaphore,
+ page: int = 1,
+ black: List[str] = None,
+) -> "int, int":
+ """
+ 搜索图片
+ :param url: 搜索url
+ :param keyword: 关键词
+ :param params: params参数
+ :param semaphore: semaphore
+ :param page: 页面
+ :param black: pid黑名单
+ :return: pid数量和图片数量
+ """
+ tmp_pid = []
+ pic_count = 0
+ pid_count = 0
+ async with semaphore:
+ try:
+ data = (await AsyncHttpx.get(url, params=params)).json()
+ if (
+ not data
+ or data.get("error")
+ or (not data.get("illusts") and not data.get("illust"))
+ ):
+ return 0, 0
+ if url != f"{HIBIAPI}/api/pixiv/illust":
+ logger.info(f'{keyword}: 获取数据成功...数据总量:{len(data["illusts"])}')
+ data = data["illusts"]
+ else:
+ logger.info(f'获取数据成功...PID:{params.get("id")}')
+ data = [data["illust"]]
+ img_data = {}
+ for x in data:
+ pid = x["id"]
+ title = x["title"]
+ width = x["width"]
+ height = x["height"]
+ view = x["total_view"]
+ bookmarks = x["total_bookmarks"]
+ uid = x["user"]["id"]
+ author = x["user"]["name"]
+ tags = []
+ for tag in x["tags"]:
+ for i in tag:
+ if tag[i]:
+ tags.append(tag[i])
+ img_urls = []
+ if x["page_count"] == 1:
+ img_urls.append(x["meta_single_page"]["original_image_url"])
+ else:
+ for urls in x["meta_pages"]:
+ img_urls.append(urls["image_urls"]["original"])
+ if (
+ (
+ bookmarks
+ >= Config.get_config("pix", "SEARCH_HIBIAPI_BOOKMARKS")
+ or (
+ url == f"{HIBIAPI}/api/pixiv/member_illust"
+ and bookmarks >= 1500
+ )
+ or (url == f"{HIBIAPI}/api/pixiv/illust")
+ )
+ and len(img_urls) < 10
+ and _check_black(img_urls, black)
+ ):
+ img_data[pid] = {
+ "pid": pid,
+ "title": title,
+ "width": width,
+ "height": height,
+ "view": view,
+ "bookmarks": bookmarks,
+ "img_urls": img_urls,
+ "uid": uid,
+ "author": author,
+ "tags": tags,
+ }
+ else:
+ continue
+ for x in img_data.keys():
+ data = img_data[x]
+ for img_url in data["img_urls"]:
+ img_p = img_url[img_url.rfind("_") + 1 : img_url.rfind(".")]
+ try:
+ if await Pixiv.add_image_data(
+ data["pid"],
+ data["title"],
+ data["width"],
+ data["height"],
+ data["view"],
+ data["bookmarks"],
+ img_url,
+ img_p,
+ data["uid"],
+ data["author"],
+ ",".join(data["tags"]),
+ ):
+ if data["pid"] not in tmp_pid:
+ pid_count += 1
+ tmp_pid.append(data["pid"])
+ pic_count += 1
+ logger.info(f'存储图片PID:{data["pid"]} IMG_P:{img_p}')
+ except UniqueViolationError:
+ logger.warning(f'{data["pid"]} | {img_url} 已存在...')
+ except Exception as e:
+ logger.warning(f"PIX在线搜索图片错误,已再次调用 {type(e)}:{e}")
+ await search_image(url, keyword, params, semaphore, page, black)
+ return pid_count, pic_count
+
+
+async def get_image(img_url: str, user_id: int) -> Optional[str]:
+ """
+ 下载图片
+ :param img_url:
+ :param user_id:
+ :return: 图片名称
+ """
+ if "https://www.pixiv.net/artworks" in img_url:
+ pid = img_url.rsplit("/", maxsplit=1)[-1]
+ params = {"id": pid}
+ for _ in range(3):
+ try:
+ response = await AsyncHttpx.get(f"{HIBIAPI}/api/pixiv/illust", params=params)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("illust"):
+ if data["illust"]["page_count"] == 1:
+ img_url = data["illust"]["meta_single_page"][
+ "original_image_url"
+ ]
+ else:
+ img_url = data["illust"]["meta_pages"][0][
+ "image_urls"
+ ]["original"]
+ break
+ except TimeoutError:
+ pass
+ old_img_url = img_url
+ img_url = change_pixiv_image_links(
+ img_url, Config.get_config("pix", "PIX_IMAGE_SIZE"), Config.get_config("pixiv", "PIXIV_NGINX_URL")
+ )
+ old_img_url = change_pixiv_image_links(
+ old_img_url, None, Config.get_config("pixiv", "PIXIV_NGINX_URL")
+ )
+ for _ in range(3):
+ try:
+ response = await AsyncHttpx.get(img_url, timeout=Config.get_config("pix", "TIMEOUT"),)
+ if response.status_code == 404:
+ img_url = old_img_url
+ continue
+ async with aiofiles.open(
+ f"{TEMP_PATH}/pix_{user_id}_{img_url[-10:-4]}.jpg", "wb"
+ ) as f:
+ await f.write(response.content)
+ return f"pix_{user_id}_{img_url[-10:-4]}.jpg"
+ except TimeoutError:
+ pass
+ return None
+
+
+async def uid_pid_exists(id_: str) -> bool:
+ """
+ 检测 pid/uid 是否有效
+ :param id_: pid/uid
+ """
+ if id_.startswith("uid:"):
+ url = f"{HIBIAPI}/api/pixiv/member"
+ elif id_.startswith("pid:"):
+ url = f"{HIBIAPI}/api/pixiv/illust"
+ else:
+ return False
+ params = {"id": int(id_[4:])}
+ data = (await AsyncHttpx.get(url, params=params)).json()
+ if data.get("error"):
+ return False
+ return True
+
+
+async def get_keyword_num(keyword: str) -> "int, int, int, int, int":
+ """
+ 查看图片相关 tag 数量
+ :param keyword: 关键词tag
+ """
+ count, r18_count = await Pixiv.get_keyword_num(keyword.split())
+ count_, setu_count, r18_count_ = await OmegaPixivIllusts.get_keyword_num(
+ keyword.split()
+ )
+ return count, r18_count, count_, setu_count, r18_count_
+
+
+async def remove_image(pid: int, img_p: str) -> bool:
+ """
+ 删除置顶图片
+ :param pid: pid
+ :param img_p: 图片 p 如 p0,p1 等
+ """
+ if img_p:
+ if "p" not in img_p:
+ img_p = f"p{img_p}"
+ return await Pixiv.remove_image_data(pid, img_p)
+
+
+def gen_keyword_pic(
+ _pass_keyword: List[str], not_pass_keyword: List[str], is_superuser: bool
+):
+ """
+ 已通过或未通过的所有关键词/uid/pid
+ :param _pass_keyword: 通过列表
+ :param not_pass_keyword: 未通过列表
+ :param is_superuser: 是否超级用户
+ """
+ _keyword = [
+ x
+ for x in _pass_keyword
+ if not x.startswith("uid:")
+ and not x.startswith("pid:")
+ and not x.startswith("black:")
+ ]
+ _uid = [x for x in _pass_keyword if x.startswith("uid:")]
+ _pid = [x for x in _pass_keyword if x.startswith("pid:")]
+ _n_keyword = [
+ x
+ for x in not_pass_keyword
+ if not x.startswith("uid:")
+ and not x.startswith("pid:")
+ and not x.startswith("black:")
+ ]
+ _n_uid = [
+ x
+ for x in not_pass_keyword
+ if x.startswith("uid:") and not x.startswith("black:")
+ ]
+ _n_pid = [
+ x
+ for x in not_pass_keyword
+ if x.startswith("pid:") and not x.startswith("black:")
+ ]
+ img_width = 0
+ img_data = {
+ "_keyword": {"width": 0, "data": _keyword},
+ "_uid": {"width": 0, "data": _uid},
+ "_pid": {"width": 0, "data": _pid},
+ "_n_keyword": {"width": 0, "data": _n_keyword},
+ "_n_uid": {"width": 0, "data": _n_uid},
+ "_n_pid": {"width": 0, "data": _n_pid},
+ }
+ for x in list(img_data.keys()):
+ img_data[x]["width"] = math.ceil(len(img_data[x]["data"]) / 40)
+ img_width += img_data[x]["width"] * 200
+ if not is_superuser:
+ img_width = (
+ img_width
+ - (
+ img_data["_n_keyword"]["width"]
+ + img_data["_n_uid"]["width"]
+ + img_data["_n_pid"]["width"]
+ )
+ * 200
+ )
+ del img_data["_n_keyword"]
+ del img_data["_n_pid"]
+ del img_data["_n_uid"]
+ current_width = 0
+ A = CreateImg(img_width, 1100)
+ for x in list(img_data.keys()):
+ if img_data[x]["data"]:
+ img = CreateImg(img_data[x]["width"] * 200, 1100, 200, 1100, font_size=40)
+ start_index = 0
+ end_index = 40
+ total_index = img_data[x]["width"] * 40
+ for _ in range(img_data[x]["width"]):
+ tmp = CreateImg(198, 1100, font_size=20)
+ text_img = CreateImg(198, 100, font_size=50)
+ key_str = "\n".join(
+ [key for key in img_data[x]["data"][start_index:end_index]]
+ )
+ tmp.text((10, 100), key_str)
+ if x.find("_n") == -1:
+ text_img.text((24, 24), "已收录")
+ else:
+ text_img.text((24, 24), "待收录")
+ tmp.paste(text_img, (0, 0))
+ start_index += 40
+ end_index = (
+ end_index + 40 if end_index + 40 <= total_index else total_index
+ )
+ background_img = CreateImg(200, 1100, color="#FFE4C4")
+ background_img.paste(tmp, (1, 1))
+ img.paste(background_img)
+ A.paste(img, (current_width, 0))
+ current_width += img_data[x]["width"] * 200
+ return A.pic2bs4()
+
+
+def _check_black(img_urls: List[str], black: List[str]) -> bool:
+ """
+ 检测pid是否在黑名单中
+ :param img_urls: 图片img列表
+ :param black: 黑名单
+ :return:
+ """
+ for b in black:
+ for img_url in img_urls:
+ if b in img_url:
+ return False
+ return True
diff --git a/plugins/pix_gallery/model/__init__.py b/plugins/pix_gallery/model/__init__.py
old mode 100644
new mode 100755
index e3ad2b4b..f16c3e52
--- a/plugins/pix_gallery/model/__init__.py
+++ b/plugins/pix_gallery/model/__init__.py
@@ -1,3 +1,3 @@
-from .pixiv_keyword_user import *
-from .omega_pixiv_illusts import *
-from .pixiv import *
+from .pixiv_keyword_user import *
+from .omega_pixiv_illusts import *
+from .pixiv import *
diff --git a/plugins/pix_gallery/model/omega_pixiv_illusts.py b/plugins/pix_gallery/model/omega_pixiv_illusts.py
old mode 100644
new mode 100755
index cd213853..b9df7fce
--- a/plugins/pix_gallery/model/omega_pixiv_illusts.py
+++ b/plugins/pix_gallery/model/omega_pixiv_illusts.py
@@ -1,141 +1,141 @@
-from typing import Optional, List
-from datetime import datetime
-from services.db_context import db
-
-
-class OmegaPixivIllusts(db.Model):
- __tablename__ = "omega_pixiv_illusts"
- __table_args__ = {'extend_existing': True}
-
- id = db.Column(db.Integer(), primary_key=True)
- pid = db.Column(db.BigInteger(), nullable=False)
- uid = db.Column(db.BigInteger(), nullable=False)
- title = db.Column(db.String(), nullable=False)
- uname = db.Column(db.String(), nullable=False)
- nsfw_tag = db.Column(db.Integer(), nullable=False)
- width = db.Column(db.Integer(), nullable=False)
- height = db.Column(db.Integer(), nullable=False)
- tags = db.Column(db.String(), nullable=False)
- url = db.Column(db.String(), nullable=False)
- created_at = db.Column(db.DateTime(timezone=True))
- updated_at = db.Column(db.DateTime(timezone=True))
-
- _idx1 = db.Index("omega_pixiv_illusts_idx1", "pid", "url", unique=True)
-
- @classmethod
- async def add_image_data(
- cls,
- pid: int,
- title: str,
- width: int,
- height: int,
- url: str,
- uid: int,
- uname: str,
- nsfw_tag: int,
- tags: str,
- created_at: datetime,
- updated_at: datetime,
- ):
- """
- 说明:
- 添加图片信息
- 参数:
- :param pid: pid
- :param title: 标题
- :param width: 宽度
- :param height: 长度
- :param url: url链接
- :param uid: 作者uid
- :param uname: 作者名称
- :param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
- :param tags: 相关tag
- :param created_at: 创建日期
- :param updated_at: 更新日期
- """
- if not await cls.check_exists(pid):
- await cls.create(
- pid=pid,
- title=title,
- width=width,
- height=height,
- url=url,
- uid=uid,
- uname=uname,
- nsfw_tag=nsfw_tag,
- tags=tags,
- )
- return True
- return False
-
- @classmethod
- async def query_images(
- cls,
- keywords: Optional[List[str]] = None,
- uid: Optional[int] = None,
- pid: Optional[int] = None,
- nsfw_tag: Optional[int] = 0,
- num: int = 100
- ) -> List[Optional["OmegaPixivIllusts"]]:
- """
- 说明:
- 查找符合条件的图片
- 参数:
- :param keywords: 关键词
- :param uid: 画师uid
- :param pid: 图片pid
- :param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
- :param num: 获取图片数量
- """
- if nsfw_tag is not None:
- query = cls.query.where(cls.nsfw_tag == nsfw_tag)
- else:
- query = cls.query
- if keywords:
- for keyword in keywords:
- query = query.where(cls.tags.contains(keyword))
- elif uid:
- query = query.where(cls.uid == uid)
- elif pid:
- query = query.where(cls.uid == pid)
- query = query.order_by(db.func.random()).limit(num)
- return await query.gino.all()
-
- @classmethod
- async def check_exists(cls, pid: int) -> bool:
- """
- 说明:
- 检测pid是否已存在
- 参数:
- :param pid: 图片PID
- """
- query = await cls.query.where(cls.pid == pid).gino.all()
- return bool(query)
-
- @classmethod
- async def get_keyword_num(cls, tags: List[str] = None) -> "int, int, int":
- """
- 说明:
- 获取相关关键词(keyword, tag)在图库中的数量
- 参数:
- :param tags: 关键词/Tag
- """
- setattr(OmegaPixivIllusts, 'count', db.func.count(cls.pid).label('count'))
- query = cls.select('count')
- if tags:
- for tag in tags:
- query = query.where(cls.tags.contains(tag))
- count = await query.where(cls.nsfw_tag == 0).gino.first()
- setu_count = await query.where(cls.nsfw_tag == 1).gino.first()
- r18_count = await query.where(cls.nsfw_tag == 2).gino.first()
- return count[0], setu_count[0], r18_count[0]
-
- @classmethod
- async def get_all_pid(cls) -> List[int]:
- """
- 说明:
- 获取所有图片PID
- """
- data = await cls.select('pid').gino.all()
- return [x[0] for x in data]
-
+from typing import Optional, List
+from datetime import datetime
+from services.db_context import db
+
+
+class OmegaPixivIllusts(db.Model):
+ __tablename__ = "omega_pixiv_illusts"
+ __table_args__ = {'extend_existing': True}
+
+ id = db.Column(db.Integer(), primary_key=True)
+ pid = db.Column(db.BigInteger(), nullable=False)
+ uid = db.Column(db.BigInteger(), nullable=False)
+ title = db.Column(db.String(), nullable=False)
+ uname = db.Column(db.String(), nullable=False)
+ nsfw_tag = db.Column(db.Integer(), nullable=False)
+ width = db.Column(db.Integer(), nullable=False)
+ height = db.Column(db.Integer(), nullable=False)
+ tags = db.Column(db.String(), nullable=False)
+ url = db.Column(db.String(), nullable=False)
+ created_at = db.Column(db.DateTime(timezone=True))
+ updated_at = db.Column(db.DateTime(timezone=True))
+
+ _idx1 = db.Index("omega_pixiv_illusts_idx1", "pid", "url", unique=True)
+
+ @classmethod
+ async def add_image_data(
+ cls,
+ pid: int,
+ title: str,
+ width: int,
+ height: int,
+ url: str,
+ uid: int,
+ uname: str,
+ nsfw_tag: int,
+ tags: str,
+ created_at: datetime,
+ updated_at: datetime,
+ ):
+ """
+ 说明:
+ 添加图片信息
+ 参数:
+ :param pid: pid
+ :param title: 标题
+ :param width: 宽度
+ :param height: 长度
+ :param url: url链接
+ :param uid: 作者uid
+ :param uname: 作者名称
+ :param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
+ :param tags: 相关tag
+ :param created_at: 创建日期
+ :param updated_at: 更新日期
+ """
+ if not await cls.check_exists(pid):
+ await cls.create(
+ pid=pid,
+ title=title,
+ width=width,
+ height=height,
+ url=url,
+ uid=uid,
+ uname=uname,
+ nsfw_tag=nsfw_tag,
+ tags=tags,
+ )
+ return True
+ return False
+
+ @classmethod
+ async def query_images(
+ cls,
+ keywords: Optional[List[str]] = None,
+ uid: Optional[int] = None,
+ pid: Optional[int] = None,
+ nsfw_tag: Optional[int] = 0,
+ num: int = 100
+ ) -> List[Optional["OmegaPixivIllusts"]]:
+ """
+ 说明:
+ 查找符合条件的图片
+ 参数:
+ :param keywords: 关键词
+ :param uid: 画师uid
+ :param pid: 图片pid
+ :param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
+ :param num: 获取图片数量
+ """
+ if nsfw_tag is not None:
+ query = cls.query.where(cls.nsfw_tag == nsfw_tag)
+ else:
+ query = cls.query
+ if keywords:
+ for keyword in keywords:
+ query = query.where(cls.tags.contains(keyword))
+ elif uid:
+ query = query.where(cls.uid == uid)
+ elif pid:
+ query = query.where(cls.uid == pid)
+ query = query.order_by(db.func.random()).limit(num)
+ return await query.gino.all()
+
+ @classmethod
+ async def check_exists(cls, pid: int) -> bool:
+ """
+ 说明:
+ 检测pid是否已存在
+ 参数:
+ :param pid: 图片PID
+ """
+ query = await cls.query.where(cls.pid == pid).gino.all()
+ return bool(query)
+
+ @classmethod
+ async def get_keyword_num(cls, tags: List[str] = None) -> "int, int, int":
+ """
+ 说明:
+ 获取相关关键词(keyword, tag)在图库中的数量
+ 参数:
+ :param tags: 关键词/Tag
+ """
+ setattr(OmegaPixivIllusts, 'count', db.func.count(cls.pid).label('count'))
+ query = cls.select('count')
+ if tags:
+ for tag in tags:
+ query = query.where(cls.tags.contains(tag))
+ count = await query.where(cls.nsfw_tag == 0).gino.first()
+ setu_count = await query.where(cls.nsfw_tag == 1).gino.first()
+ r18_count = await query.where(cls.nsfw_tag == 2).gino.first()
+ return count[0], setu_count[0], r18_count[0]
+
+ @classmethod
+ async def get_all_pid(cls) -> List[int]:
+ """
+ 说明:
+ 获取所有图片PID
+ """
+ data = await cls.select('pid').gino.all()
+ return [x[0] for x in data]
+
diff --git a/plugins/pix_gallery/model/pixiv.py b/plugins/pix_gallery/model/pixiv.py
old mode 100644
new mode 100755
index 15275d3e..e43b9c35
--- a/plugins/pix_gallery/model/pixiv.py
+++ b/plugins/pix_gallery/model/pixiv.py
@@ -1,170 +1,170 @@
-from typing import Optional, List
-from services.db_context import db
-
-
-class Pixiv(db.Model):
- __tablename__ = "pixiv"
- __table_args__ = {'extend_existing': True}
-
- id = db.Column(db.Integer(), primary_key=True)
- pid = db.Column(db.BigInteger(), nullable=False)
- title = db.Column(db.String(), nullable=False)
- width = db.Column(db.Integer(), nullable=False)
- height = db.Column(db.Integer(), nullable=False)
- view = db.Column(db.Integer(), nullable=False)
- bookmarks = db.Column(db.Integer(), nullable=False)
- img_url = db.Column(db.String(), nullable=False)
- img_p = db.Column(db.String(), nullable=False)
- uid = db.Column(db.BigInteger(), nullable=False)
- author = db.Column(db.String(), nullable=False)
- is_r18 = db.Column(db.Boolean(), nullable=False)
- tags = db.Column(db.String(), nullable=False)
-
- _idx1 = db.Index("pixiv_idx1", "pid", "img_url", unique=True)
-
- @classmethod
- async def add_image_data(
- cls,
- pid: int,
- title: str,
- width: int,
- height: int,
- view: int,
- bookmarks: int,
- img_url: str,
- img_p: str,
- uid: int,
- author: str,
- tags: str,
- ):
- """
- 说明:
- 添加图片信息
- 参数:
- :param pid: pid
- :param title: 标题
- :param width: 宽度
- :param height: 长度
- :param view: 被查看次数
- :param bookmarks: 收藏数
- :param img_url: url链接
- :param img_p: 张数
- :param uid: 作者uid
- :param author: 作者名称
- :param tags: 相关tag
- """
- if not await cls.check_exists(pid, img_p):
- await cls.create(
- pid=pid,
- title=title,
- width=width,
- height=height,
- view=view,
- bookmarks=bookmarks,
- img_url=img_url,
- img_p=img_p,
- uid=uid,
- author=author,
- is_r18=True if "R-18" in tags else False,
- tags=tags,
- )
- return True
- return False
-
- @classmethod
- async def remove_image_data(cls, pid: int, img_p: str) -> bool:
- """
- 说明:
- 删除图片数据
- 参数:
- :param pid: 图片pid
- :param img_p: 图片pid的张数,如:p0,p1
- """
- try:
- if img_p:
- await cls.delete.where(
- (cls.pid == pid) & (cls.img_p == img_p)
- ).gino.status()
- else:
- await cls.delete.where(cls.pid == pid).gino.status()
- return True
- except Exception:
- return False
-
- @classmethod
- async def get_all_pid(cls) -> List[int]:
- """
- 说明:
- 获取所有PID
- """
- query = await cls.query.select("pid").gino.first()
- pid = [x[0] for x in query]
- return list(set(pid))
-
- # 0:非r18 1:r18 2:混合
- @classmethod
- async def query_images(
- cls,
- keywords: Optional[List[str]] = None,
- uid: Optional[int] = None,
- pid: Optional[int] = None,
- r18: Optional[int] = 0,
- num: int = 100
- ) -> List[Optional["Pixiv"]]:
- """
- 说明:
- 查找符合条件的图片
- 参数:
- :param keywords: 关键词
- :param uid: 画师uid
- :param pid: 图片pid
- :param r18: 是否r18,0:非r18 1:r18 2:混合
- :param num: 查找图片的数量
- """
- if r18 == 0:
- query = cls.query.where(cls.is_r18 == False)
- elif r18 == 1:
- query = cls.query.where(cls.is_r18 == True)
- else:
- query = cls.query
- if keywords:
- for keyword in keywords:
- query = query.where(cls.tags.contains(keyword))
- elif uid:
- query = query.where(cls.uid == uid)
- elif pid:
- query = query.where(cls.pid == pid)
- query = query.order_by(db.func.random()).limit(num)
- return await query.gino.all()
-
- @classmethod
- async def check_exists(cls, pid: int, img_p: str) -> bool:
- """
- 说明:
- 检测pid是否已存在
- 参数:
- :param pid: 图片PID
- :param img_p: 张数
- """
- query = await cls.query.where(
- (cls.pid == pid) & (cls.img_p == img_p)
- ).gino.all()
- return bool(query)
-
- @classmethod
- async def get_keyword_num(cls, tags: List[str] = None) -> "int, int":
- """
- 说明:
- 获取相关关键词(keyword, tag)在图库中的数量
- 参数:
- :param tags: 关键词/Tag
- """
- setattr(Pixiv, 'count', db.func.count(cls.pid).label('count'))
- query = cls.select('count')
- if tags:
- for tag in tags:
- query = query.where(cls.tags.contains(tag))
- count = await query.where(cls.is_r18 == False).gino.first()
- r18_count = await query.where(cls.is_r18 == True).gino.first()
- return count[0], r18_count[0]
-
+from typing import Optional, List
+from services.db_context import db
+
+
+class Pixiv(db.Model):
+ __tablename__ = "pixiv"
+ __table_args__ = {'extend_existing': True}
+
+ id = db.Column(db.Integer(), primary_key=True)
+ pid = db.Column(db.BigInteger(), nullable=False)
+ title = db.Column(db.String(), nullable=False)
+ width = db.Column(db.Integer(), nullable=False)
+ height = db.Column(db.Integer(), nullable=False)
+ view = db.Column(db.Integer(), nullable=False)
+ bookmarks = db.Column(db.Integer(), nullable=False)
+ img_url = db.Column(db.String(), nullable=False)
+ img_p = db.Column(db.String(), nullable=False)
+ uid = db.Column(db.BigInteger(), nullable=False)
+ author = db.Column(db.String(), nullable=False)
+ is_r18 = db.Column(db.Boolean(), nullable=False)
+ tags = db.Column(db.String(), nullable=False)
+
+ _idx1 = db.Index("pixiv_idx1", "pid", "img_url", unique=True)
+
+ @classmethod
+ async def add_image_data(
+ cls,
+ pid: int,
+ title: str,
+ width: int,
+ height: int,
+ view: int,
+ bookmarks: int,
+ img_url: str,
+ img_p: str,
+ uid: int,
+ author: str,
+ tags: str,
+ ):
+ """
+ 说明:
+ 添加图片信息
+ 参数:
+ :param pid: pid
+ :param title: 标题
+ :param width: 宽度
+ :param height: 长度
+ :param view: 被查看次数
+ :param bookmarks: 收藏数
+ :param img_url: url链接
+ :param img_p: 张数
+ :param uid: 作者uid
+ :param author: 作者名称
+ :param tags: 相关tag
+ """
+ if not await cls.check_exists(pid, img_p):
+ await cls.create(
+ pid=pid,
+ title=title,
+ width=width,
+ height=height,
+ view=view,
+ bookmarks=bookmarks,
+ img_url=img_url,
+ img_p=img_p,
+ uid=uid,
+ author=author,
+ is_r18=True if "R-18" in tags else False,
+ tags=tags,
+ )
+ return True
+ return False
+
+ @classmethod
+ async def remove_image_data(cls, pid: int, img_p: str) -> bool:
+ """
+ 说明:
+ 删除图片数据
+ 参数:
+ :param pid: 图片pid
+ :param img_p: 图片pid的张数,如:p0,p1
+ """
+ try:
+ if img_p:
+ await cls.delete.where(
+ (cls.pid == pid) & (cls.img_p == img_p)
+ ).gino.status()
+ else:
+ await cls.delete.where(cls.pid == pid).gino.status()
+ return True
+ except Exception:
+ return False
+
+ @classmethod
+ async def get_all_pid(cls) -> List[int]:
+ """
+ 说明:
+ 获取所有PID
+ """
+ query = await cls.query.select("pid").gino.first()
+ pid = [x[0] for x in query]
+ return list(set(pid))
+
+ # 0:非r18 1:r18 2:混合
+ @classmethod
+ async def query_images(
+ cls,
+ keywords: Optional[List[str]] = None,
+ uid: Optional[int] = None,
+ pid: Optional[int] = None,
+ r18: Optional[int] = 0,
+ num: int = 100
+ ) -> List[Optional["Pixiv"]]:
+ """
+ 说明:
+ 查找符合条件的图片
+ 参数:
+ :param keywords: 关键词
+ :param uid: 画师uid
+ :param pid: 图片pid
+ :param r18: 是否r18,0:非r18 1:r18 2:混合
+ :param num: 查找图片的数量
+ """
+ if r18 == 0:
+ query = cls.query.where(cls.is_r18 == False)
+ elif r18 == 1:
+ query = cls.query.where(cls.is_r18 == True)
+ else:
+ query = cls.query
+ if keywords:
+ for keyword in keywords:
+ query = query.where(cls.tags.contains(keyword))
+ elif uid:
+ query = query.where(cls.uid == uid)
+ elif pid:
+ query = query.where(cls.pid == pid)
+ query = query.order_by(db.func.random()).limit(num)
+ return await query.gino.all()
+
+ @classmethod
+ async def check_exists(cls, pid: int, img_p: str) -> bool:
+ """
+ 说明:
+ 检测pid是否已存在
+ 参数:
+ :param pid: 图片PID
+ :param img_p: 张数
+ """
+ query = await cls.query.where(
+ (cls.pid == pid) & (cls.img_p == img_p)
+ ).gino.all()
+ return bool(query)
+
+ @classmethod
+ async def get_keyword_num(cls, tags: List[str] = None) -> "int, int":
+ """
+ 说明:
+ 获取相关关键词(keyword, tag)在图库中的数量
+ 参数:
+ :param tags: 关键词/Tag
+ """
+ setattr(Pixiv, 'count', db.func.count(cls.pid).label('count'))
+ query = cls.select('count')
+ if tags:
+ for tag in tags:
+ query = query.where(cls.tags.contains(tag))
+ count = await query.where(cls.is_r18 == False).gino.first()
+ r18_count = await query.where(cls.is_r18 == True).gino.first()
+ return count[0], r18_count[0]
+
diff --git a/plugins/pix_gallery/model/pixiv_keyword_user.py b/plugins/pix_gallery/model/pixiv_keyword_user.py
old mode 100644
new mode 100755
index f8774e6d..10d33301
--- a/plugins/pix_gallery/model/pixiv_keyword_user.py
+++ b/plugins/pix_gallery/model/pixiv_keyword_user.py
@@ -1,127 +1,127 @@
-from services.db_context import db
-from typing import Set, List
-
-
-class PixivKeywordUser(db.Model):
- __tablename__ = "pixiv_keyword_users"
- __table_args__ = {'extend_existing': True}
-
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- keyword = db.Column(db.String(), nullable=False)
- is_pass = db.Column(db.Boolean(), default=False)
-
- _idx1 = db.Index("pixiv_keyword_users_idx1", "keyword", unique=True)
-
- @classmethod
- async def add_keyword(
- cls, user_qq: int, group_id: int, keyword: str, superusers: Set[str]
- ) -> bool:
- """
- 说明:
- 添加搜图的关键词
- 参数:
- :param user_qq: qq号
- :param group_id: 群号
- :param keyword: 关键词
- :param superusers: 是否为超级用户
- """
- is_pass = True if str(user_qq) in superusers else False
- if not await cls._check_keyword_exists(keyword):
- await cls.create(
- user_qq=user_qq, group_id=group_id, keyword=keyword, is_pass=is_pass
- )
- return True
- return False
-
- @classmethod
- async def delete_keyword(cls, keyword: str) -> bool:
- """
- 说明:
- 删除关键词
- 参数:
- :param keyword: 关键词
- """
- if await cls._check_keyword_exists(keyword):
- query = cls.query.where(cls.keyword == keyword).with_for_update()
- query = await query.gino.first()
- await query.delete()
- return True
- return False
-
- @classmethod
- async def set_keyword_pass(cls, keyword: str, is_pass: bool) -> "int, int":
- """
- 说明:
- 通过或禁用关键词
- 参数:
- :param keyword: 关键词
- :param is_pass: 通过状态
- """
- if await cls._check_keyword_exists(keyword):
- query = cls.query.where(cls.keyword == keyword).with_for_update()
- query = await query.gino.first()
- await query.update(
- is_pass=is_pass,
- ).apply()
- return query.user_qq, query.group_id
- return 0, 0
-
- @classmethod
- async def get_all_user_dict(cls) -> dict:
- """
- 说明:
- 获取关键词数据库各个用户贡献的关键词字典
- """
- tmp = {}
- query = await cls.query.gino.all()
- for user in query:
- if not tmp.get(user.user_qq):
- tmp[user.user_qq] = {"keyword": []}
- tmp[user.user_qq]["keyword"].append(user.keyword)
- return tmp
-
- @classmethod
- async def get_current_keyword(cls) -> "List[str], List[str]":
- """
- 说明:
- 获取当前通过与未通过的关键词
- """
- pass_keyword = []
- not_pass_keyword = []
- query = await cls.query.gino.all()
- for user in query:
- if user.is_pass:
- pass_keyword.append(user.keyword)
- else:
- not_pass_keyword.append(user.keyword)
- return pass_keyword, not_pass_keyword
-
- @classmethod
- async def get_black_pid(cls) -> List[str]:
- """
- 说明:
- 获取黑名单PID
- """
- black_pid = []
- query = await cls.query.where(cls.user_qq == 114514).gino.all()
- for image in query:
- black_pid.append(image.keyword[6:])
- return black_pid
-
- @classmethod
- async def _check_keyword_exists(cls, keyword: str) -> bool:
- """
- 说明:
- 检测关键词是否已存在
- 参数:
- :param keyword: 关键词
- """
- current_keyword = []
- query = await cls.query.gino.all()
- for user in query:
- current_keyword.append(user.keyword)
- if keyword in current_keyword:
- return True
- return False
+from services.db_context import db
+from typing import Set, List
+
+
+class PixivKeywordUser(db.Model):
+ __tablename__ = "pixiv_keyword_users"
+ __table_args__ = {'extend_existing': True}
+
+ id = db.Column(db.Integer(), primary_key=True)
+ user_qq = db.Column(db.BigInteger(), nullable=False)
+ group_id = db.Column(db.BigInteger(), nullable=False)
+ keyword = db.Column(db.String(), nullable=False)
+ is_pass = db.Column(db.Boolean(), default=False)
+
+ _idx1 = db.Index("pixiv_keyword_users_idx1", "keyword", unique=True)
+
+ @classmethod
+ async def add_keyword(
+ cls, user_qq: int, group_id: int, keyword: str, superusers: Set[str]
+ ) -> bool:
+ """
+ 说明:
+ 添加搜图的关键词
+ 参数:
+ :param user_qq: qq号
+ :param group_id: 群号
+ :param keyword: 关键词
+ :param superusers: 是否为超级用户
+ """
+ is_pass = True if str(user_qq) in superusers else False
+ if not await cls._check_keyword_exists(keyword):
+ await cls.create(
+ user_qq=user_qq, group_id=group_id, keyword=keyword, is_pass=is_pass
+ )
+ return True
+ return False
+
+ @classmethod
+ async def delete_keyword(cls, keyword: str) -> bool:
+ """
+ 说明:
+ 删除关键词
+ 参数:
+ :param keyword: 关键词
+ """
+ if await cls._check_keyword_exists(keyword):
+ query = cls.query.where(cls.keyword == keyword).with_for_update()
+ query = await query.gino.first()
+ await query.delete()
+ return True
+ return False
+
+ @classmethod
+ async def set_keyword_pass(cls, keyword: str, is_pass: bool) -> "int, int":
+ """
+ 说明:
+ 通过或禁用关键词
+ 参数:
+ :param keyword: 关键词
+ :param is_pass: 通过状态
+ """
+ if await cls._check_keyword_exists(keyword):
+ query = cls.query.where(cls.keyword == keyword).with_for_update()
+ query = await query.gino.first()
+ await query.update(
+ is_pass=is_pass,
+ ).apply()
+ return query.user_qq, query.group_id
+ return 0, 0
+
+ @classmethod
+ async def get_all_user_dict(cls) -> dict:
+ """
+ 说明:
+ 获取关键词数据库各个用户贡献的关键词字典
+ """
+ tmp = {}
+ query = await cls.query.gino.all()
+ for user in query:
+ if not tmp.get(user.user_qq):
+ tmp[user.user_qq] = {"keyword": []}
+ tmp[user.user_qq]["keyword"].append(user.keyword)
+ return tmp
+
+ @classmethod
+ async def get_current_keyword(cls) -> "List[str], List[str]":
+ """
+ 说明:
+ 获取当前通过与未通过的关键词
+ """
+ pass_keyword = []
+ not_pass_keyword = []
+ query = await cls.query.gino.all()
+ for user in query:
+ if user.is_pass:
+ pass_keyword.append(user.keyword)
+ else:
+ not_pass_keyword.append(user.keyword)
+ return pass_keyword, not_pass_keyword
+
+ @classmethod
+ async def get_black_pid(cls) -> List[str]:
+ """
+ 说明:
+ 获取黑名单PID
+ """
+ black_pid = []
+ query = await cls.query.where(cls.user_qq == 114514).gino.all()
+ for image in query:
+ black_pid.append(image.keyword[6:])
+ return black_pid
+
+ @classmethod
+ async def _check_keyword_exists(cls, keyword: str) -> bool:
+ """
+ 说明:
+ 检测关键词是否已存在
+ 参数:
+ :param keyword: 关键词
+ """
+ current_keyword = []
+ query = await cls.query.gino.all()
+ for user in query:
+ current_keyword.append(user.keyword)
+ if keyword in current_keyword:
+ return True
+ return False
diff --git a/plugins/pix_gallery/pix.py b/plugins/pix_gallery/pix.py
old mode 100644
new mode 100755
index 10c352c1..04c1bfc0
--- a/plugins/pix_gallery/pix.py
+++ b/plugins/pix_gallery/pix.py
@@ -1,165 +1,165 @@
-from nonebot.adapters.cqhttp.message import Message
-from utils.utils import get_message_text, is_number
-from configs.config import Config
-from .model.omega_pixiv_illusts import OmegaPixivIllusts
-from utils.message_builder import image
-from utils.manager import withdraw_message_manager
-from services.log import logger
-from nonebot.adapters.cqhttp import (
- Bot,
- MessageEvent,
- GroupMessageEvent,
-)
-from nonebot.typing import T_State
-from .data_source import get_image
-from .model.pixiv import Pixiv
-from nonebot import on_command
-import random
-
-
-__zx_plugin_name__ = "PIX"
-__plugin_usage__ = """
-usage:
- 查看 pix 好康图库
- 指令:
- pix ?*[tags]: 通过 tag 获取相似图片,不含tag时随机抽取
- pix pid[pid]: 查看图库中指定pid图片
-""".strip()
-__plugin_superuser_usage__ = """
-usage:
- 超级用户额外的 pix 指令
- 指令:
- pix -s ?*[tags]: 通过tag获取色图,不含tag时随机
- pix -r ?*[tags]: 通过tag获取r18图,不含tag时随机
-""".strip()
-__plugin_des__ = "这里是PIX图库!"
-__plugin_cmd__ = [
- "pix ?*[tags]",
- "pix pid [pid]",
- "pix -s ?*[tags] [_superuser]",
- "pix -r ?*[tags] [_superuser]",
-]
-__plugin_type__ = ("来点好康的",)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["pix", "Pix", "PIX", "pIx"],
-}
-__plugin_block_limit__ = {"rst": "您有PIX图片正在处理,请稍等..."}
-
-
-pix = on_command("pix", aliases={"PIX", "Pix"}, priority=5, block=True)
-
-
-PIX_RATIO = None
-OMEGA_RATIO = None
-
-
-@pix.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- global PIX_RATIO, OMEGA_RATIO
- if PIX_RATIO is None:
- pix_omega_pixiv_ratio = Config.get_config("pix", "PIX_OMEGA_PIXIV_RATIO")
- PIX_RATIO = pix_omega_pixiv_ratio[0] / (
- pix_omega_pixiv_ratio[0] + pix_omega_pixiv_ratio[1]
- )
- OMEGA_RATIO = 1 - PIX_RATIO
- num = 1
- keyword = get_message_text(event.json())
- x = keyword.split(" ")
- if "-s" in x:
- x.remove("-s")
- nsfw_tag = 1
- elif "-r" in x:
- x.remove("-r")
- nsfw_tag = 2
- else:
- nsfw_tag = 0
- if nsfw_tag != 0 and str(event.user_id) not in bot.config.superusers:
- await pix.finish("你不能看这些噢,这些都是是留给管理员看的...")
- if len(x) > 1:
- if is_number(x[-1]):
- num = int(x[-1])
- if num > 10:
- if str(event.user_id) not in bot.config.superusers or (
- str(event.user_id) in bot.config.superusers and num > 30
- ):
- num = random.randint(1, 10)
- await pix.send(f"太贪心了,就给你发 {num}张 好了")
- x = x[:-1]
- keyword = " ".join(x)
- pix_num = int(num * PIX_RATIO) + 15 if PIX_RATIO != 0 else 0
- omega_num = num - pix_num + 15
- if is_number(keyword):
- if num == 1:
- pix_num = 15
- omega_num = 15
- all_image = await Pixiv.query_images(
- uid=int(keyword), num=pix_num, r18=1 if nsfw_tag == 2 else 0
- ) + await OmegaPixivIllusts.query_images(
- uid=int(keyword), num=omega_num, nsfw_tag=nsfw_tag
- )
- elif keyword.lower().startswith("pid"):
- pid = keyword.replace("pid", "").replace(":", "").replace(":", "")
- if not is_number(pid):
- await pix.finish("PID必须是数字...", at_sender=True)
- all_image = await Pixiv.query_images(
- pid=int(pid), r18=1 if nsfw_tag == 2 else 0
- )
- if not all_image:
- all_image = await OmegaPixivIllusts.query_images(
- pid=int(pid), nsfw_tag=nsfw_tag
- )
- else:
- tmp = await Pixiv.query_images(
- x, r18=1 if nsfw_tag == 2 else 0, num=pix_num
- ) + await OmegaPixivIllusts.query_images(x, nsfw_tag=nsfw_tag, num=omega_num)
- tmp_ = []
- all_image = []
- for x in tmp:
- if x.pid not in tmp_:
- all_image.append(x)
- tmp_.append(x.pid)
- if not all_image:
- await pix.finish(f"未在图库中找到与 {keyword} 相关Tag/UID/PID的图片...", at_sender=True)
- for _ in range(num):
- img_url = None
- author = None
- if not all_image:
- await pix.finish("坏了...发完了,没图了...")
- img = random.choice(all_image)
- all_image.remove(img)
- if isinstance(img, OmegaPixivIllusts):
- img_url = img.url
- author = img.uname
- elif isinstance(img, Pixiv):
- img_url = img.img_url
- author = img.author
- pid = img.pid
- title = img.title
- uid = img.uid
- _img = await get_image(img_url, event.user_id)
- if _img:
- msg_id = await pix.send(
- Message(
- f"title:{title}\n"
- f"author:{author}\n"
- f"PID:{pid}\nUID:{uid}\n"
- f"{image(_img, 'temp')}"
- )
- )
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查看PIX图库PID: {pid}"
- )
- else:
- msg_id = await pix.send(f"下载图片似乎出了一点问题,PID:{pid}")
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查看PIX图库PID: {pid},下载图片出错"
- )
- withdraw_message_manager.withdraw_message(event, msg_id, Config.get_config("pix", "WITHDRAW_PIX_MESSAGE"))
-
+from nonebot.adapters.cqhttp.message import Message
+from utils.utils import get_message_text, is_number
+from configs.config import Config
+from .model.omega_pixiv_illusts import OmegaPixivIllusts
+from utils.message_builder import image
+from utils.manager import withdraw_message_manager
+from services.log import logger
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ GroupMessageEvent,
+)
+from nonebot.typing import T_State
+from .data_source import get_image
+from .model.pixiv import Pixiv
+from nonebot import on_command
+import random
+
+
+__zx_plugin_name__ = "PIX"
+__plugin_usage__ = """
+usage:
+ 查看 pix 好康图库
+ 指令:
+ pix ?*[tags]: 通过 tag 获取相似图片,不含tag时随机抽取
+ pix pid[pid]: 查看图库中指定pid图片
+""".strip()
+__plugin_superuser_usage__ = """
+usage:
+ 超级用户额外的 pix 指令
+ 指令:
+ pix -s ?*[tags]: 通过tag获取色图,不含tag时随机
+ pix -r ?*[tags]: 通过tag获取r18图,不含tag时随机
+""".strip()
+__plugin_des__ = "这里是PIX图库!"
+__plugin_cmd__ = [
+ "pix ?*[tags]",
+ "pix pid [pid]",
+ "pix -s ?*[tags] [_superuser]",
+ "pix -r ?*[tags] [_superuser]",
+]
+__plugin_type__ = ("来点好康的",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["pix", "Pix", "PIX", "pIx"],
+}
+__plugin_block_limit__ = {"rst": "您有PIX图片正在处理,请稍等..."}
+
+
+pix = on_command("pix", aliases={"PIX", "Pix"}, priority=5, block=True)
+
+
+PIX_RATIO = None
+OMEGA_RATIO = None
+
+
+@pix.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ global PIX_RATIO, OMEGA_RATIO
+ if PIX_RATIO is None:
+ pix_omega_pixiv_ratio = Config.get_config("pix", "PIX_OMEGA_PIXIV_RATIO")
+ PIX_RATIO = pix_omega_pixiv_ratio[0] / (
+ pix_omega_pixiv_ratio[0] + pix_omega_pixiv_ratio[1]
+ )
+ OMEGA_RATIO = 1 - PIX_RATIO
+ num = 1
+ keyword = get_message_text(event.json())
+ x = keyword.split(" ")
+ if "-s" in x:
+ x.remove("-s")
+ nsfw_tag = 1
+ elif "-r" in x:
+ x.remove("-r")
+ nsfw_tag = 2
+ else:
+ nsfw_tag = 0
+ if nsfw_tag != 0 and str(event.user_id) not in bot.config.superusers:
+ await pix.finish("你不能看这些噢,这些都是是留给管理员看的...")
+ if len(x) > 1:
+ if is_number(x[-1]):
+ num = int(x[-1])
+ if num > 10:
+ if str(event.user_id) not in bot.config.superusers or (
+ str(event.user_id) in bot.config.superusers and num > 30
+ ):
+ num = random.randint(1, 10)
+ await pix.send(f"太贪心了,就给你发 {num}张 好了")
+ x = x[:-1]
+ keyword = " ".join(x)
+ pix_num = int(num * PIX_RATIO) + 15 if PIX_RATIO != 0 else 0
+ omega_num = num - pix_num + 15
+ if is_number(keyword):
+ if num == 1:
+ pix_num = 15
+ omega_num = 15
+ all_image = await Pixiv.query_images(
+ uid=int(keyword), num=pix_num, r18=1 if nsfw_tag == 2 else 0
+ ) + await OmegaPixivIllusts.query_images(
+ uid=int(keyword), num=omega_num, nsfw_tag=nsfw_tag
+ )
+ elif keyword.lower().startswith("pid"):
+ pid = keyword.replace("pid", "").replace(":", "").replace(":", "")
+ if not is_number(pid):
+ await pix.finish("PID必须是数字...", at_sender=True)
+ all_image = await Pixiv.query_images(
+ pid=int(pid), r18=1 if nsfw_tag == 2 else 0
+ )
+ if not all_image:
+ all_image = await OmegaPixivIllusts.query_images(
+ pid=int(pid), nsfw_tag=nsfw_tag
+ )
+ else:
+ tmp = await Pixiv.query_images(
+ x, r18=1 if nsfw_tag == 2 else 0, num=pix_num
+ ) + await OmegaPixivIllusts.query_images(x, nsfw_tag=nsfw_tag, num=omega_num)
+ tmp_ = []
+ all_image = []
+ for x in tmp:
+ if x.pid not in tmp_:
+ all_image.append(x)
+ tmp_.append(x.pid)
+ if not all_image:
+ await pix.finish(f"未在图库中找到与 {keyword} 相关Tag/UID/PID的图片...", at_sender=True)
+ for _ in range(num):
+ img_url = None
+ author = None
+ if not all_image:
+ await pix.finish("坏了...发完了,没图了...")
+ img = random.choice(all_image)
+ all_image.remove(img)
+ if isinstance(img, OmegaPixivIllusts):
+ img_url = img.url
+ author = img.uname
+ elif isinstance(img, Pixiv):
+ img_url = img.img_url
+ author = img.author
+ pid = img.pid
+ title = img.title
+ uid = img.uid
+ _img = await get_image(img_url, event.user_id)
+ if _img:
+ msg_id = await pix.send(
+ Message(
+ f"title:{title}\n"
+ f"author:{author}\n"
+ f"PID:{pid}\nUID:{uid}\n"
+ f"{image(_img, 'temp')}"
+ )
+ )
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 查看PIX图库PID: {pid}"
+ )
+ else:
+ msg_id = await pix.send(f"下载图片似乎出了一点问题,PID:{pid}")
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 查看PIX图库PID: {pid},下载图片出错"
+ )
+ withdraw_message_manager.withdraw_message(event, msg_id, Config.get_config("pix", "WITHDRAW_PIX_MESSAGE"))
+
diff --git a/plugins/pix_gallery/pix_add_keyword.py b/plugins/pix_gallery/pix_add_keyword.py
old mode 100644
new mode 100755
index 6160be15..84b8b957
--- a/plugins/pix_gallery/pix_add_keyword.py
+++ b/plugins/pix_gallery/pix_add_keyword.py
@@ -1,120 +1,120 @@
-from nonebot import on_command
-from utils.utils import get_message_text, is_number
-from services.log import logger
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.typing import T_State
-from .data_source import uid_pid_exists
-from .model.pixiv_keyword_user import PixivKeywordUser
-from .model.pixiv import Pixiv
-from nonebot.permission import SUPERUSER
-
-__zx_plugin_name__ = "PIX关键词/UID/PID添加管理 [Superuser]"
-__plugin_usage__ = """
-usage:
- PIX关键词/UID/PID添加管理操作
- 指令:
- 添加pix关键词 [Tag]: 添加一个pix搜索收录Tag
- 添加pixuid [uid]: 添加一个pix搜索收录uid
- 添加pixpid [pid]: 添加一个pix收录pid
-""".strip()
-__plugin_des__ = "PIX关键词/UID/PID添加管理"
-__plugin_cmd__ = ["添加pix关键词 [Tag]", "添加pixuid [uid]", "添加pixpid [pid]"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-add_keyword = on_command("添加pix关键词", aliases={"添加pix关键字"}, priority=1, block=True)
-
-add_black_pid = on_command("添加pix黑名单", permission=SUPERUSER, priority=1, block=True)
-
-# 超级用户可以通过字符 -f 来强制收录不检查是否存在
-add_uid_pid = on_command(
- "添加pixuid",
- aliases={
- "添加pixpid",
- },
- priority=1,
- block=True,
-)
-
-
-@add_keyword.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- group_id = -1
- if isinstance(event, GroupMessageEvent):
- group_id = event.group_id
- if msg:
- if await PixivKeywordUser.add_keyword(
- event.user_id, group_id, msg, bot.config.superusers
- ):
- await add_keyword.send(
- f"已成功添加pixiv搜图关键词:{msg},请等待管理员通过该关键词!", at_sender=True
- )
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 添加了pixiv搜图关键词:" + msg
- )
- else:
- await add_keyword.finish(f"该关键词 {msg} 已存在...")
- else:
- await add_keyword.finish(f"虚空关键词?.?.?.?")
-
-
-@add_uid_pid.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- exists_flag = True
- if msg.find("-f") != -1 and str(event.user_id) in bot.config.superusers:
- exists_flag = False
- msg = msg.replace("-f", "").strip()
- if msg:
- for msg in msg.split():
- if not is_number(msg):
- await add_uid_pid.finish("UID只能是数字的说...", at_sender=True)
- if state["_prefix"]["raw_command"].lower().endswith("uid"):
- msg = f"uid:{msg}"
- else:
- msg = f"pid:{msg}"
- if await Pixiv.check_exists(int(msg[4:]), "p0"):
- await add_uid_pid.finish(f"该PID:{msg[4:]}已存在...", at_sender=True)
- if not await uid_pid_exists(msg) and exists_flag:
- await add_uid_pid.finish("画师或作品不存在或搜索正在CD,请稍等...", at_sender=True)
- group_id = -1
- if isinstance(event, GroupMessageEvent):
- group_id = event.group_id
- if await PixivKeywordUser.add_keyword(
- event.user_id, group_id, msg, bot.config.superusers
- ):
- await add_uid_pid.send(
- f"已成功添加pixiv搜图UID/PID:{msg[4:]},请等待管理员通过!", at_sender=True
- )
- else:
- await add_uid_pid.finish(f"该UID/PID:{msg[4:]} 已存在...")
- else:
- await add_uid_pid.finish("湮灭吧!虚空的UID!")
-
-
-@add_black_pid.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- pid = get_message_text(event.json())
- img_p = ""
- if "p" in pid:
- img_p = pid.split("p")[-1]
- pid = pid.replace("_", "")
- pid = pid[: pid.find("p")]
- if not is_number(pid):
- await add_black_pid.finish("PID必须全部是数字!", at_sender=True)
- if await PixivKeywordUser.add_keyword(
- 114514,
- 114514,
- f"black:{pid}{f'_p{img_p}' if img_p else ''}",
- bot.config.superusers,
- ):
- await add_black_pid.send(f"已添加PID:{pid} 至黑名单中...")
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 添加了pixiv搜图黑名单 PID:{pid}"
- )
- else:
- await add_black_pid.send(f"PID:{pid} 已添加黑名单中,添加失败...")
+from nonebot import on_command
+from utils.utils import get_message_text, is_number
+from services.log import logger
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot.typing import T_State
+from .data_source import uid_pid_exists
+from .model.pixiv_keyword_user import PixivKeywordUser
+from .model.pixiv import Pixiv
+from nonebot.permission import SUPERUSER
+
+__zx_plugin_name__ = "PIX关键词/UID/PID添加管理 [Superuser]"
+__plugin_usage__ = """
+usage:
+ PIX关键词/UID/PID添加管理操作
+ 指令:
+ 添加pix关键词 [Tag]: 添加一个pix搜索收录Tag
+ 添加pixuid [uid]: 添加一个pix搜索收录uid
+ 添加pixpid [pid]: 添加一个pix收录pid
+""".strip()
+__plugin_des__ = "PIX关键词/UID/PID添加管理"
+__plugin_cmd__ = ["添加pix关键词 [Tag]", "添加pixuid [uid]", "添加pixpid [pid]"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+add_keyword = on_command("添加pix关键词", aliases={"添加pix关键字"}, priority=1, block=True)
+
+add_black_pid = on_command("添加pix黑名单", permission=SUPERUSER, priority=1, block=True)
+
+# 超级用户可以通过字符 -f 来强制收录不检查是否存在
+add_uid_pid = on_command(
+ "添加pixuid",
+ aliases={
+ "添加pixpid",
+ },
+ priority=1,
+ block=True,
+)
+
+
+@add_keyword.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ group_id = -1
+ if isinstance(event, GroupMessageEvent):
+ group_id = event.group_id
+ if msg:
+ if await PixivKeywordUser.add_keyword(
+ event.user_id, group_id, msg, bot.config.superusers
+ ):
+ await add_keyword.send(
+ f"已成功添加pixiv搜图关键词:{msg},请等待管理员通过该关键词!", at_sender=True
+ )
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 添加了pixiv搜图关键词:" + msg
+ )
+ else:
+ await add_keyword.finish(f"该关键词 {msg} 已存在...")
+ else:
+ await add_keyword.finish(f"虚空关键词?.?.?.?")
+
+
+@add_uid_pid.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ exists_flag = True
+ if msg.find("-f") != -1 and str(event.user_id) in bot.config.superusers:
+ exists_flag = False
+ msg = msg.replace("-f", "").strip()
+ if msg:
+ for msg in msg.split():
+ if not is_number(msg):
+ await add_uid_pid.finish("UID只能是数字的说...", at_sender=True)
+ if state["_prefix"]["raw_command"].lower().endswith("uid"):
+ msg = f"uid:{msg}"
+ else:
+ msg = f"pid:{msg}"
+ if await Pixiv.check_exists(int(msg[4:]), "p0"):
+ await add_uid_pid.finish(f"该PID:{msg[4:]}已存在...", at_sender=True)
+ if not await uid_pid_exists(msg) and exists_flag:
+ await add_uid_pid.finish("画师或作品不存在或搜索正在CD,请稍等...", at_sender=True)
+ group_id = -1
+ if isinstance(event, GroupMessageEvent):
+ group_id = event.group_id
+ if await PixivKeywordUser.add_keyword(
+ event.user_id, group_id, msg, bot.config.superusers
+ ):
+ await add_uid_pid.send(
+ f"已成功添加pixiv搜图UID/PID:{msg[4:]},请等待管理员通过!", at_sender=True
+ )
+ else:
+ await add_uid_pid.finish(f"该UID/PID:{msg[4:]} 已存在...")
+ else:
+ await add_uid_pid.finish("湮灭吧!虚空的UID!")
+
+
+@add_black_pid.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ pid = get_message_text(event.json())
+ img_p = ""
+ if "p" in pid:
+ img_p = pid.split("p")[-1]
+ pid = pid.replace("_", "")
+ pid = pid[: pid.find("p")]
+ if not is_number(pid):
+ await add_black_pid.finish("PID必须全部是数字!", at_sender=True)
+ if await PixivKeywordUser.add_keyword(
+ 114514,
+ 114514,
+ f"black:{pid}{f'_p{img_p}' if img_p else ''}",
+ bot.config.superusers,
+ ):
+ await add_black_pid.send(f"已添加PID:{pid} 至黑名单中...")
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 添加了pixiv搜图黑名单 PID:{pid}"
+ )
+ else:
+ await add_black_pid.send(f"PID:{pid} 已添加黑名单中,添加失败...")
diff --git a/plugins/pix_gallery/pix_pass_del_keyword.py b/plugins/pix_gallery/pix_pass_del_keyword.py
old mode 100644
new mode 100755
index 9bbbba1d..812d21a2
--- a/plugins/pix_gallery/pix_pass_del_keyword.py
+++ b/plugins/pix_gallery/pix_pass_del_keyword.py
@@ -1,182 +1,182 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp.message import Message
-from utils.utils import get_message_text, is_number
-from utils.message_builder import at
-from services.log import logger
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from .data_source import remove_image
-from .model.pixiv_keyword_user import PixivKeywordUser
-from .model.pixiv import Pixiv
-
-
-__zx_plugin_name__ = "PIX关键词/UID/PID删除管理 [Superuser]"
-__plugin_usage__ = """
-usage:
- PIX关键词/UID/PID删除管理操作
- 指令:
- 通过pix关键词 [关键词/pid/uid]
- 取消pix关键词 [关键词/pid/uid]
- 删除pix关键词 [关键词/pid/uid]
- 删除pix图片 *[pid]
- 示例:通过pix关键词萝莉
- 示例:通过pix关键词uid:123456
- 示例:通过pix关键词pid:123456
- 示例:删除pix图片4223442
-""".strip()
-__plugin_des__ = "PIX关键词/UID/PID删除管理"
-__plugin_cmd__ = [
- "通过pix关键词 [关键词/pid/uid]",
- "取消pix关键词 [关键词/pid/uid]",
- "删除pix关键词 [关键词/pid/uid]",
- "删除pix图片 *[pid]",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-pass_keyword = on_command(
- "通过pix关键词",
- aliases={"通过pix关键字", "取消pix关键词", "取消pix关键字"},
- permission=SUPERUSER,
- priority=1,
- block=True,
-)
-
-del_keyword = on_command(
- "删除pix关键词", aliases={"删除pix关键字"}, permission=SUPERUSER, priority=1, block=True
-)
-
-del_pic = on_command("删除pix图片", permission=SUPERUSER, priority=1, block=True)
-
-
-@del_keyword.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if not msg:
- await del_keyword.finish("好好输入要删除什么关键字啊笨蛋!")
- if is_number(msg):
- msg = f"uid:{msg}"
- if msg.lower().startswith("pid"):
- msg = "pid:" + msg.replace("pid", "").replace(":", "")
- if await PixivKeywordUser.delete_keyword(msg):
- await del_keyword.send(f"删除搜图关键词/UID:{msg} 成功...")
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 删除了pixiv搜图关键词:" + msg
- )
- else:
- await del_keyword.send(f"未查询到搜索关键词/UID/PID:{msg},删除失败!")
-
-
-@del_pic.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- pid_arr = get_message_text(event.json())
- if pid_arr:
- msg = ""
- black_pid = ""
- flag = False
- pid_arr = pid_arr.split()
- if pid_arr[-1] in ["-black", "-b"]:
- flag = True
- pid_arr = pid_arr[:-1]
- for pid in pid_arr:
- img_p = None
- if "p" in pid or "ugoira" in pid:
- if "p" in pid:
- img_p = pid.split("p")[-1]
- pid = pid.replace("_", "")
- pid = pid[: pid.find("p")]
- elif "ugoira" in pid:
- img_p = pid.split("ugoira")[-1]
- pid = pid.replace("_", "")
- pid = pid[: pid.find("ugoira")]
- if is_number(pid):
- if await Pixiv.query_images(pid=int(pid), r18=2):
- if await remove_image(int(pid), img_p):
- msg += f'{pid}{f"_p{img_p}" if img_p else ""},'
- if flag:
- if await PixivKeywordUser.add_keyword(
- 114514,
- 114514,
- f"black:{pid}{f'_p{img_p}' if img_p else ''}",
- bot.config.superusers,
- ):
- black_pid += f'{pid}{f"_p{img_p}" if img_p else ""},'
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 删除了PIX图片 PID:{pid}{f'_p{img_p}' if img_p else ''}"
- )
- else:
- await del_pic.send(
- f"PIX:删除pid:{pid}{f'_p{img_p}' if img_p else ''} 失败.."
- )
- else:
- await del_pic.send(
- f"PIX:图片pix:{pid}{f'_p{img_p}' if img_p else ''} 不存在...无法删除.."
- )
- else:
- await del_pic.send(f"PID必须为数字!pid:{pid}", at_sender=True)
- await del_pic.send(f"PIX:成功删除图片:{msg[:-1]}")
- if flag:
- await del_pic.send(f"成功图片PID加入黑名单:{black_pid[:-1]}")
- else:
- await del_pic.send("虚空删除?")
-
-
-@pass_keyword.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- tmp = {"group": {}, "private": {}}
- msg = get_message_text(event.json())
- if not msg:
- await pass_keyword.finish("通过虚空的关键词/UID?离谱...")
- msg = msg.split()
- flag = True if state["_prefix"]["raw_command"][:2] == "通过" else False
- for x in msg:
- if x.lower().startswith("uid"):
- x = x.replace("uid", "").replace(":", "")
- x = f"uid:{x}"
- elif x.lower().startswith("pid"):
- x = x.replace("pid", "").replace(":", "")
- x = f"pid:{x}"
- if x.lower().find("pid") != -1 or x.lower().find("uid") != -1:
- if not is_number(x[4:]):
- await pass_keyword.send(f"UID/PID:{x} 非全数字,跳过该关键词...")
- continue
- user_id, group_id = await PixivKeywordUser.set_keyword_pass(x, flag)
- if not user_id:
- await pass_keyword.send(f"未找到关键词/UID:{x},请检查关键词/UID是否存在...")
- continue
- if flag:
- if group_id == -1:
- if not tmp["private"].get(user_id):
- tmp["private"][user_id] = {"keyword": [x]}
- else:
- tmp["private"][user_id]["keyword"].append(x)
- else:
- if not tmp["group"].get(group_id):
- tmp["group"][group_id] = {}
- if not tmp["group"][group_id].get(user_id):
- tmp["group"][group_id][user_id] = {"keyword": [x]}
- else:
- tmp["group"][group_id][user_id]["keyword"].append(x)
- msg = " ".join(msg)
- await pass_keyword.send(f'已成功{state["_prefix"]["raw_command"][:2]}搜图关键词:{msg}....')
- for user in tmp["private"]:
- x = ",".join(tmp["private"][user]["keyword"])
- await bot.send_private_msg(
- user_id=user, message=f"你的关键词/UID/PID {x} 已被管理员通过,将在下一次进行更新..."
- )
- for group in tmp["group"]:
- for user in tmp["group"][group]:
- x = ",".join(tmp["group"][group][user]["keyword"])
- await bot.send_group_msg(
- group_id=group,
- message=Message(f"{at(user)}你的关键词/UID/PID {x} 已被管理员通过,将在下一次进行更新..."),
- )
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 通过了pixiv搜图关键词/UID:" + msg
- )
+from nonebot import on_command
+from nonebot.adapters.cqhttp.message import Message
+from utils.utils import get_message_text, is_number
+from utils.message_builder import at
+from services.log import logger
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from .data_source import remove_image
+from .model.pixiv_keyword_user import PixivKeywordUser
+from .model.pixiv import Pixiv
+
+
+__zx_plugin_name__ = "PIX关键词/UID/PID删除管理 [Superuser]"
+__plugin_usage__ = """
+usage:
+ PIX关键词/UID/PID删除管理操作
+ 指令:
+ 通过pix关键词 [关键词/pid/uid]
+ 取消pix关键词 [关键词/pid/uid]
+ 删除pix关键词 [关键词/pid/uid]
+ 删除pix图片 *[pid]
+ 示例:通过pix关键词萝莉
+ 示例:通过pix关键词uid:123456
+ 示例:通过pix关键词pid:123456
+ 示例:删除pix图片4223442
+""".strip()
+__plugin_des__ = "PIX关键词/UID/PID删除管理"
+__plugin_cmd__ = [
+ "通过pix关键词 [关键词/pid/uid]",
+ "取消pix关键词 [关键词/pid/uid]",
+ "删除pix关键词 [关键词/pid/uid]",
+ "删除pix图片 *[pid]",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+
+pass_keyword = on_command(
+ "通过pix关键词",
+ aliases={"通过pix关键字", "取消pix关键词", "取消pix关键字"},
+ permission=SUPERUSER,
+ priority=1,
+ block=True,
+)
+
+del_keyword = on_command(
+ "删除pix关键词", aliases={"删除pix关键字"}, permission=SUPERUSER, priority=1, block=True
+)
+
+del_pic = on_command("删除pix图片", permission=SUPERUSER, priority=1, block=True)
+
+
+@del_keyword.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if not msg:
+ await del_keyword.finish("好好输入要删除什么关键字啊笨蛋!")
+ if is_number(msg):
+ msg = f"uid:{msg}"
+ if msg.lower().startswith("pid"):
+ msg = "pid:" + msg.replace("pid", "").replace(":", "")
+ if await PixivKeywordUser.delete_keyword(msg):
+ await del_keyword.send(f"删除搜图关键词/UID:{msg} 成功...")
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 删除了pixiv搜图关键词:" + msg
+ )
+ else:
+ await del_keyword.send(f"未查询到搜索关键词/UID/PID:{msg},删除失败!")
+
+
+@del_pic.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ pid_arr = get_message_text(event.json())
+ if pid_arr:
+ msg = ""
+ black_pid = ""
+ flag = False
+ pid_arr = pid_arr.split()
+ if pid_arr[-1] in ["-black", "-b"]:
+ flag = True
+ pid_arr = pid_arr[:-1]
+ for pid in pid_arr:
+ img_p = None
+ if "p" in pid or "ugoira" in pid:
+ if "p" in pid:
+ img_p = pid.split("p")[-1]
+ pid = pid.replace("_", "")
+ pid = pid[: pid.find("p")]
+ elif "ugoira" in pid:
+ img_p = pid.split("ugoira")[-1]
+ pid = pid.replace("_", "")
+ pid = pid[: pid.find("ugoira")]
+ if is_number(pid):
+ if await Pixiv.query_images(pid=int(pid), r18=2):
+ if await remove_image(int(pid), img_p):
+ msg += f'{pid}{f"_p{img_p}" if img_p else ""},'
+ if flag:
+ if await PixivKeywordUser.add_keyword(
+ 114514,
+ 114514,
+ f"black:{pid}{f'_p{img_p}' if img_p else ''}",
+ bot.config.superusers,
+ ):
+ black_pid += f'{pid}{f"_p{img_p}" if img_p else ""},'
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 删除了PIX图片 PID:{pid}{f'_p{img_p}' if img_p else ''}"
+ )
+ else:
+ await del_pic.send(
+ f"PIX:删除pid:{pid}{f'_p{img_p}' if img_p else ''} 失败.."
+ )
+ else:
+ await del_pic.send(
+ f"PIX:图片pix:{pid}{f'_p{img_p}' if img_p else ''} 不存在...无法删除.."
+ )
+ else:
+ await del_pic.send(f"PID必须为数字!pid:{pid}", at_sender=True)
+ await del_pic.send(f"PIX:成功删除图片:{msg[:-1]}")
+ if flag:
+ await del_pic.send(f"成功图片PID加入黑名单:{black_pid[:-1]}")
+ else:
+ await del_pic.send("虚空删除?")
+
+
+@pass_keyword.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ tmp = {"group": {}, "private": {}}
+ msg = get_message_text(event.json())
+ if not msg:
+ await pass_keyword.finish("通过虚空的关键词/UID?离谱...")
+ msg = msg.split()
+ flag = True if state["_prefix"]["raw_command"][:2] == "通过" else False
+ for x in msg:
+ if x.lower().startswith("uid"):
+ x = x.replace("uid", "").replace(":", "")
+ x = f"uid:{x}"
+ elif x.lower().startswith("pid"):
+ x = x.replace("pid", "").replace(":", "")
+ x = f"pid:{x}"
+ if x.lower().find("pid") != -1 or x.lower().find("uid") != -1:
+ if not is_number(x[4:]):
+ await pass_keyword.send(f"UID/PID:{x} 非全数字,跳过该关键词...")
+ continue
+ user_id, group_id = await PixivKeywordUser.set_keyword_pass(x, flag)
+ if not user_id:
+ await pass_keyword.send(f"未找到关键词/UID:{x},请检查关键词/UID是否存在...")
+ continue
+ if flag:
+ if group_id == -1:
+ if not tmp["private"].get(user_id):
+ tmp["private"][user_id] = {"keyword": [x]}
+ else:
+ tmp["private"][user_id]["keyword"].append(x)
+ else:
+ if not tmp["group"].get(group_id):
+ tmp["group"][group_id] = {}
+ if not tmp["group"][group_id].get(user_id):
+ tmp["group"][group_id][user_id] = {"keyword": [x]}
+ else:
+ tmp["group"][group_id][user_id]["keyword"].append(x)
+ msg = " ".join(msg)
+ await pass_keyword.send(f'已成功{state["_prefix"]["raw_command"][:2]}搜图关键词:{msg}....')
+ for user in tmp["private"]:
+ x = ",".join(tmp["private"][user]["keyword"])
+ await bot.send_private_msg(
+ user_id=user, message=f"你的关键词/UID/PID {x} 已被管理员通过,将在下一次进行更新..."
+ )
+ for group in tmp["group"]:
+ for user in tmp["group"][group]:
+ x = ",".join(tmp["group"][group][user]["keyword"])
+ await bot.send_group_msg(
+ group_id=group,
+ message=Message(f"{at(user)}你的关键词/UID/PID {x} 已被管理员通过,将在下一次进行更新..."),
+ )
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 通过了pixiv搜图关键词/UID:" + msg
+ )
diff --git a/plugins/pix_gallery/pix_show_info.py b/plugins/pix_gallery/pix_show_info.py
old mode 100644
new mode 100755
index 5ed7eb9f..798e1ca2
--- a/plugins/pix_gallery/pix_show_info.py
+++ b/plugins/pix_gallery/pix_show_info.py
@@ -1,84 +1,84 @@
-from nonebot import on_command
-from utils.utils import get_message_text
-from utils.message_builder import image
-from nonebot.adapters.cqhttp import Bot, MessageEvent
-from nonebot.typing import T_State
-from .data_source import gen_keyword_pic, get_keyword_num
-from .model.pixiv_keyword_user import PixivKeywordUser
-import asyncio
-
-
-__zx_plugin_name__ = "查看pix图库"
-__plugin_usage__ = """
-usage:
- 查看pix图库
- 指令:
- 查看pix图库 ?[tags]: 查看指定tag图片数量,为空时查看整个图库
-""".strip()
-__plugin_des__ = "让我看看管理员私藏了多少货"
-__plugin_cmd__ = ["查看pix图库 ?[tags]"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["查看pix图库"],
-}
-
-
-my_keyword = on_command("我的pix关键词", aliases={"我的pix关键字"}, priority=1, block=True)
-
-show_keyword = on_command("显示pix关键词", aliases={"显示pix关键字"}, priority=1, block=True)
-
-show_pix = on_command("查看pix图库", priority=1, block=True)
-
-
-@my_keyword.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- data = await PixivKeywordUser.get_all_user_dict()
- if data.get(event.user_id) is None or not data[event.user_id]["keyword"]:
- await my_keyword.finish("您目前没有提供任何Pixiv搜图关键字...", at_sender=True)
- await my_keyword.send(
- f"您目前提供的如下关键字:\n\t" + ",".join(data[event.user_id]["keyword"])
- )
-
-
-@show_keyword.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- _pass_keyword, not_pass_keyword = await PixivKeywordUser.get_current_keyword()
- if _pass_keyword or not_pass_keyword:
- await show_keyword.send(
- image(
- b64=await asyncio.get_event_loop().run_in_executor(
- None,
- gen_keyword_pic,
- _pass_keyword,
- not_pass_keyword,
- str(event.user_id) in bot.config.superusers,
- )
- )
- )
- else:
- if str(event.user_id) in bot.config.superusers:
- await show_keyword.finish(f"目前没有已收录或待收录的搜索关键词...")
- else:
- await show_keyword.finish(f"目前没有已收录的搜索关键词...")
-
-
-@show_pix.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- keyword = get_message_text(event.json())
- count, r18_count, count_, setu_count, r18_count_ = await get_keyword_num(keyword)
- await show_pix.send(
- f"PIX图库:{keyword}\n"
- f"总数:{count + r18_count}\n"
- f"美图:{count}\n"
- f"R18:{r18_count}\n"
- f"---------------\n"
- f"Omega图库:{keyword}\n"
- f"总数:{count_ + setu_count + r18_count_}\n"
- f"美图:{count_}\n"
- f"色图:{setu_count}\n"
- f"R18:{r18_count_}"
- )
+from nonebot import on_command
+from utils.utils import get_message_text
+from utils.message_builder import image
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from nonebot.typing import T_State
+from .data_source import gen_keyword_pic, get_keyword_num
+from .model.pixiv_keyword_user import PixivKeywordUser
+import asyncio
+
+
+__zx_plugin_name__ = "查看pix图库"
+__plugin_usage__ = """
+usage:
+ 查看pix图库
+ 指令:
+ 查看pix图库 ?[tags]: 查看指定tag图片数量,为空时查看整个图库
+""".strip()
+__plugin_des__ = "让我看看管理员私藏了多少货"
+__plugin_cmd__ = ["查看pix图库 ?[tags]"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["查看pix图库"],
+}
+
+
+my_keyword = on_command("我的pix关键词", aliases={"我的pix关键字"}, priority=1, block=True)
+
+show_keyword = on_command("显示pix关键词", aliases={"显示pix关键字"}, priority=1, block=True)
+
+show_pix = on_command("查看pix图库", priority=1, block=True)
+
+
+@my_keyword.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ data = await PixivKeywordUser.get_all_user_dict()
+ if data.get(event.user_id) is None or not data[event.user_id]["keyword"]:
+ await my_keyword.finish("您目前没有提供任何Pixiv搜图关键字...", at_sender=True)
+ await my_keyword.send(
+ f"您目前提供的如下关键字:\n\t" + ",".join(data[event.user_id]["keyword"])
+ )
+
+
+@show_keyword.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ _pass_keyword, not_pass_keyword = await PixivKeywordUser.get_current_keyword()
+ if _pass_keyword or not_pass_keyword:
+ await show_keyword.send(
+ image(
+ b64=await asyncio.get_event_loop().run_in_executor(
+ None,
+ gen_keyword_pic,
+ _pass_keyword,
+ not_pass_keyword,
+ str(event.user_id) in bot.config.superusers,
+ )
+ )
+ )
+ else:
+ if str(event.user_id) in bot.config.superusers:
+ await show_keyword.finish(f"目前没有已收录或待收录的搜索关键词...")
+ else:
+ await show_keyword.finish(f"目前没有已收录的搜索关键词...")
+
+
+@show_pix.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ keyword = get_message_text(event.json())
+ count, r18_count, count_, setu_count, r18_count_ = await get_keyword_num(keyword)
+ await show_pix.send(
+ f"PIX图库:{keyword}\n"
+ f"总数:{count + r18_count}\n"
+ f"美图:{count}\n"
+ f"R18:{r18_count}\n"
+ f"---------------\n"
+ f"Omega图库:{keyword}\n"
+ f"总数:{count_ + setu_count + r18_count_}\n"
+ f"美图:{count_}\n"
+ f"色图:{setu_count}\n"
+ f"R18:{r18_count_}"
+ )
diff --git a/plugins/pix_gallery/pix_update.py b/plugins/pix_gallery/pix_update.py
old mode 100644
new mode 100755
index 162e03db..0b58b481
--- a/plugins/pix_gallery/pix_update.py
+++ b/plugins/pix_gallery/pix_update.py
@@ -1,208 +1,132 @@
-from nonebot import on_command
-from utils.utils import get_message_text, is_number
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from .data_source import start_update_image_url
-from .model import PixivKeywordUser, Pixiv, OmegaPixivIllusts
-from nonebot.adapters.cqhttp import Bot, MessageEvent
-from services.log import logger
-from typing import List
-from datetime import datetime
-from pathlib import Path
-import asyncio
-import time
-import os
-
-
-__zx_plugin_name__ = "pix检查更新 [Superuser]"
-__plugin_usage__ = """
-usage:
- 更新pix收录的所有或指定数量的 关键词/uid/pid
- 指令:
- 更新pix关键词 *[keyword/uid/pid] [num=max]: 更新仅keyword/uid/pid或全部
- pix检测更新:检测从未更新过的uid和pid
- 示例:更新pix关键词keyword
- 示例:更新pix关键词uid 10
-""".strip()
-__plugin_des__ = "pix图库收录数据检查更新"
-__plugin_cmd__ = ["更新pix关键词 *[keyword/uid/pid] [num=max]", "pix检测更新"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-start_update = on_command(
- "更新pix关键词", aliases={"更新pix关键字"}, permission=SUPERUSER, priority=1, block=True
-)
-
-check_omega = on_command(
- "检测omega图库", permission=SUPERUSER, priority=1, block=True
-)
-
-check_not_update_uid_pid = on_command(
- "pix检测更新",
- aliases={"pix检查更新"},
- permission=SUPERUSER,
- priority=1,
- block=True,
-)
-
-
-@start_update.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg_sp = get_message_text(event.json()).split()
- _pass_keyword, _ = await PixivKeywordUser.get_current_keyword()
- _pass_keyword.reverse()
- black_pid = await PixivKeywordUser.get_black_pid()
- _keyword = [
- x
- for x in _pass_keyword
- if not x.startswith("uid:")
- and not x.startswith("pid:")
- and not x.startswith("black:")
- ]
- _uid = [x for x in _pass_keyword if x.startswith("uid:")]
- _pid = [x for x in _pass_keyword if x.startswith("pid:")]
- num = 9999
- msg = msg_sp[0] if len(msg_sp) else ""
- if len(msg_sp) == 2:
- if is_number(msg_sp[1]):
- num = int(msg_sp[1])
- else:
- await start_update.finish("参数错误...第二参数必须为数字")
- if num < 10000:
- keyword_str = ",".join(
- _keyword[: num if num < len(_keyword) else len(_keyword)]
- )
- uid_str = ",".join(_uid[: num if num < len(_uid) else len(_uid)])
- pid_str = ",".join(_pid[: num if num < len(_pid) else len(_pid)])
- if msg.lower() == "pid":
- update_lst = _pid
- info = f"开始更新Pixiv搜图PID:\n{pid_str}"
- elif msg.lower() == "uid":
- update_lst = _uid
- info = f"开始更新Pixiv搜图UID:\n{uid_str}"
- elif msg.lower() == "keyword":
- update_lst = _keyword
- info = f"开始更新Pixiv搜图关键词:\n{keyword_str}"
- else:
- update_lst = _pass_keyword
- info = f"开始更新Pixiv搜图关键词:\n{keyword_str}\n更新UID:{uid_str}\n更新PID:{pid_str}"
- num = num if num < len(update_lst) else len(update_lst)
- else:
- if msg.lower() == "pid":
- update_lst = [f"pid:{num}"]
- info = f"开始更新Pixiv搜图UID:\npid:{num}"
- else:
- update_lst = [f"uid:{num}"]
- info = f"开始更新Pixiv搜图UID:\nuid:{num}"
- await start_update.send(info)
- start_time = time.time()
- pid_count, pic_count = await start_update_image_url(update_lst[:num], black_pid)
- await start_update.send(
- f"Pixiv搜图关键词搜图更新完成...\n"
- f"累计更新PID {pid_count} 个\n"
- f"累计更新图片 {pic_count} 张" + "\n耗时:{:.2f}秒".format((time.time() - start_time))
- )
-
-
-@check_not_update_uid_pid.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- flag = False
- if msg == "update":
- flag = True
- _pass_keyword, _ = await PixivKeywordUser.get_current_keyword()
- x_uid = []
- x_pid = []
- _uid = [int(x[4:]) for x in _pass_keyword if x.startswith("uid:")]
- _pid = [int(x[4:]) for x in _pass_keyword if x.startswith("pid:")]
- all_images = await Pixiv.query_images(r18=2)
- for img in all_images:
- if img.pid not in x_pid:
- x_pid.append(img.pid)
- if img.uid not in x_uid:
- x_uid.append(img.uid)
- await check_not_update_uid_pid.send(
- "从未更新过的UID:"
- + ",".join([f"uid:{x}" for x in _uid if x not in x_uid])
- + "\n"
- + "从未更新过的PID:"
- + ",".join([f"pid:{x}" for x in _pid if x not in x_pid])
- )
- if flag:
- await check_not_update_uid_pid.send("开始自动自动更新PID....")
- update_lst = [f"pid:{x}" for x in _uid if x not in x_uid]
- black_pid = await PixivKeywordUser.get_black_pid()
- start_time = time.time()
- pid_count, pic_count = await start_update_image_url(update_lst, black_pid)
- await check_not_update_uid_pid.send(
- f"Pixiv搜图关键词搜图更新完成...\n"
- f"累计更新PID {pid_count} 个\n"
- f"累计更新图片 {pic_count} 张" + "\n耗时:{:.2f}秒".format((time.time() - start_time))
- )
-
-
-@check_omega.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- async def _tasks(line: str, all_pid: List[int], length: int, index: int):
- data = line.split("VALUES", maxsplit=1)[-1].strip()
- if data.startswith("("):
- data = data[1:]
- if data.endswith(");"):
- data = data[:-2]
- x = data.split(maxsplit=3)
- pid = int(x[1][:-1].strip())
- if pid in all_pid:
- logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
- return
- uid = int(x[2][:-1].strip())
- x = x[3].split(", '")
- title = x[0].strip()[1:-1]
- tmp = x[1].split(", ")
- author = tmp[0].strip()[:-1]
- nsfw_tag = int(tmp[1])
- width = int(tmp[2])
- height = int(tmp[3])
- tags = x[2][:-1]
- url = x[3][:-1]
- if await OmegaPixivIllusts.add_image_data(
- pid,
- title,
- width,
- height,
- url,
- uid,
- author,
- nsfw_tag,
- tags,
- datetime.min,
- datetime.min,
- ):
- logger.info(
- f"成功添加OmegaPixivIllusts图库数据 pid:{pid} 本次预计存储 {length} 张,已更新第 {index} 张"
- )
- else:
- logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
- omega_pixiv_illusts = None
- for file in os.listdir("."):
- if "omega_pixiv_illusts" in file and ".sql" in file:
- omega_pixiv_illusts = Path() / file
- if omega_pixiv_illusts:
- with open(omega_pixiv_illusts, "r", encoding="utf8") as f:
- lines = f.readlines()
- tasks = []
- length = len([x for x in lines if "INSERT INTO" in x.upper()])
- all_pid = await OmegaPixivIllusts.get_all_pid()
- index = 0
- logger.info("检测到OmegaPixivIllusts数据库,准备开始更新....")
- for line in lines:
- if "INSERT INTO" in line.upper():
- index += 1
- tasks.append(
- asyncio.ensure_future(_tasks(line, all_pid, length, index))
- )
- await asyncio.gather(*tasks)
- omega_pixiv_illusts.unlink()
-
-
-
-
+from nonebot import on_command
+from utils.utils import get_message_text, is_number
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from .data_source import start_update_image_url
+from .model.pixiv_keyword_user import PixivKeywordUser
+from .model.pixiv import Pixiv
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+import time
+
+
+__zx_plugin_name__ = "pix检查更新 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 更新pix收录的所有或指定数量的 关键词/uid/pid
+ 指令:
+ 更新pix关键词 *[keyword/uid/pid] [num=max]: 更新仅keyword/uid/pid或全部
+ pix检测更新:检测从未更新过的uid和pid
+ 示例:更新pix关键词keyword
+ 示例:更新pix关键词uid 10
+""".strip()
+__plugin_des__ = "pix图库收录数据检查更新"
+__plugin_cmd__ = ["更新pix关键词 *[keyword/uid/pid] [num=max]", "pix检测更新"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+start_update = on_command(
+ "更新pix关键词", aliases={"更新pix关键字"}, permission=SUPERUSER, priority=1, block=True
+)
+
+check_not_update_uid_pid = on_command(
+ "pix检测更新",
+ aliases={"pix检查更新"},
+ permission=SUPERUSER,
+ priority=1,
+ block=True,
+)
+
+
+@start_update.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg_sp = get_message_text(event.json()).split()
+ _pass_keyword, _ = await PixivKeywordUser.get_current_keyword()
+ _pass_keyword.reverse()
+ black_pid = await PixivKeywordUser.get_black_pid()
+ _keyword = [
+ x
+ for x in _pass_keyword
+ if not x.startswith("uid:")
+ and not x.startswith("pid:")
+ and not x.startswith("black:")
+ ]
+ _uid = [x for x in _pass_keyword if x.startswith("uid:")]
+ _pid = [x for x in _pass_keyword if x.startswith("pid:")]
+ num = 9999
+ msg = msg_sp[0] if len(msg_sp) else ""
+ if len(msg_sp) == 2:
+ if is_number(msg_sp[1]):
+ num = int(msg_sp[1])
+ else:
+ await start_update.finish("参数错误...第二参数必须为数字")
+ if num < 10000:
+ keyword_str = ",".join(
+ _keyword[: num if num < len(_keyword) else len(_keyword)]
+ )
+ uid_str = ",".join(_uid[: num if num < len(_uid) else len(_uid)])
+ pid_str = ",".join(_pid[: num if num < len(_pid) else len(_pid)])
+ if msg.lower() == "pid":
+ update_lst = _pid
+ info = f"开始更新Pixiv搜图PID:\n{pid_str}"
+ elif msg.lower() == "uid":
+ update_lst = _uid
+ info = f"开始更新Pixiv搜图UID:\n{uid_str}"
+ elif msg.lower() == "keyword":
+ update_lst = _keyword
+ info = f"开始更新Pixiv搜图关键词:\n{keyword_str}"
+ else:
+ update_lst = _pass_keyword
+ info = f"开始更新Pixiv搜图关键词:\n{keyword_str}\n更新UID:{uid_str}\n更新PID:{pid_str}"
+ num = num if num < len(update_lst) else len(update_lst)
+ else:
+ if msg.lower() == "pid":
+ update_lst = [f"pid:{num}"]
+ info = f"开始更新Pixiv搜图UID:\npid:{num}"
+ else:
+ update_lst = [f"uid:{num}"]
+ info = f"开始更新Pixiv搜图UID:\nuid:{num}"
+ await start_update.send(info)
+ start_time = time.time()
+ pid_count, pic_count = await start_update_image_url(update_lst[:num], black_pid)
+ await start_update.send(
+ f"Pixiv搜图关键词搜图更新完成...\n"
+ f"累计更新PID {pid_count} 个\n"
+ f"累计更新图片 {pic_count} 张" + "\n耗时:{:.2f}秒".format((time.time() - start_time))
+ )
+
+
+@check_not_update_uid_pid.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ flag = False
+ if msg == "update":
+ flag = True
+ _pass_keyword, _ = await PixivKeywordUser.get_current_keyword()
+ x_uid = []
+ x_pid = []
+ _uid = [int(x[4:]) for x in _pass_keyword if x.startswith("uid:")]
+ _pid = [int(x[4:]) for x in _pass_keyword if x.startswith("pid:")]
+ all_images = await Pixiv.query_images(r18=2)
+ for img in all_images:
+ if img.pid not in x_pid:
+ x_pid.append(img.pid)
+ if img.uid not in x_uid:
+ x_uid.append(img.uid)
+ await check_not_update_uid_pid.send(
+ "从未更新过的UID:"
+ + ",".join([f"uid:{x}" for x in _uid if x not in x_uid])
+ + "\n"
+ + "从未更新过的PID:"
+ + ",".join([f"pid:{x}" for x in _pid if x not in x_pid])
+ )
+ if flag:
+ await check_not_update_uid_pid.send("开始自动自动更新PID....")
+ update_lst = [f"pid:{x}" for x in _uid if x not in x_uid]
+ black_pid = await PixivKeywordUser.get_black_pid()
+ start_time = time.time()
+ pid_count, pic_count = await start_update_image_url(update_lst, black_pid)
+ await check_not_update_uid_pid.send(
+ f"Pixiv搜图关键词搜图更新完成...\n"
+ f"累计更新PID {pid_count} 个\n"
+ f"累计更新图片 {pic_count} 张" + "\n耗时:{:.2f}秒".format((time.time() - start_time))
+ )
diff --git a/plugins/pixiv_rank_search/__init__.py b/plugins/pixiv_rank_search/__init__.py
old mode 100644
new mode 100755
index 172cbc89..c09b4795
--- a/plugins/pixiv_rank_search/__init__.py
+++ b/plugins/pixiv_rank_search/__init__.py
@@ -1,213 +1,212 @@
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from nonebot.matcher import Matcher
-from nonebot import on_command
-from utils.utils import get_message_text, is_number
-from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
-from services.log import logger
-from nonebot.adapters.cqhttp.exception import NetworkError
-from asyncio.exceptions import TimeoutError
-from aiohttp.client_exceptions import ClientConnectorError
-from utils.message_builder import custom_forward_msg
-from configs.config import Config
-from typing import Type
-from nonebot.rule import to_me
-import time
-
-__zx_plugin_name__ = "P站排行/搜图"
-
-__plugin_usage__ = """
-usage:
- P站排行:
- 可选参数:
- 类型:
- 1. 日排行
- 2. 周排行
- 3. 月排行
- 4. 原创排行
- 5. 新人排行
- 6. R18日排行
- 7. R18周排行
- 8. R18受男性欢迎排行
- 9. R18重口排行【慎重!】
- 【使用时选择参数序号即可,R18仅可私聊】
- p站排行 ?[参数] ?[数量] ?[日期]
- 示例:
- p站排行榜 [无参数默认为日榜]
- p站排行榜 1
- p站排行榜 1 5
- p站排行榜 1 5 2018-4-25
- 【注意空格!!】【在线搜索会较慢】
- ---------------------------------
- P站搜图:
- 搜图 [关键词] ?[数量] ?[页数=1] ?[r18](不屏蔽R-18)
- 示例:
- 搜图 樱岛麻衣
- 搜图 樱岛麻衣 5
- 搜图 樱岛麻衣 5 r18
- 【默认为 热度排序】
- 【注意空格!!】【在线搜索会较慢】【数量可能不符?可能该页数量不够,也可能被R-18屏蔽】
-""".strip()
-__plugin_des__ = "P站排行榜直接冲,P站搜图跟着冲"
-__plugin_cmd__ = ["p站排行 ?[参数] ?[数量] ?[日期]", "搜图 [关键词] ?[数量] ?[页数=1] ?[r18](不屏蔽R-18)"]
-__plugin_type__ = ("来点好康的",)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 9,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["p站排行", "搜图", "p站搜图", "P站搜图"],
-}
-__plugin_block_limit__ = {"rst": "P站排行榜或搜图正在搜索,请不要重复触发命令..."}
-__plugin_configs__ = {
- "TIMEOUT": {
- "value": 10,
- "help": "图片下载超时限制",
- "default_value": 10
- }
-}
-Config.add_plugin_config(
- "hibiapi",
- "HIBIAPI",
- "https://api.obfs.dev",
- help_="如果没有自建或其他hibiapi请不要修改",
- default_value="https://api.obfs.dev",
-)
-Config.add_plugin_config(
- "pixiv",
- "PIXIV_NGINX_URL",
- "i.pixiv.re",
- help_="Pixiv反向代理"
-)
-
-
-rank_dict = {
- "1": "day",
- "2": "week",
- "3": "month",
- "4": "week_original",
- "5": "week_rookie",
- "6": "day_r18",
- "7": "week_r18",
- "8": "day_male_r18",
- "9": "week_r18g",
-}
-
-
-pixiv_rank = on_command(
- "p站排行",
- aliases={"P站排行榜", "p站排行榜", "P站排行榜", "P站排行"},
- priority=5,
- block=True,
- rule=to_me(),
-)
-pixiv_keyword = on_command("搜图", priority=5, block=True, rule=to_me())
-
-
-@pixiv_rank.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json()).strip()
- msg = msg.split(" ")
- msg = [m for m in msg if m]
- code = 0
- info_list = []
- if not msg:
- msg = ["1"]
- if msg[0] in ["6", "7", "8", "9"]:
- if event.message_type == "group":
- await pixiv_rank.finish("羞羞脸!私聊里自己看!", at_sender=True)
- if (n := len(msg)) == 0 or msg[0] == "":
- info_list, code = await get_pixiv_urls(rank_dict.get("1"))
- elif n == 1:
- if msg[0] not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
- await pixiv_rank.finish("要好好输入要看什么类型的排行榜呀!", at_sender=True)
- info_list, code = await get_pixiv_urls(rank_dict.get(msg[0]))
- elif n == 2:
- info_list, code = await get_pixiv_urls(rank_dict.get(msg[0]), int(msg[1]))
- elif n == 3:
- if not check_date(msg[2]):
- await pixiv_rank.finish("日期格式错误了", at_sender=True)
- info_list, code = await get_pixiv_urls(
- rank_dict.get(msg[0]), int(msg[1]), date=msg[2]
- )
- else:
- await pixiv_rank.finish("格式错了噢,参数不够?看看帮助?", at_sender=True)
- if code != 200 and info_list:
- await pixiv_rank.finish(info_list[0])
- if not info_list:
- await pixiv_rank.finish("没有找到啊,等等再试试吧~V", at_sender=True)
- await send_image(info_list, pixiv_rank, bot, event)
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查看了P站排行榜 code:{msg[0]}"
- )
-
-
-@pixiv_keyword.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if isinstance(event, GroupMessageEvent):
- if "r18" in msg.lower():
- await pixiv_keyword.finish("(脸红#) 你不会害羞的 八嘎!", at_sender=True)
- r18 = 0 if "r18" in msg else 1
- msg = msg.replace("r18", "").strip().split()
- msg = [m.strip() for m in msg if m]
- keyword = None
- info_list = None
- num = 10
- page = 1
- if (n := len(msg)) == 1:
- keyword = msg[0]
- if n > 1:
- if not is_number(msg[1]):
- await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
- num = int(msg[1])
- if n > 2:
- if not is_number(msg[2]):
- await pixiv_keyword.finish("页数数量必须是数字!", at_sender=True)
- page = int(msg[2])
- if keyword:
- info_list, code = await search_pixiv_urls(keyword, num, page, r18)
- if code != 200:
- await pixiv_keyword.finish(info_list[0])
- if not info_list:
- await pixiv_keyword.finish("没有找到啊,等等再试试吧~V", at_sender=True)
- await send_image(info_list, pixiv_keyword, bot, event)
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查看了搜索 {keyword} R18:{r18}"
- )
-
-
-def check_date(date):
- try:
- time.strptime(date, "%Y-%m-%d")
- return True
- except:
- return False
-
-
-async def send_image(
- info_list: list, matcher: Type[Matcher], bot: Bot, event: MessageEvent
-):
- if isinstance(event, GroupMessageEvent):
- await pixiv_rank.send("开始下载整理数据...")
- idx = 0
- mes_list = []
- for title, author, urls in info_list:
- _message = f"title: {title}\nauthor: {author}\n" + await download_pixiv_imgs(urls, event.user_id, idx)
- mes_list.append(_message)
- idx += 1
- mes_list = custom_forward_msg(mes_list, bot.self_id)
- await bot.send_group_forward_msg(group_id=event.group_id, messages=mes_list)
- else:
- for title, author, urls in info_list:
- try:
- await matcher.send(
- f"title: {title}\n"
- f"author: {author}\n"
- + await download_pixiv_imgs(urls, event.user_id)
- )
- except (NetworkError, TimeoutError, ClientConnectorError):
- await matcher.send("这张图网络直接炸掉了!", at_sender=True)
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot.matcher import Matcher
+from nonebot import on_command
+from utils.utils import get_message_text, is_number
+from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
+from services.log import logger
+from nonebot.adapters.cqhttp.exception import NetworkError
+from asyncio.exceptions import TimeoutError
+from utils.message_builder import custom_forward_msg
+from configs.config import Config
+from typing import Type
+from nonebot.rule import to_me
+import time
+
+__zx_plugin_name__ = "P站排行/搜图"
+
+__plugin_usage__ = """
+usage:
+ P站排行:
+ 可选参数:
+ 类型:
+ 1. 日排行
+ 2. 周排行
+ 3. 月排行
+ 4. 原创排行
+ 5. 新人排行
+ 6. R18日排行
+ 7. R18周排行
+ 8. R18受男性欢迎排行
+ 9. R18重口排行【慎重!】
+ 【使用时选择参数序号即可,R18仅可私聊】
+ p站排行 ?[参数] ?[数量] ?[日期]
+ 示例:
+ p站排行榜 [无参数默认为日榜]
+ p站排行榜 1
+ p站排行榜 1 5
+ p站排行榜 1 5 2018-4-25
+ 【注意空格!!】【在线搜索会较慢】
+ ---------------------------------
+ P站搜图:
+ 搜图 [关键词] ?[数量] ?[页数=1] ?[r18](不屏蔽R-18)
+ 示例:
+ 搜图 樱岛麻衣
+ 搜图 樱岛麻衣 5
+ 搜图 樱岛麻衣 5 r18
+ 【默认为 热度排序】
+ 【注意空格!!】【在线搜索会较慢】【数量可能不符?可能该页数量不够,也可能被R-18屏蔽】
+""".strip()
+__plugin_des__ = "P站排行榜直接冲,P站搜图跟着冲"
+__plugin_cmd__ = ["p站排行 ?[参数] ?[数量] ?[日期]", "搜图 [关键词] ?[数量] ?[页数=1] ?[r18](不屏蔽R-18)"]
+__plugin_type__ = ("来点好康的",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 9,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["p站排行", "搜图", "p站搜图", "P站搜图"],
+}
+__plugin_block_limit__ = {"rst": "P站排行榜或搜图正在搜索,请不要重复触发命令..."}
+__plugin_configs__ = {
+ "TIMEOUT": {
+ "value": 10,
+ "help": "图片下载超时限制",
+ "default_value": 10
+ }
+}
+Config.add_plugin_config(
+ "hibiapi",
+ "HIBIAPI",
+ "https://api.obfs.dev",
+ help_="如果没有自建或其他hibiapi请不要修改",
+ default_value="https://api.obfs.dev",
+)
+Config.add_plugin_config(
+ "pixiv",
+ "PIXIV_NGINX_URL",
+ "i.pixiv.re",
+ help_="Pixiv反向代理"
+)
+
+
+rank_dict = {
+ "1": "day",
+ "2": "week",
+ "3": "month",
+ "4": "week_original",
+ "5": "week_rookie",
+ "6": "day_r18",
+ "7": "week_r18",
+ "8": "day_male_r18",
+ "9": "week_r18g",
+}
+
+
+pixiv_rank = on_command(
+ "p站排行",
+ aliases={"P站排行榜", "p站排行榜", "P站排行榜", "P站排行"},
+ priority=5,
+ block=True,
+ rule=to_me(),
+)
+pixiv_keyword = on_command("搜图", priority=5, block=True, rule=to_me())
+
+
+@pixiv_rank.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json()).strip()
+ msg = msg.split(" ")
+ msg = [m for m in msg if m]
+ code = 0
+ info_list = []
+ if not msg:
+ msg = ["1"]
+ if msg[0] in ["6", "7", "8", "9"]:
+ if event.message_type == "group":
+ await pixiv_rank.finish("羞羞脸!私聊里自己看!", at_sender=True)
+ if (n := len(msg)) == 0 or msg[0] == "":
+ info_list, code = await get_pixiv_urls(rank_dict.get("1"))
+ elif n == 1:
+ if msg[0] not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
+ await pixiv_rank.finish("要好好输入要看什么类型的排行榜呀!", at_sender=True)
+ info_list, code = await get_pixiv_urls(rank_dict.get(msg[0]))
+ elif n == 2:
+ info_list, code = await get_pixiv_urls(rank_dict.get(msg[0]), int(msg[1]))
+ elif n == 3:
+ if not check_date(msg[2]):
+ await pixiv_rank.finish("日期格式错误了", at_sender=True)
+ info_list, code = await get_pixiv_urls(
+ rank_dict.get(msg[0]), int(msg[1]), date=msg[2]
+ )
+ else:
+ await pixiv_rank.finish("格式错了噢,参数不够?看看帮助?", at_sender=True)
+ if code != 200 and info_list:
+ await pixiv_rank.finish(info_list[0])
+ if not info_list:
+ await pixiv_rank.finish("没有找到啊,等等再试试吧~V", at_sender=True)
+ await send_image(info_list, pixiv_rank, bot, event)
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 查看了P站排行榜 code:{msg[0]}"
+ )
+
+
+@pixiv_keyword.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if isinstance(event, GroupMessageEvent):
+ if "r18" in msg.lower():
+ await pixiv_keyword.finish("(脸红#) 你不会害羞的 八嘎!", at_sender=True)
+ r18 = 0 if "r18" in msg else 1
+ msg = msg.replace("r18", "").strip().split()
+ msg = [m.strip() for m in msg if m]
+ keyword = None
+ info_list = None
+ num = 10
+ page = 1
+ if (n := len(msg)) == 1:
+ keyword = msg[0]
+ if n > 1:
+ if not is_number(msg[1]):
+ await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
+ num = int(msg[1])
+ if n > 2:
+ if not is_number(msg[2]):
+ await pixiv_keyword.finish("页数数量必须是数字!", at_sender=True)
+ page = int(msg[2])
+ if keyword:
+ info_list, code = await search_pixiv_urls(keyword, num, page, r18)
+ if code != 200:
+ await pixiv_keyword.finish(info_list[0])
+ if not info_list:
+ await pixiv_keyword.finish("没有找到啊,等等再试试吧~V", at_sender=True)
+ await send_image(info_list, pixiv_keyword, bot, event)
+ logger.info(
+ f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 查看了搜索 {keyword} R18:{r18}"
+ )
+
+
+def check_date(date):
+ try:
+ time.strptime(date, "%Y-%m-%d")
+ return True
+ except:
+ return False
+
+
+async def send_image(
+ info_list: list, matcher: Type[Matcher], bot: Bot, event: MessageEvent
+):
+ if isinstance(event, GroupMessageEvent):
+ await pixiv_rank.send("开始下载整理数据...")
+ idx = 0
+ mes_list = []
+ for title, author, urls in info_list:
+ _message = f"title: {title}\nauthor: {author}\n" + await download_pixiv_imgs(urls, event.user_id, idx)
+ mes_list.append(_message)
+ idx += 1
+ mes_list = custom_forward_msg(mes_list, bot.self_id)
+ await bot.send_group_forward_msg(group_id=event.group_id, messages=mes_list)
+ else:
+ for title, author, urls in info_list:
+ try:
+ await matcher.send(
+ f"title: {title}\n"
+ f"author: {author}\n"
+ + await download_pixiv_imgs(urls, event.user_id)
+ )
+ except (NetworkError, TimeoutError):
+ await matcher.send("这张图网络直接炸掉了!", at_sender=True)
diff --git a/plugins/pixiv_rank_search/data_source.py b/plugins/pixiv_rank_search/data_source.py
old mode 100644
new mode 100755
index 6547747e..898c97d0
--- a/plugins/pixiv_rank_search/data_source.py
+++ b/plugins/pixiv_rank_search/data_source.py
@@ -1,174 +1,154 @@
-from configs.path_config import IMAGE_PATH
-from utils.utils import get_local_proxy
-from utils.message_builder import image
-from asyncio.exceptions import TimeoutError
-from configs.config import Config
-from aiohttp.client_exceptions import ClientConnectorError
-from typing import Optional
-from pathlib import Path
-import aiohttp
-import aiofiles
-import platform
-
-if platform.system() == "Windows":
- import asyncio
-
- asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
-
-
-headers = {
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
- " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
- "Referer": "https://www.pixiv.net",
-}
-
-
-async def get_pixiv_urls(
- mode: str, num: int = 10, page: int = 1, date: Optional[str] = None
-) -> "list, int":
- """
- 拿到pixiv rank图片url
- :param mode: 模式
- :param num: 数量
- :param page: 页数
- :param date: 日期
- """
- params = {"mode": mode, "page": page}
- if date:
- params["date"] = date
- hibiapi = Config.get_config("hibiapi", "HIBIAPI")
- hibiapi = hibiapi[:-1] if hibiapi[-1] == "/" else hibiapi
- rank_url = f"{hibiapi}/api/pixiv/rank"
- return await parser_data(rank_url, num, params, "rank")
-
-
-async def search_pixiv_urls(
- keyword: str, num: int, page: int, r18: int
-) -> "list, list":
- """
- 搜图图片的url
- :param keyword: 关键词
- :param num: 数量
- :param page: 页数
- :param r18: 是否r18
- """
- params = {"word": keyword, "page": page}
- hibiapi = Config.get_config("hibiapi", "HIBIAPI")
- hibiapi = hibiapi[:-1] if hibiapi[-1] == "/" else hibiapi
- search_url = f"{hibiapi}/api/pixiv/search"
- return await parser_data(search_url, num, params, "search", r18)
-
-
-async def parser_data(
- url: str, num: int, params: dict, type_: str, r18: int = 0
-) -> "list, int":
- """
- 解析数据
- :param url: hibiapi搜索url
- :param num: 数量
- :param params: 参数
- :param type_: 类型,rank或search
- :param r18: 是否r18
- """
- info_list = []
- async with aiohttp.ClientSession() as session:
- for _ in range(3):
- try:
- async with session.get(
- url,
- params=params,
- proxy=get_local_proxy(),
- timeout=Config.get_config("pixiv_rank_search", "TIMEOUT"),
- ) as response:
- if response.status == 200:
- data = await response.json()
- if data.get("illusts"):
- data = data["illusts"]
- break
- except (TimeoutError, ClientConnectorError):
- pass
- else:
- return ["网络不太好?没有该页数?也许过一会就好了..."], 998
- num = num if num < 30 else 30
- data = data[:num]
- for x in data:
- if type_ == "search" and r18 == 1:
- if "R-18" in str(x["tags"]):
- continue
- title = x["title"]
- author = x["user"]["name"]
- urls = []
- if x["page_count"] == 1:
- urls.append(x["image_urls"]["large"])
- else:
- for j in x["meta_pages"]:
- urls.append(j["image_urls"]["large"])
- info_list.append((title, author, urls))
- return info_list, 200
-
-
-async def download_pixiv_imgs(
- urls: list, user_id: int, forward_msg_index: int = None
-) -> str:
- """
- 下载图片
- :param urls: 图片链接
- :param user_id: 用户id
- :param forward_msg_index: 转发消息中的图片排序
- """
- result = ""
- index = 0
- for url in urls:
- ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
- if ws_url.startswith("http"):
- ws_url = ws_url.split("//")[-1]
- url = (
- url.replace("i.pximg.net", ws_url)
- .replace("i.pixiv.cat", ws_url)
- .replace("_webp", "")
- )
- async with aiohttp.ClientSession(headers=headers) as session:
- for _ in range(3):
- try:
- async with session.get(
- url,
- proxy=get_local_proxy(),
- timeout=Config.get_config("pixiv_rank_search", "TIMEOUT"),
- ) as response:
- if response.status == 200:
- try:
- file = (
- f"{IMAGE_PATH}/temp/{user_id}_{forward_msg_index}_{index}_pixiv.jpg"
- if forward_msg_index is not None
- else f"{IMAGE_PATH}/temp/{user_id}_{index}_pixiv.jpg"
- )
- file = Path(file)
- if forward_msg_index is not None:
- async with aiofiles.open(
- file,
- "wb",
- ) as f:
- await f.write(await response.read())
- result += image(
- f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg",
- "temp",
- )
- else:
- async with aiofiles.open(
- file,
- "wb",
- ) as f:
- await f.write(await response.read())
- result += image(
- f"{user_id}_{index}_pixiv.jpg", "temp"
- )
- index += 1
- break
- except OSError:
- file.unlink()
- except (TimeoutError, ClientConnectorError):
- # result += '\n这张图下载失败了..\n'
- pass
- else:
- result += "\n这张图下载失败了..\n"
- return result
+from configs.path_config import IMAGE_PATH
+from utils.message_builder import image
+from asyncio.exceptions import TimeoutError
+from configs.config import Config
+from utils.http_utils import AsyncHttpx
+from typing import Optional
+from services.log import logger
+from pathlib import Path
+import platform
+
+if platform.system() == "Windows":
+ import asyncio
+
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+
+
+headers = {
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
+ " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
+ "Referer": "https://www.pixiv.net",
+}
+
+
+async def get_pixiv_urls(
+ mode: str, num: int = 10, page: int = 1, date: Optional[str] = None
+) -> "list, int":
+ """
+ 拿到pixiv rank图片url
+ :param mode: 模式
+ :param num: 数量
+ :param page: 页数
+ :param date: 日期
+ """
+ params = {"mode": mode, "page": page}
+ if date:
+ params["date"] = date
+ hibiapi = Config.get_config("hibiapi", "HIBIAPI")
+ hibiapi = hibiapi[:-1] if hibiapi[-1] == "/" else hibiapi
+ rank_url = f"{hibiapi}/api/pixiv/rank"
+ return await parser_data(rank_url, num, params, "rank")
+
+
+async def search_pixiv_urls(
+ keyword: str, num: int, page: int, r18: int
+) -> "list, list":
+ """
+ 搜图图片的url
+ :param keyword: 关键词
+ :param num: 数量
+ :param page: 页数
+ :param r18: 是否r18
+ """
+ params = {"word": keyword, "page": page}
+ hibiapi = Config.get_config("hibiapi", "HIBIAPI")
+ hibiapi = hibiapi[:-1] if hibiapi[-1] == "/" else hibiapi
+ search_url = f"{hibiapi}/api/pixiv/search"
+ return await parser_data(search_url, num, params, "search", r18)
+
+
+async def parser_data(
+ url: str, num: int, params: dict, type_: str, r18: int = 0
+) -> "list, int":
+ """
+ 解析数据
+ :param url: hibiapi搜索url
+ :param num: 数量
+ :param params: 参数
+ :param type_: 类型,rank或search
+ :param r18: 是否r18
+ """
+ info_list = []
+ for _ in range(3):
+ try:
+ response = await AsyncHttpx.get(
+ url,
+ params=params,
+ timeout=Config.get_config("pixiv_rank_search", "TIMEOUT"),
+ )
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("illusts"):
+ data = data["illusts"]
+ break
+ except TimeoutError:
+ pass
+ except Exception as e:
+ logger.error(f"P站排行/搜图解析数据发生错误 {type(e)}:{e}")
+ return ["发生了一些些错误..."], 995
+ else:
+ return ["网络不太好?没有该页数?也许过一会就好了..."], 998
+ num = num if num < 30 else 30
+ data = data[:num]
+ for x in data:
+ if type_ == "search" and r18 == 1:
+ if "R-18" in str(x["tags"]):
+ continue
+ title = x["title"]
+ author = x["user"]["name"]
+ urls = []
+ if x["page_count"] == 1:
+ urls.append(x["image_urls"]["large"])
+ else:
+ for j in x["meta_pages"]:
+ urls.append(j["image_urls"]["large"])
+ info_list.append((title, author, urls))
+ return info_list, 200
+
+
+async def download_pixiv_imgs(
+ urls: list, user_id: int, forward_msg_index: int = None
+) -> str:
+ """
+ 下载图片
+ :param urls: 图片链接
+ :param user_id: 用户id
+ :param forward_msg_index: 转发消息中的图片排序
+ """
+ result = ""
+ index = 0
+ for url in urls:
+ ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
+ if ws_url:
+ url = (
+ url.replace("i.pximg.net", ws_url)
+ .replace("i.pixiv.cat", ws_url)
+ .replace("_webp", "")
+ )
+ try:
+ file = (
+ f"{IMAGE_PATH}/temp/{user_id}_{forward_msg_index}_{index}_pixiv.jpg"
+ if forward_msg_index is not None
+ else f"{IMAGE_PATH}/temp/{user_id}_{index}_pixiv.jpg"
+ )
+ file = Path(file)
+ try:
+ if await AsyncHttpx.download_file(
+ url,
+ file,
+ timeout=Config.get_config("pixiv_rank_search", "TIMEOUT"),
+ ):
+ if forward_msg_index is not None:
+ result += image(
+ f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg",
+ "temp",
+ )
+ else:
+ result += image(f"{user_id}_{index}_pixiv.jpg", "temp")
+ index += 1
+ except OSError:
+ if file.exists():
+ file.unlink()
+ except Exception as e:
+ logger.error(f"P站排行/搜图下载图片错误 {type(e)}:{e}")
+ return result
diff --git a/plugins/poke/__init__.py b/plugins/poke/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/quotations.py b/plugins/quotations.py
old mode 100644
new mode 100755
index f3e98b90..3c083c84
--- a/plugins/quotations.py
+++ b/plugins/quotations.py
@@ -2,8 +2,7 @@ from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from nonebot.typing import T_State
-import aiohttp
-from utils.utils import get_local_proxy
+from utils.http_utils import AsyncHttpx
__zx_plugin_name__ = "一言二次元语录"
@@ -32,9 +31,7 @@ url = "https://international.v1.hitokoto.cn/?c=a"
@quotations.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
- async with aiohttp.ClientSession() as session:
- async with session.get(url, proxy=get_local_proxy(), timeout=5) as response:
- data = await response.json()
+ data = (await AsyncHttpx.get(url, timeout=5)).json()
result = f'{data["hitokoto"]}\t——{data["from"]}'
await quotations.send(result)
logger.info(
diff --git a/plugins/roll.py b/plugins/roll.py
old mode 100644
new mode 100755
index b8fe723b..35fb09f3
--- a/plugins/roll.py
+++ b/plugins/roll.py
@@ -1,66 +1,66 @@
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
-from utils.utils import get_message_text
-from services.log import logger
-from configs.config import NICKNAME
-import random
-import asyncio
-
-
-__zx_plugin_name__ = "roll"
-__plugin_usage__ = """
-usage:
- 随机数字 或 随机选择事件
- 指令:
- roll: 随机 0-100 的数字
- roll *[文本]: 随机事件
- 示例:roll 吃饭 睡觉 打游戏
-""".strip()
-__plugin_des__ = "犹豫不决吗?那就让我帮你决定吧"
-__plugin_cmd__ = ["roll", "roll *[文本]"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["roll"],
-}
-
-
-roll = on_command("roll", priority=5, block=True)
-
-
-@roll.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json()).split()
- if not msg:
- await roll.finish(f"roll: {random.randint(0, 100)}", at_sender=True)
- user_name = event.sender.card if event.sender.card else event.sender.nickname
- await roll.send(
- random.choice(
- [
- "转动命运的齿轮,拨开眼前迷雾...",
- f"启动吧,命运的水晶球,为{user_name}指引方向!",
- "嗯哼,在此刻转动吧!命运!",
- f"在此祈愿,请为{user_name}降下指引...",
- ]
- )
- )
- await asyncio.sleep(1)
- x = random.choice(msg)
- await roll.send(
- random.choice(
- [
- f"让{NICKNAME}看看是什么结果!答案是:‘{x}’",
- f"根据命运的指引,接下来{user_name} ‘{x}’ 会比较好",
- f"祈愿被回应了!是 ‘{x}’!",
- f"结束了,{user_name},命运之轮停在了 ‘{x}’!",
- ]
- )
- )
- logger.info(
- f"(USER {event.user_id}, "
- f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 发送roll:{msg}"
- )
+from nonebot import on_command
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from utils.utils import get_message_text
+from services.log import logger
+from configs.config import NICKNAME
+import random
+import asyncio
+
+
+__zx_plugin_name__ = "roll"
+__plugin_usage__ = """
+usage:
+ 随机数字 或 随机选择事件
+ 指令:
+ roll: 随机 0-100 的数字
+ roll *[文本]: 随机事件
+ 示例:roll 吃饭 睡觉 打游戏
+""".strip()
+__plugin_des__ = "犹豫不决吗?那就让我帮你决定吧"
+__plugin_cmd__ = ["roll", "roll *[文本]"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["roll"],
+}
+
+
+roll = on_command("roll", priority=5, block=True)
+
+
+@roll.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json()).split()
+ if not msg:
+ await roll.finish(f"roll: {random.randint(0, 100)}", at_sender=True)
+ user_name = event.sender.card if event.sender.card else event.sender.nickname
+ await roll.send(
+ random.choice(
+ [
+ "转动命运的齿轮,拨开眼前迷雾...",
+ f"启动吧,命运的水晶球,为{user_name}指引方向!",
+ "嗯哼,在此刻转动吧!命运!",
+ f"在此祈愿,请为{user_name}降下指引...",
+ ]
+ )
+ )
+ await asyncio.sleep(1)
+ x = random.choice(msg)
+ await roll.send(
+ random.choice(
+ [
+ f"让{NICKNAME}看看是什么结果!答案是:‘{x}’",
+ f"根据命运的指引,接下来{user_name} ‘{x}’ 会比较好",
+ f"祈愿被回应了!是 ‘{x}’!",
+ f"结束了,{user_name},命运之轮停在了 ‘{x}’!",
+ ]
+ )
+ )
+ logger.info(
+ f"(USER {event.user_id}, "
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 发送roll:{msg}"
+ )
diff --git a/plugins/russian/__init__.py b/plugins/russian/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/russian/data_source.py b/plugins/russian/data_source.py
old mode 100644
new mode 100755
diff --git a/plugins/russian/model.py b/plugins/russian/model.py
old mode 100644
new mode 100755
diff --git a/plugins/search_anime/__init__.py b/plugins/search_anime/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/search_anime/data_source.py b/plugins/search_anime/data_source.py
old mode 100644
new mode 100755
index 577ccf3d..42daba1d
--- a/plugins/search_anime/data_source.py
+++ b/plugins/search_anime/data_source.py
@@ -2,10 +2,9 @@ from lxml import etree
import feedparser
from urllib import parse
from services.log import logger
+from utils.http_utils import AsyncHttpx
from typing import List
-import aiohttp
import time
-from utils.utils import get_local_proxy
async def from_anime_get_info(key_word: str, max_: int) -> List[str]:
@@ -22,35 +21,32 @@ async def from_anime_get_info(key_word: str, max_: int) -> List[str]:
async def get_repass(url: str, max_: int) -> List[str]:
put_line = []
- async with aiohttp.ClientSession() as session:
- async with session.get(url, proxy=get_local_proxy(), timeout=20) as response:
- d = feedparser.parse(await response.text())
- max_ = max_ if max_ < len([e.link for e in d.entries]) else len([e.link for e in d.entries])
- url_list = [e.link for e in d.entries][:max_]
- for u in url_list:
- try:
- async with session.get(
- u, proxy=get_local_proxy(), timeout=20
- ) as res:
- html = etree.HTML(await res.text())
- magent = html.xpath('.//a[@id="a_magnet"]/text()')[0]
- title = html.xpath(".//h3/text()")[0]
- item = html.xpath(
- '//div[@class="info resource-info right"]/ul/li'
- )
- class_a = (
- item[0]
- .xpath("string(.)")[5:]
- .strip()
- .replace("\xa0", "")
- .replace("\t", "")
- )
- size = item[3].xpath("string(.)")[5:].strip()
- put_line.append(
- "【{}】| {}\n【{}】| {}".format(class_a, title, size, magent)
- )
- except Exception as e:
- logger.warning(f"搜番超时 e:{e}")
+ text = (await AsyncHttpx.get(url)).text
+ d = feedparser.parse(text)
+ max_ = max_ if max_ < len([e.link for e in d.entries]) else len([e.link for e in d.entries])
+ url_list = [e.link for e in d.entries][:max_]
+ for u in url_list:
+ try:
+ text = (await AsyncHttpx.get(u)).text
+ html = etree.HTML(text)
+ magent = html.xpath('.//a[@id="a_magnet"]/text()')[0]
+ title = html.xpath(".//h3/text()")[0]
+ item = html.xpath(
+ '//div[@class="info resource-info right"]/ul/li'
+ )
+ class_a = (
+ item[0]
+ .xpath("string(.)")[5:]
+ .strip()
+ .replace("\xa0", "")
+ .replace("\t", "")
+ )
+ size = item[3].xpath("string(.)")[5:].strip()
+ put_line.append(
+ "【{}】| {}\n【{}】| {}".format(class_a, title, size, magent)
+ )
+ except Exception as e:
+ logger.error(f"搜番发生错误 {type(e)}:{e}")
return put_line
diff --git a/plugins/search_buff_skin_price/__init__.py b/plugins/search_buff_skin_price/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/search_buff_skin_price/data_source.py b/plugins/search_buff_skin_price/data_source.py
old mode 100644
new mode 100755
index 3785484a..5ab86040
--- a/plugins/search_buff_skin_price/data_source.py
+++ b/plugins/search_buff_skin_price/data_source.py
@@ -1,44 +1,49 @@
-from utils.user_agent import get_user_agent
-import aiohttp
from asyncio.exceptions import TimeoutError
from configs.config import Config
+from utils.http_utils import AsyncHttpx
+from services.log import logger
url = "https://buff.163.com/api/market/goods"
-async def get_price(dname):
+async def get_price(d_name: str) -> "str, int":
+ """
+ 查看皮肤价格
+ :param d_name: 武器皮肤,如:awp 二西莫夫
+ """
cookie = {"session": Config.get_config("search_buff_skin_price", "COOKIE")}
name_list = []
price_list = []
- parameter = {"game": "csgo", "page_num": "1", "search": dname}
+ parameter = {"game": "csgo", "page_num": "1", "search": d_name}
try:
- async with aiohttp.ClientSession(
- cookies=cookie, headers=get_user_agent()
- ) as session:
- async with session.get(
- url, proxy=Config.get_config("search_buff_skin_price", "BUFF_PROXY"), params=parameter, timeout=5
- ) as response:
- if response.status == 200:
- try:
- if str(await response.text()).find("Login Required") != -1:
- return "BUFF登录被重置,请联系管理员重新登入", 996
- data = (await response.json())["data"]
- total_page = data["total_page"]
- data = data["items"]
- for _ in range(total_page):
- for i in range(len(data)):
- name = data[i]["name"]
- price = data[i]["sell_reference_price"]
- name_list.append(name)
- price_list.append(price)
- except Exception:
- return "没有查询到...", 998
- else:
- return "访问失败!", response.status
+ response = await AsyncHttpx.get(
+ url,
+ proxy=Config.get_config("search_buff_skin_price", "BUFF_PROXY"),
+ params=parameter,
+ cookies=cookie,
+ )
+ if response.status_code == 200:
+ try:
+ if response.text.find("Login Required") != -1:
+ return "BUFF登录被重置,请联系管理员重新登入", 996
+ data = response.json()["data"]
+ total_page = data["total_page"]
+ data = data["items"]
+ for _ in range(total_page):
+ for i in range(len(data)):
+ name = data[i]["name"]
+ price = data[i]["sell_reference_price"]
+ name_list.append(name)
+ price_list.append(price)
+ except Exception as e:
+ logger.error(f"BUFF查询皮肤发生错误 {type(e)}:{e}")
+ return "没有查询到...", 998
+ else:
+ return "访问失败!", response.status_code
except TimeoutError:
return "访问超时! 请重试或稍后再试!", 997
- result = f"皮肤: {dname}({len(name_list)})\n"
+ result = f"皮肤: {d_name}({len(name_list)})\n"
for i in range(len(name_list)):
result += name_list[i] + ": " + price_list[i] + "\n"
return result[:-1], 999
diff --git a/plugins/search_image/__init__.py b/plugins/search_image/__init__.py
new file mode 100644
index 00000000..d10b9505
--- /dev/null
+++ b/plugins/search_image/__init__.py
@@ -0,0 +1,133 @@
+# # -*- coding: utf-8 -*-
+# from typing import Dict
+#
+# from aiohttp.client_exceptions import ClientError
+# from nonebot.plugin import on_command, on_message
+# from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+# from nonebot.typing import T_State
+# from services.log import logger
+# from utils.utils import get_message_text, get_message_imgs
+# from configs.config import Config
+# from nonebot.rule import to_me
+#
+#
+#
+# __zx_plugin_name__ = "识图"
+# __plugin_usage__ = """
+# usage:
+# 识别图片 [二次元图片]
+# 指令:
+# 识图 [图片]
+# """.strip()
+# __plugin_des__ = "以图搜图,看破本源"
+# __plugin_cmd__ = ["识图"]
+# __plugin_type__ = ("一些工具",)
+# __plugin_version__ = 0.1
+# __plugin_author__ = "synodriver"
+# __plugin_settings__ = {
+# "level": 5,
+# "default_status": True,
+# "limit_superuser": False,
+# "cmd": ["识图"],
+# }
+# __plugin_configs__ = {
+# "MAX_FIND_IMAGE_COUNT": {"value": 3, "help": "识图返回的最大结果数", "default_value": 3}
+# }
+#
+#
+# async def get_des(url: str, mode: str, user_id: int):
+# """
+# :param url: 图片链接
+# :param mode: 图源
+# :param user_id: 用户 id
+# """
+# if mode == "iqdb":
+# async for msg in get_des_iqdb(url):
+# yield msg
+# elif mode == "ex":
+# async for msg in get_des_ex(url):
+# yield msg
+# elif mode == "trace":
+# async for msg in get_des_trace(url):
+# yield msg
+# elif mode == "yandex":
+# async for msg in get_des_yandex(url):
+# yield msg
+# elif mode.startswith("asc"):
+# async for msg in get_des_asc(url, user_id):
+# yield msg
+# else:
+# async for msg in get_des_sau(url, user_id):
+# yield msg
+#
+#
+# setu = on_command("识图", aliases={"search"}, block=True, priority=5)
+#
+#
+# @setu.handle()
+# async def handle_first_receive(bot: Bot, event: MessageEvent, state: T_State):
+# msg = get_message_text(event.json())
+# imgs = get_message_imgs(event.json())
+# if imgs:
+# state["setu"] = imgs[0]
+# if msg:
+# state["mod"] = msg
+#
+#
+# # ex/nao/trace/iqdb/ascii2d
+# # @setu.got("mod", prompt="从哪里查找呢? ex/nao/trace/iqdb/ascii2d")
+# # async def get_func(bot: Bot, event: MessageEvent, state: dict):
+# # pass
+#
+#
+# @setu.args_parser
+# async def get_setu(bot: Bot, event: MessageEvent, state: T_State):
+# imgs = get_message_imgs(event.json())
+# msg = get_message_text(event.json())
+# if not imgs:
+# await setu.reject()
+# if msg:
+# state["mod"] = msg
+# state["setu"] = imgs[0]
+#
+#
+# @setu.got("setu", prompt="图呢?")
+# async def get_setu(bot: Bot, event: MessageEvent, state: T_State):
+# """
+# 发现没有的时候要发问
+# :return:
+# """
+# url: str = state["setu"]
+# mod: str = state["mod"] if state.get("mod") else "nao" # 模式
+# try:
+# await bot.send(event=event, message="正在处理图片")
+# idx = 1
+# async for msg in get_des(url, mod, event.user_id):
+# if msg:
+# await bot.send(event=event, message=msg)
+# if idx == Config.get_config(
+# "nonebot_plugin_picsearcher", "MAX_FIND_IMAGE_COUNT"
+# ):
+# break
+# idx += 1
+# if id == 1:
+# await bot.send(event=event, message="没找着.")
+# logger.info(
+# f"(USER {event.user_id}, GROUP "
+# f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 识图:{url}"
+# )
+# # image_data: List[Tuple] = await get_pic_from_url(url)
+# # await setu.finish("hso")
+# except IndexError:
+# # await bot.send(event, traceback.format_exc())
+# await setu.finish("参数错误")
+# except ClientError:
+# await setu.finish("连接失败")
+#
+#
+#
+#
+#
+#
+#
+#
diff --git a/plugins/search_image/config.py b/plugins/search_image/config.py
new file mode 100644
index 00000000..121ce757
--- /dev/null
+++ b/plugins/search_image/config.py
@@ -0,0 +1,4 @@
+
+API_URL_SAUCENAO = 'https://saucenao.com/search.php'
+API_URL_ASCII2D = 'https://ascii2d.net/search/url/'
+API_URL_IQDB = 'https://iqdb.org/'
diff --git a/plugins/search_image/saucenao.py b/plugins/search_image/saucenao.py
new file mode 100644
index 00000000..8dd14280
--- /dev/null
+++ b/plugins/search_image/saucenao.py
@@ -0,0 +1,47 @@
+from utils.user_agent import get_user_agent
+from utils.utils import get_local_proxy
+
+
+
+
+
+async def get_saucenao_identify_result(url: str) -> Result.DictListResult:
+ fetcher = HttpFetcher(timeout=10, flag='search_image_saucenao', headers=HEADERS)
+
+ if not API_KEY:
+ logger.opt(colors=True).warning(f'Saucenao API KEY未配置, 无法使用Saucenao API进行识图!')
+ return Result.DictListResult(error=True, info='Saucenao API KEY未配置', result=[])
+
+ __payload = {'output_type': 2,
+ 'api_key': API_KEY,
+ 'testmode': 1,
+ 'numres': 6,
+ 'db': 999,
+ 'url': url}
+ saucenao_result = await fetcher.get_json(url=API_URL_SAUCENAO, params=__payload)
+ if saucenao_result.error:
+ logger.warning(f'get_saucenao_identify_result failed, Network error: {saucenao_result.info}')
+ return Result.DictListResult(error=True, info=f'Network error: {saucenao_result.info}', result=[])
+
+ __result_json = saucenao_result.result
+
+ if __result_json['header']['status'] != 0:
+ logger.error(f"get_saucenao_identify_result failed, DataSource error, "
+ f"status code: {__result_json['header']['status']}")
+ return Result.DictListResult(
+ error=True, info=f"DataSource error, status code: {__result_json['header']['status']}", result=[])
+
+ __result = []
+ for __item in __result_json['results']:
+ try:
+ if int(float(__item['header']['similarity'])) < 75:
+ continue
+ else:
+ __result.append({'similarity': __item['header']['similarity'],
+ 'thumbnail': __item['header']['thumbnail'],
+ 'index_name': __item['header']['index_name'],
+ 'ext_urls': __item['data']['ext_urls']})
+ except Exception as res_err:
+ logger.warning(f"get_saucenao_identify_result failed: {repr(res_err)}, can not resolve results")
+ continue
+ return Result.DictListResult(error=False, info='Success', result=__result)
\ No newline at end of file
diff --git a/plugins/send_dinggong_voice/__init__.py b/plugins/send_dinggong_voice/__init__.py
old mode 100644
new mode 100755
index 2b584168..d0359f53
--- a/plugins/send_dinggong_voice/__init__.py
+++ b/plugins/send_dinggong_voice/__init__.py
@@ -1,11 +1,11 @@
from nonebot import on_keyword
from utils.message_builder import record
from configs.path_config import VOICE_PATH
-import random
from services.log import logger
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from nonebot.rule import to_me
+import random
import os
__zx_plugin_name__ = "骂我"
diff --git a/plugins/send_setu_/__init__.py b/plugins/send_setu_/__init__.py
old mode 100644
new mode 100755
index 9418a25b..5f878a25
--- a/plugins/send_setu_/__init__.py
+++ b/plugins/send_setu_/__init__.py
@@ -1,4 +1,4 @@
-import nonebot
-
-
-nonebot.load_plugins("plugins/send_setu_")
+import nonebot
+
+
+nonebot.load_plugins("plugins/send_setu_")
diff --git a/plugins/send_setu_/model.py b/plugins/send_setu_/model.py
old mode 100644
new mode 100755
index affe617d..b35881c9
--- a/plugins/send_setu_/model.py
+++ b/plugins/send_setu_/model.py
@@ -1,177 +1,177 @@
-from services.db_context import db
-from typing import List, Optional
-
-
-class Setu(db.Model):
- __tablename__ = "setu"
- __table_args__ = {'extend_existing': True}
-
- id = db.Column(db.Integer(), primary_key=True)
- local_id = db.Column(db.Integer(), nullable=False)
- title = db.Column(db.String(), nullable=False)
- author = db.Column(db.String(), nullable=False)
- pid = db.Column(db.BigInteger(), nullable=False)
- img_hash = db.Column(db.String(), nullable=False)
- img_url = db.Column(db.String(), nullable=False)
- is_r18 = db.Column(db.Boolean(), nullable=False)
- tags = db.Column(db.String())
-
- _idx1 = db.Index("setu_pid_img_url_idx1", "pid", "img_url", unique=True)
-
- @classmethod
- async def add_setu_data(
- cls,
- local_id: int,
- title: str,
- author: str,
- pid: int,
- img_hash: str,
- img_url: str,
- tags: str,
- ):
- """
- 说明:
- 添加一份色图数据
- 参数:
- :param local_id: 本地存储id
- :param title: 标题
- :param author: 作者
- :param pid: 图片pid
- :param img_hash: 图片hash值
- :param img_url: 图片链接
- :param tags: 图片标签
- """
- if not await cls._check_exists(pid, img_url):
- await cls.create(
- local_id=local_id,
- title=title,
- author=author,
- pid=pid,
- img_hash=img_hash,
- img_url=img_url,
- is_r18=True if "R-18" in tags else False,
- tags=tags,
- )
-
- @classmethod
- async def query_image(
- cls,
- local_id: Optional[int] = None,
- tags: Optional[List[str]] = None,
- r18: int = 0,
- limit: int = 50,
- ):
- """
- 说明:
- 通过tag查找色图
- 参数:
- :param local_id: 本地色图 id
- :param tags: tags
- :param r18: 是否 r18,0:非r18 1:r18 2:混合
- :param limit: 获取数量
- """
- if local_id:
- flag = True if r18 == 1 else False
- return await cls.query.where(
- (cls.local_id == local_id) & (cls.is_r18 == flag)
- ).gino.first()
- if r18 == 0:
- query = cls.query.where(cls.is_r18 == False)
- elif r18 == 1:
- query = cls.query.where(cls.is_r18 == True)
- else:
- query = cls.query
- if tags:
- for tag in tags:
- query = query.where(cls.tags.contains(tag) | cls.title.contains(tag) | cls.author.contains(tag))
- query = query.order_by(db.func.random()).limit(limit)
- return await query.gino.all()
-
- @classmethod
- async def get_image_count(cls, r18: int = 0) -> int:
- """
- 说明:
- 查询图片数量
- """
- flag = False if r18 == 0 else True
- setattr(Setu, 'count', db.func.count(cls.local_id).label('count'))
- count = await cls.select('count').where(cls.is_r18 == flag).gino.first()
- return count[0]
-
- @classmethod
- async def get_image_in_hash(cls, img_hash: str) -> "Setu":
- """
- 说明:
- 通过图像hash获取图像信息
- 参数:
- :param img_hash: = 图像hash值
- """
- query = await cls.query.where(cls.img_hash == img_hash).gino.first()
- return query
-
- @classmethod
- async def _check_exists(cls, pid: int, img_url: str) -> bool:
- """
- 说明:
- 检测图片是否存在
- 参数:
- :param pid: 图片pid
- :param img_url: 图片链接
- """
- return bool(
- await cls.query.where(
- (cls.pid == pid) & (cls.img_url == img_url)
- ).gino.first()
- )
-
- @classmethod
- async def update_setu_data(
- cls,
- pid: int,
- *,
- local_id: Optional[int] = None,
- title: Optional[str] = None,
- author: Optional[str] = None,
- img_hash: Optional[str] = None,
- img_url: Optional[str] = None,
- tags: Optional[str] = None,
- ) -> bool:
- """
- 说明:
- 根据PID修改图片数据
- 参数:
- :param local_id: 本地id
- :param pid: 图片pid
- :param title: 标题
- :param author: 作者
- :param img_hash: 图片hash值
- :param img_url: 图片链接
- :param tags: 图片标签
- """
- query = cls.query.where(cls.pid == pid).with_for_update()
- image_list = await query.gino.all()
- if image_list:
- for image in image_list:
- if local_id:
- await image.update(local_id=local_id).apply()
- if title:
- await image.update(title=title).apply()
- if author:
- await image.update(author=author).apply()
- if img_hash:
- await image.update(img_hash=img_hash).apply()
- if img_url:
- await image.update(img_url=img_url).apply()
- if tags:
- await image.update(tags=tags).apply()
- return True
- return False
-
- @classmethod
- async def get_all_setu(cls) -> List["Setu"]:
- """
- 说明:
- 获取所有图片对象
- """
- return await cls.query.gino.all()
-
+from services.db_context import db
+from typing import List, Optional
+
+
+class Setu(db.Model):
+ __tablename__ = "setu"
+ __table_args__ = {'extend_existing': True}
+
+ id = db.Column(db.Integer(), primary_key=True)
+ local_id = db.Column(db.Integer(), nullable=False)
+ title = db.Column(db.String(), nullable=False)
+ author = db.Column(db.String(), nullable=False)
+ pid = db.Column(db.BigInteger(), nullable=False)
+ img_hash = db.Column(db.String(), nullable=False)
+ img_url = db.Column(db.String(), nullable=False)
+ is_r18 = db.Column(db.Boolean(), nullable=False)
+ tags = db.Column(db.String())
+
+ _idx1 = db.Index("setu_pid_img_url_idx1", "pid", "img_url", unique=True)
+
+ @classmethod
+ async def add_setu_data(
+ cls,
+ local_id: int,
+ title: str,
+ author: str,
+ pid: int,
+ img_hash: str,
+ img_url: str,
+ tags: str,
+ ):
+ """
+ 说明:
+ 添加一份色图数据
+ 参数:
+ :param local_id: 本地存储id
+ :param title: 标题
+ :param author: 作者
+ :param pid: 图片pid
+ :param img_hash: 图片hash值
+ :param img_url: 图片链接
+ :param tags: 图片标签
+ """
+ if not await cls._check_exists(pid, img_url):
+ await cls.create(
+ local_id=local_id,
+ title=title,
+ author=author,
+ pid=pid,
+ img_hash=img_hash,
+ img_url=img_url,
+ is_r18=True if "R-18" in tags else False,
+ tags=tags,
+ )
+
+ @classmethod
+ async def query_image(
+ cls,
+ local_id: Optional[int] = None,
+ tags: Optional[List[str]] = None,
+ r18: int = 0,
+ limit: int = 50,
+ ):
+ """
+ 说明:
+ 通过tag查找色图
+ 参数:
+ :param local_id: 本地色图 id
+ :param tags: tags
+ :param r18: 是否 r18,0:非r18 1:r18 2:混合
+ :param limit: 获取数量
+ """
+ if local_id:
+ flag = True if r18 == 1 else False
+ return await cls.query.where(
+ (cls.local_id == local_id) & (cls.is_r18 == flag)
+ ).gino.first()
+ if r18 == 0:
+ query = cls.query.where(cls.is_r18 == False)
+ elif r18 == 1:
+ query = cls.query.where(cls.is_r18 == True)
+ else:
+ query = cls.query
+ if tags:
+ for tag in tags:
+ query = query.where(cls.tags.contains(tag) | cls.title.contains(tag) | cls.author.contains(tag))
+ query = query.order_by(db.func.random()).limit(limit)
+ return await query.gino.all()
+
+ @classmethod
+ async def get_image_count(cls, r18: int = 0) -> int:
+ """
+ 说明:
+ 查询图片数量
+ """
+ flag = False if r18 == 0 else True
+ setattr(Setu, 'count', db.func.count(cls.local_id).label('count'))
+ count = await cls.select('count').where(cls.is_r18 == flag).gino.first()
+ return count[0]
+
+ @classmethod
+ async def get_image_in_hash(cls, img_hash: str) -> "Setu":
+ """
+ 说明:
+ 通过图像hash获取图像信息
+ 参数:
+ :param img_hash: = 图像hash值
+ """
+ query = await cls.query.where(cls.img_hash == img_hash).gino.first()
+ return query
+
+ @classmethod
+ async def _check_exists(cls, pid: int, img_url: str) -> bool:
+ """
+ 说明:
+ 检测图片是否存在
+ 参数:
+ :param pid: 图片pid
+ :param img_url: 图片链接
+ """
+ return bool(
+ await cls.query.where(
+ (cls.pid == pid) & (cls.img_url == img_url)
+ ).gino.first()
+ )
+
+ @classmethod
+ async def update_setu_data(
+ cls,
+ pid: int,
+ *,
+ local_id: Optional[int] = None,
+ title: Optional[str] = None,
+ author: Optional[str] = None,
+ img_hash: Optional[str] = None,
+ img_url: Optional[str] = None,
+ tags: Optional[str] = None,
+ ) -> bool:
+ """
+ 说明:
+ 根据PID修改图片数据
+ 参数:
+ :param local_id: 本地id
+ :param pid: 图片pid
+ :param title: 标题
+ :param author: 作者
+ :param img_hash: 图片hash值
+ :param img_url: 图片链接
+ :param tags: 图片标签
+ """
+ query = cls.query.where(cls.pid == pid).with_for_update()
+ image_list = await query.gino.all()
+ if image_list:
+ for image in image_list:
+ if local_id:
+ await image.update(local_id=local_id).apply()
+ if title:
+ await image.update(title=title).apply()
+ if author:
+ await image.update(author=author).apply()
+ if img_hash:
+ await image.update(img_hash=img_hash).apply()
+ if img_url:
+ await image.update(img_url=img_url).apply()
+ if tags:
+ await image.update(tags=tags).apply()
+ return True
+ return False
+
+ @classmethod
+ async def get_all_setu(cls) -> List["Setu"]:
+ """
+ 说明:
+ 获取所有图片对象
+ """
+ return await cls.query.gino.all()
+
diff --git a/plugins/send_setu_/send_setu/__init__.py b/plugins/send_setu_/send_setu/__init__.py
old mode 100644
new mode 100755
index 2d4ce1fc..16b439b4
--- a/plugins/send_setu_/send_setu/__init__.py
+++ b/plugins/send_setu_/send_setu/__init__.py
@@ -1,368 +1,368 @@
-import random
-from nonebot import on_command, on_regex
-from services.log import logger
-from models.sign_group_user import SignGroupUser
-from nonebot.message import run_postprocessor
-from nonebot.matcher import Matcher
-from typing import Optional, Type
-from gino.exceptions import UninitializedError
-from utils.utils import (
- is_number,
- get_message_text,
- get_message_imgs,
-)
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import (
- Bot,
- MessageEvent,
- GroupMessageEvent,
- PrivateMessageEvent,
- Message,
- Event,
-)
-from .data_source import (
- get_setu_list,
- get_luoxiang,
- search_online_setu,
- get_setu_urls,
- find_img_index,
- gen_message,
- check_local_exists_or_download,
- add_data_to_database,
- get_setu_count,
-)
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from configs.config import Config, NICKNAME
-from utils.manager import withdraw_message_manager
-import re
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-__zx_plugin_name__ = "色图"
-__plugin_usage__ = f"""
-usage:
- 搜索 lolicon 图库,每日色图time...
- 指令:
- 色图: 随机本地色图
- 色图r: 随机在线十张r18涩图
- 色图 [id]: 本地指定id色图
- 色图 *[tags]: 在线搜索指定tag色图
- 色图r *[tags]: 同上
- [1-9]张涩图: 本地随机色图连发
- [1-9]张[tags]的涩图: 指定tag色图连发
- 示例:色图 萝莉|少女 白丝|黑丝
- 示例:色图 萝莉 猫娘
- 注:
- tag至多取前20项,| 为或,萝莉|少女=萝莉或者少女
-""".strip()
-__plugin_des__ = "不要小看涩图啊混蛋!"
-__plugin_cmd__ = ["色图 ?[id]", "色图 ?[tags]", "色图r ?[tags]", "[1-9]张?[tags]色图"]
-__plugin_type__ = ("来点好康的",)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 9,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["色图", "涩图", "瑟图"],
-}
-__plugin_block_limit__ = {}
-__plugin_cd_limit__ = {
- "rst": "您冲的太快了,请稍后再冲.",
-}
-__plugin_configs__ = {
- "WITHDRAW_SETU_MESSAGE": {
- "value": (0, 1),
- "help": "自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
- "default_value": (0, 1),
- },
- "ONLY_USE_LOCAL_SETU": {
- "value": False,
- "help": "仅仅使用本地色图,不在线搜索",
- "default_value": False,
- },
- "INITIAL_SETU_PROBABILITY": {
- "value": 0.7,
- "help": "初始色图概率,总概率 = 初始色图概率 + 好感度",
- "default_value": 0.7
- },
- "DOWNLOAD_SETU": {
- "value": True,
- "help": "是否存储下载的色图,使用本地色图可以加快图片发送速度",
- "default_value": True
- },
- "TIMEOUT": {
- "value": 10,
- "help": "色图下载超时限制(秒)",
- "default_value": 10
- }
-}
-Config.add_plugin_config(
- "pixiv",
- "PIXIV_NGINX_URL",
- "i.pixiv.re",
- help_="Pixiv反向代理"
-)
-
-setu_data_list = []
-
-
-@run_postprocessor
-async def do_something(
- matcher: Matcher,
- exception: Optional[Exception],
- bot: Bot,
- event: Event,
- state: T_State,
-):
- global setu_data_list
- if isinstance(event, MessageEvent):
- if matcher.module == "send_setu":
- # 添加数据至数据库
- try:
- await add_data_to_database(setu_data_list)
- logger.info("色图数据自动存储数据库成功...")
- setu_data_list = []
- except UninitializedError:
- pass
-
-
-setu = on_command(
- "色图", aliases={"涩图", "不够色", "来一发", "再来点", "色图r"}, priority=5, block=True
-)
-
-setu_reg = on_regex("(.*)[份|发|张|个|次|点](.*)[瑟|色|涩]图$", priority=5, block=True)
-
-find_setu = on_command("查色图", priority=5, block=True)
-
-
-@setu.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if isinstance(event, GroupMessageEvent):
- impression = (
- await SignGroupUser.ensure(event.user_id, event.group_id)
- ).impression
- luox = get_luoxiang(impression)
- if luox:
- await setu.finish(luox)
- r18 = 0
- num = 1
- # 是否看r18
- if state["_prefix"]["raw_command"] == "色图r" and isinstance(
- event, PrivateMessageEvent
- ):
- r18 = 1
- num = 10
- elif state["_prefix"]["raw_command"] == "色图r" and isinstance(
- event, GroupMessageEvent
- ):
- await setu.finish(
- random.choice(["这种不好意思的东西怎么可能给这么多人看啦", "羞羞脸!给我滚出克私聊!", "变态变态变态变态大变态!"])
- )
- # 有 数字 的话先尝试本地色图id
- if msg and is_number(msg):
- setu_list, code = await get_setu_list(int(msg), r18=r18)
- if code != 200:
- await setu.finish(setu_list[0], at_sender=True)
- setu_img, code = await check_local_exists_or_download(setu_list[0])
- msg_id = await setu.send(gen_message(setu_list[0]) + setu_img, at_sender=True)
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送色图 {setu_list[0].local_id}.png"
- )
- if msg_id:
- withdraw_message_manager.withdraw_message(
- event,
- msg_id["message_id"],
- Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
- )
- return
- await send_setu_handle(setu, event, state["_prefix"]["raw_command"], msg, num, r18)
-
-
-num_key = {
- "一": 1,
- "二": 2,
- "两": 2,
- "双": 2,
- "三": 3,
- "四": 4,
- "五": 5,
- "六": 6,
- "七": 7,
- "八": 8,
- "九": 9,
-}
-
-
-@setu_reg.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if isinstance(event, GroupMessageEvent):
- impression = (
- await SignGroupUser.ensure(event.user_id, event.group_id)
- ).impression
- luox = get_luoxiang(impression)
- if luox:
- await setu.finish(luox, at_sender=True)
- msg = get_message_text(event.json())
- num = 1
- msg = re.search(r"(.*)[份发张个次点](.*)[瑟涩色]图", msg)
- # 解析 tags 以及 num
- if msg:
- num = msg.group(1)
- tags = msg.group(2)
- if tags:
- tags = tags[:-1] if tags[-1] == "的" else tags
- if num:
- num = num[-1]
- if num_key.get(num):
- num = num_key[num]
- elif is_number(num):
- try:
- num = int(num)
- except ValueError:
- num = 1
- else:
- num = 1
- else:
- return
- await send_setu_handle(setu_reg, event, "色图", tags, num, 0)
-
-
-@find_setu.args_parser
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if str(event.message) == "取消":
- await find_setu.finish("取消了操作", at_sender=True)
- imgs = get_message_imgs(event.json())
- if not imgs:
- await find_setu.reject("不搞错了,俺要图!")
- state["img"] = imgs[0]
-
-
-@find_setu.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- if get_message_text(event.json()) in ["帮助"]:
- await find_setu.finish("通过图片获取本地色图id\n\t示例:查色图(图片)")
- imgs = get_message_imgs(event.json())
- if imgs:
- state["img"] = imgs[0]
-
-
-@find_setu.got("img", prompt="速速来图!")
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- img = state["img"]
- await find_setu.send(await find_img_index(img, event.user_id), at_sender=True)
-
-
-async def send_setu_handle(
- matcher: Type[Matcher],
- event: MessageEvent,
- command: str,
- msg: str,
- num: int,
- r18: int,
-):
- global setu_data_list
- # 非 id,在线搜索
- tags = msg.split()
- # 真寻的色图?怎么可能
- if f"{NICKNAME}" in tags:
- await matcher.finish("咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀")
- # 本地先拿图,下载失败补上去
- setu_list, code = None, 200
- setu_count = await get_setu_count(r18)
- if (
- not Config.get_config("send_setu", "ONLY_USE_LOCAL_SETU") and tags
- ) or setu_count <= 0:
- # 先尝试获取在线图片
- urls, text_list, add_databases_list, code = await get_setu_urls(
- tags, num, r18, command
- )
- for x in add_databases_list:
- setu_data_list.append(x)
- # 未找到符合的色图,想来本地应该也没有
- if code == 401:
- await setu.finish(urls[0], at_sender=True)
- if code == 200:
- for i in range(len(urls)):
- try:
- setu_img, index = await search_online_setu(urls[i])
- # 下载成功的话
- if index != -1:
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送色图 {index}.png"
- )
- msg_id = await matcher.send(
- Message(f"{text_list[i]}\n{setu_img}")
- )
- else:
- if setu_list is None:
- setu_list, code = await get_setu_list(tags=tags, r18=r18)
- if code != 200:
- await setu.finish(setu_list[0], at_sender=True)
- if setu_list:
- setu_image = random.choice(setu_list)
- setu_list.remove(setu_image)
- msg_id = await matcher.send(
- Message(
- gen_message(setu_image)
- + (
- await check_local_exists_or_download(setu_image)
- )[0]
- )
- )
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送本地色图 {setu_image.local_id}.png"
- )
- else:
- msg_id = await matcher.send(text_list[i] + "\n" + setu_img)
- if msg_id:
- withdraw_message_manager.withdraw_message(
- event,
- msg_id["message_id"],
- Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
- )
- except ActionFailed:
- await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
- return
- if code != 200:
- await matcher.finish("网络连接失败...", at_sender=True)
- # 本地无图
- if setu_list is None:
- setu_list, code = await get_setu_list(tags=tags, r18=r18)
- if code != 200:
- await matcher.finish(setu_list[0], at_sender=True)
- # 开始发图
- for _ in range(num):
- if not setu_list:
- await setu.finish("坏了,已经没图了,被榨干了!")
- setu_image = random.choice(setu_list)
- setu_list.remove(setu_image)
- try:
- msg_id = await matcher.send(
- Message(
- gen_message(setu_image)
- + (await check_local_exists_or_download(setu_image))[0]
- )
- )
- withdraw_message_manager.withdraw_message(
- event,
- msg_id["message_id"],
- Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
- )
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送本地色图 {setu_image.local_id}.png"
- )
- except ActionFailed:
- await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
+import random
+from nonebot import on_command, on_regex
+from services.log import logger
+from models.sign_group_user import SignGroupUser
+from nonebot.message import run_postprocessor
+from nonebot.matcher import Matcher
+from typing import Optional, Type
+from gino.exceptions import UninitializedError
+from utils.utils import (
+ is_number,
+ get_message_text,
+ get_message_imgs,
+)
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ GroupMessageEvent,
+ PrivateMessageEvent,
+ Message,
+ Event,
+)
+from .data_source import (
+ get_setu_list,
+ get_luoxiang,
+ search_online_setu,
+ get_setu_urls,
+ find_img_index,
+ gen_message,
+ check_local_exists_or_download,
+ add_data_to_database,
+ get_setu_count,
+)
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from configs.config import Config, NICKNAME
+from utils.manager import withdraw_message_manager
+import re
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+__zx_plugin_name__ = "色图"
+__plugin_usage__ = f"""
+usage:
+ 搜索 lolicon 图库,每日色图time...
+ 指令:
+ 色图: 随机本地色图
+ 色图r: 随机在线十张r18涩图
+ 色图 [id]: 本地指定id色图
+ 色图 *[tags]: 在线搜索指定tag色图
+ 色图r *[tags]: 同上
+ [1-9]张涩图: 本地随机色图连发
+ [1-9]张[tags]的涩图: 指定tag色图连发
+ 示例:色图 萝莉|少女 白丝|黑丝
+ 示例:色图 萝莉 猫娘
+ 注:
+ tag至多取前20项,| 为或,萝莉|少女=萝莉或者少女
+""".strip()
+__plugin_des__ = "不要小看涩图啊混蛋!"
+__plugin_cmd__ = ["色图 ?[id]", "色图 ?[tags]", "色图r ?[tags]", "[1-9]张?[tags]色图"]
+__plugin_type__ = ("来点好康的",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 9,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["色图", "涩图", "瑟图"],
+}
+__plugin_block_limit__ = {}
+__plugin_cd_limit__ = {
+ "rst": "您冲的太快了,请稍后再冲.",
+}
+__plugin_configs__ = {
+ "WITHDRAW_SETU_MESSAGE": {
+ "value": (0, 1),
+ "help": "自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
+ "default_value": (0, 1),
+ },
+ "ONLY_USE_LOCAL_SETU": {
+ "value": False,
+ "help": "仅仅使用本地色图,不在线搜索",
+ "default_value": False,
+ },
+ "INITIAL_SETU_PROBABILITY": {
+ "value": 0.7,
+ "help": "初始色图概率,总概率 = 初始色图概率 + 好感度",
+ "default_value": 0.7
+ },
+ "DOWNLOAD_SETU": {
+ "value": True,
+ "help": "是否存储下载的色图,使用本地色图可以加快图片发送速度",
+ "default_value": True
+ },
+ "TIMEOUT": {
+ "value": 10,
+ "help": "色图下载超时限制(秒)",
+ "default_value": 10
+ }
+}
+Config.add_plugin_config(
+ "pixiv",
+ "PIXIV_NGINX_URL",
+ "i.pixiv.re",
+ help_="Pixiv反向代理"
+)
+
+setu_data_list = []
+
+
+@run_postprocessor
+async def do_something(
+ matcher: Matcher,
+ exception: Optional[Exception],
+ bot: Bot,
+ event: Event,
+ state: T_State,
+):
+ global setu_data_list
+ if isinstance(event, MessageEvent):
+ if matcher.module == "send_setu":
+ # 添加数据至数据库
+ try:
+ await add_data_to_database(setu_data_list)
+ logger.info("色图数据自动存储数据库成功...")
+ setu_data_list = []
+ except UninitializedError:
+ pass
+
+
+setu = on_command(
+ "色图", aliases={"涩图", "不够色", "来一发", "再来点", "色图r"}, priority=5, block=True
+)
+
+setu_reg = on_regex("(.*)[份|发|张|个|次|点](.*)[瑟|色|涩]图$", priority=5, block=True)
+
+find_setu = on_command("查色图", priority=5, block=True)
+
+
+@setu.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if isinstance(event, GroupMessageEvent):
+ impression = (
+ await SignGroupUser.ensure(event.user_id, event.group_id)
+ ).impression
+ luox = get_luoxiang(impression)
+ if luox:
+ await setu.finish(luox)
+ r18 = 0
+ num = 1
+ # 是否看r18
+ if state["_prefix"]["raw_command"] == "色图r" and isinstance(
+ event, PrivateMessageEvent
+ ):
+ r18 = 1
+ num = 10
+ elif state["_prefix"]["raw_command"] == "色图r" and isinstance(
+ event, GroupMessageEvent
+ ):
+ await setu.finish(
+ random.choice(["这种不好意思的东西怎么可能给这么多人看啦", "羞羞脸!给我滚出克私聊!", "变态变态变态变态大变态!"])
+ )
+ # 有 数字 的话先尝试本地色图id
+ if msg and is_number(msg):
+ setu_list, code = await get_setu_list(int(msg), r18=r18)
+ if code != 200:
+ await setu.finish(setu_list[0], at_sender=True)
+ setu_img, code = await check_local_exists_or_download(setu_list[0])
+ msg_id = await setu.send(gen_message(setu_list[0]) + setu_img, at_sender=True)
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送色图 {setu_list[0].local_id}.png"
+ )
+ if msg_id:
+ withdraw_message_manager.withdraw_message(
+ event,
+ msg_id["message_id"],
+ Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
+ )
+ return
+ await send_setu_handle(setu, event, state["_prefix"]["raw_command"], msg, num, r18)
+
+
+num_key = {
+ "一": 1,
+ "二": 2,
+ "两": 2,
+ "双": 2,
+ "三": 3,
+ "四": 4,
+ "五": 5,
+ "六": 6,
+ "七": 7,
+ "八": 8,
+ "九": 9,
+}
+
+
+@setu_reg.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if isinstance(event, GroupMessageEvent):
+ impression = (
+ await SignGroupUser.ensure(event.user_id, event.group_id)
+ ).impression
+ luox = get_luoxiang(impression)
+ if luox:
+ await setu.finish(luox, at_sender=True)
+ msg = get_message_text(event.json())
+ num = 1
+ msg = re.search(r"(.*)[份发张个次点](.*)[瑟涩色]图", msg)
+ # 解析 tags 以及 num
+ if msg:
+ num = msg.group(1)
+ tags = msg.group(2)
+ if tags:
+ tags = tags[:-1] if tags[-1] == "的" else tags
+ if num:
+ num = num[-1]
+ if num_key.get(num):
+ num = num_key[num]
+ elif is_number(num):
+ try:
+ num = int(num)
+ except ValueError:
+ num = 1
+ else:
+ num = 1
+ else:
+ return
+ await send_setu_handle(setu_reg, event, "色图", tags, num, 0)
+
+
+@find_setu.args_parser
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if str(event.message) == "取消":
+ await find_setu.finish("取消了操作", at_sender=True)
+ imgs = get_message_imgs(event.json())
+ if not imgs:
+ await find_setu.reject("不搞错了,俺要图!")
+ state["img"] = imgs[0]
+
+
+@find_setu.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ if get_message_text(event.json()) in ["帮助"]:
+ await find_setu.finish("通过图片获取本地色图id\n\t示例:查色图(图片)")
+ imgs = get_message_imgs(event.json())
+ if imgs:
+ state["img"] = imgs[0]
+
+
+@find_setu.got("img", prompt="速速来图!")
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ img = state["img"]
+ await find_setu.send(await find_img_index(img, event.user_id), at_sender=True)
+
+
+async def send_setu_handle(
+ matcher: Type[Matcher],
+ event: MessageEvent,
+ command: str,
+ msg: str,
+ num: int,
+ r18: int,
+):
+ global setu_data_list
+ # 非 id,在线搜索
+ tags = msg.split()
+ # 真寻的色图?怎么可能
+ if f"{NICKNAME}" in tags:
+ await matcher.finish("咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀")
+ # 本地先拿图,下载失败补上去
+ setu_list, code = None, 200
+ setu_count = await get_setu_count(r18)
+ if (
+ not Config.get_config("send_setu", "ONLY_USE_LOCAL_SETU") and tags
+ ) or setu_count <= 0:
+ # 先尝试获取在线图片
+ urls, text_list, add_databases_list, code = await get_setu_urls(
+ tags, num, r18, command
+ )
+ for x in add_databases_list:
+ setu_data_list.append(x)
+ # 未找到符合的色图,想来本地应该也没有
+ if code == 401:
+ await setu.finish(urls[0], at_sender=True)
+ if code == 200:
+ for i in range(len(urls)):
+ try:
+ setu_img, index = await search_online_setu(urls[i])
+ # 下载成功的话
+ if index != -1:
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送色图 {index}.png"
+ )
+ msg_id = await matcher.send(
+ Message(f"{text_list[i]}\n{setu_img}")
+ )
+ else:
+ if setu_list is None:
+ setu_list, code = await get_setu_list(tags=tags, r18=r18)
+ if code != 200:
+ await setu.finish(setu_list[0], at_sender=True)
+ if setu_list:
+ setu_image = random.choice(setu_list)
+ setu_list.remove(setu_image)
+ msg_id = await matcher.send(
+ Message(
+ gen_message(setu_image)
+ + (
+ await check_local_exists_or_download(setu_image)
+ )[0]
+ )
+ )
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送本地色图 {setu_image.local_id}.png"
+ )
+ else:
+ msg_id = await matcher.send(text_list[i] + "\n" + setu_img)
+ if msg_id:
+ withdraw_message_manager.withdraw_message(
+ event,
+ msg_id["message_id"],
+ Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
+ )
+ except ActionFailed:
+ await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
+ return
+ if code != 200:
+ await matcher.finish("网络连接失败...", at_sender=True)
+ # 本地无图
+ if setu_list is None:
+ setu_list, code = await get_setu_list(tags=tags, r18=r18)
+ if code != 200:
+ await matcher.finish(setu_list[0], at_sender=True)
+ # 开始发图
+ for _ in range(num):
+ if not setu_list:
+ await setu.finish("坏了,已经没图了,被榨干了!")
+ setu_image = random.choice(setu_list)
+ setu_list.remove(setu_image)
+ try:
+ msg_id = await matcher.send(
+ Message(
+ gen_message(setu_image)
+ + (await check_local_exists_or_download(setu_image))[0]
+ )
+ )
+ withdraw_message_manager.withdraw_message(
+ event,
+ msg_id["message_id"],
+ Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
+ )
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 发送本地色图 {setu_image.local_id}.png"
+ )
+ except ActionFailed:
+ await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
diff --git a/plugins/send_setu_/send_setu/data_source.py b/plugins/send_setu_/send_setu/data_source.py
old mode 100644
new mode 100755
index acb9590f..99732714
--- a/plugins/send_setu_/send_setu/data_source.py
+++ b/plugins/send_setu_/send_setu/data_source.py
@@ -1,278 +1,269 @@
-from configs.path_config import IMAGE_PATH
-from utils.message_builder import image
-from services.log import logger
-from aiohttp.client_exceptions import ClientConnectorError
-from utils.image_utils import get_img_hash, compressed_image
-from asyncpg.exceptions import UniqueViolationError
-from utils.utils import get_local_proxy
-from asyncio.exceptions import TimeoutError
-from typing import List, Optional
-from configs.config import NICKNAME, Config
-from ..model import Setu
-import aiohttp
-import aiofiles
-import asyncio
-import os
-import random
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-url = "https://api.lolicon.app/setu/v2"
-path = "_setu/"
-r18_path = "_r18/"
-
-
-# 获取url
-async def get_setu_urls(
- tags: List[str], num: int = 1, r18: int = 0, command: str = ""
-) -> "List[str], List[str], List[tuple], int":
- tags = tags[:3] if len(tags) > 3 else tags
- params = {
- "r18": r18, # 添加r18参数 0为否,1为是,2为混合
- "tag": tags, # 若指定tag
- "num": 100, # 一次返回的结果数量
- "size": ["original"],
- }
- async with aiohttp.ClientSession() as session:
- for count in range(3):
- logger.info(f"get_setu_url: count --> {count}")
- try:
- async with session.get(
- url, proxy=get_local_proxy(), timeout=Config.get_config("send_setu", "TIMEOUT"), params=params
- ) as response:
- if response.status == 200:
- data = await response.json()
- if not data["error"]:
- data = data["data"]
- (
- urls,
- text_list,
- add_databases_list,
- ) = await asyncio.get_event_loop().run_in_executor(
- None, _setu_data_process, data, command
- )
- num = num if num < len(data) else len(data)
- random_idx = random.sample(range(len(data)), num)
- x_urls = []
- x_text_lst = []
- for x in random_idx:
- x_urls.append(urls[x])
- x_text_lst.append(text_list[x])
- if not x_urls:
- return ["没找到符合条件的色图..."], [], [], 401
- return x_urls, x_text_lst, add_databases_list, 200
- else:
- return ["没找到符合条件的色图..."], [], [], 401
- except (TimeoutError, ClientConnectorError):
- pass
- return ["我网线被人拔了..QAQ"], [], [], 999
-
-
-headers = {
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
- " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
- "Referer": "https://www.pixiv.net",
-}
-
-
-async def search_online_setu(
- url_: str, id_: Optional[int] = None, path_: Optional[str] = None
-) -> "MessageSegment, int":
- """
- 下载色图
- :param url_: 色图url
- :param id_: 本地id
- :param path_: 存储路径
- """
- ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
- if ws_url:
- if ws_url.startswith("http"):
- ws_url = ws_url.split("//")[-1]
- url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
- async with aiohttp.ClientSession(headers=headers) as session:
- for i in range(3):
- logger.info(f"search_online_setu --> {i}")
- try:
- async with session.get(url_, proxy=get_local_proxy(), timeout=Config.get_config("send_setu", "TIMEOUT")) as res:
- if res.status == 200:
- index = random.randint(1, 100000) if id_ is None else id_
- path_ = "temp" if not path_ else path_
- file = f"{index}_temp_setu.jpg" if not path_ else f"{index}.jpg"
- if not os.path.exists(f"{IMAGE_PATH}/{path_}"):
- os.mkdir(f"{IMAGE_PATH}/{path_}")
- async with aiofiles.open(
- f"{IMAGE_PATH}/{path_}/{file}", "wb"
- ) as f:
- try:
- await f.write(await res.read())
- except TimeoutError:
- continue
- if id_ is not None:
- if (
- os.path.getsize(f"{IMAGE_PATH}/{path_}/{index}.jpg")
- > 1024 * 1024 * 1.5
- ):
- compressed_image(
- f"{IMAGE_PATH}/{path_}/{index}.jpg",
- )
- logger.info(f"下载 lolicon图片 {url_} 成功, id:{index}")
- return image(file, path_), index
- else:
- logger.warning(f"访问 lolicon图片 {url_} 失败 status:{res.status}")
- # return '\n这图好难下载啊!QAQ', -1, False
- except (TimeoutError, ClientConnectorError):
- pass
- return "图片被小怪兽恰掉啦..!QAQ", -1
-
-
-# 检测本地是否有id涩图,无的话则下载
-async def check_local_exists_or_download(setu_image: Setu) -> "MessageSegment, int":
- path_ = None
- id_ = None
- if Config.get_config("send_setu", "DOWNLOAD_SETU"):
- id_ = setu_image.local_id
- if setu_image.is_r18:
- path_ = "_r18"
- else:
- path_ = path
- if os.path.exists(f"{IMAGE_PATH}/{path_}/{setu_image.local_id}.jpg"):
- return image(f"{setu_image.local_id}.jpg", path_), 200
- return await search_online_setu(setu_image.img_url, id_, path_)
-
-
-# 添加涩图数据到数据库
-async def add_data_to_database(lst: List[tuple]):
- tmp = []
- for x in lst:
- if x not in tmp:
- tmp.append(x)
- if tmp:
- for x in tmp:
- try:
- r18 = 1 if "R-18" in x[5] else 0
- idx = await Setu.get_image_count(r18)
- await Setu.add_setu_data(
- idx,
- x[0],
- x[1],
- x[2],
- x[3],
- x[4],
- x[5],
- )
- except UniqueViolationError:
- pass
-
-
-# 拿到本地色图列表
-async def get_setu_list(
- index: Optional[int] = None, tags: Optional[List[str]] = None, r18: int = 0
-) -> "list, int":
- if index:
- image_count = await Setu.get_image_count(r18) - 1
- if index < 0 or index > image_count:
- return [f"超过当前上下限!({image_count})"], 999
- image_list = [await Setu.query_image(index, r18=r18)]
- elif tags:
- image_list = await Setu.query_image(tags=tags, r18=r18)
- else:
- image_list = await Setu.query_image(r18=r18)
- if not image_list:
- return ["没找到符合条件的色图..."], 998
- return image_list, 200
-
-
-# 初始化消息
-def gen_message(setu_image: Setu, img_msg: bool = False) -> str:
- local_id = setu_image.local_id
- title = setu_image.title
- author = setu_image.author
- pid = setu_image.pid
- return (
- f"id:{local_id}\n"
- f"title:{title}\n"
- f"author:{author}\n"
- f"PID:{pid}\n"
- f"{image(f'{local_id}', f'{r18_path if setu_image.is_r18 else path}') if img_msg else ''}"
- )
-
-
-# 罗翔老师!
-def get_luoxiang(impression):
- probability = (
- impression + Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
- )
- if probability < random.randint(1, 101):
- return (
- "我为什么要给你发这个?"
- + image(random.choice(os.listdir(IMAGE_PATH + "luoxiang/")), "luoxiang")
- + f"\n(快向{NICKNAME}签到提升好感度吧!)"
- )
- return None
-
-
-async def get_setu_count(r18: int) -> int:
- """
- 获取色图数量
- :param r18: r18类型
- """
- return await Setu.get_image_count(r18)
-
-
-async def find_img_index(img_url, user_id):
- async with aiohttp.ClientSession() as session:
- async with session.get(img_url, proxy=get_local_proxy(), timeout=Config.get_config("send_setu", "TIMEOUT")) as res:
- async with aiofiles.open(
- IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg", "wb"
- ) as f:
- await f.write(await res.read())
- img_hash = str(get_img_hash(IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg"))
- setu_img = await Setu.get_image_in_hash(img_hash)
- if setu_img:
- return (
- f"id:{setu_img.local_id}\n"
- f"title:{setu_img.title}\n"
- f"author:{setu_img.author}\n"
- f"PID:{setu_img.pid}"
- )
- return "该图不在色图库中或色图库未更新!"
-
-
-# 处理色图数据
-def _setu_data_process(data: dict, command: str) -> "list, list, list":
- urls = []
- text_list = []
- add_databases_list = []
- for i in range(len(data)):
- img_url = data[i]["urls"]["original"]
- img_url = (
- img_url.replace("i.pixiv.cat", "i.pximg.net")
- if "i.pixiv.cat" in img_url
- else img_url
- )
- title = data[i]["title"]
- author = data[i]["author"]
- pid = data[i]["pid"]
- urls.append(img_url)
- text_list.append(f"title:{title}\nauthor:{author}\nPID:{pid}")
- tags = []
- for j in range(len(data[i]["tags"])):
- tags.append(data[i]["tags"][j])
- if command != "色图r":
- if "R-18" in tags:
- tags.remove("R-18")
- add_databases_list.append(
- (
- title,
- author,
- pid,
- "",
- img_url,
- ",".join(tags),
- )
- )
- return urls, text_list, add_databases_list
+from configs.path_config import IMAGE_PATH
+from utils.message_builder import image
+from services.log import logger
+from utils.image_utils import get_img_hash, compressed_image
+from asyncpg.exceptions import UniqueViolationError
+from asyncio.exceptions import TimeoutError
+from typing import List, Optional
+from configs.config import NICKNAME, Config
+from utils.http_utils import AsyncHttpx
+from ..model import Setu
+import asyncio
+import os
+import random
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+url = "https://api.lolicon.app/setu/v2"
+path = "_setu/"
+r18_path = "_r18/"
+
+
+# 获取url
+async def get_setu_urls(
+ tags: List[str], num: int = 1, r18: int = 0, command: str = ""
+) -> "List[str], List[str], List[tuple], int":
+ tags = tags[:3] if len(tags) > 3 else tags
+ params = {
+ "r18": r18, # 添加r18参数 0为否,1为是,2为混合
+ "tag": tags, # 若指定tag
+ "num": 100, # 一次返回的结果数量
+ "size": ["original"],
+ }
+ for count in range(3):
+ logger.info(f"get_setu_url: count --> {count}")
+ try:
+ response = await AsyncHttpx.get(
+ url, timeout=Config.get_config("send_setu", "TIMEOUT"), params=params
+ )
+ if response.status_code == 200:
+ data = await response.json()
+ if not data["error"]:
+ data = data["data"]
+ (
+ urls,
+ text_list,
+ add_databases_list,
+ ) = await asyncio.get_event_loop().run_in_executor(
+ None, _setu_data_process, data, command
+ )
+ num = num if num < len(data) else len(data)
+ random_idx = random.sample(range(len(data)), num)
+ x_urls = []
+ x_text_lst = []
+ for x in random_idx:
+ x_urls.append(urls[x])
+ x_text_lst.append(text_list[x])
+ if not x_urls:
+ return ["没找到符合条件的色图..."], [], [], 401
+ return x_urls, x_text_lst, add_databases_list, 200
+ else:
+ return ["没找到符合条件的色图..."], [], [], 401
+ except TimeoutError:
+ pass
+ except Exception as e:
+ logger.error(f"send_setu 访问页面错误 {type(e)}:{e}")
+ return ["我网线被人拔了..QAQ"], [], [], 999
+
+
+headers = {
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
+ " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
+ "Referer": "https://www.pixiv.net",
+}
+
+
+async def search_online_setu(
+ url_: str, id_: Optional[int] = None, path_: Optional[str] = None
+) -> "MessageSegment, int":
+ """
+ 下载色图
+ :param url_: 色图url
+ :param id_: 本地id
+ :param path_: 存储路径
+ """
+ ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
+ if ws_url:
+ url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
+ for i in range(3):
+ logger.info(f"search_online_setu --> {i}")
+ try:
+ index = random.randint(1, 100000) if id_ is None else id_
+ path_ = "temp" if not path_ else path_
+ file = f"{index}_temp_setu.jpg" if not path_ else f"{index}.jpg"
+ if not os.path.exists(f"{IMAGE_PATH}/{path_}"):
+ os.mkdir(f"{IMAGE_PATH}/{path_}")
+ if not await AsyncHttpx.download_file(
+ url_,
+ f"{IMAGE_PATH}/{path_}/{file}",
+ timeout=Config.get_config("send_setu", "TIMEOUT"),
+ ):
+ continue
+ if id_ is not None:
+ if (
+ os.path.getsize(f"{IMAGE_PATH}/{path_}/{index}.jpg")
+ > 1024 * 1024 * 1.5
+ ):
+ compressed_image(
+ f"{IMAGE_PATH}/{path_}/{index}.jpg",
+ )
+ logger.info(f"下载 lolicon图片 {url_} 成功, id:{index}")
+ return image(file, path_), index
+ except TimeoutError:
+ pass
+ except Exception as e:
+ logger.error(f"send_setu 下载图片错误 {type(e)}:{e}")
+ return "图片被小怪兽恰掉啦..!QAQ", -1
+
+
+# 检测本地是否有id涩图,无的话则下载
+async def check_local_exists_or_download(setu_image: Setu) -> "MessageSegment, int":
+ path_ = None
+ id_ = None
+ if Config.get_config("send_setu", "DOWNLOAD_SETU"):
+ id_ = setu_image.local_id
+ if setu_image.is_r18:
+ path_ = "_r18"
+ else:
+ path_ = path
+ if os.path.exists(f"{IMAGE_PATH}/{path_}/{setu_image.local_id}.jpg"):
+ return image(f"{setu_image.local_id}.jpg", path_), 200
+ return await search_online_setu(setu_image.img_url, id_, path_)
+
+
+# 添加涩图数据到数据库
+async def add_data_to_database(lst: List[tuple]):
+ tmp = []
+ for x in lst:
+ if x not in tmp:
+ tmp.append(x)
+ if tmp:
+ for x in tmp:
+ try:
+ r18 = 1 if "R-18" in x[5] else 0
+ idx = await Setu.get_image_count(r18)
+ await Setu.add_setu_data(
+ idx,
+ x[0],
+ x[1],
+ x[2],
+ x[3],
+ x[4],
+ x[5],
+ )
+ except UniqueViolationError:
+ pass
+
+
+# 拿到本地色图列表
+async def get_setu_list(
+ index: Optional[int] = None, tags: Optional[List[str]] = None, r18: int = 0
+) -> "list, int":
+ if index:
+ image_count = await Setu.get_image_count(r18) - 1
+ if index < 0 or index > image_count:
+ return [f"超过当前上下限!({image_count})"], 999
+ image_list = [await Setu.query_image(index, r18=r18)]
+ elif tags:
+ image_list = await Setu.query_image(tags=tags, r18=r18)
+ else:
+ image_list = await Setu.query_image(r18=r18)
+ if not image_list:
+ return ["没找到符合条件的色图..."], 998
+ return image_list, 200
+
+
+# 初始化消息
+def gen_message(setu_image: Setu, img_msg: bool = False) -> str:
+ local_id = setu_image.local_id
+ title = setu_image.title
+ author = setu_image.author
+ pid = setu_image.pid
+ return (
+ f"id:{local_id}\n"
+ f"title:{title}\n"
+ f"author:{author}\n"
+ f"PID:{pid}\n"
+ f"{image(f'{local_id}', f'{r18_path if setu_image.is_r18 else path}') if img_msg else ''}"
+ )
+
+
+# 罗翔老师!
+def get_luoxiang(impression):
+ probability = (
+ impression + Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
+ )
+ if probability < random.randint(1, 101):
+ return (
+ "我为什么要给你发这个?"
+ + image(random.choice(os.listdir(IMAGE_PATH + "luoxiang/")), "luoxiang")
+ + f"\n(快向{NICKNAME}签到提升好感度吧!)"
+ )
+ return None
+
+
+async def get_setu_count(r18: int) -> int:
+ """
+ 获取色图数量
+ :param r18: r18类型
+ """
+ return await Setu.get_image_count(r18)
+
+
+async def find_img_index(img_url, user_id):
+ if not await AsyncHttpx.download_file(
+ img_url,
+ IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg",
+ timeout=Config.get_config("send_setu", "TIMEOUT"),
+ ):
+ return "检索图片下载上失败..."
+ img_hash = str(get_img_hash(IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg"))
+ setu_img = await Setu.get_image_in_hash(img_hash)
+ if setu_img:
+ return (
+ f"id:{setu_img.local_id}\n"
+ f"title:{setu_img.title}\n"
+ f"author:{setu_img.author}\n"
+ f"PID:{setu_img.pid}"
+ )
+ return "该图不在色图库中或色图库未更新!"
+
+
+# 处理色图数据
+def _setu_data_process(data: dict, command: str) -> "list, list, list":
+ urls = []
+ text_list = []
+ add_databases_list = []
+ for i in range(len(data)):
+ img_url = data[i]["urls"]["original"]
+ img_url = (
+ img_url.replace("i.pixiv.cat", "i.pximg.net")
+ if "i.pixiv.cat" in img_url
+ else img_url
+ )
+ title = data[i]["title"]
+ author = data[i]["author"]
+ pid = data[i]["pid"]
+ urls.append(img_url)
+ text_list.append(f"title:{title}\nauthor:{author}\nPID:{pid}")
+ tags = []
+ for j in range(len(data[i]["tags"])):
+ tags.append(data[i]["tags"][j])
+ if command != "色图r":
+ if "R-18" in tags:
+ tags.remove("R-18")
+ add_databases_list.append(
+ (
+ title,
+ author,
+ pid,
+ "",
+ img_url,
+ ",".join(tags),
+ )
+ )
+ return urls, text_list, add_databases_list
diff --git a/plugins/send_setu_/update_setu/__init__.py b/plugins/send_setu_/update_setu/__init__.py
old mode 100644
new mode 100755
index aa048f9b..ff9018b4
--- a/plugins/send_setu_/update_setu/__init__.py
+++ b/plugins/send_setu_/update_setu/__init__.py
@@ -1,48 +1,48 @@
-from utils.utils import scheduler
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.adapters import Bot, Event
-from nonebot.rule import to_me
-from .data_source import update_setu_img
-from configs.config import Config
-
-
-__zx_plugin_name__ = "更新色图 [Superuser]"
-__plugin_usage__ = """
-usage:
- 更新数据库内存在的色图
- 指令:
- 更新色图
-""".strip()
-__plugin_cmd__ = ["更新色图"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_block_limit__ = {
- "rst": "色图正在更新..."
-}
-
-
-update_setu = on_command(
- "更新色图", rule=to_me(), permission=SUPERUSER, priority=1, block=True
-)
-
-
-@update_setu.handle()
-async def _(bot: Bot, event: Event, state: T_State):
- if Config.get_config("send_setu", "DOWNLOAD_SETU"):
- await update_setu.send("开始更新色图...", at_sender=True)
- await update_setu.send(await update_setu_img(), at_sender=True)
- else:
- await update_setu.finish("更新色图配置未开启")
-
-
-# 更新色图
-@scheduler.scheduled_job(
- "cron",
- hour=4,
- minute=30,
-)
-async def _():
- if Config.get_config("send_setu", "DOWNLOAD_SETU"):
- await update_setu_img()
+from utils.utils import scheduler
+from nonebot import on_command
+from nonebot.permission import SUPERUSER
+from nonebot.typing import T_State
+from nonebot.adapters import Bot, Event
+from nonebot.rule import to_me
+from .data_source import update_setu_img
+from configs.config import Config
+
+
+__zx_plugin_name__ = "更新色图 [Superuser]"
+__plugin_usage__ = """
+usage:
+ 更新数据库内存在的色图
+ 指令:
+ 更新色图
+""".strip()
+__plugin_cmd__ = ["更新色图"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_block_limit__ = {
+ "rst": "色图正在更新..."
+}
+
+
+update_setu = on_command(
+ "更新色图", rule=to_me(), permission=SUPERUSER, priority=1, block=True
+)
+
+
+@update_setu.handle()
+async def _(bot: Bot, event: Event, state: T_State):
+ if Config.get_config("send_setu", "DOWNLOAD_SETU"):
+ await update_setu.send("开始更新色图...", at_sender=True)
+ await update_setu.send(await update_setu_img(), at_sender=True)
+ else:
+ await update_setu.finish("更新色图配置未开启")
+
+
+# 更新色图
+@scheduler.scheduled_job(
+ "cron",
+ hour=4,
+ minute=30,
+)
+async def _():
+ if Config.get_config("send_setu", "DOWNLOAD_SETU"):
+ await update_setu_img()
diff --git a/plugins/send_setu_/update_setu/data_source.py b/plugins/send_setu_/update_setu/data_source.py
old mode 100644
new mode 100755
index 92d81355..67d83c43
--- a/plugins/send_setu_/update_setu/data_source.py
+++ b/plugins/send_setu_/update_setu/data_source.py
@@ -1,177 +1,163 @@
-from configs.path_config import IMAGE_PATH, TEXT_PATH, TEMP_PATH
-from services.log import logger
-from datetime import datetime
-from utils.image_utils import compressed_image, get_img_hash
-from utils.utils import get_bot, get_local_proxy
-from asyncio.exceptions import TimeoutError
-from ..model import Setu
-from aiohttp.client_exceptions import ClientConnectorError
-from asyncpg.exceptions import UniqueViolationError
-from configs.config import Config
-from pathlib import Path
-from nonebot import Driver
-import nonebot
-import aiofiles
-import aiohttp
-import os
-import ujson as json
-import shutil
-
-driver: Driver = nonebot.get_driver()
-
-_path = Path(IMAGE_PATH)
-
-
-# 替换旧色图数据,修复local_id一直是50的问题
-@driver.on_startup
-async def update_old_setu_data():
- path = Path(TEXT_PATH)
- setu_data_file = path / "setu_data.json"
- r18_data_file = path / "r18_setu_data.json"
- if setu_data_file.exists() or r18_data_file.exists():
- index = 0
- r18_index = 0
- count = 0
- fail_count = 0
- for file in [setu_data_file, r18_data_file]:
- if file.exists():
- data = json.load(open(file, "r", encoding="utf8"))
- for x in data:
- if file == setu_data_file:
- idx = index
- if 'R-18' in data[x]["tags"]:
- data[x]["tags"].remove('R-18')
- else:
- idx = r18_index
- img_url = (
- data[x]["img_url"].replace("i.pixiv.cat", "i.pximg.net")
- if "i.pixiv.cat" in data[x]["img_url"]
- else data[x]["img_url"]
- )
- # idx = r18_index if 'R-18' in data[x]["tags"] else index
- try:
- await Setu.add_setu_data(
- idx,
- data[x]["title"],
- data[x]["author"],
- data[x]["pid"],
- data[x]["img_hash"],
- img_url,
- ",".join(data[x]["tags"]),
- )
- count += 1
- if 'R-18' in data[x]["tags"]:
- r18_index += 1
- else:
- index += 1
- logger.info(f'添加旧色图数据成功 PID:{data[x]["pid"]} index:{idx}....')
- except UniqueViolationError:
- fail_count += 1
- logger.info(f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....')
- file.unlink()
- setu_url_path = path / "setu_url.json"
- setu_r18_url_path = path / "setu_r18_url.json"
- if setu_url_path.exists():
- setu_url_path.unlink()
- if setu_r18_url_path.exists():
- setu_r18_url_path.unlink()
- logger.info(f"更新旧色图数据完成,成功更新数据:{count} 条,累计失败:{fail_count} 条")
-
-
-# 删除色图rar文件夹
-shutil.rmtree(Path(IMAGE_PATH) / "setu_rar", ignore_errors=True)
-shutil.rmtree(Path(IMAGE_PATH) / "r18_rar", ignore_errors=True)
-shutil.rmtree(Path(IMAGE_PATH) / "rar", ignore_errors=True)
-
-headers = {
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
- " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
- "Referer": "https://www.pixiv.net",
-}
-
-
-async def update_setu_img():
- image_list = await Setu.get_all_setu()
- image_list.reverse()
- _success = 0
- error_info = []
- error_type = []
- count = 0
- async with aiohttp.ClientSession(headers=headers) as session:
- for image in image_list:
- count += 1
- path = _path / "_r18" if image.is_r18 else _path / "_setu"
- rar_path = Path(TEMP_PATH)
- local_image = path / f"{image.local_id}.jpg"
- path.mkdir(exist_ok=True, parents=True)
- rar_path.mkdir(exist_ok=True, parents=True)
- if not local_image.exists() or not image.img_hash:
- url_ = image.img_url
- ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
- if ws_url.startswith("http"):
- ws_url = ws_url.split("//")[-1]
- url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
- for _ in range(3):
- try:
- async with session.get(
- url_, proxy=get_local_proxy(), timeout=30
- ) as response:
- if response.status == 200:
- async with aiofiles.open(
- rar_path / f'{image.local_id}.jpg',
- "wb",
- ) as f:
- await f.write(await response.read())
- _success += 1
- try:
- if (
- os.path.getsize(
- rar_path / f'{image.local_id}.jpg',
- )
- > 1024 * 1024 * 1.5
- ):
- compressed_image(
- rar_path / f"{image.local_id}.jpg",
- path / f"{image.local_id}.jpg"
- )
- else:
- logger.info(
- f"不需要压缩,移动图片{rar_path}/{image.local_id}.jpg "
- f"--> /{path}/{image.local_id}.jpg"
- )
- os.rename(
- f"{rar_path}/{image.local_id}.jpg",
- f"{path}/{image.local_id}.jpg",
- )
- except FileNotFoundError:
- logger.warning(f"文件 {image.local_id}.jpg 不存在,跳过...")
- continue
- img_hash = str(
- get_img_hash(
- f"{path}/{image.local_id}.jpg"
- )
- )
- await Setu.update_setu_data(
- image.pid, img_hash=img_hash
- )
- break
- except (TimeoutError, ClientConnectorError) as e:
- logger.warning(f"{image.local_id}.jpg 更新失败 ..{type(e)}:{e}")
- except Exception as e:
- logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")
- if type(e) not in error_type:
- error_type.append(type(e))
- error_info.append(
- f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}"
- )
- else:
- logger.info(f'更新色图 {image.local_id}.jpg 已存在')
- error_info = ['无报错..'] if not error_info else error_info
- if count or _success or (error_info and "无报错.." not in error_info):
- await get_bot().send_private_msg(
- user_id=int(list(get_bot().config.superusers)[0]),
- message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,本地存在 {count} 张,实际更新 {_success} 张,以下为更新时未知错误:\n'
- + "\n".join(error_info),
- )
-
-
+from configs.path_config import IMAGE_PATH, TEXT_PATH, TEMP_PATH
+from services.log import logger
+from datetime import datetime
+from utils.image_utils import compressed_image, get_img_hash
+from utils.utils import get_bot
+from asyncio.exceptions import TimeoutError
+from ..model import Setu
+from asyncpg.exceptions import UniqueViolationError
+from configs.config import Config
+from utils.http_utils import AsyncHttpx
+from pathlib import Path
+from nonebot import Driver
+import nonebot
+import os
+import ujson as json
+import shutil
+
+driver: Driver = nonebot.get_driver()
+
+_path = Path(IMAGE_PATH)
+
+
+# 替换旧色图数据,修复local_id一直是50的问题
+@driver.on_startup
+async def update_old_setu_data():
+ path = Path(TEXT_PATH)
+ setu_data_file = path / "setu_data.json"
+ r18_data_file = path / "r18_setu_data.json"
+ if setu_data_file.exists() or r18_data_file.exists():
+ index = 0
+ r18_index = 0
+ count = 0
+ fail_count = 0
+ for file in [setu_data_file, r18_data_file]:
+ if file.exists():
+ data = json.load(open(file, "r", encoding="utf8"))
+ for x in data:
+ if file == setu_data_file:
+ idx = index
+ if 'R-18' in data[x]["tags"]:
+ data[x]["tags"].remove('R-18')
+ else:
+ idx = r18_index
+ img_url = (
+ data[x]["img_url"].replace("i.pixiv.cat", "i.pximg.net")
+ if "i.pixiv.cat" in data[x]["img_url"]
+ else data[x]["img_url"]
+ )
+ # idx = r18_index if 'R-18' in data[x]["tags"] else index
+ try:
+ await Setu.add_setu_data(
+ idx,
+ data[x]["title"],
+ data[x]["author"],
+ data[x]["pid"],
+ data[x]["img_hash"],
+ img_url,
+ ",".join(data[x]["tags"]),
+ )
+ count += 1
+ if 'R-18' in data[x]["tags"]:
+ r18_index += 1
+ else:
+ index += 1
+ logger.info(f'添加旧色图数据成功 PID:{data[x]["pid"]} index:{idx}....')
+ except UniqueViolationError:
+ fail_count += 1
+ logger.info(f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....')
+ file.unlink()
+ setu_url_path = path / "setu_url.json"
+ setu_r18_url_path = path / "setu_r18_url.json"
+ if setu_url_path.exists():
+ setu_url_path.unlink()
+ if setu_r18_url_path.exists():
+ setu_r18_url_path.unlink()
+ logger.info(f"更新旧色图数据完成,成功更新数据:{count} 条,累计失败:{fail_count} 条")
+
+
+# 删除色图rar文件夹
+shutil.rmtree(Path(IMAGE_PATH) / "setu_rar", ignore_errors=True)
+shutil.rmtree(Path(IMAGE_PATH) / "r18_rar", ignore_errors=True)
+shutil.rmtree(Path(IMAGE_PATH) / "rar", ignore_errors=True)
+
+headers = {
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
+ " rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
+ "Referer": "https://www.pixiv.net",
+}
+
+
+async def update_setu_img():
+ image_list = await Setu.get_all_setu()
+ image_list.reverse()
+ _success = 0
+ error_info = []
+ error_type = []
+ count = 0
+ for image in image_list:
+ count += 1
+ path = _path / "_r18" if image.is_r18 else _path / "_setu"
+ rar_path = Path(TEMP_PATH)
+ local_image = path / f"{image.local_id}.jpg"
+ path.mkdir(exist_ok=True, parents=True)
+ rar_path.mkdir(exist_ok=True, parents=True)
+ if not local_image.exists() or not image.img_hash:
+ url_ = image.img_url
+ ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
+ if ws_url:
+ url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
+ try:
+ if not await AsyncHttpx.download_file(url_, rar_path / f'{image.local_id}.jpg'):
+ continue
+ _success += 1
+ try:
+ if (
+ os.path.getsize(
+ rar_path / f'{image.local_id}.jpg',
+ )
+ > 1024 * 1024 * 1.5
+ ):
+ compressed_image(
+ rar_path / f"{image.local_id}.jpg",
+ path / f"{image.local_id}.jpg"
+ )
+ else:
+ logger.info(
+ f"不需要压缩,移动图片{rar_path}/{image.local_id}.jpg "
+ f"--> /{path}/{image.local_id}.jpg"
+ )
+ os.rename(
+ f"{rar_path}/{image.local_id}.jpg",
+ f"{path}/{image.local_id}.jpg",
+ )
+ except FileNotFoundError:
+ logger.warning(f"文件 {image.local_id}.jpg 不存在,跳过...")
+ continue
+ img_hash = str(
+ get_img_hash(
+ f"{path}/{image.local_id}.jpg"
+ )
+ )
+ await Setu.update_setu_data(
+ image.pid, img_hash=img_hash
+ )
+ except Exception as e:
+ _success -= 1
+ logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")
+ if type(e) not in error_type:
+ error_type.append(type(e))
+ error_info.append(
+ f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}"
+ )
+ else:
+ logger.info(f'更新色图 {image.local_id}.jpg 已存在')
+ error_info = ['无报错..'] if not error_info else error_info
+ if count or _success or (error_info and "无报错.." not in error_info):
+ await get_bot().send_private_msg(
+ user_id=int(list(get_bot().config.superusers)[0]),
+ message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,本地存在 {count} 张,实际更新 {_success} 张,以下为更新时未知错误:\n'
+ + "\n".join(error_info),
+ )
+
+
diff --git a/plugins/shop/__init__.py b/plugins/shop/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/buy.py b/plugins/shop/buy.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/gold.py b/plugins/shop/gold.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/models/__init__.py b/plugins/shop/models/__init__.py
old mode 100644
new mode 100755
index db1ab9ef..8a0c62fb
--- a/plugins/shop/models/__init__.py
+++ b/plugins/shop/models/__init__.py
@@ -1 +1 @@
-from .goods_info import *
+from .goods_info import *
diff --git a/plugins/shop/models/goods_info.py b/plugins/shop/models/goods_info.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/my_props.py b/plugins/shop/my_props.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/reset_today_gold.py b/plugins/shop/reset_today_gold.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/shop_handle/__init__.py b/plugins/shop/shop_handle/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/shop_handle/data_source.py b/plugins/shop/shop_handle/data_source.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/use/__init__.py b/plugins/shop/use/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/shop/use/data_source.py b/plugins/shop/use/data_source.py
old mode 100644
new mode 100755
diff --git a/plugins/sign_in/__init__.py b/plugins/sign_in/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/sign_in/config.py b/plugins/sign_in/config.py
old mode 100644
new mode 100755
index 68232954..1bfa7a30
--- a/plugins/sign_in/config.py
+++ b/plugins/sign_in/config.py
@@ -1,65 +1,65 @@
-from configs.path_config import IMAGE_PATH
-from pathlib import Path
-
-
-SIGN_RESOURCE_PATH = Path(IMAGE_PATH) / 'sign' / 'sign_res'
-SIGN_TODAY_CARD_PATH = Path(IMAGE_PATH) / 'sign' / 'today_card'
-SIGN_BORDER_PATH = Path(SIGN_RESOURCE_PATH) / 'border'
-SIGN_BACKGROUND_PATH = Path(SIGN_RESOURCE_PATH) / 'background'
-
-SIGN_BORDER_PATH.mkdir(exist_ok=True, parents=True)
-SIGN_BACKGROUND_PATH.mkdir(exist_ok=True, parents=True)
-
-
-lik2relation = {
- '0': '路人',
- '1': '陌生',
- '2': '初识',
- '3': '普通',
- '4': '熟悉',
- '5': '信赖',
- '6': '相知',
- '7': '厚谊',
- '8': '亲密'
-}
-
-level2attitude = {
- '0': '排斥',
- '1': '警惕',
- '2': '可以交流',
- '3': '一般',
- '4': '是个好人',
- '5': '好朋友',
- '6': '可以分享小秘密',
- '7': '喜欢',
- '8': '恋人'
-}
-
-weekdays = {
- 1: 'Mon',
- 2: 'Tue',
- 3: 'Wed',
- 4: 'Thu',
- 5: 'Fri',
- 6: 'Sat',
- 7: 'Sun'
-}
-
-lik2level = {
- 9999: '9',
- 400: '8',
- 270: '7',
- 200: '6',
- 140: '5',
- 90: '4',
- 50: '3',
- 25: '2',
- 10: '1',
- 0: '0'
-}
-
-
-
-
-
-
+from configs.path_config import IMAGE_PATH
+from pathlib import Path
+
+
+SIGN_RESOURCE_PATH = Path(IMAGE_PATH) / 'sign' / 'sign_res'
+SIGN_TODAY_CARD_PATH = Path(IMAGE_PATH) / 'sign' / 'today_card'
+SIGN_BORDER_PATH = Path(SIGN_RESOURCE_PATH) / 'border'
+SIGN_BACKGROUND_PATH = Path(SIGN_RESOURCE_PATH) / 'background'
+
+SIGN_BORDER_PATH.mkdir(exist_ok=True, parents=True)
+SIGN_BACKGROUND_PATH.mkdir(exist_ok=True, parents=True)
+
+
+lik2relation = {
+ '0': '路人',
+ '1': '陌生',
+ '2': '初识',
+ '3': '普通',
+ '4': '熟悉',
+ '5': '信赖',
+ '6': '相知',
+ '7': '厚谊',
+ '8': '亲密'
+}
+
+level2attitude = {
+ '0': '排斥',
+ '1': '警惕',
+ '2': '可以交流',
+ '3': '一般',
+ '4': '是个好人',
+ '5': '好朋友',
+ '6': '可以分享小秘密',
+ '7': '喜欢',
+ '8': '恋人'
+}
+
+weekdays = {
+ 1: 'Mon',
+ 2: 'Tue',
+ 3: 'Wed',
+ 4: 'Thu',
+ 5: 'Fri',
+ 6: 'Sat',
+ 7: 'Sun'
+}
+
+lik2level = {
+ 9999: '9',
+ 400: '8',
+ 270: '7',
+ 200: '6',
+ 140: '5',
+ 90: '4',
+ 50: '3',
+ 25: '2',
+ 10: '1',
+ 0: '0'
+}
+
+
+
+
+
+
diff --git a/plugins/sign_in/group_user_checkin.py b/plugins/sign_in/group_user_checkin.py
old mode 100644
new mode 100755
index 18150ab4..990b053a
--- a/plugins/sign_in/group_user_checkin.py
+++ b/plugins/sign_in/group_user_checkin.py
@@ -4,7 +4,6 @@ from models.group_member_info import GroupInfoUser
from models.bag_user import BagUser
from configs.config import NICKNAME
from nonebot.adapters.cqhttp import MessageSegment
-from asyncio.exceptions import TimeoutError
from utils.image_utils import CreateImg, CreateMat
from services.db_context import db
from .utils import get_card, SIGN_TODAY_CARD_PATH
@@ -12,9 +11,9 @@ from typing import Optional
from services.log import logger
from .random_event import random_event
from utils.data_utils import init_rank
+from utils.utils import get_user_avatar
from io import BytesIO
import random
-import aiohttp
import math
import asyncio
import secrets
@@ -142,47 +141,44 @@ async def _pst(users: list, impressions: list, groups: list):
width = 10
idx = 0
A = CreateImg(1740, 3300, color="#FFE4C4")
- async with aiohttp.ClientSession() as session:
- for _ in range(count):
- col_img = CreateImg(550, 3300, 550, 100, color="#FFE4C4")
- for _ in range(33 if int(lens / 33) >= 1 else lens % 33 - 1):
- idx += 1
- if idx > 100:
- break
- impression = max(impressions)
- index = impressions.index(impression)
- user = users[index]
- group = groups[index]
- impressions.pop(index)
- users.pop(index)
- groups.pop(index)
- try:
- user_name = (
- await GroupInfoUser.get_member_info(user, group)
- ).user_name
- except AttributeError:
- user_name = f"我名字呢?"
- user_name = user_name if len(user_name) < 11 else user_name[:10] + "..."
- try:
- async with session.get(
- f"http://q1.qlogo.cn/g?b=qq&nk={user}&s=160", timeout=5
- ) as response:
- ava = CreateImg(
- 50, 50, background=BytesIO(await response.read())
- )
- except TimeoutError:
- ava = CreateImg(50, 50, color="white")
- ava.circle()
- bk = CreateImg(550, 100, color="#FFE4C4", font_size=30)
- font_w, font_h = bk.getsize(f"{idx}")
- bk.text((5, int((100 - font_h) / 2)), f"{idx}.")
- bk.paste(ava, (55, int((100 - 50) / 2)), True)
- bk.text((120, int((100 - font_h) / 2)), f"{user_name}")
- bk.text((460, int((100 - font_h) / 2)), f"[{impression:.2f}]")
- col_img.paste(bk)
- A.paste(col_img, (width, 0))
- lens -= 33
- width += 580
+ for _ in range(count):
+ col_img = CreateImg(550, 3300, 550, 100, color="#FFE4C4")
+ for _ in range(33 if int(lens / 33) >= 1 else lens % 33 - 1):
+ idx += 1
+ if idx > 100:
+ break
+ impression = max(impressions)
+ index = impressions.index(impression)
+ user = users[index]
+ group = groups[index]
+ impressions.pop(index)
+ users.pop(index)
+ groups.pop(index)
+ try:
+ user_name = (
+ await GroupInfoUser.get_member_info(user, group)
+ ).user_name
+ except AttributeError:
+ user_name = f"我名字呢?"
+ user_name = user_name if len(user_name) < 11 else user_name[:10] + "..."
+ ava = await get_user_avatar(user)
+ if ava:
+ ava = CreateImg(
+ 50, 50, background=BytesIO(ava)
+ )
+ else:
+ ava = CreateImg(50, 50, color="white")
+ ava.circle()
+ bk = CreateImg(550, 100, color="#FFE4C4", font_size=30)
+ font_w, font_h = bk.getsize(f"{idx}")
+ bk.text((5, int((100 - font_h) / 2)), f"{idx}.")
+ bk.paste(ava, (55, int((100 - 50) / 2)), True)
+ bk.text((120, int((100 - font_h) / 2)), f"{user_name}")
+ bk.text((460, int((100 - font_h) / 2)), f"[{impression:.2f}]")
+ col_img.paste(bk)
+ A.paste(col_img, (width, 0))
+ lens -= 33
+ width += 580
W = CreateImg(1740, 3700, color="#FFE4C4", font_size=130)
W.paste(A, (0, 260))
font_w, font_h = W.getsize(f"{NICKNAME}的好感度总榜")
diff --git a/plugins/sign_in/random_event.py b/plugins/sign_in/random_event.py
old mode 100644
new mode 100755
index c5ea35a8..22d799c0
--- a/plugins/sign_in/random_event.py
+++ b/plugins/sign_in/random_event.py
@@ -1,33 +1,33 @@
-from configs.config import Config
-import random
-
-
-PROB_DATA = None
-
-
-def random_event(impression: float) -> 'Union[str, int], str':
- """
- 签到随机事件
- :param impression: 好感度
- :return: 额外奖励 和 类型
- """
- global PROB_DATA
- if not PROB_DATA:
- PROB_DATA = {
- Config.get_config("sign_in", "SIGN_CARD3_PROB"): '好感度双倍加持卡Ⅲ',
- Config.get_config("sign_in", "SIGN_CARD2_PROB"): '好感度双倍加持卡Ⅱ',
- Config.get_config("sign_in", "SIGN_CARD1_PROB"): '好感度双倍加持卡Ⅰ'
- }
- rand = random.random() - impression / 1000
- for prob in PROB_DATA.keys():
- if rand <= prob:
- return PROB_DATA[prob], 'props'
- gold = random.randint(1, random.randint(1, int(1 if impression < 1 else impression)))
- max_sign_gold = Config.get_config("sign_in", "MAX_SIGN_GOLD")
- gold = max_sign_gold if gold > max_sign_gold else gold
- return gold, 'gold'
-
-
-
-
-
+from configs.config import Config
+import random
+
+
+PROB_DATA = None
+
+
+def random_event(impression: float) -> 'Union[str, int], str':
+ """
+ 签到随机事件
+ :param impression: 好感度
+ :return: 额外奖励 和 类型
+ """
+ global PROB_DATA
+ if not PROB_DATA:
+ PROB_DATA = {
+ Config.get_config("sign_in", "SIGN_CARD3_PROB"): '好感度双倍加持卡Ⅲ',
+ Config.get_config("sign_in", "SIGN_CARD2_PROB"): '好感度双倍加持卡Ⅱ',
+ Config.get_config("sign_in", "SIGN_CARD1_PROB"): '好感度双倍加持卡Ⅰ'
+ }
+ rand = random.random() - impression / 1000
+ for prob in PROB_DATA.keys():
+ if rand <= prob:
+ return PROB_DATA[prob], 'props'
+ gold = random.randint(1, random.randint(1, int(1 if impression < 1 else impression)))
+ max_sign_gold = Config.get_config("sign_in", "MAX_SIGN_GOLD")
+ gold = max_sign_gold if gold > max_sign_gold else gold
+ return gold, 'gold'
+
+
+
+
+
diff --git a/plugins/sign_in/utils.py b/plugins/sign_in/utils.py
old mode 100644
new mode 100755
index 2bffa5ea..4f5a8fb0
--- a/plugins/sign_in/utils.py
+++ b/plugins/sign_in/utils.py
@@ -1,352 +1,352 @@
-from .config import (
- SIGN_RESOURCE_PATH,
- SIGN_TODAY_CARD_PATH,
- SIGN_BORDER_PATH,
- SIGN_BACKGROUND_PATH,
- lik2level,
- lik2relation,
- level2attitude,
- weekdays,
-)
-from models.sign_group_user import SignGroupUser
-from models.group_member_info import GroupInfoUser
-from nonebot.adapters.cqhttp import MessageSegment
-from utils.utils import get_user_avatar
-from utils.image_utils import CreateImg
-from utils.message_builder import image
-from configs.config import NICKNAME
-from pathlib import Path
-from datetime import datetime
-from typing import Optional, List
-from nonebot import Driver
-from io import BytesIO
-import asyncio
-import random
-import nonebot
-import os
-
-
-driver: Driver = nonebot.get_driver()
-
-
-@driver.on_startup
-async def init_image():
- SIGN_RESOURCE_PATH.mkdir(parents=True, exist_ok=True)
- SIGN_TODAY_CARD_PATH.mkdir(exist_ok=True, parents=True)
- await GroupInfoUser.add_member_info(114514, 114514, "", datetime.min, 0)
- _u = await GroupInfoUser.get_member_info(114514, 114514)
- if _u.uid is None:
- await _u.update(uid=0).apply()
- generate_progress_bar_pic()
- clear_sign_data_pic()
-
-
-async def get_card(
- user: "SignGroupUser",
- nickname: str,
- add_impression: Optional[float],
- gold: Optional[int],
- gift: str,
- is_double: bool = False,
- is_card_view: bool = False,
-) -> MessageSegment:
- user_id = user.user_qq
- date = datetime.now().date()
- _type = "view" if is_card_view else "sign"
- card_file = (
- Path(SIGN_TODAY_CARD_PATH)
- / f"{user_id}_{user.belonging_group}_{_type}_{date}.png"
- )
- if card_file.exists():
- return image(
- f"{user_id}_{user.belonging_group}_{_type}_{date}.png", "sign/today_card"
- )
- else:
- if add_impression == -1:
- card_file = (
- Path(SIGN_TODAY_CARD_PATH)
- / f"{user_id}_{user.belonging_group}_view_{date}.png"
- )
- if card_file.exists():
- return image(
- f"{user_id}_{user.belonging_group}_view_{date}.png",
- "sign/today_card",
- )
- is_card_view = True
- ava = BytesIO(await get_user_avatar(user_id))
- uid = await GroupInfoUser.get_group_member_uid(
- user.user_qq, user.belonging_group
- )
- impression_list = None
- if is_card_view:
- _, impression_list, _ = await SignGroupUser.get_all_impression(
- user.belonging_group
- )
- return await asyncio.get_event_loop().run_in_executor(
- None,
- _generate_card,
- user,
- nickname,
- user_id,
- add_impression,
- gold,
- gift,
- uid,
- ava,
- impression_list,
- is_double,
- is_card_view,
- )
-
-
-def _generate_card(
- user: "SignGroupUser",
- nickname: str,
- user_id: int,
- impression: Optional[float],
- gold: Optional[int],
- gift: str,
- uid: str,
- ava_bytes: BytesIO,
- impression_list: List[float],
- is_double: bool = False,
- is_card_view: bool = False,
-) -> MessageSegment:
- ava_bk = CreateImg(140, 140, is_alpha=True)
- ava_border = CreateImg(
- 140,
- 140,
- background=SIGN_BORDER_PATH / "ava_border_01.png",
- )
- ava = CreateImg(102, 102, background=ava_bytes)
- ava.circle()
- ava_bk.paste(ava, center_type="center")
- ava_bk.paste(ava_border, alpha=True, center_type="center")
-
- info_img = CreateImg(250, 150, color=(255, 255, 255, 0), font_size=15)
- level, next_impression, previous_impression = get_level_and_next_impression(
- user.impression
- )
- info_img.text((0, 0), f"· 好感度等级:{level} [{lik2relation[level]}]")
- info_img.text((0, 20), f"· {NICKNAME}对你的态度:{level2attitude[level]}")
- info_img.text((0, 40), f"· 距离升级还差 {next_impression - user.impression:.2f} 好感度")
-
- bar_bk = CreateImg(220, 20, background=SIGN_RESOURCE_PATH / "bar_white.png")
- bar = CreateImg(220, 20, background=SIGN_RESOURCE_PATH / "bar.png")
- bar_bk.paste(
- bar,
- (
- -int(
- 220
- * (
- (next_impression - user.impression)
- / (next_impression - previous_impression)
- )
- ),
- 0,
- ),
- True,
- )
- font_size = 30
- if "好感度双倍加持卡" in gift:
- font_size = 20
- gift_border = CreateImg(
- 270,
- 100,
- background=SIGN_BORDER_PATH / "gift_border_02.png",
- font_size=font_size,
- )
- gift_border.text((0, 0), gift, center_type="center")
-
- bk = CreateImg(
- 876,
- 424,
- background=SIGN_BACKGROUND_PATH
- / random.choice(os.listdir(SIGN_BACKGROUND_PATH)),
- font_size=25,
- )
- A = CreateImg(876, 274, background=SIGN_RESOURCE_PATH / "white.png")
- line = CreateImg(2, 180, color="black")
- A.transparent(2)
- A.paste(ava_bk, (25, 80), True)
- A.paste(line, (200, 70))
-
- nickname_img = CreateImg(
- 0,
- 0,
- plain_text=nickname,
- color=(255, 255, 255, 0),
- font_size=50,
- font_color=(255, 255, 255),
- )
- if uid:
- uid = f"{uid}".rjust(12, "0")
- uid = uid[:4] + " " + uid[4:8] + " " + uid[8:]
- else:
- uid = "XXXX XXXX XXXX"
- uid_img = CreateImg(
- 0,
- 0,
- plain_text=f"UID: {uid}",
- color=(255, 255, 255, 0),
- font_size=30,
- font_color=(255, 255, 255),
- )
- sign_day_img = CreateImg(
- 0,
- 0,
- plain_text=f"{user.checkin_count}",
- color=(255, 255, 255, 0),
- font_size=40,
- font_color=(211, 64, 33),
- )
- lik_text1_img = CreateImg(
- 0, 0, plain_text="当前", color=(255, 255, 255, 0), font_size=20
- )
- lik_text2_img = CreateImg(
- 0,
- 0,
- plain_text=f"好感度:{user.impression:.2f}",
- color=(255, 255, 255, 0),
- font_size=30,
- )
- watermark = CreateImg(
- 0,
- 0,
- plain_text=f"{NICKNAME}@{datetime.now().year}",
- color=(255, 255, 255, 0),
- font_size=15,
- font_color=(155, 155, 155),
- )
- today_data = CreateImg(300, 300, color=(255, 255, 255, 0), font_size=20)
- if is_card_view:
- today_sign_text_img = CreateImg(
- 0, 0, plain_text="", color=(255, 255, 255, 0), font_size=30
- )
- if impression_list:
- impression_list.sort(reverse=True)
- index = impression_list.index(user.impression)
- rank_img = CreateImg(
- 0,
- 0,
- plain_text=f"* 此群好感排名第 {index + 1} 位",
- color=(255, 255, 255, 0),
- font_size=30,
- )
- A.paste(rank_img, ((A.w - rank_img.w - 10), 20), True)
- today_data.text(
- (0, 0),
- f"上次签到日期:{'从未' if user.checkin_time_last == datetime.min else user.checkin_time_last.date()}",
- )
- today_data.text((0, 25), f"总金币:{gold}")
- today_data.text(
- (0, 50),
- f"色图概率:{(70 + user.impression if user.impression < 100 else 100):.2f}%",
- )
- today_data.text((0, 75), f"开箱次数:{(20 + int(user.impression / 3))}")
- _type = "view"
- else:
- A.paste(gift_border, (570, 140), True)
- today_sign_text_img = CreateImg(
- 0, 0, plain_text="今日签到", color=(255, 255, 255, 0), font_size=30
- )
- if is_double:
- today_data.text((0, 0), f"好感度 + {impression / 2:.2f} × 2")
- else:
- today_data.text((0, 0), f"好感度 + {impression:.2f}")
- today_data.text((0, 25), f"金币 + {gold}")
- _type = "sign"
- current_date = datetime.now()
- week = current_date.isoweekday()
- data = current_date.date()
- hour = current_date.hour
- minute = current_date.minute
- second = current_date.second
- data_img = CreateImg(
- 0,
- 0,
- plain_text=f"时间:{data} {weekdays[week]} {hour}:{minute}:{second}",
- color=(255, 255, 255, 0),
- font_size=20,
- )
- bk.paste(nickname_img, (30, 15), True)
- bk.paste(uid_img, (30, 85), True)
- bk.paste(A, (0, 150), alpha=True)
- bk.text((30, 167), "Accumulative check-in for")
- _x = bk.getsize("Accumulative check-in for")[0] + sign_day_img.w + 45
- bk.paste(sign_day_img, (346, 158), True)
- bk.text((_x, 167), "days")
- bk.paste(data_img, (220, 370), True)
- bk.paste(lik_text1_img, (220, 240), True)
- bk.paste(lik_text2_img, (262, 234), True)
- bk.paste(bar_bk, (225, 275), True)
- bk.paste(info_img, (220, 305), True)
- bk.paste(today_sign_text_img, (550, 180), True)
- bk.paste(today_data, (580, 220), True)
- bk.paste(watermark, (15, 400), True)
- bk.save(
- SIGN_TODAY_CARD_PATH / f"{user_id}_{user.belonging_group}_{_type}_{data}.png"
- )
- return image(
- f"{user_id}_{user.belonging_group}_{_type}_{data}.png", "sign/today_card"
- )
-
-
-def generate_progress_bar_pic():
- bg_2 = (254, 1, 254)
- bg_1 = (0, 245, 246)
-
- bk = CreateImg(1000, 50, is_alpha=True)
- img_x = CreateImg(50, 50, color=bg_2)
- img_x.circle()
- img_x.crop((25, 0, 50, 50))
- img_y = CreateImg(50, 50, color=bg_1)
- img_y.circle()
- img_y.crop((0, 0, 25, 50))
- A = CreateImg(950, 50)
- width, height = A.size
-
- step_r = (bg_2[0] - bg_1[0]) / width
- step_g = (bg_2[1] - bg_1[1]) / width
- step_b = (bg_2[2] - bg_1[2]) / width
-
- for y in range(0, width):
- bg_r = round(bg_1[0] + step_r * y)
- bg_g = round(bg_1[1] + step_g * y)
- bg_b = round(bg_1[2] + step_b * y)
- for x in range(0, height):
- A.point((y, x), fill=(bg_r, bg_g, bg_b))
- bk.paste(img_y, (0, 0), True)
- bk.paste(A, (25, 0))
- bk.paste(img_x, (975, 0), True)
- bk.save(SIGN_RESOURCE_PATH / "bar.png")
-
- A = CreateImg(950, 50)
- bk = CreateImg(1000, 50, is_alpha=True)
- img_x = CreateImg(50, 50)
- img_x.circle()
- img_x.crop((25, 0, 50, 50))
- img_y = CreateImg(50, 50)
- img_y.circle()
- img_y.crop((0, 0, 25, 50))
- bk.paste(img_y, (0, 0), True)
- bk.paste(A, (25, 0))
- bk.paste(img_x, (975, 0), True)
- bk.save(SIGN_RESOURCE_PATH / "bar_white.png")
-
-
-def get_level_and_next_impression(impression: float):
- if impression == 0:
- return lik2level[10], 10, 0
- keys = list(lik2level.keys())
- for i in range(len(keys)):
- if impression > keys[i]:
- return lik2level[keys[i]], keys[i - 1], keys[i]
- return lik2level[10], 10, 0
-
-
-def clear_sign_data_pic():
- date = datetime.now().date()
- for file in os.listdir(SIGN_TODAY_CARD_PATH):
- if str(date) not in file:
- os.remove(SIGN_TODAY_CARD_PATH / file)
+from .config import (
+ SIGN_RESOURCE_PATH,
+ SIGN_TODAY_CARD_PATH,
+ SIGN_BORDER_PATH,
+ SIGN_BACKGROUND_PATH,
+ lik2level,
+ lik2relation,
+ level2attitude,
+ weekdays,
+)
+from models.sign_group_user import SignGroupUser
+from models.group_member_info import GroupInfoUser
+from nonebot.adapters.cqhttp import MessageSegment
+from utils.utils import get_user_avatar
+from utils.image_utils import CreateImg
+from utils.message_builder import image
+from configs.config import NICKNAME
+from pathlib import Path
+from datetime import datetime
+from typing import Optional, List
+from nonebot import Driver
+from io import BytesIO
+import asyncio
+import random
+import nonebot
+import os
+
+
+driver: Driver = nonebot.get_driver()
+
+
+@driver.on_startup
+async def init_image():
+ SIGN_RESOURCE_PATH.mkdir(parents=True, exist_ok=True)
+ SIGN_TODAY_CARD_PATH.mkdir(exist_ok=True, parents=True)
+ await GroupInfoUser.add_member_info(114514, 114514, "", datetime.min, 0)
+ _u = await GroupInfoUser.get_member_info(114514, 114514)
+ if _u.uid is None:
+ await _u.update(uid=0).apply()
+ generate_progress_bar_pic()
+ clear_sign_data_pic()
+
+
+async def get_card(
+ user: "SignGroupUser",
+ nickname: str,
+ add_impression: Optional[float],
+ gold: Optional[int],
+ gift: str,
+ is_double: bool = False,
+ is_card_view: bool = False,
+) -> MessageSegment:
+ user_id = user.user_qq
+ date = datetime.now().date()
+ _type = "view" if is_card_view else "sign"
+ card_file = (
+ Path(SIGN_TODAY_CARD_PATH)
+ / f"{user_id}_{user.belonging_group}_{_type}_{date}.png"
+ )
+ if card_file.exists():
+ return image(
+ f"{user_id}_{user.belonging_group}_{_type}_{date}.png", "sign/today_card"
+ )
+ else:
+ if add_impression == -1:
+ card_file = (
+ Path(SIGN_TODAY_CARD_PATH)
+ / f"{user_id}_{user.belonging_group}_view_{date}.png"
+ )
+ if card_file.exists():
+ return image(
+ f"{user_id}_{user.belonging_group}_view_{date}.png",
+ "sign/today_card",
+ )
+ is_card_view = True
+ ava = BytesIO(await get_user_avatar(user_id))
+ uid = await GroupInfoUser.get_group_member_uid(
+ user.user_qq, user.belonging_group
+ )
+ impression_list = None
+ if is_card_view:
+ _, impression_list, _ = await SignGroupUser.get_all_impression(
+ user.belonging_group
+ )
+ return await asyncio.get_event_loop().run_in_executor(
+ None,
+ _generate_card,
+ user,
+ nickname,
+ user_id,
+ add_impression,
+ gold,
+ gift,
+ uid,
+ ava,
+ impression_list,
+ is_double,
+ is_card_view,
+ )
+
+
+def _generate_card(
+ user: "SignGroupUser",
+ nickname: str,
+ user_id: int,
+ impression: Optional[float],
+ gold: Optional[int],
+ gift: str,
+ uid: str,
+ ava_bytes: BytesIO,
+ impression_list: List[float],
+ is_double: bool = False,
+ is_card_view: bool = False,
+) -> MessageSegment:
+ ava_bk = CreateImg(140, 140, is_alpha=True)
+ ava_border = CreateImg(
+ 140,
+ 140,
+ background=SIGN_BORDER_PATH / "ava_border_01.png",
+ )
+ ava = CreateImg(102, 102, background=ava_bytes)
+ ava.circle()
+ ava_bk.paste(ava, center_type="center")
+ ava_bk.paste(ava_border, alpha=True, center_type="center")
+
+ info_img = CreateImg(250, 150, color=(255, 255, 255, 0), font_size=15)
+ level, next_impression, previous_impression = get_level_and_next_impression(
+ user.impression
+ )
+ info_img.text((0, 0), f"· 好感度等级:{level} [{lik2relation[level]}]")
+ info_img.text((0, 20), f"· {NICKNAME}对你的态度:{level2attitude[level]}")
+ info_img.text((0, 40), f"· 距离升级还差 {next_impression - user.impression:.2f} 好感度")
+
+ bar_bk = CreateImg(220, 20, background=SIGN_RESOURCE_PATH / "bar_white.png")
+ bar = CreateImg(220, 20, background=SIGN_RESOURCE_PATH / "bar.png")
+ bar_bk.paste(
+ bar,
+ (
+ -int(
+ 220
+ * (
+ (next_impression - user.impression)
+ / (next_impression - previous_impression)
+ )
+ ),
+ 0,
+ ),
+ True,
+ )
+ font_size = 30
+ if "好感度双倍加持卡" in gift:
+ font_size = 20
+ gift_border = CreateImg(
+ 270,
+ 100,
+ background=SIGN_BORDER_PATH / "gift_border_02.png",
+ font_size=font_size,
+ )
+ gift_border.text((0, 0), gift, center_type="center")
+
+ bk = CreateImg(
+ 876,
+ 424,
+ background=SIGN_BACKGROUND_PATH
+ / random.choice(os.listdir(SIGN_BACKGROUND_PATH)),
+ font_size=25,
+ )
+ A = CreateImg(876, 274, background=SIGN_RESOURCE_PATH / "white.png")
+ line = CreateImg(2, 180, color="black")
+ A.transparent(2)
+ A.paste(ava_bk, (25, 80), True)
+ A.paste(line, (200, 70))
+
+ nickname_img = CreateImg(
+ 0,
+ 0,
+ plain_text=nickname,
+ color=(255, 255, 255, 0),
+ font_size=50,
+ font_color=(255, 255, 255),
+ )
+ if uid:
+ uid = f"{uid}".rjust(12, "0")
+ uid = uid[:4] + " " + uid[4:8] + " " + uid[8:]
+ else:
+ uid = "XXXX XXXX XXXX"
+ uid_img = CreateImg(
+ 0,
+ 0,
+ plain_text=f"UID: {uid}",
+ color=(255, 255, 255, 0),
+ font_size=30,
+ font_color=(255, 255, 255),
+ )
+ sign_day_img = CreateImg(
+ 0,
+ 0,
+ plain_text=f"{user.checkin_count}",
+ color=(255, 255, 255, 0),
+ font_size=40,
+ font_color=(211, 64, 33),
+ )
+ lik_text1_img = CreateImg(
+ 0, 0, plain_text="当前", color=(255, 255, 255, 0), font_size=20
+ )
+ lik_text2_img = CreateImg(
+ 0,
+ 0,
+ plain_text=f"好感度:{user.impression:.2f}",
+ color=(255, 255, 255, 0),
+ font_size=30,
+ )
+ watermark = CreateImg(
+ 0,
+ 0,
+ plain_text=f"{NICKNAME}@{datetime.now().year}",
+ color=(255, 255, 255, 0),
+ font_size=15,
+ font_color=(155, 155, 155),
+ )
+ today_data = CreateImg(300, 300, color=(255, 255, 255, 0), font_size=20)
+ if is_card_view:
+ today_sign_text_img = CreateImg(
+ 0, 0, plain_text="", color=(255, 255, 255, 0), font_size=30
+ )
+ if impression_list:
+ impression_list.sort(reverse=True)
+ index = impression_list.index(user.impression)
+ rank_img = CreateImg(
+ 0,
+ 0,
+ plain_text=f"* 此群好感排名第 {index + 1} 位",
+ color=(255, 255, 255, 0),
+ font_size=30,
+ )
+ A.paste(rank_img, ((A.w - rank_img.w - 10), 20), True)
+ today_data.text(
+ (0, 0),
+ f"上次签到日期:{'从未' if user.checkin_time_last == datetime.min else user.checkin_time_last.date()}",
+ )
+ today_data.text((0, 25), f"总金币:{gold}")
+ today_data.text(
+ (0, 50),
+ f"色图概率:{(70 + user.impression if user.impression < 100 else 100):.2f}%",
+ )
+ today_data.text((0, 75), f"开箱次数:{(20 + int(user.impression / 3))}")
+ _type = "view"
+ else:
+ A.paste(gift_border, (570, 140), True)
+ today_sign_text_img = CreateImg(
+ 0, 0, plain_text="今日签到", color=(255, 255, 255, 0), font_size=30
+ )
+ if is_double:
+ today_data.text((0, 0), f"好感度 + {impression / 2:.2f} × 2")
+ else:
+ today_data.text((0, 0), f"好感度 + {impression:.2f}")
+ today_data.text((0, 25), f"金币 + {gold}")
+ _type = "sign"
+ current_date = datetime.now()
+ week = current_date.isoweekday()
+ data = current_date.date()
+ hour = current_date.hour
+ minute = current_date.minute
+ second = current_date.second
+ data_img = CreateImg(
+ 0,
+ 0,
+ plain_text=f"时间:{data} {weekdays[week]} {hour}:{minute}:{second}",
+ color=(255, 255, 255, 0),
+ font_size=20,
+ )
+ bk.paste(nickname_img, (30, 15), True)
+ bk.paste(uid_img, (30, 85), True)
+ bk.paste(A, (0, 150), alpha=True)
+ bk.text((30, 167), "Accumulative check-in for")
+ _x = bk.getsize("Accumulative check-in for")[0] + sign_day_img.w + 45
+ bk.paste(sign_day_img, (346, 158), True)
+ bk.text((_x, 167), "days")
+ bk.paste(data_img, (220, 370), True)
+ bk.paste(lik_text1_img, (220, 240), True)
+ bk.paste(lik_text2_img, (262, 234), True)
+ bk.paste(bar_bk, (225, 275), True)
+ bk.paste(info_img, (220, 305), True)
+ bk.paste(today_sign_text_img, (550, 180), True)
+ bk.paste(today_data, (580, 220), True)
+ bk.paste(watermark, (15, 400), True)
+ bk.save(
+ SIGN_TODAY_CARD_PATH / f"{user_id}_{user.belonging_group}_{_type}_{data}.png"
+ )
+ return image(
+ f"{user_id}_{user.belonging_group}_{_type}_{data}.png", "sign/today_card"
+ )
+
+
+def generate_progress_bar_pic():
+ bg_2 = (254, 1, 254)
+ bg_1 = (0, 245, 246)
+
+ bk = CreateImg(1000, 50, is_alpha=True)
+ img_x = CreateImg(50, 50, color=bg_2)
+ img_x.circle()
+ img_x.crop((25, 0, 50, 50))
+ img_y = CreateImg(50, 50, color=bg_1)
+ img_y.circle()
+ img_y.crop((0, 0, 25, 50))
+ A = CreateImg(950, 50)
+ width, height = A.size
+
+ step_r = (bg_2[0] - bg_1[0]) / width
+ step_g = (bg_2[1] - bg_1[1]) / width
+ step_b = (bg_2[2] - bg_1[2]) / width
+
+ for y in range(0, width):
+ bg_r = round(bg_1[0] + step_r * y)
+ bg_g = round(bg_1[1] + step_g * y)
+ bg_b = round(bg_1[2] + step_b * y)
+ for x in range(0, height):
+ A.point((y, x), fill=(bg_r, bg_g, bg_b))
+ bk.paste(img_y, (0, 0), True)
+ bk.paste(A, (25, 0))
+ bk.paste(img_x, (975, 0), True)
+ bk.save(SIGN_RESOURCE_PATH / "bar.png")
+
+ A = CreateImg(950, 50)
+ bk = CreateImg(1000, 50, is_alpha=True)
+ img_x = CreateImg(50, 50)
+ img_x.circle()
+ img_x.crop((25, 0, 50, 50))
+ img_y = CreateImg(50, 50)
+ img_y.circle()
+ img_y.crop((0, 0, 25, 50))
+ bk.paste(img_y, (0, 0), True)
+ bk.paste(A, (25, 0))
+ bk.paste(img_x, (975, 0), True)
+ bk.save(SIGN_RESOURCE_PATH / "bar_white.png")
+
+
+def get_level_and_next_impression(impression: float):
+ if impression == 0:
+ return lik2level[10], 10, 0
+ keys = list(lik2level.keys())
+ for i in range(len(keys)):
+ if impression > keys[i]:
+ return lik2level[keys[i]], keys[i - 1], keys[i]
+ return lik2level[10], 10, 0
+
+
+def clear_sign_data_pic():
+ date = datetime.now().date()
+ for file in os.listdir(SIGN_TODAY_CARD_PATH):
+ if str(date) not in file:
+ os.remove(SIGN_TODAY_CARD_PATH / file)
diff --git a/plugins/statistics/__init__.py b/plugins/statistics/__init__.py
old mode 100644
new mode 100755
index 590246d9..644a544e
--- a/plugins/statistics/__init__.py
+++ b/plugins/statistics/__init__.py
@@ -1,128 +1,128 @@
-from pathlib import Path
-from configs.path_config import DATA_PATH
-import nonebot
-import os
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-nonebot.load_plugins("plugins/statistics")
-
-old_file1 = Path(DATA_PATH) / "_prefix_count.json"
-old_file2 = Path(DATA_PATH) / "_prefix_user_count.json"
-new_path = Path(DATA_PATH) / "statistics"
-new_path.mkdir(parents=True, exist_ok=True)
-if old_file1.exists():
- os.rename(old_file1, new_path / "_prefix_count.json")
-if old_file2.exists():
- os.rename(old_file2, new_path / "_prefix_user_count.json")
-
-
-# 修改旧数据
-
-statistics_group_file = Path(DATA_PATH) / "statistics" / "_prefix_count.json"
-statistics_user_file = Path(DATA_PATH) / "statistics" / "_prefix_user_count.json"
-
-for file in [statistics_group_file, statistics_user_file]:
- if file.exists():
- with open(file, "r", encoding="utf8") as f:
- data = json.load(f)
- if not (statistics_group_file.parent / f"{file}.bak").exists():
- with open(f"{file}.bak", "w", encoding="utf8") as wf:
- json.dump(data, wf, ensure_ascii=False, indent=4)
- for x in ["total_statistics", "day_statistics"]:
- for key in data[x].keys():
- num = 0
- if data[x][key].get("ai") is not None:
- if data[x][key].get("Ai") is not None:
- data[x][key]["Ai"] += data[x][key]["ai"]
- else:
- data[x][key]["Ai"] = data[x][key]["ai"]
- del data[x][key]["ai"]
- if data[x][key].get("抽卡") is not None:
- if data[x][key].get("游戏抽卡") is not None:
- data[x][key]["游戏抽卡"] += data[x][key]["抽卡"]
- else:
- data[x][key]["游戏抽卡"] = data[x][key]["抽卡"]
- del data[x][key]["抽卡"]
- if data[x][key].get("我的道具") is not None:
- num += data[x][key]["我的道具"]
- del data[x][key]["我的道具"]
- if data[x][key].get("使用道具") is not None:
- num += data[x][key]["使用道具"]
- del data[x][key]["使用道具"]
- if data[x][key].get("我的金币") is not None:
- num += data[x][key]["我的金币"]
- del data[x][key]["我的金币"]
- if data[x][key].get("购买") is not None:
- num += data[x][key]["购买"]
- del data[x][key]["购买"]
- if data[x][key].get("商店") is not None:
- data[x][key]["商店"] += num
- else:
- data[x][key]["商店"] = num
- for x in ["week_statistics", "month_statistics"]:
- for key in data[x].keys():
- if key == "total":
- if data[x][key].get("ai") is not None:
- if data[x][key].get("Ai") is not None:
- data[x][key]["Ai"] += data[x][key]["ai"]
- else:
- data[x][key]["Ai"] = data[x][key]["ai"]
- del data[x][key]["ai"]
- if data[x][key].get("抽卡") is not None:
- if data[x][key].get("游戏抽卡") is not None:
- data[x][key]["游戏抽卡"] += data[x][key]["抽卡"]
- else:
- data[x][key]["游戏抽卡"] = data[x][key]["抽卡"]
- del data[x][key]["抽卡"]
- if data[x][key].get("我的道具") is not None:
- num += data[x][key]["我的道具"]
- del data[x][key]["我的道具"]
- if data[x][key].get("使用道具") is not None:
- num += data[x][key]["使用道具"]
- del data[x][key]["使用道具"]
- if data[x][key].get("我的金币") is not None:
- num += data[x][key]["我的金币"]
- del data[x][key]["我的金币"]
- if data[x][key].get("购买") is not None:
- num += data[x][key]["购买"]
- del data[x][key]["购买"]
- if data[x][key].get("商店") is not None:
- data[x][key]["商店"] += num
- else:
- data[x][key]["商店"] = num
- else:
- for day in data[x][key].keys():
- num = 0
- if data[x][key][day].get("ai") is not None:
- if data[x][key][day].get("Ai") is not None:
- data[x][key][day]["Ai"] += data[x][key][day]["ai"]
- else:
- data[x][key][day]["Ai"] = data[x][key][day]["ai"]
- del data[x][key][day]["ai"]
- if data[x][key][day].get("抽卡") is not None:
- if data[x][key][day].get("游戏抽卡") is not None:
- data[x][key][day]["游戏抽卡"] += data[x][key][day]["抽卡"]
- else:
- data[x][key][day]["游戏抽卡"] = data[x][key][day]["抽卡"]
- del data[x][key][day]["抽卡"]
- if data[x][key][day].get("我的道具") is not None:
- num += data[x][key][day]["我的道具"]
- del data[x][key][day]["我的道具"]
- if data[x][key][day].get("使用道具") is not None:
- num += data[x][key][day]["使用道具"]
- del data[x][key][day]["使用道具"]
- if data[x][key][day].get("我的金币") is not None:
- num += data[x][key][day]["我的金币"]
- del data[x][key][day]["我的金币"]
- if data[x][key][day].get("购买") is not None:
- num += data[x][key][day]["购买"]
- del data[x][key][day]["购买"]
- if data[x][key][day].get("商店") is not None:
- data[x][key][day]["商店"] += num
- else:
- data[x][key][day]["商店"] = num
- with open(file, "w", encoding="utf8") as f:
- json.dump(data, f, ensure_ascii=False, indent=4)
+from pathlib import Path
+from configs.path_config import DATA_PATH
+import nonebot
+import os
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+nonebot.load_plugins("plugins/statistics")
+
+old_file1 = Path(DATA_PATH) / "_prefix_count.json"
+old_file2 = Path(DATA_PATH) / "_prefix_user_count.json"
+new_path = Path(DATA_PATH) / "statistics"
+new_path.mkdir(parents=True, exist_ok=True)
+if old_file1.exists():
+ os.rename(old_file1, new_path / "_prefix_count.json")
+if old_file2.exists():
+ os.rename(old_file2, new_path / "_prefix_user_count.json")
+
+
+# 修改旧数据
+
+statistics_group_file = Path(DATA_PATH) / "statistics" / "_prefix_count.json"
+statistics_user_file = Path(DATA_PATH) / "statistics" / "_prefix_user_count.json"
+
+for file in [statistics_group_file, statistics_user_file]:
+ if file.exists():
+ with open(file, "r", encoding="utf8") as f:
+ data = json.load(f)
+ if not (statistics_group_file.parent / f"{file}.bak").exists():
+ with open(f"{file}.bak", "w", encoding="utf8") as wf:
+ json.dump(data, wf, ensure_ascii=False, indent=4)
+ for x in ["total_statistics", "day_statistics"]:
+ for key in data[x].keys():
+ num = 0
+ if data[x][key].get("ai") is not None:
+ if data[x][key].get("Ai") is not None:
+ data[x][key]["Ai"] += data[x][key]["ai"]
+ else:
+ data[x][key]["Ai"] = data[x][key]["ai"]
+ del data[x][key]["ai"]
+ if data[x][key].get("抽卡") is not None:
+ if data[x][key].get("游戏抽卡") is not None:
+ data[x][key]["游戏抽卡"] += data[x][key]["抽卡"]
+ else:
+ data[x][key]["游戏抽卡"] = data[x][key]["抽卡"]
+ del data[x][key]["抽卡"]
+ if data[x][key].get("我的道具") is not None:
+ num += data[x][key]["我的道具"]
+ del data[x][key]["我的道具"]
+ if data[x][key].get("使用道具") is not None:
+ num += data[x][key]["使用道具"]
+ del data[x][key]["使用道具"]
+ if data[x][key].get("我的金币") is not None:
+ num += data[x][key]["我的金币"]
+ del data[x][key]["我的金币"]
+ if data[x][key].get("购买") is not None:
+ num += data[x][key]["购买"]
+ del data[x][key]["购买"]
+ if data[x][key].get("商店") is not None:
+ data[x][key]["商店"] += num
+ else:
+ data[x][key]["商店"] = num
+ for x in ["week_statistics", "month_statistics"]:
+ for key in data[x].keys():
+ if key == "total":
+ if data[x][key].get("ai") is not None:
+ if data[x][key].get("Ai") is not None:
+ data[x][key]["Ai"] += data[x][key]["ai"]
+ else:
+ data[x][key]["Ai"] = data[x][key]["ai"]
+ del data[x][key]["ai"]
+ if data[x][key].get("抽卡") is not None:
+ if data[x][key].get("游戏抽卡") is not None:
+ data[x][key]["游戏抽卡"] += data[x][key]["抽卡"]
+ else:
+ data[x][key]["游戏抽卡"] = data[x][key]["抽卡"]
+ del data[x][key]["抽卡"]
+ if data[x][key].get("我的道具") is not None:
+ num += data[x][key]["我的道具"]
+ del data[x][key]["我的道具"]
+ if data[x][key].get("使用道具") is not None:
+ num += data[x][key]["使用道具"]
+ del data[x][key]["使用道具"]
+ if data[x][key].get("我的金币") is not None:
+ num += data[x][key]["我的金币"]
+ del data[x][key]["我的金币"]
+ if data[x][key].get("购买") is not None:
+ num += data[x][key]["购买"]
+ del data[x][key]["购买"]
+ if data[x][key].get("商店") is not None:
+ data[x][key]["商店"] += num
+ else:
+ data[x][key]["商店"] = num
+ else:
+ for day in data[x][key].keys():
+ num = 0
+ if data[x][key][day].get("ai") is not None:
+ if data[x][key][day].get("Ai") is not None:
+ data[x][key][day]["Ai"] += data[x][key][day]["ai"]
+ else:
+ data[x][key][day]["Ai"] = data[x][key][day]["ai"]
+ del data[x][key][day]["ai"]
+ if data[x][key][day].get("抽卡") is not None:
+ if data[x][key][day].get("游戏抽卡") is not None:
+ data[x][key][day]["游戏抽卡"] += data[x][key][day]["抽卡"]
+ else:
+ data[x][key][day]["游戏抽卡"] = data[x][key][day]["抽卡"]
+ del data[x][key][day]["抽卡"]
+ if data[x][key][day].get("我的道具") is not None:
+ num += data[x][key][day]["我的道具"]
+ del data[x][key][day]["我的道具"]
+ if data[x][key][day].get("使用道具") is not None:
+ num += data[x][key][day]["使用道具"]
+ del data[x][key][day]["使用道具"]
+ if data[x][key][day].get("我的金币") is not None:
+ num += data[x][key][day]["我的金币"]
+ del data[x][key][day]["我的金币"]
+ if data[x][key][day].get("购买") is not None:
+ num += data[x][key][day]["购买"]
+ del data[x][key][day]["购买"]
+ if data[x][key][day].get("商店") is not None:
+ data[x][key][day]["商店"] += num
+ else:
+ data[x][key][day]["商店"] = num
+ with open(file, "w", encoding="utf8") as f:
+ json.dump(data, f, ensure_ascii=False, indent=4)
diff --git a/plugins/statistics/statistics_handle.py b/plugins/statistics/statistics_handle.py
old mode 100644
new mode 100755
index 6626bc2c..f44308c8
--- a/plugins/statistics/statistics_handle.py
+++ b/plugins/statistics/statistics_handle.py
@@ -1,280 +1,280 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
-from models.group_info import GroupInfo
-from nonebot.typing import T_State
-from pathlib import Path
-from configs.path_config import DATA_PATH, IMAGE_PATH
-from utils.utils import get_message_text
-from utils.image_utils import CreateMat
-from utils.message_builder import image
-from utils.manager import plugins2settings_manager
-import asyncio
-import os
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-__zx_plugin_name__ = "功能调用统计可视化"
-__plugin_usage__ = """
-usage:
- 功能调用统计可视化
- 指令:
- 功能调用统计
- 日功能调用统计
- 周功能调用统计 ?[功能]
- 月功能调用统计 ?[功能]
- 我的功能调用统计
- 我的日功能调用统计 ?[功能]
- 我的周功能调用统计 ?[功能]
- 我的月功能调用统计 ?[功能]
-""".strip()
-__plugin_superuser_usage__ = """
-usage:
- 功能调用统计可视化
- 指令:
- 全局功能调用统计
- 全局日功能调用统计
- 全局周功能调用统计 ?[功能]
- 全局月功能调用统计 ?[功能]
-""".strip()
-__plugin_des__ = "功能调用统计可视化"
-__plugin_cmd__ = [
- "功能调用统计",
- "全局功能调用统计 [_superuser]",
- "全局日功能调用统计 [_superuser]",
- "全局周功能调用统计 ?[功能] [_superuser]",
- "全局月功能调用统计 ?[功能] [_superuser]",
- "周功能调用统计 ?[功能]",
- "月功能调用统计 ?[功能]",
- "我的功能调用统计",
- "我的日功能调用统计 ?[功能]",
- "我的周功能调用统计 ?[功能]",
- "我的月功能调用统计 ?[功能]",
-]
-__plugin_type__ = ("功能调用统计可视化", 1)
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "level": 5,
- "default_status": True,
- "limit_superuser": False,
- "cmd": ["功能调用统计"],
-}
-
-
-statistics = on_command(
- "功能调用统计",
- aliases={
- "全局功能调用统计",
- "全局日功能调用统计",
- "全局周功能调用统计",
- "全局月功能调用统计",
- "日功能调用统计",
- "周功能调用统计",
- "月功能调用统计",
- "我的功能调用统计",
- "我的日功能调用统计",
- "我的周功能调用统计",
- "我的月功能调用统计",
- },
- priority=5,
- block=True,
-)
-
-
-statistics_group_file = Path(DATA_PATH) / "statistics" / "_prefix_count.json"
-statistics_user_file = Path(DATA_PATH) / "statistics" / "_prefix_user_count.json"
-
-
-@statistics.handle()
-async def _(bot: Bot, event: MessageEvent, state: T_State):
- msg = get_message_text(event.json())
- if state["_prefix"]["raw_command"][:2] == "全局":
- if str(event.user_id) in bot.config.superusers:
- data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
- if state["_prefix"]["raw_command"][2] == '日':
- itype = 'day_statistics'
- elif state["_prefix"]["raw_command"][2] == '周':
- itype = 'week_statistics'
- elif state["_prefix"]["raw_command"][2] == '月':
- itype = 'month_statistics'
- else:
- itype = 'total_statistics'
- tmp_dict = {}
- data = data[itype]
- if itype in ["day_statistics", "total_statistics"]:
- for key in data['total']:
- tmp_dict[key] = data['total'][key]
- else:
- for group in data.keys():
- if group != 'total':
- for day in data[group].keys():
- for plugin_name in data[group][day].keys():
- if data[group][day][plugin_name] is not None:
- if tmp_dict.get(plugin_name) is None:
- tmp_dict[plugin_name] = 1
- else:
- tmp_dict[plugin_name] += data[group][day][plugin_name]
- bar_graph = await init_bar_graph(tmp_dict, state["_prefix"]["raw_command"])
- await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
- await statistics.finish(image(b64=bar_graph.pic2bs4()))
- return
- if state["_prefix"]["raw_command"][:2] == "我的":
- itype = "user"
- key = str(event.user_id)
- state["_prefix"]["raw_command"] = state["_prefix"]["raw_command"][2:]
- if not statistics_user_file.exists():
- await statistics.finish("统计文件不存在...", at_sender=True)
- else:
- if not isinstance(event, GroupMessageEvent):
- await statistics.finish("请在群内调用此功能...")
- itype = "group"
- key = str(event.group_id)
- if not statistics_group_file.exists():
- await statistics.finish("统计文件不存在...", at_sender=True)
- plugin = ""
- if state["_prefix"]["raw_command"][0] == "日":
- arg = "day_statistics"
- elif state["_prefix"]["raw_command"][0] == "周":
- arg = "week_statistics"
- elif state["_prefix"]["raw_command"][0] == "月":
- arg = "month_statistics"
- else:
- arg = "total_statistics"
- if msg:
- plugin = plugins2settings_manager.get_plugin_module(msg)
- if not plugin:
- if arg not in ["day_statistics", "total_statistics"]:
- await statistics.finish("未找到此功能的调用...", at_sender=True)
- if itype == "group":
- data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
- if not data[arg].get(str(event.group_id)):
- await statistics.finish("该群统计数据不存在...", at_sender=True)
- else:
- data: dict = json.load(open(statistics_user_file, "r", encoding="utf8"))
- if not data[arg].get(str(event.user_id)):
- await statistics.finish("该用户统计数据不存在...", at_sender=True)
- day_index = data["day_index"]
- data = data[arg][key]
- if itype == "group":
- name = await GroupInfo.get_group_info(event.group_id)
- name = name.group_name if name else str(event.group_id)
- else:
- name = event.sender.card if event.sender.card else event.sender.nickname
- img = await generate_statistics_img(data, arg, name, plugin, day_index)
- await statistics.send(image(b64=img))
-
-
-async def generate_statistics_img(
- data: dict, arg: str, name: str, plugin: str, day_index: int
-):
- try:
- plugin = plugins2settings_manager.get_plugin_data(plugin)['cmd'][0]
- except (KeyError, IndexError):
- pass
- bar_graph = None
- if arg == "day_statistics":
- bar_graph = await init_bar_graph(data, f"{name} 日功能调用统计")
- elif arg == "week_statistics":
- if plugin:
- current_week = day_index % 7
- week_lst = []
- if current_week == 0:
- week_lst = [1, 2, 3, 4, 5, 6, 7]
- else:
- for i in range(current_week + 1, 7):
- week_lst.append(str(i))
- for i in range(current_week + 1):
- week_lst.append(str(i))
- count = []
- for i in range(7):
- if int(week_lst[i]) == 7:
- try:
- count.append(data[str(0)][plugin])
- except KeyError:
- count.append(0)
- else:
- try:
- count.append(data[str(week_lst[i])][plugin])
- except KeyError:
- count.append(0)
- week_lst = ["7" if i == "0" else i for i in week_lst]
- bar_graph = CreateMat(
- y=count,
- mat_type="line",
- title=f"{name} 周 {plugin} 功能调用统计【为7天统计】",
- x_index=week_lst,
- display_num=True,
- background=[
- f"{IMAGE_PATH}/background/create_mat/{x}"
- for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
- ],
- bar_color=["*"],
- )
- else:
- bar_graph = await init_bar_graph(update_data(data), f"{name} 周功能调用统计【为7天统计】")
- elif arg == "month_statistics":
- if plugin:
- day_index = day_index % 30
- day_lst = []
- for i in range(day_index + 1, 30):
- day_lst.append(i)
- for i in range(day_index + 1):
- day_lst.append(i)
- count = [data[str(day_lst[i])][plugin] for i in range(30)]
- day_lst = [str(x + 1) for x in day_lst]
- bar_graph = CreateMat(
- y=count,
- mat_type="line",
- title=f"{name} 月 {plugin} 功能调用统计【为30天统计】",
- x_index=day_lst,
- display_num=True,
- background=[
- f"{IMAGE_PATH}/background/create_mat/{x}"
- for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
- ],
- bar_color=["*"],
- )
- else:
- bar_graph = await init_bar_graph(update_data(data), f"{name} 月功能调用统计【为30天统计】")
- elif arg == "total_statistics":
- bar_graph = await init_bar_graph(data, f"{name} 功能调用统计")
- await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
- return bar_graph.pic2bs4()
-
-
-async def init_bar_graph(data: dict, title: str) -> CreateMat:
- return await asyncio.get_event_loop().run_in_executor(None, _init_bar_graph, data, title)
-
-
-def _init_bar_graph(data: dict, title: str) -> CreateMat:
- bar_graph = CreateMat(
- y=[data[x] for x in data.keys() if data[x] != 0],
- mat_type="barh",
- title=title,
- x_index=[x for x in data.keys() if data[x] != 0],
- display_num=True,
- background=[
- f"{IMAGE_PATH}/background/create_mat/{x}"
- for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
- ],
- bar_color=["*"],
- )
- return bar_graph
-
-
-def update_data(data: dict):
- tmp_dict = {}
- for day in data.keys():
- for plugin_name in data[day].keys():
- # print(f'{day}:{plugin_name} = {data[day][plugin_name]}')
- if data[day][plugin_name] is not None:
- if tmp_dict.get(plugin_name) is None:
- tmp_dict[plugin_name] = 1
- else:
- tmp_dict[plugin_name] += data[day][plugin_name]
- return tmp_dict
-
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
+from models.group_info import GroupInfo
+from nonebot.typing import T_State
+from pathlib import Path
+from configs.path_config import DATA_PATH, IMAGE_PATH
+from utils.utils import get_message_text
+from utils.image_utils import CreateMat
+from utils.message_builder import image
+from utils.manager import plugins2settings_manager
+import asyncio
+import os
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+__zx_plugin_name__ = "功能调用统计可视化"
+__plugin_usage__ = """
+usage:
+ 功能调用统计可视化
+ 指令:
+ 功能调用统计
+ 日功能调用统计
+ 周功能调用统计 ?[功能]
+ 月功能调用统计 ?[功能]
+ 我的功能调用统计
+ 我的日功能调用统计 ?[功能]
+ 我的周功能调用统计 ?[功能]
+ 我的月功能调用统计 ?[功能]
+""".strip()
+__plugin_superuser_usage__ = """
+usage:
+ 功能调用统计可视化
+ 指令:
+ 全局功能调用统计
+ 全局日功能调用统计
+ 全局周功能调用统计 ?[功能]
+ 全局月功能调用统计 ?[功能]
+""".strip()
+__plugin_des__ = "功能调用统计可视化"
+__plugin_cmd__ = [
+ "功能调用统计",
+ "全局功能调用统计 [_superuser]",
+ "全局日功能调用统计 [_superuser]",
+ "全局周功能调用统计 ?[功能] [_superuser]",
+ "全局月功能调用统计 ?[功能] [_superuser]",
+ "周功能调用统计 ?[功能]",
+ "月功能调用统计 ?[功能]",
+ "我的功能调用统计",
+ "我的日功能调用统计 ?[功能]",
+ "我的周功能调用统计 ?[功能]",
+ "我的月功能调用统计 ?[功能]",
+]
+__plugin_type__ = ("功能调用统计可视化", 1)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["功能调用统计"],
+}
+
+
+statistics = on_command(
+ "功能调用统计",
+ aliases={
+ "全局功能调用统计",
+ "全局日功能调用统计",
+ "全局周功能调用统计",
+ "全局月功能调用统计",
+ "日功能调用统计",
+ "周功能调用统计",
+ "月功能调用统计",
+ "我的功能调用统计",
+ "我的日功能调用统计",
+ "我的周功能调用统计",
+ "我的月功能调用统计",
+ },
+ priority=5,
+ block=True,
+)
+
+
+statistics_group_file = Path(DATA_PATH) / "statistics" / "_prefix_count.json"
+statistics_user_file = Path(DATA_PATH) / "statistics" / "_prefix_user_count.json"
+
+
+@statistics.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if state["_prefix"]["raw_command"][:2] == "全局":
+ if str(event.user_id) in bot.config.superusers:
+ data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
+ if state["_prefix"]["raw_command"][2] == '日':
+ itype = 'day_statistics'
+ elif state["_prefix"]["raw_command"][2] == '周':
+ itype = 'week_statistics'
+ elif state["_prefix"]["raw_command"][2] == '月':
+ itype = 'month_statistics'
+ else:
+ itype = 'total_statistics'
+ tmp_dict = {}
+ data = data[itype]
+ if itype in ["day_statistics", "total_statistics"]:
+ for key in data['total']:
+ tmp_dict[key] = data['total'][key]
+ else:
+ for group in data.keys():
+ if group != 'total':
+ for day in data[group].keys():
+ for plugin_name in data[group][day].keys():
+ if data[group][day][plugin_name] is not None:
+ if tmp_dict.get(plugin_name) is None:
+ tmp_dict[plugin_name] = 1
+ else:
+ tmp_dict[plugin_name] += data[group][day][plugin_name]
+ bar_graph = await init_bar_graph(tmp_dict, state["_prefix"]["raw_command"])
+ await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
+ await statistics.finish(image(b64=bar_graph.pic2bs4()))
+ return
+ if state["_prefix"]["raw_command"][:2] == "我的":
+ itype = "user"
+ key = str(event.user_id)
+ state["_prefix"]["raw_command"] = state["_prefix"]["raw_command"][2:]
+ if not statistics_user_file.exists():
+ await statistics.finish("统计文件不存在...", at_sender=True)
+ else:
+ if not isinstance(event, GroupMessageEvent):
+ await statistics.finish("请在群内调用此功能...")
+ itype = "group"
+ key = str(event.group_id)
+ if not statistics_group_file.exists():
+ await statistics.finish("统计文件不存在...", at_sender=True)
+ plugin = ""
+ if state["_prefix"]["raw_command"][0] == "日":
+ arg = "day_statistics"
+ elif state["_prefix"]["raw_command"][0] == "周":
+ arg = "week_statistics"
+ elif state["_prefix"]["raw_command"][0] == "月":
+ arg = "month_statistics"
+ else:
+ arg = "total_statistics"
+ if msg:
+ plugin = plugins2settings_manager.get_plugin_module(msg)
+ if not plugin:
+ if arg not in ["day_statistics", "total_statistics"]:
+ await statistics.finish("未找到此功能的调用...", at_sender=True)
+ if itype == "group":
+ data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
+ if not data[arg].get(str(event.group_id)):
+ await statistics.finish("该群统计数据不存在...", at_sender=True)
+ else:
+ data: dict = json.load(open(statistics_user_file, "r", encoding="utf8"))
+ if not data[arg].get(str(event.user_id)):
+ await statistics.finish("该用户统计数据不存在...", at_sender=True)
+ day_index = data["day_index"]
+ data = data[arg][key]
+ if itype == "group":
+ name = await GroupInfo.get_group_info(event.group_id)
+ name = name.group_name if name else str(event.group_id)
+ else:
+ name = event.sender.card if event.sender.card else event.sender.nickname
+ img = await generate_statistics_img(data, arg, name, plugin, day_index)
+ await statistics.send(image(b64=img))
+
+
+async def generate_statistics_img(
+ data: dict, arg: str, name: str, plugin: str, day_index: int
+):
+ try:
+ plugin = plugins2settings_manager.get_plugin_data(plugin)['cmd'][0]
+ except (KeyError, IndexError):
+ pass
+ bar_graph = None
+ if arg == "day_statistics":
+ bar_graph = await init_bar_graph(data, f"{name} 日功能调用统计")
+ elif arg == "week_statistics":
+ if plugin:
+ current_week = day_index % 7
+ week_lst = []
+ if current_week == 0:
+ week_lst = [1, 2, 3, 4, 5, 6, 7]
+ else:
+ for i in range(current_week + 1, 7):
+ week_lst.append(str(i))
+ for i in range(current_week + 1):
+ week_lst.append(str(i))
+ count = []
+ for i in range(7):
+ if int(week_lst[i]) == 7:
+ try:
+ count.append(data[str(0)][plugin])
+ except KeyError:
+ count.append(0)
+ else:
+ try:
+ count.append(data[str(week_lst[i])][plugin])
+ except KeyError:
+ count.append(0)
+ week_lst = ["7" if i == "0" else i for i in week_lst]
+ bar_graph = CreateMat(
+ y=count,
+ mat_type="line",
+ title=f"{name} 周 {plugin} 功能调用统计【为7天统计】",
+ x_index=week_lst,
+ display_num=True,
+ background=[
+ f"{IMAGE_PATH}/background/create_mat/{x}"
+ for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
+ ],
+ bar_color=["*"],
+ )
+ else:
+ bar_graph = await init_bar_graph(update_data(data), f"{name} 周功能调用统计【为7天统计】")
+ elif arg == "month_statistics":
+ if plugin:
+ day_index = day_index % 30
+ day_lst = []
+ for i in range(day_index + 1, 30):
+ day_lst.append(i)
+ for i in range(day_index + 1):
+ day_lst.append(i)
+ count = [data[str(day_lst[i])][plugin] for i in range(30)]
+ day_lst = [str(x + 1) for x in day_lst]
+ bar_graph = CreateMat(
+ y=count,
+ mat_type="line",
+ title=f"{name} 月 {plugin} 功能调用统计【为30天统计】",
+ x_index=day_lst,
+ display_num=True,
+ background=[
+ f"{IMAGE_PATH}/background/create_mat/{x}"
+ for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
+ ],
+ bar_color=["*"],
+ )
+ else:
+ bar_graph = await init_bar_graph(update_data(data), f"{name} 月功能调用统计【为30天统计】")
+ elif arg == "total_statistics":
+ bar_graph = await init_bar_graph(data, f"{name} 功能调用统计")
+ await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
+ return bar_graph.pic2bs4()
+
+
+async def init_bar_graph(data: dict, title: str) -> CreateMat:
+ return await asyncio.get_event_loop().run_in_executor(None, _init_bar_graph, data, title)
+
+
+def _init_bar_graph(data: dict, title: str) -> CreateMat:
+ bar_graph = CreateMat(
+ y=[data[x] for x in data.keys() if data[x] != 0],
+ mat_type="barh",
+ title=title,
+ x_index=[x for x in data.keys() if data[x] != 0],
+ display_num=True,
+ background=[
+ f"{IMAGE_PATH}/background/create_mat/{x}"
+ for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
+ ],
+ bar_color=["*"],
+ )
+ return bar_graph
+
+
+def update_data(data: dict):
+ tmp_dict = {}
+ for day in data.keys():
+ for plugin_name in data[day].keys():
+ # print(f'{day}:{plugin_name} = {data[day][plugin_name]}')
+ if data[day][plugin_name] is not None:
+ if tmp_dict.get(plugin_name) is None:
+ tmp_dict[plugin_name] = 1
+ else:
+ tmp_dict[plugin_name] += data[day][plugin_name]
+ return tmp_dict
+
diff --git a/plugins/statistics/statistics_hook.py b/plugins/statistics/statistics_hook.py
old mode 100644
new mode 100755
index b2f0b2d6..c94622c9
--- a/plugins/statistics/statistics_hook.py
+++ b/plugins/statistics/statistics_hook.py
@@ -1,217 +1,217 @@
-from configs.path_config import DATA_PATH
-from nonebot.matcher import Matcher
-from nonebot.message import run_postprocessor
-from nonebot.typing import T_State
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
-from datetime import datetime
-from utils.manager import plugins2settings_manager
-from utils.utils import scheduler
-from nonebot.typing import Optional
-from pathlib import Path
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-
-
-__zx_plugin_name__ = "功能调用统计 [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-statistics_group_file = Path(DATA_PATH) / "statistics" / "_prefix_count.json"
-statistics_user_file = Path(DATA_PATH) / "statistics" / "_prefix_user_count.json"
-
-try:
- with open(statistics_group_file, "r", encoding="utf8") as f:
- _prefix_count_dict = json.load(f)
-except (FileNotFoundError, ValueError):
- _prefix_count_dict = {
- "total_statistics": {
- "total": {},
- },
- "day_statistics": {
- "total": {},
- },
- "week_statistics": {
- "total": {},
- },
- "month_statistics": {
- "total": {},
- },
- "start_time": str(datetime.now().date()),
- "day_index": 0,
- }
-
-try:
- with open(statistics_user_file, "r", encoding="utf8") as f:
- _prefix_user_count_dict = json.load(f)
-except (FileNotFoundError, ValueError):
- _prefix_user_count_dict = {
- "total_statistics": {
- "total": {},
- },
- "day_statistics": {
- "total": {},
- },
- "week_statistics": {
- "total": {},
- },
- "month_statistics": {
- "total": {},
- },
- "start_time": str(datetime.now().date()),
- "day_index": 0,
- }
-
-
-# 以前版本转换
-if _prefix_count_dict.get("day_index") is None:
- tmp = _prefix_count_dict.copy()
- _prefix_count_dict = {
- "total_statistics": tmp["total_statistics"],
- "day_statistics": {
- "total": {},
- },
- "week_statistics": {
- "total": {},
- },
- "month_statistics": {
- "total": {},
- },
- "start_time": tmp["start_time"],
- "day_index": 0,
- }
-
-
-# 添加命令次数
-@run_postprocessor
-async def _(
- matcher: Matcher,
- exception: Optional[Exception],
- bot: Bot,
- event: GroupMessageEvent,
- state: T_State,
-):
- global _prefix_count_dict
- if (
- matcher.type == "message"
- and matcher.priority not in [1, 9]
- and matcher.module not in ["update_info", "statistics_handle"]
- ):
- module = matcher.module
- day_index = _prefix_count_dict["day_index"]
- try:
- group_id = str(event.group_id)
- except AttributeError:
- group_id = "total"
- user_id = str(event.user_id)
- plugin_name = plugins2settings_manager.get_plugin_data(module)
- if plugin_name and plugin_name.get('cmd'):
- plugin_name = plugin_name.get('cmd')[0]
- check_exists_key(group_id, user_id, plugin_name)
- for data in [_prefix_count_dict, _prefix_user_count_dict]:
- data["total_statistics"]["total"][plugin_name] += 1
- data["day_statistics"]["total"][plugin_name] += 1
- data["week_statistics"]["total"][plugin_name] += 1
- data["month_statistics"]["total"][plugin_name] += 1
- # print(_prefix_count_dict)
- if group_id != "total":
- for data in [_prefix_count_dict, _prefix_user_count_dict]:
- if data == _prefix_count_dict:
- key = group_id
- else:
- key = user_id
- data["total_statistics"][key][plugin_name] += 1
- data["day_statistics"][key][plugin_name] += 1
- data["week_statistics"][key][str(day_index % 7)][
- plugin_name
- ] += 1
- data["month_statistics"][key][str(day_index % 30)][
- plugin_name
- ] += 1
- with open(statistics_group_file, "w", encoding="utf8") as f:
- json.dump(_prefix_count_dict, f, indent=4, ensure_ascii=False)
- with open(
- statistics_user_file, "w", encoding="utf8"
- ) as f:
- json.dump(_prefix_user_count_dict, f, ensure_ascii=False, indent=4)
-
-
-def check_exists_key(group_id: str, user_id: str, plugin_name: str):
- global _prefix_count_dict, _prefix_user_count_dict
- for data in [_prefix_count_dict, _prefix_user_count_dict]:
- if data == _prefix_count_dict:
- key = group_id
- else:
- key = user_id
- if not data["total_statistics"]["total"].get(plugin_name):
- data["total_statistics"]["total"][plugin_name] = 0
- if not data["day_statistics"]["total"].get(plugin_name):
- data["day_statistics"]["total"][plugin_name] = 0
- if not data["week_statistics"]["total"].get(plugin_name):
- data["week_statistics"]["total"][plugin_name] = 0
- if not data["month_statistics"]["total"].get(plugin_name):
- data["month_statistics"]["total"][plugin_name] = 0
-
- if not data["total_statistics"].get(key):
- data["total_statistics"][key] = {}
- if not data["total_statistics"][key].get(plugin_name):
- data["total_statistics"][key][plugin_name] = 0
- if not data["day_statistics"].get(key):
- data["day_statistics"][key] = {}
- if not data["day_statistics"][key].get(plugin_name):
- data["day_statistics"][key][plugin_name] = 0
-
- if key != 'total':
- if not data["week_statistics"].get(key):
- data["week_statistics"][key] = {}
- if data["week_statistics"][key].get("0") is None:
- for i in range(7):
- data["week_statistics"][key][str(i)] = {}
- if data["week_statistics"][key]["0"].get(plugin_name) is None:
- for i in range(7):
- data["week_statistics"][key][str(i)][plugin_name] = 0
-
- if not data["month_statistics"].get(key):
- data["month_statistics"][key] = {}
- if data["month_statistics"][key].get("0") is None:
- for i in range(30):
- data["month_statistics"][key][str(i)] = {}
- if data["month_statistics"][key]["0"].get(plugin_name) is None:
- for i in range(30):
- data["month_statistics"][key][str(i)][plugin_name] = 0
-
-
-# 天
-@scheduler.scheduled_job(
- "cron",
- hour=0,
- minute=1,
-)
-async def _():
- for data in [_prefix_count_dict, _prefix_user_count_dict]:
- data["day_index"] += 1
- for x in data["day_statistics"].keys():
- for key in data["day_statistics"][x].keys():
- try:
- data["day_statistics"][x][key] = 0
- except KeyError:
- pass
- for type_ in ["week_statistics", "month_statistics"]:
- index = str(
- data["day_index"] % 7
- if type_ == "week_statistics"
- else data["day_index"] % 30
- )
- for x in data[type_].keys():
- try:
- for key in data[type_][x][index].keys():
- data[type_][x][index][key] = 0
- except KeyError:
- pass
- with open(statistics_group_file, "w", encoding="utf8") as f:
- json.dump(_prefix_count_dict, f, indent=4, ensure_ascii=False)
- with open(statistics_user_file, "w", encoding="utf8") as f:
- json.dump(_prefix_user_count_dict, f, indent=4, ensure_ascii=False)
-
+from configs.path_config import DATA_PATH
+from nonebot.matcher import Matcher
+from nonebot.message import run_postprocessor
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
+from datetime import datetime
+from utils.manager import plugins2settings_manager
+from utils.utils import scheduler
+from nonebot.typing import Optional
+from pathlib import Path
+
+try:
+ import ujson as json
+except ModuleNotFoundError:
+ import json
+
+
+__zx_plugin_name__ = "功能调用统计 [Hidden]"
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+
+statistics_group_file = Path(DATA_PATH) / "statistics" / "_prefix_count.json"
+statistics_user_file = Path(DATA_PATH) / "statistics" / "_prefix_user_count.json"
+
+try:
+ with open(statistics_group_file, "r", encoding="utf8") as f:
+ _prefix_count_dict = json.load(f)
+except (FileNotFoundError, ValueError):
+ _prefix_count_dict = {
+ "total_statistics": {
+ "total": {},
+ },
+ "day_statistics": {
+ "total": {},
+ },
+ "week_statistics": {
+ "total": {},
+ },
+ "month_statistics": {
+ "total": {},
+ },
+ "start_time": str(datetime.now().date()),
+ "day_index": 0,
+ }
+
+try:
+ with open(statistics_user_file, "r", encoding="utf8") as f:
+ _prefix_user_count_dict = json.load(f)
+except (FileNotFoundError, ValueError):
+ _prefix_user_count_dict = {
+ "total_statistics": {
+ "total": {},
+ },
+ "day_statistics": {
+ "total": {},
+ },
+ "week_statistics": {
+ "total": {},
+ },
+ "month_statistics": {
+ "total": {},
+ },
+ "start_time": str(datetime.now().date()),
+ "day_index": 0,
+ }
+
+
+# 以前版本转换
+if _prefix_count_dict.get("day_index") is None:
+ tmp = _prefix_count_dict.copy()
+ _prefix_count_dict = {
+ "total_statistics": tmp["total_statistics"],
+ "day_statistics": {
+ "total": {},
+ },
+ "week_statistics": {
+ "total": {},
+ },
+ "month_statistics": {
+ "total": {},
+ },
+ "start_time": tmp["start_time"],
+ "day_index": 0,
+ }
+
+
+# 添加命令次数
+@run_postprocessor
+async def _(
+ matcher: Matcher,
+ exception: Optional[Exception],
+ bot: Bot,
+ event: GroupMessageEvent,
+ state: T_State,
+):
+ global _prefix_count_dict
+ if (
+ matcher.type == "message"
+ and matcher.priority not in [1, 9]
+ and matcher.module not in ["update_info", "statistics_handle"]
+ ):
+ module = matcher.module
+ day_index = _prefix_count_dict["day_index"]
+ try:
+ group_id = str(event.group_id)
+ except AttributeError:
+ group_id = "total"
+ user_id = str(event.user_id)
+ plugin_name = plugins2settings_manager.get_plugin_data(module)
+ if plugin_name and plugin_name.get('cmd'):
+ plugin_name = plugin_name.get('cmd')[0]
+ check_exists_key(group_id, user_id, plugin_name)
+ for data in [_prefix_count_dict, _prefix_user_count_dict]:
+ data["total_statistics"]["total"][plugin_name] += 1
+ data["day_statistics"]["total"][plugin_name] += 1
+ data["week_statistics"]["total"][plugin_name] += 1
+ data["month_statistics"]["total"][plugin_name] += 1
+ # print(_prefix_count_dict)
+ if group_id != "total":
+ for data in [_prefix_count_dict, _prefix_user_count_dict]:
+ if data == _prefix_count_dict:
+ key = group_id
+ else:
+ key = user_id
+ data["total_statistics"][key][plugin_name] += 1
+ data["day_statistics"][key][plugin_name] += 1
+ data["week_statistics"][key][str(day_index % 7)][
+ plugin_name
+ ] += 1
+ data["month_statistics"][key][str(day_index % 30)][
+ plugin_name
+ ] += 1
+ with open(statistics_group_file, "w", encoding="utf8") as f:
+ json.dump(_prefix_count_dict, f, indent=4, ensure_ascii=False)
+ with open(
+ statistics_user_file, "w", encoding="utf8"
+ ) as f:
+ json.dump(_prefix_user_count_dict, f, ensure_ascii=False, indent=4)
+
+
+def check_exists_key(group_id: str, user_id: str, plugin_name: str):
+ global _prefix_count_dict, _prefix_user_count_dict
+ for data in [_prefix_count_dict, _prefix_user_count_dict]:
+ if data == _prefix_count_dict:
+ key = group_id
+ else:
+ key = user_id
+ if not data["total_statistics"]["total"].get(plugin_name):
+ data["total_statistics"]["total"][plugin_name] = 0
+ if not data["day_statistics"]["total"].get(plugin_name):
+ data["day_statistics"]["total"][plugin_name] = 0
+ if not data["week_statistics"]["total"].get(plugin_name):
+ data["week_statistics"]["total"][plugin_name] = 0
+ if not data["month_statistics"]["total"].get(plugin_name):
+ data["month_statistics"]["total"][plugin_name] = 0
+
+ if not data["total_statistics"].get(key):
+ data["total_statistics"][key] = {}
+ if not data["total_statistics"][key].get(plugin_name):
+ data["total_statistics"][key][plugin_name] = 0
+ if not data["day_statistics"].get(key):
+ data["day_statistics"][key] = {}
+ if not data["day_statistics"][key].get(plugin_name):
+ data["day_statistics"][key][plugin_name] = 0
+
+ if key != 'total':
+ if not data["week_statistics"].get(key):
+ data["week_statistics"][key] = {}
+ if data["week_statistics"][key].get("0") is None:
+ for i in range(7):
+ data["week_statistics"][key][str(i)] = {}
+ if data["week_statistics"][key]["0"].get(plugin_name) is None:
+ for i in range(7):
+ data["week_statistics"][key][str(i)][plugin_name] = 0
+
+ if not data["month_statistics"].get(key):
+ data["month_statistics"][key] = {}
+ if data["month_statistics"][key].get("0") is None:
+ for i in range(30):
+ data["month_statistics"][key][str(i)] = {}
+ if data["month_statistics"][key]["0"].get(plugin_name) is None:
+ for i in range(30):
+ data["month_statistics"][key][str(i)][plugin_name] = 0
+
+
+# 天
+@scheduler.scheduled_job(
+ "cron",
+ hour=0,
+ minute=1,
+)
+async def _():
+ for data in [_prefix_count_dict, _prefix_user_count_dict]:
+ data["day_index"] += 1
+ for x in data["day_statistics"].keys():
+ for key in data["day_statistics"][x].keys():
+ try:
+ data["day_statistics"][x][key] = 0
+ except KeyError:
+ pass
+ for type_ in ["week_statistics", "month_statistics"]:
+ index = str(
+ data["day_index"] % 7
+ if type_ == "week_statistics"
+ else data["day_index"] % 30
+ )
+ for x in data[type_].keys():
+ try:
+ for key in data[type_][x][index].keys():
+ data[type_][x][index][key] = 0
+ except KeyError:
+ pass
+ with open(statistics_group_file, "w", encoding="utf8") as f:
+ json.dump(_prefix_count_dict, f, indent=4, ensure_ascii=False)
+ with open(statistics_user_file, "w", encoding="utf8") as f:
+ json.dump(_prefix_user_count_dict, f, indent=4, ensure_ascii=False)
+
diff --git a/plugins/translate/__init__.py b/plugins/translate/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/translate/data_source.py b/plugins/translate/data_source.py
old mode 100644
new mode 100755
index e2fd80f5..77df30a1
--- a/plugins/translate/data_source.py
+++ b/plugins/translate/data_source.py
@@ -1,6 +1,4 @@
-import aiohttp
-from utils.utils import get_local_proxy
-from utils.user_agent import get_user_agent
+from utils.http_utils import AsyncHttpx
url = f"http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"
@@ -16,11 +14,9 @@ async def translate_msg(language_type, msg):
"action": "FY_BY_CLICKBUTTON",
"typoResult": "true",
}
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.post(url, data=data, proxy=get_local_proxy()) as res:
- data = await res.json()
- if data["errorCode"] == 0:
- return data["translateResult"][0][0]["tgt"]
+ data = (await AsyncHttpx.post(url, data=data)).json()
+ if data["errorCode"] == 0:
+ return data["translateResult"][0][0]["tgt"]
return "翻译惜败.."
diff --git a/plugins/update_gocqhttp/__init__.py b/plugins/update_gocqhttp/__init__.py
old mode 100644
new mode 100755
index d910e596..ba6e7ed8
--- a/plugins/update_gocqhttp/__init__.py
+++ b/plugins/update_gocqhttp/__init__.py
@@ -2,12 +2,12 @@ from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from .data_source import download_gocq_lasted, upload_gocq_lasted
-import os
from services.log import logger
from utils.utils import scheduler, get_bot
from nonebot.permission import SUPERUSER
from configs.config import Config
from pathlib import Path
+import os
__zx_plugin_name__ = "更新gocq [Superuser]"
diff --git a/plugins/update_gocqhttp/data_source.py b/plugins/update_gocqhttp/data_source.py
old mode 100644
new mode 100755
index 2782f629..9383648d
--- a/plugins/update_gocqhttp/data_source.py
+++ b/plugins/update_gocqhttp/data_source.py
@@ -1,10 +1,8 @@
-import aiohttp
-from utils.utils import get_local_proxy, get_bot
-from utils.user_agent import get_user_agent
+from utils.utils import get_bot
+from bs4 import BeautifulSoup
+from utils.http_utils import AsyncHttpx
import asyncio
import platform
-import aiofiles
-from bs4 import BeautifulSoup
import os
if platform.system() == "Windows":
@@ -15,53 +13,45 @@ url = "https://github.com/Mrs4s/go-cqhttp/releases"
async def download_gocq_lasted(path: str):
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(url, proxy=get_local_proxy()) as response:
- soup = BeautifulSoup(await response.text(), "lxml")
- a = soup.find("div", {"class": "release-header"}).find("a")
- title = a.text
- _url = a.get("href")
- for file in os.listdir(path):
- if file.endswith(".zip"):
- if (
- file == title + "-windows-amd64.zip"
- or file == title + "_windows_amd64.zip"
- ):
- return "gocqhttp没有更新!"
- for file in os.listdir(path):
- os.remove(path + file)
- async with session.get(
- "https://github.com" + _url, proxy=get_local_proxy()
- ) as res:
- update_info = ""
- soup = BeautifulSoup(await res.text(), "lxml")
- info_div = soup.find("div", {"class": "markdown-body"})
- for p in info_div.find_all("p"):
- update_info += p.text.replace("
", "\n") + "\n"
- div_all = soup.select(
- "div.d-flex.flex-justify-between.flex-items-center.py-1.py-md-2.Box-body.px-2"
- )
- for div in div_all:
- if (
- div.find("a").find("span").text == title + "-windows-amd64.zip"
- or div.find("a").find("span").text
- == title + "-linux-arm64.tar.gz"
- or div.find("a").find("span").text
- == "go-cqhttp_windows_amd64.zip"
- or div.find("a").find("span").text
- == "go-cqhttp_linux_arm64.tar.gz"
- ):
- file_url = div.find("a").get("href")
- if div.find("a").find("span").text.find("windows") == -1:
- tag = "-linux-arm64.tar.gz"
- else:
- tag = "-windows-amd64.zip"
- async with session.get(
- "https://github.com" + file_url, proxy=get_local_proxy()
- ) as res_file:
- async with aiofiles.open(path + title + tag, "wb") as f:
- await f.write(await res_file.read())
- return update_info
+ text = (await AsyncHttpx.get(url)).text
+ soup = BeautifulSoup(text, "lxml")
+ a = soup.find("div", {"class": "release-header"}).find("a")
+ title = a.text
+ _url = a.get("href")
+ for file in os.listdir(path):
+ if file.endswith(".zip"):
+ if (
+ file == title + "-windows-amd64.zip"
+ or file == title + "_windows_amd64.zip"
+ ):
+ return "gocqhttp没有更新!"
+ for file in os.listdir(path):
+ os.remove(path + file)
+ text = (await AsyncHttpx.get("https://github.com" + _url)).text
+ update_info = ""
+ soup = BeautifulSoup(text, "lxml")
+ info_div = soup.find("div", {"class": "markdown-body"})
+ for p in info_div.find_all("p"):
+ update_info += p.text.replace("
", "\n") + "\n"
+ div_all = soup.select(
+ "div.d-flex.flex-justify-between.flex-items-center.py-1.py-md-2.Box-body.px-2"
+ )
+ for div in div_all:
+ if (
+ div.find("a").find("span").text == title + "-windows-amd64.zip"
+ or div.find("a").find("span").text == title + "-linux-arm64.tar.gz"
+ or div.find("a").find("span").text == "go-cqhttp_windows_amd64.zip"
+ or div.find("a").find("span").text == "go-cqhttp_linux_arm64.tar.gz"
+ ):
+ file_url = div.find("a").get("href")
+ if div.find("a").find("span").text.find("windows") == -1:
+ tag = "-linux-arm64.tar.gz"
+ else:
+ tag = "-windows-amd64.zip"
+ await AsyncHttpx.download_file(
+ "https://github.com" + file_url, path + title + tag
+ )
+ return update_info
async def upload_gocq_lasted(path, name, group_id):
diff --git a/plugins/update_pic.py b/plugins/update_picture.py
old mode 100644
new mode 100755
similarity index 90%
rename from plugins/update_pic.py
rename to plugins/update_picture.py
index 15511fdb..f197a5a3
--- a/plugins/update_pic.py
+++ b/plugins/update_picture.py
@@ -7,11 +7,11 @@ from nonebot.rule import to_me
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from nonebot.typing import T_State
from utils.utils import get_message_imgs
-import aiofiles
-import aiohttp
+from pathlib import Path
from utils.utils import is_number, get_message_text
from utils.image_utils import CreateImg, pic2b64
from configs.config import NICKNAME
+from utils.http_utils import AsyncHttpx
import cv2
import numpy as np
@@ -203,22 +203,13 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
y = int(y)
index = 0
result = ""
- async with aiohttp.ClientSession() as session:
- for img_url in img_list:
- async with session.get(img_url, timeout=7) as response:
- if response.status == 200:
- async with aiofiles.open(
- IMAGE_PATH + f"temp/{event.user_id}_{index}_update.png", "wb"
- ) as f:
- await f.write(await response.read())
- index += 1
- else:
- logger.warning(
- f"USER {event.user_id} GROUP "
- f"{event.group_id if event.message_type != 'private' else 'private'} "
- f"使用 {method} 时下载图片超时"
- )
- await update_img.finish("获取图片超时了...", at_sender=True)
+ for img_url in img_list:
+ if await AsyncHttpx.download_file(
+ img_url, Path(IMAGE_PATH) / "temp" / f"{event.user_id}_{index}_update.png"
+ ):
+ index += 1
+ else:
+ await update_img.finish("获取图片超时了...", at_sender=True)
if index == 0:
return
if method in ["修改尺寸", "1"]:
diff --git a/plugins/weather/__init__.py b/plugins/weather/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/weather/data_source.py b/plugins/weather/data_source.py
old mode 100644
new mode 100755
index a787cf67..d5c39431
--- a/plugins/weather/data_source.py
+++ b/plugins/weather/data_source.py
@@ -1,11 +1,10 @@
from utils.message_builder import image
-from utils.user_agent import get_user_agent
from configs.path_config import TEXT_PATH
from configs.config import NICKNAME
from typing import List
from nonebot import Driver
from pathlib import Path
-import aiohttp
+from utils.http_utils import AsyncHttpx
import ujson as json
import nonebot
@@ -17,37 +16,44 @@ data = {}
async def get_weather_of_city(city: str) -> str:
+ """
+ 获取城市天气数据
+ :param city: 城市
+ """
code = _check_exists_city(city)
if code == 999:
return "不要查一个省份的天气啊,很累人的!"
elif code == 998:
return f"{NICKNAME}没查到!!试试查火星的天气?"
else:
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(
- f"http://wthrcdn.etouch.cn/weather_mini?city={city}", timeout=5
- ) as res:
- data_json = json.loads(await res.text(encoding="utf8"))
- if "desc" in data_json:
- if data_json["desc"] == "invilad-citykey":
- return f"{NICKNAME}没查到!!试试查火星的天气?" + image(
- "shengqi", "zhenxun"
- )
- elif data_json["desc"] == "OK":
- w_type = data_json["data"]["forecast"][0]["type"]
- w_max = data_json["data"]["forecast"][0]["high"][3:]
- w_min = data_json["data"]["forecast"][0]["low"][3:]
- fengli = data_json["data"]["forecast"][0]["fengli"][9:-3]
- ganmao = data_json["data"]["ganmao"]
- fengxiang = data_json["data"]["forecast"][0]["fengxiang"]
- repass = f"{city}的天气是 {w_type} 天\n最高温度: {w_max}\n最低温度: {w_min}\n风力: {fengli} {fengxiang}\n{ganmao}"
- return repass
- else:
- return "好像出错了?"
+ data_json = json.loads(
+ (
+ await AsyncHttpx.get(
+ f"http://wthrcdn.etouch.cn/weather_mini?city={city}"
+ )
+ ).text
+ )
+ if "desc" in data_json:
+ if data_json["desc"] == "invilad-citykey":
+ return f"{NICKNAME}没查到!!试试查火星的天气?" + image("shengqi", "zhenxun")
+ elif data_json["desc"] == "OK":
+ w_type = data_json["data"]["forecast"][0]["type"]
+ w_max = data_json["data"]["forecast"][0]["high"][3:]
+ w_min = data_json["data"]["forecast"][0]["low"][3:]
+ fengli = data_json["data"]["forecast"][0]["fengli"][9:-3]
+ ganmao = data_json["data"]["ganmao"]
+ fengxiang = data_json["data"]["forecast"][0]["fengxiang"]
+ repass = f"{city}的天气是 {w_type} 天\n最高温度: {w_max}\n最低温度: {w_min}\n风力: {fengli} {fengxiang}\n{ganmao}"
+ return repass
+ else:
+ return "好像出错了?再试试?"
-# 城市是否存在或是否是省份
def _check_exists_city(city: str) -> int:
+ """
+ 检测城市是否存在合法
+ :param city: 城市名称
+ """
global data
city = city if city[-1] != "市" else city[:-1]
for province in data.keys():
@@ -61,6 +67,9 @@ def _check_exists_city(city: str) -> int:
def get_city_list() -> List[str]:
+ """
+ 获取城市列表
+ """
global data
if not data:
try:
diff --git a/plugins/what_anime/__init__.py b/plugins/what_anime/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/what_anime/data_source.py b/plugins/what_anime/data_source.py
old mode 100644
new mode 100755
index d80b65a7..87fc071a
--- a/plugins/what_anime/data_source.py
+++ b/plugins/what_anime/data_source.py
@@ -1,8 +1,7 @@
import time
from services.log import logger
from utils.langconv import *
-import aiohttp
-from utils.user_agent import get_user_agent
+from utils.http_utils import AsyncHttpx
async def get_anime(anime: str) -> str:
@@ -10,44 +9,39 @@ async def get_anime(anime: str) -> str:
url = "https://api.trace.moe/search?anilistInfo&url={}".format(anime)
logger.debug("[info]Now starting get the {}".format(url))
try:
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(url, timeout=45) as response:
- if response.status == 200:
- anime_json = await response.json()
- if not anime_json["error"]:
- if anime_json == "Error reading imagenull":
- return "图像源错误,注意必须是静态图片哦"
- repass = ""
- # 拿到动漫 中文名
- for anime in anime_json["result"][:5]:
- synonyms = anime["anilist"]["synonyms"]
- for x in synonyms:
- _count_ch = 0
- for word in x:
- if "\u4e00" <= word <= "\u9fff":
- _count_ch += 1
- if _count_ch > 3:
- anime_name = x
- break
- else:
- anime_name = anime["anilist"]["title"]["native"]
- episode = anime["episode"]
- from_ = int(anime["from"])
- m, s = divmod(from_, 60)
- similarity = anime["similarity"]
- putline = "[ {} ][{}][{}:{}] 相似度:{:.2%}".format(
- Converter("zh-hans").convert(anime_name),
- episode if episode else "?",
- m,
- s,
- similarity,
- )
- repass += putline + "\n"
- return f"耗时 {int(time.time() - s_time)} 秒\n" + repass[:-1]
- else:
- return f'访问错误 error:{anime_json["error"]}'
+ anime_json = (await AsyncHttpx.get(url)).json()
+ if not anime_json["error"]:
+ if anime_json == "Error reading imagenull":
+ return "图像源错误,注意必须是静态图片哦"
+ repass = ""
+ # 拿到动漫 中文名
+ for anime in anime_json["result"][:5]:
+ synonyms = anime["anilist"]["synonyms"]
+ for x in synonyms:
+ _count_ch = 0
+ for word in x:
+ if "\u4e00" <= word <= "\u9fff":
+ _count_ch += 1
+ if _count_ch > 3:
+ anime_name = x
+ break
else:
- return f"访问失败,请再试一次吧, status: {response.status}"
+ anime_name = anime["anilist"]["title"]["native"]
+ episode = anime["episode"]
+ from_ = int(anime["from"])
+ m, s = divmod(from_, 60)
+ similarity = anime["similarity"]
+ putline = "[ {} ][{}][{}:{}] 相似度:{:.2%}".format(
+ Converter("zh-hans").convert(anime_name),
+ episode if episode else "?",
+ m,
+ s,
+ similarity,
+ )
+ repass += putline + "\n"
+ return f"耗时 {int(time.time() - s_time)} 秒\n" + repass[:-1]
+ else:
+ return f'访问错误 error:{anime_json["error"]}'
except Exception as e:
- logger.error(f"识番发生错误 e:{e}")
+ logger.error(f"识番发生错误 {type(e)}:{e}")
return "发生了奇怪的错误,那就没办法了,再试一次?"
diff --git a/plugins/white2black_img.py b/plugins/white2black_image.py
old mode 100644
new mode 100755
similarity index 71%
rename from plugins/white2black_img.py
rename to plugins/white2black_image.py
index 2d5e8e5e..9a5bf7f2
--- a/plugins/white2black_img.py
+++ b/plugins/white2black_image.py
@@ -1,14 +1,13 @@
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from nonebot import on_command
-from utils.utils import get_message_imgs, get_local_proxy, get_message_text, is_chinese
+from utils.utils import get_message_imgs, get_message_text, is_chinese
from utils.message_builder import image
-import aiohttp
-import aiofiles
-from configs.path_config import IMAGE_PATH
+from configs.path_config import TEMP_PATH
from utils.image_utils import CreateImg
-from utils.user_agent import get_user_agent
from services.log import logger
+from utils.http_utils import AsyncHttpx
+from pathlib import Path
# ZH_CN2EN 中文 » 英语
# ZH_CN2JA 中文 » 日语
@@ -53,14 +52,12 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
if not img or not msg:
await w2b_img.finish(f"格式错误:\n" + __plugin_usage__)
img = img[0]
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(img, proxy=get_local_proxy()) as response:
- async with aiofiles.open(
- IMAGE_PATH + f"temp/{event.user_id}_w2b.png", "wb"
- ) as f:
- await f.write(await response.read())
+ if not await AsyncHttpx.download_file(
+ img, Path(TEMP_PATH) / f"{event.user_id}_w2b.png"
+ ):
+ await w2b_img.finish("下载图片失败...请稍后再试...")
msg = await get_translate(msg)
- w2b = CreateImg(0, 0, background=IMAGE_PATH + f"temp/{event.user_id}_w2b.png")
+ w2b = CreateImg(0, 0, background=Path(TEMP_PATH) / f"{event.user_id}_w2b.png")
w2b.convert("L")
msg_sp = msg.split("<|>")
w, h = w2b.size
@@ -93,17 +90,17 @@ def centered_text(img: CreateImg, text: str, add_h: int):
text_sp = text.split("<|>")
w, h = img.getsize(text_sp[0])
if len(text_sp) == 1:
- w = (img.w - w) / 2
- h = top_h + (bottom_h - top_h - h) / 2
+ w = int((img.w - w) / 2)
+ h = int(top_h + (bottom_h - top_h - h) / 2)
img.text((w, h), text_sp[0], (255, 255, 255))
else:
- br_h = top_h + (bottom_h - top_h) / 2
- w = (img.w - w) / 2
- h = top_h + (br_h - top_h - h) / 2
+ br_h = int(top_h + (bottom_h - top_h) / 2)
+ w = int((img.w - w) / 2)
+ h = int(top_h + (br_h - top_h - h) / 2)
img.text((w, h), text_sp[0], (255, 255, 255))
w, h = img.getsize(text_sp[1])
- w = (img.w - w) / 2
- h = br_h + (bottom_h - br_h - h) / 2
+ w = int((img.w - w) / 2)
+ h = int(br_h + (bottom_h - br_h - h) / 2)
img.text((w, h), text_sp[1], (255, 255, 255))
@@ -119,15 +116,10 @@ async def get_translate(msg: str) -> str:
"action": "FY_BY_CLICKBUTTON",
"typoResult": "true",
}
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- try:
- async with session.post(url, data=data, proxy=get_local_proxy()) as res:
- data = await res.json()
- if data["errorCode"] == 0:
- translate = data["translateResult"][0][0]["tgt"]
- msg += "<|>" + translate
- except Exception as e:
- logger.warning(f"黑白草图翻译出错 e:{e}")
+ data = (await AsyncHttpx.post(url, data=data)).json()
+ if data["errorCode"] == 0:
+ translate = data["translateResult"][0][0]["tgt"]
+ msg += "<|>" + translate
return msg
diff --git a/plugins/withdraw.py b/plugins/withdraw.py
old mode 100644
new mode 100755
index 534f9adb..42319f59
--- a/plugins/withdraw.py
+++ b/plugins/withdraw.py
@@ -1,30 +1,30 @@
-from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
-from nonebot.typing import T_State
-import re
-
-
-__zx_plugin_name__ = "消息撤回 [Admin]"
-__plugin_usage__ = """
-usage:
- 简易的消息撤回机制
- 指令:
- [回复]撤回
-""".strip()
-__plugin_des__ = "消息撤回机制"
-__plugin_cmd__ = ["[回复]撤回"]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-__plugin_settings__ = {
- "admin_level": 0,
-}
-
-
-withdraw_msg = on_command("撤回", priority=5, block=True)
-
-
-@withdraw_msg.handle()
-async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
- r = re.search(r"\[CQ:reply,id=(-?\d*)]", event.raw_message)
- if r:
- await bot.delete_msg(message_id=int(r.group(1)), self_id=int(bot.self_id))
+from nonebot import on_command
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
+from nonebot.typing import T_State
+import re
+
+
+__zx_plugin_name__ = "消息撤回 [Admin]"
+__plugin_usage__ = """
+usage:
+ 简易的消息撤回机制
+ 指令:
+ [回复]撤回
+""".strip()
+__plugin_des__ = "消息撤回机制"
+__plugin_cmd__ = ["[回复]撤回"]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "admin_level": 0,
+}
+
+
+withdraw_msg = on_command("撤回", priority=5, block=True)
+
+
+@withdraw_msg.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ r = re.search(r"\[CQ:reply,id=(-?\d*)]", event.raw_message)
+ if r:
+ await bot.delete_msg(message_id=int(r.group(1)), self_id=int(bot.self_id))
diff --git a/plugins/word_bank/__init__.py b/plugins/word_bank/__init__.py
new file mode 100644
index 00000000..38fd6cdc
--- /dev/null
+++ b/plugins/word_bank/__init__.py
@@ -0,0 +1,16 @@
+from configs.config import Config
+import nonebot
+
+
+Config.add_plugin_config(
+ "word_bank",
+ "WORD_BANK_LEVEL [LEVEL]",
+ 5,
+ name="词库问答",
+ help_="设置增删词库的权限等级",
+ default_value=5
+)
+
+
+nonebot.load_plugins("plugins/word_bank")
+
diff --git a/plugins/word_bank/data_source.py b/plugins/word_bank/data_source.py
new file mode 100644
index 00000000..fd9bcbc5
--- /dev/null
+++ b/plugins/word_bank/data_source.py
@@ -0,0 +1,52 @@
+from .model import WordBank
+from typing import Union
+
+
+class WordBankBuilder:
+
+ def __init__(self, user_id: int, group_id: int, problem: str):
+
+ self._data = {
+ "user_id": user_id,
+ "group_id": group_id,
+ "problem": problem
+ }
+
+ def set_placeholder(self, id_: int, placeholder: Union[str, int]):
+ """
+ 设置占位符
+ :param id_: 站位id
+ :param placeholder: 占位符内容
+ """
+ if self._data.get("placeholder") is None:
+ self._data["placeholder"] = []
+ self._data["placeholder"].append((id_, placeholder))
+
+ def set_answer(self, answer: str):
+ """
+ 设置回答
+ :param answer: 回答
+ """
+ self._data["answer"] = answer
+
+ async def save(self):
+ user_id = self._data["user_id"]
+ group_id = self._data["group_id"]
+ problem = self._data["problem"]
+ answer = self._data["answer"]
+ placeholder = self._data.get("placeholder")
+ await WordBank.add_problem_answer(user_id, group_id, problem, answer, placeholder)
+
+ def __str__(self):
+ return str(self._data)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/word_bank/message_handle.py b/plugins/word_bank/message_handle.py
new file mode 100644
index 00000000..117e461e
--- /dev/null
+++ b/plugins/word_bank/message_handle.py
@@ -0,0 +1,44 @@
+from utils.utils import get_message_text
+from utils.message_builder import image, at
+from .rule import check
+from .model import WordBank
+from configs.path_config import DATA_PATH
+from pathlib import Path
+from nonebot.adapters.cqhttp import (
+ Bot,
+ GroupMessageEvent,
+)
+from nonebot.typing import T_State
+from nonebot import on_message
+
+
+__zx_plugin_name__ = "词库问答回复操作 [Hidden]"
+
+
+data_dir = Path(DATA_PATH) / "word_bank"
+data_dir.mkdir(parents=True, exist_ok=True)
+
+
+message_handle = on_message(priority=7, block=True, rule=check)
+
+
+@message_handle.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ path = data_dir / f"{event.group_id}"
+ q = await WordBank.check(event.group_id, get_message_text(event.json()))
+ placeholder_list = [
+ (x.split("<_s>")[0], x.split("<_s>")[1])
+ for x in q.format.split("")[:-1]
+ ] if q.format else []
+ answer = ""
+ _a = q.answer
+ if not placeholder_list:
+ answer = _a
+ else:
+ for idx, placeholder in placeholder_list:
+ if placeholder.endswith("jpg"):
+ answer += _a[:_a.find(f"[__placeholder_{idx}]")] + image(path / placeholder)
+ else:
+ answer += _a[:_a.find(f"[__placeholder_{idx}]")] + at(placeholder)
+ _a = _a[_a.find(f"[__placeholder_{idx}]") + len(f"[__placeholder_{idx}]"):]
+ await message_handle.send(answer)
diff --git a/plugins/word_bank/model.py b/plugins/word_bank/model.py
new file mode 100644
index 00000000..b4d2e265
--- /dev/null
+++ b/plugins/word_bank/model.py
@@ -0,0 +1,189 @@
+from services.db_context import db
+from typing import Optional, List, Union, Tuple
+from datetime import datetime
+from pathlib import Path
+from configs.path_config import DATA_PATH
+import random
+
+
+class WordBank(db.Model):
+ __tablename__ = "word_bank"
+
+ user_qq = db.Column(db.BigInteger(), nullable=False)
+ group_id = db.Column(db.Integer())
+ search_type = db.Column(db.Integer(), nullable=False, default=0)
+ problem = db.Column(db.String(), nullable=False)
+ answer = db.Column(db.String(), nullable=False)
+ format = db.Column(db.String())
+ create_time = db.Column(db.DateTime(), nullable=False)
+ update_time = db.Column(db.DateTime(), nullable=False)
+
+ @classmethod
+ async def add_problem_answer(
+ cls,
+ user_id: int,
+ group_id: Optional[int],
+ problem: str,
+ answer: str,
+ format_: Optional[List[Tuple[int, Union[int, str]]]],
+ ) -> bool:
+ """
+ 添加或新增一个问答
+ :param user_id: 用户id
+ :param group_id: 群号
+ :param problem: 问题
+ :param answer: 回答
+ :param format_: 格式化数据
+ """
+ _str = None
+ if format_:
+ _str = ""
+ for x, y in format_:
+ _str += f"{x}<_s>{y}"
+ return await cls._problem_answer_handle(
+ user_id, group_id, problem, "add", answer=answer, format_=_str
+ )
+
+ @classmethod
+ async def delete_problem_answer(
+ cls, user_id: int, group_id: Optional[int], problem: str, index: Optional[int]
+ ) -> str:
+ """
+ 删除某问题一个或全部回答
+ :param user_id: 用户id
+ :param group_id: 群号
+ :param problem: 问题
+ :param index: 回答下标
+ """
+ return await cls._problem_answer_handle(
+ user_id, group_id, problem, "delete", index=index
+ )
+
+ @classmethod
+ async def get_problem_answer(
+ cls, user_id: int, group_id: Optional[int], problem: str
+ ) -> List[str]:
+ """
+ 获取问题的所有回答
+ :param user_id: 用户id
+ :param group_id: 群号
+ :param problem: 问题
+ """
+ return await cls._problem_answer_handle(user_id, group_id, problem, "get")
+
+ @classmethod
+ async def get_group_all_answer(cls, group_id: int, problem: str) -> List[str]:
+ """
+ 获取群聊指定词条所有回答
+ :param group_id: 群号
+ :param problem: 问题
+ """
+ if problem.startswith("id:"):
+ problem_index = int(problem.split(":")[-1])
+ q = await cls.get_group_all_problem(group_id)
+ if len(q) > problem_index:
+ problem = q[problem_index]
+ q = await cls.query.where(
+ (cls.group_id == group_id) & (cls.problem == problem)
+ ).gino.all()
+ return [x.answer for x in q] if q else None
+
+ @classmethod
+ async def get_group_all_problem(cls, group_id: int) -> List[str]:
+ """
+ 获取群聊所有词条
+ :param group_id: 群号
+ """
+ q = await cls.query.where(cls.group_id == group_id).gino.all()
+ q = [x.problem for x in q]
+ q.sort()
+ return list(set(q))
+
+ @classmethod
+ async def check(cls, group_id: int, problem: str) -> Optional["WordBank"]:
+ """
+ 检测词条并随机返回
+ :param group_id: 群号
+ :param problem: 问题
+ """
+ q = await cls.query.where(
+ (cls.group_id == group_id) & (cls.problem == problem)
+ ).gino.all()
+ return random.choice(q) if q else None
+
+ @classmethod
+ async def _problem_answer_handle(
+ cls,
+ user_id: int,
+ group_id: Optional[int],
+ problem: str,
+ type_: str,
+ *,
+ answer: Optional[str] = None,
+ index: Optional[int] = None,
+ format_: Optional[str] = None,
+ ) -> Union[List[Union[str, Tuple[str, str]]], bool, str]:
+ """
+ 添加或新增一个问答
+ :param user_id: 用户id
+ :param group_id: 群号
+ :param problem: 问题
+ :param type_: 操作类型
+ :param answer: 回答
+ :param format_: 格式化数据
+ """
+ if problem.startswith("id:"):
+ problem_index = int(problem.split(":")[-1])
+ q = await cls.get_group_all_problem(group_id)
+ if not q:
+ return []
+ if len(q) > problem_index:
+ problem = q[problem_index]
+ if group_id:
+ q = cls.query.where((cls.group_id == group_id) & (cls.problem == problem))
+ else:
+ q = cls.query.where((cls.user_qq == user_id) & (cls.problem == problem))
+ if type_ == "add":
+ q = await q.where(cls.answer == answer).gino.all()
+ if not q or ".jpg" in format_:
+ await cls.create(
+ user_qq=user_id,
+ group_id=group_id,
+ problem=problem,
+ answer=answer,
+ format=format_,
+ create_time=datetime.now().date(),
+ update_time=datetime.now().date(),
+ )
+ return True
+ elif type_ == "delete":
+ q = await q.with_for_update().gino.all()
+ if q:
+ path = Path(DATA_PATH) / "word_bank" / f"{group_id}"
+ if index is not None:
+ _q = [x.problem for x in q]
+ _q.sort()
+ prob = _q[index]
+ index = [x.problem for x in q].index(prob)
+ q = [q[index]]
+ answer = "\n".join([x.answer for x in q])
+ for x in q:
+ format_ = x.format
+ if format_:
+ for sp in format_.split("")[:-1]:
+ _, image_name = sp.split("<_s>")
+ if image_name.endswith("jpg"):
+ _path = path / image_name
+ if _path.exists():
+ _path.unlink()
+ await cls.delete.where(
+ (cls.problem == problem)
+ & (cls.answer == x.answer)
+ & (cls.group_id == group_id)
+ ).gino.status()
+ return answer
+ elif type_ == "get":
+ q = await q.gino.all()
+ if q:
+ return [(x.answer, x.format.split("")[:-1]) for x in q]
+ return False
diff --git a/plugins/word_bank/rule.py b/plugins/word_bank/rule.py
new file mode 100644
index 00000000..b93a9e89
--- /dev/null
+++ b/plugins/word_bank/rule.py
@@ -0,0 +1,12 @@
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, Event
+from utils.utils import get_message_text
+from nonebot.typing import T_State
+from .model import WordBank
+
+
+async def check(bot: Bot, event: Event, state: T_State) -> bool:
+ if isinstance(event, GroupMessageEvent):
+ return bool(
+ await WordBank.check(event.group_id, get_message_text(event.json()))
+ )
+ return False
diff --git a/plugins/word_bank/word_hanlde.py b/plugins/word_bank/word_hanlde.py
new file mode 100644
index 00000000..2ef837b2
--- /dev/null
+++ b/plugins/word_bank/word_hanlde.py
@@ -0,0 +1,155 @@
+from utils.utils import get_message_at, is_number, get_message_imgs, get_message_text
+from services.log import logger
+from configs.path_config import DATA_PATH
+from utils.http_utils import AsyncHttpx
+from .data_source import WordBankBuilder
+from configs.config import Config
+from .model import WordBank
+from nonebot.adapters.cqhttp import (
+ Bot,
+ GroupMessageEvent,
+)
+from pathlib import Path
+from nonebot.typing import T_State
+from nonebot import on_command
+import random
+import re
+
+__zx_plugin_name__ = "词库问答 [Admin]"
+__plugin_usage__ = """
+usage:
+ 对指定问题的随机回答,对相同问题可以设置多个不同回答
+ 删除词条后每个词条的id可能会变化,请查看后再删除
+ 指令:
+ 添加词条问...答...:添加问答词条,可重复添加相同问题的不同回答
+ 删除词条 [问题/下标] ?[下标]:删除指定词条指定或全部回答
+ 查看词条 ?[问题/下标]:查看全部词条或对应词条回答
+ 示例:添加词条问谁是萝莉答是我
+ 示例:删除词条 谁是萝莉
+ 示例:删除词条 谁是萝莉 0
+ 示例:删除词条 id:0
+ 示例:查看词条
+ 示例:查看词条 谁是萝莉
+ 示例:查看词条 id:0
+""".strip()
+__plugin_des__ = "自定义词条内容随机回复"
+__plugin_cmd__ = [
+ "添加词条问...答..",
+ "删除词条 [问题/下标] ?[下标]",
+ "查看词条 ?[问题/下标]",
+]
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "admin_level": Config.get_config("word_bank", "WORD_BANK_LEVEL"),
+ "cmd": ["词库问答", "添加词条", "删除词条", "查看词条"]
+}
+
+data_dir = Path(DATA_PATH) / "word_bank"
+data_dir.mkdir(parents=True, exist_ok=True)
+
+
+add_word = on_command("添加词条", priority=5, block=True)
+
+delete_word = on_command("删除词条", priority=5, block=True)
+
+show_word = on_command("显示词条", aliases={"查看词条"}, priority=5, block=True)
+
+
+@add_word.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ msg = str(event.get_message()).strip()
+ r = re.search(r"^问(.+)\s?答(.*)", msg)
+ if not r:
+ await add_word.finish("未检测到词条问题...")
+ problem = r.group(1).strip()
+ answer = r.group(2).strip()
+ if not answer:
+ await add_word.finish("未检测到词条回答...")
+ idx = 0
+ _builder = WordBankBuilder(event.user_id, event.group_id, problem)
+ for at_ in get_message_at(event.json()):
+ r = re.search(rf"\[CQ:at,qq={at_}]", answer)
+ if r:
+ answer = answer.replace(f"[CQ:at,qq={at_}]", f"[__placeholder_{idx}]", 1)
+ _builder.set_placeholder(idx, at_)
+ idx += 1
+ for img in get_message_imgs(event.json()):
+ _x = img.split("?")[0]
+ r = re.search(rf"\[CQ:image,file=(.*),url={_x}.*?]", answer)
+ if r:
+ rand = random.randint(1, 10000) + random.randint(1, 14514)
+ for i in range(3):
+ answer = answer.replace(f",subType={i}", "")
+ answer = answer.replace(
+ rf"[CQ:image,file={r.group(1)},url={img}]", f"[__placeholder_{idx}]",
+ )
+ await AsyncHttpx.download_file(
+ img, data_dir / f"{event.group_id}" / f"__placeholder_{rand}_{idx}.jpg"
+ )
+ _builder.set_placeholder(idx, f"__placeholder_{rand}_{idx}.jpg")
+ idx += 1
+ _builder.set_answer(answer)
+ await _builder.save()
+ logger.info(f"已保存词条 问:{problem} 答:{msg}")
+ await add_word.send(f"已保存词条:{problem}")
+
+
+@delete_word.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if not msg:
+ await delete_word.finish("此命令之后需要跟随指定词条,通过“显示词条“查看")
+ index = None
+ _sp_msg = msg.split()
+ if len(_sp_msg) > 1:
+ if is_number(_sp_msg[-1]):
+ index = int(_sp_msg[-1])
+ msg = " ".join(_sp_msg[:-1])
+ problem = msg
+ if problem.startswith("id:"):
+ x = problem.split(":")[-1]
+ if not is_number(x) or int(x) < 0:
+ await delete_word.finish("id必须为数字且符合规范!")
+ p = (await WordBank.get_group_all_problem(event.group_id))
+ if p:
+ problem = p[int(x)]
+ try:
+ if answer := await WordBank.delete_problem_answer(event.user_id, event.group_id, problem, index):
+ await delete_word.send(f"删除词条成功:{problem}\n回答:\n{answer}")
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 删除词条: {problem}"
+ )
+ else:
+ await delete_word.send(f"删除词条:{problem} 失败,可能该词条不存在")
+ except IndexError:
+ await delete_word.send("指定下标错误...请通过查看词条来确定..")
+
+
+@show_word.handle()
+async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
+ msg = get_message_text(event.json())
+ if not msg:
+ _problem_list = await WordBank.get_group_all_problem(event.group_id)
+ if not _problem_list:
+ await show_word.finish("该群未收录任何词条..")
+ _problem_list = [f"{i}. {x}" for i, x in enumerate(_problem_list)]
+ await show_word.send(
+ "该群已收录的词条:\n" + "\n".join(_problem_list)
+ )
+ else:
+ _answer_list = await WordBank.get_group_all_answer(event.group_id, msg)
+ if not _answer_list:
+ await show_word.send(
+ "未收录该词条..."
+ )
+ else:
+ _answer_list = [f"{i}. {x}" for i, x in enumerate(_answer_list)]
+ await show_word.send(
+ f"词条 {msg} 回答:\n" + "\n".join(_answer_list)
+ )
+
+
+
diff --git a/plugins/yiqing/__init__.py b/plugins/yiqing/__init__.py
old mode 100644
new mode 100755
diff --git a/plugins/yiqing/data_source.py b/plugins/yiqing/data_source.py
old mode 100644
new mode 100755
index f56c638e..02a7381f
--- a/plugins/yiqing/data_source.py
+++ b/plugins/yiqing/data_source.py
@@ -1,9 +1,8 @@
-from utils.user_agent import get_user_agent
from configs.path_config import TEXT_PATH
from typing import List
from pathlib import Path
+from utils.http_utils import AsyncHttpx
import ujson as json
-import aiohttp
china_city = Path(TEXT_PATH) / "china_city.json"
@@ -14,6 +13,10 @@ url = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5"
async def get_yiqing_data(area: str):
+ """
+ 查看疫情数据
+ :param area: 省份/城市
+ """
global data
province = None
city = None
@@ -32,31 +35,29 @@ async def get_yiqing_data(area: str):
if area in data[p]:
province = p
city = area
- async with aiohttp.ClientSession(headers=get_user_agent()) as session:
- async with session.get(url, timeout=7) as response:
- epidemic_data = json.loads((await response.json())["data"])
- last_update_time = epidemic_data["lastUpdateTime"]
- if area == "中国":
- data_ = epidemic_data["areaTree"][0]
- else:
- data_ = [
- x
- for x in epidemic_data["areaTree"][0]["children"]
- if x["name"] == province
- ][0]
- if city:
- try:
- data_ = [x for x in data_["children"] if x["name"] == city][0]
- except IndexError:
- return "未查询到..."
- confirm = data_["total"]["confirm"] # 累计确诊
- heal = data_["total"]["heal"] # 累计治愈
- dead = data_["total"]["dead"] # 累计死亡
- dead_rate = data_["total"]["deadRate"] # 死亡率
- heal_rate = data_["total"]["healRate"] # 治愈率
- now_confirm = data_["total"]["nowConfirm"] # 目前确诊
- suspect = data_["total"]["suspect"] # 疑似
- add_confirm = data_["today"]["confirm"] # 新增确诊
+ epidemic_data = json.loads((await AsyncHttpx.get(url)).json()["data"])
+ last_update_time = epidemic_data["lastUpdateTime"]
+ if area == "中国":
+ data_ = epidemic_data["areaTree"][0]
+ else:
+ data_ = [
+ x
+ for x in epidemic_data["areaTree"][0]["children"]
+ if x["name"] == province
+ ][0]
+ if city:
+ try:
+ data_ = [x for x in data_["children"] if x["name"] == city][0]
+ except IndexError:
+ return "未查询到..."
+ confirm = data_["total"]["confirm"] # 累计确诊
+ heal = data_["total"]["heal"] # 累计治愈
+ dead = data_["total"]["dead"] # 累计死亡
+ dead_rate = data_["total"]["deadRate"] # 死亡率
+ heal_rate = data_["total"]["healRate"] # 治愈率
+ now_confirm = data_["total"]["nowConfirm"] # 目前确诊
+ suspect = data_["total"]["suspect"] # 疑似
+ add_confirm = data_["today"]["confirm"] # 新增确诊
x = f"{city}市" if city else f"{province}{province_type}"
return (
f"{x} 疫情数据:\n"
@@ -75,6 +76,9 @@ async def get_yiqing_data(area: str):
def get_city_and_province_list() -> List[str]:
+ """
+ 获取城市省份列表
+ """
global data
if not data:
try:
diff --git a/update_info.json b/update_info.json
index 394dbad2..74df5904 100644
--- a/update_info.json
+++ b/update_info.json
@@ -1,12 +1,10 @@
{
"update_file": [
"plugins",
- "configs",
"models",
- "services",
+ "basic_plugins",
"utils",
- "bot.py"
],
- "add_file": ["basic_plugins", "resources/img/background/check"],
+ "add_file": [],
"delete_file": []
}
diff --git a/utils/__init__.py b/utils/__init__.py
old mode 100644
new mode 100755
diff --git a/utils/browser.py b/utils/browser.py
old mode 100644
new mode 100755
index b08f728b..f5563ce6
--- a/utils/browser.py
+++ b/utils/browser.py
@@ -1,41 +1,41 @@
-from typing import Optional
-from nonebot.log import logger
-from playwright.async_api import Browser, async_playwright
-import nonebot
-from nonebot import Driver
-from services.log import logger
-import platform
-
-
-driver: Driver = nonebot.get_driver()
-
-
-_browser: Optional[Browser] = None
-
-
-async def init(**kwargs) -> Optional[Browser]:
- if platform.system() == "Windows":
- return None
- try:
- global _browser
- browser = await async_playwright().start()
- _browser = await browser.chromium.launch(**kwargs)
- return _browser
- except NotImplementedError:
- logger.warning("win环境下 初始化playwright失败....请替换环境至linux")
- return None
-
-
-async def get_browser(**kwargs) -> Browser:
- return _browser or await init(**kwargs)
-
-
-@driver.on_startup
-def install():
- """自动安装、更新 Chromium"""
- logger.info("正在检查 Chromium 更新")
- import sys
- from playwright.__main__ import main
-
- sys.argv = ["", "install", "chromium"]
- main()
+from typing import Optional
+from nonebot.log import logger
+from playwright.async_api import Browser, async_playwright
+import nonebot
+from nonebot import Driver
+from services.log import logger
+import platform
+
+
+driver: Driver = nonebot.get_driver()
+
+
+_browser: Optional[Browser] = None
+
+
+async def init(**kwargs) -> Optional[Browser]:
+ if platform.system() == "Windows":
+ return None
+ try:
+ global _browser
+ browser = await async_playwright().start()
+ _browser = await browser.chromium.launch(**kwargs)
+ return _browser
+ except NotImplementedError:
+ logger.warning("win环境下 初始化playwright失败....请替换环境至linux")
+ return None
+
+
+async def get_browser(**kwargs) -> Browser:
+ return _browser or await init(**kwargs)
+
+
+@driver.on_startup
+def install():
+ """自动安装、更新 Chromium"""
+ logger.info("正在检查 Chromium 更新")
+ import sys
+ from playwright.__main__ import main
+
+ sys.argv = ["", "install", "chromium"]
+ main()
diff --git a/utils/data_utils.py b/utils/data_utils.py
old mode 100644
new mode 100755
diff --git a/utils/http_utils.py b/utils/http_utils.py
new file mode 100644
index 00000000..9140d743
--- /dev/null
+++ b/utils/http_utils.py
@@ -0,0 +1,325 @@
+from typing import Dict, Union, Optional, List, Any, Literal
+from utils.user_agent import get_user_agent
+from .utils import get_local_proxy
+from services.log import logger
+from pathlib import Path
+from httpx import Response
+from asyncio.exceptions import TimeoutError
+from nonebot.adapters.cqhttp import MessageSegment
+from playwright.async_api import Page
+from .message_builder import image
+from .browser import get_browser
+import asyncio
+import aiofiles
+import httpx
+
+
+class AsyncHttpx:
+
+ proxy = {"http://": get_local_proxy()}
+
+ @classmethod
+ async def get(
+ cls,
+ url: str,
+ *,
+ params: Optional[Dict[str, Any]] = None,
+ headers: Optional[Dict[str, str]] = None,
+ cookies: Optional[Dict[str, str]] = None,
+ use_proxy: bool = True,
+ proxy: Dict[str, str] = None,
+ allow_redirects: bool = True,
+ timeout: Optional[int] = 30,
+ ) -> Response:
+ """
+ Get
+ :param url: url
+ :param params: params
+ :param headers: 请求头
+ :param cookies: cookies
+ :param use_proxy: 使用默认代理
+ :param proxy: 指定代理
+ :param allow_redirects: allow_redirects
+ :param timeout: 超时时间
+ """
+ if not headers:
+ headers = get_user_agent()
+ proxy = proxy if proxy else cls.proxy if use_proxy else None
+ async with httpx.AsyncClient(proxies=proxy) as client:
+ return await client.get(
+ url,
+ params=params,
+ headers=headers,
+ cookies=cookies,
+ allow_redirects=allow_redirects,
+ timeout=timeout,
+ )
+
+ @classmethod
+ async def post(
+ cls,
+ url: str,
+ *,
+ data: Optional[Dict[str, str]] = None,
+ content: Any = None,
+ files: Any = None,
+ use_proxy: bool = True,
+ proxy: Dict[str, str] = None,
+ json: Optional[Dict[str, Union[Any]]] = None,
+ params: Optional[Dict[str, str]] = None,
+ headers: Optional[Dict[str, str]] = None,
+ cookies: Optional[Dict[str, str]] = None,
+ allow_redirects: bool = True,
+ timeout: Optional[int] = 30,
+ ) -> Response:
+ """
+ Post
+ :param url: url
+ :param data: data
+ :param content: content
+ :param files: files
+ :param use_proxy: 是否默认代理
+ :param proxy: 指定代理
+ :param json: json
+ :param params: params
+ :param headers: 请求头
+ :param cookies: cookies
+ :param allow_redirects: allow_redirects
+ :param timeout: 超时时间
+ """
+ if not headers:
+ headers = get_user_agent()
+ proxy = proxy if proxy else cls.proxy if use_proxy else None
+ async with httpx.AsyncClient(proxies=proxy) as client:
+ return await client.post(
+ url,
+ content=content,
+ data=data,
+ files=files,
+ json=json,
+ params=params,
+ headers=headers,
+ cookies=cookies,
+ allow_redirects=allow_redirects,
+ timeout=timeout,
+ )
+
+ @classmethod
+ async def download_file(
+ cls,
+ url: str,
+ path: Union[str, Path],
+ *,
+ params: Optional[Dict[str, str]] = None,
+ use_proxy: bool = True,
+ proxy: Dict[str, str] = None,
+ headers: Optional[Dict[str, str]] = None,
+ cookies: Optional[Dict[str, str]] = None,
+ timeout: Optional[int] = 30,
+ ) -> bool:
+ """
+ 下载文件
+ :param url: url
+ :param path: 存储路径
+ :param params: params
+ :param use_proxy: 使用代理
+ :param proxy: 指定代理
+ :param headers: 请求头
+ :param cookies: cookies
+ :param timeout: 超时时间
+ """
+ if isinstance(path, str):
+ path = Path(path)
+ path.parent.mkdir(parents=True, exist_ok=True)
+ try:
+ for _ in range(3):
+ try:
+ content = (
+ await cls.get(
+ url,
+ params=params,
+ headers=headers,
+ cookies=cookies,
+ use_proxy=use_proxy,
+ proxy=proxy,
+ timeout=timeout,
+ )
+ ).content
+ async with aiofiles.open(path, "wb") as wf:
+ await wf.write(content)
+ logger.info(f"下载图片 {url} 成功.. Path:{path.absolute()}")
+ return True
+ except TimeoutError:
+ pass
+ else:
+ logger.error(f"下载图片 {url} 下载超时.. Path:{path.absolute()}")
+ except Exception as e:
+ logger.error(f"下载图片 {url} 未知错误 {type(e)}:{e}.. Path:{path.absolute()}")
+ return False
+
+ @classmethod
+ async def gather_download_file(
+ cls,
+ url_list: List[str],
+ path_list: List[Union[str, Path]],
+ *,
+ limit_async_number: Optional[int] = None,
+ params: Optional[Dict[str, str]] = None,
+ use_proxy: bool = True,
+ proxy: Dict[str, str] = None,
+ headers: Optional[Dict[str, str]] = None,
+ cookies: Optional[Dict[str, str]] = None,
+ timeout: Optional[int] = 30,
+ ) -> List[bool]:
+ """
+ 分组同时下载文件
+ :param url_list: url列表
+ :param path_list: 存储路径列表
+ :param limit_async_number: 限制同时请求数量
+ :param params: params
+ :param use_proxy: 使用代理
+ :param proxy: 指定代理
+ :param headers: 请求头
+ :param cookies: cookies
+ :param timeout: 超时时间
+ :return:
+ """
+ if n := len(url_list) != len(path_list):
+ raise UrlPathNumberNotEqual(
+ f"Url数量与Path数量不对等,Url:{len(url_list)},Path:{len(path_list)}"
+ )
+ if limit_async_number and n > limit_async_number:
+ m = float(n) / limit_async_number
+ x = 0
+ j = limit_async_number
+ _split_url_list = []
+ _split_path_list = []
+ for _ in range(int(m)):
+ _split_url_list.append(url_list[x:j])
+ _split_path_list.append(path_list[x:j])
+ x += limit_async_number
+ j += limit_async_number
+ if int(m) < m:
+ _split_url_list.append(url_list[j:])
+ _split_path_list.append(path_list[j:])
+ else:
+ _split_url_list = [url_list]
+ _split_path_list = [path_list]
+ tasks = []
+ result_ = []
+ for x, y in zip(_split_url_list, _split_path_list):
+ for url, path in zip(x, y):
+ tasks.append(
+ asyncio.create_task(
+ cls.download_file(
+ url,
+ path,
+ params=params,
+ headers=headers,
+ cookies=cookies,
+ use_proxy=use_proxy,
+ timeout=timeout,
+ proxy=proxy
+ )
+ )
+ )
+ _x = await asyncio.gather(*tasks)
+ result_ = result_ + list(_x)
+ tasks.clear()
+ return result_
+
+
+class AsyncPlaywright:
+
+ @classmethod
+ async def _new_page(cls, user_agent: Optional[str] = None) -> Page:
+ """
+ 获取一个新页面
+ :param user_agent: 请求头
+ """
+ browser = await get_browser()
+ if browser:
+ return await browser.new_page(user_agent=user_agent)
+ raise BrowserIsNone("获取Browser失败...")
+
+ @classmethod
+ async def goto(
+ cls,
+ url: str,
+ *,
+ timeout: Optional[float] = 100000,
+ wait_until: Optional[
+ Literal["domcontentloaded", "load", "networkidle"]
+ ] = "networkidle",
+ referer: str = None,
+ ) -> Optional[Page]:
+ """
+ goto
+ :param url: 网址
+ :param timeout: 超时限制
+ :param wait_until: 等待类型
+ :param referer:
+ """
+ page = None
+ try:
+ page = await cls._new_page()
+ await page.goto(url, timeout=timeout, wait_until=wait_until, referer=referer)
+ return page
+ except Exception as e:
+ logger.warning(f"Playwright 访问 url:{url} 发生错误 {type(e)}:{e}")
+ if page:
+ await page.close()
+ return None
+
+ @classmethod
+ async def screenshot(
+ cls,
+ url: str,
+ path: Union[Path, str],
+ element: str,
+ *,
+ sleep: Optional[int] = None,
+ viewport_size: Dict[str, int] = None,
+ wait_until: Optional[
+ Literal["domcontentloaded", "load", "networkidle"]
+ ] = "networkidle",
+ timeout: float = None,
+ type_: Literal["jpeg", "png"] = None,
+ ) -> Optional[MessageSegment]:
+ """
+ 截图,该方法仅用于简单快捷截图,复杂截图请操作 page
+ :param url: 网址
+ :param path: 存储路径
+ :param element: 元素选择
+ :param sleep: 延迟截取
+ :param viewport_size: 窗口大小
+ :param wait_until: 等待类型
+ :param timeout: 超时限制
+ :param type_: 保存类型
+ """
+ page = None
+ if viewport_size is None:
+ viewport_size = dict(width=2560, height=1080)
+ if isinstance(path, str):
+ path = Path(path)
+ try:
+ page = await cls.goto(url, wait_until=wait_until)
+ await page.set_viewport_size(viewport_size)
+ if sleep:
+ await asyncio.sleep(sleep)
+ card = await page.query_selector(element)
+ await card.screenshot(path=path, timeout=timeout, type=type_)
+ return image(path)
+ except Exception as e:
+ logger.warning(f"Playwright 截图 url:{url} element:{element} 发生错误 {type(e)}:{e}")
+ if page:
+ await page.close()
+ return None
+
+
+class UrlPathNumberNotEqual(Exception):
+ pass
+
+
+class BrowserIsNone(Exception):
+ pass
diff --git a/utils/image_utils.py b/utils/image_utils.py
old mode 100644
new mode 100755
index 6db72d32..50096e9f
--- a/utils/image_utils.py
+++ b/utils/image_utils.py
@@ -3,7 +3,7 @@ from PIL import Image, ImageFile, ImageDraw, ImageFont, ImageFilter
from imagehash import ImageHash
from io import BytesIO
from matplotlib import pyplot as plt
-from typing import Tuple, Optional, Union, List
+from typing import Tuple, Optional, Union, List, Literal
from pathlib import Path
from math import ceil
import random
@@ -38,7 +38,7 @@ def compare_image_with_hash(
return False
-def get_img_hash(image_file: str) -> ImageHash:
+def get_img_hash(image_file: Union[str, Path]) -> ImageHash:
"""
说明:
获取图片的hash值
@@ -225,7 +225,7 @@ class CreateImg:
img: "CreateImg" or Image,
pos: Tuple[int, int] = None,
alpha: bool = False,
- center_type: Optional[str] = None,
+ center_type: Optional[Literal["center", "by_height", "by_width"]] = None,
):
"""
说明:
@@ -313,7 +313,7 @@ class CreateImg:
pos: Tuple[int, int],
text: str,
fill: Tuple[int, int, int] = (0, 0, 0),
- center_type: Optional[str] = None,
+ center_type: Optional[Literal["center", "by_height", "by_width"]] = None,
):
"""
说明:
@@ -867,7 +867,10 @@ class CreateMat:
font_h = self.markImg.getsize(str(y[i]))[1]
self.markImg.text(
(
- self.padding_w + int(y[i] * self._p * self._deviation) + 2 + 5,
+ self.padding_w
+ + int(y[i] * self._p * self._deviation)
+ + 2
+ + 5,
current_h - int(font_h / 2) - 1,
),
f"{y[i]:.2f}" if isinstance(y[i], float) else f"{y[i]}",
@@ -937,7 +940,9 @@ class CreateMat:
padding_h = self.padding_h
line_length = self.line_length
background = random.choice(self.background) if self.background else None
- A = CreateImg(self.w, self.h, font_size=font_size, font=self.font, background=background)
+ A = CreateImg(
+ self.w, self.h, font_size=font_size, font=self.font, background=background
+ )
if background:
_tmp = CreateImg(self.w, self.h)
_tmp.transparent(2)
@@ -950,7 +955,7 @@ class CreateMat:
color=(255, 255, 255, 0),
font_size=35,
font_color=self._color.get("title"),
- font=self.font
+ font=self.font,
)
A.paste(title, (0, 25), True, "by_width")
A.line(
@@ -993,7 +998,7 @@ class CreateMat:
plain_text=f"{_x}",
font_size=self.font_size,
color=(255, 255, 255, 0),
- font=self.font
+ font=self.font,
)
text.rotate(self.x_rotate, True)
A.paste(text, (current_w - w, padding_h + line_length + 10), alpha=True)
@@ -1013,7 +1018,7 @@ class CreateMat:
plain_text=f"{_y}",
font_size=self.font_size,
color=(255, 255, 255, 0),
- font=self.font
+ font=self.font,
)
idx = 0
while text.size[0] > self.padding_w - 10 and idx < 3:
@@ -1023,7 +1028,7 @@ class CreateMat:
plain_text=f"{_y}",
font_size=int(self.font_size * 0.75),
color=(255, 255, 255, 0),
- font=self.font
+ font=self.font,
)
w, _ = text.getsize(f"{_y}")
idx += 1
@@ -1033,8 +1038,10 @@ class CreateMat:
A.text((int(padding_w / 2), int(padding_w / 2)), x_name)
if y_name:
A.text(
- (int(padding_w + line_length + 50 - A.getsize(y_name)[0]),
- int(padding_h + line_length + 50 + x_rotate_height)),
+ (
+ int(padding_w + line_length + 50 - A.getsize(y_name)[0]),
+ int(padding_h + line_length + 50 + x_rotate_height),
+ ),
y_name,
)
return A
diff --git a/utils/langconv.py b/utils/langconv.py
old mode 100644
new mode 100755
diff --git a/utils/manager/__init__.py b/utils/manager/__init__.py
old mode 100644
new mode 100755
index ce83637b..15ab6c27
--- a/utils/manager/__init__.py
+++ b/utils/manager/__init__.py
@@ -1,71 +1,72 @@
-from typing import Optional
-from .group_manager import GroupManager
-from pathlib import Path
-from .data_class import StaticData
-from .withdraw_message_manager import WithdrawMessageManager
-from .plugins2cd_manager import Plugins2cdManager
-from .plugins2block_manager import Plugins2blockManager
-from .plugins2count_manager import Plugins2countManager
-from .plugins2settings_manager import Plugins2settingsManager
-from .plugins_manager import PluginsManager
-from .resources_manager import ResourcesManager
-from .admin_manager import AdminManager
-from .none_plugin_count_manager import NonePluginCountManager
-from .requests_manager import RequestManager
-from configs.path_config import DATA_PATH
-from nonebot import Driver
-import nonebot
-
-driver: Driver = nonebot.get_driver()
-
-# 群功能开关 | 群被动技能 | 群权限 管理
-group_manager: Optional[GroupManager] = GroupManager(
- Path(DATA_PATH) / "manager" / "group_manager.json"
-)
-# 撤回消息管理
-withdraw_message_manager: Optional[WithdrawMessageManager] = WithdrawMessageManager()
-
-# 插件管理
-plugins_manager: Optional[PluginsManager] = PluginsManager(
- Path(DATA_PATH) / "manager" / "plugins_manager.json"
-)
-
-# 插件基本设置管理
-plugins2settings_manager: Optional[Plugins2settingsManager] = Plugins2settingsManager(
- Path(DATA_PATH) / "configs" / "plugins2settings.yaml"
-)
-
-# 插件命令 cd 管理
-plugins2cd_manager: Optional[Plugins2cdManager] = Plugins2cdManager(
- Path(DATA_PATH) / "configs" / "plugins2cd.yaml"
-)
-
-# 插件命令 阻塞 管理
-plugins2block_manager: Optional[Plugins2blockManager] = Plugins2blockManager(
- Path(DATA_PATH) / "configs" / "plugins2block.yaml"
-)
-
-# 插件命令 每次次数限制 管理
-plugins2count_manager: Optional[Plugins2countManager] = Plugins2countManager(
- Path(DATA_PATH) / "configs" / "plugins2count.yaml"
-)
-
-# 资源管理
-resources_manager: Optional[ResourcesManager] = ResourcesManager(
- Path(DATA_PATH) / "manager" / "resources_manager.json"
-)
-
-# 插件加载容忍管理
-none_plugin_count_manager: Optional[NonePluginCountManager] = NonePluginCountManager(
- Path(DATA_PATH) / "manager" / "none_plugin_count_manager.json"
-)
-
-# 好友请求/群聊邀请 管理
-requests_manager: Optional[RequestManager] = RequestManager(
- Path(DATA_PATH) / "manager" / "requests_manager.json"
-)
-
-
-# 管理员命令管理器
-admin_manager = AdminManager()
-
+from typing import Optional
+from .group_manager import GroupManager
+from pathlib import Path
+from .data_class import StaticData
+from .withdraw_message_manager import WithdrawMessageManager
+from .plugins2cd_manager import Plugins2cdManager
+from .plugins2block_manager import Plugins2blockManager
+from .plugins2count_manager import Plugins2countManager
+from .plugins2settings_manager import Plugins2settingsManager
+from .plugins_manager import PluginsManager
+from .resources_manager import ResourcesManager
+from .admin_manager import AdminManager
+from .none_plugin_count_manager import NonePluginCountManager
+from .requests_manager import RequestManager
+from configs.path_config import DATA_PATH
+from nonebot import Driver
+import nonebot
+
+driver: Driver = nonebot.get_driver()
+
+# 群功能开关 | 群被动技能 | 群权限 管理
+group_manager: Optional[GroupManager] = GroupManager(
+ Path(DATA_PATH) / "manager" / "group_manager.json"
+)
+
+# 撤回消息管理
+withdraw_message_manager: Optional[WithdrawMessageManager] = WithdrawMessageManager()
+
+# 插件管理
+plugins_manager: Optional[PluginsManager] = PluginsManager(
+ Path(DATA_PATH) / "manager" / "plugins_manager.json"
+)
+
+# 插件基本设置管理
+plugins2settings_manager: Optional[Plugins2settingsManager] = Plugins2settingsManager(
+ Path(DATA_PATH) / "configs" / "plugins2settings.yaml"
+)
+
+# 插件命令 cd 管理
+plugins2cd_manager: Optional[Plugins2cdManager] = Plugins2cdManager(
+ Path(DATA_PATH) / "configs" / "plugins2cd.yaml"
+)
+
+# 插件命令 阻塞 管理
+plugins2block_manager: Optional[Plugins2blockManager] = Plugins2blockManager(
+ Path(DATA_PATH) / "configs" / "plugins2block.yaml"
+)
+
+# 插件命令 每次次数限制 管理
+plugins2count_manager: Optional[Plugins2countManager] = Plugins2countManager(
+ Path(DATA_PATH) / "configs" / "plugins2count.yaml"
+)
+
+# 资源管理
+resources_manager: Optional[ResourcesManager] = ResourcesManager(
+ Path(DATA_PATH) / "manager" / "resources_manager.json"
+)
+
+# 插件加载容忍管理
+none_plugin_count_manager: Optional[NonePluginCountManager] = NonePluginCountManager(
+ Path(DATA_PATH) / "manager" / "none_plugin_count_manager.json"
+)
+
+# 好友请求/群聊邀请 管理
+requests_manager: Optional[RequestManager] = RequestManager(
+ Path(DATA_PATH) / "manager" / "requests_manager.json"
+)
+
+
+# 管理员命令管理器
+admin_manager = AdminManager()
+
diff --git a/utils/manager/admin_manager.py b/utils/manager/admin_manager.py
old mode 100644
new mode 100755
diff --git a/utils/manager/configs_manager.py b/utils/manager/configs_manager.py
old mode 100644
new mode 100755
diff --git a/utils/manager/data_class.py b/utils/manager/data_class.py
old mode 100644
new mode 100755
index 6507be8f..8e78d913
--- a/utils/manager/data_class.py
+++ b/utils/manager/data_class.py
@@ -1,77 +1,76 @@
-from typing import Union, Optional
-from pathlib import Path
-from ruamel.yaml import YAML
-import ujson as json
-
-yaml = YAML(typ="safe")
-
-
-class StaticData:
- """
- 静态数据共享类
- """
-
- def __init__(self, file: Optional[Path]):
- self._data: dict = {}
- if file:
- file.parent.mkdir(exist_ok=True, parents=True)
- self.file = file
- if file.exists():
- with open(file, "r", encoding="utf8") as f:
- if file.name.endswith("json"):
- self._data: dict = json.load(f)
- elif file.name.endswith("yaml"):
- self._data = yaml.load(f)
-
- def set(self, key, value):
- self._data[key] = value
- self.save()
-
- def set_module_data(self, module, key, value):
- if module in self._data.keys():
- self._data[module][key] = value
- self.save()
-
- def get(self, key):
- return self._data.get(key)
-
- def keys(self):
- return self._data.keys()
-
- def delete(self, key):
- if self._data.get(key) is not None:
- del self._data[key]
- self.save()
-
- def get_data(self) -> dict:
- return self._data
-
- def save(self, path: Union[str, Path] = None):
- path = path if path else self.file
- if isinstance(path, str):
- path = Path(path)
- if path:
- with open(path, "w", encoding="utf8") as f:
- json.dump(self._data, f, ensure_ascii=False, indent=4)
-
- def reload(self):
- if self.file.exists():
- if self.file.name.endswith("json"):
- self._data: dict = json.load(open(self.file, "r", encoding="utf8"))
- elif self.file.name.endswith("yaml"):
- self._data: dict = yaml.load(open(self.file, "r", encoding="utf8"))
-
- def is_exists(self):
- return self.file.exists()
-
- def is_empty(self):
- return bool(len(self._data))
-
- def __str__(self):
- return str(self._data)
-
- def __setitem__(self, key, value):
- self._data[key] = value
-
- def __getitem__(self, key):
- return self._data[key]
+from typing import Union, Optional
+from pathlib import Path
+from ruamel.yaml import YAML
+import ujson as json
+
+yaml = YAML(typ="safe")
+
+
+class StaticData:
+ """
+ 静态数据共享类
+ """
+
+ def __init__(self, file: Optional[Path]):
+ self._data: dict = {}
+ if file:
+ file.parent.mkdir(exist_ok=True, parents=True)
+ self.file = file
+ if file.exists():
+ with open(file, "r", encoding="utf8") as f:
+ if file.name.endswith("json"):
+ self._data: dict = json.load(f)
+ elif file.name.endswith("yaml"):
+ self._data = yaml.load(f)
+
+ def set(self, key, value):
+ self._data[key] = value
+ self.save()
+
+ def set_module_data(self, module, key, value):
+ if module in self._data.keys():
+ self._data[module][key] = value
+ self.save()
+
+ def get(self, key):
+ return self._data.get(key)
+
+ def keys(self):
+ return self._data.keys()
+
+ def delete(self, key):
+ if self._data.get(key) is not None:
+ del self._data[key]
+
+ def get_data(self) -> dict:
+ return self._data
+
+ def save(self, path: Union[str, Path] = None):
+ path = path if path else self.file
+ if isinstance(path, str):
+ path = Path(path)
+ if path:
+ with open(path, "w", encoding="utf8") as f:
+ json.dump(self._data, f, ensure_ascii=False, indent=4)
+
+ def reload(self):
+ if self.file.exists():
+ if self.file.name.endswith("json"):
+ self._data: dict = json.load(open(self.file, "r", encoding="utf8"))
+ elif self.file.name.endswith("yaml"):
+ self._data: dict = yaml.load(open(self.file, "r", encoding="utf8"))
+
+ def is_exists(self):
+ return self.file.exists()
+
+ def is_empty(self):
+ return bool(len(self._data))
+
+ def __str__(self):
+ return str(self._data)
+
+ def __setitem__(self, key, value):
+ self._data[key] = value
+
+ def __getitem__(self, key):
+ return self._data[key]
diff --git a/utils/manager/group_manager.py b/utils/manager/group_manager.py
old mode 100644
new mode 100755
index a0db6af0..e0104311
--- a/utils/manager/group_manager.py
+++ b/utils/manager/group_manager.py
@@ -1,295 +1,295 @@
-from typing import Optional, List, Union, Dict
-from pathlib import Path
-from .data_class import StaticData
-from utils.utils import get_matchers, get_bot
-import nonebot
-
-
-class GroupManager(StaticData):
- """
- 群权限 | 功能 | 聊天时间 管理器
- """
-
- def __init__(self, file: Path):
- super().__init__(file)
- if not self._data:
- self._data = {
- "super": {"white_group_list": []},
- "group_manager": {},
- }
- self._task = {}
-
- def block_plugin(self, module: str, group_id: int):
- """
- 说明:
- 锁定插件
- 参数:
- :param module: 功能模块名
- :param group_id: 群组,None时为超级用户禁用
- """
- self._set_plugin_status(module, "block", group_id)
-
- def unblock_plugin(self, module: str, group_id: int):
- """
- 说明:
- 解锁插件
- 参数:
- :param module: 功能模块名
- :param group_id: 群组
- """
- self._set_plugin_status(module, "unblock", group_id)
-
- def set_group_level(self, group_id: int, level: int):
- """
- 说明:
- 设置群权限
- 参数:
- :param group_id: 群组
- :param level: 权限等级
- """
- group_id = str(group_id)
- if not self._data["group_manager"].get(group_id):
- self._init_group(group_id)
- self._data["group_manager"][group_id]["level"] = level
- self.save()
-
- def get_plugin_status(self, module: str, group_id: int) -> bool:
- """
- 说明:
- 获取插件状态
- 参数:
- :param module: 功能模块名
- :param group_id: 群组
- """
- group_id = str(group_id) if group_id else group_id
- if not self._data["group_manager"].get(group_id):
- self._init_group(group_id)
- return True
- if module in self._data["group_manager"][group_id]["close_plugins"]:
- return False
- return True
-
- def get_group_level(self, group_id: int) -> int:
- """
- 说明:
- 获取群等级
- 参数:
- :param group_id: 群号
- """
- group_id = str(group_id)
- if not self._data["group_manager"].get(group_id):
- self._init_group(group_id)
- return self._data["group_manager"][group_id]["level"]
-
- def check_group_is_white(self, group_id: int) -> bool:
- """
- 说明:
- 检测群聊是否在白名单
- 参数:
- :param group_id: 群号
- """
- return group_id in self._data["super"]["white_group_list"]
-
- def add_group_white_list(self, group_id: int):
- """
- 说明:
- 将群聊加入白名单
- 参数:
- :param group_id: 群号
- """
- if group_id not in self._data["super"]["white_group_list"]:
- self._data["super"]["white_group_list"].append(group_id)
-
- def delete_group_white_list(self, group_id: int):
- """
- 说明:
- 将群聊从白名单中删除
- 参数:
- :param group_id: 群号
- """
- if group_id in self._data["super"]["white_group_list"]:
- self._data["super"]["white_group_list"].remove(group_id)
-
- def get_group_white_list(self) -> List[str]:
- """
- 说明:
- 获取所有群白名单
- """
- return self._data["super"]["white_group_list"]
-
- def delete_group(self, group_id: int):
- """
- 删除群配置
- :param group_id: 群号
- """
- if group_id in self._data["group_manager"]:
- del self._data["group_manager"][str(group_id)]
- if group_id in self._data["super"]["white_group_list"]:
- self._data["super"]["white_group_list"].remove(group_id)
- self.save()
-
- async def open_group_task(self, group_id: int, task: str):
- """
- 开启群被动技能
- :param group_id: 群号
- :param task: 被动技能名称
- """
- await self._set_group_task_status(group_id, task, True)
-
- async def close_group_task(self, group_id: int, task: str):
- """
- 关闭群被动技能
- :param group_id: 群号
- :param task: 被动技能名称
- """
- await self._set_group_task_status(group_id, task, False)
-
- async def check_group_task_status(self, group_id: int, task: str) -> bool:
- """
- 查看群被动技能状态
- :param group_id: 群号
- :param task: 被动技能名称
- """
- group_id = str(group_id)
- if (
- not self._data["group_manager"][group_id].get("group_task_status")
- or self._data["group_manager"][group_id]["group_task_status"].get(task)
- is None
- ):
- await self.init_group_task(group_id)
- return self._data["group_manager"][group_id]["group_task_status"][task]
-
- def get_task_data(self) -> Dict[str, str]:
- """
- 获取所有被动任务
- """
- return self._task
-
- async def group_task_status(self, group_id: int) -> str:
- """
- 查看群被全部动技能状态
- :param group_id: 群号
- """
- x = "[群被动技能]:\n"
- group_id = str(group_id)
- if not self._data["group_manager"][group_id].get("group_task_status"):
- await self.init_group_task(group_id)
- for key in self._data["group_manager"][group_id]["group_task_status"].keys():
- x += f'{self._task[key]}:{"√" if await self.check_group_task_status(int(group_id), key) else "×"}\n'
- return x[:-1]
-
- async def _set_group_task_status(self, group_id: int, task: str, status: bool):
- """
- 管理群被动技能状态
- :param group_id: 群号
- :param task: 被动技能
- :param status: 状态
- """
- group_id = str(group_id)
- if not self._data["group_manager"].get(group_id):
- self._init_group(group_id)
- if (
- not self._data["group_manager"][group_id].get("group_task_status")
- or self._data["group_manager"][group_id]["group_task_status"].get(task)
- is None
- ):
- await self.init_group_task(group_id)
- self._data["group_manager"][group_id]["group_task_status"][task] = status
- self.save()
-
- async def init_group_task(self, group_id: Optional[Union[int, str]] = None):
- """
- 初始化群聊 被动技能 状态
- """
- if not self._task:
- for matcher in get_matchers():
- _plugin = nonebot.plugin.get_plugin(matcher.module)
- try:
- _module = _plugin.module
- plugin_task = _module.__getattribute__("__plugin_task__")
- for key in plugin_task.keys():
- self._task[key] = plugin_task[key]
- except AttributeError:
- pass
- bot = get_bot()
- if bot or group_id:
- if group_id:
- _group_list = [group_id]
- else:
- _group_list = [x["group_id"] for x in await bot.get_group_list()]
- for group_id in _group_list:
- group_id = str(group_id)
- if not self._data["group_manager"].get(group_id):
- self._init_group(group_id)
- if not self._data["group_manager"][group_id].get("group_task_status"):
- self._data["group_manager"][group_id]["group_task_status"] = {}
- for task in self._task:
- if (
- self._data["group_manager"][group_id]["group_task_status"].get(
- task
- )
- is None
- ):
- self._data["group_manager"][group_id]["group_task_status"][
- task
- ] = True
- for task in list(
- self._data["group_manager"][group_id]["group_task_status"]
- ):
- if task not in self._task:
- del self._data["group_manager"][group_id]["group_task_status"][
- task
- ]
- self.save()
-
- def _set_plugin_status(
- self,
- module: str,
- status: str,
- group_id: int,
- ):
- """
- 说明:
- 设置功能开关状态
- 参数:
- :param module: 功能模块名
- :param status: 功能状态
- :param group_id: 群组
- """
- group_id = str(group_id) if group_id else group_id
- if not self._data["group_manager"].get(group_id):
- self._init_group(group_id)
- if status == "block":
- if module not in self._data["group_manager"][group_id]["close_plugins"]:
- self._data["group_manager"][group_id]["close_plugins"].append(module)
- else:
- if module in self._data["group_manager"][group_id]["close_plugins"]:
- self._data["group_manager"][group_id]["close_plugins"].remove(module)
- self.save()
-
- def _init_group(self, group_id: str):
- """
- 说明:
- 初始化群数据
- 参数:
- :param group_id: 群号
- """
- default_group_level = 5 # Config.get_config("group_manager")
- if not default_group_level:
- default_group_level = 5
- if not self._data["group_manager"].get(group_id):
- self._data["group_manager"][group_id] = {
- "level": default_group_level,
- "close_plugins": [],
- "group_task_status": {},
- }
-
- def get_super_old_data(self) -> Optional[dict]:
- """
- 获取旧数据,平时使用请不要调用
- """
- if self._data["super"].get("close_plugins"):
- _x = self._data["super"].get("close_plugins")
- del self._data["super"]["close_plugins"]
- return _x
- return None
+from typing import Optional, List, Union, Dict
+from pathlib import Path
+from .data_class import StaticData
+from utils.utils import get_matchers, get_bot
+import nonebot
+
+
+class GroupManager(StaticData):
+ """
+ 群权限 | 功能 | 聊天时间 管理器
+ """
+
+ def __init__(self, file: Path):
+ super().__init__(file)
+ if not self._data:
+ self._data = {
+ "super": {"white_group_list": []},
+ "group_manager": {},
+ }
+ self._task = {}
+
+ def block_plugin(self, module: str, group_id: int):
+ """
+ 说明:
+ 锁定插件
+ 参数:
+ :param module: 功能模块名
+ :param group_id: 群组,None时为超级用户禁用
+ """
+ self._set_plugin_status(module, "block", group_id)
+
+ def unblock_plugin(self, module: str, group_id: int):
+ """
+ 说明:
+ 解锁插件
+ 参数:
+ :param module: 功能模块名
+ :param group_id: 群组
+ """
+ self._set_plugin_status(module, "unblock", group_id)
+
+ def set_group_level(self, group_id: int, level: int):
+ """
+ 说明:
+ 设置群权限
+ 参数:
+ :param group_id: 群组
+ :param level: 权限等级
+ """
+ group_id = str(group_id)
+ if not self._data["group_manager"].get(group_id):
+ self._init_group(group_id)
+ self._data["group_manager"][group_id]["level"] = level
+ self.save()
+
+ def get_plugin_status(self, module: str, group_id: int) -> bool:
+ """
+ 说明:
+ 获取插件状态
+ 参数:
+ :param module: 功能模块名
+ :param group_id: 群组
+ """
+ group_id = str(group_id) if group_id else group_id
+ if not self._data["group_manager"].get(group_id):
+ self._init_group(group_id)
+ return True
+ if module in self._data["group_manager"][group_id]["close_plugins"]:
+ return False
+ return True
+
+ def get_group_level(self, group_id: int) -> int:
+ """
+ 说明:
+ 获取群等级
+ 参数:
+ :param group_id: 群号
+ """
+ group_id = str(group_id)
+ if not self._data["group_manager"].get(group_id):
+ self._init_group(group_id)
+ return self._data["group_manager"][group_id]["level"]
+
+ def check_group_is_white(self, group_id: int) -> bool:
+ """
+ 说明:
+ 检测群聊是否在白名单
+ 参数:
+ :param group_id: 群号
+ """
+ return group_id in self._data["super"]["white_group_list"]
+
+ def add_group_white_list(self, group_id: int):
+ """
+ 说明:
+ 将群聊加入白名单
+ 参数:
+ :param group_id: 群号
+ """
+ if group_id not in self._data["super"]["white_group_list"]:
+ self._data["super"]["white_group_list"].append(group_id)
+
+ def delete_group_white_list(self, group_id: int):
+ """
+ 说明:
+ 将群聊从白名单中删除
+ 参数:
+ :param group_id: 群号
+ """
+ if group_id in self._data["super"]["white_group_list"]:
+ self._data["super"]["white_group_list"].remove(group_id)
+
+ def get_group_white_list(self) -> List[str]:
+ """
+ 说明:
+ 获取所有群白名单
+ """
+ return self._data["super"]["white_group_list"]
+
+ def delete_group(self, group_id: int):
+ """
+ 删除群配置
+ :param group_id: 群号
+ """
+ if group_id in self._data["group_manager"]:
+ del self._data["group_manager"][str(group_id)]
+ if group_id in self._data["super"]["white_group_list"]:
+ self._data["super"]["white_group_list"].remove(group_id)
+ self.save()
+
+ async def open_group_task(self, group_id: int, task: str):
+ """
+ 开启群被动技能
+ :param group_id: 群号
+ :param task: 被动技能名称
+ """
+ await self._set_group_task_status(group_id, task, True)
+
+ async def close_group_task(self, group_id: int, task: str):
+ """
+ 关闭群被动技能
+ :param group_id: 群号
+ :param task: 被动技能名称
+ """
+ await self._set_group_task_status(group_id, task, False)
+
+ async def check_group_task_status(self, group_id: int, task: str) -> bool:
+ """
+ 查看群被动技能状态
+ :param group_id: 群号
+ :param task: 被动技能名称
+ """
+ group_id = str(group_id)
+ if (
+ not self._data["group_manager"][group_id].get("group_task_status")
+ or self._data["group_manager"][group_id]["group_task_status"].get(task)
+ is None
+ ):
+ await self.init_group_task(group_id)
+ return self._data["group_manager"][group_id]["group_task_status"][task]
+
+ def get_task_data(self) -> Dict[str, str]:
+ """
+ 获取所有被动任务
+ """
+ return self._task
+
+ async def group_task_status(self, group_id: int) -> str:
+ """
+ 查看群被全部动技能状态
+ :param group_id: 群号
+ """
+ x = "[群被动技能]:\n"
+ group_id = str(group_id)
+ if not self._data["group_manager"][group_id].get("group_task_status"):
+ await self.init_group_task(group_id)
+ for key in self._data["group_manager"][group_id]["group_task_status"].keys():
+ x += f'{self._task[key]}:{"√" if await self.check_group_task_status(int(group_id), key) else "×"}\n'
+ return x[:-1]
+
+ async def _set_group_task_status(self, group_id: int, task: str, status: bool):
+ """
+ 管理群被动技能状态
+ :param group_id: 群号
+ :param task: 被动技能
+ :param status: 状态
+ """
+ group_id = str(group_id)
+ if not self._data["group_manager"].get(group_id):
+ self._init_group(group_id)
+ if (
+ not self._data["group_manager"][group_id].get("group_task_status")
+ or self._data["group_manager"][group_id]["group_task_status"].get(task)
+ is None
+ ):
+ await self.init_group_task(group_id)
+ self._data["group_manager"][group_id]["group_task_status"][task] = status
+ self.save()
+
+ async def init_group_task(self, group_id: Optional[Union[int, str]] = None):
+ """
+ 初始化群聊 被动技能 状态
+ """
+ if not self._task:
+ for matcher in get_matchers():
+ _plugin = nonebot.plugin.get_plugin(matcher.module)
+ try:
+ _module = _plugin.module
+ plugin_task = _module.__getattribute__("__plugin_task__")
+ for key in plugin_task.keys():
+ self._task[key] = plugin_task[key]
+ except AttributeError:
+ pass
+ bot = get_bot()
+ if bot or group_id:
+ if group_id:
+ _group_list = [group_id]
+ else:
+ _group_list = [x["group_id"] for x in await bot.get_group_list()]
+ for group_id in _group_list:
+ group_id = str(group_id)
+ if not self._data["group_manager"].get(group_id):
+ self._init_group(group_id)
+ if not self._data["group_manager"][group_id].get("group_task_status"):
+ self._data["group_manager"][group_id]["group_task_status"] = {}
+ for task in self._task:
+ if (
+ self._data["group_manager"][group_id]["group_task_status"].get(
+ task
+ )
+ is None
+ ):
+ self._data["group_manager"][group_id]["group_task_status"][
+ task
+ ] = True
+ for task in list(
+ self._data["group_manager"][group_id]["group_task_status"]
+ ):
+ if task not in self._task:
+ del self._data["group_manager"][group_id]["group_task_status"][
+ task
+ ]
+ self.save()
+
+ def _set_plugin_status(
+ self,
+ module: str,
+ status: str,
+ group_id: int,
+ ):
+ """
+ 说明:
+ 设置功能开关状态
+ 参数:
+ :param module: 功能模块名
+ :param status: 功能状态
+ :param group_id: 群组
+ """
+ group_id = str(group_id) if group_id else group_id
+ if not self._data["group_manager"].get(group_id):
+ self._init_group(group_id)
+ if status == "block":
+ if module not in self._data["group_manager"][group_id]["close_plugins"]:
+ self._data["group_manager"][group_id]["close_plugins"].append(module)
+ else:
+ if module in self._data["group_manager"][group_id]["close_plugins"]:
+ self._data["group_manager"][group_id]["close_plugins"].remove(module)
+ self.save()
+
+ def _init_group(self, group_id: str):
+ """
+ 说明:
+ 初始化群数据
+ 参数:
+ :param group_id: 群号
+ """
+ default_group_level = 5 # Config.get_config("group_manager")
+ if not default_group_level:
+ default_group_level = 5
+ if not self._data["group_manager"].get(group_id):
+ self._data["group_manager"][group_id] = {
+ "level": default_group_level,
+ "close_plugins": [],
+ "group_task_status": {},
+ }
+
+ def get_super_old_data(self) -> Optional[dict]:
+ """
+ 获取旧数据,平时使用请不要调用
+ """
+ if self._data["super"].get("close_plugins"):
+ _x = self._data["super"].get("close_plugins")
+ del self._data["super"]["close_plugins"]
+ return _x
+ return None
diff --git a/utils/manager/none_plugin_count_manager.py b/utils/manager/none_plugin_count_manager.py
old mode 100644
new mode 100755
index 88f5260e..2da14d9f
--- a/utils/manager/none_plugin_count_manager.py
+++ b/utils/manager/none_plugin_count_manager.py
@@ -1,51 +1,51 @@
-from .data_class import StaticData
-from typing import Optional
-from pathlib import Path
-
-
-class NonePluginCountManager(StaticData):
-
- """
- 插件加载容忍管理器,当连续 max_count 次插件加载,视为删除插件,清楚数据
- """
-
- def __init__(self, file: Optional[Path], max_count: int = 5):
- """
- :param file: 存储路径
- :param max_count: 容忍最大次数
- """
- super().__init__(file)
- self._max_count = max_count
-
- def add_count(self, module: str, count: int = 1):
- """
- 添加次数
- :param module: 模块
- :param count: 次数,无特殊情况均为 1
- """
- if module not in self._data.keys():
- self._data[module] = count
- else:
- self._data[module] += count
-
- def reset(self, module: str):
- """
- 重置次数
- :param module: 模块
- """
- if module in self._data.keys():
- self._data[module] = 0
-
- def check(self, module: str):
- """
- 检查容忍次数是否到达最大值
- :param module: 模块
- """
- if module in self._data.keys():
- return self._data.keys() > self._max_count
- return False
-
-
-
-
-
+from .data_class import StaticData
+from typing import Optional
+from pathlib import Path
+
+
+class NonePluginCountManager(StaticData):
+
+ """
+ 插件加载容忍管理器,当连续 max_count 次插件加载,视为删除插件,清楚数据
+ """
+
+ def __init__(self, file: Optional[Path], max_count: int = 5):
+ """
+ :param file: 存储路径
+ :param max_count: 容忍最大次数
+ """
+ super().__init__(file)
+ self._max_count = max_count
+
+ def add_count(self, module: str, count: int = 1):
+ """
+ 添加次数
+ :param module: 模块
+ :param count: 次数,无特殊情况均为 1
+ """
+ if module not in self._data.keys():
+ self._data[module] = count
+ else:
+ self._data[module] += count
+
+ def reset(self, module: str):
+ """
+ 重置次数
+ :param module: 模块
+ """
+ if module in self._data.keys():
+ self._data[module] = 0
+
+ def check(self, module: str):
+ """
+ 检查容忍次数是否到达最大值
+ :param module: 模块
+ """
+ if module in self._data.keys():
+ return self._data.keys() > self._max_count
+ return False
+
+
+
+
+
diff --git a/utils/manager/plugins2block_manager.py b/utils/manager/plugins2block_manager.py
old mode 100644
new mode 100755
diff --git a/utils/manager/plugins2cd_manager.py b/utils/manager/plugins2cd_manager.py
old mode 100644
new mode 100755
diff --git a/utils/manager/plugins2count_manager.py b/utils/manager/plugins2count_manager.py
old mode 100644
new mode 100755
diff --git a/utils/manager/plugins2settings_manager.py b/utils/manager/plugins2settings_manager.py
old mode 100644
new mode 100755
index d5f49fe6..0a794978
--- a/utils/manager/plugins2settings_manager.py
+++ b/utils/manager/plugins2settings_manager.py
@@ -14,6 +14,13 @@ class Plugins2settingsManager(StaticData):
def __init__(self, file: Path):
self.file = file
super().__init__(None)
+ if file.exists():
+ with open(file, "r", encoding="utf8") as f:
+ self._data = yaml.load(f)
+ if "PluginSettings" in self._data.keys():
+ self._data = (
+ self._data["PluginSettings"] if self._data["PluginSettings"] else {}
+ )
def add_plugin_settings(
self,
diff --git a/utils/manager/plugins_manager.py b/utils/manager/plugins_manager.py
old mode 100644
new mode 100755
diff --git a/utils/manager/requests_manager.py b/utils/manager/requests_manager.py
old mode 100644
new mode 100755
index 842926dd..1842bbd3
--- a/utils/manager/requests_manager.py
+++ b/utils/manager/requests_manager.py
@@ -1,246 +1,246 @@
-from utils.manager.data_class import StaticData
-from nonebot.adapters.cqhttp import Bot
-from nonebot.adapters.cqhttp.exception import ActionFailed
-from services.log import logger
-from typing import Optional
-from utils.image_utils import CreateImg
-from utils.utils import get_user_avatar
-from pathlib import Path
-from io import BytesIO
-
-
-class RequestManager(StaticData):
-
- """
- 好友请求/邀请请求 管理
- """
-
- def __init__(self, file: Optional[Path]):
- super().__init__(file)
- if not self._data:
- self._data = {"private": {}, "group": {}}
-
- def add_request(
- self,
- id_: int,
- type_: str,
- flag: str,
- *,
- nickname: Optional[str] = None,
- level: Optional[int] = None,
- sex: Optional[str] = None,
- age: Optional[str] = None,
- from_: Optional[str] = "",
- comment: Optional[str] = None,
- invite_group: Optional[int] = None,
- group_name: Optional[str] = None,
- ):
- """
- 添加一个请求
- :param id_: id,用户id或群id
- :param type_: 类型,private 或 group
- :param flag: event.flag
- :param nickname: 用户昵称
- :param level: 等级
- :param sex: 性别
- :param age: 年龄
- :param from_: 请求来自
- :param comment: 附加消息
- :param invite_group: 邀请群聊
- :param group_name: 群聊名称
- """
- self._data[type_][str(len(self._data[type_].keys()))] = {
- "id": id_,
- "flag": flag,
- "nickname": nickname,
- "level": level,
- "sex": sex,
- "age": age,
- "from": from_,
- "comment": comment,
- "invite_group": invite_group,
- "group_name": group_name,
- }
- self.save()
-
- def remove_request(self, type_: str, id_: int):
- """
- 删除一个请求数据
- :param type_: 类型
- :param id_: id,user_id 或 group_id
- """
- for x in self._data[type_].keys():
- if self._data[type_][x].get("id") == id_:
- del self._data[type_][x]
- break
- self.save()
-
- async def approve(self, bot: Bot, id_: int, type_: str) -> Optional[int]:
- """
- 同意请求
- :param bot: Bot
- :param id_: id
- :param type_: 类型,private 或 group
- """
- return await self._set_add_request(bot, id_, type_, True)
-
- async def refused(self, bot: Bot, id_: int, type_: str) -> Optional[int]:
- """
- 拒绝请求
- :param bot: Bot
- :param id_: id
- :param type_: 类型,private 或 group
- """
- return await self._set_add_request(bot, id_, type_, False)
-
- def clear(self):
- """
- 清空所有请求信息,无视请求
- """
- self._data = {"private": {}, "group": {}}
- self.save()
-
- def set_group_name(self, group_name: str, group_id: int):
- """
- 设置群聊名称
- :param group_name: 名称
- :param group_id: id
- """
- for id_ in self._data["group"].keys():
- if self._data["group"][id_]["invite_group"] == group_id:
- self._data["group"][id_]["group_name"] = group_name
- break
- self.save()
-
- async def show(self, type_: str) -> Optional[str]:
- """
- 请求可视化
- """
- data = self._data[type_]
- if not data:
- return None
- img_list = []
- id_list = list(data.keys())
- id_list.reverse()
- for id_ in id_list:
- age = data[id_]["age"]
- nickname = data[id_]["nickname"]
- comment = data[id_]["comment"] if type_ == "private" else ""
- from_ = data[id_]["from"]
- sex = data[id_]["sex"]
- ava = CreateImg(
- 80, 80, background=BytesIO(await get_user_avatar(data[id_]["id"]))
- )
- ava.circle()
- age_bk = CreateImg(
- len(str(age)) * 10 - 5,
- 15,
- color="#04CAF7" if sex == "male" else "#F983C1",
- )
- age_bk.text((3, 1), f"{age}", fill=(255, 255, 255))
- x = CreateImg(
- 90, 32, font_size=15, color="#EEEFF4", font="HYWenHei-85W.ttf"
- )
- x.text((0, 0), "同意/拒绝", center_type="center")
- x.circle_corner(10)
- A = CreateImg(500, 100, font_size=24, font="msyh.ttf")
- A.paste(ava, (15, 0), alpha=True, center_type="by_height")
- A.text((120, 15), nickname)
- A.paste(age_bk, (120, 50), True)
- A.paste(
- CreateImg(
- 200,
- 0,
- font_size=12,
- plain_text=f"对方留言:{comment}",
- font_color=(140, 140, 143),
- ),
- (120 + age_bk.w + 10, 49),
- True,
- )
- if type_ == "private":
- A.paste(
- CreateImg(
- 200,
- 0,
- font_size=12,
- plain_text=f"来源:{from_}",
- font_color=(140, 140, 143),
- ),
- (120, 70),
- True,
- )
- else:
- A.paste(
- CreateImg(
- 200,
- 0,
- font_size=12,
- plain_text=f"邀请你加入:{data[id_]['group_name']}({data[id_]['invite_group']})",
- font_color=(140, 140, 143),
- ),
- (120, 70),
- True,
- )
- A.paste(x, (380, 35), True)
- A.paste(
- CreateImg(
- 0,
- 0,
- plain_text=f"id:{id_}",
- font_size=13,
- font_color=(140, 140, 143),
- ),
- (400, 10),
- True,
- )
- img_list.append(A)
- A = CreateImg(500, len(img_list) * 100, 500, 100)
- for img in img_list:
- A.paste(img)
- bk = CreateImg(A.w, A.h + 50, color="#F8F9FB", font_size=20)
- bk.paste(A, (0, 50))
- bk.text(
- (15, 13), "好友请求" if type_ == "private" else "群聊请求", fill=(140, 140, 143)
- )
- return bk.pic2bs4()
-
- async def _set_add_request(
- self, bot: Bot, id_: int, type_: str, approve: bool
- ) -> Optional[int]:
- """
- 处理请求
- :param bot: Bot
- :param id_: id
- :param type_: 类型,private 或 group
- :param approve: 是否同意
- """
- id_ = str(id_)
- if id_ in self._data[type_]:
- try:
- if type_ == "private":
- await bot.set_friend_add_request(
- flag=self._data[type_][id_]["flag"], approve=approve
- )
- rid = self._data[type_][id_]["id"]
- else:
- await bot.set_group_add_request(
- flag=self._data[type_][id_]["flag"],
- sub_type="invite",
- approve=approve,
- )
- rid = self._data[type_][id_]["invite_group"]
- except ActionFailed:
- logger.info(
- f"同意{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})"
- f"的{'好友' if type_ == 'private' else '入群'}请求失败了..."
- )
- return None
- logger.info(
- f"同意{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})"
- f"的{'好友' if type_ == 'private' else '入群'}请求..."
- )
- del self._data[type_][id_]
- self.save()
- return rid
- return None
+from utils.manager.data_class import StaticData
+from nonebot.adapters.cqhttp import Bot
+from nonebot.adapters.cqhttp.exception import ActionFailed
+from services.log import logger
+from typing import Optional
+from utils.image_utils import CreateImg
+from utils.utils import get_user_avatar
+from pathlib import Path
+from io import BytesIO
+
+
+class RequestManager(StaticData):
+
+ """
+ 好友请求/邀请请求 管理
+ """
+
+ def __init__(self, file: Optional[Path]):
+ super().__init__(file)
+ if not self._data:
+ self._data = {"private": {}, "group": {}}
+
+ def add_request(
+ self,
+ id_: int,
+ type_: str,
+ flag: str,
+ *,
+ nickname: Optional[str] = None,
+ level: Optional[int] = None,
+ sex: Optional[str] = None,
+ age: Optional[str] = None,
+ from_: Optional[str] = "",
+ comment: Optional[str] = None,
+ invite_group: Optional[int] = None,
+ group_name: Optional[str] = None,
+ ):
+ """
+ 添加一个请求
+ :param id_: id,用户id或群id
+ :param type_: 类型,private 或 group
+ :param flag: event.flag
+ :param nickname: 用户昵称
+ :param level: 等级
+ :param sex: 性别
+ :param age: 年龄
+ :param from_: 请求来自
+ :param comment: 附加消息
+ :param invite_group: 邀请群聊
+ :param group_name: 群聊名称
+ """
+ self._data[type_][str(len(self._data[type_].keys()))] = {
+ "id": id_,
+ "flag": flag,
+ "nickname": nickname,
+ "level": level,
+ "sex": sex,
+ "age": age,
+ "from": from_,
+ "comment": comment,
+ "invite_group": invite_group,
+ "group_name": group_name,
+ }
+ self.save()
+
+ def remove_request(self, type_: str, id_: int):
+ """
+ 删除一个请求数据
+ :param type_: 类型
+ :param id_: id,user_id 或 group_id
+ """
+ for x in self._data[type_].keys():
+ if self._data[type_][x].get("id") == id_:
+ del self._data[type_][x]
+ break
+ self.save()
+
+ async def approve(self, bot: Bot, id_: int, type_: str) -> Optional[int]:
+ """
+ 同意请求
+ :param bot: Bot
+ :param id_: id
+ :param type_: 类型,private 或 group
+ """
+ return await self._set_add_request(bot, id_, type_, True)
+
+ async def refused(self, bot: Bot, id_: int, type_: str) -> Optional[int]:
+ """
+ 拒绝请求
+ :param bot: Bot
+ :param id_: id
+ :param type_: 类型,private 或 group
+ """
+ return await self._set_add_request(bot, id_, type_, False)
+
+ def clear(self):
+ """
+ 清空所有请求信息,无视请求
+ """
+ self._data = {"private": {}, "group": {}}
+ self.save()
+
+ def set_group_name(self, group_name: str, group_id: int):
+ """
+ 设置群聊名称
+ :param group_name: 名称
+ :param group_id: id
+ """
+ for id_ in self._data["group"].keys():
+ if self._data["group"][id_]["invite_group"] == group_id:
+ self._data["group"][id_]["group_name"] = group_name
+ break
+ self.save()
+
+ async def show(self, type_: str) -> Optional[str]:
+ """
+ 请求可视化
+ """
+ data = self._data[type_]
+ if not data:
+ return None
+ img_list = []
+ id_list = list(data.keys())
+ id_list.reverse()
+ for id_ in id_list:
+ age = data[id_]["age"]
+ nickname = data[id_]["nickname"]
+ comment = data[id_]["comment"] if type_ == "private" else ""
+ from_ = data[id_]["from"]
+ sex = data[id_]["sex"]
+ ava = CreateImg(
+ 80, 80, background=BytesIO(await get_user_avatar(data[id_]["id"]))
+ )
+ ava.circle()
+ age_bk = CreateImg(
+ len(str(age)) * 10 - 5,
+ 15,
+ color="#04CAF7" if sex == "male" else "#F983C1",
+ )
+ age_bk.text((3, 1), f"{age}", fill=(255, 255, 255))
+ x = CreateImg(
+ 90, 32, font_size=15, color="#EEEFF4", font="HYWenHei-85W.ttf"
+ )
+ x.text((0, 0), "同意/拒绝", center_type="center")
+ x.circle_corner(10)
+ A = CreateImg(500, 100, font_size=24, font="msyh.ttf")
+ A.paste(ava, (15, 0), alpha=True, center_type="by_height")
+ A.text((120, 15), nickname)
+ A.paste(age_bk, (120, 50), True)
+ A.paste(
+ CreateImg(
+ 200,
+ 0,
+ font_size=12,
+ plain_text=f"对方留言:{comment}",
+ font_color=(140, 140, 143),
+ ),
+ (120 + age_bk.w + 10, 49),
+ True,
+ )
+ if type_ == "private":
+ A.paste(
+ CreateImg(
+ 200,
+ 0,
+ font_size=12,
+ plain_text=f"来源:{from_}",
+ font_color=(140, 140, 143),
+ ),
+ (120, 70),
+ True,
+ )
+ else:
+ A.paste(
+ CreateImg(
+ 200,
+ 0,
+ font_size=12,
+ plain_text=f"邀请你加入:{data[id_]['group_name']}({data[id_]['invite_group']})",
+ font_color=(140, 140, 143),
+ ),
+ (120, 70),
+ True,
+ )
+ A.paste(x, (380, 35), True)
+ A.paste(
+ CreateImg(
+ 0,
+ 0,
+ plain_text=f"id:{id_}",
+ font_size=13,
+ font_color=(140, 140, 143),
+ ),
+ (400, 10),
+ True,
+ )
+ img_list.append(A)
+ A = CreateImg(500, len(img_list) * 100, 500, 100)
+ for img in img_list:
+ A.paste(img)
+ bk = CreateImg(A.w, A.h + 50, color="#F8F9FB", font_size=20)
+ bk.paste(A, (0, 50))
+ bk.text(
+ (15, 13), "好友请求" if type_ == "private" else "群聊请求", fill=(140, 140, 143)
+ )
+ return bk.pic2bs4()
+
+ async def _set_add_request(
+ self, bot: Bot, id_: int, type_: str, approve: bool
+ ) -> Optional[int]:
+ """
+ 处理请求
+ :param bot: Bot
+ :param id_: id
+ :param type_: 类型,private 或 group
+ :param approve: 是否同意
+ """
+ id_ = str(id_)
+ if id_ in self._data[type_]:
+ try:
+ if type_ == "private":
+ await bot.set_friend_add_request(
+ flag=self._data[type_][id_]["flag"], approve=approve
+ )
+ rid = self._data[type_][id_]["id"]
+ else:
+ await bot.set_group_add_request(
+ flag=self._data[type_][id_]["flag"],
+ sub_type="invite",
+ approve=approve,
+ )
+ rid = self._data[type_][id_]["invite_group"]
+ except ActionFailed:
+ logger.info(
+ f"同意{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})"
+ f"的{'好友' if type_ == 'private' else '入群'}请求失败了..."
+ )
+ return None
+ logger.info(
+ f"同意{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})"
+ f"的{'好友' if type_ == 'private' else '入群'}请求..."
+ )
+ del self._data[type_][id_]
+ self.save()
+ return rid
+ return None
diff --git a/utils/manager/resources_manager.py b/utils/manager/resources_manager.py
old mode 100644
new mode 100755
diff --git a/utils/manager/withdraw_message_manager.py b/utils/manager/withdraw_message_manager.py
old mode 100644
new mode 100755
diff --git a/utils/message_builder.py b/utils/message_builder.py
old mode 100644
new mode 100755
diff --git a/utils/user_agent.py b/utils/user_agent.py
old mode 100644
new mode 100755
diff --git a/utils/utils.py b/utils/utils.py
old mode 100644
new mode 100755
index c5c469ec..96fa0efb
--- a/utils/utils.py
+++ b/utils/utils.py
@@ -301,7 +301,7 @@ def is_chinese(word: str) -> bool:
return True
-async def get_user_avatar(qq: int) -> bytes:
+async def get_user_avatar(qq: int) -> Optional[bytes]:
"""
说明:
快捷获取用户头像
@@ -315,9 +315,10 @@ async def get_user_avatar(qq: int) -> bytes:
return (await client.get(url)).content
except TimeoutError:
pass
+ return None
-async def get_group_avatar(group_id: int) -> bytes:
+async def get_group_avatar(group_id: int) -> Optional[bytes]:
"""
说明:
快捷获取用群头像
@@ -331,6 +332,7 @@ async def get_group_avatar(group_id: int) -> bytes:
return (await client.get(url)).content
except TimeoutError:
pass
+ return None
def cn2py(word: str) -> str:
@@ -346,18 +348,26 @@ def cn2py(word: str) -> str:
return temp
-def change_picture_links(url: str, mode: str):
+def change_pixiv_image_links(
+ url: str, size: Optional[str] = None, nginx_url: Optional[str] = None
+):
"""
说明:
- 根据配置改变图片大小
+ 根据配置改变图片大小和反代链接
参数:
:param url: 图片原图链接
- :param mode: 模式
+ :param size: 模式
+ :param nginx_url: 反代
"""
- if mode == "master":
+ if size == "master":
img_sp = url.rsplit(".", maxsplit=1)
url = img_sp[0]
img_type = img_sp[1]
url = url.replace("original", "master") + f"_master1200.{img_type}"
+ if nginx_url:
+ url = (
+ url.replace("i.pximg.net", nginx_url)
+ .replace("i.pixiv.cat", nginx_url)
+ .replace("_webp", "")
+ )
return url
-
diff --git a/utils/zh_wiki.py b/utils/zh_wiki.py
old mode 100644
new mode 100755