mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 14:22:55 +08:00
update 0.0.6.2
This commit is contained in:
parent
c802dfda22
commit
3de487fb24
15
README.md
15
README.md
@ -100,6 +100,7 @@
|
||||
- [x] 移动图片 (同上)
|
||||
- [x] 删除图片 (同上)
|
||||
- [x] 群内B站订阅
|
||||
- [x] 群词条
|
||||
|
||||
### 已实现的超级用户功能
|
||||
- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
|
||||
@ -272,7 +273,7 @@
|
||||
|
||||
</details>
|
||||
|
||||
## 详细配置请前往文档,以下为最简部署和配置
|
||||
## 详细配置请前往文档,以下为最简部署和配置,如果你有基础并学习过nonebot2的话
|
||||
|
||||
|
||||
## 简单部署
|
||||
@ -320,6 +321,18 @@ python bot.py
|
||||
|
||||
## 更新
|
||||
|
||||
### 2021/11/23
|
||||
|
||||
* 替换cos API
|
||||
* 提供私聊b了,即跨群b了用户
|
||||
* 修复游戏抽卡导入角色失败(原神)
|
||||
* 修复无Pixiv代理时报错
|
||||
* 将项目中大部分aiohttp替换为httpx
|
||||
* 删除了丘丘人翻译插件
|
||||
* 新增群词条
|
||||
* 修复游戏抽卡碧蓝航线bwiki格式更改导致获取报错
|
||||
* 首次启动会生成配置文件后停止程序,配置后再次启动即可
|
||||
|
||||
### 2021/11/18
|
||||
|
||||
* 修复超级用户无法正确拉真寻入群
|
||||
|
||||
@ -1 +1 @@
|
||||
__version__: v0.0.6.1
|
||||
__version__: v0.0.6.2
|
||||
|
||||
0
basic_plugins/__init__.py
Normal file → Executable file
0
basic_plugins/__init__.py
Normal file → Executable file
2
basic_plugins/admin_bot_manage/__init__.py
Normal file → Executable file
2
basic_plugins/admin_bot_manage/__init__.py
Normal file → Executable file
@ -4,7 +4,7 @@ import nonebot
|
||||
|
||||
Config.add_plugin_config(
|
||||
"admin_bot_manage:custom_welcome_message",
|
||||
"SET_GROUP_WELCOME_MESSAGE_LEVEL",
|
||||
"SET_GROUP_WELCOME_MESSAGE_LEVEL [LEVEL]",
|
||||
2,
|
||||
name="群管理员操作",
|
||||
help_="设置群欢迎消息权限",
|
||||
|
||||
0
basic_plugins/admin_bot_manage/admin_config.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/admin_config.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/custom_welcome_message.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/custom_welcome_message.py
Normal file → Executable file
10
basic_plugins/admin_bot_manage/data_source.py
Normal file → Executable file
10
basic_plugins/admin_bot_manage/data_source.py
Normal file → Executable file
@ -12,8 +12,7 @@ from models.level_user import LevelUser
|
||||
from configs.config import Config
|
||||
from utils.manager import group_manager, plugins2settings_manager, plugins_manager
|
||||
from utils.image_utils import CreateImg
|
||||
import aiofiles
|
||||
import aiohttp
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import asyncio
|
||||
import time
|
||||
import os
|
||||
@ -73,12 +72,7 @@ async def custom_group_welcome(
|
||||
logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息 {msg}")
|
||||
result += msg
|
||||
if img:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(img, proxy=get_local_proxy()) as response:
|
||||
async with aiofiles.open(
|
||||
DATA_PATH + f"custom_welcome_msg/{group_id}.jpg", "wb"
|
||||
) as f:
|
||||
await f.write(await response.read())
|
||||
await AsyncHttpx.download_file(img, DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
|
||||
img_result = image(abspath=DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
|
||||
logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息图片")
|
||||
except Exception as e:
|
||||
|
||||
0
basic_plugins/admin_bot_manage/rule.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/rule.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/switch_rule.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/switch_rule.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/timing_task.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/timing_task.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/update_group_member_info.py
Normal file → Executable file
0
basic_plugins/admin_bot_manage/update_group_member_info.py
Normal file → Executable file
0
basic_plugins/admin_help/__init__.py
Normal file → Executable file
0
basic_plugins/admin_help/__init__.py
Normal file → Executable file
0
basic_plugins/admin_help/data_source.py
Normal file → Executable file
0
basic_plugins/admin_help/data_source.py
Normal file → Executable file
0
basic_plugins/apscheduler/__init__.py
Normal file → Executable file
0
basic_plugins/apscheduler/__init__.py
Normal file → Executable file
18
basic_plugins/ban/__init__.py
Normal file → Executable file
18
basic_plugins/ban/__init__.py
Normal file → Executable file
@ -3,7 +3,7 @@ from models.ban_user import BanUser
|
||||
from models.level_user import LevelUser
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.cqhttp import Bot
|
||||
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
|
||||
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent, MessageEvent
|
||||
from utils.utils import get_message_at, get_message_text, is_number
|
||||
from configs.config import NICKNAME, Config
|
||||
from nonebot.permission import SUPERUSER
|
||||
@ -24,10 +24,14 @@ usage:
|
||||
""".strip()
|
||||
__plugin_superuser_usage__ = """
|
||||
usage:
|
||||
屏蔽用户消息,相当于最上级.ban
|
||||
b了=屏蔽用户消息,相当于最上级.ban
|
||||
跨群ban以及跨群b了
|
||||
指令:
|
||||
b了 [at]
|
||||
b了 [at/qq]
|
||||
.ban [user_id] ?[小时] ?[分钟]
|
||||
示例:b了 @user
|
||||
示例:b了 1234567
|
||||
示例:.ban 12345567
|
||||
""".strip()
|
||||
__plugin_des__ = '你被逮捕了!丢进小黑屋!'
|
||||
__plugin_cmd__ = ['.ban [at] ?[小时] ?[分钟]', '.unban [at]', 'b了 [at] [_superuser]']
|
||||
@ -182,8 +186,14 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
||||
|
||||
|
||||
@super_ban.handle()
|
||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
qq = get_message_at(event.json())
|
||||
else:
|
||||
qq = get_message_text(event.json())
|
||||
if not is_number(qq):
|
||||
await super_ban.finish("对象qq必须为纯数字...")
|
||||
qq = [qq]
|
||||
if qq:
|
||||
qq = qq[0]
|
||||
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||
|
||||
0
basic_plugins/broadcast/__init__.py
Normal file → Executable file
0
basic_plugins/broadcast/__init__.py
Normal file → Executable file
12
basic_plugins/group_handle/__init__.py
Normal file → Executable file
12
basic_plugins/group_handle/__init__.py
Normal file → Executable file
@ -30,15 +30,15 @@ __plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_task__ = {"group_welcome": "进群欢迎", "refund_group_remind": "退群提醒"}
|
||||
Config.add_plugin_config(
|
||||
"auto_invite", "message", f"请不要未经同意就拉{NICKNAME}入群!告辞!", help_="强制拉群后进群回复的内容.."
|
||||
"invite_manager", "message", f"请不要未经同意就拉{NICKNAME}入群!告辞!", help_="强制拉群后进群回复的内容.."
|
||||
)
|
||||
Config.add_plugin_config(
|
||||
"auto_invite", "flag", True, help_="被强制拉群后是否直接退出", default_value=True
|
||||
"invite_manager", "flag", True, help_="被强制拉群后是否直接退出", default_value=True
|
||||
)
|
||||
Config.add_plugin_config(
|
||||
"auto_invite", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5
|
||||
"invite_manager", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5
|
||||
)
|
||||
_flmt = FreqLimiter(Config.get_config("auto_invite", "welcome_msg_cd"))
|
||||
_flmt = FreqLimiter(Config.get_config("invite_manager", "welcome_msg_cd"))
|
||||
|
||||
|
||||
# 群员增加处理
|
||||
@ -55,10 +55,10 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
|
||||
group = await GroupInfo.get_group_info(event.group_id)
|
||||
# 群聊不存在或被强制拉群,退出该群
|
||||
if (not group or group.group_flag == 0) and Config.get_config(
|
||||
"auto_invite", "flag"
|
||||
"invite_manager", "flag"
|
||||
):
|
||||
try:
|
||||
msg = Config.get_config("auto_invite", "message")
|
||||
msg = Config.get_config("invite_manager", "message")
|
||||
if msg:
|
||||
await bot.send_group_msg(group_id=event.group_id, message=msg)
|
||||
await bot.set_group_leave(group_id=event.group_id)
|
||||
|
||||
0
basic_plugins/help/__init__.py
Normal file → Executable file
0
basic_plugins/help/__init__.py
Normal file → Executable file
0
basic_plugins/help/data_source.py
Normal file → Executable file
0
basic_plugins/help/data_source.py
Normal file → Executable file
0
basic_plugins/hooks/__init__.py
Normal file → Executable file
0
basic_plugins/hooks/__init__.py
Normal file → Executable file
0
basic_plugins/hooks/auth_hook.py
Normal file → Executable file
0
basic_plugins/hooks/auth_hook.py
Normal file → Executable file
0
basic_plugins/hooks/ban_hook.py
Normal file → Executable file
0
basic_plugins/hooks/ban_hook.py
Normal file → Executable file
0
basic_plugins/hooks/chkdsk_hook.py
Normal file → Executable file
0
basic_plugins/hooks/chkdsk_hook.py
Normal file → Executable file
0
basic_plugins/hooks/limit_hook.py
Normal file → Executable file
0
basic_plugins/hooks/limit_hook.py
Normal file → Executable file
0
basic_plugins/hooks/other_hook.py
Normal file → Executable file
0
basic_plugins/hooks/other_hook.py
Normal file → Executable file
0
basic_plugins/hooks/utils.py
Normal file → Executable file
0
basic_plugins/hooks/utils.py
Normal file → Executable file
0
basic_plugins/hooks/withdraw_message_hook.py
Normal file → Executable file
0
basic_plugins/hooks/withdraw_message_hook.py
Normal file → Executable file
9
basic_plugins/init_plugin_config/__init__.py
Normal file → Executable file
9
basic_plugins/init_plugin_config/__init__.py
Normal file → Executable file
@ -9,10 +9,12 @@ from .init_plugins_limit import (
|
||||
init_plugins_count_limit,
|
||||
init_plugins_cd_limit,
|
||||
)
|
||||
from .init import init
|
||||
from .check_plugin_status import check_plugin_status
|
||||
from nonebot.adapters.cqhttp import Bot
|
||||
from configs.path_config import DATA_PATH
|
||||
from services.log import logger
|
||||
from pathlib import Path
|
||||
from nonebot import Driver
|
||||
import nonebot
|
||||
|
||||
@ -30,6 +32,11 @@ def _():
|
||||
"""
|
||||
初始化数据
|
||||
"""
|
||||
_flag = False
|
||||
config_file = Path(DATA_PATH) / "configs" / "plugins2config.yaml"
|
||||
if not config_file.exists():
|
||||
_flag = True
|
||||
init()
|
||||
init_plugins_settings(DATA_PATH)
|
||||
init_plugins_cd_limit(DATA_PATH)
|
||||
init_plugins_block_limit(DATA_PATH)
|
||||
@ -42,6 +49,8 @@ def _():
|
||||
if x:
|
||||
for key in x.keys():
|
||||
plugins_manager.block_plugin(key, block_type=x[key])
|
||||
if _flag:
|
||||
raise Exception("首次运行,已在configs目录下生成配置文件config.yaml,修改后重启即可...")
|
||||
logger.info("初始化数据完成...")
|
||||
|
||||
|
||||
|
||||
0
basic_plugins/init_plugin_config/check_plugin_status.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/check_plugin_status.py
Normal file → Executable file
14
basic_plugins/init_plugin_config/init.py
Normal file
14
basic_plugins/init_plugin_config/init.py
Normal file
@ -0,0 +1,14 @@
|
||||
from utils.manager import plugins2settings_manager
|
||||
|
||||
|
||||
def init():
|
||||
if plugins2settings_manager.get("update_pic"):
|
||||
plugins2settings_manager["update_picture"] = plugins2settings_manager["update_pic"]
|
||||
plugins2settings_manager.delete("update_pic")
|
||||
if plugins2settings_manager.get("white2black_img"):
|
||||
plugins2settings_manager["white2black_image"] = plugins2settings_manager["white2black_img"]
|
||||
plugins2settings_manager.delete("white2black_img")
|
||||
if plugins2settings_manager.get("send_img"):
|
||||
plugins2settings_manager["send_image"] = plugins2settings_manager["send_img"]
|
||||
plugins2settings_manager.delete("send_img")
|
||||
|
||||
0
basic_plugins/init_plugin_config/init_group_manager.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_group_manager.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_none_plugin_count_manager.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_none_plugin_count_manager.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_config.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_config.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_data.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_data.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_limit.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_limit.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_resources.py
Normal file → Executable file
0
basic_plugins/init_plugin_config/init_plugins_resources.py
Normal file → Executable file
28
basic_plugins/init_plugin_config/init_plugins_settings.py
Normal file → Executable file
28
basic_plugins/init_plugin_config/init_plugins_settings.py
Normal file → Executable file
@ -17,23 +17,19 @@ def init_plugins_settings(data_path: str):
|
||||
plugins2settings_file = Path(data_path) / "configs" / "plugins2settings.yaml"
|
||||
plugins2settings_file.parent.mkdir(exist_ok=True, parents=True)
|
||||
_matchers = get_matchers()
|
||||
_data = {}
|
||||
if plugins2settings_file.exists():
|
||||
with open(plugins2settings_file, "r", encoding="utf8") as f:
|
||||
_data = _yaml.load(f)
|
||||
_data = _data["PluginSettings"] if _data else {}
|
||||
_tmp_module = {}
|
||||
_tmp = []
|
||||
for x in plugins2settings_manager.keys():
|
||||
try:
|
||||
_plugin = nonebot.plugin.get_plugin(x)
|
||||
_module = _plugin.module
|
||||
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||
_tmp_module[x] = plugin_name
|
||||
except (KeyError, AttributeError) as e:
|
||||
logger.error(f"配置文件 模块:{x} 获取 plugin_name 失败...{e}")
|
||||
_tmp_module[x] = ""
|
||||
for matcher in _matchers:
|
||||
if matcher.module in _data.keys():
|
||||
plugins2settings_manager.add_plugin_settings(
|
||||
matcher.module,
|
||||
plugin_type=_data[matcher.module]["plugin_type"],
|
||||
data_dict=_data[matcher.module],
|
||||
)
|
||||
if _data[matcher.module]["cmd"]:
|
||||
_tmp_module[matcher.module] = _data[matcher.module]["cmd"][0]
|
||||
else:
|
||||
if matcher.module not in plugins2settings_manager.keys():
|
||||
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||
try:
|
||||
_module = _plugin.module
|
||||
@ -52,7 +48,7 @@ def init_plugins_settings(data_path: str):
|
||||
except (AttributeError, KeyError):
|
||||
level = 5
|
||||
cmd = None
|
||||
if not level:
|
||||
if level is None:
|
||||
level = 5
|
||||
admin_manager.add_admin_plugin_settings(
|
||||
matcher.module, cmd, level
|
||||
@ -76,7 +72,7 @@ def init_plugins_settings(data_path: str):
|
||||
"__plugin_settings__"
|
||||
)
|
||||
if (
|
||||
plugin_settings["cmd"]
|
||||
plugin_settings["cmd"] is not None
|
||||
and plugin_name not in plugin_settings["cmd"]
|
||||
):
|
||||
plugin_settings["cmd"].append(plugin_name)
|
||||
|
||||
4
basic_plugins/auto_invite/__init__.py → basic_plugins/invite_manager/__init__.py
Normal file → Executable file
4
basic_plugins/auto_invite/__init__.py → basic_plugins/invite_manager/__init__.py
Normal file → Executable file
@ -46,11 +46,11 @@ async def _(bot: Bot, event: FriendRequestEvent, state: dict):
|
||||
user_id=int(list(bot.config.superusers)[0]),
|
||||
message=f"*****一份好友申请*****\n"
|
||||
f"昵称:{nickname}({event.user_id})\n"
|
||||
f"自动同意:{'√' if Config.get_config('auto_invite', 'AUTO_ADD_FRIEND') else '×'}\n"
|
||||
f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
|
||||
f"日期:{str(datetime.now()).split('.')[0]}\n"
|
||||
f"备注:{event.comment}",
|
||||
)
|
||||
if Config.get_config("auto_invite", "AUTO_ADD_FRIEND"):
|
||||
if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
|
||||
await bot.set_friend_add_request(flag=event.flag, approve=True)
|
||||
await FriendUser.add_friend_info(user["user_id"], user["nickname"])
|
||||
else:
|
||||
0
basic_plugins/nickname.py
Normal file → Executable file
0
basic_plugins/nickname.py
Normal file → Executable file
40
basic_plugins/scripts.py
Normal file → Executable file
40
basic_plugins/scripts.py
Normal file → Executable file
@ -3,12 +3,11 @@ from services.db_context import db
|
||||
from asyncpg.exceptions import DuplicateColumnError
|
||||
from models.group_info import GroupInfo
|
||||
from nonebot.adapters.cqhttp import Bot
|
||||
from utils.user_agent import get_user_agent
|
||||
from services.log import logger
|
||||
from configs.path_config import TEXT_PATH
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from pathlib import Path
|
||||
import aiohttp
|
||||
import nonebot
|
||||
|
||||
try:
|
||||
@ -25,30 +24,34 @@ async def update_city():
|
||||
"""
|
||||
部分插件需要中国省份城市
|
||||
这里直接更新,避免插件内代码重复
|
||||
:return:
|
||||
"""
|
||||
china_city = Path(TEXT_PATH) / "china_city.json"
|
||||
data = {}
|
||||
try:
|
||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||
async with session.get(
|
||||
res = await AsyncHttpx.get(
|
||||
"http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
|
||||
) as res:
|
||||
provinces_data = json.loads(await res.text(encoding="utf8"))
|
||||
)
|
||||
res.encoding = "utf8"
|
||||
provinces_data = json.loads(res.text)
|
||||
for province in provinces_data.keys():
|
||||
data[provinces_data[province]] = []
|
||||
async with session.get(
|
||||
res = await AsyncHttpx.get(
|
||||
f"http://www.weather.com.cn/data/city3jdata/provshi/{province}.html",
|
||||
timeout=5,
|
||||
) as res:
|
||||
city_data = json.loads(await res.text(encoding="utf8"))
|
||||
)
|
||||
res.encoding = "utf8"
|
||||
city_data = json.loads(res.text)
|
||||
for city in city_data.keys():
|
||||
data[provinces_data[province]].append(city_data[city])
|
||||
with open(china_city, "w", encoding="utf8") as f:
|
||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||
logger.info("自动更新城市列表完成.....")
|
||||
except TimeoutError:
|
||||
logger.info("自动更新城市列表超时.....")
|
||||
logger.warning("自动更新城市列表超时.....")
|
||||
except ValueError:
|
||||
logger.warning("自动城市列表失败.....")
|
||||
except Exception as e:
|
||||
logger.error(f"自动城市列表未知错误 {type(e)}:{e}")
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
@ -75,13 +78,7 @@ async def _(bot: Bot):
|
||||
# 清空不存在的群聊信息,并将已所有已存在的群聊group_flag设置为1(认证所有已存在的群)
|
||||
if not await GroupInfo.get_group_info(114514):
|
||||
# 标识符,该功能只需执行一次
|
||||
await GroupInfo.add_group_info(
|
||||
114514,
|
||||
"114514",
|
||||
114514,
|
||||
114514,
|
||||
1
|
||||
)
|
||||
await GroupInfo.add_group_info(114514, "114514", 114514, 114514, 1)
|
||||
group_list = await bot.get_group_list()
|
||||
group_list = [g["group_id"] for g in group_list]
|
||||
_gl = [x.group_id for x in await GroupInfo.get_all_group()]
|
||||
@ -98,14 +95,9 @@ async def _(bot: Bot):
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1
|
||||
1,
|
||||
)
|
||||
logger.info(f"已将群聊 {group_id} 添加认证...")
|
||||
else:
|
||||
await GroupInfo.delete_group_info(group_id)
|
||||
logger.info(f"移除不存在的群聊信息:{group_id}")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
0
basic_plugins/super_cmd/__init__.py
Normal file → Executable file
0
basic_plugins/super_cmd/__init__.py
Normal file → Executable file
0
basic_plugins/super_cmd/bot_friend_group.py
Normal file → Executable file
0
basic_plugins/super_cmd/bot_friend_group.py
Normal file → Executable file
0
basic_plugins/super_cmd/clear_data.py
Normal file → Executable file
0
basic_plugins/super_cmd/clear_data.py
Normal file → Executable file
0
basic_plugins/super_cmd/data_source.py
Normal file → Executable file
0
basic_plugins/super_cmd/data_source.py
Normal file → Executable file
0
basic_plugins/super_cmd/manager_group.py
Normal file → Executable file
0
basic_plugins/super_cmd/manager_group.py
Normal file → Executable file
0
basic_plugins/super_cmd/reload_setting.py
Normal file → Executable file
0
basic_plugins/super_cmd/reload_setting.py
Normal file → Executable file
0
basic_plugins/super_cmd/set_admin_permissions.py
Normal file → Executable file
0
basic_plugins/super_cmd/set_admin_permissions.py
Normal file → Executable file
0
basic_plugins/super_cmd/super_task_switch.py
Normal file → Executable file
0
basic_plugins/super_cmd/super_task_switch.py
Normal file → Executable file
0
basic_plugins/super_cmd/update_friend_group_info.py
Normal file → Executable file
0
basic_plugins/super_cmd/update_friend_group_info.py
Normal file → Executable file
0
basic_plugins/super_help/__init__.py
Normal file → Executable file
0
basic_plugins/super_help/__init__.py
Normal file → Executable file
0
basic_plugins/super_help/data_source.py
Normal file → Executable file
0
basic_plugins/super_help/data_source.py
Normal file → Executable file
0
basic_plugins/update_info.py
Normal file → Executable file
0
basic_plugins/update_info.py
Normal file → Executable file
0
models/bag_user.py
Normal file → Executable file
0
models/bag_user.py
Normal file → Executable file
2
models/ban_user.py
Normal file → Executable file
2
models/ban_user.py
Normal file → Executable file
@ -82,7 +82,7 @@ class BanUser(db.Model):
|
||||
参数:
|
||||
:param user_qq: 目标用户qq号
|
||||
:param ban_level: 使用ban命令用户的权限
|
||||
:param duration: ban时长
|
||||
:param duration: ban时长,秒
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq))
|
||||
query = query.with_for_update()
|
||||
|
||||
0
models/friend_user.py
Normal file → Executable file
0
models/friend_user.py
Normal file → Executable file
0
models/group_info.py
Normal file → Executable file
0
models/group_info.py
Normal file → Executable file
0
models/group_member_info.py
Normal file → Executable file
0
models/group_member_info.py
Normal file → Executable file
0
models/level_user.py
Normal file → Executable file
0
models/level_user.py
Normal file → Executable file
0
models/sign_group_user.py
Normal file → Executable file
0
models/sign_group_user.py
Normal file → Executable file
0
plugins/__init__.py
Normal file → Executable file
0
plugins/__init__.py
Normal file → Executable file
0
plugins/aconfig/__init__.py
Normal file → Executable file
0
plugins/aconfig/__init__.py
Normal file → Executable file
2
plugins/ai/__init__.py
Normal file → Executable file
2
plugins/ai/__init__.py
Normal file → Executable file
@ -24,8 +24,6 @@ __plugin_version__ = 0.1
|
||||
__plugin_author__ = 'HibiKier'
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["Ai", "ai", "AI", "aI"],
|
||||
}
|
||||
__plugin_configs__ = {
|
||||
|
||||
48
plugins/ai/data_source.py
Normal file → Executable file
48
plugins/ai/data_source.py
Normal file → Executable file
@ -1,13 +1,12 @@
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
|
||||
import aiohttp
|
||||
from aiohttp.client import ClientSession
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.path_config import IMAGE_PATH, DATA_PATH
|
||||
from services.log import logger
|
||||
from utils.message_builder import image, face
|
||||
from configs.config import Config, NICKNAME
|
||||
from .utils import ai_message_manager
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@ -26,7 +25,7 @@ anime_data = json.load(open(DATA_PATH + "anime.json", "r", encoding="utf8"))
|
||||
|
||||
async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str) -> str:
|
||||
"""
|
||||
获取 AI 返回值,顺序:图灵 -> 青云客
|
||||
获取 AI 返回值,顺序: 特殊回复 -> 图灵 -> 青云客
|
||||
:param text: 问题
|
||||
:param img_url: 图片链接
|
||||
:param user_id: 用户id
|
||||
@ -34,6 +33,11 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
|
||||
:return: 回答
|
||||
"""
|
||||
global index
|
||||
ai_message_manager.add_message(user_id, text)
|
||||
special_rst = await ai_message_manager.get_result(user_id, nickname)
|
||||
if special_rst:
|
||||
ai_message_manager.add_result(user_id, special_rst)
|
||||
return special_rst
|
||||
if index == 5:
|
||||
index = 0
|
||||
if len(text) < 6 and random.random() < 0.6:
|
||||
@ -41,10 +45,9 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
|
||||
for key in keys:
|
||||
if text.find(key) != -1:
|
||||
return random.choice(anime_data[key]).replace("你", nickname)
|
||||
async with aiohttp.ClientSession() as sess:
|
||||
rst = await tu_ling(text, img_url, user_id, sess)
|
||||
rst = await tu_ling(text, img_url, user_id)
|
||||
if not rst:
|
||||
rst = await xie_ai(text, sess)
|
||||
rst = await xie_ai(text)
|
||||
if not rst:
|
||||
return no_result()
|
||||
if nickname:
|
||||
@ -55,23 +58,25 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
|
||||
if nickname.find("大人") == -1:
|
||||
nickname += "大~人~"
|
||||
rst = rst.replace("小主人", nickname).replace("小朋友", nickname)
|
||||
ai_message_manager.add_result(user_id, rst)
|
||||
print(ai_message_manager)
|
||||
return rst
|
||||
|
||||
|
||||
# 图灵接口
|
||||
async def tu_ling(text: str, img_url: str, user_id: int, sess: ClientSession) -> str:
|
||||
async def tu_ling(text: str, img_url: str, user_id: int) -> str:
|
||||
"""
|
||||
获取图灵接口的回复
|
||||
:param text: 问题
|
||||
:param img_url: 图片链接
|
||||
:param user_id: 用户id
|
||||
:param sess: AIOHTTP SESSION
|
||||
:return: 图灵回复
|
||||
"""
|
||||
global index
|
||||
TL_KEY = Config.get_config("ai", "TL_KEY")
|
||||
req = None
|
||||
if not TL_KEY:
|
||||
return ''
|
||||
return ""
|
||||
try:
|
||||
if text:
|
||||
req = {
|
||||
@ -98,10 +103,10 @@ async def tu_ling(text: str, img_url: str, user_id: int, sess: ClientSession) ->
|
||||
index = 0
|
||||
return ""
|
||||
text = ""
|
||||
async with sess.post(url, json=req) as response:
|
||||
if response.status != 200:
|
||||
response = await AsyncHttpx.post(url, json=req)
|
||||
if response.status_code != 200:
|
||||
return no_result()
|
||||
resp_payload = json.loads(await response.text())
|
||||
resp_payload = json.loads(response.text)
|
||||
if int(resp_payload["intent"]["code"]) in [4003]:
|
||||
return ""
|
||||
if resp_payload["results"]:
|
||||
@ -114,18 +119,15 @@ async def tu_ling(text: str, img_url: str, user_id: int, sess: ClientSession) ->
|
||||
|
||||
|
||||
# 屑 AI
|
||||
async def xie_ai(text: str, sess: ClientSession) -> str:
|
||||
async def xie_ai(text: str) -> str:
|
||||
"""
|
||||
获取青云客回复
|
||||
:param text: 问题
|
||||
:param sess: AIOHTTP SESSION
|
||||
:return: 青云可回复
|
||||
"""
|
||||
async with sess.get(
|
||||
f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}"
|
||||
) as res:
|
||||
res = await AsyncHttpx.get(f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}")
|
||||
content = ""
|
||||
data = json.loads(await res.text())
|
||||
data = json.loads(res.text)
|
||||
if data["result"] == 0:
|
||||
content = data["content"]
|
||||
if "菲菲" in content:
|
||||
@ -152,7 +154,7 @@ async def xie_ai(text: str, sess: ClientSession) -> str:
|
||||
return (
|
||||
content
|
||||
if not content and not Config.get_config("ai", "ALAPI_AI_CHECK")
|
||||
else await check_text(content, sess)
|
||||
else await check_text(content)
|
||||
)
|
||||
|
||||
|
||||
@ -196,18 +198,16 @@ def no_result() -> str:
|
||||
)
|
||||
|
||||
|
||||
async def check_text(text: str, sess: ClientSession) -> str:
|
||||
async def check_text(text: str) -> str:
|
||||
"""
|
||||
ALAPI文本检测,主要针对青云客API,检测为恶俗文本改为无回复的回答
|
||||
:param text: 回复
|
||||
:param sess: AIOHTTP SESSION
|
||||
"""
|
||||
if not Config.get_config("alapi", "ALAPI_TOKEN"):
|
||||
return text
|
||||
params = {"token": Config.get_config("alapi", "ALAPI_TOKEN"), "text": text}
|
||||
try:
|
||||
async with sess.get(check_url, timeout=2, params=params) as response:
|
||||
data = await response.json()
|
||||
data = (await AsyncHttpx.get(check_url, timeout=2, params=params)).json()
|
||||
if data["code"] == 200:
|
||||
if data["data"]["conclusion_type"] == 2:
|
||||
return ""
|
||||
|
||||
137
plugins/ai/utils.py
Executable file
137
plugins/ai/utils.py
Executable file
@ -0,0 +1,137 @@
|
||||
from utils.manager import StaticData
|
||||
from configs.config import NICKNAME
|
||||
from models.ban_user import BanUser
|
||||
from typing import Optional
|
||||
import random
|
||||
import time
|
||||
|
||||
|
||||
class AiMessageManager(StaticData):
|
||||
def __init__(self):
|
||||
super().__init__(None)
|
||||
self._same_message = [
|
||||
"为什么要发一样的话?",
|
||||
"请不要再重复对我说一句话了,不然我就要生气了!",
|
||||
"别再发这句话了,我已经知道了...",
|
||||
"你是只会说这一句话吗?",
|
||||
"[*],你发我也发!",
|
||||
"[uname],[*]",
|
||||
f"救命!有笨蛋一直给{NICKNAME}发一样的话!",
|
||||
"这句话你已经给我发了{}次了,再发就生气!",
|
||||
]
|
||||
self._repeat_message = [
|
||||
f"请不要学{NICKNAME}说话",
|
||||
f"为什么要一直学{NICKNAME}说话?",
|
||||
"你再学!你再学我就生气了!",
|
||||
f"呜呜,你是想欺负{NICKNAME}嘛..",
|
||||
"[uname]不要再学我说话了!",
|
||||
"再学我说话,我就把你拉进黑名单(生气",
|
||||
"你再学![uname]是个笨蛋!",
|
||||
"你已经学我说话{}次了!别再学了!",
|
||||
]
|
||||
|
||||
def add_message(self, user_id: int, message: str):
|
||||
"""
|
||||
添加用户消息
|
||||
:param user_id: 用户id
|
||||
:param message: 消息内容
|
||||
"""
|
||||
if message:
|
||||
if self._data.get(user_id) is None:
|
||||
self._data[user_id] = {
|
||||
"time": time.time(),
|
||||
"message": [],
|
||||
"result": [],
|
||||
"repeat_count": 0,
|
||||
}
|
||||
if time.time() - self._data[user_id]["time"] > 60 * 10:
|
||||
self._data[user_id]["message"].clear()
|
||||
self._data[user_id]["time"] = time.time()
|
||||
self._data[user_id]["message"].append(message.strip())
|
||||
|
||||
def add_result(self, user_id: int, message: str):
|
||||
"""
|
||||
添加回复用户的消息
|
||||
:param user_id: 用户id
|
||||
:param message: 回复消息内容
|
||||
"""
|
||||
if message:
|
||||
if self._data.get(user_id) is None:
|
||||
self._data[user_id] = {
|
||||
"time": time.time(),
|
||||
"message": [],
|
||||
"result": [],
|
||||
"repeat_count": 0,
|
||||
}
|
||||
if time.time() - self._data[user_id]["time"] > 60 * 10:
|
||||
self._data[user_id]["result"].clear()
|
||||
self._data[user_id]["repeat_count"] = 0
|
||||
self._data[user_id]["time"] = time.time()
|
||||
self._data[user_id]["result"].append(message.strip())
|
||||
|
||||
async def get_result(self, user_id: int, nickname: str) -> Optional[str]:
|
||||
"""
|
||||
特殊消息特殊回复
|
||||
:param user_id: 用户id
|
||||
:param nickname: 用户昵称
|
||||
"""
|
||||
if len(self._data[user_id]["message"]) < 2:
|
||||
return None
|
||||
msg = await self._get_user_repeat_message_result(user_id)
|
||||
if not msg:
|
||||
msg = await self._get_user_same_message_result(user_id)
|
||||
if msg:
|
||||
if "[uname]" in msg:
|
||||
msg = msg.replace("[uname]", nickname)
|
||||
if not msg.startswith("生气了!你好烦,闭嘴!") and "[*]" in msg:
|
||||
msg = msg.replace("[*]", self._data[user_id]["message"][-1])
|
||||
return msg
|
||||
|
||||
async def _get_user_same_message_result(self, user_id: int) -> Optional[str]:
|
||||
"""
|
||||
重复消息回复
|
||||
:param user_id: 用户id
|
||||
"""
|
||||
msg = self._data[user_id]["message"][-1]
|
||||
cnt = 0
|
||||
_tmp = self._data[user_id]["message"][:-1]
|
||||
_tmp.reverse()
|
||||
for s in _tmp:
|
||||
if s == msg:
|
||||
cnt += 1
|
||||
else:
|
||||
break
|
||||
if cnt > 1:
|
||||
if random.random() < 0.5 and cnt > 3:
|
||||
rand = random.randint(60, 300)
|
||||
await BanUser.ban(user_id, 9, rand)
|
||||
self._data[user_id]["message"].clear()
|
||||
return f"生气了!你好烦,闭嘴!给我老实安静{rand}秒"
|
||||
return random.choice(self._same_message).format(cnt)
|
||||
return None
|
||||
|
||||
async def _get_user_repeat_message_result(self, user_id: int) -> Optional[str]:
|
||||
"""
|
||||
复读真寻的消息回复
|
||||
:param user_id: 用户id
|
||||
"""
|
||||
msg = self._data[user_id]["message"][-1]
|
||||
if self._data[user_id]["result"]:
|
||||
rst = self._data[user_id]["result"][-1]
|
||||
else:
|
||||
return None
|
||||
if msg == rst:
|
||||
self._data[user_id]["repeat_count"] += 1
|
||||
cnt = self._data[user_id]["repeat_count"]
|
||||
if cnt > 1:
|
||||
if random.random() < 0.5 and cnt > 3:
|
||||
rand = random.randint(60, 300)
|
||||
await BanUser.ban(user_id, 9, rand)
|
||||
self._data[user_id]["result"].clear()
|
||||
self._data[user_id]["repeat_count"] = 0
|
||||
return f"生气了!你好烦,闭嘴!给我老实安静{rand}秒"
|
||||
return random.choice(self._repeat_message).format(cnt)
|
||||
return None
|
||||
|
||||
|
||||
ai_message_manager = AiMessageManager()
|
||||
0
plugins/alapi/__init__.py
Normal file → Executable file
0
plugins/alapi/__init__.py
Normal file → Executable file
0
plugins/alapi/comments_163.py
Normal file → Executable file
0
plugins/alapi/comments_163.py
Normal file → Executable file
0
plugins/alapi/cover.py
Normal file → Executable file
0
plugins/alapi/cover.py
Normal file → Executable file
6
plugins/alapi/data_source.py
Normal file → Executable file
6
plugins/alapi/data_source.py
Normal file → Executable file
@ -4,7 +4,7 @@ from utils.message_builder import image
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from typing import Optional
|
||||
from configs.config import Config
|
||||
import aiohttp
|
||||
from utils.http_utils import AsyncHttpx
|
||||
|
||||
|
||||
async def get_data(url: str, params: Optional[dict] = None) -> "Union[dict, str], int":
|
||||
@ -16,10 +16,8 @@ async def get_data(url: str, params: Optional[dict] = None) -> "Union[dict, str]
|
||||
if not params:
|
||||
params = {}
|
||||
params["token"] = Config.get_config("alapi", "ALAPI_TOKEN")
|
||||
async with aiohttp.ClientSession() as session:
|
||||
try:
|
||||
async with session.get(url, timeout=2, params=params) as response:
|
||||
data = await response.json()
|
||||
data = (await AsyncHttpx.get(url, params=params, timeout=5)).json()
|
||||
if data["code"] == 200:
|
||||
if not data["data"]:
|
||||
return "没有搜索到...", 997
|
||||
|
||||
48
plugins/alapi/jitang.py
Executable file
48
plugins/alapi/jitang.py
Executable file
@ -0,0 +1,48 @@
|
||||
from nonebot import on_command
|
||||
from services.log import logger
|
||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
||||
from nonebot.typing import T_State
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.config import Config
|
||||
from .data_source import get_data
|
||||
|
||||
|
||||
__zx_plugin_name__ = "鸡汤"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
不喝点什么感觉有点不舒服
|
||||
指令:
|
||||
鸡汤
|
||||
""".strip()
|
||||
__plugin_des__ = "喏,亲手为你煮的鸡汤"
|
||||
__plugin_cmd__ = ["鸡汤"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["鸡汤", "毒鸡汤"],
|
||||
}
|
||||
|
||||
url = "https://v2.alapi.cn/api/soul"
|
||||
|
||||
|
||||
jitang = on_command("鸡汤", aliases={"毒鸡汤"}, priority=5, block=True)
|
||||
|
||||
|
||||
@jitang.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
try:
|
||||
data, code = await get_data(url)
|
||||
if code != 200:
|
||||
await jitang.finish(data, at_sender=True)
|
||||
await jitang.send(data["data"]["content"])
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 发送鸡汤:" + data["data"]["content"]
|
||||
)
|
||||
except Exception as e:
|
||||
await jitang.send("鸡汤煮坏掉了...")
|
||||
logger.error(f"鸡汤煮坏掉了 {type(e)}:{e}")
|
||||
0
plugins/alapi/poetry.py
Normal file → Executable file
0
plugins/alapi/poetry.py
Normal file → Executable file
55
plugins/alapi/wbtop.py
Normal file → Executable file
55
plugins/alapi/wbtop.py
Normal file → Executable file
@ -3,13 +3,13 @@ from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
||||
from nonebot.typing import T_State
|
||||
from services.log import logger
|
||||
from .data_source import get_data, gen_wbtop_pic
|
||||
from utils.browser import get_browser
|
||||
from utils.utils import get_message_text, is_number
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.message_builder import image
|
||||
from utils.http_utils import AsyncPlaywright
|
||||
import asyncio
|
||||
|
||||
__zx_plugin_name__ = '微博热搜'
|
||||
__zx_plugin_name__ = "微博热搜"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
在QQ上吃个瓜
|
||||
@ -18,21 +18,21 @@ usage:
|
||||
微博热搜 [id]:截图该热搜页面
|
||||
示例:微博热搜 5
|
||||
""".strip()
|
||||
__plugin_des__ = '刚买完瓜,在吃瓜现场'
|
||||
__plugin_cmd__ = ['微博热搜', '微博热搜 [id]']
|
||||
__plugin_des__ = "刚买完瓜,在吃瓜现场"
|
||||
__plugin_cmd__ = ["微博热搜", "微博热搜 [id]"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = 'HibiKier'
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ['微博热搜'],
|
||||
"cmd": ["微博热搜"],
|
||||
}
|
||||
|
||||
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://v2.alapi.cn/api/new/wbtop"
|
||||
|
||||
wbtop_data = []
|
||||
|
||||
@ -45,32 +45,27 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
data, code = await get_data(wbtop_url)
|
||||
if code != 200:
|
||||
await wbtop.finish(data, at_sender=True)
|
||||
wbtop_data = data['data']
|
||||
wbtop_data = data["data"]
|
||||
if not msg:
|
||||
img = await asyncio.get_event_loop().run_in_executor(None, gen_wbtop_pic, wbtop_data)
|
||||
img = await asyncio.get_event_loop().run_in_executor(
|
||||
None, gen_wbtop_pic, wbtop_data
|
||||
)
|
||||
await wbtop.send(img)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 查询微博热搜")
|
||||
f" 查询微博热搜"
|
||||
)
|
||||
if is_number(msg) and 0 < int(msg) <= 50:
|
||||
url = wbtop_data[int(msg) - 1]['url']
|
||||
browser = await get_browser()
|
||||
page = None
|
||||
url = wbtop_data[int(msg) - 1]["url"]
|
||||
try:
|
||||
if not browser:
|
||||
logger.warning('获取 browser 失败,请部署至 linux 环境....')
|
||||
await wbtop.finish('获取 browser 对象失败...')
|
||||
page = await browser.new_page()
|
||||
await page.goto(url, wait_until='networkidle', timeout=10000)
|
||||
await page.set_viewport_size({"width": 2560, "height": 1080})
|
||||
await asyncio.sleep(5)
|
||||
div = await page.query_selector("#pl_feedlist_index")
|
||||
await div.screenshot(path=f'{IMAGE_PATH}/temp/wbtop_{event.user_id}.png', timeout=100000)
|
||||
await page.close()
|
||||
await wbtop.send(image(f'wbtop_{event.user_id}.png', 'temp'))
|
||||
await wbtop.send("开始截取数据...")
|
||||
img = await AsyncPlaywright.screenshot(
|
||||
url,
|
||||
f"{IMAGE_PATH}/temp/wbtop_{event.user_id}.png",
|
||||
"#pl_feedlist_index",
|
||||
sleep=5
|
||||
)
|
||||
await wbtop.send(img)
|
||||
except Exception as e:
|
||||
logger.error(f'微博热搜截图出错... {type(e)}: {e}')
|
||||
if page:
|
||||
await page.close()
|
||||
await wbtop.send('发生了一些错误.....')
|
||||
|
||||
logger.error(f"微博热搜截图出错... {type(e)}: {e}")
|
||||
await wbtop.send("发生了一些错误.....")
|
||||
|
||||
1
plugins/bilibili_sub/__init__.py
Normal file → Executable file
1
plugins/bilibili_sub/__init__.py
Normal file → Executable file
@ -206,6 +206,7 @@ async def _():
|
||||
await sub_manager.reload_sub_data()
|
||||
sub = await sub_manager.random_sub_data()
|
||||
if sub:
|
||||
logger.info(f"Bilibili订阅开始检测:{sub.sub_id}")
|
||||
rst = await get_sub_status(sub.sub_id, sub.sub_type)
|
||||
await send_sub_msg(rst, sub, bot)
|
||||
if sub.sub_type == "live":
|
||||
|
||||
13
plugins/bilibili_sub/data_source.py
Normal file → Executable file
13
plugins/bilibili_sub/data_source.py
Normal file → Executable file
@ -14,7 +14,7 @@ from datetime import datetime
|
||||
from utils.browser import get_browser
|
||||
from services.db_context import db
|
||||
from services.log import logger
|
||||
import aiohttp
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import random
|
||||
|
||||
|
||||
@ -150,7 +150,7 @@ async def delete_sub(sub_id: str, sub_user: str) -> str:
|
||||
:param sub_id: 订阅 id
|
||||
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
|
||||
"""
|
||||
if await BilibiliSub.delete_bilibili_sub(sub_id, sub_user):
|
||||
if await BilibiliSub.delete_bilibili_sub(int(sub_id), sub_user):
|
||||
return f"已成功取消订阅:{sub_id}"
|
||||
else:
|
||||
return f"取消订阅:{sub_id} 失败,请检查是否订阅过该Id...."
|
||||
@ -162,15 +162,12 @@ async def get_media_id(keyword: str) -> dict:
|
||||
:param keyword: 番剧名称
|
||||
"""
|
||||
params = {"keyword": keyword}
|
||||
async with aiohttp.ClientSession() as session:
|
||||
for _ in range(3):
|
||||
try:
|
||||
_season_data = {}
|
||||
async with session.get(
|
||||
bilibili_search_url, timeout=5, params=params
|
||||
) as response:
|
||||
if response.status == 200:
|
||||
data = await response.json()
|
||||
response = await AsyncHttpx.get(bilibili_search_url, params=params, timeout=5)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get("data"):
|
||||
for item in data["data"]["result"]:
|
||||
if item["result_type"] == "media_bangumi":
|
||||
|
||||
0
plugins/bilibili_sub/model.py
Normal file → Executable file
0
plugins/bilibili_sub/model.py
Normal file → Executable file
39
plugins/bilibili_sub/utils.py
Normal file → Executable file
39
plugins/bilibili_sub/utils.py
Normal file → Executable file
@ -1,12 +1,12 @@
|
||||
from utils.image_utils import CreateImg
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from pathlib import Path
|
||||
from bilibili_api import user
|
||||
from io import BytesIO
|
||||
import aiohttp
|
||||
|
||||
|
||||
BORDER_PATH = Path(IMAGE_PATH) / 'border'
|
||||
BORDER_PATH = Path(IMAGE_PATH) / "border"
|
||||
BORDER_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
@ -16,9 +16,7 @@ async def get_pic(url: str) -> bytes:
|
||||
:param url: 图像链接
|
||||
:return: 图像二进制
|
||||
"""
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url, timeout=2) as response:
|
||||
return await response.read()
|
||||
return (await AsyncHttpx.get(url, timeout=10)).content
|
||||
|
||||
|
||||
async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des: str):
|
||||
@ -33,17 +31,26 @@ async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des
|
||||
"""
|
||||
u = user.User(uid)
|
||||
user_info = await u.get_user_info()
|
||||
name = user_info['name']
|
||||
sex = user_info['sex']
|
||||
face = user_info['face']
|
||||
sign = user_info['sign']
|
||||
name = user_info["name"]
|
||||
sex = user_info["sex"]
|
||||
face = user_info["face"]
|
||||
sign = user_info["sign"]
|
||||
ava = CreateImg(100, 100, background=BytesIO(await get_pic(face)))
|
||||
ava.circle()
|
||||
cover = CreateImg(470, 265, background=BytesIO(await get_pic(cover)))
|
||||
print()
|
||||
|
||||
|
||||
def _create_live_des_image(title: str, cover: CreateImg, tags: str, des: str, user_name: str, sex: str, sign: str, ava: CreateImg):
|
||||
def _create_live_des_image(
|
||||
title: str,
|
||||
cover: CreateImg,
|
||||
tags: str,
|
||||
des: str,
|
||||
user_name: str,
|
||||
sex: str,
|
||||
sign: str,
|
||||
ava: CreateImg,
|
||||
):
|
||||
"""
|
||||
生成主播简介图片
|
||||
:param title: 直播间标题
|
||||
@ -56,17 +63,9 @@ def _create_live_des_image(title: str, cover: CreateImg, tags: str, des: str, us
|
||||
:param ava: 主播头像
|
||||
:return:
|
||||
"""
|
||||
border = BORDER_PATH / '0.png'
|
||||
border = BORDER_PATH / "0.png"
|
||||
border_img = None
|
||||
if border.exists():
|
||||
border_img = CreateImg(1772, 2657, background=border)
|
||||
bk = CreateImg(1772, 2657, font_size=30)
|
||||
bk.paste(cover, (0, 100), center_type='by_width')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bk.paste(cover, (0, 100), center_type="by_width")
|
||||
|
||||
5
plugins/bt/__init__.py
Normal file → Executable file
5
plugins/bt/__init__.py
Normal file → Executable file
@ -7,7 +7,6 @@ from nonebot.adapters.cqhttp import PrivateMessageEvent
|
||||
from utils.utils import get_message_text
|
||||
from nonebot.adapters.cqhttp.permission import PRIVATE
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from aiohttp.client_exceptions import ServerDisconnectedError
|
||||
|
||||
__zx_plugin_name__ = "磁力搜索"
|
||||
__plugin_usage__ = """
|
||||
@ -89,11 +88,9 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
||||
send_flag = True
|
||||
except TimeoutError:
|
||||
await bt.finish(f"搜索 {keyword} 超时...")
|
||||
except ServerDisconnectedError:
|
||||
await bt.finish(f"搜索 {keyword} 连接失败")
|
||||
except Exception as e:
|
||||
await bt.finish(f"bt 其他未知错误..")
|
||||
logger.error(f"bt 错误 e:{e}")
|
||||
logger.error(f"bt 错误 {type(e)}:{e}")
|
||||
if not send_flag:
|
||||
await bt.send(f"{keyword} 未搜索到...")
|
||||
logger.info(f"USER {event.user_id} BT搜索 {keyword} 第 {page} 页")
|
||||
|
||||
29
plugins/bt/data_source.py
Normal file → Executable file
29
plugins/bt/data_source.py
Normal file → Executable file
@ -1,8 +1,6 @@
|
||||
from utils.user_agent import get_user_agent
|
||||
import aiohttp
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.config import Config
|
||||
from bs4 import BeautifulSoup
|
||||
from utils.utils import get_local_proxy
|
||||
import platform
|
||||
|
||||
if platform.system() == "Windows":
|
||||
@ -15,11 +13,12 @@ url = "http://www.eclzz.world"
|
||||
|
||||
|
||||
async def get_bt_info(keyword: str, page: str):
|
||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||
async with session.get(
|
||||
f"{url}/s/{keyword}_rel_{page}.html", proxy=get_local_proxy(), timeout=5
|
||||
) as response:
|
||||
text = await response.text()
|
||||
"""
|
||||
获取资源信息
|
||||
:param keyword: 关键词
|
||||
:param page: 页数
|
||||
"""
|
||||
text = (await AsyncHttpx.get(f"{url}/s/{keyword}_rel_{page}.html", timeout=5)).text
|
||||
if text.find("大约0条结果") != -1:
|
||||
return
|
||||
soup = BeautifulSoup(text, "lxml")
|
||||
@ -38,13 +37,15 @@ async def get_bt_info(keyword: str, page: str):
|
||||
itype = spans[0].text
|
||||
create_time = spans[1].find("b").text
|
||||
file_size = spans[2].find("b").text
|
||||
link = await get_download_link(divs[0].find("a")["href"], session)
|
||||
link = await get_download_link(divs[0].find("a")["href"])
|
||||
yield title, itype, create_time, file_size, link
|
||||
|
||||
|
||||
async def get_download_link(_url: str, session) -> str:
|
||||
async with session.get(
|
||||
f"{url}{_url}", proxy=get_local_proxy(), timeout=30
|
||||
) as response:
|
||||
soup = BeautifulSoup(await response.text(), "lxml")
|
||||
async def get_download_link(_url: str) -> str:
|
||||
"""
|
||||
获取资源下载地址
|
||||
:param _url: 链接
|
||||
"""
|
||||
text = (await AsyncHttpx.get(f"{url}{_url}")).text
|
||||
soup = BeautifulSoup(text, "lxml")
|
||||
return soup.find("a", {"id": "down-url"})["href"]
|
||||
|
||||
12
plugins/c_song/__init__.py
Normal file → Executable file
12
plugins/c_song/__init__.py
Normal file → Executable file
@ -25,22 +25,22 @@ __plugin_settings__ = {
|
||||
}
|
||||
|
||||
|
||||
songpicker = on_command("点歌", priority=5, block=True)
|
||||
music = on_command("点歌", priority=5, block=True)
|
||||
|
||||
|
||||
@songpicker.handle()
|
||||
@music.handle()
|
||||
async def handle_first_receive(bot: Bot, event: Event, state: T_State):
|
||||
args = str(event.get_message()).strip()
|
||||
if args:
|
||||
state["song_name"] = args
|
||||
|
||||
|
||||
@songpicker.got("song_name", prompt="歌名是?")
|
||||
@music.got("song_name", prompt="歌名是?")
|
||||
async def _(bot: Bot, event: Event, state: T_State):
|
||||
song = state["song_name"]
|
||||
song_id = await get_song_id(song)
|
||||
if not song_id:
|
||||
await songpicker.finish("没有找到这首歌!", at_sender=True)
|
||||
await music.finish("没有找到这首歌!", at_sender=True)
|
||||
for _ in range(3):
|
||||
song_content = [{"type": "music", "data": {"type": 163, "id": song_id}}]
|
||||
logger.info(
|
||||
@ -48,9 +48,9 @@ async def _(bot: Bot, event: Event, state: T_State):
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 点歌 :{song}"
|
||||
)
|
||||
await songpicker.finish(song_content)
|
||||
await music.finish(song_content)
|
||||
else:
|
||||
await songpicker.finish("网易云繁忙...")
|
||||
await music.finish("网易云繁忙...")
|
||||
|
||||
|
||||
|
||||
|
||||
41
plugins/c_song/music_163.py
Normal file → Executable file
41
plugins/c_song/music_163.py
Normal file → Executable file
@ -1,4 +1,4 @@
|
||||
import aiohttp
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import json
|
||||
|
||||
|
||||
@ -7,24 +7,22 @@ cookies = {"appver": "2.0.2"}
|
||||
|
||||
|
||||
async def search_song(song_name: str):
|
||||
async with aiohttp.ClientSession(
|
||||
headers=headers, cookies=cookies
|
||||
) as session:
|
||||
async with session.post(
|
||||
"""
|
||||
搜索歌曲
|
||||
:param song_name: 歌名
|
||||
"""
|
||||
r = await AsyncHttpx.post(
|
||||
f"http://music.163.com/api/search/get/",
|
||||
data={"s": song_name, "limit": 1, "type": 1, "offset": 0},
|
||||
) as r:
|
||||
if r.status != 200:
|
||||
)
|
||||
if r.status_code != 200:
|
||||
return None
|
||||
r = await r.text()
|
||||
return json.loads(r)
|
||||
return json.loads(r.text)
|
||||
|
||||
|
||||
async def get_song_id(songName: str) -> int:
|
||||
"""
|
||||
根据用户输入的songName 获取候选songId列表 [默认songId数量:5]
|
||||
"""
|
||||
r = await search_song(songName)
|
||||
async def get_song_id(song_name: str) -> int:
|
||||
""" """
|
||||
r = await search_song(song_name)
|
||||
return r["result"]["songs"][0]["id"]
|
||||
|
||||
|
||||
@ -32,16 +30,9 @@ async def get_song_info(songId: int):
|
||||
"""
|
||||
获取歌曲信息
|
||||
"""
|
||||
async with aiohttp.ClientSession(
|
||||
headers=headers, cookies=cookies
|
||||
) as session:
|
||||
async with session.post(
|
||||
r = await AsyncHttpx.post(
|
||||
f"http://music.163.com/api/song/detail/?id={songId}&ids=%5B{songId}%5D",
|
||||
) as r:
|
||||
if r.status != 200:
|
||||
)
|
||||
if r.status_code != 200:
|
||||
return None
|
||||
r = await r.text()
|
||||
return json.loads(r)
|
||||
|
||||
|
||||
|
||||
return json.loads(r.text)
|
||||
|
||||
0
plugins/check/__init__.py
Normal file → Executable file
0
plugins/check/__init__.py
Normal file → Executable file
25
plugins/check/data_source.py
Normal file → Executable file
25
plugins/check/data_source.py
Normal file → Executable file
@ -1,11 +1,7 @@
|
||||
import psutil
|
||||
import aiohttp
|
||||
import time
|
||||
from datetime import datetime
|
||||
from utils.user_agent import get_user_agent
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
from utils.utils import get_local_proxy
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.image_utils import CreateImg
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from pathlib import Path
|
||||
@ -34,22 +30,15 @@ class Check:
|
||||
self.disk = psutil.disk_usage("/").percent
|
||||
|
||||
async def check_network(self):
|
||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||
try:
|
||||
async with session.get(
|
||||
"https://www.baidu.com/", proxy=get_local_proxy(), timeout=3
|
||||
) as response:
|
||||
pass
|
||||
except (TimeoutError, ClientConnectorError) as e:
|
||||
logger.warning(f"访问BaiDu失败... e: {e}")
|
||||
await AsyncHttpx.get("https://www.baidu.com/", timeout=5)
|
||||
except Exception as e:
|
||||
logger.warning(f"访问BaiDu失败... {type(e)}: {e}")
|
||||
self.baidu = 404
|
||||
try:
|
||||
async with session.get(
|
||||
"https://www.google.com/", proxy=get_local_proxy(), timeout=3
|
||||
) as response:
|
||||
pass
|
||||
except (TimeoutError, ClientConnectorError) as e:
|
||||
logger.warning(f"访问Google失败... e: {e}")
|
||||
await AsyncHttpx.get("https://www.google.com/", timeout=5)
|
||||
except Exception as e:
|
||||
logger.warning(f"访问Google失败... {type(e)}: {e}")
|
||||
self.google = 404
|
||||
|
||||
def check_user(self):
|
||||
|
||||
0
plugins/check_zhenxun_update/__init__.py
Normal file → Executable file
0
plugins/check_zhenxun_update/__init__.py
Normal file → Executable file
35
plugins/check_zhenxun_update/data_source.py
Normal file → Executable file
35
plugins/check_zhenxun_update/data_source.py
Normal file → Executable file
@ -1,18 +1,14 @@
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
from nonebot.adapters.cqhttp import Bot, Message
|
||||
from utils.user_agent import get_user_agent
|
||||
from utils.utils import get_local_proxy
|
||||
from utils.image_utils import CreateImg
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.message_builder import image
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from typing import List
|
||||
from services.log import logger
|
||||
from pathlib import Path
|
||||
import ujson as json
|
||||
import nonebot
|
||||
import asyncio
|
||||
import aiofiles
|
||||
import aiohttp
|
||||
import platform
|
||||
import tarfile
|
||||
import shutil
|
||||
@ -77,7 +73,7 @@ async def check_update(bot: Bot) -> 'int, str':
|
||||
message=f"检测真寻已更新,当前版本:{_version},最新版本:{latest_version}\n" f"开始更新.....",
|
||||
)
|
||||
logger.info(f"开始下载真寻最新版文件....")
|
||||
if await download_latest_file(tar_gz_url):
|
||||
if await AsyncHttpx.download_file(tar_gz_url, zhenxun_latest_tar_gz):
|
||||
logger.info("下载真寻最新版文件完成....")
|
||||
error = await asyncio.get_event_loop().run_in_executor(
|
||||
None, _file_handle, latest_version
|
||||
@ -194,38 +190,23 @@ def _file_handle(latest_version: str) -> str:
|
||||
|
||||
# 获取最新版本号
|
||||
async def get_latest_version_data() -> dict:
|
||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||
for _ in range(3):
|
||||
try:
|
||||
async with session.get(release_url, proxy=get_local_proxy()) as res:
|
||||
if res.status == 200:
|
||||
return await res.json()
|
||||
except (TimeoutError, ClientConnectorError):
|
||||
res = await AsyncHttpx.get(release_url)
|
||||
if res.status_code == 200:
|
||||
return res.json()
|
||||
except TimeoutError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.error(f"检查更新真寻获取版本失败 {type(e)}:{e}")
|
||||
return {}
|
||||
|
||||
|
||||
# 下载文件
|
||||
async def download_latest_file(url_: str) -> bool:
|
||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||
for _ in range(3):
|
||||
try:
|
||||
async with session.get(url_, proxy=get_local_proxy()) as res:
|
||||
if res.status == 200:
|
||||
async with aiofiles.open(zhenxun_latest_tar_gz, "wb") as f:
|
||||
await f.write(await res.read())
|
||||
return True
|
||||
except (TimeoutError, ClientConnectorError):
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
# 逐行检测
|
||||
def check_old_lines(lines: List[str], line: str) -> str:
|
||||
if "=" not in line:
|
||||
return line
|
||||
for l in lines:
|
||||
if "=" in l and l.split("=")[0].strip() == line.split("=")[0].strip():
|
||||
if l.split("=")[1].strip() == 'None':
|
||||
return l
|
||||
return line
|
||||
|
||||
40
plugins/coser/__init__.py
Normal file → Executable file
40
plugins/coser/__init__.py
Normal file → Executable file
@ -1,13 +1,8 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
||||
from services.log import logger
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from nonebot.adapters.cqhttp import Bot, MessageEvent
|
||||
from utils.message_builder import image
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.utils import get_local_proxy
|
||||
import aiohttp
|
||||
import aiofiles
|
||||
from services.log import logger
|
||||
|
||||
__zx_plugin_name__ = "coser"
|
||||
__plugin_usage__ = """
|
||||
@ -32,38 +27,13 @@ coser = on_command(
|
||||
)
|
||||
|
||||
|
||||
url = "http://ovooa.com/API/cosplay/api.php"
|
||||
url = "http://iw233.cn/API/cos.php"
|
||||
|
||||
|
||||
@coser.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
async with aiohttp.ClientSession() as session:
|
||||
try:
|
||||
for _ in range(3):
|
||||
try:
|
||||
async with session.get(url, proxy=get_local_proxy(), timeout=2, verify_ssl=False) as response:
|
||||
_url = (await response.json())['text']
|
||||
async with session.get(
|
||||
_url, timeout=5, proxy=get_local_proxy(), verify_ssl=False
|
||||
) as res:
|
||||
if res.status == 200:
|
||||
async with aiofiles.open(
|
||||
f"{IMAGE_PATH}/temp/{event.user_id}_coser.jpg", "wb"
|
||||
) as f:
|
||||
await f.write(await res.read())
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, "
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 发送COSER"
|
||||
)
|
||||
await coser.send(
|
||||
image(f"{event.user_id}_coser.jpg", "temp")
|
||||
)
|
||||
break
|
||||
except (TimeoutError, KeyError):
|
||||
pass
|
||||
else:
|
||||
await coser.send("你cos给我看!")
|
||||
await coser.send(image(url))
|
||||
except Exception as e:
|
||||
await coser.send("发生了预料之外的错误..请稍后再试或联系管理员修复...")
|
||||
await coser.send("你cos给我看!")
|
||||
logger.error(f"coser 发送了未知错误 {type(e)}:{e}")
|
||||
|
||||
@ -1,69 +0,0 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
|
||||
from utils.utils import get_message_text, is_number
|
||||
from .data_source import get_csgola_data, get_5e_data
|
||||
from services.log import logger
|
||||
|
||||
|
||||
__zx_plugin_name__ = "cs国服/平台信息查找"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
快速查询csgo战绩和数据
|
||||
指令:
|
||||
cs国服查询 [steam主页个人id]
|
||||
5e查询 [5e战绩个人名称]
|
||||
示例:cs国服查询 23848238483
|
||||
示例:5e查询 poster
|
||||
"""
|
||||
__plugin_des__ = "什么?你也是rush B玩家?"
|
||||
__plugin_cmd__ = ["cs国服查询 [steam主页个人id]", "5e查询 [5e战绩个人名称]"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["csgo战绩查询", "cs国服查询", "5e查询"],
|
||||
}
|
||||
|
||||
csgola = on_command("cs国服查询", priority=5, block=True)
|
||||
|
||||
csgo5e = on_command("5e查询", priority=5, block=True)
|
||||
|
||||
|
||||
@csgola.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
msg = get_message_text(event.json())
|
||||
if "http" in msg:
|
||||
msg = msg[:-1] if msg[-1] == "/" else msg
|
||||
msg = msg.split("/")[-1]
|
||||
if not is_number(msg):
|
||||
await csgola.finish("Id必须为数字!", at_sender=True)
|
||||
await csgola.send("开始查找...")
|
||||
img, code = await get_csgola_data(int(msg))
|
||||
if code == 200:
|
||||
await csgola.send(img, at_sender=True)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 查询csgo国服战绩:{msg}"
|
||||
)
|
||||
else:
|
||||
await csgola.send(img, at_sender=True)
|
||||
|
||||
|
||||
@csgo5e.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
msg = get_message_text(event.json())
|
||||
await csgola.send("开始查找...")
|
||||
img, code = await get_5e_data(msg)
|
||||
if code == 200:
|
||||
await csgo5e.send(img, at_sender=True)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 查询csgo国服战绩:{msg}"
|
||||
)
|
||||
else:
|
||||
await csgo5e.send(img, at_sender=True)
|
||||
@ -1,130 +0,0 @@
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.image_utils import CreateImg
|
||||
from utils.message_builder import image
|
||||
from services.log import logger
|
||||
from utils.browser import get_browser
|
||||
from playwright._impl._api_types import TimeoutError
|
||||
|
||||
csgola_url = "https://www.csgola.com/player/"
|
||||
_5e_url = "https://arena.5eplay.com/data/player/"
|
||||
|
||||
|
||||
async def get_csgola_data(uid: int) -> "str, int":
|
||||
page = None
|
||||
try:
|
||||
browser = await get_browser()
|
||||
if not browser:
|
||||
return "", 997
|
||||
page = await browser.new_page()
|
||||
for _ in range(3):
|
||||
try:
|
||||
await page.goto(f"{csgola_url}{uid}", wait_until="networkidle", timeout=10000)
|
||||
break
|
||||
except TimeoutError:
|
||||
pass
|
||||
else:
|
||||
return '连接超时...', 995
|
||||
await page.set_viewport_size({"width": 2560, "height": 1080})
|
||||
|
||||
data = await page.query_selector_all(".panel-body")
|
||||
if not data:
|
||||
return "未查询到该Id....", 999
|
||||
await data[0].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_1.png", timeout=100000)
|
||||
await data[3].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_2.png", timeout=100000)
|
||||
await data[5].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_3.png", timeout=100000)
|
||||
await data[7].screenshot(path=f"{IMAGE_PATH}/temp/{uid}_5.png", timeout=100000)
|
||||
|
||||
ava = await page.query_selector("div.container:nth-child(4) > div:nth-child(1)")
|
||||
await ava.screenshot(path=f"{IMAGE_PATH}/temp/{uid}_0.png", timeout=100000)
|
||||
|
||||
weapon_data = await page.query_selector(".gun-stats-sec")
|
||||
await weapon_data.screenshot(
|
||||
path=f"{IMAGE_PATH}/temp/{uid}_4.png", timeout=100000
|
||||
)
|
||||
|
||||
ava = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_0.png")
|
||||
statistical_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_1.png")
|
||||
combined_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_2.png")
|
||||
detailed_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_3.png")
|
||||
weapon_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_4.png")
|
||||
map_data = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/{uid}_5.png")
|
||||
if statistical_data.h > 300:
|
||||
statistical_data.crop((0, 0, statistical_data.w, 300))
|
||||
if combined_data.h > 260:
|
||||
combined_data.crop((0, 0, combined_data.w, 260))
|
||||
if detailed_data.h > 400:
|
||||
detailed_data.crop((0, 0, detailed_data.w, 400))
|
||||
weapon_data.crop((0, 100, weapon_data.w, weapon_data.h))
|
||||
map_data.crop((0, 310, map_data.w, map_data.h))
|
||||
height = (
|
||||
ava.h
|
||||
+ statistical_data.h
|
||||
+ combined_data.h
|
||||
+ detailed_data.h
|
||||
+ weapon_data.h
|
||||
+ map_data.h
|
||||
)
|
||||
bk = CreateImg(1168, height)
|
||||
current_h = 0
|
||||
for img in [
|
||||
ava,
|
||||
statistical_data,
|
||||
combined_data,
|
||||
detailed_data,
|
||||
weapon_data,
|
||||
map_data,
|
||||
]:
|
||||
bk.paste(img, (0, current_h))
|
||||
current_h += img.h
|
||||
bk.save(f"{IMAGE_PATH}/temp/csgo_{uid}.png")
|
||||
except Exception as e:
|
||||
logger.error(f"生成csgola图片错误 {type(e)}:{e}")
|
||||
if page:
|
||||
await page.close()
|
||||
return "发生了错误....", 998
|
||||
if page:
|
||||
await page.close()
|
||||
return image(f"csgo_{uid}.png", "temp"), 200
|
||||
|
||||
|
||||
async def get_5e_data(uname: str) -> "str, int":
|
||||
page = None
|
||||
try:
|
||||
browser = await get_browser()
|
||||
if not browser:
|
||||
return "", 997
|
||||
page = await browser.new_page()
|
||||
await page.goto(f"{_5e_url}{uname}", wait_until="networkidle", timeout=10000)
|
||||
if "HTTP ERROR 404" in await page.content():
|
||||
return "未查询到该玩家...", 999
|
||||
await page.set_viewport_size({"width": 2560, "height": 1080})
|
||||
body = await page.query_selector("body")
|
||||
await body.screenshot(
|
||||
path=f"{IMAGE_PATH}/temp/csgo_{uname}_0.png", timeout=100000
|
||||
)
|
||||
await page.click("a.match-tab-item:nth-child(2)")
|
||||
body = await page.query_selector("body")
|
||||
await body.screenshot(
|
||||
path=f"{IMAGE_PATH}/temp/csgo_{uname}_1.png", timeout=100000
|
||||
)
|
||||
await page.click("a.match-tab-item:nth-child(1)")
|
||||
body = await page.query_selector("body")
|
||||
await body.screenshot(
|
||||
path=f"{IMAGE_PATH}/temp/csgo_{uname}_2.png", timeout=100000
|
||||
)
|
||||
bk = CreateImg(1344 * 3, 2307)
|
||||
current_w = 0
|
||||
for i in range(3):
|
||||
body = CreateImg(0, 0, background=f"{IMAGE_PATH}/temp/csgo_{uname}_{i}.png")
|
||||
body.crop((600, 90, body.w - 600, body.h - 410))
|
||||
bk.paste(body, (current_w, 0))
|
||||
current_w += 1344
|
||||
bk.save(f"{IMAGE_PATH}/temp/csgo_{uname}.png")
|
||||
except Exception as e:
|
||||
logger.error(f"生成5e图片错误 {type(e)}:{e}")
|
||||
if page:
|
||||
await page.close()
|
||||
return "发生了错误...", 998
|
||||
if page:
|
||||
await page.close()
|
||||
return image(f"csgo_{uname}.png", "temp"), 200
|
||||
0
plugins/dialogue/__init__.py
Normal file → Executable file
0
plugins/dialogue/__init__.py
Normal file → Executable file
0
plugins/draw_card/__init__.py
Normal file → Executable file
0
plugins/draw_card/__init__.py
Normal file → Executable file
29
plugins/draw_card/announcement.py
Normal file → Executable file
29
plugins/draw_card/announcement.py
Normal file → Executable file
@ -1,11 +1,11 @@
|
||||
import aiohttp
|
||||
from bs4 import BeautifulSoup
|
||||
import re
|
||||
from datetime import datetime, timedelta
|
||||
from .config import DRAW_PATH
|
||||
from pathlib import Path
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import re
|
||||
try:
|
||||
import ujson as json
|
||||
except ModuleNotFoundError:
|
||||
@ -66,16 +66,14 @@ class PrtsAnnouncement:
|
||||
self.game_name = '明日方舟'
|
||||
|
||||
async def _get_announcement_text(self):
|
||||
async with aiohttp.ClientSession(headers=headers) as session:
|
||||
async with session.get(prts_url, timeout=7) as res:
|
||||
soup = BeautifulSoup(await res.text(), 'lxml')
|
||||
text = (await AsyncHttpx.get(prts_url)).text
|
||||
soup = BeautifulSoup(text, 'lxml')
|
||||
ol = soup.find('ol', {'class': 'articleList active', 'data-category-key': 'LATEST'})
|
||||
for li in ol:
|
||||
itype = li.find('span', {'class': 'articleItemCate'}).text
|
||||
if itype == '活动':
|
||||
a = li.find('a')['href']
|
||||
async with session.get(f'https://ak.hypergryph.com{a}', headers=headers, timeout=7) as res:
|
||||
return await res.text()
|
||||
return (await AsyncHttpx.get(f'https://ak.hypergryph.com{a}')).text
|
||||
|
||||
async def update_up_char(self):
|
||||
prts_up_char.parent.mkdir(parents=True, exist_ok=True)
|
||||
@ -147,9 +145,7 @@ class GenshinAnnouncement:
|
||||
self.game_name = '原神'
|
||||
|
||||
async def _get_announcement_text(self):
|
||||
async with aiohttp.ClientSession(headers=headers) as session:
|
||||
async with session.get(genshin_url, timeout=7) as res:
|
||||
return await res.text()
|
||||
return (await AsyncHttpx.get(genshin_url)).text
|
||||
|
||||
async def update_up_char(self):
|
||||
genshin_up_char.parent.mkdir(exist_ok=True, parents=True)
|
||||
@ -218,10 +214,10 @@ class PrettyAnnouncement:
|
||||
self.game_name = '赛马娘'
|
||||
|
||||
async def _get_announcement_text(self):
|
||||
async with aiohttp.ClientSession(headers=headers) as session:
|
||||
async with session.get(pretty_url, timeout=7) as res:
|
||||
soup = BeautifulSoup(await res.text(), 'lxml')
|
||||
text = (await AsyncHttpx.get(pretty_url)).text
|
||||
soup = BeautifulSoup(text, 'lxml')
|
||||
divs = soup.find('div', {'id': 'mw-content-text'}).find('div').find_all('div')
|
||||
title = " "
|
||||
for div in divs:
|
||||
a = div.find('a')
|
||||
try:
|
||||
@ -231,8 +227,7 @@ class PrettyAnnouncement:
|
||||
if title.find('新角色追加') != -1:
|
||||
url = a['href']
|
||||
break
|
||||
async with session.get(f'https://wiki.biligame.com/{url}', timeout=7) as res:
|
||||
return await res.text(), title[:-2]
|
||||
return (await AsyncHttpx.get(f'https://wiki.biligame.com/{url}')).text, title[:-2]
|
||||
|
||||
async def update_up_char(self):
|
||||
pretty_up_char.parent.mkdir(exist_ok=True, parents=True)
|
||||
@ -343,9 +338,7 @@ class GuardianAnnouncement:
|
||||
self.game_name = '坎公骑冠剑'
|
||||
|
||||
async def _get_announcement_text(self):
|
||||
async with aiohttp.ClientSession(headers=headers) as session:
|
||||
async with session.get(guardian_url, timeout=7) as res:
|
||||
return await res.text()
|
||||
return (await AsyncHttpx.get(guardian_url)).text
|
||||
|
||||
async def update_up_char(self):
|
||||
data = {
|
||||
|
||||
0
plugins/draw_card/async_update_game_info.py
Normal file → Executable file
0
plugins/draw_card/async_update_game_info.py
Normal file → Executable file
0
plugins/draw_card/azur_handle.py
Normal file → Executable file
0
plugins/draw_card/azur_handle.py
Normal file → Executable file
0
plugins/draw_card/config.py
Normal file → Executable file
0
plugins/draw_card/config.py
Normal file → Executable file
0
plugins/draw_card/fgo_handle.py
Normal file → Executable file
0
plugins/draw_card/fgo_handle.py
Normal file → Executable file
0
plugins/draw_card/genshin_handle.py
Normal file → Executable file
0
plugins/draw_card/genshin_handle.py
Normal file → Executable file
0
plugins/draw_card/guardian_handle.py
Normal file → Executable file
0
plugins/draw_card/guardian_handle.py
Normal file → Executable file
28
plugins/draw_card/init_card_pool.py
Normal file → Executable file
28
plugins/draw_card/init_card_pool.py
Normal file → Executable file
@ -2,6 +2,7 @@ from typing import Any
|
||||
from .config import DATA_PATH
|
||||
from utils.utils import is_number
|
||||
from pathlib import Path
|
||||
from services.log import logger
|
||||
try:
|
||||
import ujson as json
|
||||
except ModuleNotFoundError:
|
||||
@ -27,8 +28,11 @@ def init_game_pool(game: str, data: dict, Operator: Any):
|
||||
limited = True
|
||||
if key.find('阿米娅') != -1:
|
||||
continue
|
||||
try:
|
||||
tmp_lst.append(Operator(name=key, star=int(data[key]['星级']),
|
||||
limited=limited, recruit_only=recruit_only, event_only=event_only))
|
||||
except Exception as e:
|
||||
logger.warning(f"明日方舟导入角色 {key} 数据错误:{type(e)}:{e}")
|
||||
if game == 'genshin':
|
||||
for key in data.keys():
|
||||
if key.find('旅行者') != -1:
|
||||
@ -36,17 +40,26 @@ def init_game_pool(game: str, data: dict, Operator: Any):
|
||||
limited = False
|
||||
if data[key]['常驻/限定'] == '限定UP':
|
||||
limited = True
|
||||
try:
|
||||
tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited))
|
||||
except Exception as e:
|
||||
logger.warning(f"原神导入角色 {key} 数据错误:{type(e)}:{e}")
|
||||
if game == 'genshin_arms':
|
||||
for key in data.keys():
|
||||
if data[key]['获取途径'].find('祈愿') != -1:
|
||||
limited = False
|
||||
if data[key]['获取途径'].find('限定祈愿') != -1:
|
||||
limited = True
|
||||
try:
|
||||
tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited))
|
||||
except Exception as e:
|
||||
logger.warning(f"原神导入武器 {key} 数据错误:{type(e)}:{e}")
|
||||
if game == 'pretty':
|
||||
for key in data.keys():
|
||||
try:
|
||||
tmp_lst.append(Operator(name=key, star=data[key]['初始星级'], limited=False))
|
||||
except Exception as e:
|
||||
logger.warning(f"赛马娘导入角色 {key} 数据错误:{type(e)}:{e}")
|
||||
if game == 'pretty_card':
|
||||
for key in data.keys():
|
||||
limited = False
|
||||
@ -54,7 +67,10 @@ def init_game_pool(game: str, data: dict, Operator: Any):
|
||||
limited = True
|
||||
if not data[key]['获取方式']:
|
||||
limited = False
|
||||
try:
|
||||
tmp_lst.append(Operator(name=data[key]['中文名'], star=len(data[key]['稀有度']), limited=limited))
|
||||
except Exception as e:
|
||||
logger.warning(f"赛马娘导入卡片 {key} 数据错误:{type(e)}:{e}")
|
||||
if game in ['guardian', 'guardian_arms']:
|
||||
for key in data.keys():
|
||||
tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=False))
|
||||
@ -63,15 +79,21 @@ def init_game_pool(game: str, data: dict, Operator: Any):
|
||||
limited = False
|
||||
if key.find('(') != -1:
|
||||
limited = True
|
||||
try:
|
||||
tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited))
|
||||
except Exception as e:
|
||||
logger.warning(f"公主连接导入角色 {key} 数据错误:{type(e)}:{e}")
|
||||
if game == 'azur':
|
||||
for key in data.keys():
|
||||
if is_number(data[key]['星级']):
|
||||
limited = False
|
||||
if '可以建造' not in data[key]['获取途径']:
|
||||
limited = True
|
||||
try:
|
||||
tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']),
|
||||
limited=limited, itype=data[key]['类型']))
|
||||
except Exception as e:
|
||||
logger.warning(f"碧蓝航线导入角色 {key} 数据错误:{type(e)}:{e}")
|
||||
if game in ['fgo', 'fgo_card']:
|
||||
for key in data.keys():
|
||||
limited = False
|
||||
@ -80,14 +102,20 @@ def init_game_pool(game: str, data: dict, Operator: Any):
|
||||
limited = True
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited))
|
||||
except Exception as e:
|
||||
logger.warning(f"FGO导入角色 {key} 数据错误:{type(e)}:{e}")
|
||||
if game == 'onmyoji':
|
||||
for key in data.keys():
|
||||
limited = False
|
||||
if key in ['奴良陆生', '卖药郎', '鬼灯', '阿香', '蜜桃&芥子', '犬夜叉', '杀生丸', '桔梗', '朽木露琪亚', '黑崎一护',
|
||||
'灶门祢豆子', '灶门炭治郎']:
|
||||
limited = True
|
||||
try:
|
||||
tmp_lst.append(Operator(name=data[key]['名称'], star=data[key]['星级'], limited=limited))
|
||||
except Exception as e:
|
||||
logger.warning(f"阴阳师导入角色 {key} 数据错误:{type(e)}:{e}")
|
||||
# print(tmp_lst)
|
||||
char_name_lst = [x.name for x in tmp_lst]
|
||||
up_char_file = Path(f'{DATA_PATH}/draw_card/draw_card_up/{game.split("_")[0]}_up_char.json')
|
||||
|
||||
1
plugins/draw_card/onmyoji_handle.py
Normal file → Executable file
1
plugins/draw_card/onmyoji_handle.py
Normal file → Executable file
@ -6,7 +6,6 @@ from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max
|
||||
from .config import ONMYOJI_SR, ONMYOJI_SSR, ONMYOJI_SP, ONMYOJI_R, DRAW_PATH, ONMYOJI_FLAG
|
||||
from dataclasses import dataclass
|
||||
from .init_card_pool import init_game_pool
|
||||
import nonebot
|
||||
try:
|
||||
import ujson as json
|
||||
except ModuleNotFoundError:
|
||||
|
||||
3
plugins/draw_card/pcr_handle.py
Normal file → Executable file
3
plugins/draw_card/pcr_handle.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
import ujson as json
|
||||
import os
|
||||
from nonebot.adapters.cqhttp import MessageSegment
|
||||
import nonebot
|
||||
import random
|
||||
from .update_game_info import update_info
|
||||
from .update_game_simple_info import update_simple_info
|
||||
@ -10,7 +8,6 @@ from .config import PCR_TWO_P, PCR_THREE_P, PCR_ONE_P, DRAW_PATH, PCR_FLAG, PCR_
|
||||
from dataclasses import dataclass
|
||||
from .init_card_pool import init_game_pool
|
||||
|
||||
driver: nonebot.Driver = nonebot.get_driver()
|
||||
|
||||
ALL_CHAR = []
|
||||
|
||||
|
||||
0
plugins/draw_card/pretty_handle.py
Normal file → Executable file
0
plugins/draw_card/pretty_handle.py
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user