mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-04 11:20:01 +08:00
fit nonebot.beta2
This commit is contained in:
+5
-2
@@ -30,7 +30,7 @@ async def get_browser(**kwargs) -> Browser:
|
||||
return _browser or await init(**kwargs)
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
# @driver.on_startup
|
||||
def install():
|
||||
"""自动安装、更新 Chromium"""
|
||||
logger.info("正在检查 Chromium 更新")
|
||||
@@ -38,4 +38,7 @@ def install():
|
||||
from playwright.__main__ import main
|
||||
|
||||
sys.argv = ["", "install", "chromium"]
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except SystemExit:
|
||||
pass
|
||||
|
||||
+8
-9
@@ -5,7 +5,7 @@ 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 nonebot.adapters.onebot.v11 import MessageSegment
|
||||
from playwright.async_api import Page
|
||||
from .message_builder import image
|
||||
from httpx import ConnectTimeout
|
||||
@@ -31,7 +31,6 @@ class AsyncHttpx:
|
||||
cookies: Optional[Dict[str, str]] = None,
|
||||
use_proxy: bool = True,
|
||||
proxy: Dict[str, str] = None,
|
||||
allow_redirects: bool = True,
|
||||
timeout: Optional[int] = 30,
|
||||
**kwargs,
|
||||
) -> Response:
|
||||
@@ -45,7 +44,6 @@ class AsyncHttpx:
|
||||
:param cookies: cookies
|
||||
:param use_proxy: 使用默认代理
|
||||
:param proxy: 指定代理
|
||||
:param allow_redirects: allow_redirects
|
||||
:param timeout: 超时时间
|
||||
"""
|
||||
if not headers:
|
||||
@@ -57,7 +55,6 @@ class AsyncHttpx:
|
||||
params=params,
|
||||
headers=headers,
|
||||
cookies=cookies,
|
||||
allow_redirects=allow_redirects,
|
||||
timeout=timeout,
|
||||
**kwargs
|
||||
)
|
||||
@@ -76,7 +73,6 @@ class AsyncHttpx:
|
||||
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,
|
||||
**kwargs,
|
||||
) -> Response:
|
||||
@@ -94,7 +90,6 @@ class AsyncHttpx:
|
||||
:param params: params
|
||||
:param headers: 请求头
|
||||
:param cookies: cookies
|
||||
:param allow_redirects: allow_redirects
|
||||
:param timeout: 超时时间
|
||||
"""
|
||||
if not headers:
|
||||
@@ -110,7 +105,6 @@ class AsyncHttpx:
|
||||
params=params,
|
||||
headers=headers,
|
||||
cookies=cookies,
|
||||
allow_redirects=allow_redirects,
|
||||
timeout=timeout,
|
||||
**kwargs,
|
||||
)
|
||||
@@ -299,7 +293,7 @@ class AsyncPlaywright:
|
||||
cls,
|
||||
url: str,
|
||||
path: Union[Path, str],
|
||||
element: str,
|
||||
element: Union[str, List[str]],
|
||||
*,
|
||||
sleep: Optional[int] = None,
|
||||
viewport_size: Dict[str, int] = None,
|
||||
@@ -333,7 +327,12 @@ class AsyncPlaywright:
|
||||
await page.set_viewport_size(viewport_size)
|
||||
if sleep:
|
||||
await asyncio.sleep(sleep)
|
||||
card = await page.query_selector(element)
|
||||
if isinstance(element, str):
|
||||
card = await page.query_selector(element)
|
||||
else:
|
||||
card = page
|
||||
for e in element:
|
||||
card = await card.query_selector(e)
|
||||
await card.screenshot(path=path, timeout=timeout, type=type_)
|
||||
return image(path)
|
||||
except Exception as e:
|
||||
|
||||
+199
-211
@@ -63,10 +63,10 @@ def compressed_image(
|
||||
:param out_file: 压缩后输出的文件路径
|
||||
:param ratio: 压缩率,宽高 * 压缩率
|
||||
"""
|
||||
in_file = Path(IMAGE_PATH) / in_file if isinstance(in_file, str) else in_file
|
||||
in_file = IMAGE_PATH / in_file if isinstance(in_file, str) else in_file
|
||||
if out_file:
|
||||
out_file = (
|
||||
Path(IMAGE_PATH) / out_file if isinstance(out_file, str) else out_file
|
||||
IMAGE_PATH / out_file if isinstance(out_file, str) else out_file
|
||||
)
|
||||
else:
|
||||
out_file = in_file
|
||||
@@ -137,186 +137,6 @@ def is_valid(file: str) -> bool:
|
||||
return valid
|
||||
|
||||
|
||||
async def text2image(
|
||||
text: str,
|
||||
auto_parse: bool = True,
|
||||
font_size: int = 20,
|
||||
color: Union[str, Tuple[int, int, int], Tuple[int, int, int, int]] = "white",
|
||||
font: str = "CJGaoDeGuo.otf",
|
||||
font_color: Union[str, Tuple[int, int, int]] = "black",
|
||||
padding: Union[int, Tuple[int, int, int, int]] = 0,
|
||||
) -> str:
|
||||
"""
|
||||
说明:
|
||||
解析文本并转为图片
|
||||
使用标签
|
||||
<f> </f>
|
||||
可选配置项
|
||||
font: str -> 特殊文本字体
|
||||
font_size: int -> 特殊文本大小
|
||||
font_color: str -> 特殊文本颜色
|
||||
示例
|
||||
在不在,<f font=YSHaoShenTi-2.ttf font_size=30 font_color=red>HibiKi小姐</f>,
|
||||
你最近还好吗,<f font_size=15 font_color=black>我非常想你</f>,这段时间我非常不好过,
|
||||
<f font_size=25>抽卡抽不到金色</f>,这让我很痛苦
|
||||
参数:
|
||||
:param text: 文本
|
||||
:param auto_parse: 是否自动解析,否则原样发送
|
||||
:param font_size: 普通字体大小
|
||||
:param color: 背景颜色
|
||||
:param font: 普通字体
|
||||
:param font_color: 普通字体颜色
|
||||
:param padding: 文本外边距,元组类型时为 (上,左,下,右)
|
||||
"""
|
||||
pw = ph = top_padding = left_padding = 0
|
||||
if padding:
|
||||
if isinstance(padding, int):
|
||||
pw = padding * 2
|
||||
ph = padding * 2
|
||||
top_padding = left_padding = padding
|
||||
elif isinstance(padding, tuple):
|
||||
pw = padding[0] + padding[2]
|
||||
ph = padding[1] + padding[3]
|
||||
top_padding = padding[0]
|
||||
left_padding = padding[1]
|
||||
if auto_parse and re.search(r"<f(.*)>(.*)</f>", text):
|
||||
_data = []
|
||||
new_text = ""
|
||||
placeholder_index = 0
|
||||
for s in text.split("</f>"):
|
||||
r = re.search(r"<f(.*)>(.*)", s)
|
||||
if r:
|
||||
start, end = r.span()
|
||||
if start != 0 and (t := s[:start]):
|
||||
new_text += t
|
||||
_data.append(
|
||||
[
|
||||
(start, end),
|
||||
f"[placeholder_{placeholder_index}]",
|
||||
r.group(1).strip(),
|
||||
r.group(2),
|
||||
]
|
||||
)
|
||||
new_text += f"[placeholder_{placeholder_index}]"
|
||||
placeholder_index += 1
|
||||
new_text += text.split("</f>")[-1]
|
||||
image_list = []
|
||||
current_placeholder_index = 0
|
||||
# 切分换行,每行为单张图片
|
||||
for s in new_text.split("\n"):
|
||||
_tmp_text = s
|
||||
img_height = BuildImage(0, 0, font_size=font_size).getsize("正")[1]
|
||||
img_width = 0
|
||||
_tmp_index = current_placeholder_index
|
||||
for _ in range(s.count("[placeholder_")):
|
||||
placeholder = _data[_tmp_index]
|
||||
if "font_size" in placeholder[2]:
|
||||
r = re.search(r"font_size=['\"]?(\d+)", placeholder[2])
|
||||
if r:
|
||||
w, h = BuildImage(0, 0, font_size=int(r.group(1))).getsize(
|
||||
placeholder[3]
|
||||
)
|
||||
img_height = img_height if img_height > h else h
|
||||
img_width += w
|
||||
else:
|
||||
img_width += BuildImage(0, 0, font_size=font_size).getsize(
|
||||
placeholder[3]
|
||||
)[0]
|
||||
_tmp_text = _tmp_text.replace(f"[placeholder_{_tmp_index}]", "")
|
||||
_tmp_index += 1
|
||||
img_width += BuildImage(0, 0, font_size=font_size).getsize(_tmp_text)[0]
|
||||
# img_width += len(_tmp_text) * font_size
|
||||
# 开始画图
|
||||
A = BuildImage(
|
||||
img_width, img_height, color=color, font=font, font_size=font_size
|
||||
)
|
||||
basic_font_h = A.getsize("正")[1]
|
||||
current_width = 0
|
||||
# 遍历占位符
|
||||
for _ in range(s.count("[placeholder_")):
|
||||
if not s.startswith(f"[placeholder_{current_placeholder_index}]"):
|
||||
slice_ = s.split(f"[placeholder_{current_placeholder_index}]")
|
||||
await A.atext(
|
||||
(current_width, A.h - basic_font_h - 1), slice_[0], font_color
|
||||
)
|
||||
current_width += A.getsize(slice_[0])[0]
|
||||
placeholder = _data[current_placeholder_index]
|
||||
# 解析配置
|
||||
_font = font
|
||||
_font_size = font_size
|
||||
_font_color = font_color
|
||||
for e in placeholder[2].split():
|
||||
if e.startswith("font="):
|
||||
_font = e.split("=")[-1]
|
||||
if e.startswith("font_size=") or e.startswith("fs="):
|
||||
_font_size = int(e.split("=")[-1])
|
||||
if _font_size > 1000:
|
||||
_font_size = 1000
|
||||
if _font_size < 1:
|
||||
_font_size = 1
|
||||
if e.startswith("font_color") or e.startswith("fc="):
|
||||
_font_color = e.split("=")[-1]
|
||||
text_img = BuildImage(
|
||||
0,
|
||||
0,
|
||||
plain_text=placeholder[3],
|
||||
font_size=_font_size,
|
||||
font_color=_font_color,
|
||||
font=_font,
|
||||
)
|
||||
_img_h = (
|
||||
int(A.h / 2 - text_img.h / 2)
|
||||
if new_text == "[placeholder_0]"
|
||||
else A.h - text_img.h
|
||||
)
|
||||
await A.apaste(text_img, (current_width, _img_h - 1), True)
|
||||
current_width += text_img.w
|
||||
s = s[
|
||||
s.index(f"[placeholder_{current_placeholder_index}]")
|
||||
+ len(f"[placeholder_{current_placeholder_index}]") :
|
||||
]
|
||||
current_placeholder_index += 1
|
||||
if s:
|
||||
slice_ = s.split(f"[placeholder_{current_placeholder_index}]")
|
||||
await A.atext((current_width, A.h - basic_font_h), slice_[0])
|
||||
current_width += A.getsize(slice_[0])[0]
|
||||
A.crop((0, 0, current_width, A.h))
|
||||
# A.show()
|
||||
image_list.append(A)
|
||||
height = 0
|
||||
width = 0
|
||||
for img in image_list:
|
||||
height += img.h
|
||||
width = width if width > img.w else img.w
|
||||
width += pw
|
||||
height += ph
|
||||
A = BuildImage(width + left_padding, height + top_padding, color=color)
|
||||
current_height = top_padding
|
||||
for img in image_list:
|
||||
await A.apaste(img, (left_padding, current_height), True)
|
||||
current_height += img.h
|
||||
else:
|
||||
width = 0
|
||||
height = 0
|
||||
_tmp = BuildImage(0, 0, font_size=font_size)
|
||||
for x in text.split("\n"):
|
||||
w, h = _tmp.getsize(x)
|
||||
height += h
|
||||
width = width if width > w else w
|
||||
width += pw
|
||||
height += ph
|
||||
A = BuildImage(
|
||||
width + left_padding,
|
||||
height + top_padding,
|
||||
font_size=font_size,
|
||||
color=color,
|
||||
font=font,
|
||||
)
|
||||
await A.atext((left_padding, top_padding), text, font_color)
|
||||
# A.show()
|
||||
return A.pic2bs4()
|
||||
|
||||
|
||||
class BuildImage:
|
||||
"""
|
||||
快捷生成图片与操作图片的工具类
|
||||
@@ -359,7 +179,7 @@ class BuildImage:
|
||||
self.paste_image_height = int(paste_image_height)
|
||||
self.current_w = 0
|
||||
self.current_h = 0
|
||||
self.font = ImageFont.truetype(FONT_PATH + font, int(font_size))
|
||||
self.font = ImageFont.truetype(str(FONT_PATH / font), int(font_size))
|
||||
if not plain_text and not color:
|
||||
color = (255, 255, 255)
|
||||
self.background = background
|
||||
@@ -838,41 +658,29 @@ class BuildImage:
|
||||
"""
|
||||
await self.loop.run_in_executor(None, self.circle)
|
||||
|
||||
def draw_ellipse(self, image, bounds, width=1, outline='white', antialias=4):
|
||||
"""
|
||||
Improved ellipse drawing function, based on PIL.ImageDraw.
|
||||
"""
|
||||
|
||||
# Use a single channel image (mode='L') as mask.
|
||||
# The size of the mask can be increased relative to the imput image
|
||||
# to get smoother looking results.
|
||||
mask = Image.new(
|
||||
size=[int(dim * antialias) for dim in image.size],
|
||||
mode='L', color='black')
|
||||
draw = ImageDraw.Draw(mask)
|
||||
|
||||
# draw outer shape in white (color) and inner shape in black (transparent)
|
||||
for offset, fill in (width / -2.0, 'black'), (width / 2.0, 'white'):
|
||||
left, top = [(value + offset) * antialias for value in bounds[:2]]
|
||||
right, bottom = [(value - offset) * antialias for value in bounds[2:]]
|
||||
draw.ellipse([left, top, right, bottom], fill=fill)
|
||||
|
||||
# downsample the mask using PIL.Image.LANCZOS
|
||||
# (a high-quality downsampling filter).
|
||||
mask = mask.resize(image.size, Image.LANCZOS)
|
||||
|
||||
# paste outline color to input image through the mask
|
||||
image.putalpha(mask)
|
||||
|
||||
#
|
||||
def circle(self):
|
||||
"""
|
||||
说明:
|
||||
使图像变圆
|
||||
"""
|
||||
self.markImg.convert("RGBA")
|
||||
size = self.markImg.size
|
||||
r2 = min(size[0], size[1])
|
||||
if size[0] != size[1]:
|
||||
self.markImg = self.markImg.resize((r2, r2), Image.ANTIALIAS)
|
||||
width = 1
|
||||
antialias = 4
|
||||
ellipse_box = [0, 0, r2 - 2, r2 - 2]
|
||||
self.draw_ellipse(self.markImg, ellipse_box, width=1)
|
||||
mask = Image.new(
|
||||
size=[int(dim * antialias) for dim in self.markImg.size],
|
||||
mode='L', color='black')
|
||||
draw = ImageDraw.Draw(mask)
|
||||
for offset, fill in (width / -2.0, 'black'), (width / 2.0, 'white'):
|
||||
left, top = [(value + offset) * antialias for value in ellipse_box[:2]]
|
||||
right, bottom = [(value - offset) * antialias for value in ellipse_box[2:]]
|
||||
draw.ellipse([left, top, right, bottom], fill=fill)
|
||||
mask = mask.resize(self.markImg.size, Image.LANCZOS)
|
||||
self.markImg.putalpha(mask)
|
||||
|
||||
async def acircle_corner(self, radii: int = 30):
|
||||
"""
|
||||
@@ -1519,5 +1327,185 @@ class BuildMat:
|
||||
return A
|
||||
|
||||
|
||||
async def text2image(
|
||||
text: str,
|
||||
auto_parse: bool = True,
|
||||
font_size: int = 20,
|
||||
color: Union[str, Tuple[int, int, int], Tuple[int, int, int, int]] = "white",
|
||||
font: str = "CJGaoDeGuo.otf",
|
||||
font_color: Union[str, Tuple[int, int, int]] = "black",
|
||||
padding: Union[int, Tuple[int, int, int, int]] = 0,
|
||||
) -> BuildImage:
|
||||
"""
|
||||
说明:
|
||||
解析文本并转为图片
|
||||
使用标签
|
||||
<f> </f>
|
||||
可选配置项
|
||||
font: str -> 特殊文本字体
|
||||
fs / font_size: int -> 特殊文本大小
|
||||
fc / font_color: Union[str, Tuple[int, int, int]] -> 特殊文本颜色
|
||||
示例
|
||||
在不在,<f font=YSHaoShenTi-2.ttf font_size=30 font_color=red>HibiKi小姐</f>,
|
||||
你最近还好吗,<f font_size=15 font_color=black>我非常想你</f>,这段时间我非常不好过,
|
||||
<f font_size=25>抽卡抽不到金色</f>,这让我很痛苦
|
||||
参数:
|
||||
:param text: 文本
|
||||
:param auto_parse: 是否自动解析,否则原样发送
|
||||
:param font_size: 普通字体大小
|
||||
:param color: 背景颜色
|
||||
:param font: 普通字体
|
||||
:param font_color: 普通字体颜色
|
||||
:param padding: 文本外边距,元组类型时为 (上,左,下,右)
|
||||
"""
|
||||
pw = ph = top_padding = left_padding = 0
|
||||
if padding:
|
||||
if isinstance(padding, int):
|
||||
pw = padding * 2
|
||||
ph = padding * 2
|
||||
top_padding = left_padding = padding
|
||||
elif isinstance(padding, tuple):
|
||||
pw = padding[0] + padding[2]
|
||||
ph = padding[1] + padding[3]
|
||||
top_padding = padding[0]
|
||||
left_padding = padding[1]
|
||||
if auto_parse and re.search(r"<f(.*)>(.*)</f>", text):
|
||||
_data = []
|
||||
new_text = ""
|
||||
placeholder_index = 0
|
||||
for s in text.split("</f>"):
|
||||
r = re.search(r"<f(.*)>(.*)", s)
|
||||
if r:
|
||||
start, end = r.span()
|
||||
if start != 0 and (t := s[:start]):
|
||||
new_text += t
|
||||
_data.append(
|
||||
[
|
||||
(start, end),
|
||||
f"[placeholder_{placeholder_index}]",
|
||||
r.group(1).strip(),
|
||||
r.group(2),
|
||||
]
|
||||
)
|
||||
new_text += f"[placeholder_{placeholder_index}]"
|
||||
placeholder_index += 1
|
||||
new_text += text.split("</f>")[-1]
|
||||
image_list = []
|
||||
current_placeholder_index = 0
|
||||
# 切分换行,每行为单张图片
|
||||
for s in new_text.split("\n"):
|
||||
_tmp_text = s
|
||||
img_height = BuildImage(0, 0, font_size=font_size).getsize("正")[1]
|
||||
img_width = 0
|
||||
_tmp_index = current_placeholder_index
|
||||
for _ in range(s.count("[placeholder_")):
|
||||
placeholder = _data[_tmp_index]
|
||||
if "font_size" in placeholder[2]:
|
||||
r = re.search(r"font_size=['\"]?(\d+)", placeholder[2])
|
||||
if r:
|
||||
w, h = BuildImage(0, 0, font_size=int(r.group(1))).getsize(
|
||||
placeholder[3]
|
||||
)
|
||||
img_height = img_height if img_height > h else h
|
||||
img_width += w
|
||||
else:
|
||||
img_width += BuildImage(0, 0, font_size=font_size).getsize(
|
||||
placeholder[3]
|
||||
)[0]
|
||||
_tmp_text = _tmp_text.replace(f"[placeholder_{_tmp_index}]", "")
|
||||
_tmp_index += 1
|
||||
img_width += BuildImage(0, 0, font_size=font_size).getsize(_tmp_text)[0]
|
||||
# img_width += len(_tmp_text) * font_size
|
||||
# 开始画图
|
||||
A = BuildImage(
|
||||
img_width, img_height, color=color, font=font, font_size=font_size
|
||||
)
|
||||
basic_font_h = A.getsize("正")[1]
|
||||
current_width = 0
|
||||
# 遍历占位符
|
||||
for _ in range(s.count("[placeholder_")):
|
||||
if not s.startswith(f"[placeholder_{current_placeholder_index}]"):
|
||||
slice_ = s.split(f"[placeholder_{current_placeholder_index}]")
|
||||
await A.atext(
|
||||
(current_width, A.h - basic_font_h - 1), slice_[0], font_color
|
||||
)
|
||||
current_width += A.getsize(slice_[0])[0]
|
||||
placeholder = _data[current_placeholder_index]
|
||||
# 解析配置
|
||||
_font = font
|
||||
_font_size = font_size
|
||||
_font_color = font_color
|
||||
for e in placeholder[2].split():
|
||||
if e.startswith("font="):
|
||||
_font = e.split("=")[-1]
|
||||
if e.startswith("font_size=") or e.startswith("fs="):
|
||||
_font_size = int(e.split("=")[-1])
|
||||
if _font_size > 1000:
|
||||
_font_size = 1000
|
||||
if _font_size < 1:
|
||||
_font_size = 1
|
||||
if e.startswith("font_color") or e.startswith("fc="):
|
||||
_font_color = e.split("=")[-1]
|
||||
text_img = BuildImage(
|
||||
0,
|
||||
0,
|
||||
plain_text=placeholder[3],
|
||||
font_size=_font_size,
|
||||
font_color=_font_color,
|
||||
font=_font,
|
||||
)
|
||||
_img_h = (
|
||||
int(A.h / 2 - text_img.h / 2)
|
||||
if new_text == "[placeholder_0]"
|
||||
else A.h - text_img.h
|
||||
)
|
||||
await A.apaste(text_img, (current_width, _img_h - 1), True)
|
||||
current_width += text_img.w
|
||||
s = s[
|
||||
s.index(f"[placeholder_{current_placeholder_index}]")
|
||||
+ len(f"[placeholder_{current_placeholder_index}]") :
|
||||
]
|
||||
current_placeholder_index += 1
|
||||
if s:
|
||||
slice_ = s.split(f"[placeholder_{current_placeholder_index}]")
|
||||
await A.atext((current_width, A.h - basic_font_h), slice_[0])
|
||||
current_width += A.getsize(slice_[0])[0]
|
||||
A.crop((0, 0, current_width, A.h))
|
||||
# A.show()
|
||||
image_list.append(A)
|
||||
height = 0
|
||||
width = 0
|
||||
for img in image_list:
|
||||
height += img.h
|
||||
width = width if width > img.w else img.w
|
||||
width += pw
|
||||
height += ph
|
||||
A = BuildImage(width + left_padding, height + top_padding, color=color)
|
||||
current_height = top_padding
|
||||
for img in image_list:
|
||||
await A.apaste(img, (left_padding, current_height), True)
|
||||
current_height += img.h
|
||||
else:
|
||||
width = 0
|
||||
height = 0
|
||||
_tmp = BuildImage(0, 0, font_size=font_size)
|
||||
for x in text.split("\n"):
|
||||
w, h = _tmp.getsize(x)
|
||||
height += h
|
||||
width = width if width > w else w
|
||||
width += pw
|
||||
height += ph
|
||||
A = BuildImage(
|
||||
width + left_padding,
|
||||
height + top_padding,
|
||||
font_size=font_size,
|
||||
color=color,
|
||||
font=font,
|
||||
)
|
||||
await A.atext((left_padding, top_padding), text, font_color)
|
||||
# A.show()
|
||||
return A
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
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
|
||||
@@ -17,7 +16,7 @@ from configs.path_config import DATA_PATH
|
||||
|
||||
# 群功能开关 | 群被动技能 | 群权限 管理
|
||||
group_manager: Optional[GroupManager] = GroupManager(
|
||||
Path(DATA_PATH) / "manager" / "group_manager.json"
|
||||
DATA_PATH / "manager" / "group_manager.json"
|
||||
)
|
||||
|
||||
# 撤回消息管理
|
||||
@@ -25,42 +24,42 @@ withdraw_message_manager: Optional[WithdrawMessageManager] = WithdrawMessageMana
|
||||
|
||||
# 插件管理
|
||||
plugins_manager: Optional[PluginsManager] = PluginsManager(
|
||||
Path(DATA_PATH) / "manager" / "plugins_manager.json"
|
||||
DATA_PATH / "manager" / "plugins_manager.json"
|
||||
)
|
||||
|
||||
# 插件基本设置管理
|
||||
plugins2settings_manager: Optional[Plugins2settingsManager] = Plugins2settingsManager(
|
||||
Path(DATA_PATH) / "configs" / "plugins2settings.yaml"
|
||||
DATA_PATH / "configs" / "plugins2settings.yaml"
|
||||
)
|
||||
|
||||
# 插件命令 cd 管理
|
||||
plugins2cd_manager: Optional[Plugins2cdManager] = Plugins2cdManager(
|
||||
Path(DATA_PATH) / "configs" / "plugins2cd.yaml"
|
||||
DATA_PATH / "configs" / "plugins2cd.yaml"
|
||||
)
|
||||
|
||||
# 插件命令 阻塞 管理
|
||||
plugins2block_manager: Optional[Plugins2blockManager] = Plugins2blockManager(
|
||||
Path(DATA_PATH) / "configs" / "plugins2block.yaml"
|
||||
DATA_PATH / "configs" / "plugins2block.yaml"
|
||||
)
|
||||
|
||||
# 插件命令 每次次数限制 管理
|
||||
plugins2count_manager: Optional[Plugins2countManager] = Plugins2countManager(
|
||||
Path(DATA_PATH) / "configs" / "plugins2count.yaml"
|
||||
DATA_PATH / "configs" / "plugins2count.yaml"
|
||||
)
|
||||
|
||||
# 资源管理
|
||||
resources_manager: Optional[ResourcesManager] = ResourcesManager(
|
||||
Path(DATA_PATH) / "manager" / "resources_manager.json"
|
||||
DATA_PATH / "manager" / "resources_manager.json"
|
||||
)
|
||||
|
||||
# 插件加载容忍管理
|
||||
none_plugin_count_manager: Optional[NonePluginCountManager] = NonePluginCountManager(
|
||||
Path(DATA_PATH) / "manager" / "none_plugin_count_manager.json"
|
||||
DATA_PATH / "manager" / "none_plugin_count_manager.json"
|
||||
)
|
||||
|
||||
# 好友请求/群聊邀请 管理
|
||||
requests_manager: Optional[RequestManager] = RequestManager(
|
||||
Path(DATA_PATH) / "manager" / "requests_manager.json"
|
||||
DATA_PATH / "manager" / "requests_manager.json"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ class GroupManager(StaticData):
|
||||
"""
|
||||
if not self._task:
|
||||
for matcher in get_matchers():
|
||||
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
|
||||
try:
|
||||
_module = _plugin.module
|
||||
plugin_task = _module.__getattribute__("__plugin_task__")
|
||||
@@ -292,7 +292,6 @@ class GroupManager(StaticData):
|
||||
self._data["group_manager"][group_id]["group_task_status"][
|
||||
task
|
||||
] = Config.get_config('_task', f'DEFAULT_{task}', default=True)
|
||||
print(task, Config.get_config('_task', f'DEFAULT_{task}'))
|
||||
for task in list(
|
||||
self._data["group_manager"][group_id]["group_task_status"]
|
||||
):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from utils.manager.data_class import StaticData
|
||||
from nonebot.adapters.cqhttp import Bot
|
||||
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from services.log import logger
|
||||
from typing import Optional
|
||||
from utils.image_utils import BuildImage
|
||||
|
||||
@@ -31,7 +31,7 @@ class ResourcesManager(StaticData):
|
||||
if isinstance(source_file, Path):
|
||||
source_file = str(source_file.absolute())
|
||||
if isinstance(move_file, Path):
|
||||
move_file = move_file.absolute()
|
||||
move_file = str(move_file.absolute())
|
||||
if module not in self._data.keys():
|
||||
self._data[module] = {source_file: move_file}
|
||||
else:
|
||||
@@ -97,6 +97,7 @@ class ResourcesManager(StaticData):
|
||||
"""
|
||||
添加临时清理文件夹
|
||||
:param path: 路径
|
||||
:param recursive: 是否将该目录下的所有目录也添加为临时文件夹
|
||||
"""
|
||||
if isinstance(path, str):
|
||||
path = Path(path)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from typing import Tuple, Union, Dict
|
||||
from nonebot.adapters.cqhttp import MessageEvent, PrivateMessageEvent, GroupMessageEvent
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, PrivateMessageEvent, GroupMessageEvent
|
||||
|
||||
|
||||
class WithdrawMessageManager:
|
||||
|
||||
+21
-17
@@ -1,5 +1,5 @@
|
||||
from configs.path_config import IMAGE_PATH, VOICE_PATH
|
||||
from nonebot.adapters.cqhttp.message import MessageSegment
|
||||
from configs.path_config import IMAGE_PATH, RECORD_PATH
|
||||
from nonebot.adapters.onebot.v11.message import MessageSegment
|
||||
from configs.config import NICKNAME
|
||||
from services.log import logger
|
||||
from typing import Union, List
|
||||
@@ -8,9 +8,9 @@ import os
|
||||
|
||||
|
||||
def image(
|
||||
img_name: Union[str, Path] = None,
|
||||
file: Union[str, Path, bytes] = None,
|
||||
path: str = None,
|
||||
abspath: str = None,
|
||||
abspath: Union[str, Path] = None,
|
||||
b64: str = None,
|
||||
) -> Union[MessageSegment, str]:
|
||||
"""
|
||||
@@ -18,36 +18,40 @@ def image(
|
||||
生成一个 MessageSegment.image 消息
|
||||
生成顺序:绝对路径(abspath) > base64(b64) > img_name
|
||||
参数:
|
||||
:param img_name: 图片文件名称,默认在 resource/img 目录下
|
||||
:param file: 图片文件名称,默认在 resource/img 目录下
|
||||
:param path: 图片所在路径,默认在 resource/img 目录下
|
||||
:param abspath: 图片绝对路径
|
||||
:param b64: 图片base64
|
||||
"""
|
||||
if abspath:
|
||||
if isinstance(abspath, Path):
|
||||
return MessageSegment.image(file)
|
||||
return (
|
||||
MessageSegment.image("file:///" + abspath)
|
||||
if os.path.exists(abspath)
|
||||
else ""
|
||||
)
|
||||
elif isinstance(img_name, Path):
|
||||
if img_name.exists():
|
||||
return MessageSegment.image(f"file:///{img_name.absolute()}")
|
||||
logger.warning(f"图片 {img_name.absolute()}缺失...")
|
||||
elif isinstance(file, Path):
|
||||
if file.exists():
|
||||
return MessageSegment.image(file)
|
||||
logger.warning(f"图片 {file.absolute()}缺失...")
|
||||
return ""
|
||||
elif isinstance(file, bytes):
|
||||
return MessageSegment.image(file)
|
||||
elif b64:
|
||||
return MessageSegment.image(b64 if "base64://" in b64 else "base64://" + b64)
|
||||
else:
|
||||
if "http" in img_name:
|
||||
return MessageSegment.image(img_name)
|
||||
if len(img_name.split(".")) == 1:
|
||||
img_name += ".jpg"
|
||||
if "http" in file:
|
||||
return MessageSegment.image(file)
|
||||
if len(file.split(".")) == 1:
|
||||
file += ".jpg"
|
||||
file = (
|
||||
Path(IMAGE_PATH) / path / img_name if path else Path(IMAGE_PATH) / img_name
|
||||
IMAGE_PATH / path / file if path else IMAGE_PATH / file
|
||||
)
|
||||
if file.exists():
|
||||
return MessageSegment.image(f"file:///{file.absolute()}")
|
||||
return MessageSegment.image(file)
|
||||
else:
|
||||
logger.warning(f"图片 {file.absolute()}缺失...")
|
||||
logger.warning(f"图片 {file} 缺失...")
|
||||
return ""
|
||||
|
||||
|
||||
@@ -72,7 +76,7 @@ def record(voice_name: str, path: str = None) -> MessageSegment or str:
|
||||
if len(voice_name.split(".")) == 1:
|
||||
voice_name += ".mp3"
|
||||
file = (
|
||||
Path(VOICE_PATH) / path / voice_name if path else Path(VOICE_PATH) / voice_name
|
||||
Path(RECORD_PATH) / path / voice_name if path else Path(RECORD_PATH) / voice_name
|
||||
)
|
||||
if "http" in voice_name:
|
||||
return MessageSegment.record(voice_name)
|
||||
|
||||
+30
-24
@@ -3,7 +3,7 @@ from collections import defaultdict
|
||||
from nonebot import require
|
||||
from configs.config import SYSTEM_PROXY
|
||||
from typing import List, Union, Optional, Type, Any
|
||||
from nonebot.adapters.cqhttp import Bot
|
||||
from nonebot.adapters.onebot.v11 import Bot, Message
|
||||
from nonebot.matcher import matchers, Matcher
|
||||
import httpx
|
||||
import nonebot
|
||||
@@ -190,76 +190,82 @@ def get_matchers() -> List[Type[Matcher]]:
|
||||
return _matchers
|
||||
|
||||
|
||||
def get_message_at(data: str) -> List[int]:
|
||||
def get_message_at(data: Union[str, Message]) -> List[int]:
|
||||
"""
|
||||
说明:
|
||||
获取消息中所有的 at 对象的 qq
|
||||
参数:
|
||||
:param data: event.json()
|
||||
"""
|
||||
try:
|
||||
qq_list = []
|
||||
qq_list = []
|
||||
if isinstance(data, str):
|
||||
data = json.loads(data)
|
||||
for msg in data["message"]:
|
||||
if msg["type"] == "at":
|
||||
qq_list.append(int(msg["data"]["qq"]))
|
||||
return qq_list
|
||||
except KeyError:
|
||||
return []
|
||||
else:
|
||||
for seg in data:
|
||||
if seg.type == "image":
|
||||
qq_list.append(seg.data["url"])
|
||||
return qq_list
|
||||
|
||||
|
||||
def get_message_img(data: str) -> List[str]:
|
||||
def get_message_img(data: Union[str, Message]) -> List[str]:
|
||||
"""
|
||||
说明:
|
||||
获取消息中所有的 图片 的链接
|
||||
参数:
|
||||
:param data: event.json()
|
||||
"""
|
||||
try:
|
||||
img_list = []
|
||||
img_list = []
|
||||
if isinstance(data, str):
|
||||
data = json.loads(data)
|
||||
for msg in data["message"]:
|
||||
if msg["type"] == "image":
|
||||
img_list.append(msg["data"]["url"])
|
||||
return img_list
|
||||
except KeyError:
|
||||
return []
|
||||
else:
|
||||
for seg in data["image"]:
|
||||
img_list.append(seg.data["url"])
|
||||
return img_list
|
||||
|
||||
|
||||
def get_message_text(data: str) -> str:
|
||||
def get_message_text(data: Union[str, Message]) -> str:
|
||||
"""
|
||||
说明:
|
||||
获取消息中 纯文本 的信息
|
||||
参数:
|
||||
:param data: event.json()
|
||||
"""
|
||||
try:
|
||||
result = ""
|
||||
if isinstance(data, str):
|
||||
data = json.loads(data)
|
||||
result = ""
|
||||
for msg in data["message"]:
|
||||
if msg["type"] == "text":
|
||||
result += msg["data"]["text"].strip() + " "
|
||||
return result.strip()
|
||||
except KeyError:
|
||||
return ""
|
||||
else:
|
||||
for seg in data["text"]:
|
||||
result += seg.data["text"] + " "
|
||||
return result
|
||||
|
||||
|
||||
def get_message_record(data: str) -> List[str]:
|
||||
def get_message_record(data: Union[str, Message]) -> List[str]:
|
||||
"""
|
||||
说明:
|
||||
获取消息中所有 语音 的链接
|
||||
参数:
|
||||
:param data: event.json()
|
||||
"""
|
||||
try:
|
||||
record_list = []
|
||||
record_list = []
|
||||
if isinstance(data, str):
|
||||
data = json.loads(data)
|
||||
for msg in data["message"]:
|
||||
if msg["type"] == "record":
|
||||
record_list.append(msg["data"]["url"])
|
||||
return record_list
|
||||
except KeyError:
|
||||
return []
|
||||
else:
|
||||
for seg in data["record"]:
|
||||
record_list.append(seg.data["url"])
|
||||
return record_list
|
||||
|
||||
|
||||
def get_message_json(data: str) -> List[dict]:
|
||||
|
||||
Reference in New Issue
Block a user