mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-24 05:30:08 +08:00
Merge branch 'HibiKier:main' into main
This commit is contained in:
@@ -238,6 +238,34 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
|
|||||||
|
|
||||||
## 更新
|
## 更新
|
||||||
|
|
||||||
|
### 2022/5/24
|
||||||
|
|
||||||
|
* fix: 修正了签到时日期时间的显示不补齐零的bug (符合日期时间表示法 ISO 8601)[@pull/600](https://github.com/HibiKier/zhenxun_bot/pull/600)
|
||||||
|
* 更新"微博热搜"接口 [@pull/579](https://github.com/HibiKier/zhenxun_bot/pull/579)
|
||||||
|
* refactor&fix(manager): modify argument [@pull/576](https://github.com/HibiKier/zhenxun_bot/pull/576)
|
||||||
|
* 修复复读不能复读图片的问题 [@pull/573](https://github.com/HibiKier/zhenxun_bot/pull/573)
|
||||||
|
* 修复抽卡插件:方舟抽卡的抽取和显示问题 [@pull/581](https://github.com/HibiKier/zhenxun_bot/pull/581)
|
||||||
|
|
||||||
|
### 2022/5/23 \[v0.1.5.6]
|
||||||
|
|
||||||
|
* 修复"清除已删除插件数据" [@pull/545](https://github.com/HibiKier/zhenxun_bot/pull/545)
|
||||||
|
* 修复有置顶的up主B站动态获取失败 [@pull/552](https://github.com/HibiKier/zhenxun_bot/pull/552)
|
||||||
|
* 添加pixiv搜图多关键词支持;修复p站搜图数量参数问题 [@pull/441](https://github.com/HibiKier/zhenxun_bot/pull/441)
|
||||||
|
* 修复开箱更新价格错误传参
|
||||||
|
* 修复pix无法正确查询uid
|
||||||
|
* 新增色图插件添加配置项ALLOW_GROUP_R18:允许群聊中使用色图r
|
||||||
|
* 新增PIX插件添加配置项ALLOW_GROUP_SETU:允许非超级用户使用-s参数
|
||||||
|
* 新增PIX插件添加配置项ALLOW_GROUP_R18:允许非超级用户使用-r参数
|
||||||
|
|
||||||
|
### 2022/5/22 \[v0.1.5.4]
|
||||||
|
|
||||||
|
* 使用action自动更新poetry.lock [@pull/515](https://github.com/HibiKier/zhenxun_bot/pull/515)
|
||||||
|
* fix(bilibili_sub): card is None and timeout [@pull/516](https://github.com/HibiKier/zhenxun_bot/pull/516)
|
||||||
|
* 修复了epic有时获取新免费游戏消息时获取不到图片
|
||||||
|
* 修复好感度满时签到出错(虽然是不可能满的
|
||||||
|
* 修复原神资源图标下载路径错误
|
||||||
|
* 修复自动更新群组可能失败
|
||||||
|
|
||||||
### 2022/5/21
|
### 2022/5/21
|
||||||
|
|
||||||
* 修复搜番无结果时报错无正确反馈
|
* 修复搜番无结果时报错无正确反馈
|
||||||
@@ -279,7 +307,7 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
|
|||||||
|
|
||||||
* fix: 更改p搜api,解决p搜无法使用的问题 [@pull/155](https://github.com/HibiKier/zhenxun_bot/pull/155)
|
* fix: 更改p搜api,解决p搜无法使用的问题 [@pull/155](https://github.com/HibiKier/zhenxun_bot/pull/155)
|
||||||
|
|
||||||
### 2022/5/9
|
### 2022/5/9 \[v0.1.5.3]
|
||||||
|
|
||||||
* 替换了疫情API
|
* 替换了疫情API
|
||||||
* 修复了私聊.ban/.unban出错
|
* 修复了私聊.ban/.unban出错
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
__version__: v0.1.5.3
|
__version__: v0.1.5.6
|
||||||
@@ -2,6 +2,7 @@ from configs.config import Config
|
|||||||
from models.chat_history import ChatHistory
|
from models.chat_history import ChatHistory
|
||||||
from nonebot import on_message
|
from nonebot import on_message
|
||||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||||
|
from utils.utils import get_message_text
|
||||||
|
|
||||||
from ._rule import rule
|
from ._rule import rule
|
||||||
|
|
||||||
@@ -22,10 +23,10 @@ chat_history = on_message(rule=rule, priority=1, block=False)
|
|||||||
async def _(event: MessageEvent):
|
async def _(event: MessageEvent):
|
||||||
if isinstance(event, GroupMessageEvent):
|
if isinstance(event, GroupMessageEvent):
|
||||||
await ChatHistory.add_chat_msg(
|
await ChatHistory.add_chat_msg(
|
||||||
event.user_id, event.group_id, str(event.get_message())
|
event.user_id, event.group_id, str(event.get_message()), get_message_text(event.json())
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await ChatHistory.add_chat_msg(event.user_id, None, str(event.get_message()))
|
await ChatHistory.add_chat_msg(event.user_id, None, str(event.get_message()), get_message_text(event.json()))
|
||||||
|
|
||||||
|
|
||||||
# @test.handle()
|
# @test.handle()
|
||||||
|
|||||||
@@ -20,26 +20,36 @@ def init_none_plugin_count_manager():
|
|||||||
"""
|
"""
|
||||||
清除已删除插件数据
|
清除已删除插件数据
|
||||||
"""
|
"""
|
||||||
modules = [x.module for x in get_matchers()]
|
modules = [x.plugin_name for x in get_matchers()]
|
||||||
for module in none_plugin_count_manager.keys():
|
plugins_manager_list = list(plugins_manager.keys())
|
||||||
if module not in modules:
|
for module in plugins_manager_list:
|
||||||
none_plugin_count_manager.add_count(module)
|
if module not in modules or none_plugin_count_manager.check(module):
|
||||||
else:
|
|
||||||
none_plugin_count_manager.reset(module)
|
|
||||||
if none_plugin_count_manager.check(module):
|
|
||||||
try:
|
try:
|
||||||
plugin_name = plugins_manager.get(module)["plugin_name"]
|
plugin_name = plugins_manager.get(module)["plugin_name"]
|
||||||
except (AttributeError, KeyError):
|
except (AttributeError, KeyError):
|
||||||
plugin_name = ""
|
plugin_name = ""
|
||||||
try:
|
if none_plugin_count_manager.check(module):
|
||||||
plugins2settings_manager.delete(module)
|
try:
|
||||||
plugins2count_manager.delete(module)
|
plugins2settings_manager.delete(module)
|
||||||
plugins2cd_manager.delete(module)
|
plugins2settings_manager.save()
|
||||||
plugins2block_manager.delete(module)
|
plugins2count_manager.delete(module)
|
||||||
plugins_manager.delete(module)
|
plugins2count_manager.save()
|
||||||
resources_manager.remove_resource(module)
|
plugins2cd_manager.delete(module)
|
||||||
logger.info(f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据...")
|
plugins2cd_manager.save()
|
||||||
except Exception as e:
|
plugins2block_manager.delete(module)
|
||||||
logger.error(
|
plugins2block_manager.save()
|
||||||
f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据失败...{type(e)}:{e}"
|
plugins_manager.delete(module)
|
||||||
)
|
plugins_manager.save()
|
||||||
|
resources_manager.remove_resource(module)
|
||||||
|
none_plugin_count_manager.delete(module)
|
||||||
|
logger.info(f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据...")
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(
|
||||||
|
f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据失败...{type(e)}:{e}")
|
||||||
|
else:
|
||||||
|
none_plugin_count_manager.add_count(module)
|
||||||
|
logger.info(
|
||||||
|
f"{module}:{plugin_name} 插件疑似已删除,加载{none_plugin_count_manager._max_count}次失败后将清除对应插件数据,当前次数:{none_plugin_count_manager._data[module]}")
|
||||||
|
else:
|
||||||
|
none_plugin_count_manager.reset(module)
|
||||||
|
none_plugin_count_manager.save()
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ def init_plugins_cd_limit(data_path):
|
|||||||
_module = _plugin.module
|
_module = _plugin.module
|
||||||
plugin_cd_limit = _module.__getattribute__("__plugin_cd_limit__")
|
plugin_cd_limit = _module.__getattribute__("__plugin_cd_limit__")
|
||||||
plugins2cd_manager.add_cd_limit(
|
plugins2cd_manager.add_cd_limit(
|
||||||
matcher.plugin_name, data_dict=plugin_cd_limit
|
matcher.plugin_name, **plugin_cd_limit
|
||||||
)
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
@@ -76,7 +76,7 @@ def init_plugins_block_limit(data_path):
|
|||||||
_module = _plugin.module
|
_module = _plugin.module
|
||||||
plugin_block_limit = _module.__getattribute__("__plugin_block_limit__")
|
plugin_block_limit = _module.__getattribute__("__plugin_block_limit__")
|
||||||
plugins2block_manager.add_block_limit(
|
plugins2block_manager.add_block_limit(
|
||||||
matcher.plugin_name, data_dict=plugin_block_limit
|
matcher.plugin_name, **plugin_block_limit
|
||||||
)
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
@@ -124,7 +124,7 @@ def init_plugins_count_limit(data_path):
|
|||||||
_module = _plugin.module
|
_module = _plugin.module
|
||||||
plugin_count_limit = _module.__getattribute__("__plugin_count_limit__")
|
plugin_count_limit = _module.__getattribute__("__plugin_count_limit__")
|
||||||
plugins2count_manager.add_count_limit(
|
plugins2count_manager.add_count_limit(
|
||||||
matcher.plugin_name, data_dict=plugin_count_limit
|
matcher.plugin_name, **plugin_count_limit
|
||||||
)
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ async def _():
|
|||||||
"ALTER TABLE genshin ADD bind_group Integer;",
|
"ALTER TABLE genshin ADD bind_group Integer;",
|
||||||
"genshin"
|
"genshin"
|
||||||
), # 新增原神群号绑定字段
|
), # 新增原神群号绑定字段
|
||||||
|
(
|
||||||
|
"ALTER TABLE chat_history ADD plain_text Text;",
|
||||||
|
"chat_history"
|
||||||
|
), # 新增纯文本
|
||||||
]
|
]
|
||||||
for sql in sql_str:
|
for sql in sql_str:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|||||||
level = 0
|
level = 0
|
||||||
if not msg:
|
if not msg:
|
||||||
await add_group_level.finish("用法:修改群权限 [group] [level]")
|
await add_group_level.finish("用法:修改群权限 [group] [level]")
|
||||||
msg = msg.split(" ")
|
msg = msg.split()
|
||||||
if len(msg) < 2:
|
if len(msg) < 2:
|
||||||
await add_group_level.finish("参数不完全..[group] [level]")
|
await add_group_level.finish("参数不完全..[group] [level]")
|
||||||
if is_number(msg[0]) and is_number(msg[1]):
|
if is_number(msg[0]) and is_number(msg[1]):
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ async def _():
|
|||||||
group_info["group_name"],
|
group_info["group_name"],
|
||||||
group_info["max_member_count"],
|
group_info["max_member_count"],
|
||||||
group_info["member_count"],
|
group_info["member_count"],
|
||||||
|
1
|
||||||
):
|
):
|
||||||
num += 1
|
num += 1
|
||||||
logger.info(f"自动更新群组 {g} 信息成功")
|
logger.info(f"自动更新群组 {g} 信息成功")
|
||||||
|
|||||||
@@ -11,12 +11,13 @@ class ChatHistory(db.Model):
|
|||||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||||
group_id = db.Column(db.BigInteger())
|
group_id = db.Column(db.BigInteger())
|
||||||
text = db.Column(db.Text())
|
text = db.Column(db.Text())
|
||||||
|
plain_text = db.Column(db.Text())
|
||||||
create_time = db.Column(db.DateTime(timezone=True), nullable=False)
|
create_time = db.Column(db.DateTime(timezone=True), nullable=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def add_chat_msg(cls, user_qq: int, group_id: Optional[int], text: str):
|
async def add_chat_msg(cls, user_qq: int, group_id: Optional[int], text: str, plain_text: str):
|
||||||
await cls.create(
|
await cls.create(
|
||||||
user_qq=user_qq, group_id=group_id, text=text, create_time=datetime.now()
|
user_qq=user_qq, group_id=group_id, text=text, plain_text=plain_text, create_time=datetime.now()
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -97,7 +98,6 @@ class ChatHistory(db.Model):
|
|||||||
if date_scope:
|
if date_scope:
|
||||||
sql += f"AND create_time BETWEEN '{date_scope[0]}' AND '{date_scope[1]}' "
|
sql += f"AND create_time BETWEEN '{date_scope[0]}' AND '{date_scope[1]}' "
|
||||||
sql += f"GROUP BY user_qq ORDER BY sum {order if order and order.upper() != 'DES' else ''} LIMIT {limit}"
|
sql += f"GROUP BY user_qq ORDER BY sum {order if order and order.upper() != 'DES' else ''} LIMIT {limit}"
|
||||||
print(sql)
|
|
||||||
return await db.all(db.text(sql))
|
return await db.all(db.text(sql))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Config.add_plugin_config(
|
|||||||
"alapi", "ALAPI_TOKEN", None, help_="在 https://admin.alapi.cn/user/login 登录后获取token"
|
"alapi", "ALAPI_TOKEN", None, help_="在 https://admin.alapi.cn/user/login 登录后获取token"
|
||||||
)
|
)
|
||||||
|
|
||||||
ai = on_message(rule=to_me(), priority=8)
|
ai = on_message(rule=to_me(), priority=998)
|
||||||
|
|
||||||
|
|
||||||
@ai.handle()
|
@ai.handle()
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
|
||||||
from utils.image_utils import BuildImage
|
|
||||||
from utils.message_builder import image
|
|
||||||
from configs.path_config import IMAGE_PATH
|
|
||||||
from typing import Optional, Tuple, Union
|
from typing import Optional, Tuple, Union
|
||||||
from configs.config import Config
|
from configs.config import Config
|
||||||
from utils.http_utils import AsyncHttpx
|
from utils.http_utils import AsyncHttpx
|
||||||
@@ -28,24 +24,3 @@ async def get_data(url: str, params: Optional[dict] = None) -> Tuple[Union[dict,
|
|||||||
return f'发生了错误...code:{data["code"]}', 999
|
return f'发生了错误...code:{data["code"]}', 999
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
return "超时了....", 998
|
return "超时了....", 998
|
||||||
|
|
||||||
|
|
||||||
def gen_wbtop_pic(data: dict) -> MessageSegment:
|
|
||||||
"""
|
|
||||||
生成微博热搜图片
|
|
||||||
:param data: 微博热搜数据
|
|
||||||
"""
|
|
||||||
bk = BuildImage(700, 32 * 50 + 280, 700, 32, color="#797979")
|
|
||||||
wbtop_bk = BuildImage(700, 280, background=f"{IMAGE_PATH}/other/webtop.png")
|
|
||||||
bk.paste(wbtop_bk)
|
|
||||||
text_bk = BuildImage(700, 32 * 50, 700, 32, color="#797979")
|
|
||||||
for i, data in enumerate(data):
|
|
||||||
title = f"{i+1}. {data['hot_word']}"
|
|
||||||
hot = data["hot_word_num"]
|
|
||||||
img = BuildImage(700, 30, font_size=20)
|
|
||||||
w, h = img.getsize(title)
|
|
||||||
img.text((10, int((30 - h) / 2)), title)
|
|
||||||
img.text((580, int((30 - h) / 2)), hot)
|
|
||||||
text_bk.paste(img)
|
|
||||||
bk.paste(text_bk, (0, 280))
|
|
||||||
return image(b64=bk.pic2bs4())
|
|
||||||
|
|||||||
@@ -324,21 +324,21 @@ async def get_user_dynamic(
|
|||||||
wait_until="networkidle",
|
wait_until="networkidle",
|
||||||
timeout=10000,
|
timeout=10000,
|
||||||
)
|
)
|
||||||
await page.set_viewport_size({"width": 2560, "height": 1080})
|
await page.set_viewport_size({"width": 2560, "height": 1080, "timeout": 10000*20}) # timeout: 200s
|
||||||
# 删除置顶
|
# 删除置顶
|
||||||
await page.evaluate(
|
await page.evaluate(
|
||||||
"""
|
"""
|
||||||
xs = document.getElementsByClassName('bili-dyn-item__tag');
|
xs = document.getElementsByClassName('bili-dyn-item__tag');
|
||||||
for (x of xs) {
|
for (x of xs) {
|
||||||
x.parentNode.remove();
|
x.parentNode.parentNode.remove();
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
card = await page.query_selector(".bili-dyn-list__item")
|
card = page.locator(".bili-dyn-list__item").first
|
||||||
|
await card.wait_for()
|
||||||
# 截图并保存
|
# 截图并保存
|
||||||
await card.screenshot(
|
await card.screenshot(
|
||||||
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||||
timeout=100000,
|
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"B站订阅:获取用户动态 发送错误 {type(e)}:{e}")
|
logger.error(f"B站订阅:获取用户动态 发送错误 {type(e)}:{e}")
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des
|
|||||||
ava = BuildImage(100, 100, background=BytesIO(await get_pic(face)))
|
ava = BuildImage(100, 100, background=BytesIO(await get_pic(face)))
|
||||||
ava.circle()
|
ava.circle()
|
||||||
cover = BuildImage(470, 265, background=BytesIO(await get_pic(cover)))
|
cover = BuildImage(470, 265, background=BytesIO(await get_pic(cover)))
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def _create_live_des_image(
|
def _create_live_des_image(
|
||||||
|
|||||||
@@ -241,7 +241,6 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
|||||||
uid = int(msg[0])
|
uid = int(msg[0])
|
||||||
id_ = int(msg[1])
|
id_ = int(msg[1])
|
||||||
punish_level = int(msg[2])
|
punish_level = int(msg[2])
|
||||||
print(uid, id_, punish_level)
|
|
||||||
rst = await set_user_punish(uid, id_, punish_level)
|
rst = await set_user_punish(uid, id_, punish_level)
|
||||||
await set_punish.send(rst)
|
await set_punish.send(rst)
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ class BlackWord(db.Model):
|
|||||||
user = await query.where(cls.black_word == black_word).order_by(cls.id.desc()).gino.first()
|
user = await query.where(cls.black_word == black_word).order_by(cls.id.desc()).gino.first()
|
||||||
elif id_:
|
elif id_:
|
||||||
user_list = await query.gino.all()
|
user_list = await query.gino.all()
|
||||||
print(len(user_list))
|
|
||||||
if len(user_list) == 0 or (id_ < 0 or id_ > len(user_list)):
|
if len(user_list) == 0 or (id_ < 0 or id_ > len(user_list)):
|
||||||
return False
|
return False
|
||||||
user = user_list[id_]
|
user = user_list[id_]
|
||||||
|
|||||||
@@ -88,9 +88,7 @@ class BlackWordManager:
|
|||||||
:param group_id: 群号
|
:param group_id: 群号
|
||||||
:param message: 消息
|
:param message: 消息
|
||||||
"""
|
"""
|
||||||
print(user_id, group_id, message)
|
|
||||||
if data := self._check(message):
|
if data := self._check(message):
|
||||||
print(data)
|
|
||||||
if data[0]:
|
if data[0]:
|
||||||
await _add_user_black_word(
|
await _add_user_black_word(
|
||||||
user_id, group_id, data[0], message, int(data[1])
|
user_id, group_id, data[0], message, int(data[1])
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ from configs.config import Config
|
|||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
if platform.system() == "Windows":
|
# if platform.system() == "Windows":
|
||||||
import asyncio
|
# import asyncio
|
||||||
|
#
|
||||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||||
|
|
||||||
|
|
||||||
url = "http://www.eclzz.mobi"
|
url = "http://www.eclzz.mobi"
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import tarfile
|
|||||||
import shutil
|
import shutil
|
||||||
import os
|
import os
|
||||||
|
|
||||||
if str(platform.system()).lower() == "windows":
|
# if str(platform.system()).lower() == "windows":
|
||||||
policy = asyncio.WindowsSelectorEventLoopPolicy()
|
# policy = asyncio.WindowsSelectorEventLoopPolicy()
|
||||||
asyncio.set_event_loop_policy(policy)
|
# asyncio.set_event_loop_policy(policy)
|
||||||
|
|
||||||
|
|
||||||
driver = nonebot.get_driver()
|
driver = nonebot.get_driver()
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class PrtsHandle(BaseHandle[Operator]):
|
|||||||
all_operators = [
|
all_operators = [
|
||||||
x
|
x
|
||||||
for x in self.ALL_OPERATOR
|
for x in self.ALL_OPERATOR
|
||||||
if x.star == star and not any([x.limited, x.event_only, x.recruit_only])
|
if x.star == star and not any([x.limited, x.recruit_only, x.event_only])
|
||||||
]
|
]
|
||||||
acquire_operator = None
|
acquire_operator = None
|
||||||
|
|
||||||
@@ -107,9 +107,12 @@ class PrtsHandle(BaseHandle[Operator]):
|
|||||||
async def draw(self, count: int, **kwargs) -> Message:
|
async def draw(self, count: int, **kwargs) -> Message:
|
||||||
return await asyncio.get_event_loop().run_in_executor(None, self._draw, count)
|
return await asyncio.get_event_loop().run_in_executor(None, self._draw, count)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _draw(self, count: int, **kwargs) -> Message:
|
def _draw(self, count: int, **kwargs) -> Message:
|
||||||
index2card = self.get_cards(count)
|
index2card = self.get_cards(count)
|
||||||
cards = [card[0] for card in self.get_cards(count)]
|
"""这里cards修复了抽卡图文不符的bug"""
|
||||||
|
cards = [card[0] for card in index2card]
|
||||||
up_list = [x.name for x in self.UP_EVENT.up_char] if self.UP_EVENT else []
|
up_list = [x.name for x in self.UP_EVENT.up_char] if self.UP_EVENT else []
|
||||||
result = self.format_result(index2card, up_list=up_list)
|
result = self.format_result(index2card, up_list=up_list)
|
||||||
pool_info = self.format_pool_info()
|
pool_info = self.format_pool_info()
|
||||||
@@ -185,14 +188,15 @@ class PrtsHandle(BaseHandle[Operator]):
|
|||||||
avatar = char.xpath("./td[1]/div/div/div/a/img/@srcset")[0]
|
avatar = char.xpath("./td[1]/div/div/div/a/img/@srcset")[0]
|
||||||
name = char.xpath("./td[2]/a/text()")[0]
|
name = char.xpath("./td[2]/a/text()")[0]
|
||||||
star = char.xpath("./td[5]/text()")[0]
|
star = char.xpath("./td[5]/text()")[0]
|
||||||
sources = str(char.xpath("./td[8]/text()")[0]).split("\n")
|
"""这里sources修好了干员获取标签有问题的bug,如三星只能抽到卡缇就是这个原因"""
|
||||||
|
sources = [_.strip('\n') for _ in char.xpath("./td[8]/text()")]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
continue
|
continue
|
||||||
member_dict = {
|
member_dict = {
|
||||||
"头像": unquote(str(avatar).split(" ")[-2]),
|
"头像": unquote(str(avatar).split(" ")[-2]),
|
||||||
"名称": remove_prohibited_str(str(name).strip()),
|
"名称": remove_prohibited_str(str(name).strip()),
|
||||||
"星级": int(str(star).strip()),
|
"星级": int(str(star).strip()),
|
||||||
"获取途径": [s for s in sources if s],
|
"获取途径": sources,
|
||||||
}
|
}
|
||||||
info[member_dict["名称"]] = member_dict
|
info[member_dict["名称"]] = member_dict
|
||||||
self.dump_data(info)
|
self.dump_data(info)
|
||||||
@@ -245,6 +249,10 @@ class PrtsHandle(BaseHandle[Operator]):
|
|||||||
if match:
|
if match:
|
||||||
time = match.group(1)
|
time = match.group(1)
|
||||||
if "★" in line:
|
if "★" in line:
|
||||||
|
"""这里修复了某些池子六星名称显示错误的问题(如奔崖号角)"""
|
||||||
|
if line[0] != '★':
|
||||||
|
idx = line.find('★')
|
||||||
|
line = line[idx:]
|
||||||
chars.append(line)
|
chars.append(line)
|
||||||
if not time:
|
if not time:
|
||||||
continue
|
continue
|
||||||
|
|||||||
+24
-37
@@ -1,58 +1,34 @@
|
|||||||
from httpx import AsyncClient
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot.adapters.onebot.v11 import Bot
|
from nonebot.adapters.onebot.v11 import Bot
|
||||||
from configs.config import NICKNAME
|
from configs.config import NICKNAME
|
||||||
|
from utils.http_utils import AsyncHttpx
|
||||||
|
|
||||||
|
|
||||||
# 获取所有 Epic Game Store 促销游戏
|
# 获取所有 Epic Game Store 促销游戏
|
||||||
# 方法参考:RSSHub /epicgames 路由
|
# 方法参考:RSSHub /epicgames 路由
|
||||||
# https://github.com/DIYgod/RSSHub/blob/master/lib/routes/epicgames/index.js
|
# https://github.com/DIYgod/RSSHub/blob/master/lib/routes/epicgames/index.js
|
||||||
async def get_epic_game():
|
async def get_epic_game():
|
||||||
# 现在没用 graphql 辣
|
|
||||||
"""prv_graphql Code
|
|
||||||
epic_url = "https://www.epicgames.com/store/backend/graphql-proxy"
|
|
||||||
headers = {
|
|
||||||
"Referer": "https://www.epicgames.com/store/zh-CN/",
|
|
||||||
"Content-Type": "application/json; charset=utf-8",
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
"query": "query searchStoreQuery($allowCountries: String, $category: String, $count: Int, $country: String!, $keywords: String, $locale: String, $namespace: String, $sortBy: String, $sortDir: String, $start: Int, $tag: String, $withPrice: Boolean = false, $withPromotions: Boolean = false) {\n Catalog {\n searchStore(allowCountries: $allowCountries, category: $category, count: $count, country: $country, keywords: $keywords, locale: $locale, namespace: $namespace, sortBy: $sortBy, sortDir: $sortDir, start: $start, tag: $tag) {\n elements {\n title\n id\n namespace\n description\n effectiveDate\n keyImages {\n type\n url\n }\n seller {\n id\n name\n }\n productSlug\n urlSlug\n url\n items {\n id\n namespace\n }\n customAttributes {\n key\n value\n }\n categories {\n path\n }\n price(country: $country) @include(if: $withPrice) {\n totalPrice {\n discountPrice\n originalPrice\n voucherDiscount\n discount\n currencyCode\n currencyInfo {\n decimals\n }\n fmtPrice(locale: $locale) {\n originalPrice\n discountPrice\n intermediatePrice\n }\n }\n lineOffers {\n appliedRules {\n id\n endDate\n discountSetting {\n discountType\n }\n }\n }\n }\n promotions(category: $category) @include(if: $withPromotions) {\n promotionalOffers {\n promotionalOffers {\n startDate\n endDate\n discountSetting {\n discountType\n discountPercentage\n }\n }\n }\n upcomingPromotionalOffers {\n promotionalOffers {\n startDate\n endDate\n discountSetting {\n discountType\n discountPercentage\n }\n }\n }\n }\n }\n paging {\n count\n total\n }\n }\n }\n}\n",
|
|
||||||
"variables": {
|
|
||||||
"allowCountries": "CN",
|
|
||||||
"category": "freegames",
|
|
||||||
"count": 1000,
|
|
||||||
"country": "CN",
|
|
||||||
"locale": "zh-CN",
|
|
||||||
"sortBy": "effectiveDate",
|
|
||||||
"sortDir": "asc",
|
|
||||||
"withPrice": True,
|
|
||||||
"withPromotions": True,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
epic_url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions?locale=zh-CN&country=CN&allowCountries=CN"
|
epic_url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions?locale=zh-CN&country=CN&allowCountries=CN"
|
||||||
headers = {
|
headers = {
|
||||||
"Referer": "https://www.epicgames.com/store/zh-CN/",
|
"Referer": "https://www.epicgames.com/store/zh-CN/",
|
||||||
"Content-Type": "application/json; charset=utf-8",
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36",
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36",
|
||||||
}
|
}
|
||||||
async with AsyncClient(headers=headers) as client:
|
try:
|
||||||
try:
|
res = await AsyncHttpx.get(epic_url, headers=headers, timeout=10)
|
||||||
res = await client.get(epic_url, timeout=10.0)
|
res_json = res.json()
|
||||||
res_json = res.json()
|
games = res_json["data"]["Catalog"]["searchStore"]["elements"]
|
||||||
games = res_json["data"]["Catalog"]["searchStore"]["elements"]
|
return games
|
||||||
return games
|
except Exception as e:
|
||||||
except Exception as e:
|
logger.error(f"Epic 访问接口错误 {type(e)}:{e}")
|
||||||
logger.error(str(e))
|
return None
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
# 获取 Epic Game Store 免费游戏信息
|
# 获取 Epic Game Store 免费游戏信息
|
||||||
# 处理免费游戏的信息方法借鉴 pip 包 epicstore_api 示例
|
# 处理免费游戏的信息方法借鉴 pip 包 epicstore_api 示例
|
||||||
# https://github.com/SD4RK/epicstore_api/blob/master/examples/free_games_example.py
|
# https://github.com/SD4RK/epicstore_api/blob/master/examples/free_games_example.py
|
||||||
async def get_epic_free(bot: Bot, Type_Event: str):
|
async def get_epic_free(bot: Bot, type_event: str):
|
||||||
games = await get_epic_game()
|
games = await get_epic_game()
|
||||||
if not games:
|
if not games:
|
||||||
return "Epic 可能又抽风啦,请稍后再试(", 404
|
return "Epic 可能又抽风啦,请稍后再试(", 404
|
||||||
@@ -81,7 +57,7 @@ async def get_epic_free(bot: Bot, Type_Event: str):
|
|||||||
end_date = datetime.fromisoformat(end_date_iso).strftime(
|
end_date = datetime.fromisoformat(end_date_iso).strftime(
|
||||||
"%b.%d %H:%M"
|
"%b.%d %H:%M"
|
||||||
)
|
)
|
||||||
if Type_Event == "Group":
|
if type_event == "Group":
|
||||||
_message = "\n由 {} 公司发行的游戏 {} ({}) 在 UTC 时间 {} 即将推出免费游玩,预计截至 {}。".format(
|
_message = "\n由 {} 公司发行的游戏 {} ({}) 在 UTC 时间 {} 即将推出免费游玩,预计截至 {}。".format(
|
||||||
game_corp, game_name, game_price, start_date, end_date
|
game_corp, game_name, game_price, start_date, end_date
|
||||||
)
|
)
|
||||||
@@ -101,8 +77,19 @@ async def get_epic_free(bot: Bot, Type_Event: str):
|
|||||||
msg_list.append(msg)
|
msg_list.append(msg)
|
||||||
else:
|
else:
|
||||||
for image in game["keyImages"]:
|
for image in game["keyImages"]:
|
||||||
if image["type"] == "Thumbnail":
|
if (
|
||||||
|
image.get("url")
|
||||||
|
and not game_thumbnail
|
||||||
|
and image["type"]
|
||||||
|
in [
|
||||||
|
"Thumbnail",
|
||||||
|
"VaultOpened",
|
||||||
|
"DieselStoreFrontWide",
|
||||||
|
"OfferImageWide",
|
||||||
|
]
|
||||||
|
):
|
||||||
game_thumbnail = image["url"]
|
game_thumbnail = image["url"]
|
||||||
|
break
|
||||||
for pair in game["customAttributes"]:
|
for pair in game["customAttributes"]:
|
||||||
if pair["key"] == "developerName":
|
if pair["key"] == "developerName":
|
||||||
game_dev = pair["value"]
|
game_dev = pair["value"]
|
||||||
@@ -127,7 +114,7 @@ async def get_epic_free(bot: Bot, Type_Event: str):
|
|||||||
game_url = "https://www.epicgames.com/store/zh-CN/p/{}".format(
|
game_url = "https://www.epicgames.com/store/zh-CN/p/{}".format(
|
||||||
game_url_part
|
game_url_part
|
||||||
)
|
)
|
||||||
if Type_Event == "Group":
|
if type_event == "Group":
|
||||||
_message = "[CQ:image,file={}]\n\nFREE now :: {} ({})\n{}\n此游戏由 {} 开发、{} 发行,将在 UTC 时间 {} 结束免费游玩,戳链接速度加入你的游戏库吧~\n{}\n".format(
|
_message = "[CQ:image,file={}]\n\nFREE now :: {} ({})\n{}\n此游戏由 {} 开发、{} 发行,将在 UTC 时间 {} 结束免费游玩,戳链接速度加入你的游戏库吧~\n{}\n".format(
|
||||||
game_thumbnail,
|
game_thumbnail,
|
||||||
game_name,
|
game_name,
|
||||||
|
|||||||
+7
-6
@@ -106,20 +106,21 @@ async def _(event: GroupMessageEvent):
|
|||||||
"fudu", "FUDU_PROBABILITY"
|
"fudu", "FUDU_PROBABILITY"
|
||||||
) and not _fudu_list.is_repeater(event.group_id):
|
) and not _fudu_list.is_repeater(event.group_id):
|
||||||
if random.random() < 0.2:
|
if random.random() < 0.2:
|
||||||
await fudu.finish("[[_task|fudu]]打断施法!")
|
if msg.endswith("打断施法!"):
|
||||||
|
await fudu.finish("[[_task|fudu]]打断" + msg)
|
||||||
|
else:
|
||||||
|
await fudu.finish("[[_task|fudu]]打断施法!")
|
||||||
_fudu_list.set_repeater(event.group_id)
|
_fudu_list.set_repeater(event.group_id)
|
||||||
if img and msg:
|
if img and msg:
|
||||||
rst = msg + image(f"compare_{event.group_id}_img.jpg", "temp")
|
rst = msg + image(TEMP_PATH / f"compare_{event.group_id}_img.jpg")
|
||||||
elif img:
|
elif img:
|
||||||
rst = image(f"compare_{event.group_id}_img.jpg", "temp")
|
rst = image(TEMP_PATH / f"compare_{event.group_id}_img.jpg")
|
||||||
elif msg:
|
elif msg:
|
||||||
rst = msg
|
rst = msg
|
||||||
else:
|
else:
|
||||||
rst = ""
|
rst = ""
|
||||||
if rst:
|
if rst:
|
||||||
if rst.endswith("打断施法!"):
|
await fudu.finish("[[_task|fudu]]" + rst)
|
||||||
rst = "打断" + rst
|
|
||||||
await fudu.send("[[_task|fudu]]" + rst)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_fudu_img_hash(url, group_id):
|
async def get_fudu_img_hash(url, group_id):
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from pathlib import Path
|
||||||
from typing import Tuple, Optional, List
|
from typing import Tuple, Optional, List
|
||||||
from configs.path_config import IMAGE_PATH, TEXT_PATH
|
from configs.path_config import IMAGE_PATH, TEXT_PATH
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
@@ -136,7 +137,7 @@ async def download_resource_data(semaphore: Semaphore):
|
|||||||
asyncio.ensure_future(
|
asyncio.ensure_future(
|
||||||
download_image(
|
download_image(
|
||||||
img_url,
|
img_url,
|
||||||
f"{icon_path}/{id_}.png",
|
icon_path / f"{id_}.png",
|
||||||
semaphore,
|
semaphore,
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
@@ -178,7 +179,7 @@ async def download_map_init(semaphore: Semaphore, flag: bool = False):
|
|||||||
map_url = _map_data["url"]
|
map_url = _map_data["url"]
|
||||||
await download_image(
|
await download_image(
|
||||||
map_url,
|
map_url,
|
||||||
f"{map_path}/{idx}.png",
|
map_path / f"{idx}.png",
|
||||||
semaphore,
|
semaphore,
|
||||||
force_flag=flag,
|
force_flag=flag,
|
||||||
)
|
)
|
||||||
@@ -227,15 +228,14 @@ async def download_resource_type():
|
|||||||
except (TimeoutError, ConnectTimeout):
|
except (TimeoutError, ConnectTimeout):
|
||||||
logger.warning("下载原神资源类型数据超时....")
|
logger.warning("下载原神资源类型数据超时....")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"载原神资源类型数据超时 {type(e)}:{e}")
|
logger.error(f"载原神资源类型数据错误 {type(e)}:{e}")
|
||||||
|
|
||||||
|
|
||||||
# 初始化资源图标
|
# 初始化资源图标
|
||||||
def gen_icon(icon: str):
|
def gen_icon(icon: Path):
|
||||||
A = BuildImage(0, 0, background=f"{icon_path}/box.png")
|
A = BuildImage(0, 0, background=f"{icon_path}/box.png")
|
||||||
B = BuildImage(0, 0, background=f"{icon_path}/box_alpha.png")
|
B = BuildImage(0, 0, background=f"{icon_path}/box_alpha.png")
|
||||||
icon_ = icon_path / f"{icon}"
|
icon_img = BuildImage(115, 115, background=icon)
|
||||||
icon_img = BuildImage(115, 115, background=icon_)
|
|
||||||
icon_img.circle()
|
icon_img.circle()
|
||||||
B.paste(icon_img, (17, 10), True)
|
B.paste(icon_img, (17, 10), True)
|
||||||
B.paste(A, alpha=True)
|
B.paste(A, alpha=True)
|
||||||
@@ -246,14 +246,14 @@ def gen_icon(icon: str):
|
|||||||
# 下载图片
|
# 下载图片
|
||||||
async def download_image(
|
async def download_image(
|
||||||
img_url: str,
|
img_url: str,
|
||||||
path: str,
|
path: Path,
|
||||||
semaphore: Semaphore,
|
semaphore: Semaphore,
|
||||||
gen_flag: bool = False,
|
gen_flag: bool = False,
|
||||||
force_flag: bool = False,
|
force_flag: bool = False,
|
||||||
):
|
):
|
||||||
async with semaphore:
|
async with semaphore:
|
||||||
try:
|
try:
|
||||||
if not os.path.exists(path) or not is_valid or force_flag:
|
if not path.exists() or not is_valid(path) or force_flag:
|
||||||
if await AsyncHttpx.download_file(img_url, path, timeout=10):
|
if await AsyncHttpx.download_file(img_url, path, timeout=10):
|
||||||
logger.info(f"下载原神资源图标:{img_url}")
|
logger.info(f"下载原神资源图标:{img_url}")
|
||||||
if gen_flag:
|
if gen_flag:
|
||||||
|
|||||||
@@ -211,16 +211,16 @@ update_price = on_command("更新开箱价格", priority=1, permission=SUPERUSER
|
|||||||
|
|
||||||
|
|
||||||
@update_price.handle()
|
@update_price.handle()
|
||||||
async def _( event: MessageEvent):
|
async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||||
await update_price.send(await util_get_buff_price(str(event.get_message())))
|
await update_price.send(await util_get_buff_price(arg.extract_plain_text().strip()))
|
||||||
|
|
||||||
|
|
||||||
update_img = on_command("更新开箱图片", priority=1, permission=SUPERUSER, block=True)
|
update_img = on_command("更新开箱图片", priority=1, permission=SUPERUSER, block=True)
|
||||||
|
|
||||||
|
|
||||||
@update_img.handle()
|
@update_img.handle()
|
||||||
async def _(event: MessageEvent):
|
async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||||
await update_img.send(await util_get_buff_img(str(event.get_message())))
|
await update_img.send(await util_get_buff_img(str(arg.extract_plain_text().strip())))
|
||||||
|
|
||||||
|
|
||||||
# 重置开箱
|
# 重置开箱
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from nonebot import on_command
|
from nonebot import on_command
|
||||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
|
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from utils.utils import is_number
|
|
||||||
|
from configs.config import Config
|
||||||
|
from utils.utils import is_number, change_pixiv_image_links
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from asyncio.exceptions import TimeoutError
|
from asyncio.exceptions import TimeoutError
|
||||||
@@ -31,8 +33,6 @@ __plugin_settings__ = {
|
|||||||
|
|
||||||
pid_search = on_command("p搜", aliases={"pixiv搜", "P搜"}, priority=5, block=True)
|
pid_search = on_command("p搜", aliases={"pixiv搜", "P搜"}, priority=5, block=True)
|
||||||
|
|
||||||
url = "https://api.obfs.dev/api/pixiv/"
|
|
||||||
|
|
||||||
|
|
||||||
@pid_search.handle()
|
@pid_search.handle()
|
||||||
async def _h(event: MessageEvent, state: T_State, arg: Message = CommandArg()):
|
async def _h(event: MessageEvent, state: T_State, arg: Message = CommandArg()):
|
||||||
@@ -50,6 +50,7 @@ headers = {
|
|||||||
|
|
||||||
@pid_search.got("pid", prompt="需要查询的图片PID是?")
|
@pid_search.got("pid", prompt="需要查询的图片PID是?")
|
||||||
async def _g(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
|
async def _g(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
|
||||||
|
url = Config.get_config("hibiapi", "HIBIAPI") + "/api/pixiv/"
|
||||||
if pid in ["取消", "算了"]:
|
if pid in ["取消", "算了"]:
|
||||||
await pid_search.finish("已取消操作...")
|
await pid_search.finish("已取消操作...")
|
||||||
if not is_number(pid):
|
if not is_number(pid):
|
||||||
@@ -84,6 +85,7 @@ async def _g(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
|
|||||||
for image_url in data["meta_pages"]:
|
for image_url in data["meta_pages"]:
|
||||||
image_list.append(image_url["image_urls"]["original"])
|
image_list.append(image_url["image_urls"]["original"])
|
||||||
for i, img_url in enumerate(image_list):
|
for i, img_url in enumerate(image_list):
|
||||||
|
img_url = change_pixiv_image_links(img_url)
|
||||||
if not await AsyncHttpx.download_file(
|
if not await AsyncHttpx.download_file(
|
||||||
img_url,
|
img_url,
|
||||||
IMAGE_PATH / "temp" / f"pid_search_{event.user_id}_{i}.png",
|
IMAGE_PATH / "temp" / f"pid_search_{event.user_id}_{i}.png",
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ try:
|
|||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
if str(platform.system()).lower() == "windows":
|
# if str(platform.system()).lower() == "windows":
|
||||||
policy = asyncio.WindowsSelectorEventLoopPolicy()
|
# policy = asyncio.WindowsSelectorEventLoopPolicy()
|
||||||
asyncio.set_event_loop_policy(policy)
|
# asyncio.set_event_loop_policy(policy)
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
|
||||||
|
|||||||
@@ -139,15 +139,14 @@ class OmegaPixivIllusts(db.Model):
|
|||||||
data = await cls.select('pid').gino.all()
|
data = await cls.select('pid').gino.all()
|
||||||
return [x[0] for x in data]
|
return [x[0] for x in data]
|
||||||
|
|
||||||
@classmethod
|
# async def test(cls, nsfw_tag: int = 1):
|
||||||
async def test(cls, nsfw_tag: int = 1):
|
# if nsfw_tag is not None:
|
||||||
if nsfw_tag is not None:
|
# query = cls.query.where(cls.nsfw_tag == nsfw_tag)
|
||||||
query = cls.query.where(cls.nsfw_tag == nsfw_tag)
|
# else:
|
||||||
else:
|
# query = cls.query
|
||||||
query = cls.query
|
# query = query.where((cls.width - cls.height) < 50)
|
||||||
query = query.where((cls.width - cls.height) < 50)
|
# for x in await query.gino.all():
|
||||||
for x in await query.gino.all():
|
# print(x.pid)
|
||||||
print(x.pid)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ usage:
|
|||||||
查看 pix 好康图库
|
查看 pix 好康图库
|
||||||
指令:
|
指令:
|
||||||
pix ?*[tags]: 通过 tag 获取相似图片,不含tag时随机抽取
|
pix ?*[tags]: 通过 tag 获取相似图片,不含tag时随机抽取
|
||||||
|
pid [uid]: 通过uid获取图片
|
||||||
pix pid[pid]: 查看图库中指定pid图片
|
pix pid[pid]: 查看图库中指定pid图片
|
||||||
""".strip()
|
""".strip()
|
||||||
__plugin_superuser_usage__ = """
|
__plugin_superuser_usage__ = """
|
||||||
@@ -49,7 +50,9 @@ __plugin_configs__ = {
|
|||||||
"value": None,
|
"value": None,
|
||||||
"help": "单次发送的图片数量达到指定值时转发为合并消息",
|
"help": "单次发送的图片数量达到指定值时转发为合并消息",
|
||||||
"default_value": None,
|
"default_value": None,
|
||||||
}
|
},
|
||||||
|
"ALLOW_GROUP_SETU": {"value": False, "help": "允许非超级用户使用-s参数", "default_value": False},
|
||||||
|
"ALLOW_GROUP_R18": {"value": False, "help": "允许非超级用户使用-r参数", "default_value": False},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,10 +83,13 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|||||||
nsfw_tag = 2
|
nsfw_tag = 2
|
||||||
else:
|
else:
|
||||||
nsfw_tag = 0
|
nsfw_tag = 0
|
||||||
if nsfw_tag != 0 and str(event.user_id) not in bot.config.superusers:
|
if str(event.user_id) not in bot.config.superusers:
|
||||||
await pix.finish("你不能看这些噢,这些都是是留给管理员看的...")
|
if (nsfw_tag == 1 and not Config.get_config("pix", "ALLOW_GROUP_SETU")) or (
|
||||||
if n := len(x) == 1 and is_number(x[0]):
|
nsfw_tag == 2 and not Config.get_config("pix", "ALLOW_GROUP_R18")
|
||||||
num = int(x[-1])
|
):
|
||||||
|
await pix.finish("你不能看这些噢,这些都是是留给管理员看的...")
|
||||||
|
if n := len(x) == 1 and is_number(x[0]) and int(x[0]) < 100:
|
||||||
|
num = int(x[0])
|
||||||
keyword = ""
|
keyword = ""
|
||||||
elif n > 1:
|
elif n > 1:
|
||||||
if is_number(x[-1]):
|
if is_number(x[-1]):
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ usage:
|
|||||||
搜图 樱岛麻衣
|
搜图 樱岛麻衣
|
||||||
搜图 樱岛麻衣 5
|
搜图 樱岛麻衣 5
|
||||||
搜图 樱岛麻衣 5 r18
|
搜图 樱岛麻衣 5 r18
|
||||||
|
搜图 樱岛麻衣#1000users 5
|
||||||
|
【多个关键词用#分割】
|
||||||
【默认为 热度排序】
|
【默认为 热度排序】
|
||||||
【注意空格!!】【在线搜索会较慢】【数量可能不符?可能该页数量不够,也可能被R-18屏蔽】
|
【注意空格!!】【在线搜索会较慢】【数量可能不符?可能该页数量不够,也可能被R-18屏蔽】
|
||||||
""".strip()
|
""".strip()
|
||||||
@@ -161,8 +163,8 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|||||||
info_list = None
|
info_list = None
|
||||||
num = 10
|
num = 10
|
||||||
page = 1
|
page = 1
|
||||||
if (n := len(msg)) == 1:
|
if (n := len(msg)) > 0:
|
||||||
keyword = msg[0]
|
keyword = msg[0].replace("#"," ")
|
||||||
if n > 1:
|
if n > 1:
|
||||||
if not is_number(msg[1]):
|
if not is_number(msg[1]):
|
||||||
await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
|
await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ from services.log import logger
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
if platform.system() == "Windows":
|
# if platform.system() == "Windows":
|
||||||
import asyncio
|
# import asyncio
|
||||||
|
#
|
||||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||||
|
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ __plugin_configs__ = {
|
|||||||
},
|
},
|
||||||
"TIMEOUT": {"value": 10, "help": "色图下载超时限制(秒)", "default_value": 10},
|
"TIMEOUT": {"value": 10, "help": "色图下载超时限制(秒)", "default_value": 10},
|
||||||
"SHOW_INFO": {"value": True, "help": "是否显示色图的基本信息,如PID等", "default_value": True},
|
"SHOW_INFO": {"value": True, "help": "是否显示色图的基本信息,如PID等", "default_value": True},
|
||||||
|
"ALLOW_GROUP_R18": {"value": False, "help": "在群聊中启用R18权限", "default_value": False},
|
||||||
}
|
}
|
||||||
Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pixiv.re", help_="Pixiv反向代理")
|
Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pixiv.re", help_="Pixiv反向代理")
|
||||||
|
|
||||||
@@ -148,10 +149,16 @@ async def _(
|
|||||||
if cmd[0] == "色图r" and isinstance(event, PrivateMessageEvent):
|
if cmd[0] == "色图r" and isinstance(event, PrivateMessageEvent):
|
||||||
r18 = 1
|
r18 = 1
|
||||||
num = 10
|
num = 10
|
||||||
elif cmd[0] == "色图r" and isinstance(event, GroupMessageEvent):
|
elif (
|
||||||
await setu.finish(
|
cmd[0] == "色图r"
|
||||||
random.choice(["这种不好意思的东西怎么可能给这么多人看啦", "羞羞脸!给我滚出克私聊!", "变态变态变态变态大变态!"])
|
and isinstance(event, GroupMessageEvent)
|
||||||
)
|
):
|
||||||
|
if not Config.get_config("send_setu", "ALLOW_GROUP_R18"):
|
||||||
|
await setu.finish(
|
||||||
|
random.choice(["这种不好意思的东西怎么可能给这么多人看啦", "羞羞脸!给我滚出克私聊!", "变态变态变态变态大变态!"])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
r18 = 1
|
||||||
# 有 数字 的话先尝试本地色图id
|
# 有 数字 的话先尝试本地色图id
|
||||||
if msg and is_number(msg):
|
if msg and is_number(msg):
|
||||||
setu_list, code = await get_setu_list(int(msg), r18=r18)
|
setu_list, code = await get_setu_list(int(msg), r18=r18)
|
||||||
|
|||||||
+17
-21
@@ -24,6 +24,8 @@ from io import BytesIO
|
|||||||
import asyncio
|
import asyncio
|
||||||
import random
|
import random
|
||||||
import nonebot
|
import nonebot
|
||||||
|
import time
|
||||||
|
import locale
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
@@ -55,13 +57,10 @@ async def get_card(
|
|||||||
date = datetime.now().date()
|
date = datetime.now().date()
|
||||||
_type = "view" if is_card_view else "sign"
|
_type = "view" if is_card_view else "sign"
|
||||||
card_file = (
|
card_file = (
|
||||||
Path(SIGN_TODAY_CARD_PATH)
|
Path(SIGN_TODAY_CARD_PATH) / f"{user_id}_{user.group_id}_{_type}_{date}.png"
|
||||||
/ f"{user_id}_{user.group_id}_{_type}_{date}.png"
|
|
||||||
)
|
)
|
||||||
if card_file.exists():
|
if card_file.exists():
|
||||||
return image(
|
return image(f"{user_id}_{user.group_id}_{_type}_{date}.png", "sign/today_card")
|
||||||
f"{user_id}_{user.group_id}_{_type}_{date}.png", "sign/today_card"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if add_impression == -1:
|
if add_impression == -1:
|
||||||
card_file = (
|
card_file = (
|
||||||
@@ -75,9 +74,7 @@ async def get_card(
|
|||||||
)
|
)
|
||||||
is_card_view = True
|
is_card_view = True
|
||||||
ava = BytesIO(await get_user_avatar(user_id))
|
ava = BytesIO(await get_user_avatar(user_id))
|
||||||
uid = await GroupInfoUser.get_group_member_uid(
|
uid = await GroupInfoUser.get_group_member_uid(user.user_qq, user.group_id)
|
||||||
user.user_qq, user.group_id
|
|
||||||
)
|
|
||||||
impression_list = None
|
impression_list = None
|
||||||
if is_card_view:
|
if is_card_view:
|
||||||
_, impression_list, _ = await SignGroupUser.get_all_impression(
|
_, impression_list, _ = await SignGroupUser.get_all_impression(
|
||||||
@@ -128,9 +125,13 @@ def _generate_card(
|
|||||||
level, next_impression, previous_impression = get_level_and_next_impression(
|
level, next_impression, previous_impression = get_level_and_next_impression(
|
||||||
user.impression
|
user.impression
|
||||||
)
|
)
|
||||||
|
interpolation = next_impression - user.impression
|
||||||
|
if level == "9":
|
||||||
|
level = "8"
|
||||||
|
interpolation = 0
|
||||||
info_img.text((0, 0), f"· 好感度等级:{level} [{lik2relation[level]}]")
|
info_img.text((0, 0), f"· 好感度等级:{level} [{lik2relation[level]}]")
|
||||||
info_img.text((0, 20), f"· {NICKNAME}对你的态度:{level2attitude[level]}")
|
info_img.text((0, 20), f"· {NICKNAME}对你的态度:{level2attitude[level]}")
|
||||||
info_img.text((0, 40), f"· 距离升级还差 {next_impression - user.impression:.2f} 好感度")
|
info_img.text((0, 40), f"· 距离升级还差 {interpolation:.2f} 好感度")
|
||||||
|
|
||||||
bar_bk = BuildImage(220, 20, background=SIGN_RESOURCE_PATH / "bar_white.png")
|
bar_bk = BuildImage(220, 20, background=SIGN_RESOURCE_PATH / "bar_white.png")
|
||||||
bar = BuildImage(220, 20, background=SIGN_RESOURCE_PATH / "bar.png")
|
bar = BuildImage(220, 20, background=SIGN_RESOURCE_PATH / "bar.png")
|
||||||
@@ -240,7 +241,9 @@ def _generate_card(
|
|||||||
f"上次签到日期:{'从未' if user.checkin_time_last == datetime.min else user.checkin_time_last.date()}",
|
f"上次签到日期:{'从未' if user.checkin_time_last == datetime.min else user.checkin_time_last.date()}",
|
||||||
)
|
)
|
||||||
today_data.text((0, 25), f"总金币:{gold}")
|
today_data.text((0, 25), f"总金币:{gold}")
|
||||||
default_setu_prob = Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
|
default_setu_prob = (
|
||||||
|
Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
|
||||||
|
)
|
||||||
today_data.text(
|
today_data.text(
|
||||||
(0, 50),
|
(0, 50),
|
||||||
f"色图概率:{(default_setu_prob + user.impression if user.impression < 100 else 100):.2f}%",
|
f"色图概率:{(default_setu_prob + user.impression if user.impression < 100 else 100):.2f}%",
|
||||||
@@ -259,15 +262,12 @@ def _generate_card(
|
|||||||
today_data.text((0, 25), f"金币 + {gold}")
|
today_data.text((0, 25), f"金币 + {gold}")
|
||||||
_type = "sign"
|
_type = "sign"
|
||||||
current_date = datetime.now()
|
current_date = datetime.now()
|
||||||
week = current_date.isoweekday()
|
current_datetime_str = current_date.strftime("%Y-%m-%d %a %H:%M:%S")
|
||||||
data = current_date.date()
|
data = current_date.date()
|
||||||
hour = current_date.hour
|
|
||||||
minute = current_date.minute
|
|
||||||
second = current_date.second
|
|
||||||
data_img = BuildImage(
|
data_img = BuildImage(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
plain_text=f"时间:{data} {weekdays[week]} {hour}:{minute}:{second}",
|
plain_text=f"时间:{current_datetime_str}",
|
||||||
color=(255, 255, 255, 0),
|
color=(255, 255, 255, 0),
|
||||||
font_size=20,
|
font_size=20,
|
||||||
)
|
)
|
||||||
@@ -286,12 +286,8 @@ def _generate_card(
|
|||||||
bk.paste(today_sign_text_img, (550, 180), True)
|
bk.paste(today_sign_text_img, (550, 180), True)
|
||||||
bk.paste(today_data, (580, 220), True)
|
bk.paste(today_data, (580, 220), True)
|
||||||
bk.paste(watermark, (15, 400), True)
|
bk.paste(watermark, (15, 400), True)
|
||||||
bk.save(
|
bk.save(SIGN_TODAY_CARD_PATH / f"{user_id}_{user.group_id}_{_type}_{data}.png")
|
||||||
SIGN_TODAY_CARD_PATH / f"{user_id}_{user.group_id}_{_type}_{data}.png"
|
return image(f"{user_id}_{user.group_id}_{_type}_{data}.png", "sign/today_card")
|
||||||
)
|
|
||||||
return image(
|
|
||||||
f"{user_id}_{user.group_id}_{_type}_{data}.png", "sign/today_card"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def generate_progress_bar_pic():
|
def generate_progress_bar_pic():
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import asyncio
|
|||||||
import platform
|
import platform
|
||||||
import os
|
import os
|
||||||
|
|
||||||
if platform.system() == "Windows":
|
# if platform.system() == "Windows":
|
||||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||||
|
|
||||||
|
|
||||||
url = "https://github.com/Mrs4s/go-cqhttp/releases"
|
url = "https://github.com/Mrs4s/go-cqhttp/releases"
|
||||||
|
|||||||
Executable → Regular
+19
-11
@@ -2,12 +2,12 @@ from nonebot import on_command
|
|||||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
|
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
|
||||||
from nonebot.params import CommandArg
|
from nonebot.params import CommandArg
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from ._data_source import get_data, gen_wbtop_pic
|
from .data_source import gen_wbtop_pic,get_wbtop
|
||||||
from utils.utils import is_number
|
from utils.utils import is_number
|
||||||
from configs.path_config import IMAGE_PATH
|
from configs.path_config import IMAGE_PATH
|
||||||
from utils.http_utils import AsyncPlaywright
|
from utils.http_utils import AsyncPlaywright
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import datetime
|
||||||
__zx_plugin_name__ = "微博热搜"
|
__zx_plugin_name__ = "微博热搜"
|
||||||
__plugin_usage__ = """
|
__plugin_usage__ = """
|
||||||
usage:
|
usage:
|
||||||
@@ -19,8 +19,8 @@ usage:
|
|||||||
""".strip()
|
""".strip()
|
||||||
__plugin_des__ = "刚买完瓜,在吃瓜现场"
|
__plugin_des__ = "刚买完瓜,在吃瓜现场"
|
||||||
__plugin_cmd__ = ["微博热搜", "微博热搜 [id]"]
|
__plugin_cmd__ = ["微博热搜", "微博热搜 [id]"]
|
||||||
__plugin_version__ = 0.1
|
__plugin_version__ = 0.2
|
||||||
__plugin_author__ = "HibiKier"
|
__plugin_author__ = "HibiKier & yajiwa"
|
||||||
__plugin_settings__ = {
|
__plugin_settings__ = {
|
||||||
"level": 5,
|
"level": 5,
|
||||||
"default_status": True,
|
"default_status": True,
|
||||||
@@ -31,7 +31,7 @@ __plugin_settings__ = {
|
|||||||
wbtop = on_command("wbtop", aliases={"微博热搜"}, priority=5, block=True)
|
wbtop = on_command("wbtop", aliases={"微博热搜"}, priority=5, block=True)
|
||||||
|
|
||||||
|
|
||||||
wbtop_url = "https://v2.alapi.cn/api/new/wbtop"
|
wbtop_url = "https://weibo.com/ajax/side/hotSearch"
|
||||||
|
|
||||||
wbtop_data = []
|
wbtop_data = []
|
||||||
|
|
||||||
@@ -41,13 +41,21 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
|||||||
global wbtop_data
|
global wbtop_data
|
||||||
msg = arg.extract_plain_text().strip()
|
msg = arg.extract_plain_text().strip()
|
||||||
if not wbtop_data or not msg:
|
if not wbtop_data or not msg:
|
||||||
data, code = await get_data(wbtop_url)
|
if wbtop_data:
|
||||||
if code != 200:
|
now_time = datetime.datetime.now()
|
||||||
await wbtop.finish(data, at_sender=True)
|
if now_time > wbtop_data["time"] + datetime.timedelta(minutes=5):
|
||||||
wbtop_data = data["data"]
|
data, code = await get_wbtop(wbtop_url)
|
||||||
|
if code != 200:
|
||||||
|
await wbtop.finish(data, at_sender=True)
|
||||||
|
wbtop_data = data
|
||||||
|
else:
|
||||||
|
data, code = await get_wbtop(wbtop_url)
|
||||||
|
if code != 200:
|
||||||
|
await wbtop.finish(data, at_sender=True)
|
||||||
|
wbtop_data = data
|
||||||
if not msg:
|
if not msg:
|
||||||
img = await asyncio.get_event_loop().run_in_executor(
|
img = await asyncio.get_event_loop().run_in_executor(
|
||||||
None, gen_wbtop_pic, wbtop_data
|
None, gen_wbtop_pic, wbtop_data["data"]
|
||||||
)
|
)
|
||||||
await wbtop.send(img)
|
await wbtop.send(img)
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -55,7 +63,7 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
|||||||
f" 查询微博热搜"
|
f" 查询微博热搜"
|
||||||
)
|
)
|
||||||
if is_number(msg) and 0 < int(msg) <= 50:
|
if is_number(msg) and 0 < int(msg) <= 50:
|
||||||
url = wbtop_data[int(msg) - 1]["url"]
|
url = wbtop_data["data"][int(msg) - 1]["url"]
|
||||||
await wbtop.send("开始截取数据...")
|
await wbtop.send("开始截取数据...")
|
||||||
img = await AsyncPlaywright.screenshot(
|
img = await AsyncPlaywright.screenshot(
|
||||||
url,
|
url,
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||||
|
from utils.image_utils import BuildImage
|
||||||
|
from utils.message_builder import image
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from typing import Tuple, Union
|
||||||
|
from utils.http_utils import AsyncHttpx
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
async def get_wbtop(url: str) -> Tuple[Union[dict, str], int]:
|
||||||
|
"""
|
||||||
|
:param url: 请求链接
|
||||||
|
"""
|
||||||
|
n = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = []
|
||||||
|
get_response = (await AsyncHttpx.get(url, timeout=20))
|
||||||
|
if get_response.status_code == 200:
|
||||||
|
data_json = get_response.json()['data']['realtime']
|
||||||
|
for data_item in data_json:
|
||||||
|
# 如果是广告,则不添加
|
||||||
|
if 'is_ad' in data_item:
|
||||||
|
continue
|
||||||
|
dic = {
|
||||||
|
'hot_word': data_item['note'],
|
||||||
|
'hot_word_num': str(data_item['num']),
|
||||||
|
'url': 'https://s.weibo.com/weibo?q=%23' + data_item['word'] + '%23',
|
||||||
|
}
|
||||||
|
data.append(dic)
|
||||||
|
if not data:
|
||||||
|
return "没有搜索到...", 997
|
||||||
|
return {'data': data, 'time': datetime.datetime.now()}, 200
|
||||||
|
else:
|
||||||
|
if n > 2:
|
||||||
|
return f'获取失败,请十分钟后再试', 999
|
||||||
|
else:
|
||||||
|
n += 1
|
||||||
|
continue
|
||||||
|
except TimeoutError:
|
||||||
|
return "超时了....", 998
|
||||||
|
|
||||||
|
|
||||||
|
def gen_wbtop_pic(data: dict) -> MessageSegment:
|
||||||
|
"""
|
||||||
|
生成微博热搜图片
|
||||||
|
:param data: 微博热搜数据
|
||||||
|
"""
|
||||||
|
bk = BuildImage(700, 32 * 50 + 280, 700, 32, color="#797979")
|
||||||
|
wbtop_bk = BuildImage(700, 280, background=f"{IMAGE_PATH}/other/webtop.png")
|
||||||
|
bk.paste(wbtop_bk)
|
||||||
|
text_bk = BuildImage(700, 32 * 50, 700, 32, color="#797979")
|
||||||
|
for i, data in enumerate(data):
|
||||||
|
title = f"{i + 1}. {data['hot_word']}"
|
||||||
|
hot = data["hot_word_num"]
|
||||||
|
img = BuildImage(700, 30, font_size=20)
|
||||||
|
w, h = img.getsize(title)
|
||||||
|
img.text((10, int((30 - h) / 2)), title)
|
||||||
|
img.text((580, int((30 - h) / 2)), hot)
|
||||||
|
text_bk.paste(img)
|
||||||
|
bk.paste(text_bk, (0, 280))
|
||||||
|
return image(b64=bk.pic2bs4())
|
||||||
@@ -12,6 +12,7 @@ import numpy as np
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from configs.path_config import IMAGE_PATH, FONT_PATH
|
from configs.path_config import IMAGE_PATH, FONT_PATH
|
||||||
|
from services import logger
|
||||||
from utils.http_utils import AsyncHttpx
|
from utils.http_utils import AsyncHttpx
|
||||||
from models.chat_history import ChatHistory
|
from models.chat_history import ChatHistory
|
||||||
from configs.config import Config
|
from configs.config import Config
|
||||||
@@ -19,10 +20,11 @@ from configs.config import Config
|
|||||||
|
|
||||||
async def pre_precess(msg: List[str], config) -> str:
|
async def pre_precess(msg: List[str], config) -> str:
|
||||||
return await asyncio.get_event_loop().run_in_executor(
|
return await asyncio.get_event_loop().run_in_executor(
|
||||||
None, _pre_precess, msg,config)
|
None, _pre_precess, msg, config
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _pre_precess(msg: List[str],config) -> str:
|
def _pre_precess(msg: List[str], config) -> str:
|
||||||
"""对消息进行预处理"""
|
"""对消息进行预处理"""
|
||||||
# 过滤掉命令
|
# 过滤掉命令
|
||||||
command_start = tuple([i for i in config.command_start if i])
|
command_start = tuple([i for i in config.command_start if i])
|
||||||
@@ -46,7 +48,6 @@ def _pre_precess(msg: List[str],config) -> str:
|
|||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def draw_word_cloud(messages, config):
|
async def draw_word_cloud(messages, config):
|
||||||
wordcloud_dir = IMAGE_PATH / "wordcloud"
|
wordcloud_dir = IMAGE_PATH / "wordcloud"
|
||||||
wordcloud_dir.mkdir(exist_ok=True, parents=True)
|
wordcloud_dir.mkdir(exist_ok=True, parents=True)
|
||||||
@@ -57,19 +58,21 @@ async def draw_word_cloud(messages, config):
|
|||||||
url = "https://ghproxy.com/https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/resources/image/wordcloud/default.png"
|
url = "https://ghproxy.com/https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/resources/image/wordcloud/default.png"
|
||||||
try:
|
try:
|
||||||
await AsyncHttpx.download_file(url, zx_logo_path)
|
await AsyncHttpx.download_file(url, zx_logo_path)
|
||||||
except:
|
except Exception as e:
|
||||||
|
logger.error(f"词云图片资源下载发生错误 {type(e)}:{e}")
|
||||||
return False
|
return False
|
||||||
if not wordcloud_ttf.exists():
|
if not wordcloud_ttf.exists():
|
||||||
ttf_url = 'https://ghproxy.com/https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/resources/font/STKAITI.TTF'
|
ttf_url = "https://ghproxy.com/https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/resources/font/STKAITI.TTF"
|
||||||
try:
|
try:
|
||||||
await AsyncHttpx.download_file(ttf_url, wordcloud_ttf)
|
await AsyncHttpx.download_file(ttf_url, wordcloud_ttf)
|
||||||
except:
|
except Exception as e:
|
||||||
|
logger.error(f"词云字体资源下载发生错误 {type(e)}:{e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
topK = min(int(len(messages)), 100000)
|
topK = min(int(len(messages)), 100000)
|
||||||
read_name = jieba.analyse.extract_tags(await pre_precess(messages, config), topK=topK,
|
read_name = jieba.analyse.extract_tags(
|
||||||
withWeight=True,
|
await pre_precess(messages, config), topK=topK, withWeight=True, allowPOS=()
|
||||||
allowPOS=())
|
)
|
||||||
name = []
|
name = []
|
||||||
value = []
|
value = []
|
||||||
for t in read_name:
|
for t in read_name:
|
||||||
@@ -79,10 +82,11 @@ async def draw_word_cloud(messages, config):
|
|||||||
name[i] = str(name[i])
|
name[i] = str(name[i])
|
||||||
dic = dict(zip(name, value))
|
dic = dict(zip(name, value))
|
||||||
if Config.get_config("word_clouds", "WORD_CLOUDS_TEMPLATE") == 1:
|
if Config.get_config("word_clouds", "WORD_CLOUDS_TEMPLATE") == 1:
|
||||||
|
|
||||||
def random_pic(base_path: str) -> str:
|
def random_pic(base_path: str) -> str:
|
||||||
path_dir = os.listdir(base_path)
|
path_dir = os.listdir(base_path)
|
||||||
path = random.sample(path_dir, 1)[0]
|
path = random.sample(path_dir, 1)[0]
|
||||||
return (str(base_path) + "/" + str(path))
|
return str(base_path) + "/" + str(path)
|
||||||
|
|
||||||
mask = np.array(IMG.open(random_pic(wordcloud_dir)))
|
mask = np.array(IMG.open(random_pic(wordcloud_dir)))
|
||||||
wc = WordCloud(
|
wc = WordCloud(
|
||||||
@@ -113,7 +117,11 @@ async def draw_word_cloud(messages, config):
|
|||||||
|
|
||||||
|
|
||||||
async def get_list_msg(user_id, group_id, days):
|
async def get_list_msg(user_id, group_id, days):
|
||||||
messages_list = await ChatHistory()._get_msg(uid=user_id, gid=group_id, type_="group", days=days).gino.all()
|
messages_list = (
|
||||||
|
await ChatHistory()
|
||||||
|
._get_msg(uid=user_id, gid=group_id, type_="group", days=days)
|
||||||
|
.gino.all()
|
||||||
|
)
|
||||||
if messages_list:
|
if messages_list:
|
||||||
messages = [i.text for i in messages_list]
|
messages = [i.text for i in messages_list]
|
||||||
return messages
|
return messages
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ def fig2b64(plt_: plt) -> str:
|
|||||||
return "base64://" + base64_str
|
return "base64://" + base64_str
|
||||||
|
|
||||||
|
|
||||||
def is_valid(file: str) -> bool:
|
def is_valid(file: Union[str, Path]) -> bool:
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
判断图片是否损坏
|
判断图片是否损坏
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from pathlib import Path
|
|||||||
|
|
||||||
|
|
||||||
class NonePluginCountManager(StaticData):
|
class NonePluginCountManager(StaticData):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
插件加载容忍管理器,当连续 max_count 次插件加载,视为删除插件,清楚数据
|
插件加载容忍管理器,当连续 max_count 次插件加载,视为删除插件,清楚数据
|
||||||
"""
|
"""
|
||||||
@@ -15,6 +14,8 @@ class NonePluginCountManager(StaticData):
|
|||||||
:param max_count: 容忍最大次数
|
:param max_count: 容忍最大次数
|
||||||
"""
|
"""
|
||||||
super().__init__(file)
|
super().__init__(file)
|
||||||
|
if not self._data:
|
||||||
|
self._data = {}
|
||||||
self._max_count = max_count
|
self._max_count = max_count
|
||||||
|
|
||||||
def add_count(self, module: str, count: int = 1):
|
def add_count(self, module: str, count: int = 1):
|
||||||
@@ -42,10 +43,5 @@ class NonePluginCountManager(StaticData):
|
|||||||
:param module: 模块
|
:param module: 模块
|
||||||
"""
|
"""
|
||||||
if module in self._data.keys():
|
if module in self._data.keys():
|
||||||
return self._data.keys() > self._max_count
|
return self._data[module] >= self._max_count
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,18 +21,17 @@ class Plugins2blockManager(StaticData):
|
|||||||
with open(file, "r", encoding="utf8") as f:
|
with open(file, "r", encoding="utf8") as f:
|
||||||
self._data = yaml.load(f)
|
self._data = yaml.load(f)
|
||||||
if "PluginBlockLimit" in self._data.keys():
|
if "PluginBlockLimit" in self._data.keys():
|
||||||
self._data = (
|
self._data = self._data["PluginBlockLimit"] or {}
|
||||||
self._data["PluginBlockLimit"] if self._data["PluginBlockLimit"] else {}
|
|
||||||
)
|
|
||||||
|
|
||||||
def add_block_limit(
|
def add_block_limit(
|
||||||
self,
|
self,
|
||||||
plugin: str,
|
plugin: str,
|
||||||
|
*,
|
||||||
status: Optional[bool] = True,
|
status: Optional[bool] = True,
|
||||||
check_type: Optional[str] = "all",
|
check_type: Optional[str] = "all",
|
||||||
limit_type: Optional[str] = "user",
|
limit_type: Optional[str] = "user",
|
||||||
rst: Optional[str] = None,
|
rst: Optional[str] = None,
|
||||||
data_dict: Optional[dict] = None,
|
**kwargs # 用于接收额外实参
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
添加插件调用 block 限制
|
添加插件调用 block 限制
|
||||||
@@ -41,16 +40,10 @@ class Plugins2blockManager(StaticData):
|
|||||||
:param check_type: 检查类型 'private'/'group'/'all',限制私聊/群聊/全部
|
:param check_type: 检查类型 'private'/'group'/'all',限制私聊/群聊/全部
|
||||||
:param limit_type: 限制类型 监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
:param limit_type: 限制类型 监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
||||||
:param rst: 回复的话,为空则不回复
|
:param rst: 回复的话,为空则不回复
|
||||||
:param data_dict: 封装好的字典数据
|
|
||||||
"""
|
"""
|
||||||
if data_dict:
|
status = status or True
|
||||||
status = data_dict.get("status")
|
check_type = check_type or "all"
|
||||||
check_type = data_dict.get("check_type")
|
limit_type = limit_type or "user"
|
||||||
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"
|
|
||||||
if check_type not in ["all", "group", "private"]:
|
if check_type not in ["all", "group", "private"]:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"{plugin} 添加block限制错误,‘check_type‘ 必须为 'private'/'group'/'all'"
|
f"{plugin} 添加block限制错误,‘check_type‘ 必须为 'private'/'group'/'all'"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class Plugins2cdManager(StaticData):
|
|||||||
check_type: Optional[str] = "all",
|
check_type: Optional[str] = "all",
|
||||||
limit_type: Optional[str] = "user",
|
limit_type: Optional[str] = "user",
|
||||||
rst: Optional[str] = None,
|
rst: Optional[str] = None,
|
||||||
data_dict: Optional[dict] = None,
|
**kwargs # 用于接收额外实参
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
添加插件调用 cd 限制
|
添加插件调用 cd 限制
|
||||||
@@ -44,18 +44,11 @@ class Plugins2cdManager(StaticData):
|
|||||||
:param check_type: 检查类型 'private'/'group'/'all',限制私聊/群聊/全部
|
:param check_type: 检查类型 'private'/'group'/'all',限制私聊/群聊/全部
|
||||||
:param limit_type: 限制类型 监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
:param limit_type: 限制类型 监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
||||||
:param rst: 回复的话,为空则不回复
|
:param rst: 回复的话,为空则不回复
|
||||||
:param data_dict: 封装好的字典数据
|
|
||||||
"""
|
"""
|
||||||
if data_dict:
|
cd = cd or 5
|
||||||
cd = data_dict.get("cd")
|
status = status or True
|
||||||
status = data_dict.get("status")
|
check_type = check_type or "all"
|
||||||
check_type = data_dict.get("check_type")
|
limit_type = limit_type or "user"
|
||||||
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"
|
|
||||||
if check_type not in ["all", "group", "private"]:
|
if check_type not in ["all", "group", "private"]:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"{plugin} 添加cd限制错误,‘check_type‘ 必须为 'private'/'group'/'all'"
|
f"{plugin} 添加cd限制错误,‘check_type‘ 必须为 'private'/'group'/'all'"
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class Plugins2countManager(StaticData):
|
|||||||
status: Optional[bool] = True,
|
status: Optional[bool] = True,
|
||||||
limit_type: Optional[str] = "user",
|
limit_type: Optional[str] = "user",
|
||||||
rst: Optional[str] = None,
|
rst: Optional[str] = None,
|
||||||
data_dict: Optional[dict] = None,
|
**kwargs # 用于接收额外实参
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
添加插件调用 次数 限制
|
添加插件调用 次数 限制
|
||||||
@@ -42,16 +42,10 @@ class Plugins2countManager(StaticData):
|
|||||||
:param status: 默认开关状态
|
:param status: 默认开关状态
|
||||||
:param limit_type: 限制类型 监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
:param limit_type: 限制类型 监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
||||||
:param rst: 回复的话,为空则不回复
|
:param rst: 回复的话,为空则不回复
|
||||||
:param data_dict: 封装好的字典数据
|
|
||||||
"""
|
"""
|
||||||
if data_dict:
|
max_count = max_count or 5
|
||||||
max_count = data_dict.get("max_count")
|
status = status or True
|
||||||
status = data_dict.get("status")
|
limit_type = limit_type or "user"
|
||||||
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"]:
|
if limit_type not in ["user", "group"]:
|
||||||
raise ValueError(f"{plugin} 添加count限制错误,‘limit_type‘ 必须为 'user'/'group'")
|
raise ValueError(f"{plugin} 添加count限制错误,‘limit_type‘ 必须为 'user'/'group'")
|
||||||
self._data[plugin] = {
|
self._data[plugin] = {
|
||||||
|
|||||||
@@ -47,26 +47,17 @@ class Plugins2settingsManager(StaticData):
|
|||||||
:param plugin_type: 插件类型
|
:param plugin_type: 插件类型
|
||||||
:param cost_gold: 需要消费的金币
|
:param cost_gold: 需要消费的金币
|
||||||
"""
|
"""
|
||||||
if kwargs:
|
level = level or 5
|
||||||
level = kwargs.get("level") if kwargs.get("level") is not None else 5
|
cmd = cmd or []
|
||||||
default_status = (
|
cost_gold = cost_gold or 0
|
||||||
kwargs.get("default_status")
|
|
||||||
if kwargs.get("default_status") is not None
|
|
||||||
else True
|
|
||||||
)
|
|
||||||
limit_superuser = (
|
|
||||||
kwargs.get("limit_superuser")
|
|
||||||
if kwargs.get("limit_superuser") is not None
|
|
||||||
else False
|
|
||||||
)
|
|
||||||
cmd = kwargs.get("cmd") if kwargs.get("cmd") is not None else []
|
|
||||||
cost_gold = cost_gold if kwargs.get("cost_gold") else 0
|
|
||||||
self._data[plugin] = {
|
self._data[plugin] = {
|
||||||
"level": level if level is not None else 5,
|
"level": level if level is not None else 5,
|
||||||
"default_status": default_status if default_status is not None else True,
|
"default_status": default_status if default_status is not None else True,
|
||||||
"limit_superuser": limit_superuser
|
"limit_superuser": (
|
||||||
if limit_superuser is not None
|
limit_superuser
|
||||||
else False,
|
if limit_superuser is not None
|
||||||
|
else False
|
||||||
|
),
|
||||||
"cmd": cmd,
|
"cmd": cmd,
|
||||||
"plugin_type": list(
|
"plugin_type": list(
|
||||||
plugin_type if plugin_type is not None else ("normal",)
|
plugin_type if plugin_type is not None else ("normal",)
|
||||||
|
|||||||
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from nonebot import require
|
from nonebot import require
|
||||||
from configs.config import SYSTEM_PROXY
|
from configs.config import SYSTEM_PROXY, Config
|
||||||
from typing import List, Union, Optional, Type, Any
|
from typing import List, Union, Optional, Type, Any
|
||||||
from nonebot.adapters.onebot.v11 import Bot, Message
|
from nonebot.adapters.onebot.v11 import Bot, Message
|
||||||
from nonebot.matcher import matchers, Matcher
|
from nonebot.matcher import matchers, Matcher
|
||||||
@@ -389,6 +389,8 @@ def change_pixiv_image_links(
|
|||||||
url = img_sp[0]
|
url = img_sp[0]
|
||||||
img_type = img_sp[1]
|
img_type = img_sp[1]
|
||||||
url = url.replace("original", "master") + f"_master1200.{img_type}"
|
url = url.replace("original", "master") + f"_master1200.{img_type}"
|
||||||
|
if not nginx_url:
|
||||||
|
nginx_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
|
||||||
if nginx_url:
|
if nginx_url:
|
||||||
url = (
|
url = (
|
||||||
url.replace("i.pximg.net", nginx_url)
|
url.replace("i.pximg.net", nginx_url)
|
||||||
|
|||||||
Reference in New Issue
Block a user