update 0.0.6.0

This commit is contained in:
HibiKier
2021-11-04 16:11:50 +08:00
parent 21c1950898
commit 19d650c35d
217 changed files with 8213 additions and 5697 deletions
+32
View File
@@ -1,11 +1,17 @@
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
@@ -19,6 +25,11 @@ group_manager: Optional[GroupManager] = GroupManager(
# 撤回消息管理
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"
@@ -34,6 +45,27 @@ 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()
+27 -10
View File
@@ -1,8 +1,5 @@
from typing import Optional, Dict
from .data_class import StaticData
from utils.utils import FreqLimiter
from services.log import logger
from pathlib import Path
from typing import List, Optional
class AdminManager(StaticData):
@@ -13,15 +10,27 @@ class AdminManager(StaticData):
def __init__(self):
super().__init__(None)
def add_admin_command(self, plugin: str, level: int):
def add_admin_plugin_settings(self, plugin: str, cmd: List[str], level: int):
"""
添加一个管理员命令
:param plugin: 模块
:param cmd: 别名
:param level: 等级
"""
self._data[plugin] = {
"level": level,
"cmd": cmd,
}
def set_admin_level(self, plugin: str, level: int):
"""
设置管理员命令等级
:param plugin: 模块名
:param level: 权限等级
"""
self._data[plugin] = level
self._data[plugin]["level"] = level
def remove_admin_command(self, plugin: str):
def remove_admin_plugin_settings(self, plugin: str):
"""
删除一个管理员命令
:param plugin: 模块名
@@ -36,7 +45,7 @@ class AdminManager(StaticData):
:param level: 权限等级
"""
if plugin in self._data.keys():
return level >= self._data[plugin]
return level >= self._data[plugin]["level"]
return True
def get_plugin_level(self, plugin: str) -> int:
@@ -45,7 +54,15 @@ class AdminManager(StaticData):
:param plugin: 模块名
"""
if plugin in self._data.keys():
return self._data[plugin]
return self._data[plugin]["level"]
return 0
def get_plugin_module(self, cmd: str) -> Optional[str]:
"""
根据 cmd 获取功能 module
:param cmd: 命令
"""
for key in self._data.keys():
if self._data[key].get("cmd") and cmd in self._data[key]["cmd"]:
return key
return None
+65
View File
@@ -0,0 +1,65 @@
# from typing import Optional, Any
# from .data_class import StaticData
# from pathlib import Path
# from ruamel.yaml import YAML
#
# yaml = YAML(typ="safe")
#
#
# class ConfigsManager(StaticData):
# """
# 插件配置 与 资源 管理器
# """
#
# def __init__(self, file: Path):
# self.file = file
# super().__init__(file)
# self._resource_data = {}
#
# def add_plugin_config(
# self,
# module: str,
# key: str,
# value: str,
# help_: Optional[str] = None,
# default_value: Optional[str] = None,
# ):
# """
# 为插件添加一个配置
# :param module: 模块
# :param key: 键
# :param value: 值
# :param help_: 配置注解
# :param default_value: 默认值
# """
# if self._data.get(module) is None:
# self._data[module] = {}
# self._data[module][key] = {
# "value": value,
# "help": help_,
# "default_value": default_value,
# }
#
# def remove_plugin_config(self, module: str):
# """
# 为插件删除一个配置
# :param module: 模块名
# """
# if module in self._data.keys():
# del self._data[module]
#
# def get_config(self, module: str, key: str) -> Optional[Any]:
# """
# 获取指定配置值
# :param module: 模块名
# :param key: 配置名称
# """
# if module in self._data.keys():
# if self._data[module].get(key):
# if self._data[module][key]["value"] is None:
# return self._data[module][key]["default_value"]
# return self._data[module][key]["value"]
# return None
#
#
#
+21 -8
View File
@@ -12,15 +12,25 @@ class StaticData:
"""
def __init__(self, file: Optional[Path]):
self._data = {}
self._data: dict = {}
if file:
file.parent.mkdir(exist_ok=True, parents=True)
self.file = file
if file.exists():
self._data: dict = json.load(open(file, "r", encoding="utf8"))
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)
@@ -31,20 +41,24 @@ class StaticData:
def delete(self, key):
if self._data.get(key) is not None:
del self._data[key]
self.save()
def get_data(self):
def get_data(self) -> dict:
return self._data
def save(self, path: Union[str, Path] = None):
path = path if path else self.file
with open(path, "w", encoding="utf8") as f:
json.dump(self._data, f, ensure_ascii=False, indent=4)
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'):
if self.file.name.endswith("json"):
self._data: dict = json.load(open(self.file, "r", encoding="utf8"))
elif self.file.name.endswith('yaml'):
elif self.file.name.endswith("yaml"):
self._data: dict = yaml.load(open(self.file, "r", encoding="utf8"))
def is_exists(self):
@@ -61,4 +75,3 @@ class StaticData:
def __getitem__(self, key):
return self._data[key]
+62 -86
View File
@@ -1,4 +1,3 @@
from configs.config import DEFAULT_GROUP_LEVEL
from typing import Optional, List, Union, Dict
from pathlib import Path
from .data_class import StaticData
@@ -15,33 +14,30 @@ class GroupManager(StaticData):
super().__init__(file)
if not self._data:
self._data = {
"super": {"close_plugins": {}, "white_group_list": []},
"super": {"white_group_list": []},
"group_manager": {},
}
self._task = {}
def block_plugin(
self, plugin_cmd: str, group_id: Optional[int] = None, block_type: str = "all"
):
def block_plugin(self, module: str, group_id: int):
"""
说明:
锁定插件
参数:
:param plugin_cmd: 功能模块名
:param module: 功能模块名
:param group_id: 群组,None时为超级用户禁用
:param block_type: 限制类型
"""
self._set_plugin_status(plugin_cmd, "block", group_id, block_type)
self._set_plugin_status(module, "block", group_id)
def unblock_plugin(self, plugin_cmd: str, group_id: Optional[int] = None):
def unblock_plugin(self, module: str, group_id: int):
"""
说明:
解锁插件
参数:
:param plugin_cmd: 功能模块名
:param module: 功能模块名
:param group_id: 群组
"""
self._set_plugin_status(plugin_cmd, "unblock", group_id)
self._set_plugin_status(module, "unblock", group_id)
def set_group_level(self, group_id: int, level: int):
"""
@@ -57,49 +53,21 @@ class GroupManager(StaticData):
self._data["group_manager"][group_id]["level"] = level
self.save()
def get_plugin_status(
self, plugin_cmd: str, group_id: Optional[int] = None, block_type: str = "all"
) -> bool:
def get_plugin_status(self, module: str, group_id: int) -> bool:
"""
说明:
获取插件状态
参数:
:param plugin_cmd: 功能模块名
:param module: 功能模块名
:param group_id: 群组
:param block_type: 限制类型
"""
group_id = str(group_id) if group_id else group_id
if group_id:
if not self._data["group_manager"].get(group_id):
self._init_group(group_id)
return True
if plugin_cmd in self._data["group_manager"][group_id]["close_plugins"]:
return False
if not self._data["group_manager"].get(group_id):
self._init_group(group_id)
return True
else:
if plugin_cmd in self._data["super"]["close_plugins"]:
if (
self._data["super"]["close_plugins"][plugin_cmd] == "all"
and block_type == "all"
):
return False
else:
return (
not self._data["super"]["close_plugins"][plugin_cmd]
== block_type
)
return True
def get_plugin_block_type(self, plugin_cmd: str) -> str:
"""
说明:
获取功能限制类型
参数:
:param plugin_cmd: 模块名称
"""
if plugin_cmd in self._data["super"]["close_plugins"]:
return self._data["super"]["close_plugins"][plugin_cmd]
return ""
if module in self._data["group_manager"][group_id]["close_plugins"]:
return False
return True
def get_group_level(self, group_id: int) -> int:
"""
@@ -149,6 +117,17 @@ class GroupManager(StaticData):
"""
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):
"""
开启群被动技能
@@ -181,6 +160,9 @@ class GroupManager(StaticData):
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:
@@ -188,7 +170,7 @@ class GroupManager(StaticData):
查看群被全部动技能状态
:param group_id: 群号
"""
x = '[群被动技能]:\n'
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)
@@ -222,8 +204,8 @@ class GroupManager(StaticData):
if not self._task:
for matcher in get_matchers():
_plugin = nonebot.plugin.get_plugin(matcher.module)
_module = _plugin.module
try:
_module = _plugin.module
plugin_task = _module.__getattribute__("__plugin_task__")
for key in plugin_task.keys():
self._task[key] = plugin_task[key]
@@ -240,18 +222,20 @@ class GroupManager(StaticData):
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'] = {}
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)
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 self._data["group_manager"][group_id]["group_task_status"]:
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
@@ -260,48 +244,27 @@ class GroupManager(StaticData):
def _set_plugin_status(
self,
plugin_cmd: str,
module: str,
status: str,
group_id: Optional[str],
block_type: str = "all",
group_id: int,
):
"""
说明:
设置功能开关状态
参数:
:param plugin_cmd: 功能模块名
:param module: 功能模块名
:param status: 功能状态
:param group_id: 群组
:param block_type: 限制类型
"""
group_id = str(group_id) if group_id else group_id
if plugin_cmd:
if group_id:
if not self._data["group_manager"].get(group_id):
self._init_group(group_id)
if status == "block":
if (
plugin_cmd
not in self._data["group_manager"][group_id]["close_plugins"]
):
self._data["group_manager"][group_id]["close_plugins"].append(
plugin_cmd
)
else:
if plugin_cmd in self._data["group_manager"][group_id]["close_plugins"]:
self._data["group_manager"][group_id]["close_plugins"].remove(
plugin_cmd
)
else:
if status == "block":
if (
plugin_cmd not in self._data["super"]["close_plugins"]
or block_type != self._data["super"]["close_plugins"][plugin_cmd]
):
self._data["super"]["close_plugins"][plugin_cmd] = block_type
else:
if plugin_cmd in self._data["super"]["close_plugins"]:
del self._data["super"]["close_plugins"][plugin_cmd]
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):
@@ -311,9 +274,22 @@ class GroupManager(StaticData):
参数:
: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,
"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
@@ -0,0 +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
+17 -20
View File
@@ -12,10 +12,18 @@ class Plugins2blockManager(StaticData):
"""
插件命令阻塞 管理器
"""
def __init__(self, file: Path):
self.file = file
super().__init__(None)
self._block_limiter: Dict[str, UserBlockLimiter] = {}
if file.exists():
with open(file, "r", encoding="utf8") as f:
self._data = yaml.load(f)
if "PluginBlockLimit" in self._data.keys():
self._data = (
self._data["PluginBlockLimit"] if self._data["PluginBlockLimit"] else {}
)
def add_block_limit(
self,
@@ -36,13 +44,13 @@ class Plugins2blockManager(StaticData):
:param data_dict: 封装好的字典数据
"""
if data_dict:
status = data_dict.get('status')
check_type = data_dict.get('check_type')
limit_type = data_dict.get('limit_type')
rst = data_dict.get('rst')
status = data_dict.get("status")
check_type = data_dict.get("check_type")
limit_type = data_dict.get("limit_type")
rst = data_dict.get("rst")
status = status if status is not None else True
check_type = check_type if check_type else 'all'
limit_type = limit_type if limit_type else 'user'
check_type = check_type if check_type else "all"
limit_type = limit_type if limit_type else "user"
if check_type not in ["all", "group", "private"]:
raise ValueError(
f"{plugin} 添加block限制错误,‘check_type‘ 必须为 'private'/'group'/'all'"
@@ -56,14 +64,6 @@ class Plugins2blockManager(StaticData):
"rst": rst,
}
def remove_block_limit(self, plugin: str):
"""
删除一个插件 block 限制
:param plugin: 插件模块名称
"""
if self._data.get(plugin):
del self._data[plugin]
def get_plugin_block_data(self, plugin: str) -> Optional[dict]:
"""
获取插件block数据
@@ -78,10 +78,7 @@ class Plugins2blockManager(StaticData):
检测插件是否有 block
:param plugin: 模块名
"""
return (
plugin in self._data.keys()
and self._data[plugin]["status"]
)
return plugin in self._data.keys() and self._data[plugin]["status"]
def check(self, id_: int, plugin: str) -> bool:
"""
@@ -119,7 +116,7 @@ class Plugins2blockManager(StaticData):
for plugin in self._data:
if self.check_plugin_block_status(plugin):
self._block_limiter[plugin] = UserBlockLimiter()
logger.info(f'已成功加载 {len(self._block_limiter)} 个Block限制.')
logger.info(f"已成功加载 {len(self._block_limiter)} 个Block限制.")
def reload(self):
"""
@@ -128,5 +125,5 @@ class Plugins2blockManager(StaticData):
if self.file.exists():
with open(self.file, "r", encoding="utf8") as f:
self._data: dict = yaml.load(f)
self._data = self._data['PluginBlockLimit']
self._data = self._data["PluginBlockLimit"]
self.reload_block_limit()
+19 -20
View File
@@ -17,6 +17,13 @@ class Plugins2cdManager(StaticData):
self.file = file
super().__init__(None)
self._freq_limiter: Dict[str, FreqLimiter] = {}
if file.exists():
with open(file, "r", encoding="utf8") as f:
self._data = yaml.load(f)
if "PluginCdLimit" in self._data.keys():
self._data = (
self._data["PluginCdLimit"] if self._data["PluginCdLimit"] else {}
)
def add_cd_limit(
self,
@@ -40,15 +47,15 @@ class Plugins2cdManager(StaticData):
:param data_dict: 封装好的字典数据
"""
if data_dict:
cd = data_dict.get('cd')
status = data_dict.get('status')
check_type = data_dict.get('check_type')
limit_type = data_dict.get('limit_type')
rst = data_dict.get('rst')
cd = data_dict.get("cd")
status = data_dict.get("status")
check_type = data_dict.get("check_type")
limit_type = data_dict.get("limit_type")
rst = data_dict.get("rst")
cd = cd if cd is not None else 5
status = status if status is not None else True
check_type = check_type if check_type else 'all'
limit_type = limit_type if limit_type else 'user'
check_type = check_type if check_type else "all"
limit_type = limit_type if limit_type else "user"
if check_type not in ["all", "group", "private"]:
raise ValueError(
f"{plugin} 添加cd限制错误,‘check_type‘ 必须为 'private'/'group'/'all'"
@@ -63,14 +70,6 @@ class Plugins2cdManager(StaticData):
"rst": rst,
}
def remove_cd_limit(self, plugin: str):
"""
删除一个插件 cd 限制
:param plugin: 插件模块名称
"""
if self._data.get(plugin):
del self._data[plugin]
def get_plugin_cd_data(self, plugin: str) -> Optional[dict]:
"""
获取插件cd数据
@@ -128,8 +127,10 @@ class Plugins2cdManager(StaticData):
"""
for plugin in self._data:
if self.check_plugin_cd_status(plugin):
self._freq_limiter[plugin] = FreqLimiter(self.get_plugin_cd_data(plugin)['cd'])
logger.info(f'已成功加载 {len(self._freq_limiter)} 个Cd限制.')
self._freq_limiter[plugin] = FreqLimiter(
self.get_plugin_cd_data(plugin)["cd"]
)
logger.info(f"已成功加载 {len(self._freq_limiter)} 个Cd限制.")
def reload(self):
"""
@@ -138,7 +139,5 @@ class Plugins2cdManager(StaticData):
if self.file.exists():
with open(self.file, "r", encoding="utf8") as f:
self._data: dict = yaml.load(f)
self._data = self._data['PluginCdLimit']
self._data = self._data["PluginCdLimit"]
self.reload_cd_limit()
+134
View File
@@ -0,0 +1,134 @@
from typing import Optional, Dict
from .data_class import StaticData
from utils.utils import DailyNumberLimiter
from services.log import logger
from pathlib import Path
from ruamel.yaml import YAML
yaml = YAML(typ="safe")
class Plugins2countManager(StaticData):
"""
插件命令 次数 管理器
"""
def __init__(self, file: Path):
self.file = file
super().__init__(None)
self._daily_limiter: Dict[str, DailyNumberLimiter] = {}
if file.exists():
with open(file, "r", encoding="utf8") as f:
self._data = yaml.load(f)
if "PluginCountLimit" in self._data.keys():
self._data = (
self._data["PluginCountLimit"] if self._data["PluginCountLimit"] else {}
)
def add_count_limit(
self,
plugin: str,
*,
max_count: int = 5,
status: Optional[bool] = True,
limit_type: Optional[str] = "user",
rst: Optional[str] = None,
data_dict: Optional[dict] = None,
):
"""
添加插件调用 次数 限制
:param plugin: 插件模块名称
:param max_count: 最大次数限制
:param status: 默认开关状态
:param limit_type: 限制类型 监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
:param rst: 回复的话,为空则不回复
:param data_dict: 封装好的字典数据
"""
if data_dict:
max_count = data_dict.get("max_count")
status = data_dict.get("status")
limit_type = data_dict.get("limit_type")
rst = data_dict.get("rst")
status = status if status is not None else True
limit_type = limit_type if limit_type else "user"
max_count = max_count if max_count is not None else 5
if limit_type not in ["user", "group"]:
raise ValueError(f"{plugin} 添加count限制错误,‘limit_type‘ 必须为 'user'/'group'")
self._data[plugin] = {
"max_count": max_count,
"status": status,
"limit_type": limit_type,
"rst": rst,
}
def get_plugin_count_data(self, plugin: str) -> Optional[dict]:
"""
获取插件次数数据
:param plugin: 模块名
"""
if self.check_plugin_count_status(plugin):
return self._data[plugin]
return None
def get_plugin_data(self, plugin: str) -> Optional[dict]:
"""
获取单个模块限制数据
:param plugin: 模块名
"""
if self._data.get(plugin) is not None:
return self._data.get(plugin)
return None
def check_plugin_count_status(self, plugin: str) -> bool:
"""
检测插件是否有 次数 限制
:param plugin: 模块名
"""
return (
plugin in self._data.keys()
and self._data[plugin]["status"]
and self._data[plugin]["max_count"] > 0
)
def check(self, plugin: str, id_: int) -> bool:
"""
检查 count
:param plugin: 模块名
:param id_: 限制 id
"""
if self._daily_limiter.get(plugin):
return self._daily_limiter[plugin].check(id_)
return True
def increase(self, plugin: str, id_: int, num: int = 1):
"""
增加次数
:param plugin: 模块名
:param id_: cd 限制类型
:param num: 增加次数
:return:
"""
if self._daily_limiter.get(plugin):
self._daily_limiter[plugin].increase(id_, num)
def reload_count_limit(self):
"""
加载 cd 限制器
:return:
"""
for plugin in self._data:
if self.check_plugin_count_status(plugin):
self._daily_limiter[plugin] = DailyNumberLimiter(
self.get_plugin_count_data(plugin)["max_count"]
)
logger.info(f"已成功加载 {len(self._daily_limiter)} 个Count限制.")
def reload(self):
"""
重载本地数据
"""
if self.file.exists():
with open(self.file, "r", encoding="utf8") as f:
self._data: dict = yaml.load(f)
self._data = self._data["PluginCountLimit"]
self.reload_count_limit()
+4 -10
View File
@@ -55,17 +55,11 @@ class Plugins2settingsManager(StaticData):
if limit_superuser is not None
else False,
"cmd": cmd,
"plugin_type": list(plugin_type if plugin_type is not None else ("normal",))
"plugin_type": list(
plugin_type if plugin_type is not None else ("normal",)
),
}
def remove_plugin_settings(self, plugin: str):
"""
删除一个插件设置
:param plugin: 插件模块名称
"""
if self._data.get(plugin):
del self._data[plugin]
def get_plugin_data(self, module: str) -> dict:
"""
通过模块名获取数据
@@ -99,4 +93,4 @@ class Plugins2settingsManager(StaticData):
if self.file.exists():
with open(self.file, "r", encoding="utf8") as f:
self._data: dict = yaml.load(f)
self._data = self._data['PluginSettings']
self._data = self._data["PluginSettings"]
+154
View File
@@ -0,0 +1,154 @@
from typing import Optional
from pathlib import Path
from .data_class import StaticData
from . import group_manager
class PluginsManager(StaticData):
"""
插件 管理器
"""
def __init__(self, file: Path):
super().__init__(file)
if not self._data:
self._data = {}
def add_plugin_data(
self,
module: str,
plugin_name: str,
*,
status: Optional[bool] = True,
error: Optional[bool] = False,
block_type: Optional[str] = None,
author: Optional[str] = None,
version: Optional[int] = None,
):
"""
添加插件数据
:param module: 模块名称
:param plugin_name: 插件名称
:param status: 插件开关状态
:param error: 加载状态
:param block_type: 限制类型
:param author: 作者
:param version: 版本
"""
self._data[module] = {
"plugin_name": plugin_name,
"status": status,
"error": error,
"block_type": block_type,
"author": author,
"version": version,
}
def block_plugin(
self, module: str, group_id: Optional[int] = None, block_type: str = "all"
):
"""
说明:
锁定插件
参数:
:param module: 功能模块名
:param group_id: 群组,None时为超级用户禁用
:param block_type: 限制类型
"""
self._set_plugin_status(module, "block", group_id, block_type)
def unblock_plugin(self, module: str, group_id: Optional[int] = None):
"""
说明:
解锁插件
参数:
:param module: 功能模块名
:param group_id: 群组
"""
self._set_plugin_status(module, "unblock", group_id)
def get_plugin_status(
self, module: str, block_type: str = "all"
) -> bool:
"""
说明:
获取插件状态
参数:
:param module: 功能模块名
:param block_type: 限制类型
"""
if module in self._data.keys():
if self._data[module]["block_type"] == "all" and block_type == "all":
return False
else:
return not self._data[module]["block_type"] == block_type
return True
def get_plugin_block_type(self, module: str) -> str:
"""
说明:
获取功能限制类型
参数:
:param module: 模块名称
"""
if module in self._data.keys():
return self._data[module]["block_type"]
return ""
def get_plugin_error_status(self, module: str) -> bool:
"""
插件是否成功加载
:param module: 模块名称
"""
if module not in self._data.keys():
self.init_plugin(module)
return self._data[module]["error"]
def _set_plugin_status(
self,
module: str,
status: str,
group_id: Optional[str],
block_type: str = "all",
):
"""
说明:
设置功能开关状态
参数:
:param module: 功能模块名
:param status: 功能状态
:param group_id: 群组
:param block_type: 限制类型
"""
group_id = str(group_id) if group_id else group_id
if module:
if group_id:
if status == "block":
group_manager.block_plugin(f"{module}:super", int(group_id))
else:
group_manager.unblock_plugin(f"{module}:super", int(group_id))
else:
if module not in self._data.keys():
self.init_plugin(module)
if status == "block":
self._data[module]["status"] = False
self._data[module]["block_type"] = block_type
else:
if module in self._data.keys():
self._data[module]["status"] = True
self.save()
def init_plugin(self, module: str):
"""
初始化插件数据
:param module: 模块名称
"""
if module not in self._data.keys():
self._data[module] = {
"plugin_name": module,
"status": True,
"error": False,
"block_type": None,
"author": None,
"version": None,
}
+246
View File
@@ -0,0 +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
+109
View File
@@ -0,0 +1,109 @@
from typing import Union, List, Optional
from .data_class import StaticData
from pathlib import Path
from ruamel.yaml import YAML
from services.log import logger
import shutil
yaml = YAML(typ="safe")
class ResourcesManager(StaticData):
"""
插件配置 与 资源 管理器
"""
def __init__(self, file: Path):
self.file = file
super().__init__(file)
self._temp_dir = []
self._abspath = Path()
def add_resource(
self, module: str, source_file: Union[str, Path], move_file: Union[str, Path]
):
"""
添加一个资源移动路劲
:param module: 模块名
:param source_file: 源文件路径
:param move_file: 移动路径
"""
if isinstance(source_file, Path):
source_file = str(source_file.absolute())
if isinstance(move_file, Path):
move_file = move_file.absolute()
if module not in self._data.keys():
self._data[module] = {source_file: move_file}
else:
self._data[module][source_file] = move_file
def remove_resource(self, module: str, source_file: Optional[Union[str, Path]] = None):
"""
删除一个资源路径
:param module: 模块
:param source_file: 源文件路径
"""
if not source_file:
if module in self._data.keys():
for x in self._data[module].keys():
move_file = Path(self._data[module][x])
if move_file.exists():
shutil.rmtree(move_file.absolute(), ignore_errors=True)
logger.info(f"已清除插件 {module} 资源路径:{self._data[module][x]}")
del self._data[module][x]
else:
if isinstance(source_file, Path):
source_file = str(source_file.absolute())
if source_file:
if module in self._data.keys() and source_file in self._data[module].keys():
move_file = Path(self._data[module][source_file])
if move_file.exists():
shutil.rmtree(move_file.absolute(), ignore_errors=True)
del self._data[module][source_file]
self.save()
def start_move(self):
"""
开始移动路径
"""
for module in self._data.keys():
for source_path in self._data[module].keys():
move_path = Path(self._data[module][source_path])
source_path = Path(source_path)
file_name = source_path.name
move_path = move_path / file_name
move_path.mkdir(exist_ok=True, parents=True)
try:
if source_path.exists():
if move_path.exists():
shutil.rmtree(str(move_path.absolute()), ignore_errors=True)
shutil.move(str(source_path.absolute()), str(move_path.absolute()))
logger.info(
f"移动资源文件路径 {source_path.absolute()} >>> {move_path.absolute()}"
)
elif not move_path.exists():
logger.warning(
f"移动资源路径文件{source_path.absolute()} >>>"
f" {move_path.absolute()} 失败,源文件不存在.."
)
except Exception as e:
logger.error(
f"移动资源路径文件{source_path.absolute()} >>>"
f" {move_path.absolute()}失败,{type(e)}:{e}"
)
self.save()
def add_temp_dir(self, path: Union[str, Path]):
"""
添加临时清理文件夹
:param path: 路径
"""
if isinstance(path, str):
path = Path(path)
self._temp_dir.append(path)
def get_temp_data_dir(self) -> List[Path]:
"""
获取临时文件文件夹
"""
return self._temp_dir
+18 -2
View File
@@ -1,8 +1,8 @@
from typing import Tuple, Union, Dict
from nonebot.adapters.cqhttp import MessageEvent, PrivateMessageEvent, GroupMessageEvent
class WithdrawMessageManager:
def __init__(self):
self.data = []
@@ -14,7 +14,7 @@ class WithdrawMessageManager:
:param message_data: 撤回消息id和时间
"""
if isinstance(message_data[0], dict):
message_data = (message_data[0]['message_id'], message_data[1])
message_data = (message_data[0]["message_id"], message_data[1])
self.data.append(message_data)
def remove(self, message_data: Tuple[int, int]):
@@ -26,3 +26,19 @@ class WithdrawMessageManager:
"""
self.data.remove(message_data)
def withdraw_message(
self, event: MessageEvent, id_: Union[int, Dict[str, int]], conditions: Tuple[int, int]
):
"""
便捷判断消息撤回
:param event: event
:param id_: 消息id 或 send 返回的字典
:param conditions: 判断条件
"""
if conditions[0]:
if (
(conditions[1] == 0 and isinstance(event, PrivateMessageEvent))
or (conditions[1] == 1 and isinstance(event, GroupMessageEvent))
or conditions[1] == 2
):
self.append((id_, conditions[0]))