update 0.0.6.2

This commit is contained in:
HibiKi
2021-11-23 21:44:59 +08:00
parent c802dfda22
commit 3de487fb24
251 changed files with 14413 additions and 14002 deletions
Regular → Executable
View File
Regular → Executable
+41 -41
View File
@@ -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()
Regular → Executable
View File
+325
View File
@@ -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
Regular → Executable
+19 -12
View File
@@ -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
Regular → Executable
View File
Regular → Executable
+72 -71
View File
@@ -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()
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+76 -77
View File
@@ -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]
Regular → Executable
+295 -295
View File
@@ -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
+51 -51
View File
@@ -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
View File
View File
View File
+7
View File
@@ -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,
Regular → Executable
View File
+246 -246
View File
@@ -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
View File
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+17 -7
View File
@@ -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
Regular → Executable
View File