Compare commits

..
3 Commits
Author SHA1 Message Date
HibiKier c2a54a8164 Update update_info.json 2022-01-05 23:07:03 +08:00
HibiKier 4dbab21853 Update README.md 2022-01-05 22:57:29 +08:00
HibiKier 3063c5bc02 Update README.md 2022-01-05 22:57:08 +08:00
226 changed files with 6186 additions and 8519 deletions
-1
View File
@@ -145,4 +145,3 @@ Yu-Gi-Oh/
search_image/
black_word/
csgo/
fantasy_card/
+9 -89
View File
@@ -18,10 +18,6 @@
## 声明
此项目仅用于学习交流,请勿用于非法用途
## Gitee
# [Gitee](https://gitee.com/two_Dimension/zhenxun_bot)
## 未完成的文档
# [传送门](https://hibikier.github.io/zhenxun_bot/)
@@ -29,19 +25,20 @@
## 真寻的帮助
请对真寻说: '真寻帮助' or '管理员帮助' or '超级用户帮助' or '真寻帮助 指令'
## 普通帮助图片
![x](https://github.com/HibiKier/zhenxun_bot/blob/0.0.8.2/docs_image/3238573864-836268675-E2FFBB2AC143EAF4DDDF150438508721.png)
## 提供符合真寻标准的插件仓库
[AkashiCoin/nonebot_plugins_zhenxun_bot](https://github.com/AkashiCoin/nonebot_plugins_zhenxun_bot)
## 来点优点?
一.作为bot:
* 实现了许多功能,且提供了大量功能管理命令
* __..... 更多详细请通过`传送门`查看文档!__
二.作为框架?:
* 通过Config配置项将所有插件配置统计保存至config.yaml,利于统一用户修改
* 方便增删插件,原生nonebot2 matcher,不需要额外修改,仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息`
* 提供了cd,阻塞,每日次数等限制,仅仅通过简单的属性就可以生成一个限制,例如:`__plugin_cd_limit__`
* 基本完善的权限管理
* __..... 更多详细请通过`传送门`查看文档!__
@@ -71,8 +68,6 @@
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
- [x] 原神便笺查询
- [x] 原神玩家查询
- [x] 原神树脂提醒
- [x] 原神签到/自动签到
- [x] 金币红包
- [x] 微博热搜
- [x] B站主播/UP/番剧订阅
@@ -153,7 +148,6 @@
- [x] 清理临时数据
- [x] 增删群认证
- [x] 同意/拒绝好友/群聊请求
- [x] 配置重载
#### 超级用户的被动技能
- [x] 邀请入群提醒(别人邀请真寻入群)
@@ -178,7 +172,6 @@
- [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限
- [x] 群权限系统
- [x] 定时更新权限
- [x] 自动配置重载
</details>
## 详细配置请前往文档,以下为最简部署和配置,如果你有基础并学习过nonebot2的话
@@ -200,14 +193,12 @@ git clone https://github.com/HibiKier/zhenxun_bot.git
cd zhenxun_bot
# 安装依赖
pip install poetry # 安装 poetry
poetry install # 安装依赖
pip install -r requirements.txt
# 进行基础配置
####请查看 配置 部分####
# 开始运行
poetry shell # 进入虚拟环境
python bot.py
```
@@ -227,83 +218,11 @@ python bot.py
```
## 使用Docker
__Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
#### GitHub:[Sakuracio/zxenv](https://github.com/Sakuracio/zxenv)
#### DockerHub:[hibikier/zhenxun_bot](https://hub.docker.com/r/hibikier/zhenxun_bot)
## 更新
### 2022/2/20 \[v0.1.3.1]
* 修复pix下载临时文件目录错误
* 修复AI,天气,发送图片ignore导致无法使用
* 修复纯文本被动技能提醒有时无法删除控制文本
### 2022/2/19 \[v0.1.3] (nonebot beta2!)
* 由于nonebot升级版本,提供更新建议(__该次升级将会导致nonebot.beta1以下的插件无法使用__
* 保证services,utils,configs,plugins,basic_plugins,文件夹均为最新
* 根目录有pyproject.toml与poetry.lock
* 执行命令:
* pip3 install poetry
* poetry install
* poetry shell
* playwright install chromium
* python3 bot.py
* 适配nonebot.beta2
* 删除图片搜索 nonebot_plugin_picsearcher
* 新增图片搜索 search_image
* 替换cos api
* 原神签到树脂提醒新增绑定群里,在某群绑定uid就会在某群发送提醒信息(有好友则私聊,需要重新绑定uid
* 修改update_info.json
* 修复原神资源查询下载数据失败时导致报错
* 优化BuildImage.circle()锯齿问题 [@pull/109](https://github.com/HibiKier/zhenxun_bot/pull/109)
* epic restful 替换 [@pull/119](https://github.com/HibiKier/zhenxun_bot/pull/119)
* fix: 修复远古时期残留的epic推送问题 [@pull/122](https://github.com/HibiKier/zhenxun_bot/pull/122)
### 2021/2/11
* 修复pix不使用反代无法下载图片
### 2021/2/10 \[v0.1.1]
* 修复购买道具出错
### 2021/2/9 \[v0.1]
* 新增原神自动签到和手动签到
* 新增原神树脂提醒
* 新增手动重载Config.yaml命令以及重载配置定时任务(极少部分帮助或配置可能需要重启
* 修改了发送本地图库的matcher,改为on_message
* register_use可以通过返回值发送消息
* 修复修改商品时限制时间出错
* 修复超时商品依旧可以被购买
### 2021/1/16 \[v0.0.9.0]
* Ai提供文本敏感词过滤器
* 疫情插件适配新版腾讯API
* 修复/t回复带空格切分
* 修复原神玩家查询缺少渊下宫和稻妻家园以及角色不完全
* 修复方法 text2image 中 padding 和 font 无法对纯文本生效
* 修复签到图片中信息并未使用配置文件中的色图概率
* 修改原神大地图合成方式,改为先压缩再合成
* bag_user弃用字段props(该字段会在下次更新删除),使用新字段property
* 数据库中所有belonging_group统一修改为group_id
* 商店将registered_use和register_goods更名为register_use何register_goods
* 商品注册提供了kwargs参数提供:
* bot
* event
* 特殊字段
* “send_success_msg”(发送成功的交互信息->即:使用道具 {name} {num} 次成功)
* “_max_num_limit”(该道具单次使用的最多个数,默认1)
### 2021/1/5 \[v0.0.8.2]
### 2021/1/5 \[v0.0.8.0]
* 提供金币消费hook,可在plugins2settings.yaml中配置该功能需要消费的金币
* 商店插件将作为内置插件移动至basic_plugins
@@ -359,6 +278,7 @@ __..... 更多更新信息请查看文档__
## Todo
- [ ] docker容器
- [ ] web管理
## 感谢
@@ -373,5 +293,5 @@ __..... 更多更新信息请查看文档__
[H-K-Y / Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot) :原神bot,这是一个基于nonebot和HoshinoBot的原神娱乐及信息查询插件
[NothAmor / nonebot2_luxun_says](https://github.com/NothAmor/nonebot2_luxun_says) :基于nonebot2机器人框架的鲁迅说插件
[Kyomotoi / AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus) :一个~~特二刺螈~~(文爱)的适用于任何bot的词库
[Ailitonia / omega-miya](https://github.com/Ailitonia/omega-miya) :基于nonebot2的qq机器人
[Ailitonia / omega-miya](https://github.com/Ailitonia/omega-miya) :基于nonebot2的qq机器人
[KimigaiiWuyi / GenshinUID]("https://github.com/KimigaiiWuyi/GenshinUID") :一个基于HoshinoBot/NoneBot2的原神UID查询插件
+1 -1
View File
@@ -1 +1 @@
__version__: v0.1.3.1
__version__: v0.0.8.0
@@ -1,6 +1,7 @@
from nonebot import on_notice
from services.log import logger
from nonebot.adapters.onebot.v11 import GroupAdminNoticeEvent
from nonebot.adapters.cqhttp import Bot, GroupAdminNoticeEvent
from nonebot.typing import T_State
from models.level_user import LevelUser
from models.group_member_info import GroupInfoUser
from configs.config import Config
@@ -15,7 +16,7 @@ admin_notice = on_notice(priority=5)
@admin_notice.handle()
async def _(event: GroupAdminNoticeEvent):
async def _(bot: Bot, event: GroupAdminNoticeEvent, state: T_State):
try:
nickname = (
await GroupInfoUser.get_member_info(event.user_id, event.group_id)
@@ -1,9 +1,9 @@
from nonebot import on_command
from utils.utils import get_message_img
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
from nonebot.params import CommandArg
from ._data_source import custom_group_welcome
from nonebot.adapters.onebot.v11.permission import GROUP
from utils.utils import get_message_text, get_message_imgs
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from .data_source import custom_group_welcome
from nonebot.adapters.cqhttp.permission import GROUP
from configs.config import Config
from services.log import logger
@@ -35,14 +35,14 @@ custom_welcome = on_command(
@custom_welcome.handle()
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
try:
msg = arg.extract_plain_text().strip()
img = get_message_img(event.json())
if not msg and not img:
msg = get_message_text(event.json())
imgs = get_message_imgs(event.json())
if not msg and not imgs:
await custom_welcome.finish(__plugin_usage__)
await custom_welcome.send(
await custom_group_welcome(msg, img, event.user_id, event.group_id),
await custom_group_welcome(msg, imgs, event.user_id, event.group_id),
at_sender=True,
)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 自定义群欢迎消息:{msg}")
@@ -1,319 +1,319 @@
from typing import List
from nonebot.adapters.onebot.v11.message import MessageSegment
from services.log import logger
from configs.path_config import DATA_PATH
from utils.message_builder import image
from utils.utils import get_bot
from pathlib import Path
from models.group_member_info import GroupInfoUser
from datetime import datetime
from services.db_context import db
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 BuildImage
from utils.http_utils import AsyncHttpx
import asyncio
import time
import os
try:
import ujson as json
except ModuleNotFoundError:
import json
async def group_current_status(group_id: int) -> str:
"""
获取当前所有通知的开关
:param group_id: 群号
"""
rst = "[被动技能 状态]\n"
_data = group_manager.get_task_data()
for task in _data.keys():
rst += f'{_data[task]}: {"√" if await group_manager.check_group_task_status(group_id, task) else "×"}\n'
return rst.strip()
custom_welcome_msg_json = (
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
)
async def custom_group_welcome(
msg: str, imgs: List[str], user_id: int, group_id: int
) -> str:
"""
替换群欢迎消息
:param msg: 欢迎消息文本
:param imgs: 欢迎消息图片,只取第一张
:param user_id: 用户id,用于log记录
:param group_id: 群号
"""
img_result = ""
img = imgs[0] if imgs else ""
result = ""
if (DATA_PATH / f"custom_welcome_msg/{group_id}.jpg").exists():
(DATA_PATH / f"custom_welcome_msg/{group_id}.jpg").unlink()
if not custom_welcome_msg_json.exists():
custom_welcome_msg_json.parent.mkdir(parents=True, exist_ok=True)
data = {}
else:
try:
data = json.load(open(custom_welcome_msg_json, "r"))
except FileNotFoundError:
data = {}
try:
if msg:
data[str(group_id)] = str(msg)
json.dump(
data, open(custom_welcome_msg_json, "w"), indent=4, ensure_ascii=False
)
logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息 {msg}")
result += msg
if img:
await AsyncHttpx.download_file(
img, DATA_PATH / "custom_welcome_msg" / f"{group_id}.jpg"
)
img_result = image(abspath=DATA_PATH / "custom_welcome_msg" / f"{group_id}.jpg")
logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息图片")
except Exception as e:
logger.error(f"GROUP {group_id} 替换群消息失败 e:{e}")
return "替换群消息失败.."
return f"替换群欢迎消息成功:\n{result}" + img_result
task_data = None
async def change_group_switch(cmd: str, group_id: int, is_super: bool = False):
global task_data
"""
修改群功能状态
:param cmd: 功能名称
:param group_id: 群号
:param is_super: 是否位超级用户,超级用户用于私聊开关功能状态
"""
if not task_data:
task_data = group_manager.get_task_data()
group_help_file = DATA_PATH / "group_help" / f"{group_id}.png"
status = cmd[:2]
cmd = cmd[2:]
type_ = "plugin"
modules = plugins2settings_manager.get_plugin_module(cmd, True)
if cmd == "全部被动":
for task in task_data:
if status == "开启":
if not await group_manager.check_group_task_status(group_id, task):
await group_manager.open_group_task(group_id, task)
else:
if await group_manager.check_group_task_status(group_id, task):
await group_manager.close_group_task(group_id, task)
if group_help_file.exists():
group_help_file.unlink()
return f"已 {status} 全部被动技能!"
if cmd == "全部功能":
for f in plugins2settings_manager.get_data():
if status == "开启":
group_manager.unblock_plugin(f, group_id)
else:
group_manager.block_plugin(f, group_id)
return f"已 {status} 全部功能!"
if cmd in [task_data[x] for x in task_data.keys()]:
type_ = "task"
modules = [x for x in task_data.keys() if task_data[x] == cmd]
for module in modules:
if is_super:
module = f"{module}:super"
if status == "开启":
if type_ == "task":
if await group_manager.check_group_task_status(group_id, module):
return f"被动 {task_data[module]} 正处于开启状态!不要重复开启."
await group_manager.open_group_task(group_id, module)
else:
if group_manager.get_plugin_status(module, group_id):
return f"功能 {cmd} 正处于开启状态!不要重复开启."
group_manager.unblock_plugin(module, group_id)
else:
if type_ == "task":
if not await group_manager.check_group_task_status(group_id, module):
return f"被动 {task_data[module]} 正处于关闭状态!不要重复关闭."
await group_manager.close_group_task(group_id, module)
else:
if not group_manager.get_plugin_status(module, group_id):
return f"功能 {cmd} 正处于关闭状态!不要重复关闭."
group_manager.block_plugin(module, group_id)
if group_help_file.exists():
group_help_file.unlink()
if is_super:
for file in os.listdir(DATA_PATH / "group_help"):
file = DATA_PATH / "group_help" / file
file.unlink()
else:
_help_image = DATA_PATH / "group_help" / f"{group_id}.png"
if _help_image.exists():
_help_image.unlink()
return f"{status} {cmd} 功能!"
def set_plugin_status(cmd: str, block_type: str = "all"):
"""
设置插件功能状态(超级用户使用)
:param cmd: 功能名称
:param block_type: 限制类型, 'all': 私聊+群里, 'private': 私聊, 'group': 群聊
"""
status = cmd[:2]
cmd = cmd[2:]
module = plugins2settings_manager.get_plugin_module(cmd)
if status == "开启":
plugins_manager.unblock_plugin(module)
else:
plugins_manager.block_plugin(module, block_type=block_type)
for file in os.listdir(DATA_PATH / "group_help"):
file = DATA_PATH / "group_help" / file
file.unlink()
async def get_plugin_status():
"""
获取功能状态
"""
return await asyncio.get_event_loop().run_in_executor(None, _get_plugin_status)
def _get_plugin_status() -> MessageSegment:
"""
合成功能状态图片
"""
rst = "\t功能\n"
flag_str = "状态".rjust(4) + "\n"
for module in plugins_manager.get_data():
flag = plugins_manager.get_plugin_block_type(module)
flag = flag.upper() + " CLOSE" if flag else "OPEN"
try:
plugin_name = plugins_manager.get(module)["plugin_name"]
if (
"[Hidden]" in plugin_name
or "[Admin]" in plugin_name
or "[Superuser]" in plugin_name
):
continue
rst += f"{plugin_name}"
except KeyError:
rst += f"{module}"
if plugins_manager.get(module)["error"]:
rst += "[ERROR]"
rst += "\n"
flag_str += f"{flag}\n"
height = len(rst.split("\n")) * 24
a = BuildImage(250, height, font_size=20)
a.text((10, 10), rst)
b = BuildImage(200, height, font_size=20)
b.text((10, 10), flag_str)
A = BuildImage(500, height)
A.paste(a)
A.paste(b, (270, 0))
return image(b64=A.pic2bs4())
async def update_member_info(group_id: int, remind_superuser: bool = False) -> bool:
"""
更新群成员信息
:param group_id: 群号
:param remind_superuser: 失败信息提醒超级用户
"""
bot = get_bot()
_group_user_list = await bot.get_group_member_list(group_id=group_id)
_error_member_list = []
_exist_member_list = []
# try:
for user_info in _group_user_list:
if user_info["card"] == "":
nickname = user_info["nickname"]
else:
nickname = user_info["card"]
async with db.transaction():
# 更新权限
if (
user_info["role"]
in [
"owner",
"admin",
]
and not await LevelUser.is_group_flag(user_info["user_id"], group_id)
):
await LevelUser.set_level(
user_info["user_id"],
user_info["group_id"],
Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
)
if str(user_info["user_id"]) in bot.config.superusers:
await LevelUser.set_level(
user_info["user_id"], user_info["group_id"], 9
)
user = await GroupInfoUser.get_member_info(
user_info["user_id"], user_info["group_id"]
)
if user:
if user.user_name != nickname:
await user.update(user_name=nickname).apply()
logger.info(
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
)
_exist_member_list.append(int(user_info["user_id"]))
continue
join_time = datetime.strptime(
time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
),
"%Y-%m-%d %H:%M:%S",
)
if await GroupInfoUser.add_member_info(
user_info["user_id"],
user_info["group_id"],
nickname,
join_time,
):
_exist_member_list.append(int(user_info["user_id"]))
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
else:
_error_member_list.append(
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败\n"
)
_del_member_list = list(
set(_exist_member_list).difference(
set(await GroupInfoUser.get_group_member_id_list(group_id))
)
)
if _del_member_list:
for del_user in _del_member_list:
if await GroupInfoUser.delete_member_info(del_user, group_id):
logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
else:
logger.info(f"退群用户{del_user} 所属{group_id} 删除失败")
if _error_member_list and remind_superuser:
result = ""
for error_user in _error_member_list:
result += error_user
await bot.send_private_msg(
user_id=int(list(bot.config.superusers)[0]), message=result[:-1]
)
return True
def set_group_bot_status(group_id: int, status: bool) -> str:
"""
设置群聊bot开关状态
:param group_id: 群号
:param status: 状态
"""
if status:
if group_manager.check_group_bot_status(group_id):
return "我还醒着呢!"
group_manager.turn_on_group_bot_status(group_id)
return "呜..醒来了..."
else:
group_manager.shutdown_group_bot_status(group_id)
# for x in group_manager.get_task_data():
# group_manager.close_group_task(group_id, x)
return "那我先睡觉了..."
from typing import List
from nonebot.adapters.cqhttp.message import MessageSegment
from services.log import logger
from configs.path_config import DATA_PATH
from utils.message_builder import image
from utils.utils import get_local_proxy, get_bot
from pathlib import Path
from models.group_member_info import GroupInfoUser
from datetime import datetime
from services.db_context import db
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 BuildImage
from utils.http_utils import AsyncHttpx
import asyncio
import time
import os
try:
import ujson as json
except ModuleNotFoundError:
import json
async def group_current_status(group_id: int) -> str:
"""
获取当前所有通知的开关
:param group_id: 群号
"""
rst = "[被动技能 状态]\n"
_data = group_manager.get_task_data()
for task in _data.keys():
rst += f'{_data[task]}: {"√" if await group_manager.check_group_task_status(group_id, task) else "×"}\n'
return rst.strip()
custom_welcome_msg_json = (
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
)
async def custom_group_welcome(
msg: str, imgs: List[str], user_id: int, group_id: int
) -> str:
"""
替换群欢迎消息
:param msg: 欢迎消息文本
:param imgs: 欢迎消息图片,只取第一张
:param user_id: 用户id,用于log记录
:param group_id: 群号
"""
img_result = ""
img = imgs[0] if imgs else ""
result = ""
if os.path.exists(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg"):
os.remove(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
if not custom_welcome_msg_json.exists():
custom_welcome_msg_json.parent.mkdir(parents=True, exist_ok=True)
data = {}
else:
try:
data = json.load(open(custom_welcome_msg_json, "r"))
except FileNotFoundError:
data = {}
try:
if msg:
data[str(group_id)] = str(msg)
json.dump(
data, open(custom_welcome_msg_json, "w"), indent=4, ensure_ascii=False
)
logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息 {msg}")
result += msg
if img:
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:
logger.error(f"GROUP {group_id} 替换群消息失败 e:{e}")
return "替换群消息失败.."
return f"替换群欢迎消息成功:\n{result}" + img_result
task_data = None
async def change_group_switch(cmd: str, group_id: int, is_super: bool = False):
global task_data
"""
修改群功能状态
:param cmd: 功能名称
:param group_id: 群号
:param is_super: 是否位超级用户,超级用户用于私聊开关功能状态
"""
if not task_data:
task_data = group_manager.get_task_data()
group_help_file = Path(DATA_PATH) / "group_help" / f"{group_id}.png"
status = cmd[:2]
cmd = cmd[2:]
type_ = "plugin"
modules = plugins2settings_manager.get_plugin_module(cmd, True)
if cmd == "全部被动":
for task in task_data:
if status == "开启":
if not await group_manager.check_group_task_status(group_id, task):
await group_manager.open_group_task(group_id, task)
else:
if await group_manager.check_group_task_status(group_id, task):
await group_manager.close_group_task(group_id, task)
if group_help_file.exists():
group_help_file.unlink()
return f"已 {status} 全部被动技能!"
if cmd == "全部功能":
for f in plugins2settings_manager.get_data():
if status == "开启":
group_manager.unblock_plugin(f, group_id)
else:
group_manager.block_plugin(f, group_id)
return f"已 {status} 全部功能!"
if cmd in [task_data[x] for x in task_data.keys()]:
type_ = "task"
modules = [x for x in task_data.keys() if task_data[x] == cmd]
for module in modules:
if is_super:
module = f"{module}:super"
if status == "开启":
if type_ == "task":
if await group_manager.check_group_task_status(group_id, module):
return f"被动 {task_data[module]} 正处于开启状态!不要重复开启."
await group_manager.open_group_task(group_id, module)
else:
if group_manager.get_plugin_status(module, group_id):
return f"功能 {cmd} 正处于开启状态!不要重复开启."
group_manager.unblock_plugin(module, group_id)
else:
if type_ == "task":
if not await group_manager.check_group_task_status(group_id, module):
return f"被动 {task_data[module]} 正处于关闭状态!不要重复关闭."
await group_manager.close_group_task(group_id, module)
else:
if not group_manager.get_plugin_status(module, group_id):
return f"功能 {cmd} 正处于关闭状态!不要重复关闭."
group_manager.block_plugin(module, group_id)
if group_help_file.exists():
group_help_file.unlink()
if is_super:
for file in os.listdir(Path(DATA_PATH) / "group_help"):
file = Path(DATA_PATH) / "group_help" / file
file.unlink()
else:
_help_image = Path(DATA_PATH) / "group_help" / f"{group_id}.png"
if _help_image.exists():
_help_image.unlink()
return f"{status} {cmd} 功能!"
def set_plugin_status(cmd: str, block_type: str = "all"):
"""
设置插件功能状态(超级用户使用)
:param cmd: 功能名称
:param block_type: 限制类型, 'all': 私聊+群里, 'private': 私聊, 'group': 群聊
"""
status = cmd[:2]
cmd = cmd[2:]
module = plugins2settings_manager.get_plugin_module(cmd)
if status == "开启":
plugins_manager.unblock_plugin(module)
else:
plugins_manager.block_plugin(module, block_type=block_type)
for file in os.listdir(Path(DATA_PATH) / "group_help"):
file = Path(DATA_PATH) / "group_help" / file
file.unlink()
async def get_plugin_status():
"""
获取功能状态
"""
return await asyncio.get_event_loop().run_in_executor(None, _get_plugin_status)
def _get_plugin_status() -> MessageSegment:
"""
合成功能状态图片
"""
rst = "\t功能\n"
flag_str = "状态".rjust(4) + "\n"
for module in plugins_manager.get_data():
flag = plugins_manager.get_plugin_block_type(module)
flag = flag.upper() + " CLOSE" if flag else "OPEN"
try:
plugin_name = plugins_manager.get(module)["plugin_name"]
if (
"[Hidden]" in plugin_name
or "[Admin]" in plugin_name
or "[Superuser]" in plugin_name
):
continue
rst += f"{plugin_name}"
except KeyError:
rst += f"{module}"
if plugins_manager.get(module)["error"]:
rst += "[ERROR]"
rst += "\n"
flag_str += f"{flag}\n"
height = len(rst.split("\n")) * 24
a = BuildImage(250, height, font_size=20)
a.text((10, 10), rst)
b = BuildImage(200, height, font_size=20)
b.text((10, 10), flag_str)
A = BuildImage(500, height)
A.paste(a)
A.paste(b, (270, 0))
return image(b64=A.pic2bs4())
async def update_member_info(group_id: int, remind_superuser: bool = False) -> bool:
"""
更新群成员信息
:param group_id: 群号
:param remind_superuser: 失败信息提醒超级用户
"""
bot = get_bot()
_group_user_list = await bot.get_group_member_list(group_id=group_id)
_error_member_list = []
_exist_member_list = []
# try:
for user_info in _group_user_list:
if user_info["card"] == "":
nickname = user_info["nickname"]
else:
nickname = user_info["card"]
async with db.transaction():
# 更新权限
if (
user_info["role"]
in [
"owner",
"admin",
]
and not await LevelUser.is_group_flag(user_info["user_id"], group_id)
):
await LevelUser.set_level(
user_info["user_id"],
user_info["group_id"],
Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
)
if str(user_info["user_id"]) in bot.config.superusers:
await LevelUser.set_level(
user_info["user_id"], user_info["group_id"], 9
)
user = await GroupInfoUser.get_member_info(
user_info["user_id"], user_info["group_id"]
)
if user:
if user.user_name != nickname:
await user.update(user_name=nickname).apply()
logger.info(
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
)
_exist_member_list.append(int(user_info["user_id"]))
continue
join_time = datetime.strptime(
time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
),
"%Y-%m-%d %H:%M:%S",
)
if await GroupInfoUser.add_member_info(
user_info["user_id"],
user_info["group_id"],
nickname,
join_time,
):
_exist_member_list.append(int(user_info["user_id"]))
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
else:
_error_member_list.append(
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败\n"
)
_del_member_list = list(
set(_exist_member_list).difference(
set(await GroupInfoUser.get_group_member_id_list(group_id))
)
)
if _del_member_list:
for del_user in _del_member_list:
if await GroupInfoUser.delete_member_info(del_user, group_id):
logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
else:
logger.info(f"退群用户{del_user} 所属{group_id} 删除失败")
if _error_member_list and remind_superuser:
result = ""
for error_user in _error_member_list:
result += error_user
await bot.send_private_msg(
user_id=int(list(bot.config.superusers)[0]), message=result[:-1]
)
return True
def set_group_bot_status(group_id: int, status: bool) -> str:
"""
设置群聊bot开关状态
:param group_id: 群号
:param status: 状态
"""
if status:
if group_manager.check_group_bot_status(group_id):
return "我还醒着呢!"
group_manager.turn_on_group_bot_status(group_id)
return "呜..醒来了..."
else:
group_manager.shutdown_group_bot_status(group_id)
# for x in group_manager.get_task_data():
# group_manager.close_group_task(group_id, x)
return "那我先睡觉了..."
+6 -3
View File
@@ -1,4 +1,5 @@
from nonebot.adapters.onebot.v11 import Event
from nonebot.adapters.cqhttp import Bot, Event
from nonebot.typing import T_State
from utils.manager import group_manager, plugins2settings_manager
from utils.utils import get_message_text
from services.log import logger
@@ -6,10 +7,12 @@ from services.log import logger
cmd = []
def switch_rule(event: Event) -> bool:
def switch_rule(bot: Bot, event: Event, state: T_State) -> bool:
"""
检测文本是否是关闭功能命令
:param bot: pass
:param event: pass
:param state: pass
"""
global cmd
try:
@@ -31,7 +34,7 @@ def switch_rule(event: Event) -> bool:
cmd.append(f"关闭 {x}")
except KeyError:
pass
msg = get_message_text(event.json())
msg = get_message_text(event.json()).split()
msg = msg[0] if msg else ""
return msg in cmd
except Exception as e:
+18 -17
View File
@@ -1,8 +1,7 @@
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent, GROUP, Message
from nonebot import on_command, on_message, on_regex
from nonebot.typing import T_State
from nonebot.params import CommandArg
from ._data_source import (
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent, GROUP
from .data_source import (
change_group_switch,
set_plugin_status,
get_plugin_status,
@@ -14,6 +13,7 @@ from configs.config import NICKNAME, Config
from utils.utils import get_message_text, is_number
from nonebot.permission import SUPERUSER
from .rule import switch_rule
import re
__zx_plugin_name__ = "群功能开关 [Admin]"
@@ -65,19 +65,19 @@ group_status = on_regex("^(休息吧|醒来)$", permission=GROUP, priority=5, bl
@switch_rule_matcher.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
_cmd = arg.extract_plain_text().strip().split()[0]
async def _(bot: Bot, event: MessageEvent, state: T_State):
_cmd = get_message_text(event.json()).split()[0]
if isinstance(event, GroupMessageEvent):
await switch_rule_matcher.send(await change_group_switch(_cmd, event.group_id))
logger.info(f"USER {event.user_id} GROUP {event.group_id} 使用群功能管理命令 {_cmd}")
else:
if str(event.user_id) in bot.config.superusers:
block_type = " ".join(arg.extract_plain_text().strip().split()[1:])
block_type = " ".join(get_message_text(event.json()).split()[1:])
block_type = block_type if block_type else "a"
if is_number(block_type):
if not int(block_type) in [
g["group_id"]
for g in await bot.get_group_list()
for g in await bot.get_group_list(self_id=int(bot.self_id))
]:
await switch_rule_matcher.finish(f"{NICKNAME}未加入群聊:{block_type}")
await change_group_switch(_cmd, int(block_type), True)
@@ -104,21 +104,22 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
@plugins_status.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
await plugins_status.send(await get_plugin_status())
@group_task_status.handle()
async def _(event: GroupMessageEvent):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await group_task_status.send(await group_current_status(event.group_id))
@group_status.handle()
async def _(event: GroupMessageEvent, state: T_State):
cmd = state["_matched_groups"][0]
if cmd == "休息吧":
msg = set_group_bot_status(event.group_id, False)
else:
msg = set_group_bot_status(event.group_id, True)
await group_status.send(msg)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 使用总开关命令:{cmd}")
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
r = re.search("^(休息吧|醒来)$", get_message_text(event.json()))
if r:
if r.group(1) == "休息吧":
msg = set_group_bot_status(event.group_id, False)
else:
msg = set_group_bot_status(event.group_id, True)
await group_status.send(msg)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 使用总开关命令:{r.group(1)}")
@@ -1,5 +1,5 @@
from utils.utils import scheduler, get_bot
from ._data_source import update_member_info
from .data_source import update_member_info
from services.log import logger
from models.group_info import GroupInfo
from asyncpg.exceptions import ConnectionDoesNotExistError, UndefinedColumnError
@@ -1,6 +1,7 @@
from nonebot import on_command, on_notice
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
from ._data_source import update_member_info
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
from .data_source import update_member_info
__zx_plugin_name__ = "更新群组成员列表 [Admin]"
__plugin_usage__ = """
@@ -24,7 +25,7 @@ refresh_member_group = on_command(
@refresh_member_group.handle()
async def _(event: GroupMessageEvent):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if await update_member_info(event.group_id):
await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
else:
@@ -35,6 +36,6 @@ group_increase_handle = on_notice(priority=1, block=False)
@group_increase_handle.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
if event.user_id == int(bot.self_id):
await update_member_info(event.group_id)
+1 -1
View File
@@ -1,7 +1,7 @@
from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters import Bot
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from nonebot.adapters.cqhttp import GroupMessageEvent
from utils.message_builder import image
from .data_source import create_help_image, admin_help_image
+6 -5
View File
@@ -3,7 +3,8 @@ from configs.path_config import IMAGE_PATH
from services.log import logger
from utils.utils import get_matchers
from utils.manager import group_manager
from nonebot.adapters.onebot.v11 import Bot
from nonebot.adapters.cqhttp import Bot
from pathlib import Path
from nonebot import Driver
import asyncio
import nonebot
@@ -11,9 +12,9 @@ import nonebot
driver: Driver = nonebot.get_driver()
background = IMAGE_PATH / "background" / "0.png"
background = Path(IMAGE_PATH) / "background" / "0.png"
admin_help_image = IMAGE_PATH / 'admin_help_img.png'
admin_help_image = Path(IMAGE_PATH) / 'admin_help_img.png'
@driver.on_bot_connect
@@ -41,7 +42,7 @@ def _create_help_image():
width = 0
_plugin_level = {}
for matcher in _matchers:
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
_plugin = nonebot.plugin.get_plugin(matcher.module)
_module = _plugin.module
try:
plugin_name = _module.__getattribute__("__zx_plugin_name__")
@@ -70,7 +71,7 @@ def _create_help_image():
x = len(f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)) * 23
width = width if width > x else x
except AttributeError:
logger.warning(f"获取管理插件 {matcher.plugin_name}: {plugin_name} 设置失败...")
logger.warning(f"获取管理插件 {matcher.module}: {plugin_name} 设置失败...")
help_str = "* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" \
"[权限等级] 管理员帮助:\n\n"
x = list(_plugin_level.keys())
+15 -13
View File
@@ -4,7 +4,7 @@ from nonebot import on_message
from services.log import logger
from models.group_info import GroupInfo
from models.friend_user import FriendUser
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.adapters.cqhttp.exception import ActionFailed
from configs.config import NICKNAME, Config
from utils.manager import group_manager
from pathlib import Path
@@ -57,11 +57,12 @@ async def _():
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
for g in gl:
result = image("zao.jpg", "zhenxun")
try:
await bot.send_group_msg(group_id=g, message="[[_task|zwa]]早上好" + result)
except ActionFailed:
logger.warning(f"{g} 群被禁言中,无法发送早安")
if await group_manager.check_group_task_status(g, 'zwa'):
result = image("zao.jpg", "zhenxun")
try:
await bot.send_group_msg(group_id=g, message="早上好" + result)
except ActionFailed:
logger.warning(f"{g} 群被禁言中,无法发送早安")
except Exception as e:
logger.error(f"早晚安错误 e:{e}")
@@ -78,13 +79,14 @@ async def _():
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
for g in gl:
result = image("sleep.jpg", "zhenxun")
try:
await bot.send_group_msg(
group_id=g, message=f"[[_task|zwa]]{NICKNAME}要睡觉了,你们也要早点睡呀" + result
)
except ActionFailed:
logger.warning(f"{g} 群被禁言中,无法发送晚安")
if await group_manager.check_group_task_status(g, 'zwa'):
result = image("sleep.jpg", "zhenxun")
try:
await bot.send_group_msg(
group_id=g, message=f"{NICKNAME}要睡觉了,你们也要早点睡呀" + result
)
except ActionFailed:
logger.warning(f"{g} 群被禁言中,无法发送晚安")
except Exception as e:
logger.error(f"早晚安错误 e:{e}")
+99 -48
View File
@@ -1,13 +1,12 @@
from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent, MessageEvent, Message, Bot
from nonebot.params import CommandArg, Command
from nonebot import on_command
from models.ban_user import BanUser
from models.level_user import LevelUser
from typing import Tuple
from utils.utils import get_message_at, is_number
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot
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
from .data_source import parse_ban_time, a_ban
from services.log import logger
@@ -62,35 +61,62 @@ super_ban = on_command('b了', permission=SUPERUSER, priority=5, block=True)
@ban.handle()
async def _(bot: Bot, event: GroupMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
result = ""
qq = get_message_at(event.json())
if qq:
qq = qq[0]
user_name = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
user_name = user_name['card'] or user_name['nickname']
msg = arg.extract_plain_text().strip()
time = parse_ban_time(msg)
if isinstance(time, str):
await ban.finish(time, at_sender=True)
if cmd in [".ban", "/ban"]:
user_name = user_name['card'] if user_name['card'] else user_name['nickname']
msg = get_message_text(event.json())
if msg:
msg = msg.split()
if len(msg) == 2:
if not is_number(msg[0].strip()) or not is_number(msg[1].strip()):
await ban.finish("参数必须是数字!", at_sender=True)
time = int(msg[0]) * 60 * 60 + int(msg[1]) * 60
else:
if not is_number(msg[0].strip()):
await ban.finish("参数必须是数字!", at_sender=True)
time = int(msg[0]) * 60 * 60
else:
time = -1
if state["_prefix"]["raw_command"] in [".ban", "/ban"]:
if (
await LevelUser.get_user_level(event.user_id, event.group_id)
<= await LevelUser.get_user_level(qq, event.group_id)
and str(event.user_id) not in bot.config.superusers
await LevelUser.get_user_level(event.user_id, event.group_id)
<= await LevelUser.get_user_level(qq, event.group_id)
and str(event.user_id) not in bot.config.superusers
):
await ban.finish(
f"您的权限等级比对方低或相等, {NICKNAME}不能为您使用此功能!",
at_sender=True,
)
result = await a_ban(qq, time, user_name, event)
if await BanUser.ban(
qq, await LevelUser.get_user_level(event.user_id, event.group_id), time
):
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 封禁 时长 {time/60} 分钟"
)
result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
if time != -1:
result += f"将在 {time/60} 分钟后解封"
else:
time = await BanUser.check_ban_time(qq)
if is_number(time):
time = abs(int(time))
if time < 60:
time = str(time) + " 秒"
else:
time = str(int(time / 60)) + " 分钟"
else:
time += " 分钟"
result = f"{user_name} 已在黑名单!预计 {time}后解封"
else:
if (
await BanUser.check_ban_level(
qq, await LevelUser.get_user_level(event.user_id, event.group_id)
)
and str(event.user_id) not in bot.config.superusers
await BanUser.check_ban_level(
qq, await LevelUser.get_user_level(event.user_id, event.group_id)
)
and str(event.user_id) not in bot.config.superusers
):
await ban.finish(
f"ban掉 {user_name} 的管理员权限比您高,无法进行unban", at_sender=True
@@ -104,53 +130,78 @@ async def _(bot: Bot, event: GroupMessageEvent, cmd: Tuple[str, ...] = Command()
result = f"{user_name} 不在黑名单!"
else:
await ban.finish("艾特人了吗??", at_sender=True)
await ban.send(result, at_sender=True)
await ban.finish(result, at_sender=True)
@ban.handle()
async def _(bot: Bot, event: PrivateMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
msg = arg.extract_plain_text().strip()
if msg:
if str(event.user_id) in bot.config.superusers:
if is_number(arg.extract_plain_text().strip().split()[0]):
qq = int(msg[0])
msg = msg[1:]
if cmd in [".ban", "/ban"]:
time = parse_ban_time(msg)
if isinstance(time, str):
await ban.finish(time)
result = await a_ban(qq, time, str(qq), event, 9)
else:
if await BanUser.unban(qq):
logger.info(
f"USER {event.user_id} 将 USER {qq} 解禁"
)
result = f"已经把 {qq} 从黑名单中删除了!"
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
if str(event.user_id) in bot.config.superusers:
msg = get_message_text(event.json())
msg = msg.split()
if is_number(msg[0]):
qq = int(msg[0])
if state["_prefix"]["raw_command"] in [".ban", "/ban"]:
hour = 0
minute = 0
if len(msg) > 1 and is_number(msg[1]):
hour = int(msg[1])
if len(msg) > 2 and is_number(msg[2]):
minute = int(msg[2])
time = hour * 60 * 60 + minute * 60
time = time if time else -1
if await BanUser.ban(
qq, 9, time
):
logger.info(
f"USER {event.user_id} 将 USER {qq} 封禁 时长 {time/60} 分钟"
)
result = f"已经将 {qq} 加入{NICKNAME}的黑名单了!"
if time != -1:
result += f"将在 {time/60} 分钟后解封"
else:
result = f"{qq} 不在黑名单!"
await ban.send(result)
result += f"将在 ∞ 分钟后解封"
await ban.send(result)
else:
time = await BanUser.check_ban_time(qq)
if is_number(time):
time = abs(int(time))
if time < 60:
time = str(time) + " 秒"
else:
time = str(int(time / 60)) + " 分钟"
else:
time += " 分钟"
await ban.send(f"{qq} 已在黑名单!预计 {time}后解封")
else:
await ban.finish('qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?', at_sender=True)
if await BanUser.unban(qq):
logger.info(
f"USER {event.user_id} 将 USER {qq} 解禁"
)
result = f"已经把 {qq} 从黑名单中删除了!"
else:
result = f"{qq} 不在黑名单!"
await ban.send(result)
else:
await ban.finish('qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?', at_sender=True)
@super_ban.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
async def _(bot: Bot, event: MessageEvent, state: T_State):
if isinstance(event, GroupMessageEvent):
qq = get_message_at(event.json())
else:
qq = arg.extract_plain_text().strip()
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)
user_name = user['card'] or user['nickname']
user_name = user['card'] if user['card'] else user['nickname']
if not await BanUser.ban(qq, 10, 99999999):
await BanUser.unban(qq)
await BanUser.ban(qq, 10, 99999999)
await ban.send(f"已将 {user_name} 拉入黑名单!")
else:
await super_ban.send('需要添加被super ban的对象,可以使用at或者指定qq..')
await super_ban.send('需要艾特被super ban的对象..')
-69
View File
@@ -1,69 +0,0 @@
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
from configs.config import NICKNAME
from models.level_user import LevelUser
from utils.utils import is_number
from models.ban_user import BanUser
from services.log import logger
from typing import Union
def parse_ban_time(msg: str) -> Union[int, str]:
"""
解析ban时长
:param msg: 文本消息
"""
if not msg:
return -1
msg = msg.split()
if len(msg) == 1:
if not is_number(msg[0].strip()):
return "参数必须是数字!"
return int(msg[0]) * 60 * 60
else:
if not is_number(msg[0].strip()) or not is_number(msg[1].strip()):
return "参数必须是数字!"
return int(msg[0]) * 60 * 60 + int(msg[1]) * 60
async def a_ban(qq: int, time: int, user_name: str, event: MessageEvent, ban_level: int = None) -> str:
"""
ban
:param qq: qq
:param time: ban时长
:param user_name: ban用户昵称
:param event: event
:param ban_level: ban级别
"""
if isinstance(event, GroupMessageEvent):
ban_level = await LevelUser.get_user_level(event.user_id, event.group_id)
if await BanUser.ban(qq, ban_level, time):
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 封禁 时长 {time / 60} 分钟"
)
result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
if time != -1:
result += f"将在 {time / 60} 分钟后解封"
else:
result += f"将在 ∞ 分钟后解封"
else:
time = await BanUser.check_ban_time(qq)
if is_number(time):
time = abs(int(time))
if time < 60:
time = str(time) + " 秒"
else:
time = str(int(time / 60)) + " 分钟"
else:
time += " 分钟"
result = f"{user_name} 已在黑名单!预计 {time}后解封"
return result
+11 -11
View File
@@ -1,14 +1,13 @@
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters import Bot, Event
from nonebot.permission import SUPERUSER
from nonebot.params import CommandArg
from utils.utils import get_message_img
import asyncio
from utils.utils import get_message_text, get_message_imgs
from services.log import logger
from utils.message_builder import image
from utils.manager import group_manager
from configs.config import Config
import asyncio
__zx_plugin_name__ = "广播 [Superuser]"
__plugin_usage__ = """
@@ -34,13 +33,14 @@ broadcast = on_command("广播-", priority=1, permission=SUPERUSER, block=True)
@broadcast.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
img_list = get_message_img(event.json())
async def _(bot: Bot, event: Event, state: T_State):
msg = get_message_text(event.json())
imgs = get_message_imgs(event.json())
rst = ""
for img in img_list:
for img in imgs:
rst += image(img)
gl = await bot.get_group_list()
sid = bot.self_id
gl = await bot.get_group_list(self_id=sid)
gl = [
g["group_id"]
for g in gl
@@ -56,7 +56,7 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
await broadcast.send(f"已播报至 {int(cnt / g_cnt * 100)}% 的群聊")
x += 0.25
try:
await bot.send_group_msg(group_id=g, message=msg + rst)
await bot.send_group_msg(self_id=sid, group_id=g, message=msg + rst)
logger.info(f"GROUP {g} 投递广播成功")
except Exception as e:
logger.error(f"GROUP {g} 投递广播失败:{type(e)}")
+30 -25
View File
@@ -4,12 +4,12 @@ from utils.message_builder import image
from models.group_member_info import GroupInfoUser
from datetime import datetime
from services.log import logger
from nonebot.adapters.onebot.v11 import (
from nonebot.adapters.cqhttp import (
Bot,
GroupIncreaseNoticeEvent,
GroupDecreaseNoticeEvent,
)
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.adapters.cqhttp.exception import ActionFailed
from utils.manager import group_manager, plugins2settings_manager, requests_manager
from configs.config import NICKNAME
from models.group_info import GroupInfo
@@ -66,7 +66,7 @@ add_group = on_request(priority=1, block=False)
@group_increase_handle.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
if event.user_id == int(bot.self_id):
group = await GroupInfo.get_group_info(event.group_id)
# 群聊不存在或被强制拉群,退出该群
@@ -112,7 +112,9 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
# 群欢迎消息
if _flmt.check(event.group_id):
if await group_manager.check_group_task_status(
event.group_id, "group_welcome"
) and _flmt.check(event.group_id):
_flmt.start_cd(event.group_id)
msg = ""
img = ""
@@ -127,25 +129,23 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
if msg.find("[at]") != -1:
msg = msg.replace("[at]", "")
at_flag = True
if (DATA_PATH / "custom_welcome_msg" / f"{event.group_id}.jpg").exists():
if os.path.exists(DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"):
img = image(
abspath=DATA_PATH / "custom_welcome_msg" / f"{event.group_id}.jpg"
abspath=DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"
)
if msg or img:
msg = msg.strip() + img
msg = "\n" + msg if at_flag else msg
await group_increase_handle.send(
"[[_task|group_welcome]]" + msg, at_sender=at_flag
"\n" + msg.strip() + img, at_sender=at_flag
)
else:
await group_increase_handle.send(
"[[_task|group_welcome]]新人快跑啊!!本群现状↓(快使用自定义!)"
+ image(random.choice(os.listdir(IMAGE_PATH / "qxz")), "qxz")
"新人快跑啊!!本群现状↓(快使用自定义!)"
+ image(random.choice(os.listdir(IMAGE_PATH + "qxz/")), "qxz")
)
@group_decrease_handle.handle()
async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
async def _(bot: Bot, event: GroupDecreaseNoticeEvent, state: dict):
# 被踢出群
if event.sub_type == "kick_me":
group_id = event.group_id
@@ -180,16 +180,21 @@ async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除成功")
else:
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除失败")
rst = ""
if event.sub_type == "leave":
rst = f"{user_name}离开了我们..."
if event.sub_type == "kick":
operator = await bot.get_group_member_info(
user_id=event.operator_id, group_id=event.group_id
)
operator_name = operator["card"] if operator["card"] else operator["nickname"]
rst = f"{user_name} 被 {operator_name} 送走了."
try:
await group_decrease_handle.send(f"[[_task|refund_group_remind]]{rst}")
except ActionFailed:
return
if await group_manager.check_group_task_status(
event.group_id, "refund_group_remind"
):
rst = ""
if event.sub_type == "leave":
rst = f"{user_name}离开了我们..."
if event.sub_type == "kick":
operator = await bot.get_group_member_info(
user_id=event.operator_id, group_id=event.group_id
)
operator_name = (
operator["card"] if operator["card"] else operator["nickname"]
)
rst = f"{user_name} 被 {operator_name} 送走了."
try:
await group_decrease_handle.send(f"{rst}")
except ActionFailed:
return
+9 -9
View File
@@ -1,24 +1,24 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import (
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent,
Message
GroupMessageEvent
)
from nonebot.params import CommandArg
from nonebot.typing import T_State
from nonebot.rule import to_me
from configs.path_config import IMAGE_PATH, DATA_PATH
from utils.message_builder import image
from .data_source import create_help_img, get_plugin_help
from utils.utils import get_message_text
from pathlib import Path
import os
__zx_plugin_name__ = "帮助"
group_help_path = DATA_PATH / "group_help"
help_image = IMAGE_PATH / "help.png"
simple_help_image = IMAGE_PATH / "simple_help.png"
group_help_path = Path(DATA_PATH) / "group_help"
help_image = Path(IMAGE_PATH) / "help.png"
simple_help_image = Path(IMAGE_PATH) / "simple_help.png"
if help_image.exists():
help_image.unlink()
if simple_help_image.exists():
@@ -44,8 +44,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
@simple_help.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
is_super = False
if msg:
if '-super' in msg:
+12 -12
View File
@@ -16,9 +16,9 @@ import nonebot
import os
random_bk_path = IMAGE_PATH / "background" / "help" / "simple_help"
random_bk_path = Path(IMAGE_PATH) / "background" / "help" / "simple_help"
background = IMAGE_PATH / "background" / "0.png"
background = Path(IMAGE_PATH) / "background" / "0.png"
async def create_help_img(
@@ -55,7 +55,7 @@ def _create_help_img(
# 插件分类
for matcher in _matchers:
plugin_name = None
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
_plugin = nonebot.plugin.get_plugin(matcher.module)
_module = _plugin.module
try:
plugin_name = _module.__getattribute__("__zx_plugin_name__")
@@ -74,10 +74,10 @@ def _create_help_img(
plugin_type = ("normal",)
text_type = 0
if plugins2settings_manager.get(
matcher.plugin_name
) and plugins2settings_manager[matcher.plugin_name].get("plugin_type"):
matcher.module
) and plugins2settings_manager[matcher.module].get("plugin_type"):
plugin_type = tuple(
plugins2settings_manager.get_plugin_data(matcher.plugin_name)[
plugins2settings_manager.get_plugin_data(matcher.module)[
"plugin_type"
]
)
@@ -111,7 +111,7 @@ def _create_help_img(
logger.warning(f"{type(e)}: {e}")
else:
matchers_data[plugin_type][plugin_name] = {
"modules": matcher.plugin_name,
"module": matcher.module,
"des": plugin_des,
"cmd": plugin_cmd,
"text_type": text_type,
@@ -129,7 +129,7 @@ def _create_help_img(
_des_tmp[plugin_des] = plugin_name
except AttributeError as e:
if plugin_name not in _plugin_name_tmp:
logger.warning(f"获取功能 {matcher.plugin_name}: {plugin_name} 设置失败...e:{e}")
logger.warning(f"获取功能 {matcher.module}: {plugin_name} 设置失败...e:{e}")
if plugin_name not in _plugin_name_tmp:
_plugin_name_tmp.append(plugin_name)
help_img_list = []
@@ -147,16 +147,16 @@ def _create_help_img(
# 禁用flag
flag = True
if plugins_manager.get_plugin_status(
matchers_data[type_][k]["modules"], "all"
matchers_data[type_][k]["module"], "all"
):
flag = False
if group_id:
flag = flag and plugins_manager.get_plugin_status(
matchers_data[type_][k]["modules"], "group"
matchers_data[type_][k]["module"], "group"
)
simple_help_str += (
f"{i+1}.{k}<|_|~|>"
f"{group_manager.get_plugin_status(matchers_data[type_][k]['modules'], group_id) if group_id else '_'}|"
f"{group_manager.get_plugin_status(matchers_data[type_][k]['module'], group_id) if group_id else '_'}|"
f"{flag}\n"
)
if matchers_data[type_][k]["text_type"] == 1:
@@ -357,7 +357,7 @@ def get_plugin_help(msg: str, is_super: bool = False) -> Optional[str]:
bk = BuildImage(
width,
height,
background=IMAGE_PATH / "background" / "1.png",
background=Path(IMAGE_PATH) / "background" / "1.png",
)
A.paste(bk, alpha=True)
A.text((int(width * 0.048), int(height * 0.21)), result)
+36 -8
View File
@@ -1,6 +1,6 @@
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.adapters.cqhttp.exception import ActionFailed
from models.friend_user import FriendUser
from models.group_member_info import GroupInfoUser
from models.bag_user import BagUser
@@ -13,10 +13,10 @@ from utils.manager import (
plugins2block_manager,
plugins2count_manager
)
from ._utils import set_block_limit_false, status_message_manager
from .utils import set_block_limit_false, status_message_manager
from nonebot.typing import T_State
from typing import Optional
from nonebot.adapters.onebot.v11 import (
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent,
@@ -43,7 +43,7 @@ ignore_rst_module = ["ai", "poke", "dialogue"]
# 权限检测
@run_preprocessor
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
module = matcher.plugin_name
module = matcher.module
plugins2info_dict = plugins2settings_manager.get_data()
# 功能的金币检测 #######################################
# 功能的金币检测 #######################################
@@ -83,7 +83,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
except AttributeError:
pass
# 群黑名单检测 群总开关检测
if isinstance(event, GroupMessageEvent) or matcher.plugin_name == "poke":
if isinstance(event, GroupMessageEvent) or matcher.module == "poke":
try:
if group_manager.get_group_level(event.group_id) < 0:
raise IgnoredException("群黑名单")
@@ -260,6 +260,34 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
# 以下为限制检测 #######################################################
# 以下为限制检测 #######################################################
# 以下为限制检测 #######################################################
# Cd
if plugins2cd_manager.check_plugin_cd_status(module):
plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
check_type = plugin_cd_data["check_type"]
limit_type = plugin_cd_data["limit_type"]
rst = plugin_cd_data["rst"]
if (
(isinstance(event, PrivateMessageEvent) and check_type == "private")
or (isinstance(event, GroupMessageEvent) and check_type == "group")
or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all"
):
cd_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
cd_type_ = event.group_id
if not plugins2cd_manager.check(module, cd_type_):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{module} 正在cd中...")
else:
plugins2cd_manager.start_cd(module, cd_type_)
module = matcher.module
if (
isinstance(event, GroupMessageEvent)
and status_message_manager.get(event.group_id) is None
):
status_message_manager.delete(event.group_id)
# Cd
if plugins2cd_manager.check_plugin_cd_status(module):
plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
@@ -354,15 +382,15 @@ async def _(
event: Event,
state: T_State,
):
if not isinstance(event, MessageEvent) and matcher.plugin_name != "poke":
if not isinstance(event, MessageEvent) and matcher.module != "poke":
return
module = matcher.plugin_name
module = matcher.module
set_block_limit_false(event, module)
async def init_rst(rst: str, event: MessageEvent):
if "[uname]" in rst:
uname = event.sender.card or event.sender.nickname
uname = event.sender.card if event.sender.card else event.sender.nickname
rst = rst.replace("[uname]", uname)
if "[nickname]" in rst:
if isinstance(event, GroupMessageEvent):
+3 -3
View File
@@ -1,8 +1,8 @@
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.adapters.cqhttp.exception import ActionFailed
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import (
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent,
@@ -83,4 +83,4 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
)
except ActionFailed:
pass
raise IgnoredException("用户处于黑名单中")
raise IgnoredException("用户处于黑名单中")
+2 -2
View File
@@ -1,8 +1,8 @@
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.adapters.cqhttp.exception import ActionFailed
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import (
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent,
+4 -3
View File
@@ -1,8 +1,8 @@
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException
from nonebot.typing import T_State
from ._utils import status_message_manager
from nonebot.adapters.onebot.v11 import (
from .utils import status_message_manager
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
PrivateMessageEvent,
@@ -24,7 +24,7 @@ async def _(matcher: Matcher, bot: Bot, event: PrivateMessageEvent, state: T_Sta
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if not isinstance(event, MessageEvent):
return
if matcher.type == "message" and matcher.plugin_name == "ai":
if matcher.type == "message" and matcher.module == "ai":
if (
isinstance(event, GroupMessageEvent)
and not status_message_manager.check(event.group_id)
@@ -35,6 +35,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
isinstance(event, PrivateMessageEvent)
and not status_message_manager.check(event.user_id)
):
print(status_message_manager)
status_message_manager.delete(event.user_id)
raise IgnoredException("有命令就别说话了")
-36
View File
@@ -1,36 +0,0 @@
from nonebot.exception import MockApiException
from nonebot.adapters.onebot.v11 import Bot, MessageSegment
from utils.manager import group_manager
from utils.utils import get_message_text
from typing import Dict, Any
import re
@Bot.on_calling_api
async def handle_api_call(bot: Bot, api: str, data: Dict[str, Any]):
r = None
if (
(api == "send_msg" and data["message"] == "group_id" or api == "send_group_msg")
and (
r := re.search(
"^\[\[_task\|(.*)]]",
data["message"]
if isinstance(data["message"], str)
else get_message_text(data["message"]),
)
)
and r.group(1) in group_manager.get_task_data().keys()
):
task = r.group(1)
group_id = data["group_id"]
if not await group_manager.check_group_task_status(group_id, task):
raise MockApiException(f"被动技能 {task} 处于关闭状态...")
else:
if isinstance(data["message"], str):
msg = data["message"]
msg = msg.replace(f"[[_task|{task}]]", "")
data["message"] = msg
else:
msg = str(data["message"][0])
msg = msg.replace(f"&#91;&#91;_task|{task}&#93;&#93;", "")
data["message"][0] = MessageSegment.text(msg)
+48 -48
View File
@@ -1,48 +1,48 @@
from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent
from utils.manager import plugins2block_manager, StaticData
import time
class StatusMessageManager(StaticData):
def __init__(self):
super().__init__(None)
def add(self, id_: int):
self._data[id_] = time.time()
def delete(self, id_: int):
if self._data.get(id_):
del self._data[id_]
def check(self, id_: int, t: int = 30) -> bool:
if self._data.get(id_):
if time.time() - self._data[id_] > t:
del self._data[id_]
return True
return False
return True
status_message_manager = StatusMessageManager()
def set_block_limit_false(event, module):
"""
设置用户block为false
:param event: event
:param module: 插件模块
"""
if plugins2block_manager.check_plugin_block_status(module):
plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
check_type = plugin_block_data["check_type"]
limit_type = plugin_block_data["limit_type"]
if not (
(isinstance(event, GroupMessageEvent) and check_type == "private")
or (isinstance(event, PrivateMessageEvent) and check_type == "group")
):
block_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
block_type_ = event.group_id
plugins2block_manager.set_false(block_type_, module)
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
from utils.manager import plugins2block_manager, StaticData
import time
class StatusMessageManager(StaticData):
def __init__(self):
super().__init__(None)
def add(self, id_: int):
self._data[id_] = time.time()
def delete(self, id_: int):
if self._data.get(id_):
del self._data[id_]
def check(self, id_: int, t: int = 30) -> bool:
if self._data.get(id_):
if time.time() - self._data[id_] > t:
del self._data[id_]
return True
return False
return True
status_message_manager = StatusMessageManager()
def set_block_limit_false(event, module):
"""
设置用户block为false
:param event: event
:param module: 插件模块
"""
if plugins2block_manager.check_plugin_block_status(module):
plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
check_type = plugin_block_data["check_type"]
limit_type = plugin_block_data["limit_type"]
if not (
(isinstance(event, GroupMessageEvent) and check_type == "private")
or (isinstance(event, PrivateMessageEvent) and check_type == "group")
):
block_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
block_type_ = event.group_id
plugins2block_manager.set_false(block_type_, module)
+2 -2
View File
@@ -2,7 +2,7 @@ from nonebot.matcher import Matcher
from nonebot.message import run_postprocessor
from typing import Optional
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import Bot, Event
from nonebot.adapters.cqhttp import Bot, Event
from utils.manager import withdraw_message_manager
import asyncio
@@ -25,4 +25,4 @@ async def _(
async def _withdraw_message(bot: Bot, id_: int, time: int):
await asyncio.sleep(time)
await bot.delete_msg(message_id=id_)
await bot.delete_msg(message_id=id_, self_id=int(bot.self_id))
+3 -2
View File
@@ -11,7 +11,8 @@ from .init_plugins_limit import (
)
from .init import init
from .check_plugin_status import check_plugin_status
from nonebot.adapters.onebot.v11 import Bot
from utils.manager import admin_manager
from nonebot.adapters.cqhttp import Bot
from configs.path_config import DATA_PATH
from services.log import logger
from pathlib import Path
@@ -33,7 +34,7 @@ def _():
初始化数据
"""
_flag = False
config_file = DATA_PATH / "configs" / "plugins2config.yaml"
config_file = Path(DATA_PATH) / "configs" / "plugins2config.yaml"
if not config_file.exists():
_flag = True
init()
@@ -1,5 +1,5 @@
from utils.manager import plugins_manager
from nonebot.adapters.onebot.v11 import Bot
from nonebot.adapters.cqhttp import Bot
async def check_plugin_status(bot: Bot):
@@ -15,14 +15,14 @@ def init_plugins_config(data_path):
"""
初始化插件数据配置
"""
plugins2config_file = data_path / "configs" / "plugins2config.yaml"
plugins2config_file = Path(data_path) / "configs" / "plugins2config.yaml"
plugins2config_file.parent.mkdir(parents=True, exist_ok=True)
_data = {}
if plugins2config_file.exists():
_data = _yaml.load(open(plugins2config_file, "r", encoding="utf8"))
_matchers = get_matchers()
for matcher in _matchers:
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
_plugin = nonebot.plugin.get_plugin(matcher.module)
try:
_module = _plugin.module
except AttributeError:
@@ -39,16 +39,16 @@ def init_plugins_config(data_path):
if (
plugin_version is None
or (
_data.get(matcher.plugin_name)
and _data[matcher.plugin_name].keys() != plugin_configs.keys()
_data.get(matcher.module)
and _data[matcher.module].keys() != plugin_configs.keys()
)
or plugin_version > plugins_manager.get(matcher.plugin_name)["version"]
or matcher.plugin_name not in _data.keys()
or plugin_version > plugins_manager.get(matcher.module)["version"]
or matcher.module not in _data.keys()
):
for key in plugin_configs:
if isinstance(plugin_configs[key], dict):
Config.add_plugin_config(
matcher.plugin_name,
matcher.module,
key,
plugin_configs[key].get("value"),
help_=plugin_configs[key].get("help"),
@@ -56,12 +56,12 @@ def init_plugins_config(data_path):
_override=True,
)
else:
Config.add_plugin_config(matcher.plugin_name, key, plugin_configs[key])
Config.add_plugin_config(matcher.module, key, plugin_configs[key])
else:
plugin_configs = _data[matcher.plugin_name]
plugin_configs = _data[matcher.module]
for key in plugin_configs:
Config.add_plugin_config(
matcher.plugin_name,
matcher.module,
key,
plugin_configs[key]["value"],
help_=plugin_configs[key]["help"],
@@ -99,10 +99,7 @@ def init_plugins_config(data_path):
if _data.get(plugin) and k in _data[plugin].keys():
Config.set_config(plugin, k, _data[plugin][k])
if level2module := Config.get_level2module(plugin, k):
try:
admin_manager.set_admin_level(level2module, _data[plugin][k])
except KeyError:
logger.warning(f"{level2module} 设置权限等级失败:{_data[plugin][k]}")
admin_manager.set_admin_level(level2module, _data[plugin][k])
_tmp_data[plugin][k] = Config.get_config(plugin, k)
Config.save()
temp_file = Path() / "configs" / "temp_config.yaml"
@@ -17,27 +17,27 @@ def init_plugins_data(data_path):
"""
初始化插件数据信息
"""
plugin2data_file = data_path / "manager" / "plugin_manager.json"
plugin2data_file = Path(data_path) / "manager" / "plugin_manager.json"
plugin2data_file.parent.mkdir(parents=True, exist_ok=True)
_data = {}
if plugin2data_file.exists():
_data = json.load(open(plugin2data_file, "r", encoding="utf8"))
_matchers = get_matchers()
for matcher in _matchers:
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
_plugin = nonebot.plugin.get_plugin(matcher.module)
try:
_module = _plugin.module
except AttributeError:
if matcher.plugin_name not in _data.keys():
if matcher.module not in _data.keys():
plugins_manager.add_plugin_data(
matcher.plugin_name, matcher.plugin_name, error=True
matcher.module, matcher.module, error=True
)
else:
plugins_manager.set_module_data(matcher.plugin_name, "error", True)
plugin_data = plugins_manager.get(matcher.plugin_name)
plugins_manager.set_module_data(matcher.module, "error", True)
plugin_data = plugins_manager.get(matcher.module)
if plugin_data:
plugins_manager.set_module_data(
matcher.plugin_name, "version", plugin_data.get("version")
matcher.module, "version", plugin_data.get("version")
)
else:
try:
@@ -47,36 +47,36 @@ def init_plugins_data(data_path):
try:
plugin_name = _module.__getattribute__("__zx_plugin_name__")
except AttributeError:
plugin_name = matcher.plugin_name
plugin_name = matcher.module
try:
plugin_author = _module.__getattribute__("__plugin_author__")
except AttributeError:
plugin_author = None
if matcher.plugin_name in plugins_manager.keys():
plugins_manager.set_module_data(matcher.plugin_name, "error", False)
if matcher.plugin_name not in plugins_manager.keys():
if matcher.module in plugins_manager.keys():
plugins_manager.set_module_data(matcher.module, "error", False)
if matcher.module not in plugins_manager.keys():
plugins_manager.add_plugin_data(
matcher.plugin_name,
matcher.module,
plugin_name=plugin_name,
author=plugin_author,
version=plugin_version,
)
elif plugins_manager[matcher.plugin_name]["version"] is None or (
elif plugins_manager[matcher.module]["version"] is None or (
plugin_version is not None
and plugin_version > plugins_manager[matcher.plugin_name]["version"]
and plugin_version > plugins_manager[matcher.module]["version"]
):
plugins_manager.set_module_data(
matcher.plugin_name, "plugin_name", plugin_name
matcher.module, "plugin_name", plugin_name
)
plugins_manager.set_module_data(matcher.plugin_name, "author", plugin_author)
plugins_manager.set_module_data(matcher.module, "author", plugin_author)
plugins_manager.set_module_data(
matcher.plugin_name, "version", plugin_version
matcher.module, "version", plugin_version
)
if matcher.plugin_name in _data.keys():
if matcher.module in _data.keys():
plugins_manager.set_module_data(
matcher.plugin_name, "error", _data[matcher.plugin_name]["error"]
matcher.module, "error", _data[matcher.module]["error"]
)
plugins_manager.set_module_data(
matcher.plugin_name, "plugin_name", _data[matcher.plugin_name]["plugin_name"]
matcher.module, "plugin_name", _data[matcher.module]["plugin_name"]
)
plugins_manager.save()
@@ -17,18 +17,18 @@ def init_plugins_cd_limit(data_path):
"""
加载 cd 限制
"""
plugins2cd_file = data_path / "configs" / "plugins2cd.yaml"
plugins2cd_file = Path(data_path) / "configs" / "plugins2cd.yaml"
plugins2cd_file.parent.mkdir(exist_ok=True, parents=True)
_data = {}
_matchers = get_matchers()
for matcher in _matchers:
if not plugins2cd_manager.get_plugin_cd_data(matcher.plugin_name):
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
if not plugins2cd_manager.get_plugin_cd_data(matcher.module):
_plugin = nonebot.plugin.get_plugin(matcher.module)
try:
_module = _plugin.module
plugin_cd_limit = _module.__getattribute__("__plugin_cd_limit__")
plugins2cd_manager.add_cd_limit(
matcher.plugin_name, data_dict=plugin_cd_limit
matcher.module, data_dict=plugin_cd_limit
)
except AttributeError:
pass
@@ -65,18 +65,18 @@ def init_plugins_block_limit(data_path):
"""
加载阻塞限制
"""
plugins2block_file = data_path / "configs" / "plugins2block.yaml"
plugins2block_file = Path(data_path) / "configs" / "plugins2block.yaml"
plugins2block_file.parent.mkdir(exist_ok=True, parents=True)
_data = {}
_matchers = get_matchers()
for matcher in _matchers:
if not plugins2block_manager.get_plugin_block_data(matcher.plugin_name):
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
if not plugins2block_manager.get_plugin_block_data(matcher.module):
_plugin = nonebot.plugin.get_plugin(matcher.module)
try:
_module = _plugin.module
plugin_block_limit = _module.__getattribute__("__plugin_block_limit__")
plugins2block_manager.add_block_limit(
matcher.plugin_name, data_dict=plugin_block_limit
matcher.module, data_dict=plugin_block_limit
)
except AttributeError:
pass
@@ -113,18 +113,18 @@ def init_plugins_count_limit(data_path):
"""
加载次数限制
"""
plugins2count_file = data_path / "configs" / "plugins2count.yaml"
plugins2count_file = Path(data_path) / "configs" / "plugins2count.yaml"
plugins2count_file.parent.mkdir(exist_ok=True, parents=True)
_data = {}
_matchers = get_matchers()
for matcher in _matchers:
if not plugins2count_manager.get_plugin_count_data(matcher.plugin_name):
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
if not plugins2count_manager.get_plugin_count_data(matcher.module):
_plugin = nonebot.plugin.get_plugin(matcher.module)
try:
_module = _plugin.module
plugin_count_limit = _module.__getattribute__("__plugin_count_limit__")
plugins2count_manager.add_count_limit(
matcher.plugin_name, data_dict=plugin_count_limit
matcher.module, data_dict=plugin_count_limit
)
except AttributeError:
pass
@@ -11,13 +11,13 @@ def init_plugins_resources():
"""
_tmp = []
for matcher in get_matchers():
if matcher.plugin_name not in _tmp:
_tmp.append(matcher.plugin_name)
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
if matcher.module not in _tmp:
_tmp.append(matcher.module)
_plugin = nonebot.plugin.get_plugin(matcher.module)
try:
_module = _plugin.module
except AttributeError:
logger.warning(f"插件 {matcher.plugin_name} 加载失败...,资源控制未加载...")
logger.warning(f"插件 {matcher.module} 加载失败...,资源控制未加载...")
else:
try:
resources = _module.__getattribute__("__plugin_resources__")
@@ -26,7 +26,7 @@ def init_plugins_resources():
else:
path = Path(_module.__getattribute__("__file__")).parent
for resource in resources.keys():
resources_manager.add_resource(matcher.plugin_name, path / resource, resources[resource])
resources_manager.add_resource(matcher.module, (path / resource).absolute(), resources[resource])
resources_manager.save()
resources_manager.start_move()
@@ -14,7 +14,7 @@ def init_plugins_settings(data_path: str):
"""
初始化插件设置,从插件中获取 __zx_plugin_name__,__plugin_cmd__,__plugin_settings__
"""
plugins2settings_file = data_path / "configs" / "plugins2settings.yaml"
plugins2settings_file = Path(data_path) / "configs" / "plugins2settings.yaml"
plugins2settings_file.parent.mkdir(exist_ok=True, parents=True)
_matchers = get_matchers()
_tmp_module = {}
@@ -29,12 +29,12 @@ def init_plugins_settings(data_path: str):
logger.warning(f"配置文件 模块:{x} 获取 plugin_name 失败...{e}")
_tmp_module[x] = ""
for matcher in _matchers:
if matcher.plugin_name not in plugins2settings_manager.keys():
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
if matcher.module not in plugins2settings_manager.keys():
_plugin = nonebot.plugin.get_plugin(matcher.module)
try:
_module = _plugin.module
except AttributeError:
logger.warning(f"插件 {matcher.plugin_name} 加载失败...,插件控制未加载.")
logger.warning(f"插件 {matcher.module} 加载失败...,插件控制未加载.")
else:
try:
plugin_name = _module.__getattribute__("__zx_plugin_name__")
@@ -51,23 +51,23 @@ def init_plugins_settings(data_path: str):
if level is None:
level = 5
admin_manager.add_admin_plugin_settings(
matcher.plugin_name, cmd, level
matcher.module, cmd, level
)
if (
"[hidden]" in plugin_name.lower()
or "[admin]" in plugin_name.lower()
or "[superuser]" in plugin_name.lower()
or matcher.plugin_name in plugins2settings_manager.keys()
or matcher.module in plugins2settings_manager.keys()
):
continue
except AttributeError:
if matcher.plugin_name not in _tmp:
if matcher.module not in _tmp:
logger.warning(
f"获取插件 {matcher.plugin_name} __zx_plugin_name__ 失败...,插件控制未加载."
f"获取插件 {matcher.module} __zx_plugin_name__ 失败...,插件控制未加载."
)
else:
try:
_tmp_module[matcher.plugin_name] = plugin_name
_tmp_module[matcher.module] = plugin_name
plugin_settings = _module.__getattribute__(
"__plugin_settings__"
)
@@ -79,13 +79,13 @@ def init_plugins_settings(data_path: str):
):
plugin_settings["cmd"].append(plugin_name)
if plugins2settings_manager.get(
matcher.plugin_name
) and plugins2settings_manager[matcher.plugin_name].get(
matcher.module
) and plugins2settings_manager[matcher.module].get(
"plugin_type"
):
plugin_type = tuple(
plugins2settings_manager.get_plugin_data(
matcher.plugin_name
matcher.module
)["plugin_type"]
)
else:
@@ -95,15 +95,15 @@ def init_plugins_settings(data_path: str):
)
except AttributeError:
plugin_type = ("normal",)
if plugin_settings and matcher.plugin_name:
if plugin_settings and matcher.module:
plugins2settings_manager.add_plugin_settings(
matcher.plugin_name,
matcher.module,
plugin_type=plugin_type,
**plugin_settings,
)
except AttributeError:
pass
_tmp.append(matcher.plugin_name)
_tmp.append(matcher.module)
_tmp_data = {"PluginSettings": plugins2settings_manager.get_data()}
with open(plugins2settings_file, "w", encoding="utf8") as wf:
yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
+5 -5
View File
@@ -1,5 +1,5 @@
from nonebot import on_request, on_message
from nonebot.adapters.onebot.v11 import (
from nonebot.adapters.cqhttp import (
Bot,
FriendRequestEvent,
GroupRequestEvent,
@@ -8,7 +8,7 @@ from nonebot.adapters.onebot.v11 import (
from models.friend_user import FriendUser
from datetime import datetime
from configs.config import NICKNAME, Config
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.adapters.cqhttp.exception import ActionFailed
from utils.manager import requests_manager
from models.group_info import GroupInfo
from utils.utils import scheduler
@@ -31,7 +31,7 @@ exists_data = {"private": {}, "group": {}}
@friend_req.handle()
async def _(bot: Bot, event: FriendRequestEvent):
async def _(bot: Bot, event: FriendRequestEvent, state: dict):
global exists_data
if exists_data["private"].get(event.user_id):
if time.time() - exists_data["private"][event.user_id] < 60 * 5:
@@ -66,7 +66,7 @@ async def _(bot: Bot, event: FriendRequestEvent):
@group_req.handle()
async def _(bot: Bot, event: GroupRequestEvent):
async def _(bot: Bot, event: GroupRequestEvent, state: dict):
global exists_data
if event.sub_type == "invite":
if str(event.user_id) in bot.config.superusers:
@@ -125,7 +125,7 @@ async def _(bot: Bot, event: GroupRequestEvent):
@x.handle()
async def _(event: MessageEvent):
async def _(bot: Bot, event: MessageEvent, state: dict):
await asyncio.sleep(0.1)
r = re.search(r'groupcode="(.*?)"', str(event.get_message()))
if r:
+10 -9
View File
@@ -1,14 +1,15 @@
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, PrivateMessageEvent, Message
from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent
from nonebot.rule import to_me
from utils.utils import get_message_text
from models.group_member_info import GroupInfoUser
from models.friend_user import FriendUser
import random
from models.ban_user import BanUser
from services.log import logger
from configs.config import NICKNAME, Config
from nonebot.params import CommandArg
import random
__zx_plugin_name__ = "昵称系统"
__plugin_usage__ = f"""
@@ -47,8 +48,8 @@ cancel_nickname = on_command("取消昵称", rule=to_me(), priority=5, block=Tru
@nickname.handle()
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
msg = get_message_text(event.json())
if not msg:
await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
if len(msg) > 10:
@@ -102,7 +103,7 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
@my_nickname.handle()
async def _(event: GroupMessageEvent):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
try:
nickname_ = await GroupInfoUser.get_group_member_nickname(
event.user_id, event.group_id
@@ -123,7 +124,7 @@ async def _(event: GroupMessageEvent):
)
)
else:
nickname_ = event.sender.card or event.sender.nickname
nickname_ = event.sender.card if event.sender.card else event.sender.nickname
await my_nickname.send(
random.choice(
["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
@@ -157,7 +158,7 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
@cancel_nickname.handle()
async def _(event: GroupMessageEvent):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
nickname_ = await GroupInfoUser.get_group_member_nickname(
event.user_id, event.group_id
)
@@ -180,7 +181,7 @@ async def _(event: GroupMessageEvent):
@cancel_nickname.handle()
async def _(event: PrivateMessageEvent):
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
nickname_ = await FriendUser.get_friend_nickname(event.user_id)
if nickname_:
await cancel_nickname.send(
+6 -102
View File
@@ -1,19 +1,14 @@
from asyncpg.exceptions import (
DuplicateColumnError,
UndefinedColumnError,
PostgresSyntaxError,
)
from nonebot import Driver
from services.db_context import db
from asyncpg.exceptions import DuplicateColumnError
from models.group_info import GroupInfo
from models.bag_user import BagUser
from nonebot.adapters.onebot.v11 import Bot
from nonebot.adapters.cqhttp import Bot
from services.log import logger
from configs.path_config import TEXT_PATH
from asyncio.exceptions import TimeoutError
from typing import List
from utils.http_utils import AsyncHttpx
from utils.utils import scheduler
from pathlib import Path
import nonebot
try:
@@ -31,7 +26,7 @@ async def update_city():
部分插件需要中国省份城市
这里直接更新,避免插件内代码重复
"""
china_city = TEXT_PATH / "china_city.json"
china_city = Path(TEXT_PATH) / "china_city.json"
data = {}
if not china_city.exists():
try:
@@ -66,86 +61,15 @@ async def _():
"""
数据库表结构变换
"""
_flag = []
sql_str = [
(
"ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;",
"group_info",
), # group_info表添加一个group_flag
(
"ALTER TABLE bag_users rename belonging_group To group_id;",
"bag_users",
), # 将 bag_users 的 belonging_group 改为 group_id
(
"ALTER TABLE group_info_users rename belonging_group To group_id;",
"group_info_users",
),
(
"ALTER TABLE sign_group_users rename belonging_group To group_id;",
"sign_group_users",
),
(
"ALTER TABLE open_cases_users rename belonging_group To group_id;",
"open_cases_users",
),
(
"ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';",
"bag_users",
), # bag_users 新增字段 property 替代 props
(
"ALTER TABLE genshin ADD auto_sign_time timestamp with time zone;",
"genshin"
), # 新增原神自动签到字段
(
"ALTER TABLE genshin ADD resin_remind boolean DEFAULT False;",
"genshin"
), # 新增原神自动签到字段
(
"ALTER TABLE genshin ADD resin_recovery_time timestamp with time zone;",
"genshin"
), # 新增原神自动签到字段
(
"ALTER TABLE genshin ADD bind_group Integer;",
"genshin"
), # 新增原神群号绑定字段
"ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;" # group_info表添加一个group_flag
]
for sql in sql_str:
try:
flag = sql[1]
sql = sql[0]
query = db.text(sql)
await db.first(query)
logger.info(f"完成sql操作:{sql}")
_flag.append(flag)
except (DuplicateColumnError, UndefinedColumnError):
except DuplicateColumnError:
pass
except PostgresSyntaxError:
logger.error(f"语法错误:执行sql失败:{sql}")
# bag_user 将文本转为字典格式
await __database_script(_flag)
# 完成后
end_sql_str = [
# "ALTER TABLE bag_users DROP COLUMN props;" # 删除 bag_users 的 props 字段(还不到时候)
]
for sql in end_sql_str:
try:
query = db.text(sql)
await db.first(query)
logger.info(f"完成执行sql操作:{sql}")
except (DuplicateColumnError, UndefinedColumnError):
pass
except PostgresSyntaxError:
logger.error(f"语法错误:执行sql失败:{sql}")
# str2json_sql = ["alter table bag_users alter COLUMN props type json USING props::json;"] # 字段类型替换
# rename_sql = 'alter table {} rename {} to {};' # 字段更名
# for sql in str2json_sql:
# try:
# query = db.text(sql)
# await db.first(query)
# except DuplicateColumnError:
# pass
@driver.on_bot_connect
@@ -181,26 +105,6 @@ async def _(bot: Bot):
logger.info(f"移除不存在的群聊信息:{group_id}")
async def __database_script(_flag: List[str]):
# bag_user 将文本转为字典格式
if "bag_users" in _flag:
for x in await BagUser.get_all_users():
props = {}
if x.props:
for prop in [p for p in x.props.split(",") if p]:
if props.get(prop):
props[prop] += 1
else:
props[prop] = 1
logger.info(
f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}"
)
await x.update(
property=props,
props="",
).apply()
# 自动更新城市列表
@scheduler.scheduled_job(
"cron",
+18 -26
View File
@@ -1,13 +1,12 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
from nonebot.params import CommandArg
from utils.utils import is_number
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from utils.utils import get_message_text, is_number
from models.bag_user import BagUser
from services.db_context import db
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.adapters.cqhttp.permission import GROUP
from models.goods_info import GoodsInfo
import time
__zx_plugin_name__ = "商店 - 购买道具"
@@ -21,7 +20,7 @@ usage:
""".strip()
__plugin_des__ = "商店 - 购买道具"
__plugin_cmd__ = ["购买 [序号或名称] ?[数量=1]"]
__plugin_type__ = ("商店",)
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
@@ -30,43 +29,36 @@ __plugin_settings__ = {
"limit_superuser": False,
"cmd": ["商店", "购买道具"],
}
__plugin_cd_limit__ = {"cd": 3}
buy = on_command("购买", aliases={"购买道具"}, priority=5, block=True, permission=GROUP)
@buy.handle()
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
goods = None
if arg.extract_plain_text().strip() in ["神秘药水"]:
if get_message_text(event.json()) in ["神秘药水"]:
await buy.finish("你们看看就好啦,这是不可能卖给你们的~", at_sender=True)
goods_list = [
x
for x in await GoodsInfo.get_all_goods()
if x.goods_limit_time > time.time() or x.goods_limit_time == 0
]
goods_name_list = [
x.goods_name
for x in goods_list
]
msg = arg.extract_plain_text().strip().split()
goods_lst = await GoodsInfo.get_all_goods()
goods_name_lst = [x.goods_name for x in goods_lst]
msg = get_message_text(event.json()).split()
num = 1
if len(msg) > 1:
if is_number(msg[1]) and int(msg[1]) > 0:
num = int(msg[1])
else:
await buy.finish("购买的数量要是数字且大于0!", at_sender=True)
# print(msg, num)
if is_number(msg[0]):
msg = int(msg[0])
if msg > len(goods_name_list) or msg < 1:
if msg > len(goods_lst) or msg < 1:
await buy.finish("请输入正确的商品id!", at_sender=True)
goods = goods_list[msg - 1]
goods = goods_lst[msg - 1]
else:
if msg[0] in goods_name_list:
for i in range(len(goods_name_list)):
if msg[0] == goods_name_list[i]:
goods = goods_list[i]
if msg[0] in goods_name_lst:
for i in range(len(goods_name_lst)):
if msg[0] == goods_name_lst[i]:
goods = goods_lst[i]
break
else:
await buy.finish("请输入正确的商品名称!")
@@ -77,7 +69,7 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
await BagUser.get_gold(event.user_id, event.group_id)
) < goods.goods_price * num * goods.goods_discount:
await buy.finish("您的金币好像不太够哦", at_sender=True)
if await BagUser.buy_property(event.user_id, event.group_id, goods, num):
if await BagUser.buy_props(event.user_id, event.group_id, goods, num):
await buy.send(
f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!",
at_sender=True,
+8 -8
View File
@@ -1,11 +1,11 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
from nonebot.params import CommandArg
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from nonebot.adapters.cqhttp.permission import GROUP
from utils.data_utils import init_rank
from models.bag_user import BagUser
from utils.message_builder import image
from utils.utils import is_number
from utils.utils import get_message_text, is_number
__zx_plugin_name__ = "商店 - 我的金币"
__plugin_usage__ = """
@@ -33,13 +33,13 @@ gold_rank = on_command("金币排行", priority=5, block=True, permission=GROUP)
@my_gold.handle()
async def _(event: GroupMessageEvent):
await my_gold.finish(await BagUser.get_user_total_gold(event.user_id, event.group_id))
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await my_gold.finish(await BagUser.get_my_total_gold(event.user_id, event.group_id))
@gold_rank.handle()
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
num = arg.extract_plain_text().strip()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
num = get_message_text(event.json())
if is_number(num) and 51 > int(num) > 10:
num = int(num)
else:
+17 -6
View File
@@ -1,8 +1,9 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from models.bag_user import BagUser
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.adapters.cqhttp.permission import GROUP
__zx_plugin_name__ = "商店 - 我的道具"
@@ -29,12 +30,22 @@ my_props = on_command("我的道具", priority=5, block=True, permission=GROUP)
@my_props.handle()
async def _(event: GroupMessageEvent):
props = await BagUser.get_property(event.user_id, event.group_id)
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
props = await BagUser.get_props(event.user_id, event.group_id)
if props:
pname_list = []
pnum_list = []
rst = ""
for i, p in enumerate(props.keys()):
rst += f"{i+1}.{p}\t×{props[p]}\n"
props = props[:-1].split(",")
for p in props:
if p != "":
if p in pname_list:
pnum_list[pname_list.index(p)] += 1
else:
pname_list.append(p)
pnum_list.append(1)
for i in range(len(pname_list)):
rst += f"{i+1}.{pname_list[i]}\t×{pnum_list[i]}\n"
await my_props.send("\n" + rst[:-1], at_sender=True)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 查看我的道具")
else:
+13 -13
View File
@@ -1,11 +1,11 @@
from .data_source import create_shop_help, delete_goods, update_goods, register_goods, parse_goods_info
from nonebot.adapters.onebot.v11 import MessageEvent, Message
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
from nonebot.typing import T_State
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from .data_source import create_shop_help, delete_goods, update_goods, registered_goods, parse_goods_info
from nonebot.permission import SUPERUSER
from utils.utils import is_number
from nonebot.params import CommandArg
from utils.utils import get_message_text, is_number
from nonebot.plugin import export
from services.log import logger
import os
@@ -53,7 +53,7 @@ __plugin_block_limit__ = {
# 导出方法供其他插件使用
export = export()
export.register_goods = register_goods
export.registered_goods = registered_goods
export.delete_goods = delete_goods
export.update_goods = update_goods
@@ -67,20 +67,20 @@ shop_update_goods = on_command("修改商品", priority=5, permission=SUPERUSER,
@shop_help.handle()
async def _():
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await shop_help.send(image(b64=await create_shop_help()))
@shop_add_goods.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
data = parse_goods_info(msg)
if isinstance(data, str):
await shop_add_goods.finish(data)
if not data.get("name") or not data.get("price") or not data.get("des"):
await shop_add_goods.finish("name:price:des 参数不可缺少!")
if await register_goods(**data):
if await registered_goods(**data):
await shop_add_goods.send(f"添加商品 {data['name']} 成功!\n"
f"名称:{data['name']}\n"
f"价格:{data['price']}金币\n"
@@ -94,8 +94,8 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
@shop_del_goods.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
name = ""
id_ = 0
@@ -115,8 +115,8 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
@shop_update_goods.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
data = parse_goods_info(msg)
if isinstance(data, str):
+25 -13
View File
@@ -20,24 +20,36 @@ async def init_default_shop_goods():
"""
导入内置的三个商品
"""
async def sign_card(**kwargs):
async def sign_card_1(**kwargs):
user_id = kwargs['user_id']
group_id = kwargs['group_id']
prob = kwargs["prob"]
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=prob).apply()
await user.update(add_probability=0.1).apply()
async def sign_card_2(**kwargs):
user_id = kwargs['user_id']
group_id = kwargs['group_id']
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.2).apply()
async def sign_card_3(**kwargs):
user_id = kwargs['user_id']
group_id = kwargs['group_id']
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.3).apply()
if Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS"):
await register_goods(
await registered_goods(
"好感度双倍加持卡Ⅰ", 30, "下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)"
)
use.register_use("好感度双倍加持卡Ⅰ", sign_card, **{"prob": 0.1})
await register_goods("好感度双倍加持卡Ⅱ", 150, "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)")
use.register_use("好感度双倍加持卡Ⅱ", sign_card, **{"prob": 0.2})
await register_goods(
use.registered_use("好感度双倍加持卡Ⅰ", sign_card_1)
await registered_goods("好感度双倍加持卡Ⅱ", 150, "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)")
use.registered_use("好感度双倍加持卡Ⅱ", sign_card_2)
await registered_goods(
"好感度双倍加持卡Ⅲ", 250, "下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)"
)
use.register_use("好感度双倍加持卡Ⅲ", sign_card, **{"prob": 0.3})
use.registered_use("好感度双倍加持卡Ⅲ", sign_card_3)
# 创建商店界面
@@ -124,7 +136,7 @@ async def create_shop_help() -> str:
return shop.pic2bs4()
async def register_goods(
async def registered_goods(
name: str,
price: int,
des: str,
@@ -217,12 +229,11 @@ async def update_goods(**kwargs) -> "str, str, int":
tmp += f'折扣:{discount} --> {kwargs["discount"]}\n'
discount = kwargs["discount"]
if kwargs.get("limit_time"):
kwargs["limit_time"] = float(kwargs["limit_time"])
new_time = time.strftime(
"%Y-%m-%d %H:%M:%S",
time.localtime(time.time() + kwargs["limit_time"] * 60 * 60),
time.localtime(time.time() + int(kwargs["limit_time"] * 60 * 60)),
)
tmp += f"限时至: {new_time}\n"
tmp += f"折扣至: {new_time}\n"
limit_time = kwargs["limit_time"]
return (
await GoodsInfo.update_goods(
@@ -250,6 +261,7 @@ def parse_goods_info(msg: str) -> Union[dict, str]:
sp = x.split(":", maxsplit=1)
if str(sp[1]).strip():
sp[1] = sp[1].strip()
print(sp)
if sp[0] == "name":
data["name"] = sp[1]
elif sp[0] == "price":
+30 -35
View File
@@ -1,13 +1,13 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message
from nonebot.params import CommandArg
from utils.utils import is_number
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from utils.utils import is_number, get_message_text
from models.bag_user import BagUser
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.adapters.cqhttp.permission import GROUP
from services.db_context import db
from nonebot.plugin import export
from .data_source import effect, register_use, func_manager
from .data_source import effect, registered_use
__zx_plugin_name__ = "商店 - 使用道具"
@@ -15,7 +15,7 @@ __plugin_usage__ = """
usage:
普通的使用道具
指令:
使用道具 [序号或道具名称] ?[数量]=1
使用道具 [序号或道具名称]
* 序号以 ”我的道具“ 为准 *
""".strip()
__plugin_des__ = "商店 - 使用道具"
@@ -32,50 +32,45 @@ __plugin_settings__ = {
# 导出方法供其他插件使用
export = export()
export.register_use = register_use
export.registered_use = registered_use
use_props = on_command("使用道具", priority=5, block=True, permission=GROUP)
@use_props.handle()
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
num = 1
msg_sp = msg.split()
if len(msg_sp) > 1 and is_number(msg_sp[-1]) and int(msg_sp[-1]) > 0:
num = int(msg.split()[-1])
msg = " ".join(msg.split()[:-1])
property_ = await BagUser.get_property(event.user_id, event.group_id)
if property_:
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg in ["", "帮助"]:
await use_props.finish(__plugin_usage__)
props = await BagUser.get_props(event.user_id, event.group_id)
if props:
async with db.transaction():
pname_list = []
props = props[:-1].split(",")
for p in props:
if p != "":
if p not in pname_list:
pname_list.append(p)
if is_number(msg):
if 0 < int(msg) <= len(property_):
name = list(property_.keys())[int(msg) - 1]
if 0 < int(msg) <= len(pname_list):
name = pname_list[int(msg) - 1]
else:
await use_props.finish("仔细看看自己的道具仓库有没有这个道具?", at_sender=True)
else:
if msg not in property_.keys():
if msg not in pname_list:
await use_props.finish("道具名称错误!", at_sender=True)
name = msg
_user_prop_count = property_[name]
if num > _user_prop_count:
await use_props.finish(f"道具数量不足,无法使用{num}次!")
if num > (n := func_manager.get_max_num_limit(name)):
await use_props.finish(f"该道具单次只能使用 {n} 个!")
if await BagUser.delete_property(
event.user_id, event.group_id, name, num
):
if func_manager.check_send_success_message(name):
await use_props.send(f"使用道具 {name} {num} 次成功!", at_sender=True)
if msg := await effect(bot, event, name, num):
await use_props.send(msg, at_sender=True)
if await BagUser.del_props(
event.user_id, event.group_id, name
) and await effect(event.user_id, event.group_id, name):
await use_props.send(f"使用道具 {name} 成功!", at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次成功"
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 成功"
)
else:
await use_props.send(f"使用道具 {name} {num} 次失败!", at_sender=True)
await use_props.send(f"使用道具 {name} 失败!", at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次失败"
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 失败"
)
else:
await use_props.send("您的背包里没有任何的道具噢", at_sender=True)
await use_props.send("您的背包里没有任何的道具噢~", at_sender=True)
+23 -99
View File
@@ -1,121 +1,45 @@
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageSegment
from services.log import logger
from nonebot.adapters.onebot.v11 import Bot
from typing import Optional, Union
import asyncio
from services.log import logger
_use_func_data = {}
class GoodsUseFuncManager:
def __init__(self):
self._data = {}
def register_use(self, goods_name: str, **kwargs):
"""
注册商品使用方法
:param goods_name: 商品名称
:param kwargs: kwargs
"""
self._data[goods_name] = kwargs
def exists(self, goods_name: str) -> bool:
"""
判断商品使用方法是否被注册
:param goods_name: 商品名称
"""
return bool(self._data.get(goods_name))
def get_max_num_limit(self, goods_name: str) -> int:
"""
获取单次商品使用数量
:param goods_name: 商品名称
"""
if self.exists(goods_name):
return self._data[goods_name]["kwargs"]["_max_num_limit"]
return 1
async def use(self, **kwargs) -> Optional[Union[str, MessageSegment]]:
"""
使用道具
:param kwargs: kwargs
"""
goods_name = kwargs.get("goods_name")
if self.exists(goods_name):
if asyncio.iscoroutinefunction(self._data[goods_name]["func"]):
return await self._data[goods_name]["func"](
**kwargs,
)
else:
return self._data[goods_name]["func"](
**kwargs,
)
def check_send_success_message(self, goods_name: str) -> bool:
"""
检查是否发送使用成功信息
:param goods_name: 商品名称
"""
if self.exists(goods_name):
return bool(self._data[goods_name]["kwargs"]["send_success_msg"])
return False
def get_kwargs(self, goods_name: str) -> dict:
"""
获取商品使用方法的kwargs
:param goods_name: 商品名称
"""
if self.exists(goods_name):
return self._data[goods_name]["kwargs"]
return {}
func_manager = GoodsUseFuncManager()
async def effect(
bot: Bot, event: GroupMessageEvent, goods_name: str, num: int
) -> Optional[Union[str, MessageSegment]]:
async def effect(user_id: int, group_id: int, goods_name: str) -> bool:
"""
商品生效
:param bot: Bot
:param event: GroupMessageEvent
:param user_id: 用户id
:param group_id: 群号
:param goods_name: 商品名称
:param num: 使用数量
:return: 使用是否成功
"""
# 优先使用注册的商品插件
try:
if func_manager.exists(goods_name):
_kwargs = func_manager.get_kwargs(goods_name)
return await func_manager.use(
**{
if _use_func_data.get(goods_name):
_kwargs = _use_func_data[goods_name]["kwargs"]
_kwargs["goods_name"] = goods_name
_kwargs["user_id"] = user_id
_kwargs["group_id"] = group_id
if asyncio.iscoroutinefunction(_use_func_data[goods_name]["func"]):
await _use_func_data[goods_name]["func"](
**_kwargs,
"_bot": bot,
"event": event,
"group_id": event.group_id,
"user_id": event.user_id,
"num": num,
"goods_name": goods_name,
}
)
)
else:
_use_func_data[goods_name]["func"](
**_kwargs,
)
return True
except Exception as e:
logger.error(f"use 商品生效函数effect 发生错误 {type(e)}:{e}")
return None
return False
def register_use(goods_name: str, func, **kwargs):
def registered_use(goods_name: str, func, **kwargs):
"""
注册商品使用方法
:param goods_name: 商品名称
:param func: 使用函数
:param kwargs: kwargs
"""
if func_manager.exists(goods_name):
if goods_name in _use_func_data.keys():
raise ValueError("该商品使用函数已被注册!")
# 发送使用成功信息
if kwargs.get("send_success_msg") is None:
kwargs["send_success_msg"] = True
kwargs["_max_num_limit"] = (
kwargs.get("_max_num_limit") if kwargs.get("_max_num_limit") else 1
)
func_manager.register_use(goods_name, **{"func": func, "kwargs": kwargs})
logger.info(f"register_use 成功注册商品:{goods_name} 的使用函数")
_use_func_data[goods_name] = {"func": func, "kwargs": kwargs}
+25 -20
View File
@@ -1,10 +1,9 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11 import Bot, Message
from nonebot.params import Command, CommandArg
from typing import Tuple
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent, Message
from nonebot.rule import to_me
from utils.utils import is_number
from utils.utils import get_message_text, is_number
from utils.manager import requests_manager
from utils.message_builder import image
from models.group_info import GroupInfo
@@ -58,30 +57,37 @@ cls_request = on_command("查看所有请求", permission=SUPERUSER, priority=1,
@cls_group.handle()
async def _(bot: Bot):
gl = await bot.get_group_list()
async def _(bot: Bot, event: MessageEvent, state: T_State):
gl = await bot.get_group_list(self_id=int(bot.self_id))
msg = ["{group_id} {group_name}".format_map(g) for g in gl]
msg = "\n".join(msg)
msg = f"bot:{bot.self_id}\n| 群号 | 群名 | 共{len(gl)}个群\n" + msg
await cls_group.send(msg)
await bot.send_private_msg(
self_id=int(bot.self_id),
user_id=int(list(bot.config.superusers)[0]),
message=msg,
)
@cls_friend.handle()
async def _(bot: Bot):
gl = await bot.get_friend_list()
async def _(bot: Bot, event: MessageEvent, state: T_State):
gl = await bot.get_friend_list(self_id=int(bot.self_id))
msg = ["{user_id} {nickname}".format_map(g) for g in gl]
msg = "\n".join(msg)
msg = f"| QQ号 | 昵称 | 共{len(gl)}个好友\n" + msg
await cls_friend.send(msg)
await bot.send_private_msg(
self_id=int(bot.self_id),
user_id=int(list(bot.config.superusers)[0]),
message=msg,
)
@friend_handle.handle()
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
id_ = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
id_ = get_message_text(event.json())
if is_number(id_):
id_ = int(id_)
if cmd[:2] == "同意":
if state["_prefix"]["raw_command"][:2] == "同意":
if await requests_manager.approve(bot, id_, "private"):
await friend_handle.send("同意好友请求成功..")
else:
@@ -96,12 +102,11 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
@group_handle.handle()
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
id_ = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
id_ = get_message_text(event.json())
if is_number(id_):
id_ = int(id_)
if cmd[:2] == "同意":
if state["_prefix"]["raw_command"][:2] == "同意":
rid = await requests_manager.approve(bot, id_, "group")
if rid:
await friend_handle.send("同意群聊请求成功..")
@@ -128,7 +133,7 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
@cls_request.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
_str = ""
for type_ in ["private", "group"]:
msg = await requests_manager.show(type_)
@@ -142,6 +147,6 @@ async def _():
@clear_request.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
requests_manager.clear()
await cls_request.send("已清空所有好友/群聊请求..")
+10 -9
View File
@@ -1,5 +1,7 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from configs.path_config import TEMP_PATH
from nonebot.rule import to_me
from utils.utils import scheduler
@@ -33,7 +35,7 @@ resources_manager.add_temp_dir(TEMP_PATH)
@clear_data.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
await clear_data.send("开始清理临时数据....")
size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
await clear_data.send("共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
@@ -45,14 +47,13 @@ def _clear_data() -> float:
if dir_.exists():
for file in os.listdir(dir_):
file = dir_ / file
if file.is_file():
try:
if time.time() - os.path.getatime(file) > 300:
file_size = os.path.getsize(file)
file.unlink()
size += file_size
except Exception as e:
logger.error(f"清理临时数据错误...{type(e)}:{e}")
try:
if time.time() - os.path.getatime(file) > 300:
file_size = os.path.getsize(file)
file.unlink()
size += file_size
except Exception as e:
logger.error(f"清理临时数据错误...{type(e)}:{e}")
return float(size)
+74
View File
@@ -0,0 +1,74 @@
# async def open_remind(group: int, name: str) -> str:
# _name = ""
# if name == "zwa":
# _name = "早晚安"
# if name == "dz":
# _name = "地震播报"
# if name == "hy":
# _name = "群欢迎"
# if name == "kxcz":
# _name = "开箱重置提醒"
# if name == "gb":
# _name = "广播"
# if await GroupRemind.get_status(group, name):
# return f"该群已经开启过 {_name} 通知,请勿重复开启!"
# if await GroupRemind.set_status(group, name, True):
# return f"成功开启 {_name} 通知!0v0"
# else:
# return f"开启 {_name} 通知失败了..."
#
#
# async def close_remind(group: int, name: str) -> str:
# _name = ""
# if name == "zwa":
# _name = "早晚安"
# if name == "dz":
# _name = "地震播报"
# if name == "hy":
# _name = "群欢迎"
# if name == "kxcz":
# _name = "开箱重置提醒"
# if name == "gb":
# _name = "广播"
# if not await GroupRemind.get_status(group, name):
# return f"该群已经取消过 {_name} 通知,请勿重复取消!"
# if await GroupRemind.set_status(group, name, False):
# return f"成功关闭 {_name} 通知!0v0"
# else:
# return f"关闭 {_name} 通知失败了..."
# cmd_list = ['总开关', '签到', '发送图片', '色图', '黑白草图', 'coser', '鸡汤/语录', '骂我', '开箱', '鲁迅说', '假消息', '商店系统',
# '操作图片', '查询皮肤', '天气', '疫情', '识番', '搜番', '点歌', 'pixiv', 'rss', '方舟一井', '查干员', '骰子娘', '原神一井']
#
#
# def check_group_switch_json(group_id):
# if not os.path.exists(DATA_PATH + f'rule/group_switch/'):
# os.mkdir(DATA_PATH + f'rule/group_switch/')
# if not os.path.exists(DATA_PATH + f'rule/group_switch/{group_id}.json'):
# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'w', encoding='utf8') as f:
# data = {}
# for cmd in cmd_list:
# data[cmd] = True
# f.write(json.dumps(data, ensure_ascii=False))
# else:
# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'r', encoding='utf8') as f:
# try:
# data = json.load(f)
# except ValueError:
# data = {}
# if len(data.keys()) - 1 != len(cmd_list):
# for cmd in cmd_list:
# if cmd not in data.keys():
# data[cmd] = True
# with open(DATA_PATH + f'rule/group_switch/{group_id}.json', 'w', encoding='utf8') as wf:
# wf.write(json.dumps(data, ensure_ascii=False))
# reload(data)
# for file in os.listdir(DATA_PATH + 'group_help'):
# os.remove(DATA_PATH + f'group_help/{file}')
def reload(data):
static_group_dict = data
+5 -4
View File
@@ -1,9 +1,10 @@
from nonebot.adapters.onebot.v11 import Message
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.rule import to_me
from services.db_context import db
from nonebot.params import CommandArg
from utils.utils import get_message_text
from services.log import logger
__zx_plugin_name__ = "执行sql [Superuser]"
@@ -25,8 +26,8 @@ exec_ = on_command("exec", rule=to_me(), permission=SUPERUSER, priority=1, block
@exec_.handle()
async def _(arg: Message = CommandArg()):
sql = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
sql = get_message_text(event.json())
async with db.transaction():
try:
query = db.text(sql)
+19 -23
View File
@@ -1,16 +1,14 @@
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GROUP, GroupMessageEvent, Message
from nonebot import on_command, on_regex
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent, GROUP, GroupMessageEvent
from nonebot.rule import to_me
from utils.utils import is_number
from utils.utils import get_message_text, is_number
from utils.manager import group_manager, plugins2settings_manager
from models.group_info import GroupInfo
from services.log import logger
from configs.config import NICKNAME
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.params import Command, CommandArg
from typing import Tuple
from nonebot.adapters.cqhttp.exception import ActionFailed
__zx_plugin_name__ = "管理群操作 [Superuser]"
@@ -67,8 +65,8 @@ group_auth = on_command(
@del_group.handle()
async def _(bot: Bot, arg: Message = CommandArg()):
group_id = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
group_id = get_message_text(event.json())
if group_id:
if is_number(group_id):
try:
@@ -86,8 +84,8 @@ async def _(bot: Bot, arg: Message = CommandArg()):
@add_group_level.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
group_id = 0
level = 0
if not msg:
@@ -111,7 +109,7 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
@my_group_level.handle()
async def _(event: GroupMessageEvent):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
level = group_manager.get_group_level(event.group_id)
tmp = ""
data = plugins2settings_manager.get_data()
@@ -127,18 +125,17 @@ async def _(event: GroupMessageEvent):
@what_up_group_level.handle()
async def _():
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await what_up_group_level.finish(
f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.管理员修改权限"
)
@manager_group_whitelist.handle()
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json()).split()
all_group = [
g["group_id"] for g in await bot.get_group_list()
g["group_id"] for g in await bot.get_group_list(self_id=int(bot.self_id))
]
group_list = []
for group in msg:
@@ -146,20 +143,20 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
group_list.append(int(group))
if group_list:
for group in group_list:
if cmd in ["添加群白名单"]:
if state["_prefix"]["raw_command"] in ["添加群白名单"]:
group_manager.add_group_white_list(group)
else:
group_manager.delete_group_white_list(group)
group_list = [str(x) for x in group_list]
await manager_group_whitelist.send(
"已成功将 " + "\n".join(group_list) + " " + cmd
"已成功将 " + "\n".join(group_list) + " " + state["_prefix"]["raw_command"]
)
else:
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
@show_group_whitelist.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
x = group_manager.get_group_white_list()
x = [str(g) for g in x]
if x:
@@ -169,14 +166,13 @@ async def _():
@group_auth.handle()
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
msg = arg.extract_plain_text().strip().split()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json()).split()
for group_id in msg:
if not is_number(group_id):
await group_auth.send(f"{group_id}非纯数字,已跳过该项..")
group_id = int(group_id)
if cmd[:2] == "添加":
if state["_prefix"]["raw_command"][:2] == "添加":
if await GroupInfo.get_group_info(group_id):
await GroupInfo.set_group_flag(group_id, 1)
else:
@@ -200,5 +196,5 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
if await GroupInfo.get_group_info(group_id):
await GroupInfo.set_group_flag(group_id, 0)
await group_auth.send(
f'已为 {group_id} {cmd[:2]}群认证..'
f'已为 {group_id} {state["_prefix"]["raw_command"][:2]}群认证..'
)
+3 -31
View File
@@ -7,9 +7,8 @@ from utils.manager import (
plugins2block_manager,
group_manager,
)
from configs.config import Config
from services.log import logger
from utils.utils import scheduler
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
__zx_plugin_name__ = "重载插件配置 [Superuser]"
@@ -29,18 +28,6 @@ __plugin_cmd__ = [
]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_configs__ = {
"AUTO_RELOAD": {
"value": False,
"help": "自动重载配置文件",
"default_value": False
},
"AUTO_RELOAD_TIME": {
"value": 180,
"help": "控制自动重载配置文件时长",
"default_value": 180
}
}
reload_plugins_manager = on_command(
@@ -49,24 +36,9 @@ reload_plugins_manager = on_command(
@reload_plugins_manager.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
plugins2settings_manager.reload()
plugins2cd_manager.reload()
plugins2block_manager.reload()
group_manager.reload()
Config.reload()
await reload_plugins_manager.send("重载完成...")
@scheduler.scheduled_job(
'interval',
seconds=Config.get_config("reload_setting", "AUTO_RELOAD_TIME", 180),
)
async def _():
if Config.get_config("reload_setting", "AUTO_RELOAD"):
plugins2settings_manager.reload()
plugins2cd_manager.reload()
plugins2block_manager.reload()
group_manager.reload()
Config.reload()
logger.debug("已自动重载所有配置文件...")
@@ -1,12 +1,11 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from models.level_user import LevelUser
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message
from utils.utils import get_message_at, is_number
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, Message
from utils.utils import get_message_at, get_message_text, is_number
from services.log import logger
from utils.message_builder import at
from nonebot.params import Command, CommandArg
from typing import Tuple
__zx_plugin_name__ = "用户权限管理 [Superuser]"
__plugin_usage__ = """
@@ -37,12 +36,11 @@ super_cmd = on_command(
@super_cmd.handle()
async def _(bot: Bot, event: GroupMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
group_id = -1
level = 0
try:
args = arg.extract_plain_text().strip().split()
args = get_message_text(event.json()).split()
qq = get_message_at(event.json())
flag = -1
if not qq:
@@ -67,7 +65,7 @@ async def _(bot: Bot, event: GroupMessageEvent, cmd: Tuple[str, ...] = Command()
qq = qq[0]
group_id = event.group_id
flag = 2
if cmd[:2] == "添加":
if state["_prefix"]["raw_command"][:2] == "添加":
if await LevelUser.set_level(qq, group_id, level, 1):
result = "添加管理成功, 权限: " + str(level)
else:
+6 -8
View File
@@ -1,12 +1,11 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.rule import to_me
from utils.utils import is_number
from utils.utils import get_message_text, is_number
from services.log import logger
from utils.manager import group_manager
from nonebot.params import Command, CommandArg
from typing import Tuple
__zx_plugin_name__ = "超级用户被动开关 [Superuser]"
@@ -35,9 +34,8 @@ oc_gb = on_command(
@oc_gb.handle()
async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
group = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
group = get_message_text(event.json())
if group:
if is_number(group):
group = int(group)
@@ -46,7 +44,7 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
break
else:
await oc_gb.finish("没有加入这个群...", at_sender=True)
if cmd == "开启广播通知":
if state["_prefix"]["raw_command"] == "开启广播通知":
logger.info(f"USER {event.user_id} 开启了 GROUP {group} 的广播")
await oc_gb.finish(await group_manager.open_group_task(group, "broadcast",), at_sender=True)
else:
@@ -1,5 +1,7 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.rule import to_me
from utils.utils import get_bot
from services.log import logger
@@ -32,7 +34,7 @@ update_friend_info = on_command(
@update_group_info.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
bot = get_bot()
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
@@ -55,7 +57,7 @@ async def _():
@update_friend_info.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
num = 0
rst = ""
fl = await get_bot().get_friend_list()
+5 -2
View File
@@ -1,15 +1,18 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.adapters import Bot, Event
from nonebot.rule import to_me
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from .data_source import create_help_image
from pathlib import Path
__zx_plugin_name__ = '超级用户帮助 [Superuser]'
superuser_help_image = IMAGE_PATH / 'superuser_help.png'
superuser_help_image = Path(IMAGE_PATH) / 'superuser_help.png'
if superuser_help_image.exists():
superuser_help_image.unlink()
@@ -20,7 +23,7 @@ super_help = on_command(
@super_help.handle()
async def _():
async def _(bot: Bot, event: Event, state: T_State):
if not superuser_help_image.exists():
await create_help_image()
x = image(superuser_help_image)
+6 -5
View File
@@ -2,7 +2,8 @@ from utils.image_utils import BuildImage
from configs.path_config import IMAGE_PATH
from services.log import logger
from utils.utils import get_matchers
from nonebot.adapters.onebot.v11 import Bot
from nonebot.adapters.cqhttp import Bot
from pathlib import Path
from nonebot import Driver
import asyncio
import nonebot
@@ -10,9 +11,9 @@ import nonebot
driver: Driver = nonebot.get_driver()
background = IMAGE_PATH / "background" / "0.png"
background = Path(IMAGE_PATH) / "background" / "0.png"
superuser_help_image = IMAGE_PATH / "superuser_help.png"
superuser_help_image = Path(IMAGE_PATH) / "superuser_help.png"
@driver.on_bot_connect
@@ -35,7 +36,7 @@ def _create_help_image():
for matcher in _matchers:
plugin_name = ""
try:
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
_plugin = nonebot.plugin.get_plugin(matcher.module)
_module = _plugin.module
try:
plugin_name = _module.__getattribute__("__zx_plugin_name__")
@@ -67,7 +68,7 @@ def _create_help_image():
width = width if width > x else x
except Exception as e:
logger.warning(
f"获取超级用户插件 {matcher.plugin_name}: {plugin_name} 设置失败... {type(e)}:{e}"
f"获取超级用户插件 {matcher.module}: {plugin_name} 设置失败... {type(e)}:{e}"
)
height = len(help_str.split("\n")) * 33
width += 500
+3 -1
View File
@@ -1,4 +1,6 @@
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, Event
from nonebot.typing import T_State
from utils.message_builder import image
@@ -25,7 +27,7 @@ update_info = on_command("更新信息", aliases={"更新日志"}, priority=5, b
@update_info.handle()
async def _():
async def _(bot: Bot, event: Event, state: T_State):
img = image("update_info.png")
if img:
await update_info.finish(image("update_info.png"))
+3 -2
View File
@@ -1,10 +1,11 @@
import nonebot
from nonebot.adapters.onebot.v11 import Adapter
from nonebot.adapters.cqhttp import Bot as CQHTTPBot
from services.db_context import init, disconnect
nonebot.init()
driver = nonebot.get_driver()
driver.register_adapter(Adapter)
driver.register_adapter("cqhttp", CQHTTPBot)
config = driver.config
driver.on_startup(init)
driver.on_shutdown(disconnect)
+21 -25
View File
@@ -1,45 +1,41 @@
from pathlib import Path
import os
# 图片路径
IMAGE_PATH = Path() / "resources" / "image"
# 语音路径
RECORD_PATH = Path() / "resources" / "record"
IMAGE_PATH = Path("resources/img/")
# 音频路径
VOICE_PATH = Path("resources/voice/")
# 文本路径
TEXT_PATH = Path() / "resources" / "text"
TEXT_PATH = Path("resources/txt/")
# 日志路径
LOG_PATH = Path() / "log"
LOG_PATH = Path("log/")
# 字体路径
FONT_PATH = Path() / "resources" / "font"
FONT_PATH = Path("resources/ttf/")
# 数据路径
DATA_PATH = Path() / "data"
# 临时数据路径
TEMP_PATH = Path() / "resources" / "temp"
DATA_PATH = Path("data/")
# 临时图片路径
TEMP_PATH = Path("resources/img/temp/")
def load_path():
old_img_dir = Path() / "resources" / "img"
if not IMAGE_PATH.exists() and old_img_dir.exists():
os.rename(old_img_dir, IMAGE_PATH)
old_voice_dir = Path() / "resources" / "voice"
if not RECORD_PATH.exists() and old_voice_dir.exists():
os.rename(old_voice_dir, RECORD_PATH)
old_ttf_dir = Path() / "resources" / "ttf"
if not FONT_PATH.exists() and old_ttf_dir.exists():
os.rename(old_ttf_dir, FONT_PATH)
old_txt_dir = Path() / "resources" / "txt"
if not TEXT_PATH.exists() and old_txt_dir.exists():
os.rename(old_txt_dir, TEXT_PATH)
def init_path():
global IMAGE_PATH, VOICE_PATH, TEXT_PATH, LOG_PATH, FONT_PATH, DATA_PATH, TEMP_PATH
IMAGE_PATH.mkdir(parents=True, exist_ok=True)
RECORD_PATH.mkdir(parents=True, exist_ok=True)
VOICE_PATH.mkdir(parents=True, exist_ok=True)
TEXT_PATH.mkdir(parents=True, exist_ok=True)
LOG_PATH.mkdir(parents=True, exist_ok=True)
FONT_PATH.mkdir(parents=True, exist_ok=True)
DATA_PATH.mkdir(parents=True, exist_ok=True)
TEMP_PATH.mkdir(parents=True, exist_ok=True)
IMAGE_PATH = str(IMAGE_PATH.absolute()) + '/'
VOICE_PATH = str(VOICE_PATH.absolute()) + '/'
TEXT_PATH = str(TEXT_PATH.absolute()) + '/'
LOG_PATH = str(LOG_PATH.absolute()) + '/'
FONT_PATH = str(FONT_PATH.absolute()) + '/'
DATA_PATH = str(DATA_PATH.absolute()) + '/'
TEMP_PATH = str(TEMP_PATH.absolute()) + '/'
load_path()
init_path()
-14
View File
@@ -153,20 +153,6 @@ class ConfigsManager:
self._data, f, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True
)
def reload(self):
"""
重新加载配置文件
"""
_yaml = YAML()
temp_file = Path() / "configs" / "config.yaml"
if temp_file.exists():
with open(temp_file, "r", encoding="utf8") as f:
temp = _yaml.load(f)
for key in temp.keys():
for k in temp[key].keys():
self._data[key][k]["value"] = temp[key][k]
self.save()
def get_admin_level_data(self):
"""
获取管理插件等级
Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 KiB

+74 -59
View File
@@ -1,5 +1,4 @@
from services.db_context import db
from typing import Dict
from typing import Optional, List
from services.log import logger
@@ -8,32 +7,33 @@ class BagUser(db.Model):
__tablename__ = "bag_users"
id = db.Column(db.Integer(), primary_key=True)
user_qq = db.Column(db.BigInteger(), nullable=False)
group_id = db.Column(db.BigInteger(), nullable=False)
belonging_group = db.Column(db.BigInteger(), nullable=False)
gold = db.Column(db.Integer(), default=100)
props = db.Column(db.TEXT(), nullable=False, default="") # 旧道具字段(废弃)
props = db.Column(db.TEXT(), nullable=False, default="")
spend_total_gold = db.Column(db.Integer(), default=0)
get_total_gold = db.Column(db.Integer(), default=0)
get_today_gold = db.Column(db.Integer(), default=0)
spend_today_gold = db.Column(db.Integer(), default=0)
property = db.Column(db.JSON(), nullable=False, default={}) # 新道具字段
_idx1 = db.Index("bag_group_users_idx1", "user_qq", "group_id", unique=True)
_idx1 = db.Index("bag_group_users_idx1", "user_qq", "belonging_group", unique=True)
@classmethod
async def get_user_total_gold(cls, user_qq: int, group_id: int) -> str:
async def get_my_total_gold(cls, user_qq: int, belonging_group: int) -> str:
"""
说明:
获取金币概况
参数:
:param user_qq: qq号
:param group_id: 所在群号
:param belonging_group: 所在群号
"""
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
user = await query.gino.first()
if not user:
user = await cls.create(
user_qq=user_qq,
group_id=group_id,
belonging_group=belonging_group,
)
return (
f"当前金币:{user.gold}\n今日获取金币:{user.get_today_gold}\n今日花费金币:{user.spend_today_gold}"
@@ -42,56 +42,62 @@ class BagUser(db.Model):
)
@classmethod
async def get_gold(cls, user_qq: int, group_id: int) -> int:
async def get_gold(cls, user_qq: int, belonging_group: int) -> int:
"""
说明:
获取当前金币
参数:
:param user_qq: qq号
:param group_id: 所在群号
:param belonging_group: 所在群号
"""
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
user = await query.gino.first()
if user:
return user.gold
else:
await cls.create(
user_qq=user_qq,
group_id=group_id,
belonging_group=belonging_group,
)
return 100
@classmethod
async def get_property(cls, user_qq: int, group_id: int) -> Dict[str, int]:
async def get_props(cls, user_qq: int, belonging_group: int) -> str:
"""
说明:
获取当前道具
参数:
:param user_qq: qq号
:param group_id: 所在群号
:param belonging_group: 所在群号
"""
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
user = await query.gino.first()
if user:
return user.property
return user.props
else:
await cls.create(
user_qq=user_qq,
group_id=group_id,
belonging_group=belonging_group,
)
return {}
return ""
@classmethod
async def add_gold(cls, user_qq: int, group_id: int, num: int):
async def add_gold(cls, user_qq: int, belonging_group: int, num: int):
"""
说明:
增加金币
参数:
:param user_qq: qq号
:param group_id: 所在群号
:param belonging_group: 所在群号
:param num: 金币数量
"""
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
query = query.with_for_update()
user = await query.gino.first()
if user:
@@ -103,23 +109,25 @@ class BagUser(db.Model):
else:
await cls.create(
user_qq=user_qq,
group_id=group_id,
belonging_group=belonging_group,
gold=100 + num,
get_total_gold=num,
get_today_gold=num,
)
@classmethod
async def spend_gold(cls, user_qq: int, group_id: int, num: int):
async def spend_gold(cls, user_qq: int, belonging_group: int, num: int):
"""
说明:
花费金币
参数:
:param user_qq: qq号
:param group_id: 所在群号
:param belonging_group: 所在群号
:param num: 金币数量
"""
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
query = query.with_for_update()
user = await query.gino.first()
if user:
@@ -131,84 +139,91 @@ class BagUser(db.Model):
else:
await cls.create(
user_qq=user_qq,
group_id=group_id,
belonging_group=belonging_group,
gold=100 - num,
spend_total_gold=num,
spend_today_gold=num,
)
@classmethod
async def add_property(cls, user_qq: int, group_id: int, name: str):
async def add_props(cls, user_qq: int, belonging_group: int, name: str):
"""
说明:
增加道具
参数:
:param user_qq: qq号
:param group_id: 所在群号
:param belonging_group: 所在群号
:param name: 道具名称
"""
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
query = query.with_for_update()
user = await query.gino.first()
if user:
p = user.property
if p.get(name) is None:
p[name] = 1
else:
p[name] += 1
await user.update(property=p).apply()
await user.update(props=user.props + f"{name},").apply()
else:
await cls.create(user_qq=user_qq, group_id=group_id, property={name: 1})
await cls.create(
user_qq=user_qq, belonging_group=belonging_group, props=f"{name},"
)
@classmethod
async def delete_property(
cls, user_qq: int, group_id: int, name: str, num: int = 1
) -> bool:
async def del_props(cls, user_qq: int, belonging_group: int, name: str) -> bool:
"""
说明:
使用/删除 道具
使用道具
参数:
:param user_qq: qq号
:param group_id: 所在群号
:param belonging_group: 所在群号
:param name: 道具名称
:param num: 使用个数
"""
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
query = query.with_for_update()
user = await query.gino.first()
if user:
property_ = user.property
if name in property_:
if property_.get(name) == num:
del property_[name]
else:
property_[name] -= num
await user.update(property=property_).apply()
rst = ""
props = user.props
if props.find(name) != -1:
props = props.split(",")
try:
index = props.index(name)
except ValueError:
return False
props = props[:index] + props[index + 1 :]
for p in props:
if p != "":
rst += p + ","
await user.update(props=rst).apply()
return True
return False
else:
return False
else:
return False
@classmethod
async def buy_property(
cls, user_qq: int, group_id: int, goods: "GoodsInfo", goods_num: int
async def buy_props(
cls, user_qq: int, belonging_group: int, goods: "GoodsInfo", goods_num: int
) -> bool:
"""
说明:
购买道具
参数:
:param user_qq: 用户qq
:param group_id: 所在群聊
:param belonging_group: 所在群聊
:param goods: 商品
:param goods_num: 商品数量
"""
try:
# 折扣后金币
spend_gold = goods.goods_discount * goods.goods_price * goods_num
await BagUser.spend_gold(user_qq, group_id, spend_gold)
await BagUser.spend_gold(user_qq, belonging_group, spend_gold)
for _ in range(goods_num):
await BagUser.add_property(user_qq, group_id, goods.goods_name)
await BagUser.add_props(user_qq, belonging_group, goods.goods_name)
return True
except Exception as e:
logger.error(f"buy_property 发生错误 {type(e)}:{e}")
logger.error(f"buy_props 发生错误 {type(e)}:{e}")
return False
@classmethod
@@ -222,5 +237,5 @@ class BagUser(db.Model):
if not group_id:
query = await cls.query.gino.all()
else:
query = await cls.query.where((cls.group_id == group_id)).gino.all()
query = await cls.query.where((cls.belonging_group == group_id)).gino.all()
return query
+30 -32
View File
@@ -10,18 +10,18 @@ class GroupInfoUser(db.Model):
id = db.Column(db.Integer(), primary_key=True)
user_qq = db.Column(db.BigInteger(), nullable=False)
user_name = db.Column(db.Unicode(), nullable=False)
group_id = db.Column(db.BigInteger(), nullable=False)
belonging_group = db.Column(db.BigInteger(), nullable=False)
user_join_time = db.Column(db.DateTime(), nullable=False)
nickname = db.Column(db.Unicode())
uid = db.Column(db.BigInteger())
_idx1 = db.Index("info_group_users_idx1", "user_qq", "group_id", unique=True)
_idx1 = db.Index("info_group_users_idx1", "user_qq", "belonging_group", unique=True)
@classmethod
async def add_member_info(
cls,
user_qq: int,
group_id: int,
belonging_group: int,
user_name: str,
user_join_time: datetime,
uid: Optional[int] = None,
@@ -31,20 +31,20 @@ class GroupInfoUser(db.Model):
添加群内用户信息
参数:
:param user_qq: qq号
:param group_id: 群号
:param belonging_group: 群号
:param user_name: 用户名称
:param user_join_time: 入群时间
:param uid: 用户唯一 id(自动生成)
"""
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
try:
if not await query.gino.first():
await cls.create(
user_qq=user_qq,
user_name=user_name,
group_id=group_id,
belonging_group=belonging_group,
user_join_time=user_join_time,
uid=uid
)
@@ -54,31 +54,31 @@ class GroupInfoUser(db.Model):
@classmethod
async def get_member_info(
cls, user_qq: int, group_id: int
cls, user_qq: int, belonging_group: int
) -> "GroupInfoUser":
"""
说明:
查询群员信息
参数:
:param user_qq: qq号
:param group_id: 群号
:param belonging_group: 群号
"""
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
return await query.gino.first()
@classmethod
async def delete_member_info(cls, user_qq: int, group_id: int) -> bool:
async def delete_member_info(cls, user_qq: int, belonging_group: int) -> bool:
"""
说明:
删除群员信息
参数:
:param user_qq: qq号
:param group_id: 群号
:param belonging_group: 群号
"""
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
query = query.with_for_update()
user = await query.gino.first()
@@ -87,40 +87,40 @@ class GroupInfoUser(db.Model):
return True
else:
await cls.delete.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
).gino.status()
return True
except Exception:
return False
@classmethod
async def get_group_member_id_list(cls, group_id: int) -> List[int]:
async def get_group_member_id_list(cls, belonging_group: int) -> List[int]:
"""
说明:
获取该群所有用户qq
参数:
:param group_id: 群号
:param belonging_group: 群号
"""
member_list = []
query = cls.query.where((cls.group_id == group_id))
query = cls.query.where((cls.belonging_group == belonging_group))
for user in await query.gino.all():
member_list.append(user.user_qq)
return member_list
@classmethod
async def set_group_member_nickname(
cls, user_qq: int, group_id: int, nickname: str
cls, user_qq: int, belonging_group: int, nickname: str
) -> bool:
"""
说明:
设置群员在该群内的昵称
参数:
:param user_qq: qq号
:param group_id: 群号
:param belonging_group: 群号
:param nickname: 昵称
"""
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
user = await query.with_for_update().gino.first()
if user:
@@ -131,27 +131,25 @@ class GroupInfoUser(db.Model):
@classmethod
async def get_user_all_group(cls, user_qq: int) -> List[int]:
"""
说明:
获取该用户所在的所有群聊
参数:
:param user_qq: 用户qq
获取该用户所在的所有群聊
:param user_qq: 用户qq
"""
query = await cls.query.where(cls.user_qq == user_qq).gino.all()
if query:
query = [x.group_id for x in query]
query = [x.belonging_group for x in query]
return query
@classmethod
async def get_group_member_nickname(cls, user_qq: int, group_id: int) -> str:
async def get_group_member_nickname(cls, user_qq: int, belonging_group: int) -> str:
"""
说明:
获取用户在该群的昵称
参数:
:param user_qq: qq号
:param group_id: 群号
:param belonging_group: 群号
"""
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
user = await query.gino.first()
if user:
@@ -165,12 +163,12 @@ class GroupInfoUser(db.Model):
return ""
@classmethod
async def get_group_member_uid(cls, user_qq: int, group_id: int) -> Optional[str]:
async def get_group_member_uid(cls, user_qq: int, belonging_group: int) -> Optional[str]:
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
user = await query.gino.first()
_max_uid = cls.query.where((cls.user_qq == 114514) & (cls.group_id == 114514)).with_for_update()
_max_uid = cls.query.where((cls.user_qq == 114514) & (cls.belonging_group == 114514)).with_for_update()
_max_uid_user = await _max_uid.gino.first()
_max_uid = _max_uid_user.uid
if not user or not user.uid:
@@ -180,9 +178,9 @@ class GroupInfoUser(db.Model):
return x.uid
else:
if not user:
await GroupInfoUser.add_member_info(user_qq, group_id, '', datetime.min)
await GroupInfoUser.add_member_info(user_qq, belonging_group, '', datetime.min)
user = await cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
).gino.first()
await user.update(
uid=_max_uid + 1,
+12 -11
View File
@@ -8,7 +8,8 @@ class SignGroupUser(db.Model):
id = db.Column(db.Integer(), primary_key=True)
user_qq = db.Column(db.BigInteger(), nullable=False)
group_id = db.Column(db.BigInteger(), nullable=False)
belonging_group = db.Column(db.BigInteger(), nullable=False)
checkin_count = db.Column(db.Integer(), nullable=False)
checkin_time_last = db.Column(db.DateTime(timezone=True), nullable=False)
impression = db.Column(db.Numeric(scale=3, asdecimal=False), nullable=False)
@@ -19,29 +20,29 @@ class SignGroupUser(db.Model):
db.Numeric(scale=3, asdecimal=False), nullable=False, default=0
)
_idx1 = db.Index("sign_group_users_idx1", "user_qq", "group_id", unique=True)
_idx1 = db.Index("sign_group_users_idx1", "user_qq", "belonging_group", unique=True)
@classmethod
async def ensure(
cls, user_qq: int, group_id: int, for_update: bool = False
cls, user_qq: int, belonging_group: int, for_update: bool = False
) -> "SignGroupUser":
"""
说明:
获取签到用户
参数:
:param user_qq: 用户qq
:param group_id: 所在群聊
:param belonging_group: 所在群聊
:param for_update: 是否存在修改数据
"""
query = cls.query.where(
(cls.user_qq == user_qq) & (cls.group_id == group_id)
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
)
if for_update:
query = query.with_for_update()
user = await query.gino.first()
return user or await cls.create(
user_qq=user_qq,
group_id=group_id,
belonging_group=belonging_group,
checkin_count=0,
checkin_time_last=datetime.min, # 从未签到过
impression=0,
@@ -78,22 +79,22 @@ class SignGroupUser(db.Model):
).apply()
@classmethod
async def get_all_impression(cls, group_id: int) -> "list, list, list":
async def get_all_impression(cls, belonging_group: int) -> "list, list, list":
"""
说明:
获取该群所有用户 id 及对应 好感度
参数:
:param group_id: 群号
:param belonging_group: 群号
"""
impression_list = []
user_qq_list = []
user_group = []
if group_id:
query = cls.query.where(cls.group_id == group_id)
if belonging_group:
query = cls.query.where(cls.belonging_group == belonging_group)
else:
query = cls.query
for user in await query.gino.all():
impression_list.append(user.impression)
user_qq_list.append(user.user_qq)
user_group.append(user.group_id)
user_group.append(user.belonging_group)
return user_qq_list, impression_list, user_group
+3 -1
View File
@@ -1,4 +1,6 @@
from nonebot import on_regex
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.typing import T_State
from nonebot.rule import to_me
from pathlib import Path
@@ -27,7 +29,7 @@ about = on_regex("^关于$", priority=5, block=True, rule=to_me())
@about.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
ver_file = Path() / '__version__'
version = None
if ver_file.exists():
+10 -9
View File
@@ -1,14 +1,15 @@
import random
from nonebot import on_keyword
import os
from utils.message_builder import image
from configs.path_config import IMAGE_PATH
from nonebot import on_command
from nonebot.rule import to_me
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
from nonebot.adapters.cqhttp.permission import GROUP
from utils.utils import FreqLimiter
from configs.config import NICKNAME
import random
from nonebot import on_keyword
import os
__zx_plugin_name__ = "基本设置 [Hidden]"
@@ -24,12 +25,12 @@ config_play_game = on_keyword({"打游戏"}, permission=GROUP, priority=1, block
@config_play_game.handle()
async def _(event: GroupMessageEvent):
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if not _flmt.check(event.group_id):
return
_flmt.start_cd(event.group_id)
await config_play_game.finish(
image(random.choice(os.listdir(IMAGE_PATH / "dayouxi")), "dayouxi")
image(random.choice(os.listdir(IMAGE_PATH + "dayouxi/")), "dayouxi")
)
@@ -39,7 +40,7 @@ self_introduction = on_command(
@self_introduction.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
if NICKNAME.find('真寻') != -1:
result = (
"我叫绪山真寻\n"
@@ -56,6 +57,6 @@ my_wife = on_keyword({"老婆"}, rule=to_me(), priority=5, block=True)
@my_wife.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
await my_wife.finish(image("laopo.jpg", "other"))
+22 -17
View File
@@ -1,15 +1,17 @@
from nonebot import on_message
from nonebot.adapters.onebot.v11 import (
from nonebot.adapters.cqhttp import (
Bot,
GroupMessageEvent,
Message,
MessageEvent,
)
from nonebot.rule import to_me
from nonebot.typing import T_State
from models.friend_user import FriendUser
from models.group_member_info import GroupInfoUser
from services.log import logger
from utils.utils import get_message_img, get_message_text
from utils.utils import get_message_text, get_message_imgs
from .data_source import get_chat_result, hello, no_result
from configs.config import NICKNAME, Config
@@ -19,35 +21,40 @@ usage:
与{NICKNAME}普普通通的对话吧!
"""
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_author__ = 'HibiKier'
__plugin_settings__ = {
"level": 5,
"cmd": ["Ai", "ai", "AI", "aI"],
}
__plugin_configs__ = {
"TL_KEY": {"value": [], "help": "图灵Key"},
"ALAPI_AI_CHECK": {"value": False, "help": "是否检测青云客骂娘回复", "default_value": False},
"TEXT_FILTER": {
"value": ["鸡", "口交"],
"help": "文本过滤器,将敏感词更改为*",
"default_value": [],
"TL_KEY": {
"value": [],
"help": "图灵Key"
},
"ALAPI_AI_CHECK": {
"value": False,
"help": "是否检测青云客骂娘回复",
"default_value": False
}
}
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.handle()
async def _(bot: Bot, event: MessageEvent):
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
img = get_message_img(event.json())
imgs = get_message_imgs(event.json())
if "CQ:xml" in str(event.get_message()):
return
# 打招呼
if (not msg and not img) or msg in [
if (not msg and not imgs) or msg in [
"你好啊",
"你好",
"在吗",
@@ -58,7 +65,7 @@ async def _(bot: Bot, event: MessageEvent):
"在",
]:
await ai.finish(hello())
img = img[0] if img else ""
img = imgs[0] if imgs else ""
if isinstance(event, GroupMessageEvent):
nickname = await GroupInfoUser.get_group_member_nickname(
event.user_id, event.group_id
@@ -67,7 +74,7 @@ async def _(bot: Bot, event: MessageEvent):
nickname = await FriendUser.get_friend_nickname(event.user_id)
if not nickname:
if isinstance(event, GroupMessageEvent):
nickname = event.sender.card or event.sender.nickname
nickname = event.sender.card if event.sender.card else event.sender.nickname
else:
nickname = event.sender.nickname
result = await get_chat_result(msg, img, event.user_id, nickname)
@@ -76,8 +83,6 @@ async def _(bot: Bot, event: MessageEvent):
f"问题:{msg} ---- 回答:{result}"
)
if result:
for t in Config.get_config("ai", "TEXT_FILTER"):
result = result.replace(t, "*")
await ai.finish(Message(result))
else:
await ai.finish(no_result())
+4 -4
View File
@@ -20,7 +20,7 @@ check_url = "https://v2.alapi.cn/api/censor/text"
index = 0
anime_data = json.load(open(DATA_PATH / "anime.json", "r", encoding="utf8"))
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:
@@ -139,7 +139,7 @@ async def xie_ai(text: str) -> str:
content = content.replace("{br}", "\n")
if "提示" in content:
content = content[: content.find("提示")]
if "淘宝" in content or "taobao.com" in content:
if "淘宝" in content:
return ""
while True:
r = re.search("{face:(.*)}", content)
@@ -170,7 +170,7 @@ def hello() -> str:
"呼呼,叫俺干嘛",
)
)
img = random.choice(os.listdir(IMAGE_PATH / "zai"))
img = random.choice(os.listdir(IMAGE_PATH + "zai/"))
if img[-4:] == ".gif":
result += image(img, "zai")
else:
@@ -193,7 +193,7 @@ def no_result() -> str:
"我!不!知!道!",
]
)
+ image(random.choice(os.listdir(IMAGE_PATH / "noresult")), "noresult")
+ image(random.choice(os.listdir(IMAGE_PATH + "noresult/")), "noresult")
)
+7 -6
View File
@@ -1,6 +1,7 @@
from nonebot import on_regex
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
from ._data_source import get_data
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from nonebot.typing import T_State
from .data_source import get_data
from services.log import logger
__zx_plugin_name__ = "网易云热评"
@@ -22,8 +23,8 @@ __plugin_settings__ = {
}
comments_163 = on_regex(
"^(网易云热评|网易云评论|到点了|12点了)$", priority=5, block=True
comments_163 = on_command(
"网易云热评", aliases={"网易云评论", "到点了", "12点了"}, priority=5, block=True
)
@@ -31,7 +32,7 @@ comments_163_url = "https://v2.alapi.cn/api/comment"
@comments_163.handle()
async def _(event: MessageEvent):
async def _(bot: Bot, event: MessageEvent, state: T_State):
data, code = await get_data(comments_163_url)
if code != 200:
await comments_163.finish(data, at_sender=True)
+6 -5
View File
@@ -1,8 +1,9 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import MessageEvent, Message, GroupMessageEvent
from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
from nonebot.typing import T_State
from utils.message_builder import image
from nonebot.params import CommandArg
from ._data_source import get_data
from utils.utils import get_message_text
from .data_source import get_data
from services.log import logger
__zx_plugin_name__ = "b封面"
@@ -31,8 +32,8 @@ cover_url = "https://v2.alapi.cn/api/bilibili/cover"
@cover.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
params = {"c": msg}
data, code = await get_data(cover_url, params)
if code != 200:
+49 -49
View File
@@ -1,49 +1,49 @@
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 configs.config import Config
from utils.http_utils import AsyncHttpx
async def get_data(url: str, params: Optional[dict] = None) -> Tuple[Union[dict, str], int]:
"""
获取ALAPI数据
:param url: 请求链接
:param params: 参数
"""
if not params:
params = {}
params["token"] = Config.get_config("alapi", "ALAPI_TOKEN")
try:
data = (await AsyncHttpx.get(url, params=params, timeout=5)).json()
if data["code"] == 200:
if not data["data"]:
return "没有搜索到...", 997
return data, 200
else:
return f'发生了错误...code:{data["code"]}', 999
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())
from nonebot.adapters.cqhttp 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
from configs.config import Config
from utils.http_utils import AsyncHttpx
async def get_data(url: str, params: Optional[dict] = None) -> "Union[dict, str], int":
"""
获取ALAPI数据
:param url: 请求链接
:param params: 参数
"""
if not params:
params = {}
params["token"] = Config.get_config("alapi", "ALAPI_TOKEN")
try:
data = (await AsyncHttpx.get(url, params=params, timeout=5)).json()
if data["code"] == 200:
if not data["data"]:
return "没有搜索到...", 997
return data, 200
else:
return f'发生了错误...code:{data["code"]}', 999
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())
+8 -5
View File
@@ -1,7 +1,10 @@
from nonebot import on_regex
from nonebot import on_command
from services.log import logger
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
from ._data_source import get_data
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__ = "鸡汤"
@@ -25,11 +28,11 @@ __plugin_settings__ = {
url = "https://v2.alapi.cn/api/soul"
jitang = on_regex("^毒?鸡汤$", priority=5, block=True)
jitang = on_command("鸡汤", aliases={"毒鸡汤"}, priority=5, block=True)
@jitang.handle()
async def _(event: MessageEvent):
async def _(bot: Bot, event: MessageEvent, state: T_State):
try:
data, code = await get_data(url)
if code != 200:
+4 -3
View File
@@ -1,7 +1,8 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
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
from .data_source import get_data
__zx_plugin_name__ = "古诗"
__plugin_usage__ = """usage:
@@ -26,7 +27,7 @@ poetry_url = "https://v2.alapi.cn/api/shici"
@poetry.handle()
async def _(event: MessageEvent):
async def _(bot: Bot, event: MessageEvent, state: T_State):
data, code = await get_data(poetry_url)
if code != 200:
await poetry.finish(data, at_sender=True)
+7 -6
View File
@@ -1,10 +1,11 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
from nonebot.params import CommandArg
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.utils import is_number
from .data_source import get_data, gen_wbtop_pic
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
@@ -37,9 +38,9 @@ wbtop_data = []
@wbtop.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
async def _(bot: Bot, event: MessageEvent, state: T_State):
global wbtop_data
msg = arg.extract_plain_text().strip()
msg = get_message_text(event.json())
if not wbtop_data or not msg:
data, code = await get_data(wbtop_url)
if code != 200:
+25 -22
View File
@@ -1,6 +1,6 @@
from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
from .data_source import (
add_live_sub,
delete_sub,
@@ -9,15 +9,14 @@ from .data_source import (
get_media_id,
get_sub_status,
SubManager,
BilibiliSub,
BilibiliSub
)
from models.level_user import LevelUser
from configs.config import Config
from utils.utils import is_number, scheduler, get_bot
from utils.utils import get_message_text, is_number, scheduler, get_bot
from typing import Optional
from services.log import logger
from nonebot import Driver
from nonebot.params import CommandArg, ArgPlainText
import nonebot
__zx_plugin_name__ = "B站订阅"
@@ -69,9 +68,18 @@ async def _():
sub_manager = SubManager()
@add_sub.args_parser
async def _(bot: Bot, event: MessageEvent, state: T_State):
season_data = state["season_data"]
msg = get_message_text(event.json())
if not is_number(msg) or int(msg) < 1 or int(msg) > len(season_data):
await add_sub.reject("Id必须为数字且在范围内!请重新输入...")
state["id"] = season_data[int(msg) - 1]["media_id"]
@add_sub.handle()
async def _(event: MessageEvent, state: T_State, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip().split()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json()).split()
if len(msg) < 2:
await add_sub.finish("参数不完全,请查看订阅帮助...")
sub_type = msg[0]
@@ -113,13 +121,10 @@ async def _(event: MessageEvent, state: T_State, arg: Message = CommandArg()):
@add_sub.got("id")
async def _(event: MessageEvent, state: T_State, id_: str = ArgPlainText("id")):
season_data = state["season_data"]
if not is_number(id_) or int(id_) < 1 or int(id_) > len(season_data):
await add_sub.reject_arg("id", "Id必须为数字且在范围内!请重新输入...")
id_ = season_data[int(id_) - 1]["media_id"]
async def _(bot: Bot, event: MessageEvent, state: T_State):
sub_type = state["sub_type"]
sub_user = state["sub_user"]
id_ = state["id"]
if sub_type in ["主播", "直播"]:
await add_sub.send(await add_live_sub(id_, sub_user))
elif sub_type.lower() in ["up", "用户"]:
@@ -136,8 +141,8 @@ async def _(event: MessageEvent, state: T_State, id_: str = ArgPlainText("id")):
@del_sub.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if not is_number(msg):
await del_sub.finish("Id必须为数字!", at_sender=True)
id_ = (
@@ -157,11 +162,12 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
@show_sub_info.handle()
async def _(event: MessageEvent):
if isinstance(event, GroupMessageEvent):
id_ = f"{event.group_id}"
else:
id_ = f"{event.user_id}"
async def _(bot: Bot, event: MessageEvent, state: T_State):
id_ = (
f"{event.user_id}:{event.group_id}"
if isinstance(event, GroupMessageEvent)
else f"{event.user_id}"
)
data = await BilibiliSub.get_sub_data(id_)
live_rst = ""
up_rst = ""
@@ -175,7 +181,6 @@ async def _(event: MessageEvent):
up_rst += f"\tUP:{x.uname}\n" f"\tuid:{x.uid}\n" f"------------------\n"
if x.sub_type == "season":
season_rst += (
f"\t番剧id:{x.sub_id}\n"
f"\t番名:{x.season_name}\n"
f"\t当前集数:{x.season_current_episode}\n"
f"------------------\n"
@@ -184,9 +189,7 @@ async def _(event: MessageEvent):
up_rst = "当前订阅的UP:\n" + up_rst if up_rst else up_rst
season_rst = "当前订阅的番剧:\n" + season_rst if season_rst else season_rst
if not live_rst and not up_rst and not season_rst:
live_rst = (
"该群目前没有任何订阅..." if isinstance(event, GroupMessageEvent) else "您目前没有任何订阅..."
)
live_rst = "您目前没有任何订阅..."
await show_sub_info.send(live_rst + up_rst + season_rst)
+6 -11
View File
@@ -8,6 +8,7 @@ from utils.message_builder import image
from bilibili_api.user import User
from bilibili_api import user
from typing import Optional
from pathlib import Path
from configs.path_config import IMAGE_PATH
from datetime import datetime
from utils.browser import get_browser
@@ -19,7 +20,7 @@ import random
bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
dynamic_path = IMAGE_PATH / "bilibili_sub" / "dynamic"
dynamic_path = Path(IMAGE_PATH) / "bilibili_sub" / "dynamic"
dynamic_path.mkdir(exist_ok=True, parents=True)
@@ -164,9 +165,7 @@ async def get_media_id(keyword: str) -> dict:
for _ in range(3):
try:
_season_data = {}
response = await AsyncHttpx.get(
bilibili_search_url, params=params, timeout=5
)
response = await AsyncHttpx.get(bilibili_search_url, params=params, timeout=5)
if response.status_code == 200:
data = response.json()
if data.get("data"):
@@ -192,6 +191,7 @@ async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
获取订阅状态
:param id_: 订阅 id
:param sub_type: 订阅类型
:return:
"""
try:
if sub_type == "live":
@@ -201,7 +201,7 @@ async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
elif sub_type == "season":
return await _get_season_status(id_)
except ResponseCodeException:
return f"Id:{id_} 获取信息失败...请检查订阅Id是否存在或稍后再试..."
return "获取信息失败...请检查订阅Id是否存在或稍后再试..."
# except Exception as e:
# logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
# return "发生了预料之外的错误..请稍后再试或联系管理员....."
@@ -254,12 +254,7 @@ async def _get_up_status(id_: int) -> Optional[str]:
if dynamic_img:
await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time)
rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n"
if (
latest_video_created
and _user.latest_video_created
and video
and _user.latest_video_created < latest_video_created
):
if _user.latest_video_created < latest_video_created and video:
rst = rst + "-------------\n" if rst else rst
await BilibiliSub.update_sub_info(
id_, latest_video_created=latest_video_created
+2 -1
View File
@@ -1,11 +1,12 @@
from utils.image_utils import BuildImage
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
BORDER_PATH = IMAGE_PATH / "border"
BORDER_PATH = Path(IMAGE_PATH) / "border"
BORDER_PATH.mkdir(parents=True, exist_ok=True)
+36 -27
View File
@@ -1,12 +1,12 @@
from nonebot import on_command
from .data_source import get_bt_info
from services.log import logger
from nonebot.adapters.onebot.v11 import PrivateMessageEvent, Message
from nonebot.adapters.onebot.v11.permission import PRIVATE
from asyncio.exceptions import TimeoutError
from utils.utils import is_number
from nonebot.params import CommandArg, ArgStr
from nonebot.typing import T_State
from nonebot.adapters import Bot
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
__zx_plugin_name__ = "磁力搜索"
__plugin_usage__ = """
@@ -28,7 +28,9 @@ __plugin_settings__ = {
"limit_superuser": False,
"cmd": ["bt", "磁力搜索", "Bt", "BT"],
}
__plugin_block_limit__ = {"rst": "您有bt任务正在进行,请等待结束."}
__plugin_block_limit__ = {
"rst": "您有bt任务正在进行,请等待结束."
}
__plugin_configs__ = {
"BT_MAX_NUM": {
"value": 10,
@@ -41,37 +43,44 @@ __plugin_configs__ = {
bt = on_command("bt", permission=PRIVATE, priority=5, block=True)
@bt.args_parser
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
if str(event.get_message()) in ["取消", "算了"]:
await bt.finish("已取消操作..", at_sender=True)
msg = get_message_text(event.json())
if not msg:
await bt.reject("你想搜索什么呢?", at_sender=True)
state["keyword"] = msg
state["page"] = "1"
@bt.handle()
async def _(state: T_State, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip().split()
if msg:
keyword = None
page = 1
if n := len(msg):
keyword = msg[0]
if n > 1 and is_number(msg[1]) and int(msg[1]) > 0:
page = int(msg[1])
state["keyword"] = keyword
state["page"] = page
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
mp = get_message_text(event.json())
if not mp:
return
mp = mp.split()
if len(mp) == 2:
state["keyword"] = mp[0]
state["page"] = mp[1]
else:
state["page"] = 1
state["keyword"] = mp[0]
state["page"] = "1"
@bt.got("keyword", prompt="请输入要查询的内容!")
async def _(
event: PrivateMessageEvent,
state: T_State,
keyword: str = ArgStr("keyword"),
page: str = ArgStr("page"),
):
@bt.got("keyword", prompt="虚空磁力?查什么GKD")
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
keyword = state["keyword"]
page = state["page"]
await bt.send("开始搜索....", at_sender=True)
send_flag = False
try:
async for title, type_, create_time, file_size, link in get_bt_info(
async for title, itype, create_time, file_size, link in get_bt_info(
keyword, page
):
await bt.send(
f"标题:{title}\n"
f"类型:{type_}\n"
f"类型:{itype}\n"
f"创建时间:{create_time}\n"
f"文件大小:{file_size}\n"
f"种子:{link}"
+3 -3
View File
@@ -12,7 +12,7 @@ if platform.system() == "Windows":
url = "http://www.eclzz.world"
async def get_bt_info(keyword: str, page: int):
async def get_bt_info(keyword: str, page: str):
"""
获取资源信息
:param keyword: 关键词
@@ -34,11 +34,11 @@ async def get_bt_info(keyword: str, page: int):
.strip()
)
spans = divs[2].find_all("span")
type_ = spans[0].text
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"])
yield title, type_, create_time, file_size, link
yield title, itype, create_time, file_size, link
async def get_download_link(_url: str) -> str:
+3 -4
View File
@@ -1,6 +1,5 @@
from .music_163 import get_song_id, get_song_info
from nonebot.adapters.onebot.v11 import Bot, Event, GroupMessageEvent, Message
from nonebot.params import CommandArg
from nonebot.adapters.cqhttp import Bot, Event, GroupMessageEvent
from nonebot.typing import T_State
from services.log import logger
from nonebot import on_command
@@ -30,8 +29,8 @@ music = on_command("点歌", priority=5, block=True)
@music.handle()
async def handle_first_receive(state: T_State, arg: Message = CommandArg()):
args = arg.extract_plain_text().strip()
async def handle_first_receive(bot: Bot, event: Event, state: T_State):
args = str(event.get_message()).strip()
if args:
state["song_name"] = args
+3 -1
View File
@@ -1,5 +1,7 @@
from nonebot import on_command
from .data_source import Check
from nonebot.adapters.cqhttp import Bot, Event
from nonebot.typing import T_State
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
from utils.message_builder import image
@@ -27,5 +29,5 @@ check_ = on_command(
@check_.handle()
async def _():
async def _(bot: Bot, event: Event, state: T_State):
await check_.send(image(b64=await check.show()))
+2 -1
View File
@@ -4,6 +4,7 @@ from datetime import datetime
from utils.http_utils import AsyncHttpx
from utils.image_utils import BuildImage
from configs.path_config import IMAGE_PATH
from pathlib import Path
import asyncio
from services.log import logger
@@ -72,6 +73,6 @@ class Check:
A.transparent(1)
A.text((10, 10), rst)
_x = max(width, height)
bk = BuildImage(_x + 100, _x + 100, background=IMAGE_PATH / "background" / "check" / "0.jpg")
bk = BuildImage(_x + 100, _x + 100, background=Path(IMAGE_PATH) / "background" / "check" / "0.jpg")
bk.paste(A, alpha=True, center_type='center')
return bk.pic2bs4()
+6 -5
View File
@@ -1,4 +1,4 @@
from nonebot.adapters.onebot.v11 import Bot
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.typing import T_State
from nonebot.permission import SUPERUSER
from nonebot import on_command
@@ -45,7 +45,7 @@ restart = on_command(
@update_zhenxun.handle()
async def _(bot: Bot):
async def _(bot: Bot, event: MessageEvent, state: T_State):
try:
code, error = await check_update(bot)
if error:
@@ -67,13 +67,13 @@ async def _(bot: Bot):
@restart.handle()
async def _():
async def _(bot: Bot, event: MessageEvent, state: T_State):
if str(platform.system()).lower() == "windows":
await restart.finish("暂无windows重启脚本...")
@restart.got("flag", prompt="确定是否重启真寻?(重启失败咱们将失去联系,请谨慎!)")
async def _(state: T_State):
async def _(bot: Bot, event: MessageEvent, state: T_State):
flag = state["flag"]
if flag.lower() in ["true", "是", "好", "确定", "确定是"]:
await restart.send("开始重启真寻..请稍等...")
@@ -107,7 +107,8 @@ async def _():
await bot.send_private_msg(
user_id=int(list(bot.config.superusers)[0]),
message=f"检测到真寻版本更新\n"
f"当前版本:{_version},最新版本:{latest_version}",
f"当前版本:{_version},最新版本:{latest_version}\n"
f"尝试自动更新...",
)
# try:
# code = await check_update(bot)
+1 -1
View File
@@ -1,4 +1,4 @@
from nonebot.adapters.onebot.v11 import Bot, Message
from nonebot.adapters.cqhttp import Bot, Message
from utils.image_utils import BuildImage
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
+6 -4
View File
@@ -1,6 +1,6 @@
from nonebot import on_regex
from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.adapters.cqhttp import Bot, MessageEvent
from utils.message_builder import image
from services.log import logger
from utils.manager import withdraw_message_manager
@@ -31,10 +31,12 @@ __plugin_configs__ = {
},
}
coser = on_regex("^(cos|COS|coser|括丝)$", priority=5, block=True)
coser = on_command(
"cos", aliases={"coser", "括丝", "COS", "Cos", "cOS", "coS"}, priority=5, block=True
)
url = "https://api.iyk0.com/cos"
url = "http://iw233.cn/API/cos.php"
@coser.handle()
+26 -25
View File
@@ -1,12 +1,12 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
from nonebot.permission import SUPERUSER
from utils.utils import is_number, get_message_img
from utils.utils import get_message_text, is_number, get_message_imgs
from utils.message_builder import image
from utils.message_builder import text as _text
from services.log import logger
from utils.message_builder import at
from nonebot.params import CommandArg
__zx_plugin_name__ = "联系管理员"
@@ -58,10 +58,12 @@ reply = on_command("/t", priority=1, permission=SUPERUSER, block=True)
@dialogue.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
text = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
uid = event.user_id
coffee = int(list(bot.config.superusers)[0])
text = get_message_text(event.json())
img_msg = _text("")
for img in get_message_img(event.json()):
for img in get_message_imgs(event.json()):
img_msg += image(img)
if not text and not img_msg:
await dialogue.send("请发送[滴滴滴]+您要说的内容~", at_sender=True)
@@ -74,18 +76,17 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
group_name = (await bot.get_group_info(group_id=event.group_id))[
"group_name"
]
nickname = event.sender.card or event.sender.nickname
for coffee in bot.config.superusers:
await bot.send_private_msg(
user_id=int(coffee),
message=_text(
f"*****一份交流报告*****\n"
f"昵称:{nickname}({event.user_id})\n"
f"群聊:{group_name}({group_id})\n"
f"消息:{text}"
)
+ img_msg,
nickname = event.sender.card if event.sender.card else event.sender.nickname
await bot.send_private_msg(
user_id=coffee,
message=_text(
f"*****一份交流报告*****\n"
f"昵称:{nickname}({uid})\n"
f"群聊:{group_name}({group_id})\n"
f"消息:{text}"
)
+ img_msg,
)
await dialogue.send(
_text(f"您的话已发送至管理员!\n======\n{text}") + img_msg, at_sender=True
)
@@ -98,12 +99,12 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
"msg": _text(text) + img_msg,
}
# print(dialogue_data)
logger.info(f"Q{event.user_id}@群{group_id} 联系管理员:text:{text}")
logger.info(f"Q{uid}@群{group_id} 联系管理员:{coffee} text:{text}")
@reply.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if not msg:
result = "*****待回复消息总览*****\n"
for key in dialogue_data.keys():
@@ -126,26 +127,26 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
id_ = msg[0]
user_id = dialogue_data[id_]["user_id"]
group_id = dialogue_data[id_]["group_id"]
text = " ".join(msg[1:])
text = msg[1]
dialogue_data.pop(id_)
else:
user_id = 0
if is_number(msg[1]):
group_id = int(msg[1])
text = " ".join(msg[2:])
text = msg[2]
else:
await reply.finish("群号错误...", at_sender=True)
else:
user_id = int(msg[0])
if is_number(msg[1]) and len(msg[1]) > 5:
group_id = int(msg[1])
text = " ".join(msg[2:])
text = msg[2]
else:
group_id = 0
text = " ".join(msg[1:])
text = msg[1]
else:
await reply.finish("第一参数,请输入数字.....", at_sender=True)
for img in get_message_img(event.json()):
for img in get_message_imgs(event.json()):
text += image(img)
if group_id:
if user_id:
+167 -105
View File
@@ -1,13 +1,16 @@
from nonebot import on_regex, on_keyword
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message
from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.params import RegexGroup
from utils.utils import scheduler
from .genshin_handle import genshin_draw, update_genshin_info, reset_count, reload_genshin_pool
from .genshin_handle import (
genshin_draw,
update_genshin_info,
reset_count,
reload_genshin_pool,
)
from .prts_handle import update_prts_info, prts_draw, reload_prts_pool
from .pretty_handle import update_pretty_info, pretty_draw, reload_pretty_pool
from .guardian_handle import update_guardian_info, guardian_draw, reload_guardian_pool
from .guardian_handle import update_guardian_info, guardian_draw
from .pcr_handle import update_pcr_info, pcr_draw
from .azur_handle import update_azur_info, azur_draw
from .fgo_handle import update_fgo_info, fgo_draw
@@ -15,12 +18,21 @@ from .onmyoji_handle import update_onmyoji_info, onmyoji_draw
from .update_game_info import update_info
from .util import is_number, check_num
from .rule import is_switch
from .config import draw_config
from .config import (
PRTS_FLAG,
PRETTY_FLAG,
GUARDIAN_FLAG,
GENSHIN_FLAG,
PCR_FLAG,
AZUR_FLAG,
FGO_FLAG,
ONMYOJI_FLAG,
)
from .async_update_game_info import async_update_game
from typing import Tuple, Any
import re
import asyncio
from utils.utils import scheduler
from services.log import logger
__zx_plugin_name__ = "游戏抽卡"
__plugin_usage__ = """
@@ -89,44 +101,81 @@ __plugin_settings__ = {
"cmd": ["游戏抽卡", "抽卡"],
}
prts = on_regex(r'.*?方舟([1-9|一][0-9]{0,2}[抽|井|连])', rule=is_switch('prts'), priority=5, block=True)
prts_update = on_keyword({'更新方舟信息', '更新明日方舟信息'}, permission=SUPERUSER, priority=1, block=True)
prts_up_reload = on_keyword({'重载方舟卡池'}, priority=1, block=True)
genshin = on_regex(r'.*?原神(武器|角色)?池?[1-9|一][0-9]{0,2}[抽|井|连]', rule=is_switch('genshin'), priority=5, block=True)
genshin_update = on_keyword({'更新原神信息'}, permission=SUPERUSER, priority=1, block=True)
genshin_reset = on_keyword({'重置原神抽卡'}, priority=1, block=True)
genshin_up_reload = on_keyword({'重载原神卡池'}, priority=1, block=True)
prts = on_regex(
r".*?方舟[1-9|一][0-9]{0,2}[抽|井]", rule=is_switch("prts"), priority=5, block=True
)
prts_update = on_keyword(
{"更新方舟信息", "更新明日方舟信息"}, permission=SUPERUSER, priority=1, block=True
)
prts_up_reload = on_keyword({"重载方舟卡池"}, priority=1, block=True)
pretty = on_regex(r'.*?马娘卡?[1-9|一][0-9]{0,2}[抽|井|连]', rule=is_switch('pretty'), priority=5, block=True)
pretty_update = on_keyword({'更新马娘信息', '更新赛马娘信息'}, permission=SUPERUSER, priority=1, block=True)
pretty_up_reload = on_keyword({'重载赛马娘卡池'}, priority=1, block=True)
genshin = on_regex(
".*?原神(武器|角色)?池?[1-9|一][0-9]{0,2}[抽|井]",
rule=is_switch("genshin"),
priority=5,
block=True,
)
genshin_update = on_keyword({"更新原神信息"}, permission=SUPERUSER, priority=1, block=True)
genshin_reset = on_keyword({"重置原神抽卡"}, priority=1, block=True)
genshin_up_reload = on_keyword({"重载原神卡池"}, priority=1, block=True)
guardian = on_regex(r'.*?坎公骑冠剑武?器?[1-9|一][0-9]{0,2}[抽|井|连]', rule=is_switch('guardian'), priority=5, block=True)
guardian_update = on_keyword({'更新坎公骑冠剑信息'}, permission=SUPERUSER, priority=1, block=True)
guardian_up_reload = on_keyword({'重载坎公骑冠剑卡池'}, priority=1, block=True)
pretty = on_regex(
".*?马娘卡?[1-9|一][0-9]{0,2}[抽|井]", rule=is_switch("pretty"), priority=5, block=True
)
pretty_update = on_keyword(
{"更新马娘信息", "更新赛马娘信息"}, permission=SUPERUSER, priority=1, block=True
)
pretty_up_reload = on_keyword({"重载赛马娘卡池"}, priority=1, block=True)
pcr = on_regex(r'.*?(pcr|公主连结|公主连接|公主链接|公主焊接)[1-9|一][0-9]{0,2}[抽|井|连]', rule=is_switch('pcr'), priority=5, block=True)
pcr_update = on_keyword({'更新pcr信息', '更新公主连结信息'}, permission=SUPERUSER, priority=1, block=True)
guardian = on_regex(
".*?坎公骑冠剑武?器?[1-9|一][0-9]{0,2}[抽|井]",
rule=is_switch("guardian"),
priority=5,
block=True,
)
guardian_update = on_keyword(
{"更新坎公骑冠剑信息"}, permission=SUPERUSER, priority=1, block=True
)
azur = on_regex(r'.*?碧蓝航?线?(轻型|重型|特型)池?[1-9|一][0-9]{0,2}[抽|连]', rule=is_switch('azur'), priority=5, block=True)
azur_update = on_keyword({'更新碧蓝信息', '更新碧蓝航线信息'}, permission=SUPERUSER, priority=1, block=True)
pcr = on_regex(
".*?(pcr|公主连结|公主连接|公主链接|公主焊接)[1-9|一][0-9]{0,2}[抽|井]",
rule=is_switch("pcr"),
priority=5,
block=True,
)
pcr_update = on_keyword(
{"更新pcr信息", "更新公主连结信息"}, permission=SUPERUSER, priority=1, block=True
)
fgo = on_regex(r'.*?fgo[1-9|一][0-9]{0,2}[抽|连]', rule=is_switch('fgo'), priority=5, block=True)
fgo_update = on_keyword({'更新fgo信息'}, permission=SUPERUSER, priority=1, block=True)
azur = on_regex(
".*?碧蓝航?线?(轻型|重型|特型)池?[1-9|一][0-9]{0,2}[抽]",
rule=is_switch("azur"),
priority=5,
block=True,
)
azur_update = on_keyword(
{"更新碧蓝信息", "更新碧蓝航线信息"}, permission=SUPERUSER, priority=1, block=True
)
onmyoji = on_regex(r'.*?阴阳师[1-9|一][0-9]{0,2}[抽|连]', rule=is_switch('onmyoji'), priority=5, block=True)
onmyoji_update = on_keyword({'更新阴阳师信息'}, permission=SUPERUSER, priority=1, block=True)
fgo = on_regex(
".*?fgo[1-9|一][0-9]{0,2}[抽]", rule=is_switch("fgo"), priority=5, block=True
)
fgo_update = on_keyword({"更新fgo信息"}, permission=SUPERUSER, priority=1, block=True)
onmyoji = on_regex(
".*?阴阳师[1-9|一][0-9]{0,2}[抽]", rule=is_switch("onmyoji"), priority=5, block=True
)
onmyoji_update = on_keyword({"更新阴阳师信息"}, permission=SUPERUSER, priority=1, block=True)
@prts.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State, reg: Tuple[Any, ...] = RegexGroup()):
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
print(reg)
if msg in ['方舟一井', '方舟1井']:
if msg in ["方舟一井", "方舟1井"]:
num = 300
else:
rmsg = re.search(r'.*?方舟(.*)[抽|连]', msg)
rmsg = re.search(r".*?方舟(.*)抽", msg)
if rmsg:
num, flag = check_num(rmsg.group(1), 300)
if not flag:
@@ -134,28 +183,31 @@ async def _(bot: Bot, event: MessageEvent, state: T_State, reg: Tuple[Any, ...]
else:
return
await prts.send(await prts_draw(int(num)), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 方舟 {num}抽"
)
@prts_up_reload.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
text = await reload_prts_pool()
await prts_up_reload.finish(Message(f'重载完成!\n{text}'))
await prts_up_reload.finish(Message(f"重载完成!\n{text}"))
@genshin.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
rmsg = re.search(r'.*?原神(武器|角色)?池?(.*)[抽|井|连]', msg)
rmsg = re.search(r".*?原神(武器|角色)?池?(.*)[抽|井]", msg)
if rmsg:
pool_name = rmsg.group(1)
if pool_name == '武器':
pool_name = 'arms'
elif pool_name == '角色':
pool_name = 'char'
if pool_name == "武器":
pool_name = "arms"
elif pool_name == "角色":
pool_name = "char"
else:
pool_name = ''
pool_name = ""
num = rmsg.group(2)
if msg.find('一井') != -1 or msg.find('1井') != -1:
if msg.find("一井") != -1 or msg.find("1井") != -1:
num = 180
else:
num, flag = check_num(num, 180)
@@ -163,89 +215,94 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
await genshin.finish(num, at_sender=True)
else:
return
await genshin.send(await genshin_draw(event.user_id, int(num), pool_name), at_sender=True)
await genshin.send(
await genshin_draw(event.user_id, int(num), pool_name), at_sender=True
)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 原神 {num}抽"
)
@genshin_up_reload.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
text = await reload_genshin_pool()
await genshin_reset.finish(Message(f'重载成功!\n{text}'))
await genshin_reset.finish(Message(f"重载成功!\n{text}"))
@genshin_reset.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
reset_count(event.user_id)
await genshin_reset.send('重置了原神抽卡次数', at_sender=True)
await genshin_reset.send("重置了原神抽卡次数", at_sender=True)
@pretty.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
if msg.find('1井') != -1 or msg.find('一井') != -1:
if msg.find("1井") != -1 or msg.find("一井") != -1:
num = 200
if msg.find("卡") == -1:
pool_name = 'char'
pool_name = "char"
else:
pool_name = 'card'
pool_name = "card"
else:
rmsg = re.search(r'.*?马娘(.*)[抽|连]', msg)
rmsg = re.search(r".*?马娘(.*)抽", msg)
if rmsg:
num = rmsg.group(1)
if num[0] == '卡':
if num[0] == "卡":
num = num[1:]
pool_name = 'card'
pool_name = "card"
else:
pool_name = 'char'
pool_name = "char"
num, flag = check_num(num, 200)
if not flag:
await pretty.finish(num, at_sender=True)
else:
return
await pretty.send(await pretty_draw(int(num), pool_name), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 赛马娘 {num}抽"
)
@pretty_up_reload.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
text = await reload_pretty_pool()
await genshin_reset.finish(Message(f'重载成功!\n{text}'))
await genshin_reset.finish(Message(f"重载成功!\n{text}"))
@guardian.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
pool_name = 'char'
if msg.find('1井') != -1 or msg.find('一井') != -1:
pool_name = "char"
if msg.find("1井") != -1 or msg.find("一井") != -1:
num = 300
if msg.find('武器') != -1:
pool_name = 'arms'
if msg.find("武器") != -1:
pool_name = "arms"
else:
rmsg = re.search(r'.*?坎公骑冠剑(.*)[抽|连]', msg)
rmsg = re.search(r".*?坎公骑冠剑(.*)抽", msg)
if rmsg:
num = rmsg.group(1)
if num.find('武器') != -1:
pool_name = 'arms'
num = num.replace('武器', '')
if num.find("武器") != -1:
pool_name = "arms"
num = num.replace("武器", "")
num, flag = check_num(num, 300)
if not flag:
await guardian.finish(num, at_sender=True)
else:
return
await guardian.send(await guardian_draw(int(num), pool_name), at_sender=True)
@guardian_up_reload.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
text = await reload_guardian_pool()
await genshin_reset.finish(Message(f'重载成功!\n{text}'))
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 坎公骑冠剑 {num}抽"
)
@pcr.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
if msg.find('1井') != -1 or msg.find('一井') != -1:
if msg.find("1井") != -1 or msg.find("一井") != -1:
num = 300
else:
rmsg = re.search(r'.*?(pcr|公主连结)(.*)[抽|井|连]', msg)
rmsg = re.search(r".*?(pcr|公主连结)(.*)[抽|井]", msg)
if rmsg:
num, flag = check_num(rmsg.group(2), 300)
if not flag:
@@ -253,12 +310,15 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
else:
return
await pcr.send(await pcr_draw(int(num)), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 公主连结 {num}抽"
)
@azur.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
rmsg = re.search(r'.*?碧蓝航?线?(轻型|重型|特型)池?(.*)[抽|连]', msg)
rmsg = re.search(".*?碧蓝航?线?(轻型|重型|特型)池?(.*)[抽]", msg)
if rmsg:
pool_name = rmsg.group(1)
num, flag = check_num(rmsg.group(2), 300)
@@ -267,12 +327,15 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
else:
return
await azur.send(await azur_draw(int(num), pool_name), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 碧蓝航线 {num}抽"
)
@fgo.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
rmsg = re.search(r'.*?fgo(.*)[抽|连]', msg)
rmsg = re.search(".*?fgo(.*)抽", msg)
if rmsg:
num, flag = check_num(rmsg.group(1), 300)
if not flag:
@@ -280,12 +343,15 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
else:
return
await fgo.send(await fgo_draw(int(num)), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) fgo {num}抽"
)
@onmyoji.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
rmsg = re.search(r'.*?阴阳师(.*)[抽|连]', msg)
rmsg = re.search(".*?阴阳师(.*)抽", msg)
if rmsg:
num, flag = check_num(rmsg.group(1), 300)
if not flag:
@@ -293,122 +359,118 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
else:
return
await onmyoji.send(await onmyoji_draw(int(num)), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 阴阳师 {num}抽"
)
@prts_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_prts_info()
await prts_update.finish('更新完成!')
await prts_update.finish("更新完成!")
@genshin_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_genshin_info()
await genshin_update.finish('更新完成!')
await genshin_update.finish("更新完成!")
@pretty_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_pretty_info()
await genshin_update.finish('更新完成!')
await genshin_update.finish("更新完成!")
@guardian_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_guardian_info()
await genshin_update.finish('更新完成!')
await genshin_update.finish("更新完成!")
@pcr_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_pcr_info()
await genshin_update.finish('更新完成!')
await genshin_update.finish("更新完成!")
@azur_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_azur_info()
await genshin_update.finish('更新完成!')
await genshin_update.finish("更新完成!")
@fgo_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_fgo_info()
await genshin_update.finish('更新完成!')
await genshin_update.finish("更新完成!")
@onmyoji_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_onmyoji_info()
await genshin_update.finish('更新完成!')
await genshin_update.finish("更新完成!")
# 更新资源
@scheduler.scheduled_job(
'cron',
"cron",
hour=4,
minute=1,
)
async def _():
tasks = []
if draw_config.PRTS_FLAG:
if PRTS_FLAG:
tasks.append(asyncio.ensure_future(update_prts_info()))
if draw_config.GENSHIN_FLAG:
if GENSHIN_FLAG:
tasks.append(asyncio.ensure_future(update_genshin_info()))
if draw_config.PRETTY_FLAG:
if PRETTY_FLAG:
tasks.append(asyncio.ensure_future(update_pretty_info()))
if draw_config.GUARDIAN_FLAG:
if GUARDIAN_FLAG:
tasks.append(asyncio.ensure_future(update_guardian_info()))
if draw_config.PCR_FLAG:
if PCR_FLAG:
tasks.append(asyncio.ensure_future(update_pcr_info()))
if draw_config.AZUR_FLAG:
if AZUR_FLAG:
tasks.append(asyncio.ensure_future(update_azur_info()))
if draw_config.FGO_FLAG:
if FGO_FLAG:
tasks.append(asyncio.ensure_future(update_fgo_info()))
if draw_config.ONMYOJI_FLAG:
if ONMYOJI_FLAG:
tasks.append(asyncio.ensure_future(update_onmyoji_info()))
await asyncio.gather(*tasks)
logger.info("draw_card 抽卡自动更新完成...")
# 每天四点重载方舟up卡池
@scheduler.scheduled_job(
'cron',
"cron",
hour=4,
minute=1,
)
async def _():
if draw_config.PRTS_FLAG:
if PRTS_FLAG:
await reload_prts_pool()
logger.info("自动重载方舟卡池UP成功")
# 每天四点重载赛马娘up卡池
@scheduler.scheduled_job(
'cron',
"cron",
hour=4,
minute=1,
)
async def _():
if draw_config.PRETTY_FLAG:
if PRETTY_FLAG:
await reload_pretty_pool()
logger.info("自动重载赛马娘UP成功")
# 每天下午六点点重载原神up卡池
@scheduler.scheduled_job(
'cron',
"cron",
hour=18,
minute=1,
)
async def _():
if draw_config.PRTS_FLAG:
if PRTS_FLAG:
await reload_genshin_pool()
# 重载坎公骑冠剑卡池
@scheduler.scheduled_job(
'cron',
hour=4,
minute=1,
)
async def _():
if draw_config.GUARDIAN_FLAG:
await reload_guardian_pool()
logger.info("自动重载原神卡池UP成功")
+67 -72
View File
@@ -1,11 +1,11 @@
from bs4 import BeautifulSoup
import re
from datetime import datetime, timedelta
from .config import DRAW_DATA_PATH
from .config import DRAW_PATH
from pathlib import Path
from asyncio.exceptions import TimeoutError
from nonebot.log import logger
from services.log import logger
from utils.http_utils import AsyncHttpx
import re
try:
import ujson as json
except ModuleNotFoundError:
@@ -13,10 +13,10 @@ except ModuleNotFoundError:
headers = {'User-Agent': '"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"'}
prts_up_char = DRAW_DATA_PATH / "draw_card_up" / "prts_up_char.json"
genshin_up_char = DRAW_DATA_PATH / "draw_card_up" / "genshin_up_char.json"
pretty_up_char = DRAW_DATA_PATH / "draw_card_up" / "pretty_up_char.json"
guardian_up_char = DRAW_DATA_PATH / "draw_card_up" / "guardian_up_char.json"
prts_up_char = Path(DRAW_PATH + "/draw_card_up/prts_up_char.json")
genshin_up_char = Path(DRAW_PATH + "/draw_card_up/genshin_up_char.json")
pretty_up_char = Path(DRAW_PATH + "/draw_card_up/pretty_up_char.json")
guardian_up_char = Path(DRAW_PATH + "/draw_card_up/guardian_up_char.json")
prts_url = "https://ak.hypergryph.com/news.html"
genshin_url = "https://wiki.biligame.com/ys/%E7%A5%88%E6%84%BF"
@@ -26,37 +26,37 @@ guardian_url = "https://wiki.biligame.com/gt/%E9%A6%96%E9%A1%B5"
# 是否过时
def is_expired(data: dict):
times = data['time'].split('-')
for i in range(len(times)):
times[i] = str(datetime.now().year) + '-' + times[i].split('日')[0].strip().replace('月', '-')
start_date = datetime.strptime(times[0], '%Y-%m-%d').date()
end_date = datetime.strptime(times[1], '%Y-%m-%d').date()
now = datetime.now().date()
return not start_date <= now <= end_date
try:
times = data['time'].split('-')
for i in range(len(times)):
times[i] = str(datetime.now().year) + '-' + times[i].split('日')[0].strip().replace('月', '-')
start_date = datetime.strptime(times[0], '%Y-%m-%d').date()
end_date = datetime.strptime(times[1], '%Y-%m-%d').date()
now = datetime.now().date()
except ValueError:
return False
return start_date <= now <= end_date
# 检查写入
def check_write(data: dict, up_char_file):
try:
if is_expired(data['char']):
for x in list(data.keys()):
data[x]['title'] = ''
if is_expired(data['char']):
for x in list(data.keys()):
data[x]['title'] = ''
else:
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
if not up_char_file.exists():
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
else:
with open(up_char_file, 'r', encoding='utf8') as f:
old_data = json.load(f)
if is_expired(old_data['char']):
return old_data
else:
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
if not up_char_file.exists():
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
else:
with open(up_char_file, 'r', encoding='utf8') as f:
old_data = json.load(f)
if is_expired(old_data['char']):
return old_data
else:
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
except ValueError:
pass
return data
@@ -66,22 +66,17 @@ class PrtsAnnouncement:
self.game_name = '明日方舟'
async def _get_announcement_text(self):
res = await AsyncHttpx.get(prts_url, timeout=7)
soup = BeautifulSoup(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:
type_ = li.find('span', {'class': 'articleItemCate'}).text
if type_ == '活动':
itype = li.find('span', {'class': 'articleItemCate'}).text
if itype == '活动':
a = li.find('a')['href']
return (await AsyncHttpx.get(f'https://ak.hypergryph.com{a}', timeout=7)).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)
if prts_up_char.exists():
with open(prts_up_char, 'r', encoding='utf8') as f:
data = json.load(f)
if not data.get('char'):
prts_up_char.unlink()
try:
data = {'char': {'up_char': {'6': {}, '5': {}, '4': {}}, 'title': '', 'time': '', 'pool_img': ''}}
text = await self._get_announcement_text()
@@ -150,7 +145,7 @@ class GenshinAnnouncement:
self.game_name = '原神'
async def _get_announcement_text(self):
return (await AsyncHttpx.get(genshin_url, timeout=7)).text
return (await AsyncHttpx.get(genshin_url)).text
async def update_up_char(self):
genshin_up_char.parent.mkdir(exist_ok=True, parents=True)
@@ -167,34 +162,34 @@ class GenshinAnnouncement:
trs = table.find('tbody').find_all('tr')
pool_img = trs[0].find('th').find('img')
if pool_img['title'].find('角色活动') == -1:
type_ = 'arms'
itype = 'arms'
else:
type_ = 'char'
itype = 'char'
try:
data[type_]['pool_img'] = str(pool_img['srcset']).split(' ')[0]
data[itype]['pool_img'] = str(pool_img['srcset']).split(' ')[0]
except KeyError:
data[type_]['pool_img'] = pool_img['src']
data[type_]['title'] = str(pool_img['title']).split(f'期{"角色" if type_ == "char" else "武器"}')[0][:-3]
data[type_]['time'] = trs[1].find('td').text
if data[type_]['time'][-1] == '\n':
data[type_]['time'] = data[type_]['time'][:-1]
if '版本更新后' in data[type_]['time']:
sp = data[type_]['time'].split('~')
end_time = datetime.strptime(sp[1].strip(), "%Y/%m/%d %H:%M")
data[itype]['pool_img'] = pool_img['src']
data[itype]['title'] = str(pool_img['title']).split(f'期{"角色" if itype == "char" else "武器"}')[0][:-3]
data[itype]['time'] = trs[1].find('td').text
if data[itype]['time'][-1] == '\n':
data[itype]['time'] = data[itype]['time'][:-1]
if '版本更新后' in data[itype]['time']:
sp = data[itype]['time'].split('~')
end_time = datetime.strptime(sp[1].strip(), "%Y/%m/%d %H:%M:%S")
start_time = end_time - timedelta(days=20)
data[type_]['time'] = start_time.strftime('%Y/%m/%d') + ' ~ ' + end_time.strftime('%Y/%m/%d')
data[itype]['time'] = start_time.strftime('%Y/%m/%d') + ' ~ ' + end_time.strftime('%Y/%m/%d')
tmp = ''
for tm in data[type_]['time'].split('~'):
for tm in data[itype]['time'].split('~'):
date_time_sp = tm.split('/')
date_time_sp[2] = date_time_sp[2].strip().replace(' ', '日 ')
tmp += date_time_sp[1] + '月' + date_time_sp[2] + ' - '
data[type_]['time'] = tmp[:-2].strip()
data[itype]['time'] = tmp[:-2].strip()
for a in trs[2].find('td').find_all('a'):
char_name = a['title']
data[type_]['up_char']['5'][char_name] = "50"
data[itype]['up_char']['5'][char_name] = "50"
for a in trs[3].find('td').find_all('a'):
char_name = a['title']
data[type_]['up_char']['4'][char_name] = "50"
data[itype]['up_char']['4'][char_name] = "50"
except TimeoutError:
logger.warning(f'更新原神UP池信息超时...')
if genshin_up_char.exists():
@@ -219,9 +214,10 @@ class PrettyAnnouncement:
self.game_name = '赛马娘'
async def _get_announcement_text(self):
res = await AsyncHttpx.get(pretty_url, timeout=7)
soup = BeautifulSoup(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,9 +227,10 @@ class PrettyAnnouncement:
if title.find('新角色追加') != -1:
url = a['href']
break
return (await AsyncHttpx.get(f'https://wiki.biligame.com/{url}', timeout=7)).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)
data = {
'char': {'up_char': {'3': {}, '2': {}, '1': {}}, 'title': '', 'time': '', 'pool_img': ''},
'card': {'up_char': {'3': {}, '2': {}, '1': {}}, 'title': '', 'time': '', 'pool_img': ''}
@@ -246,14 +243,12 @@ class PrettyAnnouncement:
context = soup.find('div', {'class': 'mw-parser-output'})
data['char']['title'] = title
data['card']['title'] = title
for big in context.find_all('big'):
r = re.search(r'\d{1,2}/\d{1,2} \d{1,2}:\d{1,2}', str(big.text))
if r:
time = str(big.text)
break
r = re.search(r'(\d{1,2}/\d{1,2} \d{1,2}:\d{1,2} ~ \d{1,2}/\d{1,2} \d{1,2}:\d{1,2})', str(context.text))
if r:
time = str(r.group(1))
else:
logger.warning('赛马娘UP无法找到活动日期....取消更新UP池子...')
return
logger.error('赛马娘UP无法找到活动日期....取消更新UP池子...')
return check_write(data, pretty_up_char)
time = time.replace('~', '-').replace('/', '月').split(' ')
time = time[0] + '日 ' + time[1] + ' - ' + time[3] + '日 ' + time[4]
data['char']['time'] = time
@@ -314,7 +309,7 @@ class PrettyAnnouncement:
if star == 'R':
data['card']['up_char']['1'][char_name] = '70'
# 日文->中文
with open(DRAW_DATA_PATH / 'pretty_card.json', 'r', encoding='utf8') as f:
with open(DRAW_PATH + 'pretty_card.json', 'r', encoding='utf8') as f:
all_data = json.load(f)
for star in data['card']['up_char'].keys():
for name in list(data['card']['up_char'][star].keys()):
@@ -343,7 +338,7 @@ class GuardianAnnouncement:
self.game_name = '坎公骑冠剑'
async def _get_announcement_text(self):
return (await AsyncHttpx.get(guardian_url, timeout=7)).text
return (await AsyncHttpx.get(guardian_url)).text
async def update_up_char(self):
data = {
+23 -16
View File
@@ -1,6 +1,7 @@
import asyncio
import nonebot
from nonebot.log import logger
import os
from services.log import logger
from .pcr_handle import update_pcr_info, init_pcr_data
from .azur_handle import update_azur_info, init_azur_data
from .prts_handle import update_prts_info, init_prts_data
@@ -9,10 +10,11 @@ from .guardian_handle import update_guardian_info, init_guardian_data
from .genshin_handle import update_genshin_info, init_genshin_data
from .fgo_handle import update_fgo_info, init_fgo_data
from .onmyoji_handle import update_onmyoji_info, init_onmyoji_data
from .config import draw_config, DRAW_DATA_PATH
from .config import DRAW_PATH, PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, PCR_FLAG, AZUR_FLAG, GENSHIN_FLAG, FGO_FLAG, \
ONMYOJI_FLAG
driver = nonebot.get_driver()
driver: nonebot.Driver = nonebot.get_driver()
@driver.on_startup
@@ -20,44 +22,49 @@ async def async_update_game():
tasks = []
init_lst = [init_pcr_data, init_pretty_data, init_azur_data, init_prts_data, init_genshin_data, init_guardian_data,
init_fgo_data, init_onmyoji_data]
if draw_config.PRTS_FLAG and not (DRAW_DATA_PATH / 'prts.json').exists():
if PRTS_FLAG and not os.path.exists(DRAW_PATH + 'prts.json'):
tasks.append(asyncio.ensure_future(update_prts_info()))
init_lst.remove(init_prts_data)
if draw_config.PRETTY_FLAG and (not (DRAW_DATA_PATH / 'pretty.json').exists() or
not (DRAW_DATA_PATH / 'pretty_card.json').exists()):
if PRETTY_FLAG and (not os.path.exists(DRAW_PATH + 'pretty.json') or
not os.path.exists(DRAW_PATH + 'pretty_card.json')):
tasks.append(asyncio.ensure_future(update_pretty_info()))
init_lst.remove(init_pretty_data)
if draw_config.GUARDIAN_FLAG and not (DRAW_DATA_PATH / 'guardian.json').exists():
if GUARDIAN_FLAG and not os.path.exists(DRAW_PATH + 'guardian.json'):
tasks.append(asyncio.ensure_future(update_guardian_info()))
init_lst.remove(init_guardian_data)
if draw_config.PCR_FLAG and not (DRAW_DATA_PATH / 'pcr.json').exists():
if PCR_FLAG and not os.path.exists(DRAW_PATH + 'pcr.json'):
tasks.append(asyncio.ensure_future(update_pcr_info()))
init_lst.remove(init_pcr_data)
if draw_config.GENSHIN_FLAG and (not (DRAW_DATA_PATH / 'genshin.json').exists() or
not (DRAW_DATA_PATH / 'genshin_arms.json').exists()):
if GENSHIN_FLAG and (not os.path.exists(DRAW_PATH + 'genshin.json') or
not os.path.exists(DRAW_PATH + 'genshin_arms.json')):
tasks.append(asyncio.ensure_future(update_genshin_info()))
init_lst.remove(init_genshin_data)
if draw_config.AZUR_FLAG and not (DRAW_DATA_PATH / 'azur.json').exists():
if AZUR_FLAG and not os.path.exists(DRAW_PATH + 'azur.json'):
tasks.append(asyncio.ensure_future(update_azur_info()))
init_lst.remove(init_azur_data)
if draw_config.FGO_FLAG and (not (DRAW_DATA_PATH / 'fgo.json').exists() or
not (DRAW_DATA_PATH / 'fgo_card.json').exists()):
if FGO_FLAG and (not os.path.exists(DRAW_PATH + 'fgo.json') or
not os.path.exists(DRAW_PATH + 'fgo_card.json')):
tasks.append(asyncio.ensure_future(update_fgo_info()))
init_lst.remove(init_fgo_data)
if draw_config.ONMYOJI_FLAG and not (DRAW_DATA_PATH / 'onmyoji.json').exists():
if ONMYOJI_FLAG and not os.path.exists(DRAW_PATH + 'onmyoji.json'):
tasks.append(asyncio.ensure_future(update_onmyoji_info()))
init_lst.remove(init_onmyoji_data)
try:
await asyncio.gather(*tasks)
for func in init_lst:
await func()
except asyncio.exceptions.CancelledError:
logger.warning('更新异常:CancelledError,再次更新...')
logger.info('更新异常:CancelledError,再次更新...')
await async_update_game()
+13 -12
View File
@@ -1,8 +1,9 @@
from nonebot.adapters.onebot.v11 import MessageSegment
from nonebot.adapters.cqhttp import MessageSegment
import random
from .update_game_simple_info import update_simple_info
from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card, format_card_information
from .config import draw_config, DRAW_DATA_PATH
from .config import AZUR_ONE_P, AZUR_TWO_P, AZUR_THREE_P, AZUR_FOUR_P, AZUR_FLAG, DRAW_PATH
from dataclasses import dataclass
from .init_card_pool import init_game_pool
try:
@@ -15,7 +16,7 @@ ALL_CHAR = []
@dataclass
class AzurChar(BaseData):
type_: str # 舰娘类型
itype: str # 舰娘类型
async def azur_draw(count: int, pool_name: str):
@@ -41,22 +42,22 @@ async def update_azur_info():
async def init_azur_data():
global ALL_CHAR
if draw_config.AZUR_FLAG:
with (DRAW_DATA_PATH / 'azur.json').open('r', encoding='utf8') as f:
if AZUR_FLAG:
with open(DRAW_PATH + 'azur.json', 'r', encoding='utf8') as f:
azur_dict = json.load(f)
ALL_CHAR = init_game_pool('azur', azur_dict, AzurChar)
# 抽取卡池
def _get_azur_card(pool_name: str, mode: int = 1):
def _get_azur_card(pool_name: str):
global ALL_CHAR
azur_config = draw_config.azur
if pool_name == '轻型':
type_ = ['驱逐', '轻巡', '维修']
itype = ['驱逐', '轻巡', '维修']
elif pool_name == '重型':
type_ = ['重巡', '战列', '战巡', '重炮']
itype = ['重巡', '战列', '战巡', '重炮']
else:
type_ = ['维修', '潜艇', '重巡', '轻航', '航母']
star = get_star([4, 3, 2, 1], [azur_config.AZUR_FOUR_P, azur_config.AZUR_THREE_P, azur_config.AZUR_TWO_P, azur_config.AZUR_ONE_P])
chars = [x for x in ALL_CHAR if x.star == star and x.type_ in type_ and not x.limited]
itype = ['维修', '潜艇', '重巡', '轻航', '航母']
star = get_star([4, 3, 2, 1], [AZUR_FOUR_P, AZUR_THREE_P, AZUR_TWO_P, AZUR_ONE_P])
chars = [x for x in ALL_CHAR if x.star == star and x.itype in itype and not x.limited]
return random.choice(chars), 4 - star
+371 -123
View File
@@ -1,7 +1,6 @@
import nonebot
from nonebot.log import logger
from pydantic import BaseModel, Extra, ValidationError
from configs.path_config import IMAGE_PATH, DATA_PATH
from pathlib import Path
from configs.path_config import DATA_PATH
from configs.config import Config
try:
@@ -10,111 +9,133 @@ except ModuleNotFoundError:
import json
# 原神
class GenshinConfig(BaseModel, extra=Extra.ignore):
GENSHIN_FIVE_P: float = 0.006
GENSHIN_FOUR_P: float = 0.051
GENSHIN_THREE_P: float = 0.43
GENSHIN_G_FIVE_P: float = 0.13
GENSHIN_G_FOUR_P: float = 0.016
I72_ADD: float = 0.0585
DRAW_PATH = DATA_PATH + "/draw_card/"
_draw_config = Path(rf"{DRAW_PATH}/draw_card_config/draw_card_config.json")
# 明日方舟
class PrtsConfig(BaseModel, extra=Extra.ignore):
PRTS_SIX_P: float = 0.02
PRTS_FIVE_P: float = 0.08
PRTS_FOUR_P: float = 0.48
PRTS_THREE_P: float = 0.42
for game_flag, game_name in zip(
[
"PRTS_FLAG",
"GENSHIN_FLAG",
"PRETTY_FLAG",
"GUARDIAN_FLAG",
"PCR_FLAG",
"AZUR_FLAG",
"FGO_FLAG",
"ONMYOJI_FLAG",
"PCR_TAI",
],
["明日方舟", "原神", "赛马娘", "坎公骑冠剑", "公主连结", "碧蓝航线", "命运-冠位指定(FGO)", "阴阳师", "pcr台服卡池"],
):
Config.add_plugin_config(
"draw_card",
game_flag,
True,
name="游戏抽卡",
help_=f"{game_name} 抽卡开关",
default_value=True,
)
Config.add_plugin_config(
"draw_card", "SEMAPHORE", 5, help_=f"异步数据下载数量限制", default_value=5
)
PRTS_FLAG = Config.get_config("draw_card", "PRTS_FLAG")
GENSHIN_FLAG = Config.get_config("draw_card", "GENSHIN_FLAG")
PRETTY_FLAG = Config.get_config("draw_card", "PRETTY_FLAG")
GUARDIAN_FLAG = Config.get_config("draw_card", "GUARDIAN_FLAG")
PCR_FLAG = Config.get_config("draw_card", "PCR_FLAG")
AZUR_FLAG = Config.get_config("draw_card", "AZUR_FLAG")
FGO_FLAG = Config.get_config("draw_card", "FGO_FLAG")
ONMYOJI_FLAG = Config.get_config("draw_card", "ONMYOJI_FLAG")
PCR_TAI = Config.get_config("draw_card", "PCR_TAI")
SEMAPHORE = Config.get_config("draw_card", "SEMAPHORE")
# 赛马娘
class PrettyConfig(BaseModel, extra=Extra.ignore):
PRETTY_THREE_P: float = 0.03
PRETTY_TWO_P: float = 0.18
PRETTY_ONE_P: float = 0.79
# 方舟概率
PRTS_SIX_P = 0.02
PRTS_FIVE_P = 0.08
PRTS_FOUR_P = 0.48
PRTS_THREE_P = 0.42
# 原神概率
GENSHIN_FIVE_P = 0.006
GENSHIN_FOUR_P = 0.051
GENSHIN_THREE_P = 0.43
# 保底概率
GENSHIN_G_FIVE_P = 0.016
GENSHIN_G_FOUR_P = 0.13
# 72抽后增加的概率
I72_ADD = 0.0585
# 赛马娘概率
PRETTY_THREE_P = 0.03
PRETTY_TWO_P = 0.18
PRETTY_ONE_P = 0.79
# 坎公骑冠剑
class GuardianConfig(BaseModel, extra=Extra.ignore):
GUARDIAN_THREE_CHAR_P: float = 0.0275
GUARDIAN_TWO_CHAR_P: float = 0.19
GUARDIAN_ONE_CHAR_P: float = 0.7825
GUARDIAN_THREE_CHAR_UP_P: float = 0.01375
GUARDIAN_THREE_CHAR_OTHER_P: float = 0.01375
GUARDIAN_EXCLUSIVE_ARMS_P: float = 0.03
GUARDIAN_FIVE_ARMS_P: float = 0.03
GUARDIAN_FOUR_ARMS_P: float = 0.09
GUARDIAN_THREE_ARMS_P: float = 0.27
GUARDIAN_TWO_ARMS_P: float = 0.58
GUARDIAN_EXCLUSIVE_ARMS_UP_P: float = 0.01
GUARDIAN_EXCLUSIVE_ARMS_OTHER_P: float = 0.02
# 公主连结
class PcrConfig(BaseModel, extra=Extra.ignore):
PCR_THREE_P: float = 0.025
PCR_TWO_P: float = 0.18
PCR_ONE_P: float = 0.795
PCR_G_THREE_P: float = 0.025
PCR_G_TWO_P: float = 0.975
# 角色概率
GUARDIAN_THREE_CHAR_P = 0.0275
GUARDIAN_TWO_CHAR_P = 0.19
GUARDIAN_ONE_CHAR_P = 0.7825
# UP角色
GUARDIAN_THREE_CHAR_UP_P = 0.01375
GUARDIAN_THREE_CHAR_OTHER_P = 0.01375
# 武器概率
GUARDIAN_EXCLUSIVE_ARMS_P = 0.03
GUARDIAN_FIVE_ARMS_P = 0.03
GUARDIAN_FOUR_ARMS_P = 0.09
GUARDIAN_THREE_ARMS_P = 0.27
GUARDIAN_TWO_ARMS_P = 0.58
# UP武器
GUARDIAN_EXCLUSIVE_ARMS_UP_P = 0.01
GUARDIAN_EXCLUSIVE_ARMS_OTHER_P = 0.02
# PCR
PCR_THREE_P = 0.025
PCR_TWO_P = 0.18
PCR_ONE_P = 0.795
# 保底
PCR_G_THREE_P = 0.025
PCR_G_TWO_P = 0.975
# 碧蓝航线
class AzurConfig(BaseModel, extra=Extra.ignore):
AZUR_FIVE_P: float = 0.012
AZUR_FOUR_P: float = 0.07
AZUR_THREE_P: float = 0.12
AZUR_TWO_P: float = 0.51
AZUR_ONE_P: float = 0.3
# 命运-冠位指定
class FgoConfig(BaseModel, extra=Extra.ignore):
FGO_SERVANT_FIVE_P: float = 0.01
FGO_SERVANT_FOUR_P: float = 0.03
FGO_SERVANT_THREE_P: float = 0.4
FGO_CARD_FIVE_P: float = 0.04
FGO_CARD_FOUR_P: float = 0.12
FGO_CARD_THREE_P: float = 0.4
AZUR_FIVE_P = 0.012
AZUR_FOUR_P = 0.07
AZUR_THREE_P = 0.12
AZUR_TWO_P = 0.51
AZUR_ONE_P = 0.3
# FGO
FGO_SERVANT_FIVE_P = 0.01
FGO_SERVANT_FOUR_P = 0.03
FGO_SERVANT_THREE_P = 0.4
FGO_CARD_FIVE_P = 0.04
FGO_CARD_FOUR_P = 0.12
FGO_CARD_THREE_P = 0.4
# 阴阳师
class OnmyojiConfig(BaseModel, extra=Extra.ignore):
ONMYOJI_SP: float = 0.0025
ONMYOJI_SSR: float = 0.01
ONMYOJI_SR: float = 0.2
ONMYOJI_R: float = 0.7875
ONMYOJI_SP = 0.0025
ONMYOJI_SSR = 0.01
ONMYOJI_SR = 0.2
ONMYOJI_R = 0.7875
class PathDict(BaseModel, extra=Extra.ignore):
genshin: str = "原神"
prts: str = "明日方舟"
pretty: str = "赛马娘"
guardian: str = "坎公骑冠剑"
pcr: str = "公主连结"
azur: str = "碧蓝航线"
fgo: str = "命运-冠位指定"
onmyoji: str = "阴阳师"
path_dict = {
"genshin": "原神",
"prts": "明日方舟",
"pretty": "赛马娘",
"guardian": "坎公骑冠剑",
"pcr": "公主连结",
"azur": "碧蓝航线",
"fgo": "命运-冠位指定",
"onmyoji": "阴阳师",
}
driver: nonebot.Driver = nonebot.get_driver()
class DrawConfig(BaseModel, extra=Extra.ignore):
# 开关
PRTS_FLAG: bool = Config.get_config("draw_card", "PRTS_FLAG")
GENSHIN_FLAG: bool = Config.get_config("draw_card", "GENSHIN_FLAG")
PRETTY_FLAG: bool = Config.get_config("draw_card", "PRETTY_FLAG")
GUARDIAN_FLAG: bool = Config.get_config("draw_card", "GUARDIAN_FLAG")
PCR_FLAG: bool = Config.get_config("draw_card", "PCR_FLAG")
AZUR_FLAG: bool = Config.get_config("draw_card", "AZUR_FLAG")
FGO_FLAG: bool = Config.get_config("draw_card", "FGO_FLAG")
ONMYOJI_FLAG: bool = Config.get_config("draw_card", "ONMYOJI_FLAG")
# 其他配置
PCR_TAI: bool = Config.get_config("draw_card", "PCR_TAI")
SEMAPHORE: int = Config.get_config("draw_card", "SEMAPHORE")
# 路径
path_dict: dict = {
config_default_data = {
"path_dict": {
"genshin": "原神",
"prts": "明日方舟",
"pretty": "赛马娘",
@@ -123,41 +144,268 @@ class DrawConfig(BaseModel, extra=Extra.ignore):
"azur": "碧蓝航线",
"fgo": "命运-冠位指定",
"onmyoji": "阴阳师",
}
# 抽卡概率
prts: PrtsConfig = PrtsConfig()
genshin: GenshinConfig = GenshinConfig()
pretty: PrettyConfig = PrettyConfig()
guardian: GuardianConfig = GuardianConfig()
pcr: PcrConfig = PcrConfig()
azur: AzurConfig = AzurConfig()
fgo: FgoConfig = FgoConfig()
onmyoji: OnmyojiConfig = OnmyojiConfig()
driver = nonebot.get_driver()
global_config = driver.config
DRAW_DATA_PATH = DATA_PATH / "draw_card"
DRAW_IMAGE_PATH = IMAGE_PATH / "draw_card"
# DRAW_PATH = Path(draw_path) if draw_path else Path("data/draw_card").absolute()
config_path = DRAW_DATA_PATH / "draw_card_config" / "draw_card_config.json"
draw_config: Config = DrawConfig()
},
"prts": {
"PRTS_SIX_P": 0.02,
"PRTS_FIVE_P": 0.08,
"PRTS_FOUR_P": 0.48,
"PRTS_THREE_P": 0.42,
},
"genshin": {
"GENSHIN_FIVE_P": 0.006,
"GENSHIN_FOUR_P": 0.051,
"GENSHIN_THREE_P": 0.43,
"GENSHIN_G_FIVE_P": 0.13,
"GENSHIN_G_FOUR_P": 0.016,
"I72_ADD": 0.0585,
},
"pretty": {
"PRETTY_THREE_P": 0.03,
"PRETTY_TWO_P": 0.18,
"PRETTY_ONE_P": 0.79,
},
"guardian": {
"GUARDIAN_THREE_CHAR_P": 0.0275,
"GUARDIAN_TWO_CHAR_P": 0.19,
"GUARDIAN_ONE_CHAR_P": 0.7825,
"GUARDIAN_THREE_CHAR_UP_P": 0.01375,
"GUARDIAN_THREE_CHAR_OTHER_P": 0.01375,
"GUARDIAN_EXCLUSIVE_ARMS_P": 0.03,
"GUARDIAN_FIVE_ARMS_P": 0.03,
"GUARDIAN_FOUR_ARMS_P": 0.09,
"GUARDIAN_THREE_ARMS_P": 0.27,
"GUARDIAN_TWO_ARMS_P": 0.58,
"GUARDIAN_EXCLUSIVE_ARMS_UP_P": 0.01,
"GUARDIAN_EXCLUSIVE_ARMS_OTHER_P": 0.02,
},
"pcr": {
"PCR_THREE_P": 0.025,
"PCR_TWO_P": 0.18,
"PCR_ONE_P": 0.795,
},
"azur": {
"AZUR_FIVE_P": 0.012,
"AZUR_FOUR_P": 0.07,
"AZUR_THREE_P": 0.12,
"AZUR_TWO_P": 0.51,
"AZUR_ONE_P": 0.3,
},
"fgo": {
"FGO_SERVANT_FIVE_P": 0.01,
"FGO_SERVANT_FOUR_P": 0.03,
"FGO_SERVANT_THREE_P": 0.4,
"FGO_CARD_FIVE_P": 0.04,
"FGO_CARD_FOUR_P": 0.12,
"FGO_CARD_THREE_P": 0.4,
},
"onmyoji": {
"ONMYOJI_SP": 0.0025,
"ONMYOJI_SSR": 0.01,
"ONMYOJI_SR": 0.2,
"ONMYOJI_R": 0.7875,
},
}
@driver.on_startup
def check_config():
global draw_config
global PRTS_SIX_P, PRTS_FOUR_P, PRTS_FIVE_P, PRTS_THREE_P, GENSHIN_G_FIVE_P, config_default_data, GENSHIN_G_FOUR_P, GENSHIN_FOUR_P, GENSHIN_FIVE_P, I72_ADD, path_dict, PRETTY_THREE_P, PRETTY_ONE_P, PRETTY_TWO_P, GENSHIN_THREE_P, GUARDIAN_THREE_CHAR_P, GUARDIAN_TWO_CHAR_P, GUARDIAN_ONE_CHAR_P, GUARDIAN_THREE_CHAR_UP_P, GUARDIAN_THREE_CHAR_OTHER_P, GUARDIAN_EXCLUSIVE_ARMS_P, GUARDIAN_FIVE_ARMS_P, GUARDIAN_FOUR_ARMS_P, GUARDIAN_THREE_ARMS_P, GUARDIAN_TWO_ARMS_P, GENSHIN_FLAG, PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, GUARDIAN_EXCLUSIVE_ARMS_UP_P, GUARDIAN_EXCLUSIVE_ARMS_OTHER_P, DRAW_PATH, PCR_THREE_P, PCR_TWO_P, PCR_ONE_P, AZUR_FOUR_P, AZUR_THREE_P, AZUR_TWO_P, AZUR_ONE_P, AZUR_FIVE_P, FGO_CARD_FIVE_P, FGO_CARD_FOUR_P, FGO_CARD_THREE_P, FGO_SERVANT_THREE_P, FGO_SERVANT_FOUR_P, FGO_SERVANT_FIVE_P, ONMYOJI_R, ONMYOJI_SP, ONMYOJI_SSR, ONMYOJI_SR
_draw_config.parent.mkdir(parents=True, exist_ok=True)
try:
data = json.load(open(_draw_config, "r", encoding="utf8"))
except (FileNotFoundError, ValueError):
_draw_config.parent.mkdir(parents=True, exist_ok=True)
json.dump(
config_default_data,
open(_draw_config, "w", encoding="utf8"),
indent=4,
ensure_ascii=False,
)
print("draw_card:配置文件不存在或格式错误,已重新生成配置文件.....")
else:
if not config_path.exists():
config_path.parent.mkdir(parents=True, exist_ok=True)
draw_config = DrawConfig()
logger.warning("draw_card:配置文件不存在,已重新生成配置文件.....")
try:
PRTS_SIX_P = float(data["prts"]["PRTS_SIX_P"])
PRTS_FIVE_P = float(data["prts"]["PRTS_FIVE_P"])
PRTS_FOUR_P = float(data["prts"]["PRTS_FOUR_P"])
PRTS_THREE_P = float(data["prts"]["PRTS_THREE_P"])
except KeyError:
data["prts"] = {}
data["prts"]["PRTS_SIX_P"] = config_default_data["prts"]["PRTS_SIX_P"]
data["prts"]["PRTS_FIVE_P"] = config_default_data["prts"]["PRTS_FIVE_P"]
data["prts"]["PRTS_FOUR_P"] = config_default_data["prts"]["PRTS_FOUR_P"]
data["prts"]["PRTS_THREE_P"] = config_default_data["prts"]["PRTS_THREE_P"]
json.dump(
draw_config.dict(),
config_path.open("w", encoding="utf8"),
indent=4,
ensure_ascii=False,
)
try:
GENSHIN_FIVE_P = float(data["genshin"]["GENSHIN_FIVE_P"])
GENSHIN_FOUR_P = float(data["genshin"]["GENSHIN_FOUR_P"])
GENSHIN_THREE_P = float(data["genshin"]["GENSHIN_THREE_P"])
GENSHIN_G_FIVE_P = float(data["genshin"]["GENSHIN_G_FIVE_P"])
GENSHIN_G_FOUR_P = float(data["genshin"]["GENSHIN_G_FOUR_P"])
I72_ADD = float(data["genshin"]["I72_ADD"])
except KeyError:
data["genshin"] = {}
data["genshin"]["GENSHIN_FIVE_P"] = config_default_data["genshin"][
"GENSHIN_FIVE_P"
]
data["genshin"]["GENSHIN_FOUR_P"] = config_default_data["genshin"][
"GENSHIN_FOUR_P"
]
data["genshin"]["GENSHIN_THREE_P"] = config_default_data["genshin"][
"GENSHIN_THREE_P"
]
data["genshin"]["GENSHIN_G_FIVE_P"] = config_default_data["genshin"][
"GENSHIN_G_FIVE_P"
]
data["genshin"]["GENSHIN_G_FOUR_P"] = config_default_data["genshin"][
"GENSHIN_G_FOUR_P"
]
data["genshin"]["I72_ADD"] = config_default_data["genshin"]["I72_ADD"]
try:
PRETTY_THREE_P = float(data["pretty"]["PRETTY_THREE_P"])
PRETTY_TWO_P = float(data["pretty"]["PRETTY_TWO_P"])
PRETTY_ONE_P = float(data["pretty"]["PRETTY_ONE_P"])
except KeyError:
data["pretty"] = {}
data["pretty"]["PRETTY_THREE_P"] = config_default_data["pretty"][
"PRETTY_THREE_P"
]
data["pretty"]["PRETTY_TWO_P"] = config_default_data["pretty"][
"PRETTY_TWO_P"
]
data["pretty"]["PRETTY_ONE_P"] = config_default_data["pretty"][
"PRETTY_ONE_P"
]
try:
GUARDIAN_THREE_CHAR_P = float(data["guardian"]["GUARDIAN_THREE_CHAR_P"])
GUARDIAN_TWO_CHAR_P = float(data["guardian"]["GUARDIAN_TWO_CHAR_P"])
GUARDIAN_ONE_CHAR_P = float(data["guardian"]["GUARDIAN_ONE_CHAR_P"])
GUARDIAN_THREE_CHAR_UP_P = float(
data["guardian"]["GUARDIAN_THREE_CHAR_UP_P"]
)
GUARDIAN_THREE_CHAR_OTHER_P = float(
data["guardian"]["GUARDIAN_THREE_CHAR_OTHER_P"]
)
GUARDIAN_EXCLUSIVE_ARMS_P = float(
data["guardian"]["GUARDIAN_EXCLUSIVE_ARMS_P"]
)
GUARDIAN_FIVE_ARMS_P = float(data["guardian"]["GUARDIAN_FIVE_ARMS_P"])
GUARDIAN_FOUR_ARMS_P = float(data["guardian"]["GUARDIAN_FOUR_ARMS_P"])
GUARDIAN_THREE_ARMS_P = float(data["guardian"]["GUARDIAN_THREE_ARMS_P"])
GUARDIAN_TWO_ARMS_P = float(data["guardian"]["GUARDIAN_TWO_ARMS_P"])
GUARDIAN_EXCLUSIVE_ARMS_UP_P = float(
data["guardian"]["GUARDIAN_EXCLUSIVE_ARMS_UP_P"]
)
GUARDIAN_EXCLUSIVE_ARMS_OTHER_P = float(
data["guardian"]["GUARDIAN_EXCLUSIVE_ARMS_OTHER_P"]
)
except KeyError:
data["guardian"] = {}
data["guardian"]["GUARDIAN_THREE_CHAR_P"] = config_default_data["guardian"][
"GUARDIAN_THREE_CHAR_P"
]
data["guardian"]["GUARDIAN_TWO_CHAR_P"] = config_default_data["guardian"][
"GUARDIAN_TWO_CHAR_P"
]
data["guardian"]["GUARDIAN_ONE_CHAR_P"] = config_default_data["guardian"][
"GUARDIAN_ONE_CHAR_P"
]
data["guardian"]["GUARDIAN_THREE_CHAR_UP_P"] = config_default_data[
"guardian"
]["GUARDIAN_THREE_CHAR_UP_P"]
data["guardian"]["GUARDIAN_THREE_CHAR_OTHER_P"] = config_default_data[
"guardian"
]["GUARDIAN_THREE_CHAR_OTHER_P"]
data["guardian"]["GUARDIAN_EXCLUSIVE_ARMS_P"] = config_default_data[
"guardian"
]["GUARDIAN_EXCLUSIVE_ARMS_P"]
data["guardian"]["GUARDIAN_FIVE_ARMS_P"] = config_default_data["guardian"][
"GUARDIAN_FIVE_ARMS_P"
]
data["guardian"]["GUARDIAN_FOUR_ARMS_P"] = config_default_data["guardian"][
"GUARDIAN_FOUR_ARMS_P"
]
data["guardian"]["GUARDIAN_THREE_ARMS_P"] = config_default_data["guardian"][
"GUARDIAN_THREE_ARMS_P"
]
data["guardian"]["GUARDIAN_TWO_ARMS_P"] = config_default_data["guardian"][
"GUARDIAN_TWO_ARMS_P"
]
data["guardian"]["GUARDIAN_EXCLUSIVE_ARMS_UP_P"] = config_default_data[
"guardian"
]["GUARDIAN_EXCLUSIVE_ARMS_UP_P"]
data["guardian"]["GUARDIAN_EXCLUSIVE_ARMS_OTHER_P"] = config_default_data[
"guardian"
]["GUARDIAN_EXCLUSIVE_ARMS_OTHER_P"]
try:
PCR_THREE_P = float(data["pcr"]["PCR_THREE_P"])
PCR_TWO_P = float(data["pcr"]["PCR_TWO_P"])
PCR_ONE_P = float(data["pcr"]["PCR_ONE_P"])
except KeyError:
data["pcr"] = {}
data["pcr"]["PCR_THREE_P"] = config_default_data["pcr"]["PCR_THREE_P"]
data["pcr"]["PCR_TWO_P"] = config_default_data["pcr"]["PCR_TWO_P"]
data["pcr"]["PCR_ONE_P"] = config_default_data["pcr"]["PCR_ONE_P"]
try:
AZUR_FIVE_P = float(data["azur"]["AZUR_FIVE_P"])
AZUR_FOUR_P = float(data["azur"]["AZUR_FOUR_P"])
AZUR_THREE_P = float(data["azur"]["AZUR_THREE_P"])
AZUR_TWO_P = float(data["azur"]["AZUR_TWO_P"])
AZUR_ONE_P = float(data["azur"]["AZUR_ONE_P"])
except KeyError:
data["azur"] = {}
data["azur"]["AZUR_FIVE_P"] = config_default_data["azur"]["AZUR_FIVE_P"]
data["azur"]["AZUR_FOUR_P"] = config_default_data["azur"]["AZUR_FOUR_P"]
data["azur"]["AZUR_THREE_P"] = config_default_data["azur"]["AZUR_THREE_P"]
data["azur"]["AZUR_TWO_P"] = config_default_data["azur"]["AZUR_TWO_P"]
data["azur"]["AZUR_ONE_P"] = config_default_data["azur"]["AZUR_ONE_P"]
try:
FGO_SERVANT_FIVE_P = float(data["fgo"]["FGO_SERVANT_FIVE_P"])
FGO_SERVANT_FOUR_P = float(data["fgo"]["FGO_SERVANT_FOUR_P"])
FGO_SERVANT_THREE_P = float(data["fgo"]["FGO_SERVANT_THREE_P"])
FGO_CARD_FIVE_P = float(data["fgo"]["FGO_CARD_FIVE_P"])
FGO_CARD_FOUR_P = float(data["fgo"]["FGO_CARD_FOUR_P"])
FGO_CARD_THREE_P = float(data["fgo"]["FGO_CARD_THREE_P"])
except KeyError:
data["fgo"] = {}
data["fgo"]["FGO_SERVANT_FIVE_P"] = config_default_data["fgo"][
"FGO_SERVANT_FIVE_P"
]
data["fgo"]["FGO_SERVANT_FOUR_P"] = config_default_data["fgo"][
"FGO_SERVANT_FOUR_P"
]
data["fgo"]["FGO_SERVANT_THREE_P"] = config_default_data["fgo"][
"FGO_SERVANT_THREE_P"
]
data["fgo"]["FGO_CARD_FIVE_P"] = config_default_data["fgo"][
"FGO_CARD_FIVE_P"
]
data["fgo"]["FGO_CARD_FOUR_P"] = config_default_data["fgo"][
"FGO_CARD_FOUR_P"
]
data["fgo"]["FGO_CARD_THREE_P"] = config_default_data["fgo"][
"FGO_CARD_THREE_P"
]
try:
ONMYOJI_SP = float(data["onmyoji"]["ONMYOJI_SP"])
ONMYOJI_SSR = float(data["onmyoji"]["ONMYOJI_SSR"])
ONMYOJI_SR = float(data["onmyoji"]["ONMYOJI_SR"])
ONMYOJI_R = float(data["onmyoji"]["ONMYOJI_R"])
except KeyError:
data["onmyoji"] = {}
data["onmyoji"]["ONMYOJI_SP"] = config_default_data["onmyoji"]["ONMYOJI_SP"]
data["onmyoji"]["ONMYOJI_SSR"] = config_default_data["onmyoji"][
"ONMYOJI_SSR"
]
data["onmyoji"]["ONMYOJI_SR"] = config_default_data["onmyoji"]["ONMYOJI_SR"]
data["onmyoji"]["ONMYOJI_R"] = config_default_data["onmyoji"]["ONMYOJI_R"]
json.dump(
data, open(_draw_config, "w", encoding="utf8"), indent=4, ensure_ascii=False
)
-113
View File
@@ -1,113 +0,0 @@
from typing import Optional, Union
class DrawCountManager:
"""
抽卡统计保底
"""
def __init__(self, game_draw_count_rule: tuple, star2name: tuple):
"""
初始化保底统计
例如:DrawCountManager((10, 90, 180), ("4", "5", "5"))
抽卡保底需要的次数和返回的对应名称,例如星级等
"""
# 只有保底
self._data = {}
self._guarantee_tuple = game_draw_count_rule
self._star2name = star2name
def increase(self, key: int, value: int = 1):
"""
用户抽卡次数加1
"""
if self._data.get(key) is None:
self._data[key] = {
"count": value,
}
for x in range(len(self._guarantee_tuple)):
self._data[key][f"count_{x}"] = 0
else:
self._data[key][f"count"] += value
if self._data[key][f"count"] > self._guarantee_tuple[-1]:
self._data[key][f"count"] = self._data[key][f"count"] % self._guarantee_tuple[-1]
def reset(self, key: int):
"""
清空记录
"""
del self._data[key]
def set_count(self, key: int, type_: int, count: int):
if self._data.get(key):
self._data[key][f"count_{type_}"] = count
def check(self, key: int, *args) -> Optional[Union[str, int]]:
"""
是否保底
"""
pass
def get_user_count(self, key: int, type_: Optional[int] = None) -> int:
"""
获取用户当前抽卡次数
"""
if self._data.get(key):
if type_ is None:
return self._data[key]["count"]
return self._data[key][f"count_{type_}"]
return 0
def record_count(self, key: int, type_: int):
"""
抽出对应星级后记录当前次数
"""
if self._data.get(key):
self._data[key][f"count_{type_}"] = self._data[key]["count"]
class GenshinCountManager(DrawCountManager):
def increase(self, key: int, value: int = 1):
"""
用户抽卡次数加1
"""
if self._data.get(key) is None:
self._data[key] = {
"is_up": False,
"count": value,
}
for x in range(len(self._guarantee_tuple)):
self._data[key][f"count_{x}"] = 0
else:
self._data[key][f"count"] += value
if self._data[key][f"count"] > self._guarantee_tuple[-1]:
self._data[key][f"count"] = self._data[key][f"count"] % 180
def set_is_up(self, key: int, value: bool):
if self._data.get(key):
self._data[key]["is_up"] = value
def is_up(self, key: int) -> bool:
if self._data.get(key):
return self._data[key]["is_up"]
return False
def check(self, key: int, *args) -> Optional[Union[str, int]]:
"""
是否保底
"""
# print(self._data)
if self._data.get(key):
for i in [1, 0]:
count = self._data[key]["count"]
if count - self._data[key][f"count_{i}"] == self._guarantee_tuple[i]:
if i in [2, 1]:
# print("clean four count")
self._data[key][f"count_0"] = self._data[key]['count']
self._data[key][f"count_{i}"] = self._data[key]['count']
return self._star2name[i]
return None
+19 -18
View File
@@ -1,8 +1,10 @@
from nonebot.adapters.onebot.v11 import MessageSegment
from nonebot.adapters.cqhttp import MessageSegment
import random
from .update_game_requests_info import update_requests_info
from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card
from .config import DRAW_DATA_PATH, draw_config
from .config import FGO_CARD_FOUR_P, FGO_CARD_FIVE_P, FGO_CARD_THREE_P, FGO_SERVANT_THREE_P, \
FGO_SERVANT_FIVE_P, FGO_SERVANT_FOUR_P, FGO_FLAG, DRAW_PATH
from dataclasses import dataclass
from .init_card_pool import init_game_pool
@@ -43,11 +45,11 @@ async def update_fgo_info():
async def init_fgo_data():
global ALL_CHAR, ALL_CARD
if draw_config.FGO_FLAG:
with (DRAW_DATA_PATH / 'fgo.json').open('r', encoding='utf8') as f:
if FGO_FLAG:
with open(DRAW_PATH + 'fgo.json', 'r', encoding='utf8') as f:
fgo_dict = json.load(f)
ALL_CHAR = init_game_pool('fgo', fgo_dict, FgoChar)
with (DRAW_DATA_PATH / 'fgo_card.json').open('r', encoding='utf8') as f:
with open(DRAW_PATH + 'fgo_card.json', 'r', encoding='utf8') as f:
fgo_dict = json.load(f)
ALL_CARD = init_game_pool('fgo', fgo_dict, FgoChar)
@@ -55,22 +57,21 @@ async def init_fgo_data():
# 抽取卡池
def _get_fgo_card(mode: int = 1):
global ALL_CHAR, ALL_CARD
fgo_config = draw_config.fgo
if mode == 1:
star = get_star([8, 7, 6, 5, 4, 3], [fgo_config.FGO_SERVANT_FIVE_P, fgo_config.FGO_SERVANT_FOUR_P, fgo_config.FGO_SERVANT_THREE_P,
fgo_config.FGO_CARD_FIVE_P, fgo_config.FGO_CARD_FOUR_P, fgo_config.FGO_CARD_THREE_P])
star = get_star([8, 7, 6, 5, 4, 3], [FGO_SERVANT_FIVE_P, FGO_SERVANT_FOUR_P, FGO_SERVANT_THREE_P,
FGO_CARD_FIVE_P, FGO_CARD_FOUR_P, FGO_CARD_THREE_P])
elif mode == 2:
star = get_star([5, 4], [fgo_config.FGO_CARD_FIVE_P, fgo_config.FGO_CARD_FOUR_P])
star = get_star([5, 4], [FGO_CARD_FIVE_P, FGO_CARD_FOUR_P])
else:
star = get_star([8, 7, 6], [fgo_config.FGO_SERVANT_FIVE_P, fgo_config.FGO_SERVANT_FOUR_P, fgo_config.FGO_SERVANT_THREE_P])
star = get_star([8, 7, 6], [FGO_SERVANT_FIVE_P, FGO_SERVANT_FOUR_P, FGO_SERVANT_THREE_P])
if star > 5:
type_ = 'servant'
itype = 'servant'
star -= 3
chars = [x for x in ALL_CHAR if x.star == star if not x.limited]
else:
type_ = 'card'
itype = 'card'
chars = [x for x in ALL_CARD if x.star == star if not x.limited]
return random.choice(chars), 5 - star, type_
return random.choice(chars), 5 - star, itype
# 整理数据
@@ -87,18 +88,18 @@ def _format_card_information(count: int):
card_count += 1
# 四星卡片保底
if card_count == 9:
obj, code, type_ = _get_fgo_card(2)
obj, code, itype = _get_fgo_card(2)
# 三星从者保底
elif servant_count == 10:
obj, code, type_ = _get_fgo_card(3)
obj, code, itype = _get_fgo_card(3)
_count = 0
# 普通抽
else:
obj, code, type_ = _get_fgo_card()
obj, code, itype = _get_fgo_card()
star_list[code] += 1
if type_ == 'card' and code < 2:
if itype == 'card' and code < 2:
card_count = 0
if type_ == 'servant':
if itype == 'servant':
servant_count = 0
if code == 0:
max_star_lst.append(obj.name)
+110 -188
View File
@@ -1,16 +1,10 @@
from nonebot.adapters.onebot.v11 import MessageSegment, Message
import os
from nonebot.adapters.cqhttp import MessageSegment, Message
import random
from .update_game_info import update_info
from .util import (
generate_img,
init_rst,
BaseData,
set_list,
get_star,
init_up_char,
)
from .config import DRAW_DATA_PATH, draw_config
from .count_manager import GenshinCountManager
from .util import generate_img, init_star_rst, BaseData, set_list, get_star, init_up_char
from .config import GENSHIN_FIVE_P, GENSHIN_FOUR_P, GENSHIN_G_FIVE_P, GENSHIN_G_FOUR_P, GENSHIN_THREE_P, I72_ADD, \
DRAW_PATH, GENSHIN_FLAG
from dataclasses import dataclass
from .init_card_pool import init_game_pool
from .announcement import GenshinAnnouncement
@@ -23,11 +17,9 @@ except ModuleNotFoundError:
announcement = GenshinAnnouncement()
draw_count_manager = GenshinCountManager((10, 90), ("4", "5"))
# genshin_five = {}
# genshin_count = {}
# genshin_pl_count = {}
genshin_five = {}
genshin_count = {}
genshin_pl_count = {}
ALL_CHAR = []
ALL_ARMS = []
@@ -35,10 +27,9 @@ ALL_ARMS = []
UP_CHAR = []
UP_ARMS = []
_CURRENT_CHAR_POOL_TITLE = ""
_CURRENT_ARMS_POOL_TITLE = ""
POOL_IMG = ""
_CURRENT_CHAR_POOL_TITLE = ''
_CURRENT_ARMS_POOL_TITLE = ''
POOL_IMG = ''
@dataclass
@@ -48,22 +39,19 @@ class GenshinChar(BaseData):
async def genshin_draw(user_id: int, count: int, pool_name: str):
# 0 1 2
star = ["★★★★★", "★★★★", "★★★"]
(
char_list,
five_dict,
star_num_list,
) = _format_card_information(count, user_id, pool_name)
title = ""
cnlist = ['★★★★★', '★★★★', '★★★']
char_list, five_list, five_index_list, char_dict, star_list = _format_card_information(count, user_id, pool_name)
temp = ''
title = ''
up_type = []
up_list = []
if pool_name == "char" and _CURRENT_CHAR_POOL_TITLE:
if pool_name == 'char' and _CURRENT_CHAR_POOL_TITLE:
up_type = UP_CHAR
title = _CURRENT_CHAR_POOL_TITLE
elif pool_name == "arms" and _CURRENT_ARMS_POOL_TITLE:
elif pool_name == 'arms' and _CURRENT_ARMS_POOL_TITLE:
up_type = UP_ARMS
title = _CURRENT_ARMS_POOL_TITLE
tmp = ""
tmp = ''
if up_type:
for x in up_type:
for operator in x.operators:
@@ -72,217 +60,151 @@ async def genshin_draw(user_id: int, count: int, pool_name: str):
tmp += f'五星UP:{" ".join(x.operators)} \n'
elif x.star == 4:
tmp += f'四星UP:{" ".join(x.operators)}'
rst = init_rst(five_dict, star_num_list, star, up_list)
pool_info = f"当前up池:{title}\n{tmp}" if title else ""
rst = init_star_rst(star_list, cnlist, five_list, five_index_list, up_list)
pool_info = f'当前up池:{title}\n{tmp}' if title else ''
if count > 90:
char_list = set_list(char_list)
return (
pool_info
+ "\n"
+ MessageSegment.image(
"base64://" + await generate_img(char_list, "genshin", star_num_list)
)
+ rst
+ f'\n距离保底发还剩 {draw_count_manager.get_user_count(user_id, 1) % 90} 抽'
+ "\n【五星:0.6%,四星:5.1%\n第72抽开始五星概率每抽加0.585%】"
)
return pool_info + '\n' + MessageSegment.image(
"base64://" + await generate_img(char_list, 'genshin', star_list)) + '\n' + rst[:-1] + \
temp[:-1] + f'\n距离保底发还剩 {90 - genshin_count[user_id] if genshin_count.get(user_id) else "^"} 抽' \
+ "\n【五星:0.6%,四星:5.1%\n第72抽开始五星概率每抽加0.585%】"
async def update_genshin_info():
global ALL_CHAR, ALL_ARMS
url = "https://wiki.biligame.com/ys/角色筛选"
data, code = await update_info(url, "genshin")
url = 'https://wiki.biligame.com/ys/角色筛选'
data, code = await update_info(url, 'genshin')
if code == 200:
ALL_CHAR = init_game_pool("genshin", data, GenshinChar)
url = "https://wiki.biligame.com/ys/武器图鉴"
data, code = await update_info(
url,
"genshin_arms",
)
ALL_CHAR = init_game_pool('genshin', data, GenshinChar)
url = 'https://wiki.biligame.com/ys/武器图鉴'
data, code = await update_info(url, 'genshin_arms', ['头像', '名称', '类型', '稀有度.alt',
'获取途径', '初始基础属性1', '初始基础属性2',
'攻击力(MAX)', '副属性(MAX)', '技能'])
if code == 200:
ALL_ARMS = init_game_pool("genshin_arms", data, GenshinChar)
ALL_ARMS = init_game_pool('genshin_arms', data, GenshinChar)
await _genshin_init_up_char()
async def init_genshin_data():
global ALL_CHAR, ALL_ARMS
if draw_config.GENSHIN_FLAG:
if not (DRAW_DATA_PATH / "genshin.json").exists() or not (DRAW_DATA_PATH / "genshin_arms.json").exists():
if GENSHIN_FLAG:
if not os.path.exists(DRAW_PATH + 'genshin.json') or not os.path.exists(DRAW_PATH + 'genshin_arms.json'):
await update_genshin_info()
else:
with (DRAW_DATA_PATH / "genshin.json").open("r", encoding="utf8") as f:
with open(DRAW_PATH + 'genshin.json', 'r', encoding='utf8') as f:
genshin_dict = json.load(f)
with (DRAW_DATA_PATH / "genshin_arms.json").open("r", encoding="utf8") as f:
with open(DRAW_PATH + 'genshin_arms.json', 'r', encoding='utf8') as f:
genshin_ARMS_dict = json.load(f)
ALL_CHAR = init_game_pool("genshin", genshin_dict, GenshinChar)
ALL_ARMS = init_game_pool("genshin_arms", genshin_ARMS_dict, GenshinChar)
ALL_CHAR = init_game_pool('genshin', genshin_dict, GenshinChar)
ALL_ARMS = init_game_pool('genshin_arms', genshin_ARMS_dict, GenshinChar)
await _genshin_init_up_char()
# 抽取卡池
def _get_genshin_card(mode: int = 1, pool_name: str = "", add: float = 0.0, is_up: bool = False):
"""
mode 1:普通抽 2:四星保底 3:五星保底
"""
def _get_genshin_card(mode: int = 1, pool_name: str = '', add: float = 0.0):
global ALL_ARMS, ALL_CHAR, UP_ARMS, UP_CHAR, _CURRENT_ARMS_POOL_TITLE, _CURRENT_CHAR_POOL_TITLE
genshin_config = draw_config.genshin
if mode == 1:
star = get_star(
[5, 4, 3], [genshin_config.GENSHIN_FIVE_P + add, genshin_config.GENSHIN_FOUR_P, genshin_config.GENSHIN_THREE_P]
)
star = get_star([5, 4, 3], [GENSHIN_FIVE_P + add, GENSHIN_FOUR_P, GENSHIN_THREE_P])
elif mode == 2:
star = get_star([5, 4], [genshin_config.GENSHIN_G_FIVE_P + add, genshin_config.GENSHIN_G_FOUR_P])
star = get_star([5, 4], [GENSHIN_G_FIVE_P + add, GENSHIN_G_FOUR_P])
else:
star = 5
if pool_name == "char":
if pool_name == 'char':
data_lst = UP_CHAR
flag = _CURRENT_CHAR_POOL_TITLE
type_all_lst = ALL_CHAR + [
x for x in ALL_ARMS if x.star == star and x.star < 5
]
elif pool_name == "arms":
itype_all_lst = ALL_CHAR + [x for x in ALL_ARMS if x.star == star and x.star < 5]
elif pool_name == 'arms':
data_lst = UP_ARMS
flag = _CURRENT_ARMS_POOL_TITLE
type_all_lst = ALL_ARMS + [
x for x in ALL_CHAR if x.star == star and x.star < 5
]
itype_all_lst = ALL_ARMS + [x for x in ALL_CHAR if x.star == star and x.star < 5]
else:
data_lst = ""
flag = ""
type_all_lst = ""
data_lst = ''
flag = ''
itype_all_lst = ''
all_lst = ALL_ARMS + ALL_CHAR
# 是否UP
try:
if flag and star > 3:
# 获取up角色列表
up_char_lst = [x.operators for x in data_lst if x.star == star][0]
# print(up_char_lst)
# 成功获取up角色
if random.random() < 0.5 or is_up:
up_char_name = random.choice(up_char_lst)
acquire_char = [x for x in all_lst if x.name == up_char_name][0]
else:
# 无up
all_char_lst = [
x
for x in type_all_lst
if x.star == star and x.name not in up_char_lst and not x.limited
]
acquire_char = random.choice(all_char_lst)
if flag and star > 3 and pool_name:
# 获取up角色列表
up_char_lst = [x.operators for x in data_lst if x.star == star][0]
# 成功获取up角色
if random.random() < 0.5:
up_char_name = random.choice(up_char_lst)
acquire_char = [x for x in all_lst if x.name == up_char_name][0]
else:
chars = [x for x in all_lst if x.star == star and not x.limited]
acquire_char = random.choice(chars)
except IndexError:
# 无up
all_char_lst = [x for x in itype_all_lst if x.star == star and x.name not in up_char_lst and not x.limited]
acquire_char = random.choice(all_char_lst)
else:
chars = [x for x in all_lst if x.star == star and not x.limited]
acquire_char = random.choice(chars)
return acquire_char, 5 - star
def _format_card_information(_count: int, user_id, pool_name):
char_list = [] # 获取角色列表
star_num_list = [0, 0, 0] # 各个星级数量
five_dict = {} # 五星数量
char_list = []
star_list = [0, 0, 0]
five_index_list = []
five_list = []
five_dict = {}
_start_add_count = 72 if pool_name == 'char' else 62
_x = 90 if pool_name == 'char' else 80 # 保底
add = 0.0
pool = UP_CHAR if pool_name == 'char' else UP_ARMS
for _ in range(_count):
draw_count_manager.increase(user_id)
star = draw_count_manager.check(user_id)
if (draw_count_manager.get_user_count(user_id) - draw_count_manager.get_user_count(user_id, 1)) % 90 >= 72:
add += draw_config.genshin.I72_ADD
if star:
star = int(star)
if star == 4:
char, code = _get_genshin_card(2, pool_name, add=add)
draw_count_manager.record_count(user_id, 0)
else:
char, code = _get_genshin_card(3, pool_name, add, draw_count_manager.is_up(user_id))
if genshin_count.get(user_id) and _count <= _x:
f_count = genshin_count[user_id]
else:
f_count = 0
if genshin_pl_count.get(user_id) and _count <= _x:
count = genshin_pl_count[user_id]
else:
count = 0
for i in range(_count):
count += 1
f_count += 1
# 十连保底
if count == 10 and f_count != _x:
if f_count >= _start_add_count:
add += I72_ADD
char, code = _get_genshin_card(2, pool_name, add=add)
count = 0
# 大保底
elif f_count == _x:
char, code = _get_genshin_card(3, pool_name)
else:
char, code = _get_genshin_card(1, pool_name, add, draw_count_manager.is_up(user_id))
if f_count >= _start_add_count:
add += I72_ADD
char, code = _get_genshin_card(pool_name=pool_name, add=add)
if code == 1:
count = 0
star_list[code] += 1
if code == 0:
add = 0
if not five_dict.get(char.name):
five_dict[char.name] = [draw_count_manager.get_user_count(user_id)]
else:
five_dict[char.name].append(draw_count_manager.get_user_count(user_id) % 90)
draw_count_manager.set_count(user_id, 2, draw_count_manager.get_user_count(user_id, 1))
draw_count_manager.record_count(user_id, 0)
draw_count_manager.record_count(user_id, 1)
if char.name not in [x.operators for x in pool if x.star == 5][0]:
draw_count_manager.set_is_up(user_id, True)
else:
draw_count_manager.set_is_up(user_id, False)
star_num_list[code] += 1
if _count <= _x:
genshin_five[user_id] = f_count
add = 0.0
f_count = 0
five_list.append(char.name)
five_index_list.append(i)
try:
five_dict[char.name] += 1
except KeyError:
five_dict[char.name] = 1
char_list.append(char)
return char_list, five_dict, star_num_list
# if genshin_count.get(user_id) and _count <= 90:
# f_count = genshin_count[user_id]
# else:
# f_count = 0
# if genshin_pl_count.get(user_id) and _count <= 90:
# count = genshin_pl_count[user_id]
# else:
# count = 0
# for i in range(_count):
# count += 1
# f_count += 1
# # 十连保底
# if count == 10 and f_count != 90:
# if f_count >= 72:
# add += I72_ADD
# char, code = _get_genshin_card(2, pool_name, add=add)
# count = 0
# # 大保底
# elif f_count == 90:
# char, code = _get_genshin_card(3, pool_name)
# else:
# if f_count >= 72:
# add += I72_ADD
# char, code = _get_genshin_card(pool_name=pool_name, add=add)
# if code == 1:
# count = 0
# star_list[code] += 1
# if code == 0:
# if _count <= 90:
# genshin_five[user_id] = f_count
# add = 0.0
# f_count = 0
# five_list.append(char.name)
# five_index_list.append(i)
# try:
# five_dict[char.name] += 1
# except KeyError:
# five_dict[char.name] = 1
# char_list.append(char)
# if _count <= 90:
# genshin_count[user_id] = f_count
# genshin_pl_count[user_id] = count
# return char_list, five_list, five_index_list, five_dict, star_list
if _count <= _x:
genshin_count[user_id] = f_count
genshin_pl_count[user_id] = count
return char_list, five_list, five_index_list, five_dict, star_list
def reset_count(user_id: int):
draw_count_manager.reset(user_id)
genshin_count[user_id] = 0
genshin_pl_count[user_id] = 0
# 获取up和概率
async def _genshin_init_up_char():
global _CURRENT_CHAR_POOL_TITLE, _CURRENT_ARMS_POOL_TITLE, UP_CHAR, UP_ARMS, POOL_IMG
(
_CURRENT_CHAR_POOL_TITLE,
_CURRENT_ARMS_POOL_TITLE,
POOL_IMG,
UP_CHAR,
UP_ARMS,
) = await init_up_char(announcement)
_CURRENT_CHAR_POOL_TITLE, _CURRENT_ARMS_POOL_TITLE, POOL_IMG, UP_CHAR, UP_ARMS = await init_up_char(announcement)
async def reload_genshin_pool():
await _genshin_init_up_char()
return Message(
f"当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE} {POOL_IMG}"
)
return Message(f'当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE} {POOL_IMG}')
+17 -16
View File
@@ -1,12 +1,17 @@
from nonebot.adapters.onebot.v11 import MessageSegment, Message
import os
from nonebot.adapters.cqhttp import MessageSegment, Message
from .update_game_info import update_info
from .announcement import GuardianAnnouncement
from .util import init_star_rst, generate_img, max_card, BaseData,\
set_list, get_star, format_card_information, init_up_char
import random
from .config import DRAW_DATA_PATH, draw_config
from .config import DRAW_PATH, GUARDIAN_ONE_CHAR_P, GUARDIAN_TWO_CHAR_P, GUARDIAN_THREE_CHAR_P, \
GUARDIAN_THREE_CHAR_UP_P, GUARDIAN_TWO_ARMS_P, GUARDIAN_FIVE_ARMS_P, GUARDIAN_THREE_CHAR_OTHER_P, \
GUARDIAN_FOUR_ARMS_P, GUARDIAN_THREE_ARMS_P, GUARDIAN_EXCLUSIVE_ARMS_P, GUARDIAN_EXCLUSIVE_ARMS_UP_P, \
GUARDIAN_EXCLUSIVE_ARMS_OTHER_P, GUARDIAN_FLAG
from dataclasses import dataclass
from .init_card_pool import init_game_pool
from .announcement import GuardianAnnouncement
try:
import ujson as json
except ModuleNotFoundError:
@@ -91,13 +96,13 @@ async def update_guardian_info():
async def init_guardian_data():
global ALL_CHAR, ALL_ARMS
if draw_config.GUARDIAN_FLAG:
if not (DRAW_DATA_PATH / 'guardian.json').exists() or not (DRAW_DATA_PATH / 'guardian_arms.json').exists():
if GUARDIAN_FLAG:
if not os.path.exists(DRAW_PATH + 'guardian.json') or not os.path.exists(DRAW_PATH + 'guardian_arms.json'):
await update_guardian_info()
else:
with (DRAW_DATA_PATH / 'guardian.json').open('r', encoding='utf8') as f:
with open(DRAW_PATH + 'guardian.json', 'r', encoding='utf8') as f:
guardian_char_dict = json.load(f)
with (DRAW_DATA_PATH / 'guardian_arms.json').open('r', encoding='utf8') as f:
with open(DRAW_PATH + 'guardian_arms.json', 'r', encoding='utf8') as f:
guardian_arms_dict = json.load(f)
ALL_CHAR = init_game_pool('guardian', guardian_char_dict, GuardianChar)
ALL_ARMS = init_game_pool('guardian_arms', guardian_arms_dict, GuardianArms)
@@ -107,22 +112,21 @@ async def init_guardian_data():
# 抽取卡池
def _get_guardian_card(pool_name: str = '', mode: int = 1):
global ALL_ARMS, ALL_CHAR, UP_ARMS, UP_CHAR, _CURRENT_ARMS_POOL_TITLE, _CURRENT_CHAR_POOL_TITLE
guardian_config = draw_config.guardian
if pool_name == 'char':
if mode == 1:
star = get_star([3, 2, 1], [guardian_config.GUARDIAN_THREE_CHAR_P, guardian_config.GUARDIAN_TWO_CHAR_P, guardian_config.GUARDIAN_ONE_CHAR_P])
star = get_star([3, 2, 1], [GUARDIAN_THREE_CHAR_P, GUARDIAN_TWO_CHAR_P, GUARDIAN_ONE_CHAR_P])
else:
star = get_star([3, 2], [guardian_config.GUARDIAN_THREE_CHAR_P, guardian_config.GUARDIAN_TWO_CHAR_P])
star = get_star([3, 2], [GUARDIAN_THREE_CHAR_P, GUARDIAN_TWO_CHAR_P])
up_lst = UP_CHAR
flag = _CURRENT_CHAR_POOL_TITLE
_max_star = 3
all_data = ALL_CHAR
else:
if mode == 1:
star = get_star([5, 4, 3, 2], [guardian_config.GUARDIAN_FIVE_ARMS_P, guardian_config.GUARDIAN_FOUR_ARMS_P,
guardian_config.GUARDIAN_THREE_ARMS_P, guardian_config.GUARDIAN_TWO_ARMS_P])
star = get_star([5, 4, 3, 2], [GUARDIAN_FIVE_ARMS_P, GUARDIAN_FOUR_ARMS_P,
GUARDIAN_THREE_ARMS_P, GUARDIAN_TWO_ARMS_P])
else:
star = get_star([5, 4], [guardian_config.GUARDIAN_FIVE_ARMS_P, guardian_config.GUARDIAN_FOUR_ARMS_P])
star = get_star([5, 4], [GUARDIAN_FIVE_ARMS_P, GUARDIAN_FOUR_ARMS_P])
up_lst = UP_ARMS
flag = _CURRENT_ARMS_POOL_TITLE
_max_star = 5
@@ -154,6 +158,3 @@ async def _guardian_init_up_char():
async def reload_guardian_pool():
await _guardian_init_up_char()
return Message(f'当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE}')
+56 -123
View File
@@ -1,204 +1,137 @@
from typing import Any
from .config import DRAW_DATA_PATH
from .util import is_number
from nonebot.log import logger
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:
import json
def init_game_pool(game: str, data: dict, operator: Any):
def init_game_pool(game: str, data: dict, Operator: Any):
tmp_lst = []
if game == "prts":
if game == 'prts':
for key in data.keys():
limited = False
recruit_only = False
event_only = False
if "限定寻访" in data[key]["获取途径"]:
if '限定寻访' in data[key]['获取途径']:
limited = True
if "干员寻访" not in data[key]["获取途径"] and "公开招募" in data[key]["获取途径"]:
if '干员寻访' not in data[key]['获取途径'] and '公开招募' in data[key]['获取途径']:
recruit_only = True
if "活动获取" in data[key]["获取途径"]:
if '活动获取' in data[key]['获取途径']:
event_only = True
if "干员寻访" not in data[key]["获取途径"] and "凭证交易所" == data[key]["获取途径"][0]:
if '干员寻访' not in data[key]['获取途径'] and '凭证交易所' == data[key]['获取途径'][0]:
limited = True
if "干员寻访" not in data[key]["获取途径"] and "信用累计奖励" == data[key]["获取途径"][0]:
if '干员寻访' not in data[key]['获取途径'] and '信用累计奖励' == data[key]['获取途径'][0]:
limited = True
if key.find("阿米娅") != -1:
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,
)
)
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":
if game == 'genshin':
for key in data.keys():
if key.find("旅行者") != -1:
if key.find('旅行者') != -1:
continue
limited = False
if data[key]["常驻/限定"] == "限定UP":
if data[key]['常驻/限定'] == '限定UP':
limited = True
try:
tmp_lst.append(
operator(name=key, star=int(data[key]["稀有度"][:1]), limited=limited)
)
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":
if game == 'genshin_arms':
for key in data.keys():
if data[key]["获取途径"].find("祈愿") != -1:
if data[key]['获取途径'].find('祈愿') != -1:
limited = False
if data[key]["获取途径"].find("限定祈愿") != -1:
if data[key]['获取途径'].find('限定祈愿') != -1:
limited = True
try:
tmp_lst.append(
operator(
name=key, star=int(data[key]["稀有度"][:1]), limited=limited
)
)
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":
if game == 'pretty':
for key in data.keys():
try:
tmp_lst.append(
operator(name=key, star=data[key]["初始星级"], limited=False)
)
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":
if game == 'pretty_card':
for key in data.keys():
limited = False
if "卡池" not in data[key]["获取方式"]:
if '卡池' not in data[key]['获取方式']:
limited = True
if not data[key]["获取方式"]:
if not data[key]['获取方式']:
limited = False
try:
tmp_lst.append(
operator(
name=data[key]["中文名"],
star=len(data[key]["稀有度"]),
limited=limited,
)
)
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"]:
if game in ['guardian', 'guardian_arms']:
for key in data.keys():
tmp_lst.append(
operator(name=data[key]["名称"], star=int(data[key]["星级"]), limited=False)
)
if game == "pcr":
tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=False))
if game == 'pcr':
for key in data.keys():
limited = False
if key.find("(") != -1:
if key.find('(') != -1:
limited = True
try:
tmp_lst.append(
operator(
name=data[key]["名称"], star=int(data[key]["星级"]), limited=limited
)
)
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":
if game == 'azur':
for key in data.keys():
if is_number(data[key]["星级"]):
if is_number(data[key]['星级']):
limited = False
if "可以建造" not in data[key]["获取途径"]:
if '可以建造' not in data[key]['获取途径']:
limited = True
try:
tmp_lst.append(
operator(
name=data[key]["名称"],
star=int(data[key]["星级"]),
limited=limited,
type_=data[key]["类型"],
)
)
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"]:
if game in ['fgo', 'fgo_card']:
for key in data.keys():
limited = False
try:
if (
"圣晶石召唤" not in data[key]["入手方式"]
and "圣晶石召唤(Story卡池)" not in data[key]["入手方式"]
):
if "圣晶石召唤" not in data[key]['入手方式'] and "圣晶石召唤(Story卡池)" not in data[key]['入手方式']:
limited = True
except KeyError:
pass
try:
tmp_lst.append(
operator(
name=data[key]["名称"], star=int(data[key]["星级"]), limited=limited
)
)
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":
if game == 'onmyoji':
for key in data.keys():
limited = False
if key in [
"奴良陆生",
"卖药郎",
"鬼灯",
"阿香",
"蜜桃&芥子",
"犬夜叉",
"杀生丸",
"桔梗",
"朽木露琪亚",
"黑崎一护",
"灶门祢豆子",
"灶门炭治郎",
]:
if key in ['奴良陆生', '卖药郎', '鬼灯', '阿香', '蜜桃&芥子', '犬夜叉', '杀生丸', '桔梗', '朽木露琪亚', '黑崎一护',
'灶门祢豆子', '灶门炭治郎']:
limited = True
try:
tmp_lst.append(
operator(
name=data[key]["名称"], star=data[key]["星级"], limited=limited
)
)
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 = (
DRAW_DATA_PATH
/ f"draw_card"
/ "draw_card_up"
/ f"{game.split('_')[0]}_up_char.json"
)
up_char_file = Path(f'{DATA_PATH}/draw_card/draw_card_up/{game.split("_")[0]}_up_char.json')
if up_char_file.exists():
data = json.load(open(up_char_file, "r", encoding="utf8"))
if len(game.split("_")) == 1:
key = "char"
data = json.load(open(up_char_file, 'r', encoding='utf8'))
if len(game.split('_')) == 1:
key = 'char'
else:
key = list(data.keys())[1]
for x in data[key]["up_char"]:
for char in data[key]["up_char"][x]:
for x in data[key]['up_char']:
for char in data[key]['up_char'][x]:
if char not in char_name_lst:
if game.find("prts") != -1:
tmp_lst.append(
operator(
name=char,
star=int(x),
recruit_only=False,
event_only=False,
limited=False,
)
)
if game.find('prts') != -1:
tmp_lst.append(Operator(name=char, star=int(x),
recruit_only=False, event_only=False, limited=False))
else:
tmp_lst.append(operator(name=char, star=int(x), limited=False))
tmp_lst.append(Operator(name=char, star=int(x), limited=False))
return tmp_lst
+7 -6
View File
@@ -1,8 +1,9 @@
from nonebot.adapters.onebot.v11 import MessageSegment
from nonebot.adapters.cqhttp import MessageSegment
import random
from .update_game_requests_info import update_requests_info
from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card
from .config import DRAW_DATA_PATH, draw_config
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
try:
@@ -38,8 +39,8 @@ async def update_onmyoji_info():
async def init_onmyoji_data():
global ALL_CHAR
if draw_config.ONMYOJI_FLAG:
with (DRAW_DATA_PATH / 'onmyoji.json').open('r', encoding='utf8') as f:
if ONMYOJI_FLAG:
with open(DRAW_PATH + 'onmyoji.json', 'r', encoding='utf8') as f:
azur_dict = json.load(f)
ALL_CHAR = init_game_pool('onmyoji', azur_dict, OnmyojiChar)
@@ -55,8 +56,7 @@ onmyoji_star = {
# 抽取卡池
def _get_onmyoji_card():
global ALL_CHAR
onmyoji_config = draw_config.onmyoji
star = get_star([5, 4, 3, 2], [onmyoji_config.ONMYOJI_SP, onmyoji_config.ONMYOJI_SSR, onmyoji_config.ONMYOJI_SR, onmyoji_config.ONMYOJI_R])
star = get_star([5, 4, 3, 2], [ONMYOJI_SP, ONMYOJI_SSR, ONMYOJI_SR, ONMYOJI_R])
chars = [x for x in ALL_CHAR if x.star == onmyoji_star[star] and not x.limited]
return random.choice(chars), 5 - star
@@ -79,3 +79,4 @@ def format_card_information(count: int):
obj_dict[obj.name] = 1
obj_list.append(obj)
return obj_list, obj_dict, star_list, rst
+8 -12
View File
@@ -1,16 +1,13 @@
from nonebot.adapters.onebot.v11 import MessageSegment
import ujson as json
from nonebot.adapters.cqhttp import MessageSegment
import random
from .update_game_info import update_info
from .update_game_simple_info import update_simple_info
from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card
from .config import DRAW_DATA_PATH, draw_config
from .config import PCR_TWO_P, PCR_THREE_P, PCR_ONE_P, DRAW_PATH, PCR_FLAG, PCR_G_TWO_P, PCR_G_THREE_P, PCR_TAI
from dataclasses import dataclass
from .init_card_pool import init_game_pool
try:
import ujson as json
except ModuleNotFoundError:
import json
ALL_CHAR = []
@@ -33,7 +30,7 @@ async def pcr_draw(count: int):
async def update_pcr_info():
global ALL_CHAR
if draw_config.PCR_TAI:
if PCR_TAI:
url = 'https://wiki.biligame.com/pcr/角色图鉴'
data, code = await update_simple_info(url, 'pcr')
else:
@@ -45,8 +42,8 @@ async def update_pcr_info():
async def init_pcr_data():
global ALL_CHAR
if draw_config.PCR_FLAG:
with (DRAW_DATA_PATH / 'pcr.json').open('r', encoding='utf8') as f:
if PCR_FLAG:
with open(DRAW_PATH + 'pcr.json', 'r', encoding='utf8') as f:
pcr_dict = json.load(f)
ALL_CHAR = init_game_pool('pcr', pcr_dict, PcrChar)
@@ -54,11 +51,10 @@ async def init_pcr_data():
# 抽取卡池
def _get_pcr_card(mode: int = 1):
global ALL_CHAR
pcr_config = draw_config.pcr
if mode == 2:
star = get_star([3, 2], [pcr_config.PCR_G_THREE_P, pcr_config.PCR_G_TWO_P])
star = get_star([3, 2], [PCR_G_THREE_P, PCR_G_TWO_P])
else:
star = get_star([3, 2, 1], [pcr_config.PCR_THREE_P, pcr_config.PCR_TWO_P, pcr_config.PCR_ONE_P])
star = get_star([3, 2, 1], [PCR_THREE_P, PCR_TWO_P, PCR_ONE_P])
chars = [x for x in ALL_CHAR if x.star == star and not x.limited]
return random.choice(chars), 3 - star
+13 -12
View File
@@ -1,12 +1,13 @@
from nonebot.adapters.onebot.v11 import MessageSegment
from .announcement import PrettyAnnouncement
from .update_game_info import update_info
from .announcement import PrettyAnnouncement
from .util import init_star_rst, generate_img, max_card, BaseData, \
set_list, get_star, format_card_information, init_up_char
import random
from .config import DRAW_DATA_PATH, draw_config
from .config import PRETTY_THREE_P, PRETTY_TWO_P, DRAW_PATH, PRETTY_ONE_P, PRETTY_FLAG
from dataclasses import dataclass
from .init_card_pool import init_game_pool
from nonebot.adapters.cqhttp import MessageSegment, Message
try:
import ujson as json
@@ -73,8 +74,7 @@ async def pretty_draw(count: int, pool_name):
rst = init_star_rst(star_list, cnlist, three_list, three_olist, up_list)
if count > 90:
obj_list = set_list(obj_list)
return pool_info + MessageSegment.image(
"base64://" + await generate_img(obj_list, 'pretty', star_list)) \
return pool_info + MessageSegment.image("base64://" + await generate_img(obj_list, 'pretty', star_list)) \
+ '\n' + rst[:-1] + '\n' + max_card(obj_dict)
@@ -93,10 +93,10 @@ async def update_pretty_info():
async def init_pretty_data():
global ALL_CHAR, ALL_CARD
if draw_config.PRETTY_FLAG:
with (DRAW_DATA_PATH / 'pretty.json').open('r', encoding='utf8') as f:
if PRETTY_FLAG:
with open(DRAW_PATH + 'pretty.json', 'r', encoding='utf8') as f:
pretty_char_dict = json.load(f)
with (DRAW_DATA_PATH / 'pretty_card.json').open('r', encoding='utf8') as f:
with open(DRAW_PATH + 'pretty_card.json', 'r', encoding='utf8') as f:
pretty_card_dict = json.load(f)
ALL_CHAR = init_game_pool('pretty', pretty_char_dict, PrettyChar)
ALL_CARD = init_game_pool('pretty_card', pretty_card_dict, PrettyChar)
@@ -106,11 +106,10 @@ async def init_pretty_data():
# 抽取卡池
def _get_pretty_card(pool_name: str, mode: int = 1):
global ALL_CHAR, ALL_CARD, _CURRENT_CHAR_POOL_TITLE, _CURRENT_CARD_POOL_TITLE
pretty_config = draw_config.pretty
if mode == 1:
star = get_star([3, 2, 1], [pretty_config.PRETTY_THREE_P, pretty_config.PRETTY_TWO_P, pretty_config.PRETTY_ONE_P])
star = get_star([3, 2, 1], [PRETTY_THREE_P, PRETTY_TWO_P, PRETTY_ONE_P])
else:
star = get_star([3, 2], [pretty_config.PRETTY_THREE_P, pretty_config.PRETTY_TWO_P])
star = get_star([3, 2], [PRETTY_THREE_P, PRETTY_TWO_P])
if pool_name == 'card':
title = _CURRENT_CARD_POOL_TITLE
up_data = UP_CARD
@@ -128,6 +127,7 @@ def _get_pretty_card(pool_name: str, mode: int = 1):
acquire_operator = random.choice(all_up_star)
if pool_name == 'char':
acquire_operator = acquire_operator.split(']')[1]
print(acquire_operator)
acquire_operator = [x for x in data if x.name == acquire_operator][0]
else:
acquire_operator = random.choice([x for x in data if x.star == star and not x.limited])
@@ -144,5 +144,6 @@ async def _pretty_init_up_char():
async def reload_pretty_pool():
await _pretty_init_up_char()
return f'当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_CARD_POOL_TITLE} {POOL_IMG}'
return Message(f'当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_CARD_POOL_TITLE} {POOL_IMG}')
+13 -9
View File
@@ -1,12 +1,14 @@
from nonebot.adapters.onebot.v11 import MessageSegment, Message
from nonebot.adapters.cqhttp import MessageSegment, Message
import random
from .config import DRAW_DATA_PATH, draw_config
from .config import PRTS_FIVE_P, PRTS_FOUR_P, PRTS_SIX_P, PRTS_THREE_P, DRAW_PATH, PRTS_FLAG
from .update_game_info import update_info
from .util import generate_img, init_star_rst, max_card, BaseData, UpEvent, set_list, get_star
from .init_card_pool import init_game_pool
from pathlib import Path
from .announcement import PrtsAnnouncement
from services.log import logger
from dataclasses import dataclass
from nonebot.log import logger
try:
import ujson as json
except ModuleNotFoundError:
@@ -15,6 +17,8 @@ except ModuleNotFoundError:
announcement = PrtsAnnouncement()
up_char_file = Path() / "data" / "draw_card" / "draw_card_up" / "prts_up_char.json"
prts_dict = {}
UP_OPERATOR = []
ALL_OPERATOR = []
@@ -67,8 +71,8 @@ async def update_prts_info():
async def init_prts_data():
global prts_dict, ALL_OPERATOR
if draw_config.PRTS_FLAG:
with (DRAW_DATA_PATH / 'prts.json').open('r', encoding='utf8') as f:
if PRTS_FLAG:
with open(DRAW_PATH + 'prts.json', 'r', encoding='utf8') as f:
prts_dict = json.load(f)
ALL_OPERATOR = init_game_pool('prts', prts_dict, Operator)
await _init_up_char()
@@ -76,8 +80,7 @@ async def init_prts_data():
# 抽取干员
def _get_operator_card(add: float):
prts_config = draw_config.prts
star = get_star([6, 5, 4, 3], [prts_config.PRTS_SIX_P + add, prts_config.PRTS_FIVE_P, prts_config.PRTS_FOUR_P, prts_config.PRTS_THREE_P])
star = get_star([6, 5, 4, 3], [PRTS_SIX_P + add, PRTS_FIVE_P, PRTS_FOUR_P, PRTS_THREE_P])
if _CURRENT_POOL_TITLE:
zooms = [x.zoom for x in UP_OPERATOR if x.star == star]
zoom = 0
@@ -89,11 +92,12 @@ def _get_operator_card(add: float):
else:
weight = z
up_operator_name = ""
# UPs
# UP
try:
if 0 < zoom:
if random.random() < zoom:
up_operators = [x.operators for x in UP_OPERATOR if x.star == star and x.zoom < 1][0]
up_operator_name = random.choice(up_operators)
# print(up_operator_name)
acquire_operator = [x for x in ALL_OPERATOR if x.name == up_operator_name][0]
else:
all_star_operators = [x for x in ALL_OPERATOR if x.star == star
+27 -19
View File
@@ -1,28 +1,36 @@
from nonebot.rule import Rule
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.typing import T_State
from .config import draw_config
from .config import (
GENSHIN_FLAG,
PRTS_FLAG,
PRETTY_FLAG,
GUARDIAN_FLAG,
PCR_FLAG,
AZUR_FLAG,
FGO_FLAG,
ONMYOJI_FLAG,
)
def is_switch(game_name: str) -> Rule:
async def _is_switch(bot: Bot, event: MessageEvent, state: T_State) -> bool:
if game_name == 'prts':
return draw_config.PRTS_FLAG
if game_name == 'genshin':
return draw_config.GENSHIN_FLAG
if game_name == 'pretty':
return draw_config.PRETTY_FLAG
if game_name == 'guardian':
return draw_config.GUARDIAN_FLAG
if game_name == 'pcr':
return draw_config.PCR_FLAG
if game_name == 'azur':
return draw_config.AZUR_FLAG
if game_name == 'fgo':
return draw_config.FGO_FLAG
if game_name == 'onmyoji':
return draw_config.ONMYOJI_FLAG
if game_name == "prts":
return PRTS_FLAG
if game_name == "genshin":
return GENSHIN_FLAG
if game_name == "pretty":
return PRETTY_FLAG
if game_name == "guardian":
return GUARDIAN_FLAG
if game_name == "pcr":
return PCR_FLAG
if game_name == "azur":
return AZUR_FLAG
if game_name == "fgo":
return FGO_FLAG
if game_name == "onmyoji":
return ONMYOJI_FLAG
else:
return False
+33 -44
View File
@@ -1,12 +1,12 @@
from typing import Tuple
from .config import DRAW_DATA_PATH
from .config import DRAW_PATH
from asyncio.exceptions import TimeoutError
from bs4 import BeautifulSoup
from .util import download_img
from urllib.parse import unquote
from services.log import logger
from .util import remove_prohibited_str
from utils.http_utils import AsyncHttpx
from nonebot.log import logger
from httpx import ConnectTimeout, CloseError
import bs4
import re
try:
@@ -18,16 +18,15 @@ except ModuleNotFoundError:
headers = {'User-Agent': '"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"'}
async def update_info(url: str, game_name: str, info_list: list = None) -> Tuple[dict, int]:
info_path = DRAW_DATA_PATH / f"{game_name}.json"
async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict, int':
try:
with info_path.open('r', encoding='utf8') as f:
with open(DRAW_PATH + f'{game_name}.json', 'r', encoding='utf8') as f:
data = json.load(f)
except (ValueError, FileNotFoundError):
data = {}
try:
response = await AsyncHttpx.get(url, timeout=7)
soup = BeautifulSoup(response.text, 'lxml')
text = (await AsyncHttpx.get(url)).text
soup = BeautifulSoup(text, 'lxml')
_tbody = get_tbody(soup, game_name, url)
trs = _tbody.find_all('tr')
att_dict, start_index, index = init_attr(game_name)
@@ -59,10 +58,13 @@ async def update_info(url: str, game_name: str, info_list: list = None) -> Tuple
data[name] = member_dict
logger.info(f'{name} is update...')
data = await _last_check(data, game_name)
except TimeoutError:
except (TimeoutError, ConnectTimeout, CloseError):
logger.warning(f'更新 {game_name} 超时...')
return {}, 999
with info_path.open('w', encoding='utf8') as wf:
except Exception as e:
logger.error(f"更新 {game_name} 未知错误 {type(e)}:{e}")
return {}, 998
with open(DRAW_PATH + f'{game_name}.json', 'w', encoding='utf8') as wf:
wf.write(json.dumps(data, ensure_ascii=False, indent=4))
return data, 200
@@ -97,25 +99,21 @@ def _find_last_tag(element: bs4.element.Tag, attr: str, game_name: str) -> str:
# 获取大图(小图快爬)
async def _modify_avatar_url(game_name: str, char_name: str):
if game_name == 'prts':
res = await AsyncHttpx.get(f'https://wiki.biligame.com/arknights/{char_name}', timeout=7)
soup = BeautifulSoup(res.text, 'lxml')
try:
img_url = str(soup.find('img', {'class': 'img-bg'})['srcset']).split(' ')[-2]
except KeyError:
img_url = str(soup.find('img', {'class': 'img-bg'})['src'])
return img_url
# if game_name == 'prts':
# async with session.get(f'https://wiki.biligame.com/arknights/{char_name}', timeout=7) as res:
# soup = BeautifulSoup(await res.text(), 'lxml')
# try:
# img_url = str(soup.find('img', {'class': 'img-bg'})['srcset']).split(' ')[-2]
# except KeyError:
# img_url = str(soup.find('img', {'class': 'img-bg'})['src'])
# return img_url
if game_name == 'genshin':
return None
if game_name == 'pretty_card':
res = await AsyncHttpx.get(f'https://wiki.biligame.com/umamusume/{char_name}', timeout=7)
soup = BeautifulSoup(res.text, 'lxml')
try:
img_url = soup.find('div', {'class': 'support_card-left'}).find('div').find('img').get('src')
return img_url
except AttributeError:
logger.warning("pretty_card 获取大图像失败")
return None
text = (await AsyncHttpx.get(f'https://wiki.biligame.com/umamusume/{char_name}')).text
soup = BeautifulSoup(text, 'lxml')
img_url = soup.find('div', {'class': 'support_card-left'}).find('div').find('img').get('src')
return img_url
if game_name == 'guardian':
# 未上传图片太多,换成像素图
# async with session.get(f'https://wiki.biligame.com/gt/{char_name}', timeout=7) as res:
@@ -126,7 +124,7 @@ async def _modify_avatar_url(game_name: str, char_name: str):
# except KeyError:
# img_url = str(soup.find('img', {'class': 'img-kk'})['src'])
# except TypeError:
# print(f'{char_name} 图片还未上传,跳过...')
# logger.info(f'{char_name} 图片还未上传,跳过...')
# img_url = ''
# return img_url
return None
@@ -135,17 +133,18 @@ async def _modify_avatar_url(game_name: str, char_name: str):
# 数据最后处理(是否需要额外数据或处理数据)
async def _last_check(data: dict, game_name: str):
# if game_name == 'prts':
# url = 'https://wiki.biligame.com/arknights/'
# tasks = []
# for key in data.keys():
# tasks.append(asyncio.ensure_future(_async_update_prts_extra_info(key, session)))
# tasks.append(asyncio.ensure_future(_async_update_prts_extra_info(url, key, session)))
# asyResult = await asyncio.gather(*tasks)
# for x in asyResult:
# for key in x.keys():
# data[key]['获取途径'] = x[key]['获取途径']
if game_name == 'genshin':
for key in data.keys():
res = await AsyncHttpx.get(f'https://wiki.biligame.com/ys/{key}', timeout=7)
soup = BeautifulSoup(res.text, 'lxml')
text = (await AsyncHttpx.get(f'https://wiki.biligame.com/ys/{key}')).text
soup = BeautifulSoup(text, 'lxml')
_trs = ''
for table in soup.find_all('table', {'class': 'wikitable'}):
if str(table).find('常驻/限定') != -1:
@@ -180,13 +179,10 @@ async def _last_check(data: dict, game_name: str):
# 对抓取每行数据是否需要额外处理?
def intermediate_check(member_dict: dict, key: str, game_name: str, td: bs4.element.Tag):
if game_name == "genshin_arms":
if key == "稀有度":
member_dict["稀有度"] = td.find("img")["alt"].split('.')[0]
if game_name == 'prts':
if key == '获取途径':
msg = re.search('<td.*?>([\\s\\S]*)</td>', str(td)).group(1).strip()
msg = msg[:-1] if msg and msg[-1] == '\n' else msg
msg = msg[:-1] if msg[-1] == '\n' else msg
if msg.find('<a') != -1:
for a in td.find_all('a'):
msg = msg.replace(str(a), a.text)
@@ -194,13 +190,6 @@ def intermediate_check(member_dict: dict, key: str, game_name: str, td: bs4.elem
if game_name == 'pretty':
if key == '初始星级':
member_dict['初始星级'] = len(td.find_all('img'))
if game_name == 'pretty_card':
if key == '获取方式':
obtain = []
for x in str(td.text).replace('\n', '').strip().split('、'):
if x:
obtain.append(x)
member_dict['获取方式'] = obtain
if game_name == 'guardian':
if key == '头像':
member_dict['星级'] = str(td.find('span').find('img')['alt'])[-5]
@@ -265,7 +254,7 @@ def get_tbody(soup: bs4.BeautifulSoup, game_name: str, url: str):
return _tbody
# async def _async_update_prts_extra_info(key: str, session: aiohttp.ClientSession):
# async def _async_update_prts_extra_info(url: str, key: str, session: aiohttp.ClientSession):
# for i in range(10):
# try:
# async with session.get(f'https://wiki.biligame.com/arknights/{key}', timeout=7) as res:
@@ -285,11 +274,11 @@ def get_tbody(soup: bs4.BeautifulSoup, game_name: str, url: str):
# if r:
# text += r.group(1) + ' '
# obtain[i] = obtain[i].split('<a')[0] + text[:-1] + obtain[i].split('</a>')[-1]
# print(f'明日方舟获取额外信息 {key}...{obtain}')
# logger.info(f'明日方舟获取额外信息 {key}...{obtain}')
# x = {key: {}}
# x[key]['获取途径'] = obtain
# return x
# except TimeoutError:
# print(f'访问 https://wiki.biligame.com/arknights/{key} 第 {i}次 超时...已再次访问')
# logger.warning(f'访问{url}{key} 第 {i}次 超时...已再次访问')
# return {}

Some files were not shown because too many files have changed in this diff Show More