Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00b674cebb | ||
|
|
8ac440335e | ||
|
|
4b1821ce42 | ||
|
|
3ad955abf9 | ||
|
|
5fabb974ce | ||
|
|
5325bc3e32 | ||
|
|
6688c4626b | ||
|
|
2b95ab3d7e | ||
|
|
23e6d7e27e | ||
|
|
2760e22336 | ||
|
|
d026d09f98 | ||
|
|
e6fd1ce791 | ||
|
|
342eaa9a97 | ||
|
|
dc7681357e | ||
|
|
b61cb49c1a | ||
|
|
c7b341393d | ||
|
|
1f9fa2adb9 | ||
|
|
133b927d9d | ||
|
|
46e6b26d75 | ||
|
|
8d0b0e5505 | ||
|
|
754a0c111c | ||
|
|
81ef3f04e4 | ||
|
|
e7c00484b3 | ||
|
|
065432448f | ||
|
|
5d45a9c28a | ||
|
|
7db5b3b5c0 | ||
|
|
5eb64060dc | ||
|
|
2c4877b9f8 | ||
|
|
218dad3b86 | ||
|
|
974c6b106a | ||
|
|
954b281b69 | ||
|
|
b1b15b63a1 | ||
|
|
49567aa958 | ||
|
|
a7a470066b | ||
|
|
4e3010d75e | ||
|
|
cbacd726ef | ||
|
|
58a1fc1ca0 | ||
|
|
a704f88d75 | ||
|
|
10d0ad7d47 | ||
|
|
b47a29eb67 | ||
|
|
887177913d | ||
|
|
b6b0dc85bf | ||
|
|
29f47878e9 | ||
|
|
440b548a4f | ||
|
|
5191953657 | ||
|
|
877ac72761 | ||
|
|
685befee6b | ||
|
|
7afb099c12 | ||
|
|
21a5feda43 | ||
|
|
b7b16cfd21 | ||
|
|
615f3a58e9 | ||
|
|
f65fd73d6d | ||
|
|
6a8eb9e67a | ||
|
|
8b7adf0a6a | ||
|
|
973182c27c | ||
|
|
0dced0bc90 | ||
|
|
fc34cd541a | ||
|
|
8090ebe8ce | ||
|
|
f87c14595f | ||
|
|
39bb5a9ab9 | ||
|
|
f754ad1c76 | ||
|
|
37e1a06528 | ||
|
|
7096d258db |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
# 绪山真寻Bot
|
# 绪山真寻Bot
|
||||||
****
|
****
|
||||||
@@ -11,7 +11,9 @@
|
|||||||
用爱发电,某些功能学习借鉴了大佬们的代码,因为绪山真寻实在太可爱了因此开发了
|
用爱发电,某些功能学习借鉴了大佬们的代码,因为绪山真寻实在太可爱了因此开发了
|
||||||
绪山真寻bot,实现了一些对群友的娱乐功能和实用功能(大概)。
|
绪山真寻bot,实现了一些对群友的娱乐功能和实用功能(大概)。
|
||||||
|
|
||||||
如果该项目的图片等等侵犯猫豆腐老师权益请联系我删除!
|
如果该项目的图片等等侵犯猫豆腐老师权益请联系我删除!
|
||||||
|
|
||||||
|
如果希望有个地方讨论绪山真寻Bot,或者有问题或建议,可以发送issues或加入[ <strong>[是真寻酱哒](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) </strong>]
|
||||||
|
|
||||||
## 声明
|
## 声明
|
||||||
此项目仅用于学习交流,请勿用于非法用途
|
此项目仅用于学习交流,请勿用于非法用途
|
||||||
@@ -29,7 +31,6 @@
|
|||||||
- [x] 图灵AI(会把'你'等关键字替换为你的昵称),且带有 [AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus),够味
|
- [x] 图灵AI(会把'你'等关键字替换为你的昵称),且带有 [AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus),够味
|
||||||
- [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置)
|
- [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置)
|
||||||
- [x] 发送某文件夹下的随机图片(支持自定义,默认:美图,萝莉,壁纸)
|
- [x] 发送某文件夹下的随机图片(支持自定义,默认:美图,萝莉,壁纸)
|
||||||
- [x] 尝试搜索不色的图片 ↑↑
|
|
||||||
- [x] 色图(这不是基础功能嘛喂)
|
- [x] 色图(这不是基础功能嘛喂)
|
||||||
- [x] coser
|
- [x] coser
|
||||||
- [x] 黑白草图生成器
|
- [x] 黑白草图生成器
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
|
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
|
||||||
- [x] 金币红包
|
- [x] 金币红包
|
||||||
- [x] 微博热搜
|
- [x] 微博热搜
|
||||||
|
- [x] B站主播/UP/番剧订阅
|
||||||
|
|
||||||
- [x] pil对图片的一些操作
|
- [x] pil对图片的一些操作
|
||||||
- [x] BUFF饰品底价查询(需要session)
|
- [x] BUFF饰品底价查询(需要session)
|
||||||
@@ -69,7 +71,7 @@
|
|||||||
- [x] 我的信息(只是为了看看什么时候入群)
|
- [x] 我的信息(只是为了看看什么时候入群)
|
||||||
- [x] 更新信息(如果继续更新的话)
|
- [x] 更新信息(如果继续更新的话)
|
||||||
- [x] go-cqhttp最新版下载和上传(不需要请删除)
|
- [x] go-cqhttp最新版下载和上传(不需要请删除)
|
||||||
- [x] 撤回 (使用[nonebot-plugin-withdraw](https://github.com/MeetWq/nonebot-plugin-withdraw)插件)
|
- [x] 撤回
|
||||||
- [x] 滴滴滴-(用户对超级用户发送消息)
|
- [x] 滴滴滴-(用户对超级用户发送消息)
|
||||||
- [x] 金币红包/金币排行
|
- [x] 金币红包/金币排行
|
||||||
- [x] 俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
|
- [x] 俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
|
||||||
@@ -81,7 +83,7 @@
|
|||||||
|
|
||||||
### 已实现的管理员功能
|
### 已实现的管理员功能
|
||||||
- [x] 更新群组成员信息
|
- [x] 更新群组成员信息
|
||||||
- [x] 95%的群功能开关 (基于[nonebot_plugin_manager](https://github.com/Jigsaw111/nonebot_plugin_manager)插件修改)
|
- [x] 95%的群功能开关
|
||||||
- [x] 查看群内被动技能状态
|
- [x] 查看群内被动技能状态
|
||||||
- [x] 自定义群欢迎消息(是真寻的不是管家的!)
|
- [x] 自定义群欢迎消息(是真寻的不是管家的!)
|
||||||
- [x] .ban/.unban(支持设置ban时长)= 黑白名单
|
- [x] .ban/.unban(支持设置ban时长)= 黑白名单
|
||||||
@@ -89,9 +91,10 @@
|
|||||||
- [x] 上传图片/连续上传图片 (上传图片至指定图库)
|
- [x] 上传图片/连续上传图片 (上传图片至指定图库)
|
||||||
- [x] 移动图片 (同上)
|
- [x] 移动图片 (同上)
|
||||||
- [x] 删除图片 (同上)
|
- [x] 删除图片 (同上)
|
||||||
|
- [x] 群内B站订阅
|
||||||
|
|
||||||
### 已实现的超级用户功能
|
### 已实现的超级用户功能
|
||||||
- [x] 添加/删除管理(是真寻的管理员权限,不是群管理员)
|
- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
|
||||||
- [x] 开启/关闭指定群的广播通知
|
- [x] 开启/关闭指定群的广播通知
|
||||||
- [x] 广播
|
- [x] 广播
|
||||||
- [x] 自检(检查系统状态)
|
- [x] 自检(检查系统状态)
|
||||||
@@ -103,7 +106,6 @@
|
|||||||
- [x] 节日红包发送
|
- [x] 节日红包发送
|
||||||
- [x] 修改群权限
|
- [x] 修改群权限
|
||||||
- [x] ban
|
- [x] ban
|
||||||
- [x] 添加/删除群白名单
|
|
||||||
- [x] 更新色图
|
- [x] 更新色图
|
||||||
- [x] 更新价格/更加图片(csgo开箱)
|
- [x] 更新价格/更加图片(csgo开箱)
|
||||||
- [x] 重载原神/方舟/赛马娘/坎公骑冠剑卡池
|
- [x] 重载原神/方舟/赛马娘/坎公骑冠剑卡池
|
||||||
@@ -111,8 +113,10 @@
|
|||||||
- [x] PIX相关操作
|
- [x] PIX相关操作
|
||||||
- [x] 检查更新真寻
|
- [x] 检查更新真寻
|
||||||
- [x] 重启
|
- [x] 重启
|
||||||
- [x] 添加/删除群白名单
|
- [x] 添加/删除/查看群白名单
|
||||||
- [x] 功能开关(更多设置)
|
- [x] 功能开关(更多设置)
|
||||||
|
- [x] 功能状态
|
||||||
|
- [x] b了
|
||||||
|
|
||||||
#### 超级用户的被动技能
|
#### 超级用户的被动技能
|
||||||
- [x] 邀请入群提醒(别人邀请真寻入群)
|
- [x] 邀请入群提醒(别人邀请真寻入群)
|
||||||
@@ -122,7 +126,7 @@
|
|||||||
- [x] 进群欢迎消息
|
- [x] 进群欢迎消息
|
||||||
- [x] 群早晚安
|
- [x] 群早晚安
|
||||||
- [x] 每日开箱重置提醒
|
- [x] 每日开箱重置提醒
|
||||||
- [x] b站转发解析(解析b站分享信息,支持bv,bilibili链接,b站手机端转发卡片,cv,b23.tv)
|
- [x] b站转发解析(解析b站分享信息,支持bv,bilibili链接,b站手机端转发卡片,cv,b23.tv),且5分钟内不解析相同url
|
||||||
- [x] 丢人爬(爬表情包)
|
- [x] 丢人爬(爬表情包)
|
||||||
- [x] epic通知(每日发送epic免费游戏链接)
|
- [x] epic通知(每日发送epic免费游戏链接)
|
||||||
- [x] 原神黄历提醒
|
- [x] 原神黄历提醒
|
||||||
@@ -145,10 +149,12 @@
|
|||||||
|
|
||||||
### 常用功能
|
### 常用功能
|
||||||
|
|
||||||
|
** [*]:表示该参数可有多个 [?]:表示参数可选 **
|
||||||
|
|
||||||
| 功能 | 指令 | 说明
|
| 功能 | 指令 | 说明
|
||||||
| ----------------------| :--------------------------------------:| :------------------------:
|
| ----------------------| :--------------------------------------:| :------------------------:
|
||||||
| 签到 | 签到/我的签到/好感度排行/好感度总榜/好感度总榜\[显示我/屏蔽我] | 普通的签到插件,可以获得好感度和金币<br>好感度影响开箱次数和涩图触发概率,金币用于购买道具,俄罗斯轮盘赌注以及金币红包<br>好感度总榜,显示所有群的群员好感度排行,可通过命令好感度总榜\[显示我/屏蔽我] 来设置是否隐藏
|
| 签到 | 签到/我的签到/好感度排行/好感度总榜/好感度总榜\[显示我/屏蔽我] | 普通的签到插件,可以获得好感度和金币<br>好感度影响开箱次数和涩图触发概率,金币用于购买道具,俄罗斯轮盘赌注以及金币红包<br>好感度总榜,显示所有群的群员好感度排行,可通过命令好感度总榜\[显示我/屏蔽我] 来设置是否隐藏
|
||||||
| 发送图片 | 美图/壁纸/萝莉 \[id](默认随机)/\[num]张图\[keyword] | 发送指定文件夹下的图片<br>示例:萝莉->发送img文件夹下luoli文件夹下的图片<br>在线搜索一些不色的图,示例:3张图米浴
|
| 发送图片 | 美图/壁纸/萝莉 \[id]?(默认随机)/\[num]张图\[keyword] | 发送指定文件夹下的图片<br>示例:萝莉->发送img文件夹下luoli文件夹下的图片<br>在线搜索一些不色的图,示例:3张图米浴
|
||||||
| 色图 | 色图/色图xx/n张色图/n张xx的色图/查色图(查询本地色图信息)/色图r【n<10】 | 色图r返回10张r18色图(仅私聊),并限制每日次数(默认5次)<br>其他示例:色图 真寻 <br>5张真寻的色图
|
| 色图 | 色图/色图xx/n张色图/n张xx的色图/查色图(查询本地色图信息)/色图r【n<10】 | 色图r返回10张r18色图(仅私聊),并限制每日次数(默认5次)<br>其他示例:色图 真寻 <br>5张真寻的色图
|
||||||
| 黑白草图 | 黑白草图/黑白图 \[文字] \[图片] | 整活生成器,示例:黑白图 我喜欢真寻 \[图片]
|
| 黑白草图 | 黑白草图/黑白图 \[文字] \[图片] | 整活生成器,示例:黑白图 我喜欢真寻 \[图片]
|
||||||
| coser | coser/cos/括丝 | coser图片,说实话挺失望的,太色了
|
| coser | coser/cos/括丝 | coser图片,说实话挺失望的,太色了
|
||||||
@@ -156,7 +162,7 @@
|
|||||||
| 戳一戳 | 戳一戳 | 随机发送钉宫语音 or 美图 or 萝莉图 or 文本
|
| 戳一戳 | 戳一戳 | 随机发送钉宫语音 or 美图 or 萝莉图 or 文本
|
||||||
| 模拟开箱 | 开箱 \[武器箱名称](默认随机)/N连开箱 \[武器箱名称](默认随机)/我的开箱/群开箱统计/我的金色 | 当不指定武器箱时默认随机,此功能需要先在/open_cases/config.py中编写指定武器箱数据,然后提前爬取价格,使用超级用户命令更新cookie后,再使用命令更新xx武器箱【注:未设置爬取频率,可能会被禁用api(请谨慎!!用小号!!)】
|
| 模拟开箱 | 开箱 \[武器箱名称](默认随机)/N连开箱 \[武器箱名称](默认随机)/我的开箱/群开箱统计/我的金色 | 当不指定武器箱时默认随机,此功能需要先在/open_cases/config.py中编写指定武器箱数据,然后提前爬取价格,使用超级用户命令更新cookie后,再使用命令更新xx武器箱【注:未设置爬取频率,可能会被禁用api(请谨慎!!用小号!!)】
|
||||||
| 鲁迅说过 | 鲁迅说过 \[文本] | 示例:鲁迅说过 真寻世界第一可爱
|
| 鲁迅说过 | 鲁迅说过 \[文本] | 示例:鲁迅说过 真寻世界第一可爱
|
||||||
| 假消息 | 假消息 \[网址] \[标题] \[内容](可选) \[图片](可选) | 构造虚假的分享消息
|
| 假消息 | 假消息 \[网址] \[标题] \[内容]? \[图片]? | 构造虚假的分享消息
|
||||||
| 商店系统 | 商店/我的金币/购买道具 \[名称或序号] \[数量](默认1)/使用道具 \[名称或序号] | 示例:<br>购买道具 1 3<br>购买道具 好感度双倍加持卡Ⅰ 3<br>使用道具 1<br>使用道具 好感度双倍加持卡Ⅰ
|
| 商店系统 | 商店/我的金币/购买道具 \[名称或序号] \[数量](默认1)/使用道具 \[名称或序号] | 示例:<br>购买道具 1 3<br>购买道具 好感度双倍加持卡Ⅰ 3<br>使用道具 1<br>使用道具 好感度双倍加持卡Ⅰ
|
||||||
| 抽卡系统 | 原神/明日方舟/赛马娘/坎公骑冠剑/碧蓝航线/阴阳师/公主连结(pcr)/FGO N抽/一井 | 详细帮助请查看: [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw) <br>示例:原神90抽
|
| 抽卡系统 | 原神/明日方舟/赛马娘/坎公骑冠剑/碧蓝航线/阴阳师/公主连结(pcr)/FGO N抽/一井 | 详细帮助请查看: [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw) <br>示例:原神90抽
|
||||||
| 我有一个朋友 | 我有一个朋友他说/想问问/\[文本] | 会将文本中的(他,她,它)替换成 '我'<br>示例:我有一个朋友想问问他喜不喜欢真寻
|
| 我有一个朋友 | 我有一个朋友他说/想问问/\[文本] | 会将文本中的(他,她,它)替换成 '我'<br>示例:我有一个朋友想问问他喜不喜欢真寻
|
||||||
@@ -170,20 +176,20 @@
|
|||||||
| 金币排行 | 金币排行 | 字面意思
|
| 金币排行 | 金币排行 | 字面意思
|
||||||
|网易云热评 | 到点了/12点了/网易云热评/网易云评论 | 防下塔
|
|网易云热评 | 到点了/12点了/网易云热评/网易云评论 | 防下塔
|
||||||
| 古诗 | 念诗/念首诗/来首诗 | 突然文艺起来了
|
| 古诗 | 念诗/念首诗/来首诗 | 突然文艺起来了
|
||||||
|微博热搜 | 微博热搜/微博热搜[序号] | 快捷热搜查询方式
|
|微博热搜 | 微博热搜/微博热搜[序号]? | 快捷热搜查询方式
|
||||||
| pil对图片的操作 | 修改尺寸/等比压缩/旋转图片/水平翻转/铅笔滤镜/模糊效果/锐化效果/高斯模糊/边缘检测/底色替换 | 选项较多,请直接发送 真寻图片帮助
|
| pil对图片的操作 | 修改尺寸/等比压缩/旋转图片/水平翻转/铅笔滤镜/模糊效果/锐化效果/高斯模糊/边缘检测/底色替换 | 选项较多,请直接发送 真寻图片帮助
|
||||||
| BUFF皮肤底价查询 | 查询皮肤 \[武器名称] \[皮肤名称] | 网络不友好的话会经常超时<br>示例:查询皮肤 沙漠之鹰 印花集
|
| BUFF皮肤底价查询 | 查询皮肤 \[武器名称] \[皮肤名称] | 网络不友好的话会经常超时<br>示例:查询皮肤 沙漠之鹰 印花集
|
||||||
| 天气查询 | \[城市]天气 | 非常常见的插件,第一个入门插件
|
| 天气查询 | \[城市]天气 | 非常常见的插件,第一个入门插件
|
||||||
| 疫情查询 | 疫情/查询疫情 \[城市名或省份名] | 示例:疫情杭州
|
| 疫情查询 | 疫情/查询疫情 \[城市名或省份名] | 示例:疫情杭州
|
||||||
| bt磁力搜索 | bt \[关键词] \[页数](默认第1页) | 该功能仅仅提供给私聊,因为可以搜到一些色色的东西,示例:bt钢铁侠 5
|
| bt磁力搜索 | bt \[关键词] \[页数]?(默认第1页) | 该功能仅仅提供给私聊,因为可以搜到一些色色的东西,示例:bt钢铁侠 5
|
||||||
| 上车 | 略 | 直接查看真寻帮助 上车,每日限制次数(默认5)
|
| 上车 | 略 | 直接查看真寻帮助 上车,每日限制次数(默认5)
|
||||||
| 以图识番 | 识番 \[图片] | 以图搜翻,图片越清晰越完整正确率越高
|
| 以图识番 | 识番 \[图片] | 以图搜翻,图片越清晰越完整正确率越高
|
||||||
| 以图搜图 | 识图 (asc)? \[图片] | 参数asc更换搜索引擎为ascii2d,默认为saucenao
|
| 以图搜图 | 识图 (asc)? \[图片] | 参数asc更换搜索引擎为ascii2d,默认为saucenao
|
||||||
| 点歌 | 点歌 \[歌名] | 网易云点歌小助手
|
| 点歌 | 点歌 \[歌名] | 网易云点歌小助手
|
||||||
| 搜番 | 搜番 \[关键字] | 群聊只返回5个结果,私聊返回20个结果
|
| 搜番 | 搜番 \[关键字] | 群聊只返回5个结果,私聊返回20个结果
|
||||||
| epic白嫖游戏通知 | epic | 通知你又到了白嫖游戏的时候,可以不玩,不能没有
|
| epic白嫖游戏通知 | epic | 通知你又到了白嫖游戏的时候,可以不玩,不能没有
|
||||||
| P站排行榜 | p站排行 \[排行类型参数](默认日榜) \[数量](可选) \[日期](可选)| 9种不同排行榜,r18类型仅可私聊,通过参数选择,查看真寻帮助p站排行<br>示例:p站排行榜 1 9 2018-4-25
|
| P站排行榜 | p站排行 \[排行类型参数]? \[数量]? \[日期]?| 9种不同排行榜,r18类型仅可私聊,通过参数选择,查看真寻帮助p站排行<br>示例:p站排行榜 1 9 2018-4-25
|
||||||
| 搜图 | 搜图 \[关键词] \[数量](可选) \[排序方式](可选) \[r18](可选)| r18仅可私聊,查看真寻帮助搜图
|
| 搜图 | 搜图 \[关键词] \[数量]? \[排序方式]? \[r18]?| r18仅可私聊,查看真寻帮助搜图
|
||||||
| 通过PID搜索图片 | p搜 [pid] | 在群内使用此功能会在30秒内撤回
|
| 通过PID搜索图片 | p搜 [pid] | 在群内使用此功能会在30秒内撤回
|
||||||
| 翻译 | 英翻/日翻/韩翻/翻韩/翻日/翻英 \[文本] | 三种语言互相翻译
|
| 翻译 | 英翻/日翻/韩翻/翻韩/翻日/翻英 \[文本] | 三种语言互相翻译
|
||||||
| 获取b站视频封面 | b封面 [链接/av/bv/cv/直播id] | 快捷的封面获取方式
|
| 获取b站视频封面 | b封面 [链接/av/bv/cv/直播id] | 快捷的封面获取方式
|
||||||
@@ -191,13 +197,15 @@
|
|||||||
| 自我介绍 | 自我介绍 | 没错,一份正经的真寻自我介绍
|
| 自我介绍 | 自我介绍 | 没错,一份正经的真寻自我介绍
|
||||||
| 我的权限 | 我的权限 | 真寻内部定义的一套权限系统
|
| 我的权限 | 我的权限 | 真寻内部定义的一套权限系统
|
||||||
| 我的信息 | 我的信息 | 唯一的作用就是看看什么时候加入群
|
| 我的信息 | 我的信息 | 唯一的作用就是看看什么时候加入群
|
||||||
| 撤回 | 撤回 \[消息位置](默认为最新一条消息) | 按顺序撤回发送的消息,示例:撤回 1
|
| 撤回 | 撤回 \[消息位置]?(默认为最新一条消息) | 按顺序撤回发送的消息,示例:撤回 1
|
||||||
| 滴滴滴- | 滴滴滴- \[文本] | 用于用户联系真寻的超级用户
|
| 滴滴滴- | 滴滴滴- \[文本] | 用于用户联系真寻的超级用户
|
||||||
|功能调用统计可视化 | 功能调用统计(自记录以来的功能调用统计)<br>周功能调用统计 [plugin_name]<br>月功能调用统计 [plugin_name]| 当plugin_name为空时为7天或30内的所有功能统计
|
|功能调用统计可视化 | 功能调用统计(自记录以来的功能调用统计)<br>周功能调用统计 [plugin_name]<br>月功能调用统计 [plugin_name]| 当plugin_name为空时为7天或30内的所有功能统计
|
||||||
| pix | pix/PIX [tags/uid/pid:pid] [num] | 无参数时随机查看pix图库的图片(无r18),num数量默认=1,tags:查看相关tags图片,uid:查找相关画师图片,pid:pid:指定查看pid图片<br>示例:pix原神 3<br>pix23493844<br>pixpid:29429933
|
| pix | pix/PIX [tags/uid/pid:pid] [num] | 无参数时随机查看pix图库的图片(无r18),num数量默认=1,tags:查看相关tags图片,uid:查找相关画师图片,pid:pid:指定查看pid图片<br>示例:pix原神 3<br>pix23493844<br>pixpid:29429933
|
||||||
| 添加pix关键词/uid/pid | 添加pix关键词/uid/pid *[关键词/uid/pid]| 添加关键词或uid或pid用于下次搜索,关键词搜索相关tag,uid会收录作者下收藏符合标准的作品,pid收录单张作品<br>示例:添加pix关键词 原神<br> 添加pixuid 123441<br>添加pixpid 2748937|
|
| 添加pix关键词/uid/pid | 添加pix关键词/uid/pid *[关键词/uid/pid]| 添加关键词或uid或pid用于下次搜索,关键词搜索相关tag,uid会收录作者下收藏符合标准的作品,pid收录单张作品<br>示例:添加pix关键词 原神<br> 添加pixuid 123441<br>添加pixpid 2748937|
|
||||||
| 查看pix图库 | 查看pix图库 [tags] | 查看已收录的tag相关图片数量<br>示例:查看pix图库 原神 莫娜
|
| 查看pix图库 | 查看pix图库 [tags] | 查看已收录的tag相关图片数量<br>示例:查看pix图库 原神 莫娜
|
||||||
|显示pix关键词 | 显示pix关键词 | 查看已收录的所有关键词/UID/PID
|
|显示pix关键词 | 显示pix关键词 | 查看已收录的所有关键词/UID/PID
|
||||||
|
| b了 | b了 [at] | 使真寻完全忽略一个用户的所有信息
|
||||||
|
| B站订阅 | 添加订阅 [主播/UP/番剧] [id/链接/番名] / 删除订阅 [id] / 查看订阅 | 可以通过直接间链接或主播间id添加订阅主播开播提醒,动态和投稿,可以通过番名,番剧的id,或者番剧链接添加番剧订阅(是番剧id,md开头,不是集数id,ep开头的)更新, 可以通过UP个人id或UP主页链接订阅UP动态和投稿
|
||||||
|
|
||||||
### 管理员功能
|
### 管理员功能
|
||||||
|
|
||||||
@@ -210,18 +218,19 @@
|
|||||||
| 查看群被动技能 | 2 | 群通知状态 | 详细请查看被动技能列表
|
| 查看群被动技能 | 2 | 群通知状态 | 详细请查看被动技能列表
|
||||||
| 被动技能开关 | 2 | 开启/关闭被动技能 | 有时候花里胡哨通知也会很烦人
|
| 被动技能开关 | 2 | 开启/关闭被动技能 | 有时候花里胡哨通知也会很烦人
|
||||||
| 自定义群欢迎消息 | 2 | 自定义群欢迎消息 \[文本] \[图片] | 文本和图片至少需要一个,在文本内添加"\[at]"字符串可以用来设置艾特进群的新群员
|
| 自定义群欢迎消息 | 2 | 自定义群欢迎消息 \[文本] \[图片] | 文本和图片至少需要一个,在文本内添加"\[at]"字符串可以用来设置艾特进群的新群员
|
||||||
| 黑名单 | 5 | .ban/.unban \[at] \[小时](可选) \[分钟](可选)| 不提供具体时间的话则ban掉永久,且权限低的用户无法unban高权限用户的ban,同级权限也无法进行ban/unban <br>示例:.ban@笨蛋 1 50
|
| 黑名单 | 5 | .ban/.unban \[at] \[小时]? \[分钟]?| 不提供具体时间的话则ban掉永久,且权限低的用户无法unban高权限用户的ban,同级权限也无法进行ban/unban <br>示例:.ban@笨蛋 1 50
|
||||||
| 刷屏检测相关 | 5 | 刷屏检测设置/设置检测时间 \[文本]/设置检测次数 \[文本]/设置禁言时长 \[分钟]| 非常讨厌刷屏的人,打算给他们一点教训
|
| 刷屏检测相关 | 5 | 刷屏检测设置/设置检测时间 \[文本]/设置检测次数 \[文本]/设置禁言时长 \[分钟]| 非常讨厌刷屏的人,打算给他们一点教训
|
||||||
| 上传图片 | 6 | 上传图片 \[图库] \[图片]... | 上传图片至指定图库,虽然并不打算开放给群员,但还是写了,支持批量图片<br>示例:上传图片 美图 \[图片]..
|
| 上传图片 | 6 | 上传图片 \[图库] \[图片]... | 上传图片至指定图库,虽然并不打算开放给群员,但还是写了,支持批量图片<br>示例:上传图片 美图 \[图片]..
|
||||||
| 删除图片 | 6 | 删除图片 [图库] \[图片id] | 通过指定本地图片id来删除指定图库的图片<br>示例:删除图片 美图 1
|
| 删除图片 | 6 | 删除图片 [图库] \[图片id] | 通过指定本地图片id来删除指定图库的图片<br>示例:删除图片 美图 1
|
||||||
| 移动图片 | 6 | 移动图片 \[移出的图库] \[移入的图库] \[图片id] | 移动指定图库中的图片到指定的新图库中,移入的图片id更改为移入图库的最后一位,移除的图库中原本图片的id又最后一位图片替代<br>示例:移动图片 美图 萝莉 22
|
| 移动图片 | 6 | 移动图片 \[移出的图库] \[移入的图库] \[图片id] | 移动指定图库中的图片到指定的新图库中,移入的图片id更改为移入图库的最后一位,移除的图库中原本图片的id又最后一位图片替代<br>示例:移动图片 美图 萝莉 22
|
||||||
|
|B站订阅 | 5 | 功能同上,就是在群中有权限限制 | 略
|
||||||
|
|
||||||
### 超级用户功能
|
### 超级用户功能
|
||||||
|
|
||||||
| 功能 | 指令 | 说明
|
| 功能 | 指令 | 说明
|
||||||
| ----------------------| :--------------------------------------:| :------------------------:
|
| ----------------------| :--------------------------------------:| :------------------------:
|
||||||
| 权限增删 | 添加/删除权限 \[at] \[level]<br>添加/删除权限 [qq] [group] [level] | 用于添加或修改权限等级,且该权限不会被自动更新取消
|
| 权限增删 | 添加/删除权限 \[at] \[level]<br>添加/删除权限 [qq] [group] [level] | 用于添加或修改权限等级,且该权限不会被自动更新取消
|
||||||
| 查看群组/好友 | 查看群组/好友 | 查看真寻添加的群组与好友
|
| 所有群组/好友 | 所有群组/好友 | 查看真寻添加的群组与好友
|
||||||
| 广播 | 广播- [文本] | 广播所有群组
|
| 广播 | 广播- [文本] | 广播所有群组
|
||||||
| 更新色图 | 更新色图 | 更新群友搜索色图时保存的url
|
| 更新色图 | 更新色图 | 更新群友搜索色图时保存的url
|
||||||
| 回复 | /t | 命令较多,请查看/t帮助,省略群号则私聊用户(必须要有用户的好友)
|
| 回复 | /t | 命令较多,请查看/t帮助,省略群号则私聊用户(必须要有用户的好友)
|
||||||
@@ -231,240 +240,28 @@
|
|||||||
| 检查系统状态 | 自检 | 略
|
| 检查系统状态 | 自检 | 略
|
||||||
| 更新好友/群组信息| 更新好友/群组信息 | 包含自动更新,被t出群等等有更好的可视信息
|
| 更新好友/群组信息| 更新好友/群组信息 | 包含自动更新,被t出群等等有更好的可视信息
|
||||||
| 重载卡池 | 略 | 重载抽卡的游戏卡池,请查看 \[nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw)
|
| 重载卡池 | 略 | 重载抽卡的游戏卡池,请查看 \[nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw)
|
||||||
| 添加商品 | 添加商品 \[名称]-\[价格]-\[描述]-\[折扣](小数)(可选)-\[限时时间](分钟)(可选) | 为真寻的商店添加一点点道具<br>示例:添加商品-昏睡红茶-300-一杯上好的奇怪红茶-0.9-60
|
| 添加商品 | 添加商品 \[名称]-\[价格]-\[描述]-\[折扣](小数)?-\[限时时间](分钟)? | 为真寻的商店添加一点点道具<br>示例:添加商品-昏睡红茶-300-一杯上好的奇怪红茶-0.9-60
|
||||||
| 删除商品 | 删除商品 \[名称或序号] | 在真寻的商店中删除一点东西
|
| 删除商品 | 删除商品 \[名称或序号] | 在真寻的商店中删除一点东西
|
||||||
| 修改商品 | 修改商品 -name \[名称或序号] -price \[价格] -des \[描述] -discount \[折扣] -time \[限时]| 注意空格,不需要的参数可以不加<br>示例:修改商品 -name 1 -price 900 【修改序号为1的商品的价格为900】
|
| 修改商品 | 修改商品 -name \[名称或序号] -price \[价格] -des \[描述] -discount \[折扣] -time \[限时]| 注意空格,不需要的参数可以不加<br>示例:修改商品 -name 1 -price 900 【修改序号为1的商品的价格为900】
|
||||||
| 节日红包 | 节日红包 \[金额] \[数量] \[祝福语](可选) \[群号](可选)... | 群号支持批量,使用空格隔开,不使用群号则对所有群发送节日红包,节日红包有效时间为24小时,祝福语默认为“恭喜发财 大吉大利”<br>示例:节日红包 10000 15 真寻真可爱 123324423 23423423
|
| 节日红包 | 节日红包 \[金额] \[数量] \[祝福语]? \[群号]?... | 群号支持批量,使用空格隔开,不使用群号则对所有群发送节日红包,节日红包有效时间为24小时,祝福语默认为“恭喜发财 大吉大利”<br>示例:节日红包 10000 15 真寻真可爱 123324423 23423423
|
||||||
| 修改群权限 | 修改群权限 \[group] \[level] | 所以说这功能是对内鬼的无奈,默认群权限为5,默认无法使用 色图/coser/p站排行/搜图(这些功能都要9级权限)
|
| 修改群权限 | 修改群权限 \[group] \[level] | 所以说这功能是对内鬼的无奈,默认群权限为5,默认无法使用 色图/coser/p站排行/搜图(这些功能都要9级权限)
|
||||||
|更新原神今日素材| 更新原神今日素材 | 自动更新原神每日素材失败时可以手动触发
|
|更新原神今日素材| 更新原神今日素材 | 自动更新原神每日素材失败时可以手动触发
|
||||||
|更新原神资源信息| 更新原神资源信息 | 除了每日自动更新的资源外,额外更新大地图
|
|更新原神资源信息| 更新原神资源信息 | 除了每日自动更新的资源外,额外更新大地图
|
||||||
| 清理数据 | 清理数据 | 清理 temp,rar,r18_rar 文件夹的文件数据
|
| 清理数据 | 清理数据 | 清理 temp,rar,r18_rar 文件夹的文件数据
|
||||||
|添加pix关键词/uid/pid | 添加pix关键词/uid/pid [keyword/pid:pid/uid:uid] [-f]? | 与普通功能相同,额外可以通过参数 -f 强制通过检测
|
|添加pix关键词/uid/pid | 添加pix关键词/uid/pid [keyword/pid:pid/uid:uid] [-f]? | 与普通功能相同,额外可以通过参数 -f 强制通过检测
|
||||||
|删除pix关键词 | 删除pix关键词 *[keyword/uid/pid:pid] | 删除已收录的keyword/uid/pid
|
|删除pix关键词 | 删除pix关键词 *[keyword/uid/pid:pid] | 删除已收录的keyword/uid/pid
|
||||||
|更新pix关键词 | 更新pix关键词 [keyword/pid:pid/uid:uid] [num]| 更新keyword,uid,pid或指定uid,pid,未指定时,则更新全部,当num未指定时为keyword/uid/pid更新全部<br>示例:更新pix关键词<br>更新pix关键词uid 8<br>更新pix关键词pid:83457477
|
|更新pix关键词 | 更新pix关键词 [keyword/pid:pid/uid:uid] [num]?| 更新keyword,uid,pid或指定uid,pid,未指定时,则更新全部,当num未指定时为keyword/uid/pid更新全部<br>示例:更新pix关键词<br>更新pix关键词uid 8<br>更新pix关键词pid:83457477<br>num:倒叙更新数量
|
||||||
|删除pix图片 | 删除pix图片 [*pid] [-b]? | [-b]参数为删除的同时加入黑名单(不再更新),虽然是pid,但是_p也可以<br>示例:删除pix图片3458344 8235234_p1 -b
|
|删除pix图片 | 删除pix图片 [*pid] [-b]? | [-b]参数为删除的同时加入黑名单(不再更新),虽然是pid,但是_p也可以<br>示例:删除pix图片3458344 8235234_p1 -b
|
||||||
|显示pix关键词 | 显示pix关键词 | 与普通功能相同,额外显示待收录和黑名单
|
|显示pix关键词 | 显示pix关键词 | 与普通功能相同,额外显示待收录和黑名单
|
||||||
|pix检测更新 | pix检测更新 [update]? | 检测从未更新过的pid或uid,-update参数将在检测后直接更新未更新过的pid或uid<br>示例:pix检测更新 update
|
|pix检测更新 | pix检测更新 [update]? | 检测从未更新过的pid或uid,-update参数将在检测后直接更新未更新过的pid或uid<br>示例:pix检测更新 update
|
||||||
| 检查更新真寻 | 检查更新真寻 | 不再需要麻烦的clone第一步
|
| 检查更新真寻 | 检查更新真寻 | 不再需要麻烦的clone第一步
|
||||||
| 关闭功能 | 关闭[功能] [group/private]/*[群号] | 关闭色图:维护功能(关闭总开关)<br>关闭色图 g:在群内限制功能<br>关闭色图 p:在私聊限制功能<br>关闭色图 1234678:禁用12345678的色图功能
|
| 关闭功能 | 关闭[功能] [group/private]/*[群号]? | 关闭色图:维护功能(关闭总开关)<br>关闭色图 g:在群内限制功能<br>关闭色图 p:在私聊限制功能<br>关闭色图 1234678:禁用12345678的色图功能
|
||||||
| 群白名单 | 添加/删除群白名单 *[群号] | 白名单内的群不会受到 维护 限制
|
| 群白名单 | 添加/删除群白名单 *[群号] / 查看群白名单 | 白名单内的群不会受到 维护 限制
|
||||||
|
| 功能状态 | 功能状态 | 查看功能开关状态
|
||||||
|
| pix | pix [-s/-r] [keyword] | 可以通过pix -s 查看图库的涩图,pix -r查看图库的r18图,支持搜索,当然,pix图库只区分了r18和非r18,如果-s查询到不色的图也问题不大
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 部分功能展示
|
|
||||||
<details>
|
|
||||||
<summary>部分功能展示及说明</summary>
|
|
||||||
|
|
||||||
### 帮助以及开关(功能控制)
|
|
||||||
|
|
||||||
群帮助将会在功能左侧展示该功能的开关,带有√或×的功能代表可以开关<br>
|
|
||||||
此插件使用 [nonebot_plugin_manager](https://github.com/Jigsaw111/nonebot_plugin_manager) 并魔改一点实现
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
<br>
|
|
||||||
如果你希望某功能暂时停用<br>
|
|
||||||
私聊发送 npm block xx (xx=功能名)来锁定<br>
|
|
||||||
使用npm unblock xx 进行解锁
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### 签到
|
|
||||||
普普通通的签到,设置影响开箱次数和涩图触发成功的概率(可配置)<br>
|
|
||||||
开箱次数 = 初始开箱数量 + 好感度 / 3<br>
|
|
||||||
金币 = random.randint(100) + random.randint(好感度)【好感度获取的金币不会超过200】
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 黑白草图
|
|
||||||
|
|
||||||
整活生成器(从未设想的道路)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 发送文件夹下随机图片
|
|
||||||
|
|
||||||
提供了 美图589(获取该图库下文件名589.jpg的图片)方法,图库内图片名称需要有序(如:0.jpg,1.jpg....)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 色图
|
|
||||||
|
|
||||||
略,send_setu/check_setu_hash.py文件用于记录涩图hash和检测文件名是否连贯(例如:0.jpg, 1.jpg....)
|
|
||||||
|
|
||||||
### 开箱(csgo模拟开箱)
|
|
||||||
|
|
||||||
我的开箱/群开箱统计/我的金色 功能是对开箱数据的统计展示 <br>
|
|
||||||
|
|
||||||
目前支持的武器箱(数据已备好):
|
|
||||||
* 狂牙大行动武器箱
|
|
||||||
* 突围大行动武器箱
|
|
||||||
* 命悬一线武器箱
|
|
||||||
* 裂空武器箱
|
|
||||||
* 光谱武器箱
|
|
||||||
<br>
|
|
||||||
BUFF账号可能会因为短时间内访问api次数过多被禁止访问api!!
|
|
||||||
如果是第一次启动请先使用命令 “更新价格”, “更新图片” (需要配置cookie!!如果经常超时请设置代理,配置文件中的 buff_proxy!)<br>
|
|
||||||
如果需要配置新的箱子,请在.config.py中配置好该箱子中的皮肤,且列表名是箱子名称的大写拼音<br>
|
|
||||||
示例:光谱武器箱 GUANGPU_CASE_KNIFE,GUANGPU_CASE_RED...后面的颜色代表皮肤品质
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### BUFF皮肤底价查询
|
|
||||||
|
|
||||||
需要配置cookie!!!!!!!!<br>
|
|
||||||
如果经常超时请设置代理,配置文件中的 buff_proxy!
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### coser
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 鸡汤/语录
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 骂我
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 鲁迅说
|
|
||||||
|
|
||||||
此插件使用 [nonebot2_luxun_says](https://github.com/NothAmor/nonebot2_luxun_says)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 假消息
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 商店系统
|
|
||||||
|
|
||||||
商店内的道具支持自定义,但需要写触发后的效果...整不出活,到头来也就增加好感度概率的商品
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### 昵称系统
|
|
||||||
|
|
||||||
养成方法第一步,让可爱的小真寻叫自己昵称!(替换ai中的'你'等等)
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### 抽卡(8种手游的抽卡)
|
|
||||||
|
|
||||||
已单独分离并上传至nb2商店,不再放图片了,项目地址:[nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw)
|
|
||||||
|
|
||||||
### 我有一个朋友...
|
|
||||||
|
|
||||||
使用大佬的插件 [cappuccilo_plugins](https://github.com/pcrbot/cappuccilo_plugins#%E7%94%9F%E6%88%90%E5%99%A8%E6%8F%92%E4%BB%B6)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### 原神黄历/今日素材/丘丘语翻译/地图资源查询
|
|
||||||
|
|
||||||
使用大佬的插件 [Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)
|
|
||||||
|
|
||||||
### 对图片的操作
|
|
||||||
|
|
||||||
只是一些简单对图片操作(娱乐整活)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 识番
|
|
||||||
|
|
||||||
使用大佬的插件 [XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### 识图
|
|
||||||
|
|
||||||
使用nb2商店插件 [nonebot_plugin_picsearcher](https://github.com/synodriver/nonebot_plugin_picsearcher) (可配置图片返回的最大数量)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### epic免费游戏
|
|
||||||
|
|
||||||
访问rsshub获取数据解析<br>可以不玩,不能没有
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### P站排行/搜图
|
|
||||||
|
|
||||||
访问rsshub获取数据解析
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### 翻译
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 自定义群欢迎消息
|
|
||||||
|
|
||||||
关键字 [at] 判断是否艾特入群用户
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 查看当前群欢迎消息
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 自检
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### .ban/.unban
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 查看被动技能(被动技能除复读外都提供了开关)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 自我介绍
|
|
||||||
|
|
||||||
只是一段简单自我介绍,但是,还是想放上来
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 我的信息/我的权限
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 金币红包
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### 俄罗斯轮盘
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
### 其他
|
|
||||||
|
|
||||||
点歌:使用 [nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2) 插件<br>
|
|
||||||
<br><br>
|
|
||||||
## 其他功能请自己试一试 )
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 部署
|
## 部署
|
||||||
|
|
||||||
@@ -491,7 +288,7 @@ pip install -r requirements.txt
|
|||||||
python bot.py
|
python bot.py
|
||||||
```
|
```
|
||||||
|
|
||||||
## 配置(暂时不更新 json 配置,请将USE_CONFIG_FILE设置为False)
|
## 配置
|
||||||
在 configs/config.py 中的 USE_CONFIG_FILE,默认为False
|
在 configs/config.py 中的 USE_CONFIG_FILE,默认为False
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -507,167 +304,68 @@ python bot.py
|
|||||||
在./configs/config.py中配置基本配置(除API KEY ,数据库和代理外都含有默认值)
|
在./configs/config.py中配置基本配置(除API KEY ,数据库和代理外都含有默认值)
|
||||||
在./configs/path_config.py配置路径(含有默认配置)
|
在./configs/path_config.py配置路径(含有默认配置)
|
||||||
|
|
||||||
########(暂时不更新 json 配置,请将USE_CONFIG_FILE设置为False,直接进入./configs/config.py进行配置)
|
|
||||||
# 是否使用配置文件(为True时这将会生成三份配置文件
|
|
||||||
./config.json:主要配置
|
|
||||||
./configs/plugins2cmd_config.json: 功能模块与对应命令配置
|
|
||||||
./configs/other_config.json: 一些插件配置)
|
|
||||||
|
|
||||||
USE_CONFIG_FILE = True
|
USE_CONFIG_FILE = False
|
||||||
|
|
||||||
# 如果不使用配置文件,将USE_CONFIG_FILE设置为False
|
# 如果不使用配置文件,将USE_CONFIG_FILE设置为False
|
||||||
#可在./configs/config.py文件中修改配置,在./configs/path_config.py修改资源路径
|
#可在./configs/config.py文件中修改配置,在./configs/path_config.py修改资源路径
|
||||||
# 已在./configs/config.py和./configs/path_config.py中为各个配置提供注解!
|
# 已在./configs/config.py和./configs/path_config.py中为各个配置提供注解!
|
||||||
```
|
```
|
||||||
|
|
||||||
## 配置文件注解(如果使用配置文件的话)
|
|
||||||
<details>
|
|
||||||
<summary>配置文件注解</summary>
|
|
||||||
./config.json
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
# 必填(影响功能运行)
|
|
||||||
"apikey": {
|
|
||||||
"LOLICON_KEY": "", # loliconAPI,缺失会导致色图功能异常
|
|
||||||
"TL_KEY": [] # 图灵Key(为什么要用列表?因为白嫖用户能拿5个apikey,每个apikey每日限制100条)
|
|
||||||
},
|
|
||||||
|
|
||||||
# (必填!!!)
|
|
||||||
# 数据库配置(如果填写了bind,后面就不用再填了)只是帮你拼接好)
|
|
||||||
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
|
|
||||||
"sql": {
|
|
||||||
"bind": "",
|
|
||||||
"sql_name": "",
|
|
||||||
"user": "",
|
|
||||||
"password": "",
|
|
||||||
"address": "",
|
|
||||||
"port": "",
|
|
||||||
"database": ""
|
|
||||||
},
|
|
||||||
|
|
||||||
# 路径设置(不填则使用默认)
|
|
||||||
"path": {
|
|
||||||
"IMAGE_PATH": "", # 图片路径
|
|
||||||
"VOICE_PATH": "", # 音频路径
|
|
||||||
"TXT_PATH": "", # 文本路径
|
|
||||||
"LOG_PATH": "", # 日志路径
|
|
||||||
"DATA_PATH": "", # 数据路径
|
|
||||||
"DRAW_PATH": "" # 抽卡数据路径
|
|
||||||
"TEMP_PATH": "" # 临时图片路径
|
|
||||||
},
|
|
||||||
|
|
||||||
# 代理设置
|
|
||||||
"proxy": {
|
|
||||||
"system_proxy": "", # 系统代理
|
|
||||||
"buff_proxy": "" # buff代理
|
|
||||||
},
|
|
||||||
|
|
||||||
# RSSHUB地址
|
|
||||||
"rsshub": {
|
|
||||||
"RSSHUBAPP": "https:\/\/docs.rsshub.app\/"
|
|
||||||
},
|
|
||||||
|
|
||||||
# 各个管理员功能 对应的 权限
|
|
||||||
"level": {
|
|
||||||
"DELETE_IMG_LEVEL": 7,
|
|
||||||
"MOVE_IMG_LEVEL": 7,
|
|
||||||
"UPLOAD_LEVEL": 6,
|
|
||||||
"BAN_LEVEL": 5,
|
|
||||||
"OC_LEVEL": 2,
|
|
||||||
"MUTE_LEVEL": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
./configs/plugins2cmd_config.json
|
|
||||||
```
|
|
||||||
# 单个例子注解
|
|
||||||
"send_img": [
|
|
||||||
"发送图片",
|
|
||||||
"萝莉",
|
|
||||||
"美图",
|
|
||||||
"壁纸"
|
|
||||||
]
|
|
||||||
# 发送 关闭发送图片/关闭萝莉/关闭美图/关闭壁纸 都将触发命令 关闭send_img
|
|
||||||
```
|
|
||||||
|
|
||||||
./configs/other_config.json
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"base": {
|
|
||||||
# 图库配置,会影响 上传/删除/移动/发送图片等功能
|
|
||||||
"IMAGE_DIR_LIST": [
|
|
||||||
"色图",
|
|
||||||
"美图",
|
|
||||||
"萝莉",
|
|
||||||
"壁纸"
|
|
||||||
],
|
|
||||||
"BAN_RESULT": "才不会给你发消息." # 当被ban用户触发命令后发送的消息
|
|
||||||
},
|
|
||||||
|
|
||||||
"bool": {
|
|
||||||
"AUTO_ADD_FRIEND": true, # 是否自动添加好友
|
|
||||||
"DOWNLOAD_SETU": true # 是否下载bot发送过的色图(不会重复)
|
|
||||||
},
|
|
||||||
|
|
||||||
"max_count": {
|
|
||||||
"MAXINFO_REIMU": 7, # 上车(reimu)功能查找目的地的最大数
|
|
||||||
"COUNT_PER_DAY_REIMU": 5, # 每日上车(reimu)次数限制
|
|
||||||
"MAXINFO_BT": 10, # bt功能单次查找最大数
|
|
||||||
"MAXINFO_PRIVATE_ANIME": 20, # 私聊搜索动漫返回的最大数量
|
|
||||||
"MAXINFO_GROUP_ANIME": 5, # 群搜索动漫返回的最大数量
|
|
||||||
"MAX_FIND_IMG_COUNT": 3, # 识图最大返回数
|
|
||||||
"MAX_SIGN_GOLD": 200, # 签到好感度加成额外获得的最大金币数
|
|
||||||
"MAX_SETU_R_COUNT": 5, # 每日色图r次数限制
|
|
||||||
},
|
|
||||||
|
|
||||||
"probability": {
|
|
||||||
"INITIAL_SETU_PROBABILITY": 0.7, # 涩图触发的基础概率(触发概率 = 基础概率 + 好感度)
|
|
||||||
"FUDU_PROBABILITY": 0.7 # 复读概率
|
|
||||||
},
|
|
||||||
|
|
||||||
# 注:即在 MALICIOUS_CHECK_TIME 时间内触发相同命令 MALICIOUS_BAN_COUNT 将被ban MALICIOUS_BAN_TIME 分钟
|
|
||||||
"malicious_ban": {
|
|
||||||
"MALICIOUS_BAN_TIME": 30, # 恶意触发命令被ban的时长(分钟)
|
|
||||||
"MALICIOUS_BAN_COUNT": 4, # 恶意触发命令的规定次数
|
|
||||||
"MALICIOUS_CHECK_TIME": 5 # 恶意触发命令的规定时间(秒)
|
|
||||||
},
|
|
||||||
"open_case": {
|
|
||||||
"INITIAL_OPEN_CASE_COUNT": 20 # 每日开箱的基本数量(总数量=基本数量 + 好感度/3)
|
|
||||||
},
|
|
||||||
|
|
||||||
# 注:即在 MUTE_DEFAULT_TIME 内发送相似(包含)消息超过 MUTE_DEFAULT_COUNT 将会被 MUTE_DEFAULT_DURATION 分钟
|
|
||||||
# 这只是默认配置,各个群可以自由设置群内刷屏检测配置
|
|
||||||
"mute": {
|
|
||||||
"MUTE_DEFAULT_COUNT": 10, # 刷屏检测默认检测最大次数
|
|
||||||
"MUTE_DEFAULT_TIME": 7, # 刷屏检测默认规定时间(秒)
|
|
||||||
"MUTE_DEFAULT_DURATION": 10 # 刷屏检测默认禁言时长(分钟)
|
|
||||||
},
|
|
||||||
"other": {
|
|
||||||
"UPDATE_GOCQ_GROUP": [], # 是否需要为某些群上传最新版的gocq?
|
|
||||||
"ADMIN_DEFAULT_AUTH": 5 # 默认群管理员权限
|
|
||||||
},
|
|
||||||
|
|
||||||
# 管理员功能 和 对应的 权限
|
|
||||||
"auth": {
|
|
||||||
"admin_plugins_auth": {
|
|
||||||
"admin_bot_manage": 2,
|
|
||||||
"ban": 5,
|
|
||||||
"delete_img": 7,
|
|
||||||
"move_img": 7,
|
|
||||||
"upload_img": 6,
|
|
||||||
"admin_help": 1,
|
|
||||||
"mute": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
## 更新
|
## 更新
|
||||||
|
|
||||||
|
### 2021/9/9
|
||||||
|
|
||||||
|
* 替换coser API
|
||||||
|
* 修复签到uid可能不默认为0
|
||||||
|
* 修复签到可能重复的问题
|
||||||
|
* 修复无订阅时递归出错
|
||||||
|
* 启用了plugins2info_dict, plugins2cd_dict, plugins2exists_dict配置文件,通过USE_CONFIG_FILE=True开启
|
||||||
|
* 修复涩图local_id会被固定为50
|
||||||
|
* 优化图库数量查询
|
||||||
|
* 修复原神大地图过大无法打开报错
|
||||||
|
|
||||||
|
### 2021/9/7
|
||||||
|
|
||||||
|
* 修改 update_info.json
|
||||||
|
* 修改 更新信息 图片大小
|
||||||
|
* 修复 查看订阅 命令 UP和番剧无法正常显示
|
||||||
|
* 修复订阅推送无法正确推送
|
||||||
|
* 修复搜图返回列表为空时无法正确回复 @[pull/40](https://github.com/HibiKier/zhenxun_bot/pull/40)
|
||||||
|
|
||||||
|
### 2021/9/5
|
||||||
|
* 添加配置PIX_IMAGE_SIZE,调整PIX下载图片大小,当设置的图片404时,改为原图
|
||||||
|
* 新增配置DEFAULT_GROUP_LEVEL,默认群等级
|
||||||
|
* 新增超级用户功能 super ban,将屏蔽被ban用户的所有消息,指令:b了
|
||||||
|
* b站转发解析支持纯BV号解析,且五分钟内不会解析相同url
|
||||||
|
* 俄罗斯轮盘新增 连胜/最高连胜/连败/最高连败 纪录,新增 最高连胜排行榜/最高连败排行榜
|
||||||
|
* 增加扩展图库 OmegaPixivIllusts,不想自己找图的人福音([Ailitonia](https://github.com/Ailitonia) 佬的高质量精品手筛图库)([传送门](https://github.com/Ailitonia/omega-miya/blob/master/archive_data/db_pixiv.7z) ),可以手动导入图库,也可以将解压文件放在bot.py同级目录重启bot
|
||||||
|
* 增加配置PIX_OMEGA_PIXIV_RATIO,PIX功能发送PIX图库和扩展图库OmegaPixivIllusts图片的比例,如果没有使用扩展图库OmegaPixivIllusts,请设置为(10, 0)
|
||||||
|
* 增加配置WITHDRAW_PIX_TIME,用于配置在开关PIX图片在群私聊的自动撤回
|
||||||
|
* 上传图库cases, 开箱 也可以连抽(未更新过没有价格)
|
||||||
|
* 新增命令 查看群白名单
|
||||||
|
* plugins2info_dict新增键"default_status",设置加入新群时功能的默认开关状态
|
||||||
|
* 增加配置plugins2exists_dict,可自定义是否阻塞某命令同时触发多次
|
||||||
|
* 增加配置plugins2cd_dict,可自定义为命令添加cd
|
||||||
|
* 新增B站订阅(直播/番剧/UP)[测试],提供命令:添加订阅 [主播/UP/番剧] [id/链接/番名],删除订阅 [id],查看订阅
|
||||||
|
* 优化pix和色图的数据库查询
|
||||||
|
* 触发已关闭的功能的正则时不再触发ai
|
||||||
|
* 更换coser API
|
||||||
|
* PIX搜索pid功能在群聊无法搜索PIX图库的r18和OmegaPixivIllusts的r15以及r18,超级用户除外
|
||||||
|
* PIX单次搜索的图片张数超级用户限制为至多30张,普通用户10张
|
||||||
|
* PIX超级用户新增-s,-r,可以通过pix -s 查看图库的涩图,pix -r查看图库的r18图,支持搜索,当然,pix图库只区分了r18和非r18,如果-s查询到不色的图也问题不大
|
||||||
|
* 优化P站排行和搜图,现在需要艾特,改为使用HIBIAPI,在群内时将使用合并消息(群聊搜图会屏蔽R-18)
|
||||||
|
* win10下playwright相关功能无法使用,但是不再需要删除文件
|
||||||
|
* 签到大改,优化签到方式与逻辑,改为图片形式发送,有概率额外获得随机道具(好感度有加成)
|
||||||
|
* 修改撤回功能,改为回复撤回,回复发送撤回
|
||||||
|
* 更改logging为loguru
|
||||||
|
* 删除了 发送图片 中的 [N]张图[keyword] 功能
|
||||||
|
* 修复私聊 关闭[功能] 默认不为 全部 而要添加参数 ‘a’
|
||||||
|
* 修复0权限用户可以修改禁言检测相关设置
|
||||||
|
|
||||||
### 2021/8/17
|
### 2021/8/17
|
||||||
|
|
||||||
* 新增配置CHECK_NOTICE_INFO_CD,修改群权限,个人权限检测各种检测的提示消息cd
|
* 新增配置CHECK_NOTICE_INFO_CD,修改群权限,个人权限检测各种检测的提示消息cd
|
||||||
@@ -687,6 +385,7 @@ python bot.py
|
|||||||
* 我有一个朋友功能,当艾特一个对象时,‘朋友’改为艾特对象的群名片或昵称
|
* 我有一个朋友功能,当艾特一个对象时,‘朋友’改为艾特对象的群名片或昵称
|
||||||
* 修复‘上传/删除/移动图片’目录不正确
|
* 修复‘上传/删除/移动图片’目录不正确
|
||||||
* 修复天气功能,当城市名在‘天气’后时报错
|
* 修复天气功能,当城市名在‘天气’后时报错
|
||||||
|
* 修复配置INITIAL_SETU_PROBABILITY不生效
|
||||||
|
|
||||||
### 2021/8/10
|
### 2021/8/10
|
||||||
|
|
||||||
@@ -736,13 +435,13 @@ python bot.py
|
|||||||
* 功能维护时超级用户依然可以调用(苦了谁都不能苦了自己)
|
* 功能维护时超级用户依然可以调用(苦了谁都不能苦了自己)
|
||||||
* 修复获取赛马娘UP公告
|
* 修复获取赛马娘UP公告
|
||||||
* 重写 色图/更新色图
|
* 重写 色图/更新色图
|
||||||
* 色图数据存储改为数据库,启动时会更新之前的色图数据(有的话),更新完毕后会删除原数据文件,如果需要保留请提前备份,
|
* 色图数据存储改为数据库,启动时会更新之前的色图数据(有的话),更新完毕后会删除原数据文件,如果需要保留请提前备份,
|
||||||
* lolicon api改为v2
|
* lolicon api改为v2
|
||||||
* 取消r18次数限制
|
* 取消r18次数限制
|
||||||
* 单次搜索至多保存100条链接
|
* 单次搜索至多保存100条链接
|
||||||
* 添加定时撤回
|
* 添加定时撤回
|
||||||
* 暂时取消上传/删除色图
|
* 暂时取消上传/删除色图
|
||||||
*
|
*
|
||||||
* 更新建议(不要替换你的data和resources文件夹!)
|
* 更新建议(不要替换你的data和resources文件夹!)
|
||||||
* 删除configs,plugins,services,utils,models文件夹重新clone
|
* 删除configs,plugins,services,utils,models文件夹重新clone
|
||||||
* 删除多余文件夹,resources/img/genshin/seek_god_eye
|
* 删除多余文件夹,resources/img/genshin/seek_god_eye
|
||||||
@@ -854,3 +553,4 @@ python bot.py
|
|||||||
[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)
|
[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)
|
||||||
[nonebot2_luxun_says](https://github.com/NothAmor/nonebot2_luxun_says)
|
[nonebot2_luxun_says](https://github.com/NothAmor/nonebot2_luxun_says)
|
||||||
[AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus)
|
[AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus)
|
||||||
|
[omega-miya](https://github.com/Ailitonia/omega-miya)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
__version__: v0.0.4.6
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
from typing import List, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
from services.service_config import TL_M_KEY, SYSTEM_M_PROXY, ALAPI_M_TOKEN
|
from services.service_config import TL_M_KEY, SYSTEM_M_PROXY, ALAPI_M_TOKEN
|
||||||
|
from .utils.init_config import init_config
|
||||||
|
from configs.path_config import DATA_PATH
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
@@ -8,10 +9,14 @@ except ModuleNotFoundError:
|
|||||||
|
|
||||||
|
|
||||||
# 是否使用配置文件
|
# 是否使用配置文件
|
||||||
|
# 使用配置文件在每次启动时 plugins2info_dict, plugins2cd_dict, plugins2exists_dict 将从本地读取
|
||||||
|
# 除了 plugins2info_dict 新增内容键值会写入 plugins2info_file
|
||||||
|
# 其他修改或新增在 configs.config.py中对 plugins2info_dict, plugins2cd_dict, plugins2exists_dict 的配置无效
|
||||||
|
# 目录:data/configs/
|
||||||
USE_CONFIG_FILE: bool = False
|
USE_CONFIG_FILE: bool = False
|
||||||
|
|
||||||
# 回复消息名称
|
# 回复消息名称
|
||||||
NICKNAME: str = '小真寻'
|
NICKNAME: str = "小真寻"
|
||||||
|
|
||||||
# API KEY(必要)
|
# API KEY(必要)
|
||||||
RSSHUBAPP: str = "https://rsshub.app" # rsshub
|
RSSHUBAPP: str = "https://rsshub.app" # rsshub
|
||||||
@@ -41,6 +46,9 @@ IMAGE_DIR_LIST: List[str] = ["美图", "萝莉", "壁纸"]
|
|||||||
# 对被ban用户发送的消息
|
# 对被ban用户发送的消息
|
||||||
BAN_RESULT: str = "才不会给你发消息."
|
BAN_RESULT: str = "才不会给你发消息."
|
||||||
|
|
||||||
|
# PIX图库下载的画质 可能的值:original:原图,master:缩略图(加快发送速度)
|
||||||
|
PIX_IMAGE_SIZE: str = "master"
|
||||||
|
|
||||||
|
|
||||||
# 插件配置
|
# 插件配置
|
||||||
MAXINFO_REIMU: int = 7 # 上车(reimu)功能查找目的地的最大数
|
MAXINFO_REIMU: int = 7 # 上车(reimu)功能查找目的地的最大数
|
||||||
@@ -50,7 +58,12 @@ MAXINFO_PRIVATE_ANIME: int = 20 # 私聊搜索动漫返回的最大数量
|
|||||||
MAXINFO_GROUP_ANIME: int = 5 # 群搜索动漫返回的最大数量
|
MAXINFO_GROUP_ANIME: int = 5 # 群搜索动漫返回的最大数量
|
||||||
MAX_FIND_IMG_COUNT: int = 3 # 识图最大返回数
|
MAX_FIND_IMG_COUNT: int = 3 # 识图最大返回数
|
||||||
# 参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)
|
# 参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)
|
||||||
WITHDRAW_SETU_TIME: Tuple[int, int] = (0, 1)
|
WITHDRAW_SETU_TIME: Tuple[int, int] = (90, 1)
|
||||||
|
# 参1:延迟撤回PIX图片时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)
|
||||||
|
WITHDRAW_PIX_TIME: Tuple[int, int] = (0, 1)
|
||||||
|
|
||||||
|
# PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1:PIX图库 参2:OmegaPixivIllusts扩展图库(没有此图库请设置为0)
|
||||||
|
PIX_OMEGA_PIXIV_RATIO: Tuple[int, int] = (2, 8)
|
||||||
|
|
||||||
# 各种卡池的开关
|
# 各种卡池的开关
|
||||||
PRTS_FLAG = True # 明日方舟
|
PRTS_FLAG = True # 明日方舟
|
||||||
@@ -68,7 +81,7 @@ SEMAPHORE = 5 # 限制碧蓝航线和FGO并发数
|
|||||||
ADMIN_DEFAULT_AUTH: int = 5 # 默认群管理员权限
|
ADMIN_DEFAULT_AUTH: int = 5 # 默认群管理员权限
|
||||||
|
|
||||||
MAX_SIGN_GOLD: int = 200 # 签到好感度加成额外获得的最大金币数
|
MAX_SIGN_GOLD: int = 200 # 签到好感度加成额外获得的最大金币数
|
||||||
MAX_RUSSIAN_BET_GOLD: int = 1000 # 俄罗斯轮盘最大赌注金额
|
MAX_RUSSIAN_BET_GOLD: int = 1000 # 俄罗斯轮盘最大赌注金额
|
||||||
|
|
||||||
INITIAL_SETU_PROBABILITY: float = 0.7 # 色图概率
|
INITIAL_SETU_PROBABILITY: float = 0.7 # 色图概率
|
||||||
FUDU_PROBABILITY: float = 0.7 # 复读概率
|
FUDU_PROBABILITY: float = 0.7 # 复读概率
|
||||||
@@ -78,11 +91,11 @@ MUTE_DEFAULT_COUNT: int = 10 # 刷屏禁言默认检测次数
|
|||||||
MUTE_DEFAULT_TIME: int = 7 # 刷屏检测默认规定时间
|
MUTE_DEFAULT_TIME: int = 7 # 刷屏检测默认规定时间
|
||||||
MUTE_DEFAULT_DURATION: int = 10 # 刷屏检测默禁言时长(分钟)
|
MUTE_DEFAULT_DURATION: int = 10 # 刷屏检测默禁言时长(分钟)
|
||||||
|
|
||||||
CHECK_NOTICE_INFO_CD = 300 # 群检测,个人权限检测等各种检测提示信息cd
|
CHECK_NOTICE_INFO_CD = 300 # 群检测,个人权限检测等各种检测提示信息cd
|
||||||
|
|
||||||
# 注:即在 MALICIOUS_CHECK_TIME 时间内触发相同命令 MALICIOUS_BAN_COUNT 将被ban MALICIOUS_BAN_TIME 分钟
|
# 注:即在 MALICIOUS_CHECK_TIME 时间内触发相同命令 MALICIOUS_BAN_COUNT 将被ban MALICIOUS_BAN_TIME 分钟
|
||||||
MALICIOUS_BAN_TIME: int = 30 # 恶意命令触发检测触发后ban的时长(分钟)
|
MALICIOUS_BAN_TIME: int = 30 # 恶意命令触发检测触发后ban的时长(分钟)
|
||||||
MALICIOUS_BAN_COUNT: int = 8 # 恶意命令触发检测最大触发次数
|
MALICIOUS_BAN_COUNT: int = 3 # 恶意命令触发检测最大触发次数
|
||||||
MALICIOUS_CHECK_TIME: int = 5 # 恶意命令触发检测规定时间内(秒)
|
MALICIOUS_CHECK_TIME: int = 5 # 恶意命令触发检测规定时间内(秒)
|
||||||
|
|
||||||
# LEVEL
|
# LEVEL
|
||||||
@@ -93,6 +106,9 @@ BAN_LEVEL: int = 5 # BAN权限
|
|||||||
OC_LEVEL: int = 2 # 开关群功能权限
|
OC_LEVEL: int = 2 # 开关群功能权限
|
||||||
MUTE_LEVEL: int = 5 # 更改禁言设置权限
|
MUTE_LEVEL: int = 5 # 更改禁言设置权限
|
||||||
MEMBER_ACTIVITY_LEVEL = 5 # 群员活跃检测设置权限
|
MEMBER_ACTIVITY_LEVEL = 5 # 群员活跃检测设置权限
|
||||||
|
GROUP_BILIBILI_SUB_LEVEL = 5 # 群内bilibili订阅需要的权限
|
||||||
|
|
||||||
|
DEFAULT_GROUP_LEVEL = 5 # 默认群等级
|
||||||
|
|
||||||
# 是否开启HIBIAPI搜图功能(该功能会搜索群友提交的xp)
|
# 是否开启HIBIAPI搜图功能(该功能会搜索群友提交的xp)
|
||||||
HIBIAPI_FLAG: bool = True
|
HIBIAPI_FLAG: bool = True
|
||||||
@@ -131,76 +147,157 @@ admin_plugins_auth = {
|
|||||||
"member_activity_handle": MEMBER_ACTIVITY_LEVEL,
|
"member_activity_handle": MEMBER_ACTIVITY_LEVEL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 需要cd的功能(方便管理)[秒]
|
||||||
|
# 自定义的功能需要cd也可以在此配置
|
||||||
|
# key:模块名称
|
||||||
|
# cd:cd 时长(秒)
|
||||||
|
# status:此限制的开关状态
|
||||||
|
# check_type:'private'/'group'/'all',限制私聊/群聊/全部
|
||||||
|
# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
||||||
|
# 示例:'user':用户N秒内触发1次,'group':群N秒内触发1次
|
||||||
|
# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
|
||||||
|
# rst 为 "" 或 None 时则不回复
|
||||||
|
# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
|
||||||
|
# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
|
||||||
|
# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑
|
||||||
|
plugins2cd_dict = {
|
||||||
|
"open_cases": {
|
||||||
|
"cd": 5,
|
||||||
|
"status": True,
|
||||||
|
"check_type": "all",
|
||||||
|
"limit_type": "user",
|
||||||
|
"rst": "着什么急啊,慢慢来!",
|
||||||
|
},
|
||||||
|
"send_setu": {
|
||||||
|
"cd": 5,
|
||||||
|
"status": True,
|
||||||
|
"check_type": "all",
|
||||||
|
"limit_type": "user",
|
||||||
|
"rst": "您冲得太快了,请稍候再冲",
|
||||||
|
},
|
||||||
|
"sign_in": {
|
||||||
|
"cd": 5,
|
||||||
|
"status": True,
|
||||||
|
"check_type": "group",
|
||||||
|
"limit_type": "user",
|
||||||
|
"rst": None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 用户调用阻塞(方便管理)
|
||||||
|
# 即 当用户调用此功能还未结束时
|
||||||
|
# 用发送消息阻止用户重复调用此命令直到该命令结束
|
||||||
|
# 参数同上 plugin2cd_dict
|
||||||
|
plugins2exists_dict = {
|
||||||
|
"send_setu": {
|
||||||
|
"status": False,
|
||||||
|
"check_type": "all",
|
||||||
|
"limit_type": "user",
|
||||||
|
"rst": "您有色图正在处理,请稍等.....",
|
||||||
|
},
|
||||||
|
"pixiv": {
|
||||||
|
"status": True,
|
||||||
|
"check_type": "all",
|
||||||
|
"limit_type": "user",
|
||||||
|
"rst": "P站排行榜或搜图正在搜索,请不要重复触发命令...",
|
||||||
|
},
|
||||||
|
"pix": {
|
||||||
|
"status": True,
|
||||||
|
"check_type": "all",
|
||||||
|
"limit_type": "user",
|
||||||
|
"rst": "您有PIX图片正在处理,请稍等...",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# 模块与对应命令和对应群权限
|
# 模块与对应命令和对应群权限
|
||||||
# 用于生成帮助图片 和 开关功能
|
# 用于生成帮助图片 和 开关功能
|
||||||
|
# key:模块名称
|
||||||
|
# level:需要的群等级
|
||||||
|
# default_status:加入群时功能的默认开关状态
|
||||||
|
# cmd:关闭[cmd] 都会触发命令 关闭对应功能,cmd列表第一个词为统计的功能名称
|
||||||
plugins2info_dict = {
|
plugins2info_dict = {
|
||||||
"sign_in": {"level": 5, "cmd": ["签到"]},
|
"sign_in": {"level": 5, "default_status": True, "cmd": ["签到"]},
|
||||||
"send_img": {"level": 5, "cmd": ["发送图片", "发图", "萝莉", "美图", "壁纸"]},
|
"send_img": {
|
||||||
"send_setu": {"level": 9, "cmd": ["色图", "涩图", "瑟图", "查色图"]},
|
"level": 5,
|
||||||
"white2black": {"level": 5, "cmd": ["黑白图", "黑白草图"]},
|
"default_status": True,
|
||||||
"coser": {"level": 9, "cmd": ["coser", "cos"]},
|
"cmd": ["发送图片", "发图", "萝莉", "美图", "壁纸"],
|
||||||
"quotations": {"level": 5, "cmd": ["语录"]},
|
},
|
||||||
"jitang": {"level": 5, "cmd": ["鸡汤"]},
|
"send_setu": {"level": 9, "default_status": True, "cmd": ["色图", "涩图", "瑟图", "查色图"]},
|
||||||
"send_dinggong_voice": {"level": 5, "cmd": ["骂我", "骂老子", "骂劳资"]},
|
"white2black": {"level": 5, "default_status": True, "cmd": ["黑白图", "黑白草图"]},
|
||||||
"open_cases": {"level": 5, "cmd": ["开箱", "我的开箱", "群开箱统计", "我的金色"]},
|
"coser": {"level": 9, "default_status": True, "cmd": ["coser", "cos"]},
|
||||||
"luxun": {"level": 5, "cmd": ["鲁迅说", "鲁迅说过"]},
|
"quotations": {"level": 5, "default_status": True, "cmd": ["语录"]},
|
||||||
"fake_msg": {"level": 5, "cmd": ["假消息"]},
|
"jitang": {"level": 5, "default_status": True, "cmd": ["鸡汤"]},
|
||||||
"buy": {"level": 5, "cmd": ["购买", "购买道具"]},
|
"send_dinggong_voice": {
|
||||||
"my_gold": {"level": 5, "cmd": ["我的金币"]},
|
"level": 5,
|
||||||
"my_props": {"level": 5, "cmd": ["我的道具"]},
|
"default_status": True,
|
||||||
"shop_handle": {"level": 5, "cmd": ["商店"]},
|
"cmd": ["骂我", "骂老子", "骂劳资"],
|
||||||
"update_pic": {"level": 5, "cmd": ["图片", "操作图片", "修改图片"]},
|
},
|
||||||
"search_buff_skin_price": {"level": 5, "cmd": ["查询皮肤"]},
|
"open_cases": {
|
||||||
"weather": {"level": 5, "cmd": ["天气", "查询天气", "天气查询"]},
|
"level": 5,
|
||||||
"yiqing": {"level": 5, "cmd": ["疫情", "疫情查询", "查询疫情"]},
|
"default_status": True,
|
||||||
"what_anime": {"level": 5, "cmd": ["识番"]},
|
"cmd": ["开箱", "我的开箱", "群开箱统计", "我的金色"],
|
||||||
"search_anime": {"level": 5, "cmd": ["搜番"]},
|
},
|
||||||
"songpicker2": {"level": 5, "cmd": ["点歌"]},
|
"luxun": {"level": 5, "default_status": True, "cmd": ["鲁迅说", "鲁迅说过"]},
|
||||||
"epic": {"level": 5, "cmd": ["epic"]},
|
"fake_msg": {"level": 5, "default_status": True, "cmd": ["假消息"]},
|
||||||
"pixiv": {"level": 9, "cmd": ["pixiv", "p站排行", "搜图"]},
|
"buy": {"level": 5, "default_status": True, "cmd": ["购买", "购买道具"]},
|
||||||
"poke": {"level": 5, "cmd": ["戳一戳", "拍一拍"]},
|
"my_gold": {"level": 5, "default_status": True, "cmd": ["我的金币"]},
|
||||||
|
"my_props": {"level": 5, "default_status": True, "cmd": ["我的道具"]},
|
||||||
|
"shop_handle": {"level": 5, "default_status": True, "cmd": ["商店"]},
|
||||||
|
"update_pic": {"level": 5, "default_status": True, "cmd": ["图片", "操作图片", "修改图片"]},
|
||||||
|
"search_buff_skin_price": {"level": 5, "default_status": True, "cmd": ["查询皮肤"]},
|
||||||
|
"weather": {"level": 5, "default_status": True, "cmd": ["天气", "查询天气", "天气查询"]},
|
||||||
|
"yiqing": {"level": 5, "default_status": True, "cmd": ["疫情", "疫情查询", "查询疫情"]},
|
||||||
|
"what_anime": {"level": 5, "default_status": True, "cmd": ["识番"]},
|
||||||
|
"search_anime": {"level": 5, "default_status": True, "cmd": ["搜番"]},
|
||||||
|
"songpicker2": {"level": 5, "default_status": True, "cmd": ["点歌"]},
|
||||||
|
"epic": {"level": 5, "default_status": True, "cmd": ["epic"]},
|
||||||
|
"pixiv": {"level": 9, "default_status": True, "cmd": ["pixiv", "p站排行", "搜图"]},
|
||||||
|
"poke": {"level": 5, "default_status": True, "cmd": ["戳一戳", "拍一拍"]},
|
||||||
"draw_card": {
|
"draw_card": {
|
||||||
"level": 5,
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
"cmd": [
|
"cmd": [
|
||||||
"抽卡",
|
"抽卡",
|
||||||
"游戏抽卡",
|
"游戏抽卡",
|
||||||
"原神抽卡",
|
|
||||||
"方舟抽卡",
|
|
||||||
"坎公骑冠剑抽卡",
|
|
||||||
"pcr抽卡",
|
|
||||||
"fgo抽卡",
|
|
||||||
"碧蓝抽卡",
|
|
||||||
"碧蓝航线抽卡",
|
|
||||||
"阴阳师抽卡",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"ai": {"level": 5, "cmd": ["ai", "Ai", "AI", "aI"]},
|
"ai": {"level": 5, "default_status": True, "cmd": ["ai", "Ai", "AI", "aI"]},
|
||||||
"one_friend": {"level": 5, "cmd": ["我有一个朋友", "我有一个朋友想问问"]},
|
"one_friend": {"level": 5, "default_status": True, "cmd": ["我有一个朋友", "我有一个朋友想问问"]},
|
||||||
"translate": {"level": 5, "cmd": ["翻译", "英翻", "翻英", "日翻", "翻日", "韩翻", "翻韩"]},
|
"translate": {
|
||||||
"nonebot_plugin_picsearcher": {"level": 5, "cmd": ["识图"]},
|
"level": 5,
|
||||||
"almanac": {"level": 5, "cmd": ["原神黄历", "黄历"]},
|
"default_status": True,
|
||||||
"material_remind": {"level": 5, "cmd": ["今日素材", "天赋材料"]},
|
"cmd": ["翻译", "英翻", "翻英", "日翻", "翻日", "韩翻", "翻韩"],
|
||||||
"qiu_qiu_translation": {"level": 5, "cmd": ["丘丘翻译", "丘丘一下", "丘丘语翻译"]},
|
},
|
||||||
"query_resource_points": {"level": 5, "cmd": ["原神资源查询", "原神资源列表"]},
|
"nonebot_plugin_picsearcher": {"level": 5, "default_status": True, "cmd": ["识图"]},
|
||||||
"russian": {"level": 5, "cmd": ["俄罗斯轮盘", "俄罗斯转盘", "装弹"]},
|
"almanac": {"level": 5, "default_status": True, "cmd": ["原神黄历", "黄历"]},
|
||||||
"gold_redbag": {"level": 5, "cmd": ["塞红包", "红包", "抢红包"]},
|
"material_remind": {"level": 5, "default_status": True, "cmd": ["今日素材", "天赋材料"]},
|
||||||
"poetry": {"level": 5, "cmd": ["念诗", "来首诗", "念首诗"]},
|
"qiu_qiu_translation": {
|
||||||
"comments_163": {"level": 5, "cmd": ["到点了", "12点了", "网易云热评", "网易云评论"]},
|
"level": 5,
|
||||||
"cover": {"level": 5, "cmd": ["b封面", "B封面"]},
|
"default_status": True,
|
||||||
"pid_search": {"level": 9, "cmd": ["p搜", "P搜"]},
|
"cmd": ["丘丘翻译", "丘丘一下", "丘丘语翻译"],
|
||||||
|
},
|
||||||
|
"query_resource_points": {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"cmd": ["原神资源查询", "原神资源列表"],
|
||||||
|
},
|
||||||
|
"russian": {"level": 5, "default_status": True, "cmd": ["俄罗斯轮盘", "俄罗斯转盘", "装弹"]},
|
||||||
|
"gold_redbag": {"level": 5, "default_status": True, "cmd": ["塞红包", "红包", "抢红包"]},
|
||||||
|
"poetry": {"level": 5, "default_status": True, "cmd": ["念诗", "来首诗", "念首诗"]},
|
||||||
|
"comments_163": {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"cmd": ["到点了", "12点了", "网易云热评", "网易云评论"],
|
||||||
|
},
|
||||||
|
"cover": {"level": 5, "default_status": True, "cmd": ["b封面", "B封面"]},
|
||||||
|
"pid_search": {"level": 9, "default_status": True, "cmd": ["p搜", "P搜"]},
|
||||||
"pix": {
|
"pix": {
|
||||||
"level": 5,
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
"cmd": ["pix", "PIX", "pIX", "Pix", "PIx"],
|
"cmd": ["pix", "PIX", "pIX", "Pix", "PIx"],
|
||||||
},
|
},
|
||||||
"wbtop": {
|
"wbtop": {"level": 5, "default_status": True, "cmd": ["微博热搜", "微博", "wbtop"]},
|
||||||
"level": 5,
|
"update_info": {"level": 5, "default_status": True, "cmd": ["更新信息", "更新日志"]},
|
||||||
"cmd": ['微博热搜', "微博", "wbtop"]
|
|
||||||
},
|
|
||||||
"update_info": {
|
|
||||||
"level": 5,
|
|
||||||
"cmd": ['更新信息', '更新日志']
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if TL_M_KEY:
|
if TL_M_KEY:
|
||||||
@@ -214,6 +311,14 @@ if ALAPI_M_TOKEN:
|
|||||||
HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] == "/" else HIBIAPI
|
HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] == "/" else HIBIAPI
|
||||||
RSSHUBAPP = RSSHUBAPP[:-1] if RSSHUBAPP[-1] == "/" else RSSHUBAPP
|
RSSHUBAPP = RSSHUBAPP[:-1] if RSSHUBAPP[-1] == "/" else RSSHUBAPP
|
||||||
|
|
||||||
|
|
||||||
|
if USE_CONFIG_FILE:
|
||||||
|
# 读取配置文件
|
||||||
|
plugins2info_dict, plugins2cd_dict, plugins2exists_dict = init_config(
|
||||||
|
plugins2info_dict, plugins2cd_dict, plugins2exists_dict, DATA_PATH
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# 配置文件应用
|
# 配置文件应用
|
||||||
# if USE_CONFIG_FILE:
|
# if USE_CONFIG_FILE:
|
||||||
# config = get_config_data()
|
# config = get_config_data()
|
||||||
|
|||||||
@@ -1,176 +1,42 @@
|
|||||||
# import nonebot
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# driver: nonebot.Driver = nonebot.get_driver()
|
|
||||||
|
|
||||||
base_config = Path() / 'config.json'
|
|
||||||
plugins_cmd_config = Path() / 'configs' / 'plugins2cmd_config.json'
|
|
||||||
plugins_setting = Path() / 'configs' / 'plugins_setting.json'
|
|
||||||
|
|
||||||
|
|
||||||
def init_config():
|
|
||||||
if not base_config.exists():
|
|
||||||
base_config.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
config_dict = {
|
|
||||||
'apikey': {
|
|
||||||
'LOLICON_KEY': '',
|
|
||||||
'TL_KEY': [],
|
|
||||||
},
|
|
||||||
'sql': {
|
|
||||||
'bind': '',
|
|
||||||
'sql_name': '',
|
|
||||||
'user': '',
|
|
||||||
'password': '',
|
|
||||||
'address': '',
|
|
||||||
'port': '',
|
|
||||||
'database': '',
|
|
||||||
},
|
|
||||||
'path': {
|
|
||||||
'IMAGE_PATH': '',
|
|
||||||
'VOICE_PATH': '',
|
|
||||||
'TXT_PATH': '',
|
|
||||||
'LOG_PATH': '',
|
|
||||||
'DATA_PATH': '',
|
|
||||||
'DRAW_PATH': '',
|
|
||||||
'TEMP_PATH': '',
|
|
||||||
},
|
|
||||||
'proxy': {
|
|
||||||
'system_proxy': '',
|
|
||||||
'buff_proxy': ''
|
|
||||||
},
|
|
||||||
'level': {
|
|
||||||
'DELETE_IMG_LEVEL': 7,
|
|
||||||
'MOVE_IMG_LEVEL': 7,
|
|
||||||
'UPLOAD_LEVEL': 6,
|
|
||||||
'BAN_LEVEL': 5,
|
|
||||||
'OC_LEVEL': 2,
|
|
||||||
'MUTE_LEVEL': 5,
|
|
||||||
},
|
|
||||||
'auth': {
|
|
||||||
'ADMIN_DEFAULT_AUTH': 5,
|
|
||||||
'admin_plugins_auth': {
|
|
||||||
"admin_bot_manage": 2,
|
|
||||||
"ban": 5,
|
|
||||||
"delete_img": 7,
|
|
||||||
"move_img": 7,
|
|
||||||
"upload_img": 6,
|
|
||||||
"admin_help": 1,
|
|
||||||
"mute": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with open(base_config, 'w', encoding='utf8') as f:
|
|
||||||
json.dump(config_dict, f, indent=4, ensure_ascii=False)
|
|
||||||
if not plugins_cmd_config.exists():
|
|
||||||
plugins_cmd_config.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
config_dict = {
|
|
||||||
'base_config': {
|
|
||||||
'sign_in': ['签到'],
|
|
||||||
'send_img': ['发送图片', '萝莉', '美图', '壁纸'],
|
|
||||||
'send_setu': ['色图', '涩图', '瑟图', '查色图'],
|
|
||||||
'white2black': ['黑白图', '黑白草图'],
|
|
||||||
'coser': ['coser', 'cos'],
|
|
||||||
'quotations': ['语录'],
|
|
||||||
'jitang': ['鸡汤'],
|
|
||||||
'send_dinggong_voice': ['骂我', '骂老子', '骂劳资'],
|
|
||||||
'open_cases': ['开箱', '我的开箱', '群开箱统计', '我的金色'],
|
|
||||||
'luxun': ['鲁迅说过', '鲁迅说'],
|
|
||||||
'fake_msg': ['假消息'],
|
|
||||||
'buy': ['购买', '购买道具'],
|
|
||||||
'my_gold': ['我的金币'],
|
|
||||||
'my_props': ['我的道具'],
|
|
||||||
'shop_handle': ['商店'],
|
|
||||||
'nonebot_plugin_cocdicer': ['骰子娘'],
|
|
||||||
'update_pic': ['图片', '操作图片', '修改图片'],
|
|
||||||
'search_buff_skin_price': ['查询皮肤'],
|
|
||||||
'weather': ['天气', '查询天气', '天气查询'],
|
|
||||||
'yiqing': ['疫情', '疫情查询', '查询疫情'],
|
|
||||||
'what_anime': ['识番'],
|
|
||||||
'search_anime': ['搜番'],
|
|
||||||
'songpicker2': ['点歌'],
|
|
||||||
'epic': ['epic'],
|
|
||||||
'pixiv': ['pixiv', 'p站排行', '搜图'],
|
|
||||||
'poke': ['戳一戳'],
|
|
||||||
'draw_card': ['游戏抽卡', '原神一井', '原神来一井', '方舟一井', '方舟来一井'],
|
|
||||||
'ai': ['ai', 'Ai', 'AI', 'aI'],
|
|
||||||
'one_friend': ['我有一个朋友', '我有一个朋友想问问'],
|
|
||||||
'translate': ['翻译', '英翻', '翻英', '日翻', '翻日', '韩翻', '翻韩'],
|
|
||||||
'nonebot_plugin_picsearcher': ['识图'],
|
|
||||||
'almanac': ['原神黄历', '黄历'],
|
|
||||||
'material_remind': ['今日素材', '天赋材料'],
|
|
||||||
'qiu_qiu_translation': ['丘丘翻译', '丘丘一下', '丘丘语翻译'],
|
|
||||||
'query_resource_points': ['原神资源查询', '原神资源列表'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with open(plugins_cmd_config, 'w', encoding='utf8') as f:
|
|
||||||
json.dump(config_dict, f, indent=4, ensure_ascii=False)
|
|
||||||
if not plugins_setting.exists():
|
|
||||||
plugins_setting.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
config_dict = {
|
|
||||||
'base': {
|
|
||||||
'IMAGE_DIR_LIST': ["色图", "美图", "萝莉", "壁纸"],
|
|
||||||
'BAN_RESULT': "才不会给你发消息.",
|
|
||||||
},
|
|
||||||
'draw_card': {
|
|
||||||
'PRTS_FLAG': True, # 明日方舟
|
|
||||||
'GENSHIN_FLAG': True, # 原神
|
|
||||||
'PRETTY_FLAG': True, # 赛马娘
|
|
||||||
'GUARDIAN_FLAG': True, # 坎公骑冠剑
|
|
||||||
'PCR_FLAG': True, # 公主连结
|
|
||||||
'AZUR_FLAG': True, # 碧蓝航线
|
|
||||||
'FGO_FLAG': True, # 命运-冠位指定(FGO)
|
|
||||||
'ONMYOJI_FLAG': True, # 阴阳师
|
|
||||||
|
|
||||||
'PCR_TAI': False # pcr是否开启台服卡池
|
|
||||||
},
|
|
||||||
'fudu': {
|
|
||||||
'FUDU_PROBABILITY': 0.7,
|
|
||||||
},
|
|
||||||
'reimu': {
|
|
||||||
'MAXINFO_REIMU': 7,
|
|
||||||
'COUNT_PER_DAY_REIMU': 5,
|
|
||||||
},
|
|
||||||
'bt': {
|
|
||||||
'MAXINFO_BT': 10,
|
|
||||||
},
|
|
||||||
'search_anime': {
|
|
||||||
'MAXINFO_PRIVATE_ANIME': 20,
|
|
||||||
'MAXINFO_GROUP_ANIME': 5,
|
|
||||||
},
|
|
||||||
'picsearcher': {
|
|
||||||
'MAX_FIND_IMG_COUNT': 3,
|
|
||||||
},
|
|
||||||
'sign': {
|
|
||||||
'MAX_SIGN_GOLD': 200,
|
|
||||||
},
|
|
||||||
'send_setu': {
|
|
||||||
'INITIAL_SETU_PROBABILITY': 0.7,
|
|
||||||
'MAX_SETU_R_COUNT': 5,
|
|
||||||
'DOWNLOAD_SETU': True,
|
|
||||||
},
|
|
||||||
'malicious_ban': {
|
|
||||||
'MALICIOUS_BAN_TIME': 30,
|
|
||||||
'MALICIOUS_BAN_COUNT': 8,
|
|
||||||
'MALICIOUS_CHECK_TIME': 5,
|
|
||||||
},
|
|
||||||
'open_case': {
|
|
||||||
'INITIAL_OPEN_CASE_COUNT': 20,
|
|
||||||
},
|
|
||||||
'mute': {
|
|
||||||
'MUTE_DEFAULT_COUNT': 10,
|
|
||||||
'MUTE_DEFAULT_TIME': 7,
|
|
||||||
'MUTE_DEFAULT_DURATION': 10,
|
|
||||||
},
|
|
||||||
'update_gocq': {
|
|
||||||
'UPDATE_GOCQ_GROUP': [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
with open(plugins_setting, 'w', encoding='utf8') as f:
|
|
||||||
json.dump(config_dict, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
|
def init_config(plugins2info_dict, plugins2cd_dict, plugins2exists_dict, DATA_PATH):
|
||||||
|
plugins2info_file = Path(DATA_PATH) / 'configs' / 'plugins2info.json'
|
||||||
|
plugins2info_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
|
||||||
|
if plugins2info_file.exists():
|
||||||
|
with open(plugins2info_file, 'r', encoding='utf8') as f:
|
||||||
|
_data = json.load(f)
|
||||||
|
for p in plugins2info_dict:
|
||||||
|
if not _data.get(p):
|
||||||
|
_data[p] = plugins2info_dict[p]
|
||||||
|
with open(plugins2info_file, 'w') as wf:
|
||||||
|
json.dump(_data, wf, ensure_ascii=False, indent=4)
|
||||||
|
plugins2info_dict = _data
|
||||||
|
else:
|
||||||
|
with open(plugins2info_file, 'w', encoding='utf8') as wf:
|
||||||
|
json.dump(plugins2info_dict, wf, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
plugins2cd_file = Path(DATA_PATH) / 'configs' / 'plugins2cd.json'
|
||||||
|
if plugins2cd_file.exists():
|
||||||
|
with open(plugins2cd_file, 'r', encoding='utf8') as f:
|
||||||
|
plugins2cd_dict = json.load(f)
|
||||||
|
else:
|
||||||
|
with open(plugins2cd_file, 'w', encoding='utf8') as wf:
|
||||||
|
json.dump(plugins2cd_dict, wf, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
plugins2exists_file = Path(DATA_PATH) / 'configs' / 'plugins2exists.json'
|
||||||
|
if plugins2exists_file.exists():
|
||||||
|
with open(plugins2exists_file, 'r', encoding='utf8') as f:
|
||||||
|
plugins2exists_dict = json.load(f)
|
||||||
|
else:
|
||||||
|
with open(plugins2exists_file, 'w', encoding='utf8') as wf:
|
||||||
|
json.dump(plugins2exists_dict, wf, ensure_ascii=False, indent=4)
|
||||||
|
return plugins2info_dict, plugins2cd_dict, plugins2exists_dict
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,20 @@ class BanUser(db.Model):
|
|||||||
await cls.unban(user_qq)
|
await cls.unban(user_qq)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def is_super_ban(cls, user_qq: int) -> bool:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
判断用户是否被ban
|
||||||
|
参数:
|
||||||
|
:param user_qq: qq号
|
||||||
|
"""
|
||||||
|
user = await cls.query.where((cls.user_qq == user_qq)).gino.first()
|
||||||
|
if not user:
|
||||||
|
return False
|
||||||
|
if user.ban_level == 10:
|
||||||
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def ban(cls, user_qq: int, ban_level: int, duration: int) -> bool:
|
async def ban(cls, user_qq: int, ban_level: int, duration: int) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -0,0 +1,249 @@
|
|||||||
|
from services.log import logger
|
||||||
|
from services.db_context import db
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class BilibiliSub(db.Model):
|
||||||
|
__tablename__ = "bilibili_sub"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer(), primary_key=True)
|
||||||
|
sub_id = db.Column(db.Integer(), nullable=False)
|
||||||
|
sub_type = db.Column(db.String(), nullable=False)
|
||||||
|
# 订阅用户
|
||||||
|
sub_users = db.Column(db.String(), nullable=False)
|
||||||
|
# 直播
|
||||||
|
live_short_id = db.Column(db.Integer())
|
||||||
|
live_status = db.Column(db.Integer)
|
||||||
|
# 主播/UP
|
||||||
|
uid = db.Column(db.BigInteger())
|
||||||
|
uname = db.Column(db.String())
|
||||||
|
latest_video_created = db.Column(db.BigInteger()) # 视频上传时间
|
||||||
|
dynamic_upload_time = db.Column(db.BigInteger(), default=0) # 动态发布时间
|
||||||
|
# 番剧
|
||||||
|
season_name = db.Column(db.String())
|
||||||
|
season_id = db.Column(db.Integer())
|
||||||
|
season_current_episode = db.Column(db.String())
|
||||||
|
season_update_time = db.Column(db.DateTime())
|
||||||
|
|
||||||
|
_idx1 = db.Index("bilibili_sub_idx1", "sub_id", "sub_type", unique=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def add_bilibili_sub(
|
||||||
|
cls,
|
||||||
|
sub_id: int,
|
||||||
|
sub_type: str,
|
||||||
|
sub_user: str,
|
||||||
|
*,
|
||||||
|
live_short_id: Optional[int] = None,
|
||||||
|
live_status: Optional[int] = None,
|
||||||
|
dynamic_upload_time: Optional[int] = None,
|
||||||
|
uid: Optional[int] = None,
|
||||||
|
uname: Optional[str] = None,
|
||||||
|
latest_video_created: Optional[int] = None,
|
||||||
|
season_name: Optional[str] = None,
|
||||||
|
season_id: Optional[int] = None,
|
||||||
|
season_current_episode: Optional[str] = None,
|
||||||
|
season_update_time: Optional[datetime] = None,
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
添加订阅
|
||||||
|
参数:
|
||||||
|
:param sub_id: 订阅名称,房间号,番剧号等
|
||||||
|
:param sub_type: 订阅类型
|
||||||
|
:param sub_user: 订阅此条目的用户
|
||||||
|
:param live_short_id: 直接短 id
|
||||||
|
:param live_status: 主播开播状态
|
||||||
|
:param dynamic_upload_time: 主播/UP最新动态时间
|
||||||
|
:param uid: 主播/UP uid
|
||||||
|
:param uname: 用户名称
|
||||||
|
:param latest_video_created: 最新视频上传时间
|
||||||
|
:param season_name: 番剧名称
|
||||||
|
:param season_id: 番剧 season_id
|
||||||
|
:param season_current_episode: 番剧最新集数
|
||||||
|
:param season_update_time: 番剧更新时间
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with db.transaction():
|
||||||
|
query = (
|
||||||
|
await cls.query.where(cls.sub_id == sub_id)
|
||||||
|
.with_for_update()
|
||||||
|
.gino.first()
|
||||||
|
)
|
||||||
|
sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
|
||||||
|
if query:
|
||||||
|
if sub_user not in query.sub_users:
|
||||||
|
sub_users = query.sub_users + sub_user
|
||||||
|
await query.update(sub_users=sub_users).apply()
|
||||||
|
else:
|
||||||
|
sub = await cls.create(
|
||||||
|
sub_id=sub_id, sub_type=sub_type, sub_users=sub_user
|
||||||
|
)
|
||||||
|
await sub.update(
|
||||||
|
live_short_id=live_short_id
|
||||||
|
if live_short_id
|
||||||
|
else sub.live_short_id,
|
||||||
|
live_status=live_status if live_status else sub.live_status,
|
||||||
|
dynamic_upload_time=dynamic_upload_time
|
||||||
|
if dynamic_upload_time
|
||||||
|
else sub.dynamic_upload_time,
|
||||||
|
uid=uid if uid else sub.uid,
|
||||||
|
uname=uname if uname else sub.uname,
|
||||||
|
latest_video_created=latest_video_created
|
||||||
|
if latest_video_created
|
||||||
|
else sub.latest_video_created,
|
||||||
|
season_update_time=season_update_time
|
||||||
|
if season_update_time
|
||||||
|
else sub.season_update_time,
|
||||||
|
season_current_episode=season_current_episode
|
||||||
|
if season_current_episode
|
||||||
|
else sub.season_current_episode,
|
||||||
|
season_id=season_id if season_id else sub.season_id,
|
||||||
|
season_name=season_name if season_name else sub.season_name,
|
||||||
|
).apply()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def delete_bilibili_sub(cls, sub_id: int, sub_user: str) -> bool:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
删除订阅
|
||||||
|
参数:
|
||||||
|
:param sub_id: 订阅名称
|
||||||
|
:param sub_user: 删除此条目的用户
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with db.transaction():
|
||||||
|
query = (
|
||||||
|
await cls.query.where(
|
||||||
|
(cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user))
|
||||||
|
)
|
||||||
|
.with_for_update()
|
||||||
|
.gino.first()
|
||||||
|
)
|
||||||
|
if not query:
|
||||||
|
return False
|
||||||
|
await query.update(
|
||||||
|
sub_users=query.sub_users.replace(f"{sub_user},", "")
|
||||||
|
).apply()
|
||||||
|
if not query.sub_users.strip():
|
||||||
|
await query.delete()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"bilibili_sub 删除订阅错误 {type(e)}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_sub(cls, sub_id: int) -> Optional["BilibiliSub"]:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
获取订阅对象
|
||||||
|
参数:
|
||||||
|
:param sub_id: 订阅 id
|
||||||
|
"""
|
||||||
|
return await cls.query.where(cls.sub_id == sub_id).gino.first()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_sub_data(cls, id_: str) -> List["BilibiliSub"]:
|
||||||
|
"""
|
||||||
|
获取 id_ 订阅的所有内容
|
||||||
|
:param id_: id
|
||||||
|
"""
|
||||||
|
query = cls.query.where(cls.sub_users.contains(id_))
|
||||||
|
return await query.gino.all()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def update_sub_info(
|
||||||
|
cls,
|
||||||
|
sub_id: int,
|
||||||
|
*,
|
||||||
|
live_short_id: Optional[int] = None,
|
||||||
|
live_status: Optional[int] = None,
|
||||||
|
dynamic_upload_time: Optional[int] = None,
|
||||||
|
uid: Optional[int] = None,
|
||||||
|
uname: Optional[str] = None,
|
||||||
|
latest_video_created: Optional[int] = None,
|
||||||
|
season_name: Optional[str] = None,
|
||||||
|
season_id: Optional[int] = None,
|
||||||
|
season_current_episode: Optional[str] = None,
|
||||||
|
season_update_time: Optional[datetime] = None,
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
更新订阅信息
|
||||||
|
参数:
|
||||||
|
:param sub_id: 订阅名称,房间号,番剧号等
|
||||||
|
:param live_short_id: 直接短 id
|
||||||
|
:param live_status: 主播开播状态
|
||||||
|
:param dynamic_upload_time: 主播/UP最新动态时间
|
||||||
|
:param uid: 主播/UP uid
|
||||||
|
:param uname: 用户名称
|
||||||
|
:param latest_video_created: 最新视频上传时间
|
||||||
|
:param season_name: 番剧名称
|
||||||
|
:param season_id: 番剧 season_id
|
||||||
|
:param season_current_episode: 番剧最新集数
|
||||||
|
:param season_update_time: 番剧更新时间
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with db.transaction():
|
||||||
|
sub = (
|
||||||
|
await cls.query.where(cls.sub_id == sub_id)
|
||||||
|
.with_for_update()
|
||||||
|
.gino.first()
|
||||||
|
)
|
||||||
|
if sub:
|
||||||
|
await sub.update(
|
||||||
|
live_short_id=live_short_id
|
||||||
|
if live_short_id is not None
|
||||||
|
else sub.live_short_id,
|
||||||
|
live_status=live_status
|
||||||
|
if live_status is not None
|
||||||
|
else sub.live_status,
|
||||||
|
dynamic_upload_time=dynamic_upload_time
|
||||||
|
if dynamic_upload_time is not None
|
||||||
|
else sub.dynamic_upload_time,
|
||||||
|
uid=uid if uid is not None else sub.uid,
|
||||||
|
uname=uname if uname is not None else sub.uname,
|
||||||
|
latest_video_created=latest_video_created
|
||||||
|
if latest_video_created is not None
|
||||||
|
else sub.latest_video_created,
|
||||||
|
season_update_time=season_update_time
|
||||||
|
if season_update_time is not None
|
||||||
|
else sub.season_update_time,
|
||||||
|
season_current_episode=season_current_episode
|
||||||
|
if season_current_episode is not None
|
||||||
|
else sub.season_current_episode,
|
||||||
|
season_id=season_id if season_id is not None else sub.season_id,
|
||||||
|
season_name=season_name
|
||||||
|
if season_name is not None
|
||||||
|
else sub.season_name,
|
||||||
|
).apply()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"bilibili_sub 更新订阅错误 {type(e)}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_all_sub_data(
|
||||||
|
cls,
|
||||||
|
) -> "List[BilibiliSub], List[BilibiliSub], List[BilibiliSub]":
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
分类获取所有数据
|
||||||
|
"""
|
||||||
|
live_data = []
|
||||||
|
up_data = []
|
||||||
|
season_data = []
|
||||||
|
query = await cls.query.gino.all()
|
||||||
|
for x in query:
|
||||||
|
if x.sub_type == "live":
|
||||||
|
live_data.append(x)
|
||||||
|
if x.sub_type == "up":
|
||||||
|
up_data.append(x)
|
||||||
|
if x.sub_type == "season":
|
||||||
|
season_data.append(x)
|
||||||
|
return live_data, up_data, season_data
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from services.db_context import db
|
from services.db_context import db
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
|
|
||||||
class GroupInfoUser(db.Model):
|
class GroupInfoUser(db.Model):
|
||||||
@@ -13,6 +13,7 @@ class GroupInfoUser(db.Model):
|
|||||||
belonging_group = db.Column(db.BigInteger(), nullable=False)
|
belonging_group = db.Column(db.BigInteger(), nullable=False)
|
||||||
user_join_time = db.Column(db.DateTime(), nullable=False)
|
user_join_time = db.Column(db.DateTime(), nullable=False)
|
||||||
nickname = db.Column(db.Unicode())
|
nickname = db.Column(db.Unicode())
|
||||||
|
uid = db.Column(db.BigInteger())
|
||||||
|
|
||||||
_idx1 = db.Index("info_group_users_idx1", "user_qq", "belonging_group", unique=True)
|
_idx1 = db.Index("info_group_users_idx1", "user_qq", "belonging_group", unique=True)
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ class GroupInfoUser(db.Model):
|
|||||||
belonging_group: int,
|
belonging_group: int,
|
||||||
user_name: str,
|
user_name: str,
|
||||||
user_join_time: datetime,
|
user_join_time: datetime,
|
||||||
|
uid: Optional[int] = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
@@ -32,6 +34,7 @@ class GroupInfoUser(db.Model):
|
|||||||
:param belonging_group: 群号
|
:param belonging_group: 群号
|
||||||
:param user_name: 用户名称
|
:param user_name: 用户名称
|
||||||
:param user_join_time: 入群时间
|
:param user_join_time: 入群时间
|
||||||
|
:param uid: 用户唯一 id(自动生成)
|
||||||
"""
|
"""
|
||||||
query = cls.query.where(
|
query = cls.query.where(
|
||||||
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
|
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
|
||||||
@@ -43,6 +46,7 @@ class GroupInfoUser(db.Model):
|
|||||||
user_name=user_name,
|
user_name=user_name,
|
||||||
belonging_group=belonging_group,
|
belonging_group=belonging_group,
|
||||||
user_join_time=user_join_time,
|
user_join_time=user_join_time,
|
||||||
|
uid=uid
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -141,3 +145,33 @@ class GroupInfoUser(db.Model):
|
|||||||
if user.nickname:
|
if user.nickname:
|
||||||
return user.nickname
|
return user.nickname
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
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.belonging_group == belonging_group)
|
||||||
|
)
|
||||||
|
user = await query.gino.first()
|
||||||
|
_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:
|
||||||
|
all_user = await cls.query.where(cls.user_qq == user_qq).gino.all()
|
||||||
|
for x in all_user:
|
||||||
|
if x.uid:
|
||||||
|
return x.uid
|
||||||
|
else:
|
||||||
|
if not user:
|
||||||
|
await GroupInfoUser.add_member_info(user_qq, belonging_group, '', datetime.min)
|
||||||
|
user = await cls.query.where(
|
||||||
|
(cls.user_qq == user_qq) & (cls.belonging_group == belonging_group)
|
||||||
|
).gino.first()
|
||||||
|
await user.update(
|
||||||
|
uid=_max_uid + 1,
|
||||||
|
).apply()
|
||||||
|
await _max_uid_user.update(
|
||||||
|
uid=_max_uid + 1,
|
||||||
|
).apply()
|
||||||
|
|
||||||
|
return user.uid if user and user.uid else None
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
from typing import Optional, List
|
||||||
|
from datetime import datetime
|
||||||
|
from services.db_context import db
|
||||||
|
|
||||||
|
|
||||||
|
class OmegaPixivIllusts(db.Model):
|
||||||
|
__tablename__ = "omega_pixiv_illusts"
|
||||||
|
id = db.Column(db.Integer(), primary_key=True)
|
||||||
|
pid = db.Column(db.BigInteger(), nullable=False)
|
||||||
|
uid = db.Column(db.BigInteger(), nullable=False)
|
||||||
|
title = db.Column(db.String(), nullable=False)
|
||||||
|
uname = db.Column(db.String(), nullable=False)
|
||||||
|
nsfw_tag = db.Column(db.Integer(), nullable=False)
|
||||||
|
width = db.Column(db.Integer(), nullable=False)
|
||||||
|
height = db.Column(db.Integer(), nullable=False)
|
||||||
|
tags = db.Column(db.String(), nullable=False)
|
||||||
|
url = db.Column(db.String(), nullable=False)
|
||||||
|
created_at = db.Column(db.DateTime(timezone=True))
|
||||||
|
updated_at = db.Column(db.DateTime(timezone=True))
|
||||||
|
|
||||||
|
_idx1 = db.Index("omega_pixiv_illusts_idx1", "pid", "url", unique=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def add_image_data(
|
||||||
|
cls,
|
||||||
|
pid: int,
|
||||||
|
title: str,
|
||||||
|
width: int,
|
||||||
|
height: int,
|
||||||
|
url: str,
|
||||||
|
uid: int,
|
||||||
|
uname: str,
|
||||||
|
nsfw_tag: int,
|
||||||
|
tags: str,
|
||||||
|
created_at: datetime,
|
||||||
|
updated_at: datetime,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
添加图片信息
|
||||||
|
参数:
|
||||||
|
:param pid: pid
|
||||||
|
:param title: 标题
|
||||||
|
:param width: 宽度
|
||||||
|
:param height: 长度
|
||||||
|
:param url: url链接
|
||||||
|
:param uid: 作者uid
|
||||||
|
:param uname: 作者名称
|
||||||
|
:param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
|
||||||
|
:param tags: 相关tag
|
||||||
|
:param created_at: 创建日期
|
||||||
|
:param updated_at: 更新日期
|
||||||
|
"""
|
||||||
|
if not await cls.check_exists(pid):
|
||||||
|
await cls.create(
|
||||||
|
pid=pid,
|
||||||
|
title=title,
|
||||||
|
width=width,
|
||||||
|
height=height,
|
||||||
|
url=url,
|
||||||
|
uid=uid,
|
||||||
|
uname=uname,
|
||||||
|
nsfw_tag=nsfw_tag,
|
||||||
|
tags=tags,
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def query_images(
|
||||||
|
cls,
|
||||||
|
keywords: Optional[List[str]] = None,
|
||||||
|
uid: Optional[int] = None,
|
||||||
|
pid: Optional[int] = None,
|
||||||
|
nsfw_tag: Optional[int] = 0,
|
||||||
|
num: int = 100
|
||||||
|
) -> List[Optional["OmegaPixivIllusts"]]:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
查找符合条件的图片
|
||||||
|
参数:
|
||||||
|
:param keywords: 关键词
|
||||||
|
:param uid: 画师uid
|
||||||
|
:param pid: 图片pid
|
||||||
|
:param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
|
||||||
|
:param num: 获取图片数量
|
||||||
|
"""
|
||||||
|
if nsfw_tag is not None:
|
||||||
|
query = cls.query.where(cls.nsfw_tag == nsfw_tag)
|
||||||
|
else:
|
||||||
|
query = cls.query
|
||||||
|
if keywords:
|
||||||
|
for keyword in keywords:
|
||||||
|
query = query.where(cls.tags.contains(keyword))
|
||||||
|
elif uid:
|
||||||
|
query = query.where(cls.uid == uid)
|
||||||
|
elif pid:
|
||||||
|
query = query.where(cls.uid == pid)
|
||||||
|
query = query.order_by(db.func.random()).limit(num)
|
||||||
|
return await query.gino.all()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def check_exists(cls, pid: int) -> bool:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
检测pid是否已存在
|
||||||
|
参数:
|
||||||
|
:param pid: 图片PID
|
||||||
|
"""
|
||||||
|
query = await cls.query.where(cls.pid == pid).gino.all()
|
||||||
|
return bool(query)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_keyword_num(cls, tags: List[str] = None) -> "int, int, int":
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
获取相关关键词(keyword, tag)在图库中的数量
|
||||||
|
参数:
|
||||||
|
:param tags: 关键词/Tag
|
||||||
|
"""
|
||||||
|
setattr(OmegaPixivIllusts, 'count', db.func.count(cls.pid).label('count'))
|
||||||
|
query = cls.select('count')
|
||||||
|
if tags:
|
||||||
|
for tag in tags:
|
||||||
|
query = query.where(cls.tags.contains(tag))
|
||||||
|
count = await query.where(cls.nsfw_tag == 0).gino.first()
|
||||||
|
setu_count = await query.where(cls.nsfw_tag == 1).gino.first()
|
||||||
|
r18_count = await query.where(cls.nsfw_tag == 2).gino.first()
|
||||||
|
return count[0], setu_count[0], r18_count[0]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_all_pid(cls) -> List[int]:
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
获取所有图片PID
|
||||||
|
"""
|
||||||
|
data = await cls.select('pid').gino.all()
|
||||||
|
return [x[0] for x in data]
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
from services.db_context import db
|
from services.db_context import db
|
||||||
import asyncio
|
|
||||||
|
|
||||||
|
|
||||||
class Pixiv(db.Model):
|
class Pixiv(db.Model):
|
||||||
@@ -24,18 +23,19 @@ class Pixiv(db.Model):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def add_image_data(
|
async def add_image_data(
|
||||||
cls,
|
cls,
|
||||||
pid: int,
|
pid: int,
|
||||||
title: str,
|
title: str,
|
||||||
width: int,
|
width: int,
|
||||||
height: int,
|
height: int,
|
||||||
view: int,
|
view: int,
|
||||||
bookmarks: int,
|
bookmarks: int,
|
||||||
img_url: str,
|
img_url: str,
|
||||||
img_p: str,
|
img_p: str,
|
||||||
uid: int,
|
uid: int,
|
||||||
author: str,
|
author: str,
|
||||||
tags: str,
|
tags: str,
|
||||||
|
nws
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
@@ -65,7 +65,7 @@ class Pixiv(db.Model):
|
|||||||
img_p=img_p,
|
img_p=img_p,
|
||||||
uid=uid,
|
uid=uid,
|
||||||
author=author,
|
author=author,
|
||||||
is_r18=True if 'R-18' in tags else False,
|
is_r18=True if "R-18" in tags else False,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
@@ -97,44 +97,45 @@ class Pixiv(db.Model):
|
|||||||
说明:
|
说明:
|
||||||
获取所有PID
|
获取所有PID
|
||||||
"""
|
"""
|
||||||
pid = []
|
query = await cls.query.select("pid").gino.first()
|
||||||
query = await cls.query.gino.all()
|
pid = [x[0] for x in query]
|
||||||
for image in query:
|
return list(set(pid))
|
||||||
if image.pid not in pid:
|
|
||||||
pid.append(image.pid)
|
|
||||||
return pid
|
|
||||||
|
|
||||||
# 0:非r18 1:r18 2:混合
|
# 0:非r18 1:r18 2:混合
|
||||||
@classmethod
|
@classmethod
|
||||||
async def query_images(
|
async def query_images(
|
||||||
cls,
|
cls,
|
||||||
keyword: Optional[List[str]] = None,
|
keywords: Optional[List[str]] = None,
|
||||||
uid: Optional[int] = None,
|
uid: Optional[int] = None,
|
||||||
pid: Optional[int] = None,
|
pid: Optional[int] = None,
|
||||||
r18: int = 0,
|
r18: Optional[int] = 0,
|
||||||
|
num: int = 100
|
||||||
) -> List[Optional["Pixiv"]]:
|
) -> List[Optional["Pixiv"]]:
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
查找符合条件的图片
|
查找符合条件的图片
|
||||||
参数:
|
参数:
|
||||||
:param keyword: 关键词
|
:param keywords: 关键词
|
||||||
:param uid: 画师uid
|
:param uid: 画师uid
|
||||||
:param pid: 图片pid
|
:param pid: 图片pid
|
||||||
:param r18: 是否r18,0:非r18 1:r18 2:混合
|
:param r18: 是否r18,0:非r18 1:r18 2:混合
|
||||||
|
:param num: 查找图片的数量
|
||||||
"""
|
"""
|
||||||
if r18 == 0:
|
if r18 == 0:
|
||||||
query = await cls.query.where(cls.is_r18 == False).gino.all()
|
query = cls.query.where(cls.is_r18 == False)
|
||||||
elif r18 == 1:
|
elif r18 == 1:
|
||||||
query = await cls.query.where(cls.is_r18 == True).gino.all()
|
query = cls.query.where(cls.is_r18 == True)
|
||||||
else:
|
else:
|
||||||
query = await cls.query.gino.all()
|
query = cls.query
|
||||||
if keyword:
|
if keywords:
|
||||||
query = [x for x in query if set(x.tags.split(',')) > set(keyword)]
|
for keyword in keywords:
|
||||||
|
query = query.where(cls.tags.contains(keyword))
|
||||||
elif uid:
|
elif uid:
|
||||||
query = [x for x in query if x.uid == uid]
|
query = query.where(cls.uid == uid)
|
||||||
elif pid:
|
elif pid:
|
||||||
query = [x for x in query if x.pid == pid]
|
query = query.where(cls.uid == pid)
|
||||||
return query
|
query = query.order_by(db.func.random()).limit(num)
|
||||||
|
return await query.gino.all()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def check_exists(cls, pid: int, img_p: str) -> bool:
|
async def check_exists(cls, pid: int, img_p: str) -> bool:
|
||||||
@@ -151,41 +152,19 @@ class Pixiv(db.Model):
|
|||||||
return bool(query)
|
return bool(query)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_keyword_num(cls, keyword: List[str]) -> "int, int":
|
async def get_keyword_num(cls, tags: List[str] = None) -> "int, int":
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
获取相关关键词(keyword, tag)在图库中的数量
|
获取相关关键词(keyword, tag)在图库中的数量
|
||||||
参数:
|
参数:
|
||||||
:param keyword: 关键词/Tag
|
:param tags: 关键词/Tag
|
||||||
"""
|
"""
|
||||||
query = await cls.query.gino.all()
|
setattr(Pixiv, 'count', db.func.count(cls.pid).label('count'))
|
||||||
i = int(len(query) / 200)
|
query = cls.select('count')
|
||||||
mod = len(query) % 200
|
if tags:
|
||||||
tasks = []
|
for tag in tags:
|
||||||
start = 0
|
query = query.where(cls.tags.contains(tag))
|
||||||
end = 200
|
count = await query.where(cls.is_r18 == False).gino.first()
|
||||||
count = 0
|
r18_count = await query.where(cls.is_r18 == True).gino.first()
|
||||||
r18_count = 0
|
return count[0], r18_count[0]
|
||||||
for _ in range(i):
|
|
||||||
tasks.append(asyncio.ensure_future(split_query_list(query[start: end], keyword)))
|
|
||||||
start += 200
|
|
||||||
end += 200
|
|
||||||
if mod:
|
|
||||||
tasks.append(asyncio.ensure_future(split_query_list(query[end:], keyword)))
|
|
||||||
result = await asyncio.gather(*tasks)
|
|
||||||
for x, j in result:
|
|
||||||
count += x
|
|
||||||
r18_count += j
|
|
||||||
# query = [x for x in query if set(x.tags.split(',')) > set(keyword)]
|
|
||||||
# r18_count = len([x for x in query if x.is_r18])
|
|
||||||
return count, r18_count
|
|
||||||
|
|
||||||
|
|
||||||
async def split_query_list(query: List['Pixiv'], keyword: List[str]) -> 'int, int':
|
|
||||||
return await asyncio.get_event_loop().run_in_executor(None, _split_query_list, query, keyword)
|
|
||||||
|
|
||||||
|
|
||||||
def _split_query_list(query: List['Pixiv'], keyword: List[str]) -> 'int, int':
|
|
||||||
query = [x for x in query if set(x.tags.split(',')) > set(keyword)]
|
|
||||||
r18_count = len([x for x in query if x.is_r18])
|
|
||||||
return len(query) - r18_count, r18_count
|
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ class RussianUser(db.Model):
|
|||||||
fail_count = db.Column(db.Integer(), default=0)
|
fail_count = db.Column(db.Integer(), default=0)
|
||||||
make_money = db.Column(db.Integer(), default=0)
|
make_money = db.Column(db.Integer(), default=0)
|
||||||
lose_money = db.Column(db.Integer(), default=0)
|
lose_money = db.Column(db.Integer(), default=0)
|
||||||
|
winning_streak = db.Column(db.Integer(), default=0)
|
||||||
|
losing_streak = db.Column(db.Integer(), default=0)
|
||||||
|
max_winning_streak = db.Column(db.Integer(), default=0)
|
||||||
|
max_losing_streak = db.Column(db.Integer(), default=0)
|
||||||
|
|
||||||
_idx1 = db.Index("russian_group_users_idx1", "user_qq", "group_id", unique=True)
|
_idx1 = db.Index("russian_group_users_idx1", "user_qq", "group_id", unique=True)
|
||||||
|
|
||||||
@@ -52,12 +56,28 @@ class RussianUser(db.Model):
|
|||||||
if not user:
|
if not user:
|
||||||
user = await cls.create(user_qq=user_qq, group_id=group_id)
|
user = await cls.create(user_qq=user_qq, group_id=group_id)
|
||||||
if itype == "win":
|
if itype == "win":
|
||||||
|
_max = (
|
||||||
|
user.max_winning_streak
|
||||||
|
if user.max_winning_streak > user.winning_streak + 1
|
||||||
|
else user.winning_streak + 1
|
||||||
|
)
|
||||||
await user.update(
|
await user.update(
|
||||||
win_count=user.win_count + 1,
|
win_count=user.win_count + 1,
|
||||||
|
winning_streak=user.winning_streak + 1,
|
||||||
|
losing_streak=0,
|
||||||
|
max_winning_streak=_max
|
||||||
).apply()
|
).apply()
|
||||||
elif itype == "lose":
|
elif itype == "lose":
|
||||||
|
_max = (
|
||||||
|
user.max_losing_streak
|
||||||
|
if user.max_losing_streak > user.losing_streak + 1
|
||||||
|
else user.losing_streak + 1
|
||||||
|
)
|
||||||
await user.update(
|
await user.update(
|
||||||
fail_count=user.fail_count + 1,
|
fail_count=user.fail_count + 1,
|
||||||
|
losing_streak=user.losing_streak + 1,
|
||||||
|
winning_streak=0,
|
||||||
|
max_losing_streak=_max,
|
||||||
).apply()
|
).apply()
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class Setu(db.Model):
|
|||||||
local_id: Optional[int] = None,
|
local_id: Optional[int] = None,
|
||||||
tags: Optional[List[str]] = None,
|
tags: Optional[List[str]] = None,
|
||||||
r18: int = 0,
|
r18: int = 0,
|
||||||
|
limit: int = 50,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
@@ -65,6 +66,7 @@ class Setu(db.Model):
|
|||||||
:param local_id: 本地色图 id
|
:param local_id: 本地色图 id
|
||||||
:param tags: tags
|
:param tags: tags
|
||||||
:param r18: 是否 r18,0:非r18 1:r18 2:混合
|
:param r18: 是否 r18,0:非r18 1:r18 2:混合
|
||||||
|
:param limit: 获取数量
|
||||||
"""
|
"""
|
||||||
if local_id:
|
if local_id:
|
||||||
flag = True if r18 == 1 else False
|
flag = True if r18 == 1 else False
|
||||||
@@ -72,23 +74,27 @@ class Setu(db.Model):
|
|||||||
(cls.local_id == local_id) & (cls.is_r18 == flag)
|
(cls.local_id == local_id) & (cls.is_r18 == flag)
|
||||||
).gino.first()
|
).gino.first()
|
||||||
if r18 == 0:
|
if r18 == 0:
|
||||||
query = await cls.query.where(cls.is_r18 == False).gino.all()
|
query = cls.query.where(cls.is_r18 == False)
|
||||||
elif r18 == 1:
|
elif r18 == 1:
|
||||||
query = await cls.query.where(cls.is_r18 == True).gino.all()
|
query = cls.query.where(cls.is_r18 == True)
|
||||||
else:
|
else:
|
||||||
query = await cls.query.gino.all()
|
query = cls.query
|
||||||
if tags:
|
if tags:
|
||||||
query = [x for x in query if set(x.tags.split(",")) > set(tags)]
|
for tag in tags:
|
||||||
return query
|
query = query.where(cls.tags.contains(tag) | cls.title.contains(tag) | cls.author.contains(tag))
|
||||||
|
query = query.order_by(db.func.random()).limit(limit)
|
||||||
|
return await query.gino.all()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_image_count(cls, r18: int = 0):
|
async def get_image_count(cls, r18: int = 0) -> int:
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
查询图片数量
|
查询图片数量
|
||||||
"""
|
"""
|
||||||
return len(await cls.query_image(r18=r18))
|
flag = False if r18 == 0 else True
|
||||||
# return await db.func.count(cls.local_id).gino.scalar()
|
setattr(Setu, 'count', db.func.count(cls.local_id).label('count'))
|
||||||
|
count = await cls.select('count').where(cls.is_r18 == flag).gino.first()
|
||||||
|
return count[0]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_image_in_hash(cls, img_hash: str) -> "Setu":
|
async def get_image_in_hash(cls, img_hash: str) -> "Setu":
|
||||||
|
|||||||
@@ -41,7 +41,17 @@ class SignGroupUser(db.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_all_impression(cls, belonging_group: int) -> "list, list":
|
async def sign(cls, user: "SignGroupUser", impression: float, checkin_time_last: datetime):
|
||||||
|
await user.update(
|
||||||
|
checkin_count=user.checkin_count + 1,
|
||||||
|
checkin_time_last=checkin_time_last,
|
||||||
|
impression=user.impression + impression,
|
||||||
|
add_probability=0,
|
||||||
|
specify_probability=0,
|
||||||
|
).apply()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_all_impression(cls, belonging_group: int) -> "list, list, list":
|
||||||
"""
|
"""
|
||||||
说明:
|
说明:
|
||||||
获取该群所有用户 id 及对应 好感度
|
获取该群所有用户 id 及对应 好感度
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
from models.group_remind import GroupRemind
|
from models.group_remind import GroupRemind
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from configs.path_config import DATA_PATH
|
from configs.path_config import DATA_PATH
|
||||||
import os
|
|
||||||
import aiofiles
|
|
||||||
import aiohttp
|
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
from utils.utils import get_local_proxy, get_bot
|
from utils.utils import get_local_proxy, get_bot
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from configs.config import plugins2info_dict
|
|
||||||
from models.group_member_info import GroupInfoUser
|
from models.group_member_info import GroupInfoUser
|
||||||
import time
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from services.db_context import db
|
from services.db_context import db
|
||||||
from models.level_user import LevelUser
|
from models.level_user import LevelUser
|
||||||
from configs.config import ADMIN_DEFAULT_AUTH
|
from configs.config import ADMIN_DEFAULT_AUTH
|
||||||
from utils.static_data import group_manager
|
from utils.static_data import group_manager
|
||||||
from utils.image_utils import CreateImg
|
from utils.image_utils import CreateImg
|
||||||
|
from configs.config import plugins2info_dict
|
||||||
|
import aiofiles
|
||||||
|
import aiohttp
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
@@ -53,7 +53,7 @@ async def remind_status(group: int, name: str, flag: bool) -> str:
|
|||||||
else:
|
else:
|
||||||
rst = "关闭"
|
rst = "关闭"
|
||||||
if not await GroupRemind.get_status(group, name):
|
if not await GroupRemind.get_status(group, name):
|
||||||
return f"该群已经{rst}过 {_name},请勿重复开启!"
|
return f"该群已经{rst}过 {_name},请勿重复关闭!"
|
||||||
if await GroupRemind.set_status(group, name, flag):
|
if await GroupRemind.set_status(group, name, flag):
|
||||||
info = command_info_dt[_name] if command_info_dt.get(_name) else ""
|
info = command_info_dt[_name] if command_info_dt.get(_name) else ""
|
||||||
if info:
|
if info:
|
||||||
@@ -267,3 +267,7 @@ async def update_member_info(group_id: int) -> bool:
|
|||||||
user_id=int(list(bot.config.superusers)[0]), message=result[:-1]
|
user_id=int(list(bot.config.superusers)[0]), message=result[:-1]
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
else:
|
else:
|
||||||
if str(event.user_id) in bot.config.superusers:
|
if str(event.user_id) in bot.config.superusers:
|
||||||
block_type = get_message_text(event.json())
|
block_type = get_message_text(event.json())
|
||||||
|
block_type = block_type if block_type else 'a'
|
||||||
_cmd = state["_prefix"]["raw_command"].strip()
|
_cmd = state["_prefix"]["raw_command"].strip()
|
||||||
if is_number(block_type):
|
if is_number(block_type):
|
||||||
if not int(block_type) in [g["group_id"] for g in await bot.get_group_list(self_id=int(bot.self_id))]:
|
if not int(block_type) in [g["group_id"] for g in await bot.get_group_list(self_id=int(bot.self_id))]:
|
||||||
@@ -53,9 +54,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
change_group_switch(_cmd, int(block_type), True)
|
change_group_switch(_cmd, int(block_type), True)
|
||||||
group_name = (await bot.get_group_info(group_id=int(block_type)))['group_name']
|
group_name = (await bot.get_group_info(group_id=int(block_type)))['group_name']
|
||||||
await switch_rule.send(f'已禁用群聊 {group_name}({block_type}) 的 {_cmd[2:]} 功能')
|
await switch_rule.send(f'已禁用群聊 {group_name}({block_type}) 的 {_cmd[2:]} 功能')
|
||||||
else:
|
elif block_type in ['all', 'private', 'group', 'a', 'p', 'g']:
|
||||||
if block_type not in ['all', 'private', 'group', 'a', 'p', 'g']:
|
|
||||||
block_type = 'all'
|
|
||||||
block_type = 'all' if block_type == 'a' else block_type
|
block_type = 'all' if block_type == 'a' else block_type
|
||||||
block_type = 'private' if block_type == 'p' else block_type
|
block_type = 'private' if block_type == 'p' else block_type
|
||||||
block_type = 'group' if block_type == 'g' else block_type
|
block_type = 'group' if block_type == 'g' else block_type
|
||||||
@@ -66,6 +65,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
await switch_rule.send(f'已在私聊中{_cmd[:2]}功能:{_cmd[2:]}')
|
await switch_rule.send(f'已在私聊中{_cmd[:2]}功能:{_cmd[2:]}')
|
||||||
else:
|
else:
|
||||||
await switch_rule.send(f'已在群聊中{_cmd[:2]}功能:{_cmd[2:]}')
|
await switch_rule.send(f'已在群聊中{_cmd[:2]}功能:{_cmd[2:]}')
|
||||||
|
else:
|
||||||
|
await switch_rule.finish('格式错误:关闭[功能] [group]/[p/g]')
|
||||||
logger.info(
|
logger.info(
|
||||||
f'USER {event.user_id} 使用功能管理命令 {state["_prefix"]["raw_command"]} | {block_type}'
|
f'USER {event.user_id} 使用功能管理命令 {state["_prefix"]["raw_command"]} | {block_type}'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from nonebot import on_command, export
|
from nonebot import on_command, on_notice
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, GROUP
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
|
||||||
from .data_source import update_member_info
|
from .data_source import update_member_info
|
||||||
|
|
||||||
__plugin_name__ = "更新群组成员列表"
|
__plugin_name__ = "更新群组成员列表"
|
||||||
@@ -12,8 +12,6 @@ __plugin_usage__ = """
|
|||||||
更新群组成员列表
|
更新群组成员列表
|
||||||
"""
|
"""
|
||||||
|
|
||||||
export = export()
|
|
||||||
export.update_member_info = update_member_info
|
|
||||||
|
|
||||||
refresh_member_group = on_command(
|
refresh_member_group = on_command(
|
||||||
"更新群组成员列表", aliases={"更新群组成员信息"}, permission=GROUP, priority=5, block=True
|
"更新群组成员列表", aliases={"更新群组成员信息"}, permission=GROUP, priority=5, block=True
|
||||||
@@ -26,3 +24,12 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
|
await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
|
||||||
else:
|
else:
|
||||||
await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
|
await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
|
||||||
|
|
||||||
|
|
||||||
|
group_increase_handle = on_notice(priority=1, block=False)
|
||||||
|
|
||||||
|
|
||||||
|
@group_increase_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
|
||||||
|
if event.user_id == int(bot.self_id):
|
||||||
|
await update_member_info(event.group_id)
|
||||||
|
|||||||
@@ -9,17 +9,23 @@ from configs.config import NICKNAME
|
|||||||
|
|
||||||
|
|
||||||
__plugin_name__ = '管理帮助 [Hidden]'
|
__plugin_name__ = '管理帮助 [Hidden]'
|
||||||
__plugin_usage__ = f'''管理帮助(权限等级):
|
__plugin_usage__ = f'''[权限等级]管理帮助:
|
||||||
1.更新群组成员列表(1)
|
[1]1.更新群组成员列表
|
||||||
2.功能开关 --> 指令:开启/关闭xx功能(2)
|
[2]2.功能开关 --> 指令:开启/关闭xx功能
|
||||||
3.查看群被动技能 --> 指令:群通知状态(2)
|
[2]3.查看群被动技能 --> 指令:群通知状态
|
||||||
4.自定义群欢迎 --> 指令:自定义进群欢迎消息(2)
|
[2]4.自定义群欢迎 --> 指令:自定义进群欢迎消息
|
||||||
5.将用户拉入{NICKNAME}黑名单 --> .ban/.unban(5)
|
[5]5.将用户拉入{NICKNAME}黑名单 --> .ban/.unban
|
||||||
6.刷屏禁言相关 --> 指令:刷屏检测设置/设置检测时间
|
[5]6.刷屏禁言相关 -> 指令:刷屏检测设置/设置检测时间
|
||||||
\t\t/设置检测次数/设置禁言时长(5)
|
\t\t/设置检测次数/设置禁言时长
|
||||||
8.上传图片/连续上传图片(6)
|
[5]7.群订阅相关 -> 指令:添加订阅 [主播/up/番剧] [id/番名/链接]
|
||||||
9.移动图片(7)
|
\t\t/删除订阅 [id]/ 查看订阅
|
||||||
10.删除图片(7)
|
[5]8.群员活跃度相关 --> 指令:群员活跃检测设置
|
||||||
|
设置群员活跃检测时长(天)
|
||||||
|
添加群员活跃检测白名单[at]...
|
||||||
|
查看群员活跃检测白名单
|
||||||
|
[6]8.上传图片/连续上传图片(6)
|
||||||
|
[7]9.移动图片(7)
|
||||||
|
[7]10.删除图片(7)
|
||||||
对我说 “{NICKNAME}帮助 指令” 获取对应详细帮助
|
对我说 “{NICKNAME}帮助 指令” 获取对应详细帮助
|
||||||
群主与管理员默认 5 级权限
|
群主与管理员默认 5 级权限
|
||||||
'''
|
'''
|
||||||
@@ -37,11 +43,11 @@ passive_help = '''【被动技能开关(2):
|
|||||||
|
|
||||||
admin_help = on_command("管理员帮助", aliases={"管理帮助"}, priority=5, block=True)
|
admin_help = on_command("管理员帮助", aliases={"管理帮助"}, priority=5, block=True)
|
||||||
|
|
||||||
admin_help_img = CreateImg(1000, 600, font_size=24)
|
admin_help_img = CreateImg(1200, 600, font_size=24)
|
||||||
admin_help_img.text((10, 10), __plugin_usage__)
|
admin_help_img.text((10, 10), __plugin_usage__)
|
||||||
text_img = CreateImg(450, 600, font_size=24)
|
text_img = CreateImg(450, 600, font_size=24)
|
||||||
text_img.text((0, 0), passive_help)
|
text_img.text((0, 0), passive_help)
|
||||||
admin_help_img.paste(text_img, (650, 50))
|
admin_help_img.paste(text_img, (850, 50))
|
||||||
admin_help_img.save(IMAGE_PATH + 'admin_help_img.png')
|
admin_help_img.save(IMAGE_PATH + 'admin_help_img.png')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
result = await get_chat_result(msg, img, event.user_id, nickname)
|
result = await get_chat_result(msg, img, event.user_id, nickname)
|
||||||
logger.info(
|
logger.info(
|
||||||
f"USER {event.user_id} GROUP {event.group_id if not isinstance(event, PrivateMessageEvent) else ''} "
|
f"USER {event.user_id} GROUP {event.group_id if not isinstance(event, PrivateMessageEvent) else ''} "
|
||||||
f"问题:{msg}\n回答:{result}"
|
f"问题:{msg} ---- 回答:{result}"
|
||||||
)
|
)
|
||||||
if result:
|
if result:
|
||||||
await ai.finish(Message(result))
|
await ai.finish(Message(result))
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ 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"))
|
||||||
|
|
||||||
|
|
||||||
# 图灵AI
|
|
||||||
async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str) -> str:
|
async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str) -> str:
|
||||||
global index
|
global index
|
||||||
if index == 5:
|
if index == 5:
|
||||||
@@ -104,7 +103,9 @@ async def xie_ai(text: str, sess: ClientSession):
|
|||||||
if data["result"] == 0:
|
if data["result"] == 0:
|
||||||
content = data["content"]
|
content = data["content"]
|
||||||
if "菲菲" in content:
|
if "菲菲" in content:
|
||||||
content = content.replace("菲菲", f"{NICKNAME}")
|
content = content.replace("菲菲", NICKNAME)
|
||||||
|
if '艳儿' in content:
|
||||||
|
content = content.replace('艳儿', NICKNAME)
|
||||||
if "公众号" in content:
|
if "公众号" in content:
|
||||||
content = ""
|
content = ""
|
||||||
if "{br}" in content:
|
if "{br}" in content:
|
||||||
@@ -131,7 +132,7 @@ def hello() -> str:
|
|||||||
(
|
(
|
||||||
"哦豁?!",
|
"哦豁?!",
|
||||||
"你好!Ov<",
|
"你好!Ov<",
|
||||||
f"库库库,呼唤{list(get_bot().config.nickname)[0]}做什么呢",
|
f"库库库,呼唤{NICKNAME}做什么呢",
|
||||||
"我在呢!",
|
"我在呢!",
|
||||||
"呼呼,叫俺干嘛",
|
"呼呼,叫俺干嘛",
|
||||||
)
|
)
|
||||||
@@ -169,8 +170,8 @@ async def check_text(text: str, sess: ClientSession) -> str:
|
|||||||
async with sess.get(check_url, timeout=2, params=params) as response:
|
async with sess.get(check_url, timeout=2, params=params) as response:
|
||||||
data = await response.json()
|
data = await response.json()
|
||||||
if data["code"] == 200:
|
if data["code"] == 200:
|
||||||
if data["conclusion_type"] == 2:
|
if data['data']["conclusion_type"] == 2:
|
||||||
return ''
|
return ''
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"检测违规文本错误...e:{e}")
|
logger.error(f"检测违规文本错误...{type(e)}:{e}")
|
||||||
return text
|
return text
|
||||||
|
|||||||
@@ -34,11 +34,12 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
if code != 200:
|
if code != 200:
|
||||||
await wbtop.finish(data, at_sender=True)
|
await wbtop.finish(data, at_sender=True)
|
||||||
wbtop_data = data['data']
|
wbtop_data = data['data']
|
||||||
img = await asyncio.get_event_loop().run_in_executor(None, gen_wbtop_pic, wbtop_data)
|
if not msg:
|
||||||
await wbtop.send(img)
|
img = await asyncio.get_event_loop().run_in_executor(None, gen_wbtop_pic, wbtop_data)
|
||||||
logger.info(
|
await wbtop.send(img)
|
||||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
logger.info(
|
||||||
f" 查询微博热搜")
|
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
|
f" 查询微博热搜")
|
||||||
if is_number(msg) and 0 < int(msg) <= 50:
|
if is_number(msg) and 0 < int(msg) <= 50:
|
||||||
url = wbtop_data[int(msg) - 1]['url']
|
url = wbtop_data[int(msg) - 1]['url']
|
||||||
browser = await get_browser()
|
browser = await get_browser()
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ from models.level_user import LevelUser
|
|||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot
|
from nonebot.adapters.cqhttp import Bot
|
||||||
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
|
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
|
||||||
from nonebot.adapters.cqhttp.permission import GROUP
|
|
||||||
from utils.utils import get_message_at, get_message_text, is_number
|
from utils.utils import get_message_at, get_message_text, is_number
|
||||||
from configs.config import NICKNAME
|
from configs.config import NICKNAME
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
|
|
||||||
|
|
||||||
@@ -29,6 +29,8 @@ ban = on_command(
|
|||||||
block=True,
|
block=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
super_ban = on_command('b了', permission=SUPERUSER, priority=5, block=True)
|
||||||
|
|
||||||
|
|
||||||
@ban.handle()
|
@ban.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
@@ -155,5 +157,17 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
|||||||
await ban.finish('qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?', at_sender=True)
|
await ban.finish('qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?', at_sender=True)
|
||||||
|
|
||||||
|
|
||||||
|
@super_ban.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
qq = get_message_at(event.json())
|
||||||
|
if qq:
|
||||||
|
qq = qq[0]
|
||||||
|
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||||
|
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的对象..')
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,198 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
|
||||||
|
from .data_source import (
|
||||||
|
add_live_sub,
|
||||||
|
delete_sub,
|
||||||
|
add_up_sub,
|
||||||
|
add_season_sub,
|
||||||
|
get_media_id,
|
||||||
|
get_sub_status,
|
||||||
|
SubManager,
|
||||||
|
)
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
from configs.config import GROUP_BILIBILI_SUB_LEVEL
|
||||||
|
from utils.utils import get_message_text, is_number, scheduler, get_bot
|
||||||
|
from models.bilibili_sub import BilibiliSub
|
||||||
|
from typing import Optional
|
||||||
|
from services.log import logger
|
||||||
|
from nonebot import Driver
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
__plugin_name__ = "B站订阅"
|
||||||
|
|
||||||
|
__plugin_usage__ = """B站订阅帮助:
|
||||||
|
添加订阅 [主播/UP/番剧] [id/链接/番名]
|
||||||
|
删除订阅 [id]
|
||||||
|
查看订阅"""
|
||||||
|
|
||||||
|
add_sub = on_command("添加订阅", priority=5, block=True)
|
||||||
|
del_sub = on_command("删除订阅", priority=5, block=True)
|
||||||
|
show_sub_info = on_command('查看订阅', priority=5, block=True)
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
|
||||||
|
sub_manager: Optional[SubManager] = None
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def _():
|
||||||
|
global sub_manager
|
||||||
|
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 _(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]
|
||||||
|
id_ = ""
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
if not await LevelUser.check_level(
|
||||||
|
event.user_id, event.group_id, GROUP_BILIBILI_SUB_LEVEL
|
||||||
|
):
|
||||||
|
await add_sub.finish(
|
||||||
|
f"您的权限不足,群内订阅的需要 {GROUP_BILIBILI_SUB_LEVEL} 级权限..", at_sender=True
|
||||||
|
)
|
||||||
|
sub_user = f"{event.user_id}:{event.group_id}"
|
||||||
|
else:
|
||||||
|
sub_user = f"{event.user_id}"
|
||||||
|
state["sub_type"] = sub_type
|
||||||
|
state["sub_user"] = sub_user
|
||||||
|
if len(msg) > 1:
|
||||||
|
if "http" in msg[1]:
|
||||||
|
msg[1] = msg[1].split("?")[0]
|
||||||
|
msg[1] = msg[1][:-1] if msg[1][-1] == "/" else msg[1]
|
||||||
|
msg[1] = msg[1].split("/")[-1]
|
||||||
|
id_ = msg[1][2:] if msg[1].startswith("md") else msg[1]
|
||||||
|
if not is_number(id_):
|
||||||
|
if sub_type in ["season", "动漫", "番剧"]:
|
||||||
|
rst = "*以为您找到以下番剧,请输入Id选择:*\n"
|
||||||
|
state["season_data"] = await get_media_id(id_)
|
||||||
|
if len(state["season_data"]) == 0:
|
||||||
|
await add_sub.finish(f"未找到番剧:{msg}")
|
||||||
|
for i, x in enumerate(state["season_data"]):
|
||||||
|
rst += f'{i + 1}.{state["season_data"][x]["title"]}\n----------\n'
|
||||||
|
await add_sub.send("\n".join(rst.split("\n")[:-1]))
|
||||||
|
else:
|
||||||
|
await add_sub.finish("Id 必须为全数字!")
|
||||||
|
else:
|
||||||
|
state["id"] = int(id_)
|
||||||
|
|
||||||
|
|
||||||
|
@add_sub.got("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", "用户"]:
|
||||||
|
await add_sub.send(await add_up_sub(id_, sub_user))
|
||||||
|
elif sub_type in ["season", "动漫", "番剧"]:
|
||||||
|
await add_sub.send(await add_season_sub(id_, sub_user))
|
||||||
|
else:
|
||||||
|
await add_sub.finish("参数错误,第一参数必须为:主播/up/番剧!")
|
||||||
|
logger.info(
|
||||||
|
f"(USER {event.user_id}, GROUP "
|
||||||
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
|
f" 添加订阅:{sub_type} -> {sub_user} -> {id_}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@del_sub.handle()
|
||||||
|
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_ = f'{event.user_id}:{event.group_id}' if isinstance(event, GroupMessageEvent) else f'{event.user_id}'
|
||||||
|
if await BilibiliSub.delete_bilibili_sub(int(msg), id_):
|
||||||
|
await del_sub.send(f'删除订阅id:{msg} 成功...')
|
||||||
|
logger.info(
|
||||||
|
f"(USER {event.user_id}, GROUP "
|
||||||
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
|
f" 删除订阅 {id_}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await del_sub.send(f'删除订阅id:{msg} 失败...')
|
||||||
|
|
||||||
|
|
||||||
|
@show_sub_info.handle()
|
||||||
|
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 = ''
|
||||||
|
season_rst = ''
|
||||||
|
for x in data:
|
||||||
|
if x.sub_type == 'live':
|
||||||
|
live_rst += f'\t直播间id:{x.sub_id}\n' \
|
||||||
|
f'\t名称:{x.uname}\n' \
|
||||||
|
f'------------------\n'
|
||||||
|
if x.sub_type == 'up':
|
||||||
|
up_rst += f'\tUP:{x.uname}\n' \
|
||||||
|
f'\tuid:{x.uid}\n' \
|
||||||
|
f'------------------\n'
|
||||||
|
if x.sub_type == 'season':
|
||||||
|
season_rst += f'\t番名:{x.season_name}\n' \
|
||||||
|
f'\t当前集数:{x.season_current_episode}\n' \
|
||||||
|
f'------------------\n'
|
||||||
|
live_rst = '当前订阅的直播:\n' + live_rst if live_rst else live_rst
|
||||||
|
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 = '您目前没有任何订阅...'
|
||||||
|
await show_sub_info.send(live_rst + up_rst + season_rst)
|
||||||
|
|
||||||
|
|
||||||
|
# 推送
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
"interval",
|
||||||
|
seconds=30,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
bot = get_bot()
|
||||||
|
sub = None
|
||||||
|
if bot:
|
||||||
|
try:
|
||||||
|
await sub_manager.reload_sub_data()
|
||||||
|
sub = await sub_manager.random_sub_data()
|
||||||
|
if sub:
|
||||||
|
rst = await get_sub_status(sub.sub_id, sub.sub_type)
|
||||||
|
await send_sub_msg(rst, sub, bot)
|
||||||
|
if sub.sub_type == "live":
|
||||||
|
rst = await get_sub_status(sub.sub_id, "up")
|
||||||
|
await send_sub_msg(rst, sub, bot)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id if sub else 0} {type(e)}:{e}")
|
||||||
|
|
||||||
|
|
||||||
|
async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
|
||||||
|
"""
|
||||||
|
推送信息
|
||||||
|
:param rst: 回复
|
||||||
|
:param sub: BilibiliSub
|
||||||
|
:param bot: Bot
|
||||||
|
"""
|
||||||
|
if rst:
|
||||||
|
for x in sub.sub_users.split(",")[:-1]:
|
||||||
|
try:
|
||||||
|
if ":" in x:
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=int(x.split(":")[1]), message=Message(rst)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await bot.send_private_msg(user_id=int(x), message=Message(rst))
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id} {type(e)}:{e}")
|
||||||
@@ -0,0 +1,390 @@
|
|||||||
|
from bilibili_api.exceptions.ResponseCodeException import ResponseCodeException
|
||||||
|
from asyncio.exceptions import TimeoutError
|
||||||
|
from models.bilibili_sub import BilibiliSub
|
||||||
|
from bilibili_api.live import LiveRoom
|
||||||
|
from bilibili_api import bangumi
|
||||||
|
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
|
||||||
|
from services.db_context import db
|
||||||
|
from services.log import logger
|
||||||
|
import aiohttp
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
|
||||||
|
|
||||||
|
dynamic_path = Path(IMAGE_PATH) / "bilibili_sub" / "dynamic"
|
||||||
|
dynamic_path.mkdir(exist_ok=True, parents=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def add_live_sub(live_id: int, sub_user: str) -> str:
|
||||||
|
"""
|
||||||
|
添加直播订阅
|
||||||
|
:param live_id: 直播房间号
|
||||||
|
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with db.transaction():
|
||||||
|
try:
|
||||||
|
live = LiveRoom(live_id)
|
||||||
|
live_info = (await live.get_room_info())["room_info"]
|
||||||
|
except ResponseCodeException:
|
||||||
|
return f"未找到房间号Id:{live_id} 的信息,请检查Id是否正确"
|
||||||
|
uid = live_info["uid"]
|
||||||
|
room_id = live_info["room_id"]
|
||||||
|
short_id = live_info["short_id"]
|
||||||
|
title = live_info["title"]
|
||||||
|
live_status = live_info["live_status"]
|
||||||
|
if await BilibiliSub.add_bilibili_sub(
|
||||||
|
room_id,
|
||||||
|
"live",
|
||||||
|
sub_user,
|
||||||
|
uid=uid,
|
||||||
|
live_short_id=short_id,
|
||||||
|
live_status=live_status,
|
||||||
|
):
|
||||||
|
await _get_up_status(live_id)
|
||||||
|
uname = (await BilibiliSub.get_sub(live_id)).uname
|
||||||
|
return (
|
||||||
|
"已成功订阅主播:\n"
|
||||||
|
f"\ttitle:{title}\n"
|
||||||
|
f"\tname: {uname}\n"
|
||||||
|
f"\tlive_id:{live_id}\n"
|
||||||
|
f"\tuid:{uid}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return "添加订阅失败..."
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"订阅主播live_id:{live_id} 发生了错误 {type(e)}:{e}")
|
||||||
|
return "添加订阅失败..."
|
||||||
|
|
||||||
|
|
||||||
|
async def add_up_sub(uid: int, sub_user: str) -> str:
|
||||||
|
"""
|
||||||
|
添加订阅 UP
|
||||||
|
:param uid: UP uid
|
||||||
|
:param sub_user: 订阅用户
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with db.transaction():
|
||||||
|
try:
|
||||||
|
u = user.User(uid)
|
||||||
|
user_info = await u.get_user_info()
|
||||||
|
except ResponseCodeException:
|
||||||
|
return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
|
||||||
|
uname = user_info["name"]
|
||||||
|
dynamic_info = await u.get_dynamics(0)
|
||||||
|
dynamic_upload_time = 0
|
||||||
|
if dynamic_info.get("cards"):
|
||||||
|
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||||
|
video_info = await u.get_videos()
|
||||||
|
latest_video_created = 0
|
||||||
|
if video_info["list"].get("vlist"):
|
||||||
|
latest_video_created = video_info["list"]["vlist"][0]["created"]
|
||||||
|
if await BilibiliSub.add_bilibili_sub(
|
||||||
|
uid,
|
||||||
|
"up",
|
||||||
|
sub_user,
|
||||||
|
uid=uid,
|
||||||
|
uname=uname,
|
||||||
|
dynamic_upload_time=dynamic_upload_time,
|
||||||
|
latest_video_created=latest_video_created,
|
||||||
|
):
|
||||||
|
return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
|
||||||
|
else:
|
||||||
|
return "添加订阅失败..."
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"订阅Up uid:{uid} 发生了错误 {type(e)}:{e}")
|
||||||
|
return "添加订阅失败..."
|
||||||
|
|
||||||
|
|
||||||
|
async def add_season_sub(media_id: int, sub_user: str) -> str:
|
||||||
|
"""
|
||||||
|
添加订阅 UP
|
||||||
|
:param media_id: 番剧 media_id
|
||||||
|
:param sub_user: 订阅用户
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with db.transaction():
|
||||||
|
try:
|
||||||
|
season_info = await bangumi.get_meta(media_id)
|
||||||
|
except ResponseCodeException:
|
||||||
|
return f"未找到media_id:{media_id} 的信息,请检查Id是否正确"
|
||||||
|
season_id = season_info["media"]["season_id"]
|
||||||
|
season_current_episode = season_info["media"]["new_ep"]["index"]
|
||||||
|
season_name = season_info["media"]["title"]
|
||||||
|
if await BilibiliSub.add_bilibili_sub(
|
||||||
|
media_id,
|
||||||
|
"season",
|
||||||
|
sub_user,
|
||||||
|
season_name=season_name,
|
||||||
|
season_id=season_id,
|
||||||
|
season_current_episode=season_current_episode,
|
||||||
|
):
|
||||||
|
return (
|
||||||
|
"已成功订阅番剧:\n"
|
||||||
|
f"\ttitle: {season_name}\n"
|
||||||
|
f"\tcurrent_episode: {season_current_episode}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return "添加订阅失败..."
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"订阅番剧 media_id:{media_id} 发生了错误 {type(e)}:{e}")
|
||||||
|
return "添加订阅失败..."
|
||||||
|
|
||||||
|
|
||||||
|
async def delete_sub(sub_id: str, sub_user: str) -> str:
|
||||||
|
"""
|
||||||
|
删除订阅
|
||||||
|
:param sub_id: 订阅 id
|
||||||
|
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
|
||||||
|
"""
|
||||||
|
if await BilibiliSub.delete_bilibili_sub(sub_id, sub_user):
|
||||||
|
return f"已成功取消订阅:{sub_id}"
|
||||||
|
else:
|
||||||
|
return f"取消订阅:{sub_id} 失败,请检查是否订阅过该Id...."
|
||||||
|
|
||||||
|
|
||||||
|
async def get_media_id(keyword: str) -> dict:
|
||||||
|
"""
|
||||||
|
获取番剧的 media_id
|
||||||
|
:param keyword: 番剧名称
|
||||||
|
"""
|
||||||
|
params = {"keyword": keyword}
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
_season_data = {}
|
||||||
|
async with session.get(
|
||||||
|
bilibili_search_url, timeout=5, params=params
|
||||||
|
) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
data = await response.json()
|
||||||
|
if data.get("data"):
|
||||||
|
for item in data["data"]["result"]:
|
||||||
|
if item["result_type"] == "media_bangumi":
|
||||||
|
idx = 0
|
||||||
|
for x in item["data"]:
|
||||||
|
_season_data[idx] = {
|
||||||
|
"media_id": x["media_id"],
|
||||||
|
"title": x["title"]
|
||||||
|
.replace('<em class="keyword">', "")
|
||||||
|
.replace("</em>", ""),
|
||||||
|
}
|
||||||
|
idx += 1
|
||||||
|
return _season_data
|
||||||
|
except TimeoutError:
|
||||||
|
pass
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取订阅状态
|
||||||
|
:param id_: 订阅 id
|
||||||
|
:param sub_type: 订阅类型
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if sub_type == "live":
|
||||||
|
return await _get_live_status(id_)
|
||||||
|
elif sub_type == "up":
|
||||||
|
return await _get_up_status(id_)
|
||||||
|
elif sub_type == "season":
|
||||||
|
return await _get_season_status(id_)
|
||||||
|
except ResponseCodeException:
|
||||||
|
return "获取信息失败...请检查订阅Id是否存在或稍后再试..."
|
||||||
|
# except Exception as e:
|
||||||
|
# logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
|
||||||
|
# return "发生了预料之外的错误..请稍后再试或联系管理员....."
|
||||||
|
|
||||||
|
|
||||||
|
async def _get_live_status(id_: int) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取直播订阅状态
|
||||||
|
:param id_: 直播间 id
|
||||||
|
"""
|
||||||
|
live = LiveRoom(id_)
|
||||||
|
live_info = (await live.get_room_info())["room_info"]
|
||||||
|
title = live_info["title"]
|
||||||
|
room_id = live_info["room_id"]
|
||||||
|
live_status = live_info["live_status"]
|
||||||
|
cover = live_info["cover"]
|
||||||
|
sub = await BilibiliSub.get_sub(id_)
|
||||||
|
if sub.live_status != live_status:
|
||||||
|
await BilibiliSub.update_sub_info(id_, live_status=live_status)
|
||||||
|
if sub.live_status == 0 and live_status == 1:
|
||||||
|
return (
|
||||||
|
f"{image(cover)}\n"
|
||||||
|
f"{sub.uname} 开播啦!\n"
|
||||||
|
f"标题:{title}\n"
|
||||||
|
f"直链:https://live.bilibili.com/{room_id}"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def _get_up_status(id_: int) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取用户投稿状态
|
||||||
|
:param id_: 用户 id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
_user = await BilibiliSub.get_sub(id_)
|
||||||
|
u = user.User(_user.uid)
|
||||||
|
user_info = await u.get_user_info()
|
||||||
|
uname = user_info["name"]
|
||||||
|
video_info = await u.get_videos()
|
||||||
|
latest_video_created = 0
|
||||||
|
video = None
|
||||||
|
if _user.uname != uname:
|
||||||
|
await BilibiliSub.update_sub_info(id_, uname=uname)
|
||||||
|
dynamic_img, dynamic_upload_time = await get_user_dynamic(u, _user)
|
||||||
|
if video_info["list"].get("vlist"):
|
||||||
|
video = video_info["list"]["vlist"][0]
|
||||||
|
latest_video_created = video["created"]
|
||||||
|
rst = ""
|
||||||
|
if dynamic_img:
|
||||||
|
await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time)
|
||||||
|
rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n"
|
||||||
|
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
|
||||||
|
)
|
||||||
|
rst += (
|
||||||
|
f'{image(video["pic"])}\n'
|
||||||
|
f"{uname} 投稿了新视频啦\n"
|
||||||
|
f'标题:{video["title"]}\n'
|
||||||
|
f'Bvid:{video["bvid"]}\n'
|
||||||
|
f'直链:https://www.bilibili.com/video/{video["bvid"]}'
|
||||||
|
)
|
||||||
|
rst = None if rst == "-------------\n" else rst
|
||||||
|
return rst
|
||||||
|
|
||||||
|
|
||||||
|
async def _get_season_status(id_) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取 番剧 更新状态
|
||||||
|
:param id_: 番剧 id
|
||||||
|
"""
|
||||||
|
season_info = await bangumi.get_meta(id_)
|
||||||
|
title = season_info["media"]["title"]
|
||||||
|
_idx = (await BilibiliSub.get_sub(id_)).season_current_episode
|
||||||
|
new_ep = season_info["media"]["new_ep"]["index"]
|
||||||
|
if new_ep != _idx:
|
||||||
|
await BilibiliSub.update_sub_info(
|
||||||
|
id_, season_current_episode=new_ep, season_update_time=datetime.now()
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f'{image(season_info["media"]["cover"])}\n'
|
||||||
|
f"[{title}]更新啦\n"
|
||||||
|
f"最新集数:{new_ep}"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def get_user_dynamic(
|
||||||
|
u: User, local_user: BilibiliSub
|
||||||
|
) -> "Optional[MessageSegment], int":
|
||||||
|
"""
|
||||||
|
获取用户动态
|
||||||
|
:param u: 用户类
|
||||||
|
:param local_user: 数据库存储的用户数据
|
||||||
|
:return: 最新动态截图与时间
|
||||||
|
"""
|
||||||
|
dynamic_info = await u.get_dynamics(0)
|
||||||
|
browser = await get_browser()
|
||||||
|
if dynamic_info.get("cards") and browser:
|
||||||
|
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||||
|
if local_user.dynamic_upload_time != dynamic_upload_time:
|
||||||
|
page = await browser.new_page()
|
||||||
|
await page.goto(
|
||||||
|
f"https://space.bilibili.com/{local_user.uid}/dynamic",
|
||||||
|
wait_until="networkidle",
|
||||||
|
timeout=10000,
|
||||||
|
)
|
||||||
|
await page.set_viewport_size({"width": 2560, "height": 1080})
|
||||||
|
# 删除置顶
|
||||||
|
await page.evaluate(
|
||||||
|
"""
|
||||||
|
xs = document.getElementsByClassName('first-card-with-title');
|
||||||
|
for (x of xs) {
|
||||||
|
x.remove();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
card = await page.query_selector(".card")
|
||||||
|
# 截图并保存
|
||||||
|
await card.screenshot(
|
||||||
|
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||||
|
timeout=100000,
|
||||||
|
)
|
||||||
|
await page.close()
|
||||||
|
return (
|
||||||
|
image(
|
||||||
|
f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||||
|
"bilibili_sub/dynamic",
|
||||||
|
),
|
||||||
|
dynamic_upload_time,
|
||||||
|
)
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
|
class SubManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.live_data = []
|
||||||
|
self.up_data = []
|
||||||
|
self.season_data = []
|
||||||
|
self.current_index = -1
|
||||||
|
|
||||||
|
async def reload_sub_data(self):
|
||||||
|
"""
|
||||||
|
重载数据
|
||||||
|
"""
|
||||||
|
if not self.live_data or not self.up_data or not self.season_data:
|
||||||
|
(
|
||||||
|
_live_data,
|
||||||
|
_up_data,
|
||||||
|
_season_data,
|
||||||
|
) = await BilibiliSub.get_all_sub_data()
|
||||||
|
if not self.live_data:
|
||||||
|
self.live_data = _live_data
|
||||||
|
if not self.up_data:
|
||||||
|
self.up_data = _up_data
|
||||||
|
if not self.season_data:
|
||||||
|
self.season_data = _season_data
|
||||||
|
|
||||||
|
async def random_sub_data(self) -> Optional[BilibiliSub]:
|
||||||
|
"""
|
||||||
|
随机获取一条数据
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
sub = None
|
||||||
|
if not self.live_data and not self.up_data and not self.season_data:
|
||||||
|
return sub
|
||||||
|
self.current_index += 1
|
||||||
|
if self.current_index == 0:
|
||||||
|
if self.live_data:
|
||||||
|
sub = random.choice(self.live_data)
|
||||||
|
self.live_data.remove(sub)
|
||||||
|
elif self.current_index == 1:
|
||||||
|
if self.up_data:
|
||||||
|
sub = random.choice(self.up_data)
|
||||||
|
self.up_data.remove(sub)
|
||||||
|
elif self.current_index == 2:
|
||||||
|
if self.season_data:
|
||||||
|
sub = random.choice(self.season_data)
|
||||||
|
self.season_data.remove(sub)
|
||||||
|
else:
|
||||||
|
self.current_index = -1
|
||||||
|
if sub:
|
||||||
|
return sub
|
||||||
|
await self.reload_sub_data()
|
||||||
|
return await self.random_sub_data()
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
from utils.image_utils import CreateImg
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from pathlib import Path
|
||||||
|
from bilibili_api import user
|
||||||
|
from io import BytesIO
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
|
|
||||||
|
BORDER_PATH = Path(IMAGE_PATH) / 'border'
|
||||||
|
BORDER_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_pic(url: str) -> bytes:
|
||||||
|
"""
|
||||||
|
获取图像
|
||||||
|
:param url: 图像链接
|
||||||
|
:return: 图像二进制
|
||||||
|
"""
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(url, timeout=2) as response:
|
||||||
|
return await response.read()
|
||||||
|
|
||||||
|
|
||||||
|
async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des: str):
|
||||||
|
"""
|
||||||
|
生成主播简介图片
|
||||||
|
:param uid: 主播 uid
|
||||||
|
:param title: 直播间标题
|
||||||
|
:param cover: 直播封面
|
||||||
|
:param tags: 直播标签
|
||||||
|
:param des: 直播简介
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
u = user.User(uid)
|
||||||
|
user_info = await u.get_user_info()
|
||||||
|
name = user_info['name']
|
||||||
|
sex = user_info['sex']
|
||||||
|
face = user_info['face']
|
||||||
|
sign = user_info['sign']
|
||||||
|
ava = CreateImg(100, 100, background=BytesIO(await get_pic(face)))
|
||||||
|
ava.circle()
|
||||||
|
cover = CreateImg(470, 265, background=BytesIO(await get_pic(cover)))
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def _create_live_des_image(title: str, cover: CreateImg, tags: str, des: str, user_name: str, sex: str, sign: str, ava: CreateImg):
|
||||||
|
"""
|
||||||
|
生成主播简介图片
|
||||||
|
:param title: 直播间标题
|
||||||
|
:param cover: 直播封面
|
||||||
|
:param tags: 直播标签
|
||||||
|
:param des: 直播简介
|
||||||
|
:param user_name: 主播名称
|
||||||
|
:param sex: 主播性别
|
||||||
|
:param sign: 主播签名
|
||||||
|
:param ava: 主播头像
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
border = BORDER_PATH / '0.png'
|
||||||
|
border_img = None
|
||||||
|
if border.exists():
|
||||||
|
border_img = CreateImg(1772, 2657, background=border)
|
||||||
|
bk = CreateImg(1772, 2657, font_size=30)
|
||||||
|
bk.paste(cover, (0, 100), center_type='by_width')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
|||||||
|
|
||||||
@bt.got("keyword", prompt="虚空磁力?查什么GKD")
|
@bt.got("keyword", prompt="虚空磁力?查什么GKD")
|
||||||
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
||||||
_ulmt.set_True(event.user_id)
|
_ulmt.set_true(event.user_id)
|
||||||
keyword = state["keyword"]
|
keyword = state["keyword"]
|
||||||
page = state["page"]
|
page = state["page"]
|
||||||
await bt.send("开始搜索....", at_sender=True)
|
await bt.send("开始搜索....", at_sender=True)
|
||||||
@@ -72,16 +72,16 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
|||||||
)
|
)
|
||||||
send_flag = True
|
send_flag = True
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
await bt.finish(f"搜索 {keyword} 超时...")
|
await bt.finish(f"搜索 {keyword} 超时...")
|
||||||
except ServerDisconnectedError:
|
except ServerDisconnectedError:
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
await bt.finish(f"搜索 {keyword} 连接失败")
|
await bt.finish(f"搜索 {keyword} 连接失败")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
await bt.finish(f"bt 其他未知错误..")
|
await bt.finish(f"bt 其他未知错误..")
|
||||||
logger.error(f"bt 错误 e:{e}")
|
logger.error(f"bt 错误 e:{e}")
|
||||||
if not send_flag:
|
if not send_flag:
|
||||||
await bt.send(f"{keyword} 未搜索到...")
|
await bt.send(f"{keyword} 未搜索到...")
|
||||||
logger.info(f"USER {event.user_id} BT搜索 {keyword} 第 {page} 页")
|
logger.info(f"USER {event.user_id} BT搜索 {keyword} 第 {page} 页")
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
|
|||||||
@@ -20,7 +20,13 @@ restart = on_command('重启', aliases={'restart'}, permission=SUPERUSER, rule=t
|
|||||||
@update_zhenxun.handle()
|
@update_zhenxun.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
try:
|
try:
|
||||||
code = await check_update(bot)
|
code, error = await check_update(bot)
|
||||||
|
if error:
|
||||||
|
logger.error(f'更新真寻未知错误 {error}')
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=f'更新真寻未知错误 {error}'
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'更新真寻未知错误 {type(e)}:{e}')
|
logger.error(f'更新真寻未知错误 {type(e)}:{e}')
|
||||||
await bot.send_private_msg(
|
await bot.send_private_msg(
|
||||||
@@ -44,7 +50,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
@restart.got('flag', prompt='确定是否重启真寻?(重启失败咱们将失去联系,请谨慎!)')
|
@restart.got('flag', prompt='确定是否重启真寻?(重启失败咱们将失去联系,请谨慎!)')
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
flag = state['flag']
|
flag = state['flag']
|
||||||
if flag.lower() in ['true', '是', '好']:
|
if flag.lower() in ['true', '是', '好', '确定', '确定是']:
|
||||||
await restart.send('开始重启真寻..请稍等...')
|
await restart.send('开始重启真寻..请稍等...')
|
||||||
open('is_restart', 'w')
|
open('is_restart', 'w')
|
||||||
os.system('./restart.sh')
|
os.system('./restart.sh')
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from aiohttp.client_exceptions import ClientConnectorError
|
from aiohttp.client_exceptions import ClientConnectorError
|
||||||
from nonebot.adapters.cqhttp import Bot
|
from nonebot.adapters.cqhttp import Bot, Message
|
||||||
from utils.user_agent import get_user_agent
|
from utils.user_agent import get_user_agent
|
||||||
from utils.utils import get_local_proxy
|
from utils.utils import get_local_proxy
|
||||||
from utils.image_utils import CreateImg
|
from utils.image_utils import CreateImg
|
||||||
from configs.path_config import IMAGE_PATH
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from utils.message_builder import image
|
||||||
from typing import List
|
from typing import List
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -58,7 +59,7 @@ async def remind(bot: Bot):
|
|||||||
is_restart_file.unlink()
|
is_restart_file.unlink()
|
||||||
|
|
||||||
|
|
||||||
async def check_update(bot: Bot) -> int:
|
async def check_update(bot: Bot) -> 'int, str':
|
||||||
logger.info("开始检查更新真寻酱....")
|
logger.info("开始检查更新真寻酱....")
|
||||||
_version = "v0.0.0"
|
_version = "v0.0.0"
|
||||||
if _version_file.exists():
|
if _version_file.exists():
|
||||||
@@ -78,28 +79,32 @@ async def check_update(bot: Bot) -> int:
|
|||||||
logger.info(f"开始下载真寻最新版文件....")
|
logger.info(f"开始下载真寻最新版文件....")
|
||||||
if await download_latest_file(tar_gz_url):
|
if await download_latest_file(tar_gz_url):
|
||||||
logger.info("下载真寻最新版文件完成....")
|
logger.info("下载真寻最新版文件完成....")
|
||||||
await asyncio.get_event_loop().run_in_executor(
|
error = await asyncio.get_event_loop().run_in_executor(
|
||||||
None, _file_handle, latest_version
|
None, _file_handle, latest_version
|
||||||
)
|
)
|
||||||
|
if error:
|
||||||
|
return 998, error
|
||||||
logger.info("真寻更新完毕,清理文件完成....")
|
logger.info("真寻更新完毕,清理文件完成....")
|
||||||
logger.info("开始获取真寻更新日志.....")
|
logger.info("开始获取真寻更新日志.....")
|
||||||
update_info = data["body"]
|
update_info = data["body"]
|
||||||
await bot.send_private_msg(
|
|
||||||
user_id=int(list(bot.config.superusers)[0]),
|
|
||||||
message=f"真寻更新完成,版本:{_version} -> {latest_version}\n"
|
|
||||||
f"更新日期:{data['created_at']}\n"
|
|
||||||
f"更新日志:\n"
|
|
||||||
f"{update_info}",
|
|
||||||
)
|
|
||||||
width = 0
|
width = 0
|
||||||
height = len(update_info.split('\n')) * 24
|
height = len(update_info.split('\n')) * 24
|
||||||
|
A = CreateImg(width, height, font_size=20)
|
||||||
for m in update_info.split('\n'):
|
for m in update_info.split('\n'):
|
||||||
if len(m) * 20 > width:
|
w, h = A.getsize(m)
|
||||||
width = len(m) * 17
|
if w > width:
|
||||||
A = CreateImg(800, height, font_size=20)
|
width = w
|
||||||
|
A = CreateImg(width + 50, height, font_size=20)
|
||||||
A.text((10, 10), update_info)
|
A.text((10, 10), update_info)
|
||||||
A.save(f'{IMAGE_PATH}/update_info.png')
|
A.save(f'{IMAGE_PATH}/update_info.png')
|
||||||
return 200
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=Message(f"真寻更新完成,版本:{_version} -> {latest_version}\n"
|
||||||
|
f"更新日期:{data['created_at']}\n"
|
||||||
|
f"更新日志:\n"
|
||||||
|
f"{image('update_info.png')}"),
|
||||||
|
)
|
||||||
|
return 200, ''
|
||||||
else:
|
else:
|
||||||
logger.warning(f"下载真寻最新版本失败...版本号:{latest_version}")
|
logger.warning(f"下载真寻最新版本失败...版本号:{latest_version}")
|
||||||
await bot.send_private_msg(
|
await bot.send_private_msg(
|
||||||
@@ -112,62 +117,68 @@ async def check_update(bot: Bot) -> int:
|
|||||||
user_id=int(list(bot.config.superusers)[0]),
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
message=f"自动获取真寻版本成功:{latest_version},当前版本为最新版,无需更新...",
|
message=f"自动获取真寻版本成功:{latest_version},当前版本为最新版,无需更新...",
|
||||||
)
|
)
|
||||||
|
return 200, ''
|
||||||
else:
|
else:
|
||||||
logger.warning("自动获取真寻版本失败....")
|
logger.warning("自动获取真寻版本失败....")
|
||||||
await bot.send_private_msg(
|
await bot.send_private_msg(
|
||||||
user_id=int(list(bot.config.superusers)[0]), message=f"自动获取真寻版本失败...."
|
user_id=int(list(bot.config.superusers)[0]), message=f"自动获取真寻版本失败...."
|
||||||
)
|
)
|
||||||
return 999
|
return 999, ''
|
||||||
|
|
||||||
|
|
||||||
def _file_handle(latest_version: str):
|
def _file_handle(latest_version: str) -> str:
|
||||||
if not temp_dir.exists():
|
if not temp_dir.exists():
|
||||||
temp_dir.mkdir(exist_ok=True, parents=True)
|
temp_dir.mkdir(exist_ok=True, parents=True)
|
||||||
if backup_dir.exists():
|
if backup_dir.exists():
|
||||||
shutil.rmtree(backup_dir)
|
shutil.rmtree(backup_dir)
|
||||||
backup_dir.mkdir(exist_ok=True, parents=True)
|
tf = None
|
||||||
logger.info("开始解压真寻文件压缩包....")
|
error = ''
|
||||||
tf = tarfile.open(zhenxun_latest_tar_gz)
|
try:
|
||||||
tf.extractall(temp_dir)
|
backup_dir.mkdir(exist_ok=True, parents=True)
|
||||||
logger.info("解压真寻文件压缩包完成....")
|
logger.info("开始解压真寻文件压缩包....")
|
||||||
zhenxun_latest_file = Path(temp_dir) / f"zhenxun_bot-{latest_version[1:]}"
|
tf = tarfile.open(zhenxun_latest_tar_gz)
|
||||||
update_info_file = Path(zhenxun_latest_file) / "update_info.json"
|
tf.extractall(temp_dir)
|
||||||
update_info = json.load(open(update_info_file, "r", encoding="utf8"))
|
logger.info("解压真寻文件压缩包完成....")
|
||||||
update_file = update_info["update_file"]
|
zhenxun_latest_file = Path(temp_dir) / os.listdir(temp_dir)[0]
|
||||||
add_file = update_info["add_file"]
|
update_info_file = Path(zhenxun_latest_file) / "update_info.json"
|
||||||
delete_file = update_info["delete_file"]
|
update_info = json.load(open(update_info_file, "r", encoding="utf8"))
|
||||||
config_file = Path() / "configs" / "config.py"
|
update_file = update_info["update_file"]
|
||||||
config_path_file = Path() / "configs" / "config_path.py"
|
add_file = update_info["add_file"]
|
||||||
for file in delete_file + update_file:
|
delete_file = update_info["delete_file"]
|
||||||
file = Path() / file
|
config_file = Path() / "configs" / "config.py"
|
||||||
backup_file = Path(backup_dir) / file
|
config_path_file = Path() / "configs" / "config_path.py"
|
||||||
if file.exists():
|
for file in delete_file + update_file:
|
||||||
backup_file.parent.mkdir(parents=True, exist_ok=True)
|
file = Path() / file
|
||||||
if backup_file.exists():
|
backup_file = Path(backup_dir) / file
|
||||||
backup_file.unlink()
|
if file.exists():
|
||||||
if file not in [config_file, config_path_file]:
|
backup_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
os.rename(file.absolute(), backup_file.absolute())
|
if backup_file.exists():
|
||||||
|
backup_file.unlink()
|
||||||
|
if file not in [config_file, config_path_file]:
|
||||||
|
os.rename(file.absolute(), backup_file.absolute())
|
||||||
|
else:
|
||||||
|
with open(file, "r", encoding="utf8") as rf:
|
||||||
|
data = rf.read()
|
||||||
|
with open(backup_file, "w", encoding="utf8") as wf:
|
||||||
|
wf.write(data)
|
||||||
|
logger.info(f"已备份文件:{file}")
|
||||||
|
for file in add_file + update_file:
|
||||||
|
new_file = Path(zhenxun_latest_file) / file
|
||||||
|
old_file = Path() / file
|
||||||
|
if old_file not in [config_file, config_path_file]:
|
||||||
|
if not old_file.exists() and new_file.exists():
|
||||||
|
os.rename(new_file.absolute(), old_file.absolute())
|
||||||
|
logger.info(f"已更新文件:{file}")
|
||||||
else:
|
else:
|
||||||
with open(file, "r", encoding="utf8") as rf:
|
tmp = ""
|
||||||
data = rf.read()
|
new_lines = open(new_file, "r", encoding="utf8").readlines()
|
||||||
with open(backup_file, "w", encoding="utf8") as wf:
|
old_lines = open(old_file, "r", encoding="utf8").readlines()
|
||||||
wf.write(data)
|
for nl in new_lines:
|
||||||
logger.info(f"已备份文件:{file}")
|
tmp += check_old_lines(old_lines, nl)
|
||||||
for file in add_file + update_file:
|
with open(file, "w", encoding="utf8") as f:
|
||||||
new_file = Path(zhenxun_latest_file) / file
|
f.write(tmp)
|
||||||
old_file = Path() / file
|
except Exception as e:
|
||||||
if old_file not in [config_file, config_path_file]:
|
error = f'{type(e)}:{e}'
|
||||||
if not old_file.exists() and new_file.exists():
|
|
||||||
os.rename(new_file.absolute(), old_file.absolute())
|
|
||||||
logger.info(f"已更新文件:{file}")
|
|
||||||
else:
|
|
||||||
tmp = ""
|
|
||||||
new_lines = open(new_file, "r", encoding="utf8").readlines()
|
|
||||||
old_lines = open(old_file, "r", encoding="utf8").readlines()
|
|
||||||
for nl in new_lines:
|
|
||||||
tmp += check_old_lines(old_lines, nl)
|
|
||||||
with open(file, "w", encoding="utf8") as f:
|
|
||||||
f.write(tmp)
|
|
||||||
if tf:
|
if tf:
|
||||||
tf.close()
|
tf.close()
|
||||||
if temp_dir.exists():
|
if temp_dir.exists():
|
||||||
@@ -179,6 +190,7 @@ def _file_handle(latest_version: str):
|
|||||||
local_update_info_file.unlink()
|
local_update_info_file.unlink()
|
||||||
with open(_version_file, "w", encoding="utf8") as f:
|
with open(_version_file, "w", encoding="utf8") as f:
|
||||||
f.write(f"__version__: {latest_version}")
|
f.write(f"__version__: {latest_version}")
|
||||||
|
return error
|
||||||
|
|
||||||
|
|
||||||
# 获取最新版本号
|
# 获取最新版本号
|
||||||
|
|||||||
@@ -2,8 +2,12 @@ from nonebot import on_command
|
|||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
|
from asyncio.exceptions import TimeoutError
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
import requests
|
from configs.path_config import IMAGE_PATH
|
||||||
|
import aiohttp
|
||||||
|
import aiofiles
|
||||||
|
import re
|
||||||
|
|
||||||
__plugin_name__ = "coser"
|
__plugin_name__ = "coser"
|
||||||
|
|
||||||
@@ -15,13 +19,33 @@ coser = on_command(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
url_2 = "http://api.rosysun.cn/cos"
|
url = "http://api520.ltd/api/cosplay.php"
|
||||||
|
|
||||||
|
|
||||||
@coser.handle()
|
@coser.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
img_url = requests.get(url_2).text
|
async with aiohttp.ClientSession() as session:
|
||||||
await coser.send(image(img_url))
|
try:
|
||||||
logger.info(
|
for _ in range(3):
|
||||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 发送COSER"
|
try:
|
||||||
)
|
async with session.get(url, timeout=2) as response:
|
||||||
|
_url = await response.text()
|
||||||
|
async with session.get(_url, timeout=5, verify_ssl=False) as res:
|
||||||
|
if res.status == 200:
|
||||||
|
async with aiofiles.open(f'{IMAGE_PATH}/temp/{event.user_id}_coser.jpg', 'wb') as f:
|
||||||
|
await f.write(await res.read())
|
||||||
|
logger.info(
|
||||||
|
f"(USER {event.user_id}, "
|
||||||
|
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
|
f" 发送COSER"
|
||||||
|
)
|
||||||
|
await coser.send(image(f'{event.user_id}_coser.jpg', 'temp'))
|
||||||
|
break
|
||||||
|
except TimeoutError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
await coser.send('你cos给我看!')
|
||||||
|
except Exception as e:
|
||||||
|
await coser.send('发生了预料之外的错误..请稍后再试或联系管理员修复...')
|
||||||
|
logger.error(f'coser 发送了未知错误 {type(e)}:{e}')
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from services.db_context import db
|
||||||
|
from asyncpg.exceptions import DuplicateColumnError
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def _init_database():
|
||||||
|
file = Path() / 'plugins' / 'database_scripts.py'
|
||||||
|
if file.exists():
|
||||||
|
update_sql = [
|
||||||
|
'ALTER TABLE russian_users ADD winning_streak Integer default 0;',
|
||||||
|
'ALTER TABLE russian_users ADD losing_streak Integer default 0;',
|
||||||
|
'ALTER TABLE russian_users ADD max_winning_streak Integer default 0;',
|
||||||
|
'ALTER TABLE russian_users ADD max_losing_streak Integer default 0;',
|
||||||
|
'ALTER TABLE group_info_users ADD uid Integer default 0;'
|
||||||
|
]
|
||||||
|
for sql in update_sql:
|
||||||
|
try:
|
||||||
|
query = db.text(sql)
|
||||||
|
await db.first(query)
|
||||||
|
except DuplicateColumnError:
|
||||||
|
pass
|
||||||
|
file.unlink()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from .config import DRAW_PATH
|
from .config import DRAW_PATH
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from asyncio.exceptions import TimeoutError
|
from asyncio.exceptions import TimeoutError
|
||||||
@@ -177,6 +177,11 @@ class GenshinAnnouncement:
|
|||||||
data[itype]['time'] = trs[1].find('td').text
|
data[itype]['time'] = trs[1].find('td').text
|
||||||
if data[itype]['time'][-1] == '\n':
|
if data[itype]['time'][-1] == '\n':
|
||||||
data[itype]['time'] = data[itype]['time'][:-1]
|
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[itype]['time'] = start_time.strftime('%Y/%m/%d') + ' ~ ' + end_time.strftime('%Y/%m/%d')
|
||||||
tmp = ''
|
tmp = ''
|
||||||
for tm in data[itype]['time'].split('~'):
|
for tm in data[itype]['time'].split('~'):
|
||||||
date_time_sp = tm.split('/')
|
date_time_sp = tm.split('/')
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from nonebot.typing import T_State
|
|||||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import aiofiles
|
import aiofiles
|
||||||
from collections import defaultdict
|
|
||||||
from asyncio.exceptions import TimeoutError
|
from asyncio.exceptions import TimeoutError
|
||||||
from configs.config import FUDU_PROBABILITY
|
from configs.config import FUDU_PROBABILITY
|
||||||
|
|
||||||
@@ -20,39 +19,39 @@ class Fudu:
|
|||||||
|
|
||||||
def append(self, key, content):
|
def append(self, key, content):
|
||||||
self._create(key)
|
self._create(key)
|
||||||
self.data[key]['data'].append(content)
|
self.data[key]["data"].append(content)
|
||||||
|
|
||||||
def clear(self, key):
|
def clear(self, key):
|
||||||
self._create(key)
|
self._create(key)
|
||||||
self.data[key]['data'] = []
|
self.data[key]["data"] = []
|
||||||
self.data[key]['is_repeater'] = False
|
self.data[key]["is_repeater"] = False
|
||||||
|
|
||||||
def size(self, key) -> int:
|
def size(self, key) -> int:
|
||||||
self._create(key)
|
self._create(key)
|
||||||
return len(self.data[key]['data'])
|
return len(self.data[key]["data"])
|
||||||
|
|
||||||
def check(self, key, content) -> bool:
|
def check(self, key, content) -> bool:
|
||||||
self._create(key)
|
self._create(key)
|
||||||
return self.data[key]['data'][0] == content
|
return self.data[key]["data"][0] == content
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
self._create(key)
|
self._create(key)
|
||||||
return self.data[key]['data'][0]
|
return self.data[key]["data"][0]
|
||||||
|
|
||||||
def is_repeater(self, key):
|
def is_repeater(self, key):
|
||||||
self._create(key)
|
self._create(key)
|
||||||
return self.data[key]['is_repeater']
|
return self.data[key]["is_repeater"]
|
||||||
|
|
||||||
def set_repeater(self, key):
|
def set_repeater(self, key):
|
||||||
self._create(key)
|
self._create(key)
|
||||||
self.data[key]['is_repeater'] = True
|
self.data[key]["is_repeater"] = True
|
||||||
|
|
||||||
def _create(self, key):
|
def _create(self, key):
|
||||||
if self.data.get(key) is None:
|
if self.data.get(key) is None:
|
||||||
self.data[key] = {'is_repeater': False, 'data': []}
|
self.data[key] = {"is_repeater": False, "data": []}
|
||||||
|
|
||||||
|
|
||||||
_fudulist = Fudu()
|
_fudu_list = Fudu()
|
||||||
|
|
||||||
|
|
||||||
fudu = on_message(permission=GROUP, priority=9)
|
fudu = on_message(permission=GROUP, priority=9)
|
||||||
@@ -74,17 +73,20 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
else:
|
else:
|
||||||
img_hash = ""
|
img_hash = ""
|
||||||
add_msg = msg + "|-|" + img_hash
|
add_msg = msg + "|-|" + img_hash
|
||||||
if _fudulist.size(event.group_id) == 0:
|
if _fudu_list.size(event.group_id) == 0:
|
||||||
_fudulist.append(event.group_id, add_msg)
|
_fudu_list.append(event.group_id, add_msg)
|
||||||
elif _fudulist.check(event.group_id, add_msg):
|
elif _fudu_list.check(event.group_id, add_msg):
|
||||||
_fudulist.append(event.group_id, add_msg)
|
_fudu_list.append(event.group_id, add_msg)
|
||||||
else:
|
else:
|
||||||
_fudulist.clear(event.group_id)
|
_fudu_list.clear(event.group_id)
|
||||||
_fudulist.append(event.group_id, add_msg)
|
_fudu_list.append(event.group_id, add_msg)
|
||||||
if _fudulist.size(event.group_id) > 2:
|
if _fudu_list.size(event.group_id) > 2:
|
||||||
if random.random() < FUDU_PROBABILITY and not _fudulist.is_repeater(event.group_id):
|
if random.random() < FUDU_PROBABILITY and not _fudu_list.is_repeater(
|
||||||
|
event.group_id
|
||||||
|
):
|
||||||
if random.random() < 0.2:
|
if random.random() < 0.2:
|
||||||
await fudu.finish("打断施法!")
|
await fudu.finish("打断施法!")
|
||||||
|
_fudu_list.set_repeater(event.group_id)
|
||||||
if imgs and msg:
|
if imgs and msg:
|
||||||
rst = msg + image(f"compare_{event.group_id}_img.jpg", "temp")
|
rst = msg + image(f"compare_{event.group_id}_img.jpg", "temp")
|
||||||
elif imgs:
|
elif imgs:
|
||||||
@@ -95,7 +97,6 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
rst = ""
|
rst = ""
|
||||||
if rst:
|
if rst:
|
||||||
await fudu.send(rst)
|
await fudu.send(rst)
|
||||||
_fudulist.set_repeater(event.group_id)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_fudu_img_hash(url, group_id):
|
async def get_fudu_img_hash(url, group_id):
|
||||||
@@ -109,4 +110,4 @@ async def get_fudu_img_hash(url, group_id):
|
|||||||
img_hash = get_img_hash(IMAGE_PATH + f"temp/compare_{group_id}_img.jpg")
|
img_hash = get_img_hash(IMAGE_PATH + f"temp/compare_{group_id}_img.jpg")
|
||||||
return str(img_hash)
|
return str(img_hash)
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
return ''
|
return ""
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from utils.utils import get_message_text, scheduler
|
|||||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
|
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
|
from configs.config import NICKNAME
|
||||||
from nonebot.permission import SUPERUSER
|
from nonebot.permission import SUPERUSER
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -58,21 +59,20 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
|
|
||||||
@qr_lst.handle()
|
@qr_lst.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
mes_list = []
|
|
||||||
txt = get_resource_type_list()
|
txt = get_resource_type_list()
|
||||||
txt_list = txt.split("\n")
|
txt_list = txt.split("\n")
|
||||||
if event.message_type == "group":
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
mes_list = []
|
||||||
for txt in txt_list:
|
for txt in txt_list:
|
||||||
data = {
|
data = {
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"data": {
|
"data": {
|
||||||
"name": f"这里是{list(bot.config.nickname)[0]}酱",
|
"name": f"这里是{NICKNAME}酱",
|
||||||
"uin": f"{bot.self_id}",
|
"uin": f"{bot.self_id}",
|
||||||
"content": txt,
|
"content": txt,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
mes_list.append(data)
|
mes_list.append(data)
|
||||||
if isinstance(event, GroupMessageEvent):
|
|
||||||
await bot.send_group_forward_msg(group_id=event.group_id, messages=mes_list)
|
await bot.send_group_forward_msg(group_id=event.group_id, messages=mes_list)
|
||||||
else:
|
else:
|
||||||
rst = ""
|
rst = ""
|
||||||
|
|||||||
@@ -164,40 +164,18 @@ async def download_map_init(
|
|||||||
if not _map.exists():
|
if not _map.exists():
|
||||||
# padding_w, padding_h = data['padding']
|
# padding_w, padding_h = data['padding']
|
||||||
data = data["slices"]
|
data = data["slices"]
|
||||||
idx = 0
|
map_url = data[0][0]['url']
|
||||||
for x in data:
|
await download_image(
|
||||||
idj = 0
|
map_url,
|
||||||
for j in x:
|
f"{map_path}/map.png",
|
||||||
await download_image(
|
session,
|
||||||
j["url"],
|
semaphore,
|
||||||
f"{map_path}/{idx}_{idj}.png",
|
force_flag=flag,
|
||||||
session,
|
|
||||||
semaphore,
|
|
||||||
force_flag=flag,
|
|
||||||
)
|
|
||||||
idj += 1
|
|
||||||
idx += 1
|
|
||||||
map_width, map_height = CreateImg(
|
|
||||||
0, 0, background=f"{map_path}/0_0.png"
|
|
||||||
).size
|
|
||||||
map_width = map_width * MAP_RATIO
|
|
||||||
map_height = map_height * MAP_RATIO
|
|
||||||
lens = len(
|
|
||||||
[x for x in os.listdir(f"{map_path}") if x.startswith("0")]
|
|
||||||
)
|
)
|
||||||
background_image = CreateImg(
|
map_file = CreateImg(
|
||||||
map_width * lens, map_height * lens, map_width, map_height
|
0, 0, background=f"{map_path}/map.png", ratio=MAP_RATIO
|
||||||
)
|
)
|
||||||
for i in range(idx):
|
map_file.save(f"{map_path}/map.png")
|
||||||
for j in range(idj):
|
|
||||||
x = CreateImg(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
background=f"{map_path}/{i}_{j}.png",
|
|
||||||
ratio=MAP_RATIO,
|
|
||||||
)
|
|
||||||
background_image.paste(x)
|
|
||||||
background_image.save(f"{map_path}/map.png")
|
|
||||||
else:
|
else:
|
||||||
logger.warning(f'获取原神地图失败 msg: {data["message"]}')
|
logger.warning(f'获取原神地图失败 msg: {data["message"]}')
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
from nonebot import on_notice, on_request
|
from nonebot import on_notice, on_request
|
||||||
from configs.path_config import IMAGE_PATH, DATA_PATH
|
from configs.path_config import IMAGE_PATH, DATA_PATH
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
import os
|
|
||||||
import random
|
|
||||||
from models.group_member_info import GroupInfoUser
|
from models.group_member_info import GroupInfoUser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
@@ -13,9 +11,12 @@ from nonebot.adapters.cqhttp import (
|
|||||||
GroupDecreaseNoticeEvent,
|
GroupDecreaseNoticeEvent,
|
||||||
)
|
)
|
||||||
from nonebot.adapters.cqhttp.exception import ActionFailed
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
from pathlib import Path
|
from configs.config import plugins2info_dict
|
||||||
|
from utils.static_data import group_manager
|
||||||
from models.group_info import GroupInfo
|
from models.group_info import GroupInfo
|
||||||
|
from pathlib import Path
|
||||||
|
import random
|
||||||
|
import os
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
@@ -37,46 +38,52 @@ add_group = on_request(priority=1, block=False)
|
|||||||
|
|
||||||
@group_increase_handle.handle()
|
@group_increase_handle.handle()
|
||||||
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
|
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
|
||||||
join_time = datetime.now()
|
if event.user_id == int(bot.self_id):
|
||||||
user_info = await bot.get_group_member_info(
|
if event.group_id not in group_manager['group_manager'].keys():
|
||||||
group_id=event.group_id, user_id=event.user_id
|
for plugin in plugins2info_dict.keys():
|
||||||
)
|
if not plugins2info_dict[plugin]['default_status']:
|
||||||
if await GroupInfoUser.add_member_info(
|
group_manager.block_plugin(plugin, str(event.group_id))
|
||||||
user_info["user_id"],
|
|
||||||
user_info["group_id"],
|
|
||||||
user_info["nickname"],
|
|
||||||
join_time,
|
|
||||||
):
|
|
||||||
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
|
|
||||||
else:
|
else:
|
||||||
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
|
join_time = datetime.now()
|
||||||
|
user_info = await bot.get_group_member_info(
|
||||||
# 群欢迎消息
|
group_id=event.group_id, user_id=event.user_id
|
||||||
if await GroupRemind.get_status(event.group_id, "hy"):
|
|
||||||
msg = ""
|
|
||||||
img = ""
|
|
||||||
at_flag = False
|
|
||||||
custom_welcome_msg_json = (
|
|
||||||
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
|
|
||||||
)
|
)
|
||||||
if custom_welcome_msg_json.exists():
|
if await GroupInfoUser.add_member_info(
|
||||||
data = json.load(open(custom_welcome_msg_json, "r"))
|
user_info["user_id"],
|
||||||
if data.get(str(event.group_id)):
|
user_info["group_id"],
|
||||||
msg = data[str(event.group_id)]
|
user_info["nickname"],
|
||||||
if msg.find("[at]") != -1:
|
join_time,
|
||||||
msg = msg.replace("[at]", "")
|
):
|
||||||
at_flag = True
|
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
|
||||||
if os.path.exists(DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"):
|
|
||||||
img = image(abspath=DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg")
|
|
||||||
if msg or img:
|
|
||||||
await group_increase_handle.send(
|
|
||||||
"\n" + msg.strip() + img, at_sender=at_flag
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
await group_increase_handle.send(
|
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
|
||||||
"新人快跑啊!!本群现状↓(快使用自定义!)"
|
|
||||||
+ image(random.choice(os.listdir(IMAGE_PATH + "qxz/")), "qxz")
|
# 群欢迎消息
|
||||||
|
if await GroupRemind.get_status(event.group_id, "hy"):
|
||||||
|
msg = ""
|
||||||
|
img = ""
|
||||||
|
at_flag = False
|
||||||
|
custom_welcome_msg_json = (
|
||||||
|
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
|
||||||
)
|
)
|
||||||
|
if custom_welcome_msg_json.exists():
|
||||||
|
data = json.load(open(custom_welcome_msg_json, "r"))
|
||||||
|
if data.get(str(event.group_id)):
|
||||||
|
msg = data[str(event.group_id)]
|
||||||
|
if msg.find("[at]") != -1:
|
||||||
|
msg = msg.replace("[at]", "")
|
||||||
|
at_flag = True
|
||||||
|
if os.path.exists(DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"):
|
||||||
|
img = image(abspath=DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg")
|
||||||
|
if msg or img:
|
||||||
|
await group_increase_handle.send(
|
||||||
|
"\n" + msg.strip() + img, at_sender=at_flag
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await group_increase_handle.send(
|
||||||
|
"新人快跑啊!!本群现状↓(快使用自定义!)"
|
||||||
|
+ image(random.choice(os.listdir(IMAGE_PATH + "qxz/")), "qxz")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@group_decrease_handle.handle()
|
@group_decrease_handle.handle()
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ manager_group_whitelist = on_command(
|
|||||||
"添加群白名单", aliases={"删除群白名单"}, priority=1, permission=SUPERUSER, block=True
|
"添加群白名单", aliases={"删除群白名单"}, priority=1, permission=SUPERUSER, block=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
show_group_whitelist = on_command('查看群白名单', priority=1, permission=SUPERUSER, block=True)
|
||||||
|
|
||||||
|
|
||||||
@add_group_level.handle()
|
@add_group_level.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
@@ -100,3 +102,13 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
|
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
|
||||||
|
|
||||||
|
|
||||||
|
@show_group_whitelist.handle()
|
||||||
|
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:
|
||||||
|
await show_group_whitelist.send("目前的群白名单:\n" + '\n'.join(x))
|
||||||
|
else:
|
||||||
|
await show_group_whitelist.send('没有任何群在群白名单...')
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ entertainment_help = {
|
|||||||
"pix_gallery": "偶尔也想看看美图? --> 指令:PIX [关键词/uid/pid:pid] [num]/查看pix图库 [关键词]/显示pix关键词",
|
"pix_gallery": "偶尔也想看看美图? --> 指令:PIX [关键词/uid/pid:pid] [num]/查看pix图库 [关键词]/显示pix关键词",
|
||||||
'nbnhhsh': "会说话就多说点! --> 指令:nbnhhsh/能不能好好说话 [文本](空格划分)",
|
'nbnhhsh': "会说话就多说点! --> 指令:nbnhhsh/能不能好好说话 [文本](空格划分)",
|
||||||
"roll": f"让{NICKNAME}来帮你决定吧! --> 指令:roll/ roll [文本](空格划分)",
|
"roll": f"让{NICKNAME}来帮你决定吧! --> 指令:roll/ roll [文本](空格划分)",
|
||||||
"wbtop": f"刚买完瓜,在吃瓜现场 --> 指令:微博热搜/微博热搜 [数字]"
|
"wbtop": f"刚买完瓜,在吃瓜现场 --> 指令:微博热搜/微博热搜 [数字]",
|
||||||
|
"bilibili_sub": f"非常快捷的订阅播报 --> 指令:添加订阅 [主播/up/番剧] [id/番名/链接] / 删除订阅 [id]/ 查看订阅"
|
||||||
}
|
}
|
||||||
# 其他
|
# 其他
|
||||||
other_help = [
|
other_help = [
|
||||||
|
|||||||
@@ -13,10 +13,6 @@ import nonebot
|
|||||||
|
|
||||||
|
|
||||||
width = 1600
|
width = 1600
|
||||||
e_height = 0
|
|
||||||
u_height = 950
|
|
||||||
o_height = 1500
|
|
||||||
# f_height =
|
|
||||||
|
|
||||||
|
|
||||||
def create_help_img():
|
def create_help_img():
|
||||||
@@ -28,9 +24,9 @@ def create_help_img():
|
|||||||
+ len(utility_help) * 24
|
+ len(utility_help) * 24
|
||||||
+ len(entertainment_help) * 24
|
+ len(entertainment_help) * 24
|
||||||
+ len(other_help) * 24
|
+ len(other_help) * 24
|
||||||
) * 2
|
) + 800
|
||||||
A = CreateImg(width, h - 200, font_size=24)
|
A = CreateImg(width, h - 200, font_size=24)
|
||||||
e = CreateImg(width, len(entertainment_help) * 42, font_size=24)
|
e = CreateImg(width, len(entertainment_help) * 26 + 100, font_size=24)
|
||||||
rst = ""
|
rst = ""
|
||||||
i = 0
|
i = 0
|
||||||
for cmd in entertainment_help:
|
for cmd in entertainment_help:
|
||||||
@@ -38,7 +34,7 @@ def create_help_img():
|
|||||||
i += 1
|
i += 1
|
||||||
e.text((10, 10), "娱乐功能:")
|
e.text((10, 10), "娱乐功能:")
|
||||||
e.text((40, 40), rst)
|
e.text((40, 40), rst)
|
||||||
u = CreateImg(width, len(utility_help) * 40 + 50, font_size=24, color="black")
|
u = CreateImg(width, len(utility_help) * 26 + 100, font_size=24, color="black")
|
||||||
rst = ""
|
rst = ""
|
||||||
i = 0
|
i = 0
|
||||||
for cmd in utility_help:
|
for cmd in utility_help:
|
||||||
@@ -46,19 +42,18 @@ def create_help_img():
|
|||||||
i += 1
|
i += 1
|
||||||
u.text((10, 10), "实用功能:", fill=(255, 255, 255))
|
u.text((10, 10), "实用功能:", fill=(255, 255, 255))
|
||||||
u.text((40, 40), rst, fill=(255, 255, 255))
|
u.text((40, 40), rst, fill=(255, 255, 255))
|
||||||
o = CreateImg(width, len(other_help) * 40, font_size=24)
|
o = CreateImg(width, len(other_help) * 26 + 100, font_size=24)
|
||||||
rst = ""
|
rst = ""
|
||||||
i = 0
|
|
||||||
for i in range(len(other_help)):
|
for i in range(len(other_help)):
|
||||||
rst += f"{i + 1}.{other_help[i]}\n"
|
rst += f"{i + 1}.{other_help[i]}\n"
|
||||||
i += 1
|
i += 1
|
||||||
o.text((10, 10), "其他功能:")
|
o.text((10, 10), "其他功能:")
|
||||||
o.text((40, 40), rst)
|
o.text((40, 40), rst)
|
||||||
A.paste(e, (0, 0))
|
A.paste(e, (0, 0))
|
||||||
A.paste(u, (0, u_height))
|
A.paste(u, (0, e.h))
|
||||||
A.paste(o, (0, o_height))
|
A.paste(o, (0, e.h + u.h))
|
||||||
A.text(
|
A.text(
|
||||||
(10, h * 0.68),
|
(10, e.h + u.h + o.h + 50),
|
||||||
f"大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对{NICKNAME}说 “{NICKNAME}帮助 指令名” 获取对应详细帮助\n"
|
f"大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对{NICKNAME}说 “{NICKNAME}帮助 指令名” 获取对应详细帮助\n"
|
||||||
"可以通过 “滴滴滴- [消息]” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>)"
|
"可以通过 “滴滴滴- [消息]” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>)"
|
||||||
"\n[群管理员请看 管理员帮助(群主与管理员自带 5 级权限)]\n\n"
|
"\n[群管理员请看 管理员帮助(群主与管理员自带 5 级权限)]\n\n"
|
||||||
@@ -75,11 +70,11 @@ def create_group_help_img(group_id: int):
|
|||||||
+ len(utility_help) * 24
|
+ len(utility_help) * 24
|
||||||
+ len(entertainment_help) * 24
|
+ len(entertainment_help) * 24
|
||||||
+ len(other_help) * 24
|
+ len(other_help) * 24
|
||||||
) * 2
|
) + 800
|
||||||
A = CreateImg(width, h - 200, font_size=24)
|
A = CreateImg(width, h, font_size=24)
|
||||||
u = CreateImg(width, len(utility_help) * 40, font_size=24, color="black")
|
u = CreateImg(width, len(utility_help) * 26 + 100, font_size=24, color="black")
|
||||||
o = CreateImg(width, len(other_help) * 40, font_size=24)
|
o = CreateImg(width, len(other_help) * 26 + 100, font_size=24)
|
||||||
e = CreateImg(width, len(entertainment_help) * 42, font_size=24)
|
e = CreateImg(width, len(entertainment_help) * 26 + 100, font_size=24)
|
||||||
rst = ""
|
rst = ""
|
||||||
i = 1
|
i = 1
|
||||||
for cmd in entertainment_help.keys():
|
for cmd in entertainment_help.keys():
|
||||||
@@ -107,17 +102,17 @@ def create_group_help_img(group_id: int):
|
|||||||
o.text((40, 40), rst)
|
o.text((40, 40), rst)
|
||||||
|
|
||||||
A.paste(e, (0, 0))
|
A.paste(e, (0, 0))
|
||||||
A.paste(u, (0, u_height))
|
A.paste(u, (0, e.h))
|
||||||
A.paste(o, (0, o_height))
|
A.paste(o, (0, e.h + u.h))
|
||||||
# A.text((width, 10), f'总开关【{"√" if data["总开关"] else "×"}】')
|
# A.text((width, 10), f'总开关【{"√" if data["总开关"] else "×"}】')
|
||||||
A.text(
|
A.text(
|
||||||
(10, h * 0.68),
|
(10, e.h + u.h + o.h + 50),
|
||||||
f"大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对{NICKNAME}说 “{NICKNAME}帮助 指令名” 获取对应详细帮助\n"
|
f"大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对{NICKNAME}说 “{NICKNAME}帮助 指令名” 获取对应详细帮助\n"
|
||||||
"可以通过 “滴滴滴- [消息]” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>)"
|
"可以通过 “滴滴滴- [消息]” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>)"
|
||||||
f"\n[群管理员请看 管理员帮助(群主与管理员自带 {ADMIN_DEFAULT_AUTH} 级权限)]",
|
f"\n[群管理员请看 管理员帮助(群主与管理员自带 {ADMIN_DEFAULT_AUTH} 级权限)]",
|
||||||
)
|
)
|
||||||
A.text(
|
A.text(
|
||||||
(10, h * 0.77),
|
(10, e.h + u.h + o.h + 250),
|
||||||
f"【注】「色图概率:好感度 + {int(INITIAL_SETU_PROBABILITY*100)}%\n"
|
f"【注】「色图概率:好感度 + {int(INITIAL_SETU_PROBABILITY*100)}%\n"
|
||||||
f"\t\t每 3 点好感度 + 1次开箱,初始 {INITIAL_OPEN_CASE_COUNT} 次\n"
|
f"\t\t每 3 点好感度 + 1次开箱,初始 {INITIAL_OPEN_CASE_COUNT} 次\n"
|
||||||
f"\t\t开启/关闭功能只需输入‘开启/关闭 指令名’(每个功能的第一个指令)」\n"
|
f"\t\t开启/关闭功能只需输入‘开启/关闭 指令名’(每个功能的第一个指令)」\n"
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
from nonebot.matcher import Matcher
|
from nonebot.matcher import Matcher
|
||||||
from nonebot.message import run_preprocessor, IgnoredException
|
from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
|
||||||
from nonebot.adapters.cqhttp.exception import ActionFailed
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
from models.group_member_info import GroupInfoUser
|
||||||
|
from models.friend_user import FriendUser
|
||||||
|
from typing import Optional
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import (
|
from nonebot.adapters.cqhttp import (
|
||||||
Bot,
|
Bot,
|
||||||
|
Event,
|
||||||
MessageEvent,
|
MessageEvent,
|
||||||
PrivateMessageEvent,
|
PrivateMessageEvent,
|
||||||
GroupMessageEvent,
|
GroupMessageEvent,
|
||||||
|
PokeNotifyEvent,
|
||||||
|
Message,
|
||||||
)
|
)
|
||||||
from configs.config import (
|
from configs.config import (
|
||||||
BAN_RESULT,
|
BAN_RESULT,
|
||||||
@@ -16,24 +22,43 @@ from configs.config import (
|
|||||||
MALICIOUS_BAN_COUNT,
|
MALICIOUS_BAN_COUNT,
|
||||||
CHECK_NOTICE_INFO_CD,
|
CHECK_NOTICE_INFO_CD,
|
||||||
plugins2info_dict,
|
plugins2info_dict,
|
||||||
|
plugins2cd_dict,
|
||||||
|
plugins2exists_dict,
|
||||||
)
|
)
|
||||||
from models.ban_user import BanUser
|
from models.ban_user import BanUser
|
||||||
from utils.utils import is_number, static_flmt, BanCheckLimiter
|
from utils.utils import (
|
||||||
|
is_number,
|
||||||
|
static_flmt,
|
||||||
|
BanCheckLimiter,
|
||||||
|
FreqLimiter,
|
||||||
|
UserExistLimiter,
|
||||||
|
)
|
||||||
|
from utils.static_data import withdraw_message_id_manager
|
||||||
from utils.message_builder import at
|
from utils.message_builder import at
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from models.level_user import LevelUser
|
from models.level_user import LevelUser
|
||||||
from utils.static_data import group_manager
|
from utils.static_data import group_manager
|
||||||
from utils.utils import FreqLimiter
|
import asyncio
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
withdraw_message_id_manager["message_id"] = []
|
||||||
|
|
||||||
|
|
||||||
# 检查是否被ban
|
# 检查是否被ban
|
||||||
@run_preprocessor
|
@run_preprocessor
|
||||||
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
await BanUser.is_super_ban(event.user_id)
|
||||||
|
and str(event.user_id) not in bot.config.superusers
|
||||||
|
):
|
||||||
|
raise IgnoredException("用户处于超级黑名单中")
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
if not isinstance(event, MessageEvent):
|
if not isinstance(event, MessageEvent):
|
||||||
return
|
return
|
||||||
if matcher.type == "message" and matcher.priority not in [1, 9]:
|
if matcher.type == "message" and matcher.priority not in [1, 9]:
|
||||||
@@ -47,9 +72,9 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
if time < 60:
|
if time < 60:
|
||||||
time = str(time) + " 秒"
|
time = str(time) + " 秒"
|
||||||
else:
|
else:
|
||||||
time = str(int(time / 60)) + " 分"
|
time = str(int(time / 60)) + " 分钟"
|
||||||
else:
|
else:
|
||||||
time = str(time) + " 分"
|
time = str(time) + " 分钟"
|
||||||
if isinstance(event, GroupMessageEvent):
|
if isinstance(event, GroupMessageEvent):
|
||||||
if not static_flmt.check(event.user_id):
|
if not static_flmt.check(event.user_id):
|
||||||
raise IgnoredException("用户处于黑名单中")
|
raise IgnoredException("用户处于黑名单中")
|
||||||
@@ -60,7 +85,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
group_id=event.group_id,
|
group_id=event.group_id,
|
||||||
message=at(event.user_id)
|
message=at(event.user_id)
|
||||||
+ BAN_RESULT
|
+ BAN_RESULT
|
||||||
+ f" 在..在 {time}后才会理你喔",
|
+ f" 在..在 {time} 后才会理你喔",
|
||||||
)
|
)
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
@@ -91,15 +116,10 @@ async def _(matcher: Matcher, bot: Bot, event: GroupMessageEvent, state: T_State
|
|||||||
return
|
return
|
||||||
if matcher.type == "message" and matcher.priority not in [1, 9]:
|
if matcher.type == "message" and matcher.priority not in [1, 9]:
|
||||||
if state["_prefix"]["raw_command"]:
|
if state["_prefix"]["raw_command"]:
|
||||||
# print(state["_prefix"]["raw_command"])
|
|
||||||
if _blmt.check(f'{event.user_id}{state["_prefix"]["raw_command"]}'):
|
if _blmt.check(f'{event.user_id}{state["_prefix"]["raw_command"]}'):
|
||||||
if await BanUser.ban(event.user_id, 9, MALICIOUS_BAN_TIME * 60):
|
if await BanUser.ban(event.user_id, 9, MALICIOUS_BAN_TIME * 60):
|
||||||
logger.info(f"USER {event.user_id} 触发了恶意触发检测")
|
logger.info(f"USER {event.user_id} 触发了恶意触发检测")
|
||||||
# await update_img.finish('检测到恶意触发命令,您将被封禁 30 分钟', at_sender=True)
|
if isinstance(event, GroupMessageEvent):
|
||||||
if event.message_type == "group":
|
|
||||||
if not static_flmt.check(event.user_id):
|
|
||||||
return
|
|
||||||
static_flmt.start_cd(event.user_id)
|
|
||||||
try:
|
try:
|
||||||
await bot.send_group_msg(
|
await bot.send_group_msg(
|
||||||
group_id=event.group_id,
|
group_id=event.group_id,
|
||||||
@@ -108,9 +128,6 @@ async def _(matcher: Matcher, bot: Bot, event: GroupMessageEvent, state: T_State
|
|||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if not static_flmt.check(event.user_id):
|
|
||||||
return
|
|
||||||
static_flmt.start_cd(event.user_id)
|
|
||||||
try:
|
try:
|
||||||
await bot.send_private_msg(
|
await bot.send_private_msg(
|
||||||
user_id=event.user_id,
|
user_id=event.user_id,
|
||||||
@@ -126,13 +143,18 @@ _flmt = FreqLimiter(CHECK_NOTICE_INFO_CD)
|
|||||||
_flmt_g = FreqLimiter(CHECK_NOTICE_INFO_CD)
|
_flmt_g = FreqLimiter(CHECK_NOTICE_INFO_CD)
|
||||||
_flmt_s = FreqLimiter(CHECK_NOTICE_INFO_CD)
|
_flmt_s = FreqLimiter(CHECK_NOTICE_INFO_CD)
|
||||||
_flmt_c = FreqLimiter(CHECK_NOTICE_INFO_CD)
|
_flmt_c = FreqLimiter(CHECK_NOTICE_INFO_CD)
|
||||||
|
_exists_msg = {}
|
||||||
|
|
||||||
|
|
||||||
|
ignore_rst_module = ["ai", "poke"]
|
||||||
|
|
||||||
|
|
||||||
# 权限检测
|
# 权限检测
|
||||||
@run_preprocessor
|
@run_preprocessor
|
||||||
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
global _exists_msg
|
||||||
if (
|
if (
|
||||||
not isinstance(event, MessageEvent)
|
(not isinstance(event, MessageEvent) and matcher.module != "poke")
|
||||||
or await BanUser.is_ban(event.user_id)
|
or await BanUser.is_ban(event.user_id)
|
||||||
or str(event.user_id) in bot.config.superusers
|
or str(event.user_id) in bot.config.superusers
|
||||||
):
|
):
|
||||||
@@ -167,55 +189,72 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
raise IgnoredException("权限不足")
|
raise IgnoredException("权限不足")
|
||||||
if module in plugins2info_dict.keys():
|
if module in plugins2info_dict.keys() and matcher.priority not in [1, 9]:
|
||||||
if isinstance(event, GroupMessageEvent):
|
# 戳一戳单独判断
|
||||||
|
if isinstance(event, GroupMessageEvent) or (
|
||||||
|
isinstance(event, PokeNotifyEvent) and event.group_id
|
||||||
|
):
|
||||||
|
if _exists_msg.get(event.group_id) is None:
|
||||||
|
_exists_msg[event.group_id] = False
|
||||||
# 群权限
|
# 群权限
|
||||||
if plugins2info_dict[module]["level"] > group_manager.get_group_level(
|
if plugins2info_dict[module]["level"] > group_manager.get_group_level(
|
||||||
str(event.group_id)
|
str(event.group_id)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
if _flmt_g.check(event.user_id):
|
if _flmt_g.check(event.user_id) and module not in ignore_rst_module:
|
||||||
_flmt_g.start_cd(event.user_id)
|
_flmt_g.start_cd(event.user_id)
|
||||||
await bot.send_group_msg(
|
await bot.send_group_msg(
|
||||||
group_id=event.group_id, message="群权限不足..."
|
group_id=event.group_id, message="群权限不足..."
|
||||||
)
|
)
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
|
_exists_msg[event.group_id] = True
|
||||||
raise IgnoredException("群权限不足")
|
raise IgnoredException("群权限不足")
|
||||||
# 插件状态
|
# 插件状态
|
||||||
if not group_manager.get_plugin_status(module, str(event.group_id)):
|
if not group_manager.get_plugin_status(module, str(event.group_id)):
|
||||||
try:
|
try:
|
||||||
if _flmt_s.check(event.group_id):
|
if module not in ignore_rst_module and _flmt_s.check(
|
||||||
|
event.group_id
|
||||||
|
):
|
||||||
_flmt_s.start_cd(event.group_id)
|
_flmt_s.start_cd(event.group_id)
|
||||||
await bot.send_group_msg(
|
await bot.send_group_msg(
|
||||||
group_id=event.group_id, message="该群未开启此功能.."
|
group_id=event.group_id, message="该群未开启此功能.."
|
||||||
)
|
)
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
|
_exists_msg[event.group_id] = True
|
||||||
raise IgnoredException("未开启此功能...")
|
raise IgnoredException("未开启此功能...")
|
||||||
# 管理员禁用
|
# 管理员禁用
|
||||||
if not group_manager.get_plugin_status(
|
if not group_manager.get_plugin_status(
|
||||||
f"{module}:super", str(event.group_id)
|
f"{module}:super", str(event.group_id)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
if _flmt_s.check(event.group_id):
|
if (
|
||||||
|
_flmt_s.check(event.group_id)
|
||||||
|
and module not in ignore_rst_module
|
||||||
|
):
|
||||||
_flmt_s.start_cd(event.group_id)
|
_flmt_s.start_cd(event.group_id)
|
||||||
await bot.send_group_msg(
|
await bot.send_group_msg(
|
||||||
group_id=event.group_id, message="管理员禁用了此群该功能..."
|
group_id=event.group_id, message="管理员禁用了此群该功能..."
|
||||||
)
|
)
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
|
_exists_msg[event.group_id] = True
|
||||||
raise IgnoredException("管理员禁用了此群该功能...")
|
raise IgnoredException("管理员禁用了此群该功能...")
|
||||||
# 群聊禁用
|
# 群聊禁用
|
||||||
if not group_manager.get_plugin_status(module, block_type="group"):
|
if not group_manager.get_plugin_status(module, block_type="group"):
|
||||||
try:
|
try:
|
||||||
if _flmt_c.check(event.group_id):
|
if (
|
||||||
|
_flmt_c.check(event.group_id)
|
||||||
|
and module not in ignore_rst_module
|
||||||
|
):
|
||||||
_flmt_c.start_cd(event.group_id)
|
_flmt_c.start_cd(event.group_id)
|
||||||
await bot.send_group_msg(
|
await bot.send_group_msg(
|
||||||
group_id=event.group_id, message="该功能在群聊中已被禁用..."
|
group_id=event.group_id, message="该功能在群聊中已被禁用..."
|
||||||
)
|
)
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
|
_exists_msg[event.group_id] = True
|
||||||
raise IgnoredException("该插件在群聊中已被禁用...")
|
raise IgnoredException("该插件在群聊中已被禁用...")
|
||||||
else:
|
else:
|
||||||
# 私聊禁用
|
# 私聊禁用
|
||||||
@@ -230,25 +269,193 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
pass
|
pass
|
||||||
raise IgnoredException("该插件在私聊中已被禁用...")
|
raise IgnoredException("该插件在私聊中已被禁用...")
|
||||||
# 维护
|
# 维护
|
||||||
if not group_manager.get_plugin_status(
|
if not group_manager.get_plugin_status(module, block_type="all"):
|
||||||
module, block_type="all"
|
if isinstance(
|
||||||
) and not group_manager.check_group_is_white(event.group_id):
|
event, GroupMessageEvent
|
||||||
|
) and group_manager.check_group_is_white(event.group_id):
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
if _flmt_c.check(event.group_id):
|
if isinstance(event, GroupMessageEvent):
|
||||||
_flmt_c.start_cd(event.group_id)
|
if (
|
||||||
if isinstance(event, GroupMessageEvent):
|
_flmt_c.check(event.group_id)
|
||||||
|
and module not in ignore_rst_module
|
||||||
|
):
|
||||||
|
_flmt_c.start_cd(event.group_id)
|
||||||
await bot.send_group_msg(
|
await bot.send_group_msg(
|
||||||
group_id=event.group_id, message="此功能正在维护..."
|
group_id=event.group_id, message="此功能正在维护..."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await bot.send_private_msg(
|
await bot.send_private_msg(
|
||||||
user_id=event.user_id, message="此功能正在维护..."
|
user_id=event.user_id, message="此功能正在维护..."
|
||||||
)
|
)
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
_exists_msg[event.group_id] = True
|
||||||
raise IgnoredException("此功能正在维护...")
|
raise IgnoredException("此功能正在维护...")
|
||||||
|
|
||||||
|
|
||||||
|
check_flmt = {}
|
||||||
|
for plugin in plugins2cd_dict.keys():
|
||||||
|
if plugins2cd_dict[plugin]["status"]:
|
||||||
|
check_flmt[plugin] = FreqLimiter(plugins2cd_dict[plugin]["cd"])
|
||||||
|
|
||||||
|
|
||||||
|
check_elmt = {}
|
||||||
|
for plugin in plugins2exists_dict.keys():
|
||||||
|
if plugins2exists_dict[plugin]["status"]:
|
||||||
|
check_elmt[plugin] = UserExistLimiter()
|
||||||
|
|
||||||
|
|
||||||
|
# 命令cd 和 命令阻塞
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
global _exists_msg
|
||||||
|
if not isinstance(event, MessageEvent) and matcher.module != "poke":
|
||||||
|
return
|
||||||
|
module = matcher.module
|
||||||
|
if isinstance(event, GroupMessageEvent) and _exists_msg.get(event.group_id) is None:
|
||||||
|
_exists_msg[event.group_id] = False
|
||||||
|
if module in plugins2cd_dict.keys() and module in check_flmt.keys():
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
isinstance(event, PrivateMessageEvent)
|
||||||
|
and plugins2cd_dict[module]["check_type"] == "private"
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
isinstance(event, GroupMessageEvent)
|
||||||
|
and plugins2cd_dict[module]["check_type"] == "group"
|
||||||
|
)
|
||||||
|
or plugins2cd_dict[module]["check_type"] == "all"
|
||||||
|
) and plugins2cd_dict[module]["cd"] > 0:
|
||||||
|
cd_type_ = event.user_id
|
||||||
|
if plugins2cd_dict[module]["limit_type"] == "group" and isinstance(
|
||||||
|
event, GroupMessageEvent
|
||||||
|
):
|
||||||
|
cd_type_ = event.group_id
|
||||||
|
if not check_flmt[module].check(cd_type_):
|
||||||
|
rst = plugins2cd_dict[module]["rst"]
|
||||||
|
if rst:
|
||||||
|
rst = await init_rst(rst, event)
|
||||||
|
await send_msg(rst, bot, event)
|
||||||
|
raise IgnoredException(f"{module} 正在cd中...")
|
||||||
|
else:
|
||||||
|
check_flmt[module].start_cd(cd_type_)
|
||||||
|
if module in plugins2exists_dict.keys() and module in check_elmt.keys():
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
isinstance(event, PrivateMessageEvent)
|
||||||
|
and plugins2exists_dict[module]["check_type"] == "private"
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
isinstance(event, GroupMessageEvent)
|
||||||
|
and plugins2exists_dict[module]["check_type"] == "group"
|
||||||
|
)
|
||||||
|
or plugins2exists_dict[module]["check_type"] == "all"
|
||||||
|
):
|
||||||
|
exists_type_ = event.user_id
|
||||||
|
if plugins2exists_dict[module]["limit_type"] == "group" and isinstance(
|
||||||
|
event, GroupMessageEvent
|
||||||
|
):
|
||||||
|
exists_type_ = event.group_id
|
||||||
|
if check_elmt[module].check(exists_type_):
|
||||||
|
rst = plugins2exists_dict[module]["rst"]
|
||||||
|
if rst:
|
||||||
|
rst = await init_rst(rst, event)
|
||||||
|
await send_msg(rst, bot, event)
|
||||||
|
raise IgnoredException(f"{event.user_id}正在调用{module}....")
|
||||||
|
else:
|
||||||
|
check_elmt[module].set_true(exists_type_)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_msg(rst: str, bot: Bot, event: MessageEvent):
|
||||||
|
"""
|
||||||
|
发送信息
|
||||||
|
:param rst: pass
|
||||||
|
:param bot: pass
|
||||||
|
:param event: pass
|
||||||
|
"""
|
||||||
|
global _exists_msg
|
||||||
|
rst = await init_rst(rst, event)
|
||||||
|
try:
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
_exists_msg[event.group_id] = True
|
||||||
|
await bot.send_group_msg(group_id=event.group_id, message=Message(rst))
|
||||||
|
else:
|
||||||
|
_exists_msg[event.user_id] = True
|
||||||
|
await bot.send_private_msg(user_id=event.user_id, message=Message(rst))
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@run_postprocessor
|
||||||
|
async def _(
|
||||||
|
matcher: Matcher,
|
||||||
|
exception: Optional[Exception],
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
):
|
||||||
|
if not isinstance(event, MessageEvent) and matcher.module != "poke":
|
||||||
|
return
|
||||||
|
module = matcher.module
|
||||||
|
if module in plugins2exists_dict.keys() and module in check_elmt.keys():
|
||||||
|
if not (
|
||||||
|
(
|
||||||
|
isinstance(event, GroupMessageEvent)
|
||||||
|
and plugins2exists_dict[module]["check_type"] == "private"
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
isinstance(event, PrivateMessageEvent)
|
||||||
|
and plugins2exists_dict[module]["check_type"] == "group"
|
||||||
|
)
|
||||||
|
):
|
||||||
|
exists_type_ = event.user_id
|
||||||
|
if plugins2exists_dict[module]["limit_type"] == "group" and isinstance(
|
||||||
|
event, GroupMessageEvent
|
||||||
|
):
|
||||||
|
exists_type_ = event.group_id
|
||||||
|
check_elmt[module].set_false(exists_type_)
|
||||||
|
|
||||||
|
|
||||||
|
async def init_rst(rst: str, event: MessageEvent):
|
||||||
|
if "[uname]" in rst:
|
||||||
|
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):
|
||||||
|
nickname = await GroupInfoUser.get_group_member_nickname(
|
||||||
|
event.user_id, event.group_id
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
nickname = await FriendUser.get_friend_nickname(event.user_id)
|
||||||
|
rst = rst.replace("[nickname]", nickname)
|
||||||
|
if "[at]" in rst and isinstance(event, GroupMessageEvent):
|
||||||
|
rst = rst.replace("[at]", str(at(event.user_id)))
|
||||||
|
return rst
|
||||||
|
|
||||||
|
|
||||||
|
# 消息撤回
|
||||||
|
@run_postprocessor
|
||||||
|
async def _(
|
||||||
|
matcher: Matcher,
|
||||||
|
exception: Optional[Exception],
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
):
|
||||||
|
tasks = []
|
||||||
|
for id_, time in withdraw_message_id_manager["message_id"]:
|
||||||
|
tasks.append(asyncio.ensure_future(_withdraw_message(bot, id_, time)))
|
||||||
|
withdraw_message_id_manager["message_id"].remove((id_, time))
|
||||||
|
await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
|
||||||
|
async def _withdraw_message(bot: Bot, id_: int, time: int):
|
||||||
|
await asyncio.sleep(time)
|
||||||
|
await bot.delete_msg(message_id=id_, self_id=int(bot.self_id))
|
||||||
|
|
||||||
|
|
||||||
# 为什么AI会自己和自己聊天
|
# 为什么AI会自己和自己聊天
|
||||||
@run_preprocessor
|
@run_preprocessor
|
||||||
async def _(matcher: Matcher, bot: Bot, event: PrivateMessageEvent, state: T_State):
|
async def _(matcher: Matcher, bot: Bot, event: PrivateMessageEvent, state: T_State):
|
||||||
@@ -261,8 +468,20 @@ async def _(matcher: Matcher, bot: Bot, event: PrivateMessageEvent, state: T_Sta
|
|||||||
# 有命令就别说话了
|
# 有命令就别说话了
|
||||||
@run_preprocessor
|
@run_preprocessor
|
||||||
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
global _exists_msg
|
||||||
if not isinstance(event, MessageEvent):
|
if not isinstance(event, MessageEvent):
|
||||||
return
|
return
|
||||||
if matcher.type == "message":
|
if matcher.type == "message":
|
||||||
if state["_prefix"]["raw_command"] and matcher.module == "ai":
|
if matcher.module == "ai":
|
||||||
raise IgnoredException("有命令就别说话了")
|
if (
|
||||||
|
isinstance(event, GroupMessageEvent)
|
||||||
|
and _exists_msg.get(event.group_id) is True
|
||||||
|
):
|
||||||
|
_exists_msg[event.group_id] = False
|
||||||
|
raise IgnoredException("有命令就别说话了")
|
||||||
|
elif (
|
||||||
|
isinstance(event, PrivateMessageEvent)
|
||||||
|
and _exists_msg.get(event.user_id) is True
|
||||||
|
):
|
||||||
|
_exists_msg[event.user_id] = False
|
||||||
|
raise IgnoredException("有命令就别说话了")
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ async def handle_event(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
content = state["content"].strip()
|
content = state["content"].strip()
|
||||||
if content.startswith(",") or content.startswith(","):
|
if content.startswith(",") or content.startswith(","):
|
||||||
content = content[1:]
|
content = content[1:]
|
||||||
_ulmt.set_True(event.user_id)
|
_ulmt.set_true(event.user_id)
|
||||||
if len(content) > 20:
|
if len(content) > 20:
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
await luxun.finish("太长了, 鲁迅说不完!", at_sender=True)
|
await luxun.finish("太长了, 鲁迅说不完!", at_sender=True)
|
||||||
else:
|
else:
|
||||||
if len(content) >= 12:
|
if len(content) >= 12:
|
||||||
@@ -47,7 +47,7 @@ async def handle_event(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'} 鲁迅说过 {content}"
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'} 鲁迅说过 {content}"
|
||||||
)
|
)
|
||||||
await luxun.send(img)
|
await luxun.send(img)
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
|
|
||||||
|
|
||||||
def process_pic(content, filename) -> str:
|
def process_pic(content, filename) -> str:
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ mute_setting = on_command(
|
|||||||
aliases={"设置检测时间", "设置检测次数", "设置禁言时长", "刷屏检测设置"},
|
aliases={"设置检测时间", "设置检测次数", "设置禁言时长", "刷屏检测设置"},
|
||||||
permission=GROUP,
|
permission=GROUP,
|
||||||
block=True,
|
block=True,
|
||||||
|
priority=5
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
from typing import Any, Dict
|
|
||||||
from nonebot import get_driver, on_command
|
|
||||||
from nonebot.adapters.cqhttp import Bot, Event, GroupMessageEvent, PrivateMessageEvent
|
|
||||||
from nonebot.rule import to_me
|
|
||||||
from nonebot.typing import T_State, T_CalledAPIHook
|
|
||||||
|
|
||||||
from .config import Config
|
|
||||||
|
|
||||||
global_config = get_driver().config
|
|
||||||
withdraw_config = Config(**global_config.dict())
|
|
||||||
|
|
||||||
msg_ids = {}
|
|
||||||
max_size = withdraw_config.withdraw_max_size
|
|
||||||
|
|
||||||
|
|
||||||
__plugin_name__ = "撤回"
|
|
||||||
|
|
||||||
__plugin_usage__ = (
|
|
||||||
"用法:撤回 [消息位置](默认0)\n" "示例:\n" "\t撤回0 -> 撤回倒数第一条消息(即最新发送的消息)" "\t撤回1 -> 撤回倒数第2条消息"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_key(msg_type, id):
|
|
||||||
return f"{msg_type}_{id}"
|
|
||||||
|
|
||||||
|
|
||||||
async def save_msg_id(
|
|
||||||
bot: Bot, e: Exception, api: str, data: Dict[str, Any], result: Any
|
|
||||||
) -> T_CalledAPIHook:
|
|
||||||
try:
|
|
||||||
if api == "send_msg":
|
|
||||||
msg_type = data["message_type"]
|
|
||||||
id = data["group_id"] if msg_type == "group" else data["user_id"]
|
|
||||||
elif api == "send_private_msg":
|
|
||||||
msg_type = "private"
|
|
||||||
id = data["user_id"]
|
|
||||||
elif api == "send_group_msg":
|
|
||||||
msg_type = "group"
|
|
||||||
id = data["group_id"]
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
key = get_key(msg_type, id)
|
|
||||||
msg_id = result["message_id"]
|
|
||||||
|
|
||||||
if key not in msg_ids:
|
|
||||||
msg_ids[key] = []
|
|
||||||
msg_ids[key].append(msg_id)
|
|
||||||
if len(msg_ids) > max_size:
|
|
||||||
msg_ids[key].pop(0)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
Bot._called_api_hook.add(save_msg_id)
|
|
||||||
|
|
||||||
|
|
||||||
withdraw = on_command("withdraw", aliases={"撤回"}, rule=to_me(), priority=1, block=True)
|
|
||||||
|
|
||||||
|
|
||||||
@withdraw.handle()
|
|
||||||
async def _(bot: Bot, event: Event, state: T_State):
|
|
||||||
if isinstance(event, GroupMessageEvent):
|
|
||||||
msg_type = "group"
|
|
||||||
id = event.group_id
|
|
||||||
elif isinstance(event, PrivateMessageEvent):
|
|
||||||
msg_type = "private"
|
|
||||||
id = event.user_id
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
key = get_key(msg_type, id)
|
|
||||||
|
|
||||||
num = event.get_plaintext().strip()
|
|
||||||
if not num:
|
|
||||||
num = 0
|
|
||||||
elif num.isdigit() and 0 <= int(num) < len(msg_ids[key]):
|
|
||||||
num = int(num)
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
idx = -num - 1
|
|
||||||
await bot.delete_msg(message_id=msg_ids[key][idx])
|
|
||||||
msg_ids[key].pop(idx)
|
|
||||||
except:
|
|
||||||
await withdraw.finish("撤回失败,可能已超时")
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
from pydantic import BaseSettings
|
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseSettings):
|
|
||||||
withdraw_max_size: int = 50
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
extra = 'ignore'
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
from utils.user_agent import get_user_agent
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from random import choice
|
from random import choice
|
||||||
from nonebot import on_regex
|
from nonebot import on_regex
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
||||||
from utils.utils import get_message_text, get_local_proxy, get_message_at
|
from utils.utils import get_message_text, get_message_at
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
import re
|
import re
|
||||||
from utils.image_utils import CreateImg
|
from utils.image_utils import CreateImg
|
||||||
@@ -16,15 +15,15 @@ __plugin_usage__ = "用法:我有一个朋友说/问 [消息] [at](不艾特
|
|||||||
|
|
||||||
one_friend = on_regex(
|
one_friend = on_regex(
|
||||||
"^我.*?朋友.*?(想问问|说|让我问问|想问|让我问|想知道|让我帮他问问|让我帮他问|让我帮忙问|让我帮忙问问|问).*",
|
"^我.*?朋友.*?(想问问|说|让我问问|想问|让我问|想知道|让我帮他问问|让我帮他问|让我帮忙问|让我帮忙问问|问).*",
|
||||||
priority=5,
|
priority=4,
|
||||||
block=True,
|
block=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_pic(qq):
|
async def get_pic(qq):
|
||||||
url = f"http://q1.qlogo.cn/g?b=qq&nk={qq}&s=100"
|
url = f"http://q1.qlogo.cn/g?b=qq&nk={qq}&s=100"
|
||||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
async with session.get(url, proxy=get_local_proxy(), timeout=5) as response:
|
async with session.get(url, timeout=5) as response:
|
||||||
return await response.read()
|
return await response.read()
|
||||||
|
|
||||||
|
|
||||||
@@ -59,7 +58,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
text.text((0, 0), user_name)
|
text.text((0, 0), user_name)
|
||||||
A = CreateImg(700, 150, font_size=25, color="white")
|
A = CreateImg(700, 150, font_size=25, color="white")
|
||||||
A.paste(ava, (30, 25), True)
|
A.paste(ava, (30, 25), True)
|
||||||
A.paste(text, (150, 40))
|
A.paste(text, (150, 38))
|
||||||
A.text((150, 85), msg, (125, 125, 125))
|
A.text((150, 85), msg, (125, 125, 125))
|
||||||
|
|
||||||
await one_friend.send(image(b64=A.pic2bs4()))
|
await one_friend.send(image(b64=A.pic2bs4()))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from nonebot import on_command
|
from nonebot import on_command
|
||||||
from utils.utils import FreqLimiter, scheduler, get_message_text, is_number
|
from utils.utils import scheduler, get_message_text, is_number
|
||||||
from nonebot.adapters.cqhttp.permission import GROUP
|
from nonebot.adapters.cqhttp.permission import GROUP
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
|
||||||
@@ -33,8 +33,6 @@ __plugin_usage__ = (
|
|||||||
"示例:我的金色"
|
"示例:我的金色"
|
||||||
)
|
)
|
||||||
|
|
||||||
_flmt = FreqLimiter(3)
|
|
||||||
|
|
||||||
cases_name = ["狂牙大行动", "突围大行动", "命悬一线", "裂空", "光谱"]
|
cases_name = ["狂牙大行动", "突围大行动", "命悬一线", "裂空", "光谱"]
|
||||||
|
|
||||||
cases_matcher_group = MatcherGroup(priority=5, permission=GROUP, block=True)
|
cases_matcher_group = MatcherGroup(priority=5, permission=GROUP, block=True)
|
||||||
@@ -47,9 +45,9 @@ k_open_case = cases_matcher_group.on_command("开箱")
|
|||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
if str(event.get_message()).strip() in ["帮助"]:
|
if str(event.get_message()).strip() in ["帮助"]:
|
||||||
await k_open_case.finish(__plugin_usage__)
|
await k_open_case.finish(__plugin_usage__)
|
||||||
if not _flmt.check(event.user_id):
|
# if not _flmt.check(event.user_id):
|
||||||
await k_open_case.finish("着什么急啊,慢慢来!", at_sender=True)
|
# await k_open_case.finish("着什么急啊,慢慢来!", at_sender=True)
|
||||||
_flmt.start_cd(event.user_id)
|
# _flmt.start_cd(event.user_id)
|
||||||
case_name = get_message_text(event.json())
|
case_name = get_message_text(event.json())
|
||||||
if case_name:
|
if case_name:
|
||||||
result = await open_case(event.user_id, event.group_id, case_name)
|
result = await open_case(event.user_id, event.group_id, case_name)
|
||||||
@@ -98,7 +96,7 @@ open_shilian = cases_matcher_group.on_regex(".*连开箱")
|
|||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
# if not _flmt.check(event.user_id):
|
# if not _flmt.check(event.user_id):
|
||||||
# await k_open_case.finish('着什么急啊,慢慢来!', at_sender=True)
|
# await k_open_case.finish('着什么急啊,慢慢来!', at_sender=True)
|
||||||
_flmt.start_cd(event.user_id)
|
# _flmt.start_cd(event.user_id)
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
rs = re.search(r"(.*)连开箱(.*)", msg)
|
rs = re.search(r"(.*)连开箱(.*)", msg)
|
||||||
if rs:
|
if rs:
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ from .config import *
|
|||||||
from services.log import logger
|
from services.log import logger
|
||||||
from services.db_context import db
|
from services.db_context import db
|
||||||
from models.open_cases_user import OpenCasesUser
|
from models.open_cases_user import OpenCasesUser
|
||||||
from models.sigin_group_user import SignGroupUser
|
from models.sign_group_user import SignGroupUser
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
import pypinyin
|
import pypinyin
|
||||||
import random
|
import random
|
||||||
from .utils import get_price
|
from .utils import get_price
|
||||||
from models.buff_price import BuffPrice
|
from models.buff_price import BuffPrice
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from utils.image_utils import alpha2white_PIL, CreateImg
|
from utils.image_utils import alpha2white_pil, CreateImg
|
||||||
from configs.path_config import IMAGE_PATH
|
from configs.path_config import IMAGE_PATH
|
||||||
import asyncio
|
import asyncio
|
||||||
from utils.utils import cn2py
|
from utils.utils import cn2py
|
||||||
@@ -221,7 +221,7 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
|
|||||||
skin_name += ''.join(i)
|
skin_name += ''.join(i)
|
||||||
# img = image(skin_name, "cases/" + case, "png")
|
# img = image(skin_name, "cases/" + case, "png")
|
||||||
wImg = CreateImg(200, 270, 200, 200)
|
wImg = CreateImg(200, 270, 200, 200)
|
||||||
wImg.paste(alpha2white_PIL(Image.open(IMAGE_PATH + f'cases/{case}/{skin_name}.png').resize((200, 200), Image.ANTIALIAS)), (0, 0))
|
wImg.paste(alpha2white_pil(Image.open(IMAGE_PATH + f'cases/{case}/{skin_name}.png').resize((200, 200), Image.ANTIALIAS)), (0, 0))
|
||||||
wImg.text((5, 200), skin)
|
wImg.text((5, 200), skin)
|
||||||
wImg.text((5, 220), f'磨损:{str(mosun)[:9]}')
|
wImg.text((5, 220), f'磨损:{str(mosun)[:9]}')
|
||||||
wImg.text((5, 240), f'价格:{price_result}')
|
wImg.text((5, 240), f'价格:{price_result}')
|
||||||
@@ -370,7 +370,7 @@ def _pst_my_knife(w, h, knifes_list):
|
|||||||
style=pypinyin.NORMAL):
|
style=pypinyin.NORMAL):
|
||||||
skin_name += ''.join(i)
|
skin_name += ''.join(i)
|
||||||
knife_img = CreateImg(470, 600, 470, 470, font_size=20)
|
knife_img = CreateImg(470, 600, 470, 470, font_size=20)
|
||||||
knife_img.paste(alpha2white_PIL(
|
knife_img.paste(alpha2white_pil(
|
||||||
Image.open(IMAGE_PATH + f'cases/{case}/{skin_name}.png').resize((470, 470), Image.ANTIALIAS)), (0, 0))
|
Image.open(IMAGE_PATH + f'cases/{case}/{skin_name}.png').resize((470, 470), Image.ANTIALIAS)), (0, 0))
|
||||||
knife_img.text((5, 500), f'\t{name}({itype})')
|
knife_img.text((5, 500), f'\t{name}({itype})')
|
||||||
knife_img.text((5, 530), f'\t磨损:{mosun}')
|
knife_img.text((5, 530), f'\t磨损:{mosun}')
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from nonebot import on_message
|
|||||||
from services.log import logger
|
from services.log import logger
|
||||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from utils.utils import get_message_json, get_local_proxy, get_message_text
|
from utils.utils import get_message_json, get_local_proxy, get_message_text, is_number
|
||||||
from utils.user_agent import get_user_agent
|
from utils.user_agent import get_user_agent
|
||||||
from nonebot.adapters.cqhttp.permission import GROUP
|
from nonebot.adapters.cqhttp.permission import GROUP
|
||||||
from bilibili_api import video
|
from bilibili_api import video
|
||||||
@@ -23,11 +23,14 @@ if get_local_proxy():
|
|||||||
|
|
||||||
parse_bilibili_json = on_message(priority=1, permission=GROUP, block=False)
|
parse_bilibili_json = on_message(priority=1, permission=GROUP, block=False)
|
||||||
|
|
||||||
|
_tmp = {}
|
||||||
|
|
||||||
|
|
||||||
@parse_bilibili_json.handle()
|
@parse_bilibili_json.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
if await GroupRemind.get_status(event.group_id, "blpar"):
|
if await GroupRemind.get_status(event.group_id, "blpar"):
|
||||||
vd_info = None
|
vd_info = None
|
||||||
|
url = None
|
||||||
if get_message_json(event.json()):
|
if get_message_json(event.json()):
|
||||||
try:
|
try:
|
||||||
data = json.loads(get_message_json(event.json())[0]["data"])
|
data = json.loads(get_message_json(event.json())[0]["data"])
|
||||||
@@ -66,7 +69,6 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
await page.goto(url, wait_until="networkidle", timeout=10000)
|
await page.goto(url, wait_until="networkidle", timeout=10000)
|
||||||
await page.set_viewport_size({"width": 2560, "height": 1080})
|
await page.set_viewport_size({"width": 2560, "height": 1080})
|
||||||
await page.click("#app > div")
|
await page.click("#app > div")
|
||||||
# await page.click("text=继续阅读全文", timeout=3000)
|
|
||||||
div = await page.query_selector("#app > div")
|
div = await page.query_selector("#app > div")
|
||||||
await div.screenshot(
|
await div.screenshot(
|
||||||
path=f"{IMAGE_PATH}/temp/cv_{event.user_id}.png",
|
path=f"{IMAGE_PATH}/temp/cv_{event.user_id}.png",
|
||||||
@@ -90,7 +92,20 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
# BV
|
# BV
|
||||||
if get_message_text(event.json()):
|
if get_message_text(event.json()):
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
if "https://b23.tv" in msg:
|
if "BV" in msg:
|
||||||
|
index = msg.find('BV')
|
||||||
|
if len(msg[index + 2:]) >= 10:
|
||||||
|
msg = msg[index: index + 12]
|
||||||
|
url = f'https://www.bilibili.com/video/{msg}'
|
||||||
|
vd_info = await video.Video(bvid=msg).get_info()
|
||||||
|
elif 'av' in msg:
|
||||||
|
index = msg.find('av')
|
||||||
|
if len(msg[index + 2:]) >= 9:
|
||||||
|
msg = msg[index + 2: index + 11]
|
||||||
|
if is_number(msg):
|
||||||
|
url = f'https://www.bilibili.com/video/{msg}'
|
||||||
|
vd_info = await video.Video(aid=int(msg)).get_info()
|
||||||
|
elif "https://b23.tv" in msg:
|
||||||
url = "https://" + msg[msg.find("b23.tv") : msg.find("b23.tv") + 13]
|
url = "https://" + msg[msg.find("b23.tv") : msg.find("b23.tv") + 13]
|
||||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||||
async with session.get(
|
async with session.get(
|
||||||
@@ -101,33 +116,32 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
url = str(response.url).split("?")[0]
|
url = str(response.url).split("?")[0]
|
||||||
bvid = url.split("/")[-1]
|
bvid = url.split("/")[-1]
|
||||||
vd_info = await video.Video(bvid=bvid).get_info()
|
vd_info = await video.Video(bvid=bvid).get_info()
|
||||||
if "https://www.bilibili.com/video" in msg:
|
|
||||||
url = msg.split("?")[0]
|
|
||||||
msg = url.split("/")[-1]
|
|
||||||
vd_info = await video.Video(bvid=msg).get_info()
|
|
||||||
if vd_info:
|
if vd_info:
|
||||||
aid = vd_info["aid"]
|
if (url in _tmp.keys() and time.time() - _tmp[url] > 30) or url not in _tmp.keys():
|
||||||
title = vd_info["title"]
|
_tmp[url] = time.time()
|
||||||
author = vd_info["owner"]["name"]
|
aid = vd_info["aid"]
|
||||||
reply = vd_info["stat"]["reply"] # 回复
|
title = vd_info["title"]
|
||||||
favorite = vd_info["stat"]["favorite"] # 收藏
|
author = vd_info["owner"]["name"]
|
||||||
coin = vd_info["stat"]["coin"] # 投币
|
reply = vd_info["stat"]["reply"] # 回复
|
||||||
# like = vd_info['stat']['like'] # 点赞
|
favorite = vd_info["stat"]["favorite"] # 收藏
|
||||||
# danmu = vd_info['stat']['danmaku'] # 弹幕
|
coin = vd_info["stat"]["coin"] # 投币
|
||||||
date = time.strftime("%Y-%m-%d", time.localtime(vd_info["ctime"]))
|
# like = vd_info['stat']['like'] # 点赞
|
||||||
try:
|
# danmu = vd_info['stat']['danmaku'] # 弹幕
|
||||||
await parse_bilibili_json.send(
|
date = time.strftime("%Y-%m-%d", time.localtime(vd_info["ctime"]))
|
||||||
image(vd_info["pic"]) + f"\nav{aid}\n标题:{title}\n"
|
try:
|
||||||
f"UP:{author}\n"
|
await parse_bilibili_json.send(
|
||||||
f"上传日期:{date}\n"
|
image(vd_info["pic"]) + f"\nav{aid}\n标题:{title}\n"
|
||||||
f"回复:{reply},收藏:{favorite},投币:{coin}\n"
|
f"UP:{author}\n"
|
||||||
f"{url}"
|
f"上传日期:{date}\n"
|
||||||
)
|
f"回复:{reply},收藏:{favorite},投币:{coin}\n"
|
||||||
except ActionFailed:
|
f"{url}"
|
||||||
logger.warning(f"{event.group_id} 发送bilibili解析失败")
|
)
|
||||||
logger.info(
|
except ActionFailed:
|
||||||
f"USER {event.user_id} GROUP {event.group_id} 解析bilibili转发 {url}"
|
logger.warning(f"{event.group_id} 发送bilibili解析失败")
|
||||||
)
|
else:
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} GROUP {event.group_id} 解析bilibili转发 {url}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def resize(path: str):
|
def resize(path: str):
|
||||||
|
|||||||
@@ -1,14 +1,76 @@
|
|||||||
|
from configs.config import HIBIAPI
|
||||||
|
from services.log import logger
|
||||||
|
from models.omega_pixiv_illusts import OmegaPixivIllusts
|
||||||
|
from pathlib import Path
|
||||||
|
from nonebot import Driver
|
||||||
|
from typing import List
|
||||||
|
from datetime import datetime
|
||||||
|
import nonebot
|
||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
illust_url = f"{HIBIAPI}/api/pixiv/illust"
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def _init_omega_pixiv_illusts():
|
||||||
|
omega_pixiv_illusts = None
|
||||||
|
for file in os.listdir("."):
|
||||||
|
if "omega_pixiv_illusts" in file and ".sql" in file:
|
||||||
|
omega_pixiv_illusts = Path() / file
|
||||||
|
if omega_pixiv_illusts:
|
||||||
|
with open(omega_pixiv_illusts, "r", encoding="utf8") as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
tasks = []
|
||||||
|
length = len([x for x in lines if "INSERT INTO" in x.upper()])
|
||||||
|
all_pid = await OmegaPixivIllusts.get_all_pid()
|
||||||
|
index = 0
|
||||||
|
logger.info('检测到OmegaPixivIllusts数据库,准备开始更新....')
|
||||||
|
for line in lines:
|
||||||
|
if "INSERT INTO" in line.upper():
|
||||||
|
index += 1
|
||||||
|
tasks.append(asyncio.ensure_future(_tasks(line, all_pid, length, index)))
|
||||||
|
await asyncio.gather(*tasks)
|
||||||
|
omega_pixiv_illusts.unlink()
|
||||||
|
|
||||||
|
|
||||||
|
async def _tasks(line: str, all_pid: List[int], length: int, index: int):
|
||||||
|
data = line.split("VALUES", maxsplit=1)[-1].strip()
|
||||||
|
if data.startswith("("):
|
||||||
|
data = data[1:]
|
||||||
|
if data.endswith(");"):
|
||||||
|
data = data[:-2]
|
||||||
|
x = data.split(maxsplit=3)
|
||||||
|
pid = int(x[1][:-1].strip())
|
||||||
|
if pid in all_pid:
|
||||||
|
logger.info(f'添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}')
|
||||||
|
return
|
||||||
|
uid = int(x[2][:-1].strip())
|
||||||
|
x = x[3].split(", '")
|
||||||
|
title = x[0].strip()[1:-1]
|
||||||
|
tmp = x[1].split(', ')
|
||||||
|
author = tmp[0].strip()[:-1]
|
||||||
|
nsfw_tag = int(tmp[1])
|
||||||
|
width = int(tmp[2])
|
||||||
|
height = int(tmp[3])
|
||||||
|
tags = x[2][:-1]
|
||||||
|
url = x[3][:-1]
|
||||||
|
if await OmegaPixivIllusts.add_image_data(
|
||||||
|
pid,
|
||||||
|
title,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
url,
|
||||||
|
uid,
|
||||||
|
author,
|
||||||
|
nsfw_tag,
|
||||||
|
tags,
|
||||||
|
datetime.min,
|
||||||
|
datetime.min
|
||||||
|
):
|
||||||
|
logger.info(f"成功添加OmegaPixivIllusts图库数据 pid:{pid} 本次预计存储 {length} 张,已更新第 {index} 张")
|
||||||
|
else:
|
||||||
|
logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
|
||||||
|
|
||||||
|
|||||||
@@ -4,16 +4,17 @@ from aiohttp.client_exceptions import (
|
|||||||
ClientConnectorError,
|
ClientConnectorError,
|
||||||
)
|
)
|
||||||
from asyncpg.exceptions import UniqueViolationError
|
from asyncpg.exceptions import UniqueViolationError
|
||||||
|
from models.omega_pixiv_illusts import OmegaPixivIllusts
|
||||||
from asyncio.locks import Semaphore
|
from asyncio.locks import Semaphore
|
||||||
from aiohttp import ClientPayloadError
|
from aiohttp import ClientPayloadError
|
||||||
from aiohttp.client import ClientSession
|
from aiohttp.client import ClientSession
|
||||||
from asyncio.exceptions import TimeoutError
|
from asyncio.exceptions import TimeoutError
|
||||||
from models.pixiv import Pixiv
|
from models.pixiv import Pixiv
|
||||||
from typing import List
|
from typing import List
|
||||||
from utils.utils import get_local_proxy
|
from utils.utils import get_local_proxy, change_picture_links
|
||||||
from utils.image_utils import CreateImg
|
from utils.image_utils import CreateImg
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from configs.config import HIBIAPI_BOOKMARKS, HIBIAPI
|
from configs.config import HIBIAPI_BOOKMARKS, HIBIAPI, PIX_IMAGE_SIZE
|
||||||
from configs.path_config import TEMP_PATH
|
from configs.path_config import TEMP_PATH
|
||||||
import platform
|
import platform
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@@ -215,19 +216,45 @@ async def download_image(img_url: str, session: ClientSession, _count: int = 1):
|
|||||||
|
|
||||||
|
|
||||||
async def get_image(img_url: str, user_id: int) -> str:
|
async def get_image(img_url: str, user_id: int) -> str:
|
||||||
try:
|
async with aiohttp.ClientSession(headers=headers) as session:
|
||||||
async with aiohttp.ClientSession(headers=headers) as session:
|
if 'https://www.pixiv.net/artworks' in img_url:
|
||||||
async with session.get(
|
pid = img_url.rsplit('/', maxsplit=1)[-1]
|
||||||
img_url,
|
params = {"id": pid}
|
||||||
proxy=get_local_proxy(),
|
for _ in range(3):
|
||||||
) as response:
|
try:
|
||||||
async with aiofiles.open(
|
async with session.get(
|
||||||
f"{TEMP_PATH}/pix_{user_id}_{img_url[-10:-4]}.jpg", "wb"
|
illust_url,
|
||||||
) as f:
|
params=params,
|
||||||
await f.write(await response.read())
|
proxy=get_local_proxy(),
|
||||||
return f"pix_{user_id}_{img_url[-10:-4]}.jpg"
|
) as response:
|
||||||
except (ClientConnectorError, TimeoutError):
|
if response.status == 200:
|
||||||
return await get_image(img_url, user_id)
|
data = await response.json()
|
||||||
|
if data.get('illust'):
|
||||||
|
if data['illust']['page_count'] == 1:
|
||||||
|
img_url = data['illust']['meta_single_page']['original_image_url']
|
||||||
|
else:
|
||||||
|
img_url = data['illust']["meta_pages"][0]["image_urls"]["original"]
|
||||||
|
break
|
||||||
|
except (ClientConnectorError, TimeoutError):
|
||||||
|
pass
|
||||||
|
old_img_url = img_url
|
||||||
|
img_url = change_picture_links(img_url, PIX_IMAGE_SIZE)
|
||||||
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
async with session.get(
|
||||||
|
img_url,
|
||||||
|
proxy=get_local_proxy(),
|
||||||
|
) as response:
|
||||||
|
if response.status == 404:
|
||||||
|
img_url = old_img_url
|
||||||
|
continue
|
||||||
|
async with aiofiles.open(
|
||||||
|
f"{TEMP_PATH}/pix_{user_id}_{img_url[-10:-4]}.jpg", "wb"
|
||||||
|
) as f:
|
||||||
|
await f.write(await response.read())
|
||||||
|
return f"pix_{user_id}_{img_url[-10:-4]}.jpg"
|
||||||
|
except (ClientConnectorError, TimeoutError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# 检测UID或PID是否有效
|
# 检测UID或PID是否有效
|
||||||
@@ -248,7 +275,9 @@ async def uid_pid_exists(id_: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
async def get_keyword_num(keyword: str) -> "int , int":
|
async def get_keyword_num(keyword: str) -> "int , int":
|
||||||
return await Pixiv.get_keyword_num(keyword.split())
|
count, r18_count = await Pixiv.get_keyword_num(keyword.split())
|
||||||
|
count_, setu_count, r18_count_ = await OmegaPixivIllusts.get_keyword_num(keyword.split())
|
||||||
|
return count, r18_count, count_, setu_count, r18_count_
|
||||||
|
|
||||||
|
|
||||||
async def remove_image(pid: int, img_p: str) -> bool:
|
async def remove_image(pid: int, img_p: str) -> bool:
|
||||||
|
|||||||
@@ -1,17 +1,30 @@
|
|||||||
from nonebot import on_command
|
|
||||||
from nonebot.adapters.cqhttp.event import GroupMessageEvent
|
|
||||||
from nonebot.adapters.cqhttp.message import Message
|
from nonebot.adapters.cqhttp.message import Message
|
||||||
from utils.utils import get_message_text, is_number
|
from utils.utils import get_message_text, is_number
|
||||||
|
from configs.config import PIX_OMEGA_PIXIV_RATIO, WITHDRAW_PIX_TIME
|
||||||
|
from models.omega_pixiv_illusts import OmegaPixivIllusts
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from nonebot.adapters.cqhttp import Bot, MessageEvent
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
PrivateMessageEvent,
|
||||||
|
)
|
||||||
|
from utils.static_data import withdraw_message_id_manager
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from .data_source import get_image
|
from .data_source import get_image
|
||||||
from models.pixiv import Pixiv
|
from models.pixiv import Pixiv
|
||||||
|
from nonebot import on_command
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
pix = on_command("pix", aliases={"PIX"}, priority=5, block=True)
|
pix = on_command("pix", aliases={"PIX", "Pix"}, priority=5, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
PIX_RATIO = PIX_OMEGA_PIXIV_RATIO[0] / (
|
||||||
|
PIX_OMEGA_PIXIV_RATIO[0] + PIX_OMEGA_PIXIV_RATIO[1]
|
||||||
|
)
|
||||||
|
OMEGA_RATIO = 1 - PIX_RATIO
|
||||||
|
|
||||||
|
|
||||||
@pix.handle()
|
@pix.handle()
|
||||||
@@ -24,40 +37,97 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
pid = keyword.replace("pid", "").replace(":", "")
|
pid = keyword.replace("pid", "").replace(":", "")
|
||||||
if not is_number(pid):
|
if not is_number(pid):
|
||||||
await pix.finish("PID必须是数字...", at_sender=True)
|
await pix.finish("PID必须是数字...", at_sender=True)
|
||||||
all_image = await Pixiv.query_images(pid=int(pid))
|
isr18 = 0 if isinstance(event, GroupMessageEvent) else 2
|
||||||
|
nsfw_tag = 0 if isinstance(event, GroupMessageEvent) else None
|
||||||
|
all_image = await Pixiv.query_images(pid=int(pid), r18=isr18)
|
||||||
|
if not all_image:
|
||||||
|
all_image = await OmegaPixivIllusts.query_images(
|
||||||
|
pid=int(pid), nsfw_tag=nsfw_tag
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
x = keyword.split()
|
x = keyword.split()
|
||||||
|
if '-s' in x:
|
||||||
|
x.remove('-s')
|
||||||
|
nsfw_tag = 1
|
||||||
|
elif '-r' in x:
|
||||||
|
x.remove('-r')
|
||||||
|
nsfw_tag = 2
|
||||||
|
else:
|
||||||
|
nsfw_tag = 0
|
||||||
|
if nsfw_tag != 0 and str(event.user_id) not in bot.config.superusers:
|
||||||
|
await pix.finish('你不能看这些噢,这些都是是留给管理员看的...')
|
||||||
if len(x) > 1:
|
if len(x) > 1:
|
||||||
if is_number(x[-1]):
|
if is_number(x[-1]):
|
||||||
num = int(x[-1])
|
num = int(x[-1])
|
||||||
if num > 11:
|
if num > 10:
|
||||||
num = random.randint(1, 10)
|
if str(event.user_id) not in bot.config.superusers or (
|
||||||
await pix.send(f"太贪心了,就给你发 {num}张 好了")
|
str(event.user_id) in bot.config.superusers and num > 30
|
||||||
|
):
|
||||||
|
num = random.randint(1, 10)
|
||||||
|
await pix.send(f"太贪心了,就给你发 {num}张 好了")
|
||||||
x = x[:-1]
|
x = x[:-1]
|
||||||
keyword = " ".join(x)
|
keyword = " ".join(x)
|
||||||
all_image = await Pixiv.query_images(x)
|
pix_num = int(num * PIX_RATIO) + 15 if PIX_RATIO != 0 else 0
|
||||||
|
omega_num = num - pix_num + 15
|
||||||
|
tmp = await Pixiv.query_images(
|
||||||
|
x, r18=1 if nsfw_tag == 2 else 0, num=pix_num
|
||||||
|
) + await OmegaPixivIllusts.query_images(x, nsfw_tag=nsfw_tag, num=omega_num)
|
||||||
|
tmp_ = []
|
||||||
|
all_image = []
|
||||||
|
for x in tmp:
|
||||||
|
if x.pid not in tmp_:
|
||||||
|
all_image.append(x)
|
||||||
|
tmp_.append(x.pid)
|
||||||
if not all_image:
|
if not all_image:
|
||||||
await pix.finish(f"未在图库中找到与 {keyword} 相关Tag/UID/PID的图片...", at_sender=True)
|
await pix.finish(f"未在图库中找到与 {keyword} 相关Tag/UID/PID的图片...", at_sender=True)
|
||||||
for _ in range(num):
|
for _ in range(num):
|
||||||
|
img_url = None
|
||||||
|
author = None
|
||||||
if not all_image:
|
if not all_image:
|
||||||
await pix.finish("坏了...发完了,没图了...")
|
await pix.finish("坏了...发完了,没图了...")
|
||||||
img = random.choice(all_image)
|
img = random.choice(all_image)
|
||||||
all_image.remove(img)
|
all_image.remove(img)
|
||||||
img_url = img.img_url
|
if isinstance(img, OmegaPixivIllusts):
|
||||||
|
img_url = img.url
|
||||||
|
author = img.uname
|
||||||
|
print(img.nsfw_tag)
|
||||||
|
elif isinstance(img, Pixiv):
|
||||||
|
img_url = img.img_url
|
||||||
|
author = img.author
|
||||||
pid = img.pid
|
pid = img.pid
|
||||||
title = img.title
|
title = img.title
|
||||||
author = img.author
|
|
||||||
uid = img.uid
|
uid = img.uid
|
||||||
# tags = img.tags
|
# tags = img.tags
|
||||||
await pix.send(
|
_img = await get_image(img_url, event.user_id)
|
||||||
Message(
|
if _img:
|
||||||
f"title:{title}\n"
|
msg_id = await pix.send(
|
||||||
f"author:{author}\n"
|
Message(
|
||||||
f"PID:{pid}\nUID:{uid}\n"
|
f"title:{title}\n"
|
||||||
f"{image(await get_image(img_url, event.user_id), 'temp')}"
|
f"author:{author}\n"
|
||||||
|
f"PID:{pid}\nUID:{uid}\n"
|
||||||
|
f"{image(_img, 'temp')}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
|
f" 查看PIX图库PID: {pid}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
msg_id = await pix.send(f"下载图片似乎出了一点问题,PID:{pid}")
|
||||||
|
logger.info(
|
||||||
|
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
|
f" 查看PIX图库PID: {pid},下载图片出错"
|
||||||
|
)
|
||||||
|
withdraw_message(event, msg_id["message_id"])
|
||||||
|
|
||||||
|
|
||||||
|
def withdraw_message(event: MessageEvent, id_: int):
|
||||||
|
if WITHDRAW_PIX_TIME[0]:
|
||||||
|
if (
|
||||||
|
(WITHDRAW_PIX_TIME[1] == 0 and isinstance(event, PrivateMessageEvent))
|
||||||
|
or (WITHDRAW_PIX_TIME[1] == 1 and isinstance(event, GroupMessageEvent))
|
||||||
|
or WITHDRAW_PIX_TIME[1] == 2
|
||||||
|
):
|
||||||
|
withdraw_message_id_manager["message_id"].append(
|
||||||
|
(id_, WITHDRAW_PIX_TIME[0])
|
||||||
)
|
)
|
||||||
)
|
|
||||||
logger.info(
|
|
||||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
|
||||||
f" 查看PIX图库PID: {pid}"
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -56,10 +56,16 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
@show_pix.handle()
|
@show_pix.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
keyword = get_message_text(event.json())
|
keyword = get_message_text(event.json())
|
||||||
count, r18_count = await get_keyword_num(keyword)
|
count, r18_count, count_, setu_count, r18_count_ = await get_keyword_num(keyword)
|
||||||
await show_pix.send(
|
await show_pix.send(
|
||||||
f"PIX图库:{keyword}\n"
|
f"PIX图库:{keyword}\n"
|
||||||
f"总数:{count + r18_count}\n"
|
f"总数:{count + r18_count}\n"
|
||||||
f"美图:{count}\n"
|
f"美图:{count}\n"
|
||||||
f"r18:{r18_count}"
|
f"R18:{r18_count}\n"
|
||||||
|
f"---------------\n"
|
||||||
|
f"Omega图库:{keyword}\n"
|
||||||
|
f"总数:{count_ + setu_count + r18_count_}\n"
|
||||||
|
f"美图:{count_}\n"
|
||||||
|
f"色图:{setu_count}\n"
|
||||||
|
f"R18:{r18_count_}"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, Event, GroupMessageEvent, Message
|
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
||||||
from nonebot.matcher import Matcher
|
from nonebot.matcher import Matcher
|
||||||
from nonebot import on_command
|
from nonebot import on_command
|
||||||
from utils.utils import get_message_text, UserExistLimiter, is_number
|
from utils.utils import get_message_text, is_number
|
||||||
from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
|
from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
|
||||||
from utils.message_builder import at
|
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from nonebot.adapters.cqhttp.exception import NetworkError
|
from nonebot.adapters.cqhttp.exception import NetworkError
|
||||||
from asyncio.exceptions import TimeoutError
|
from asyncio.exceptions import TimeoutError
|
||||||
from aiohttp.client_exceptions import ClientConnectorError
|
from aiohttp.client_exceptions import ClientConnectorError
|
||||||
from nonebot.exception import IgnoredException
|
from configs.config import NICKNAME
|
||||||
from nonebot.message import run_preprocessor, run_postprocessor
|
from typing import Type
|
||||||
from typing import Optional
|
from nonebot.rule import to_me
|
||||||
import time
|
import time
|
||||||
|
|
||||||
__plugin_name__ = "P站"
|
__plugin_name__ = "P站"
|
||||||
@@ -38,17 +37,13 @@ p站排行榜 [参数] [数量](可选) [日期](可选)
|
|||||||
【注意空格!!】【在线搜索会较慢】
|
【注意空格!!】【在线搜索会较慢】
|
||||||
---------------------------------
|
---------------------------------
|
||||||
'P站搜图帮助:
|
'P站搜图帮助:
|
||||||
可选参数:
|
搜图 [关键词] [数量](可选) [页数](可选默认1) [r18](不屏蔽R-18,可选)
|
||||||
1.热度排序
|
|
||||||
2.时间排序
|
|
||||||
【使用时选择参数序号即可,R18仅可私聊】
|
|
||||||
搜图 [关键词] [数量](可选) [排序方式](可选) [r18](可选)
|
|
||||||
示例:
|
示例:
|
||||||
搜图 樱岛麻衣
|
搜图 樱岛麻衣
|
||||||
搜图 樱岛麻衣 5 1
|
搜图 樱岛麻衣 5
|
||||||
搜图 樱岛麻衣 5 2 r18
|
搜图 樱岛麻衣 5 r18
|
||||||
【默认为 热度排序】
|
【默认为 热度排序】
|
||||||
【注意空格!!】【在线搜索会较慢】【数量可能不符】
|
【注意空格!!】【在线搜索会较慢】【数量可能不符?可能该页数量不够,也可能被R-18屏蔽】
|
||||||
"""
|
"""
|
||||||
|
|
||||||
rank_dict = {
|
rank_dict = {
|
||||||
@@ -63,142 +58,86 @@ rank_dict = {
|
|||||||
"9": "week_r18g",
|
"9": "week_r18g",
|
||||||
}
|
}
|
||||||
|
|
||||||
_ulmt = UserExistLimiter()
|
|
||||||
|
|
||||||
|
|
||||||
@run_preprocessor
|
|
||||||
async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
|
|
||||||
if isinstance(event, MessageEvent):
|
|
||||||
if matcher.module == "pixiv":
|
|
||||||
if _ulmt.check(event.user_id):
|
|
||||||
if isinstance(event, GroupMessageEvent):
|
|
||||||
await bot.send_group_msg(
|
|
||||||
group_id=event.group_id,
|
|
||||||
message=Message(f"{at(event.user_id)}P站排行榜或搜图正在搜索噢,不要重复触发命令呀"),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await bot.send_private_msg(
|
|
||||||
user_id=event.user_id, message=f"P站排行榜或搜图正在搜索噢,不要重复触发命令呀"
|
|
||||||
)
|
|
||||||
raise IgnoredException("pixiv插件正在访问!")
|
|
||||||
|
|
||||||
|
|
||||||
@run_postprocessor
|
|
||||||
async def do_something(
|
|
||||||
matcher: Matcher,
|
|
||||||
exception: Optional[Exception],
|
|
||||||
bot: Bot,
|
|
||||||
event: Event,
|
|
||||||
state: T_State,
|
|
||||||
):
|
|
||||||
if isinstance(event, MessageEvent):
|
|
||||||
if matcher.module == "pixiv":
|
|
||||||
_ulmt.set_False(event.user_id)
|
|
||||||
|
|
||||||
|
|
||||||
pixiv_rank = on_command(
|
pixiv_rank = on_command(
|
||||||
"p站排行", aliases={"P站排行榜", "p站排行榜", "P站排行榜"}, priority=5, block=True
|
"p站排行", aliases={"P站排行榜", "p站排行榜", "P站排行榜", "P站排行"}, priority=5, block=True, rule=to_me()
|
||||||
)
|
)
|
||||||
pixiv_keyword = on_command("搜图", priority=5, block=True)
|
pixiv_keyword = on_command("搜图", priority=5, block=True, rule=to_me())
|
||||||
|
|
||||||
|
|
||||||
@pixiv_rank.handle()
|
@pixiv_rank.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
msg = get_message_text(event.json()).strip()
|
msg = get_message_text(event.json()).strip()
|
||||||
_ulmt.set_True(event.user_id)
|
|
||||||
msg = msg.split(" ")
|
msg = msg.split(" ")
|
||||||
msg = [m for m in msg if m]
|
msg = [m for m in msg if m]
|
||||||
|
code = 0
|
||||||
|
info_list = []
|
||||||
if not msg:
|
if not msg:
|
||||||
msg = ["1"]
|
msg = ["1"]
|
||||||
if msg[0] in ["6", "7", "8", "9"]:
|
if msg[0] in ["6", "7", "8", "9"]:
|
||||||
if event.message_type == "group":
|
if event.message_type == "group":
|
||||||
await pixiv_rank.finish("羞羞脸!私聊里自己看!", at_sender=True)
|
await pixiv_rank.finish("羞羞脸!私聊里自己看!", at_sender=True)
|
||||||
if len(msg) == 0 or msg[0] == "":
|
if (n := len(msg)) == 0 or msg[0] == "":
|
||||||
text_list, urls, code = await get_pixiv_urls(rank_dict.get("1"))
|
info_list, code = await get_pixiv_urls(rank_dict.get("1"))
|
||||||
elif len(msg) == 1:
|
elif n == 1:
|
||||||
if msg[0] not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
|
if msg[0] not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
|
||||||
await pixiv_rank.finish("要好好输入要看什么类型的排行榜呀!", at_sender=True)
|
await pixiv_rank.finish("要好好输入要看什么类型的排行榜呀!", at_sender=True)
|
||||||
text_list, urls, code = await get_pixiv_urls(rank_dict.get(msg[0]))
|
info_list, code = await get_pixiv_urls(rank_dict.get(msg[0]))
|
||||||
elif len(msg) == 2:
|
elif n == 2:
|
||||||
text_list, urls, code = await get_pixiv_urls(rank_dict.get(msg[0]), int(msg[1]))
|
info_list, code = await get_pixiv_urls(rank_dict.get(msg[0]), int(msg[1]))
|
||||||
elif len(msg) == 3:
|
elif n == 3:
|
||||||
if not check_date(msg[2]):
|
if not check_date(msg[2]):
|
||||||
await pixiv_rank.finish("日期格式错误了", at_sender=True)
|
await pixiv_rank.finish("日期格式错误了", at_sender=True)
|
||||||
text_list, urls, code = await get_pixiv_urls(
|
info_list, code = await get_pixiv_urls(
|
||||||
rank_dict.get(msg[0]), int(msg[1]), msg[2]
|
rank_dict.get(msg[0]), int(msg[1]), date=msg[2]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await pixiv_rank.finish("格式错了噢,看看帮助?", at_sender=True)
|
await pixiv_rank.finish("格式错了噢,参数不够?看看帮助?", at_sender=True)
|
||||||
if code != 200:
|
if code != 200 and info_list:
|
||||||
await pixiv_keyword.finish(text_list[0])
|
await pixiv_rank.finish(info_list[0])
|
||||||
else:
|
if not info_list:
|
||||||
if not text_list or not urls:
|
await pixiv_rank.finish("没有找到啊,等等再试试吧~V", at_sender=True)
|
||||||
await pixiv_rank.finish("没有找到啊,等等再试试吧~V", at_sender=True)
|
await send_image(info_list, pixiv_rank, bot, event)
|
||||||
for i in range(len(text_list)):
|
logger.info(
|
||||||
try:
|
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
await pixiv_rank.send(
|
f" 查看了P站排行榜 code:{msg[0]}"
|
||||||
text_list[i] + await download_pixiv_imgs(urls[i], event.user_id)
|
)
|
||||||
)
|
|
||||||
except (NetworkError, TimeoutError, ClientConnectorError):
|
|
||||||
await pixiv_keyword.send("这张图网络炸了!", at_sender=True)
|
|
||||||
logger.info(
|
|
||||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
|
||||||
f" 查看了P站排行榜 code:{msg[0]}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pixiv_keyword.handle()
|
@pixiv_keyword.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
msg = get_message_text(event.json()).strip()
|
msg = get_message_text(event.json())
|
||||||
_ulmt.set_True(event.user_id)
|
if isinstance(event, GroupMessageEvent):
|
||||||
if event.message_type == "group":
|
if 'r18' in msg.lower():
|
||||||
if msg.find("r18") != -1:
|
|
||||||
await pixiv_keyword.finish("(脸红#) 你不会害羞的 八嘎!", at_sender=True)
|
await pixiv_keyword.finish("(脸红#) 你不会害羞的 八嘎!", at_sender=True)
|
||||||
if msg.find("r18") == -1:
|
r18 = 0 if 'r18' in msg else 1
|
||||||
r18 = 1
|
msg = msg.replace("r18", "").strip().split()
|
||||||
else:
|
msg = [m.strip() for m in msg if m]
|
||||||
r18 = 2
|
keyword = None
|
||||||
msg = msg.replace("r18", "").strip()
|
info_list = None
|
||||||
msg = msg.split(" ")
|
num = 10
|
||||||
msg = [m for m in msg if m]
|
page = 1
|
||||||
if len(msg) == 1:
|
if (n := len(msg)) == 1:
|
||||||
keyword = msg[0].strip()
|
keyword = msg[0]
|
||||||
num = 5
|
if n > 1:
|
||||||
order = "popular"
|
if not is_number(msg[1]):
|
||||||
elif len(msg) == 2:
|
|
||||||
keyword = msg[0].strip()
|
|
||||||
if not is_number(msg[1].strip()):
|
|
||||||
await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
|
await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
|
||||||
num = int(msg[1].strip())
|
num = int(msg[1])
|
||||||
order = "popular"
|
if n > 2:
|
||||||
elif len(msg) == 3:
|
if not is_number(msg[2]):
|
||||||
keyword = msg[0].strip()
|
await pixiv_keyword.finish("页数数量必须是数字!", at_sender=True)
|
||||||
if not is_number(msg[1].strip()):
|
page = int(msg[2])
|
||||||
await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
|
if keyword:
|
||||||
num = int(msg[1].strip())
|
info_list, code = await search_pixiv_urls(keyword, num, page, r18)
|
||||||
if not is_number(msg[2].strip()):
|
if code != 200:
|
||||||
await pixiv_keyword.finish("排序方式必须是数字!", at_sender=True)
|
await pixiv_keyword.finish(info_list[0])
|
||||||
if msg[2].strip() == "1":
|
if not info_list:
|
||||||
order = "popular"
|
await pixiv_keyword.finish("没有找到啊,等等再试试吧~V", at_sender=True)
|
||||||
else:
|
await send_image(info_list, pixiv_keyword, bot, event)
|
||||||
order = "xxx"
|
logger.info(
|
||||||
else:
|
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
await pixiv_keyword.finish("参数不正确,一定要好好看看帮助啊!", at_sender=True)
|
f" 查看了搜索 {keyword} R18:{r18}"
|
||||||
text_list, urls, code = await search_pixiv_urls(keyword, num, order, r18)
|
)
|
||||||
if code != 200:
|
|
||||||
await pixiv_keyword.finish(text_list[0])
|
|
||||||
else:
|
|
||||||
for i in range(len(text_list)):
|
|
||||||
try:
|
|
||||||
await pixiv_keyword.send(
|
|
||||||
text_list[i] + await download_pixiv_imgs(urls[i], event.user_id)
|
|
||||||
)
|
|
||||||
except (NetworkError, TimeoutError, ClientConnectorError):
|
|
||||||
await pixiv_keyword.send("这张图网络炸了!", at_sender=True)
|
|
||||||
logger.info(
|
|
||||||
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
|
|
||||||
f" 查看了搜索 {keyword} R18:{r18}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def check_date(date):
|
def check_date(date):
|
||||||
@@ -207,3 +146,30 @@ def check_date(date):
|
|||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
async def send_image(info_list: list, matcher: Type[Matcher], bot: Bot, event: MessageEvent):
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
await pixiv_rank.send('开始下载整理数据...')
|
||||||
|
idx = 0
|
||||||
|
mes_list = []
|
||||||
|
for title, author, urls in info_list:
|
||||||
|
_message = f'title: {title}\nauthor: {author}\n' + await download_pixiv_imgs(urls, event.user_id, idx)
|
||||||
|
data = {
|
||||||
|
"type": "node",
|
||||||
|
"data": {
|
||||||
|
"name": f"这里是{NICKNAME}酱",
|
||||||
|
"uin": f"{bot.self_id}",
|
||||||
|
"content": _message,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
mes_list.append(data)
|
||||||
|
idx += 1
|
||||||
|
await bot.send_group_forward_msg(group_id=event.group_id, messages=mes_list)
|
||||||
|
else:
|
||||||
|
for title, author, urls in info_list:
|
||||||
|
try:
|
||||||
|
await matcher.send(f'title: {title}\n'
|
||||||
|
f'author: {author}\n' + await download_pixiv_imgs(urls, event.user_id))
|
||||||
|
except (NetworkError, TimeoutError, ClientConnectorError):
|
||||||
|
await matcher.send("这张图网络直接炸掉了!", at_sender=True)
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import aiohttp
|
|
||||||
import aiofiles
|
|
||||||
from configs.path_config import IMAGE_PATH
|
from configs.path_config import IMAGE_PATH
|
||||||
from utils.utils import get_local_proxy
|
from utils.utils import get_local_proxy
|
||||||
from utils.user_agent import get_user_agent
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
import feedparser
|
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
from asyncio.exceptions import TimeoutError
|
from asyncio.exceptions import TimeoutError
|
||||||
from configs.config import RSSHUBAPP
|
from configs.config import HIBIAPI
|
||||||
from aiohttp.client_exceptions import ClientConnectorError
|
from aiohttp.client_exceptions import ClientConnectorError
|
||||||
|
from typing import Optional
|
||||||
|
from pathlib import Path
|
||||||
|
import aiohttp
|
||||||
|
import aiofiles
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
@@ -17,82 +16,115 @@ if platform.system() == "Windows":
|
|||||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||||
|
|
||||||
|
|
||||||
async def get_pixiv_urls(mode: str, num: int = 5, date: str = "") -> "list, list, int":
|
rank_url = f"{HIBIAPI}/api/pixiv/rank"
|
||||||
url = f"{RSSHUBAPP}/pixiv/ranking/{mode}"
|
search_url = f"{HIBIAPI}/api/pixiv/search"
|
||||||
|
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
|
||||||
|
" rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
|
||||||
|
"Referer": "https://www.pixiv.net",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def get_pixiv_urls(
|
||||||
|
mode: str, num: int = 10, page: int = 1, date: Optional[str] = None
|
||||||
|
) -> "list, int":
|
||||||
|
params = {"mode": mode, "page": page}
|
||||||
if date:
|
if date:
|
||||||
url += f"/{date}"
|
params["date"] = date
|
||||||
try:
|
return await parser_data(rank_url, num, params, 'rank')
|
||||||
return await parser_data(url, num)
|
|
||||||
except ClientConnectorError:
|
|
||||||
return await get_pixiv_urls(mode, num, date)
|
|
||||||
|
|
||||||
|
|
||||||
async def download_pixiv_imgs(urls: list, user_id: int) -> str:
|
|
||||||
result = ""
|
|
||||||
index = 0
|
|
||||||
for img in urls:
|
|
||||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
|
||||||
for _ in range(3):
|
|
||||||
async with session.get(
|
|
||||||
img, proxy=get_local_proxy(), timeout=2
|
|
||||||
) as response:
|
|
||||||
async with aiofiles.open(
|
|
||||||
IMAGE_PATH + f"temp/{user_id}_{index}_pixiv.jpg", "wb"
|
|
||||||
) as f:
|
|
||||||
try:
|
|
||||||
await f.write(await response.read())
|
|
||||||
result += image(f"{user_id}_{index}_pixiv.jpg", "temp")
|
|
||||||
index += 1
|
|
||||||
break
|
|
||||||
except TimeoutError:
|
|
||||||
# result += '\n这张图下载失败了..\n'
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
result += "\n这张图下载失败了..\n"
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
async def search_pixiv_urls(
|
async def search_pixiv_urls(
|
||||||
keyword: str, num: int, order: str, r18: int
|
keyword: str, num: int, page: int, r18: int
|
||||||
) -> "list, list":
|
) -> "list, list":
|
||||||
url = f"{RSSHUBAPP}/pixiv/search/{keyword}/{order}/{r18}"
|
params = {"word": keyword, 'page': page}
|
||||||
return await parser_data(url, num)
|
return await parser_data(search_url, num, params, 'search', r18)
|
||||||
|
|
||||||
|
|
||||||
async def parser_data(url: str, num: int) -> "list, list, int":
|
async def parser_data(url: str, num: int, params: dict, type_: str, r18: int = 0) -> "list, int":
|
||||||
text_list = []
|
info_list = []
|
||||||
urls = []
|
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
try:
|
try:
|
||||||
async with session.get(
|
async with session.get(
|
||||||
url, proxy=get_local_proxy(), timeout=2
|
url, params=params, proxy=get_local_proxy(), timeout=5
|
||||||
) as response:
|
) as response:
|
||||||
data = feedparser.parse(await response.text())["entries"]
|
if response.status == 200:
|
||||||
break
|
data = await response.json()
|
||||||
except TimeoutError:
|
if data.get("illusts"):
|
||||||
|
data = data["illusts"]
|
||||||
|
break
|
||||||
|
except (TimeoutError, ClientConnectorError):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return ["网络不太好,也许过一会就好了"], [], 998
|
return ["网络不太好?没有该页数?也许过一会就好了..."], 998
|
||||||
try:
|
num = num if num < 30 else 30
|
||||||
if len(data) == 0:
|
data = data[:num]
|
||||||
return ["没有搜索到喔"], [], 997
|
for x in data:
|
||||||
if num > len(data):
|
if type_ == 'search' and r18 == 1:
|
||||||
num = len(data)
|
if 'R-18' in str(x['tags']):
|
||||||
data = data[:num]
|
continue
|
||||||
for data in data:
|
title = x["title"]
|
||||||
soup = BeautifulSoup(data["summary"], "lxml")
|
author = x["user"]["name"]
|
||||||
title = "标题:" + data["title"]
|
urls = []
|
||||||
pl = soup.find_all("p")
|
if x["page_count"] == 1:
|
||||||
author = pl[0].text.split("-")[0].strip()
|
urls.append(x["image_urls"]["large"])
|
||||||
imgs = []
|
else:
|
||||||
text_list.append(f"{title}\n{author}\n")
|
for j in x["meta_pages"]:
|
||||||
for p in pl[1:]:
|
urls.append(j["image_urls"]["large"])
|
||||||
imgs.append(p.find("img").get("src"))
|
info_list.append((title, author, urls))
|
||||||
urls.append(imgs)
|
return info_list, 200
|
||||||
except ValueError:
|
|
||||||
return ["是网站坏了啊,也许过一会就好了"], [], 999
|
|
||||||
return text_list, urls, 200
|
|
||||||
|
|
||||||
|
|
||||||
# asyncio.get_event_loop().run_until_complete(get_pixiv_urls('day'))
|
async def download_pixiv_imgs(
|
||||||
|
urls: list, user_id: int, forward_msg_index: int = None
|
||||||
|
) -> str:
|
||||||
|
result = ""
|
||||||
|
index = 0
|
||||||
|
for url in urls:
|
||||||
|
async with aiohttp.ClientSession(headers=headers) as session:
|
||||||
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
async with session.get(
|
||||||
|
url, proxy=get_local_proxy(), timeout=3
|
||||||
|
) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
try:
|
||||||
|
file = (
|
||||||
|
f"{IMAGE_PATH}/temp/{user_id}_{forward_msg_index}_{index}_pixiv.jpg"
|
||||||
|
if forward_msg_index is not None
|
||||||
|
else f"{IMAGE_PATH}/temp/{user_id}_{index}_pixiv.jpg"
|
||||||
|
)
|
||||||
|
file = Path(file)
|
||||||
|
if forward_msg_index is not None:
|
||||||
|
async with aiofiles.open(
|
||||||
|
file,
|
||||||
|
"wb",
|
||||||
|
) as f:
|
||||||
|
await f.write(await response.read())
|
||||||
|
result += image(
|
||||||
|
f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg",
|
||||||
|
"temp",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
async with aiofiles.open(
|
||||||
|
file,
|
||||||
|
"wb",
|
||||||
|
) as f:
|
||||||
|
await f.write(await response.read())
|
||||||
|
result += image(
|
||||||
|
f"{user_id}_{index}_pixiv.jpg", "temp"
|
||||||
|
)
|
||||||
|
index += 1
|
||||||
|
break
|
||||||
|
except OSError:
|
||||||
|
file.unlink()
|
||||||
|
except (TimeoutError, ClientConnectorError):
|
||||||
|
# result += '\n这张图下载失败了..\n'
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
result += "\n这张图下载失败了..\n"
|
||||||
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
|||||||
await reimu.finish("今天已经没车了,请明天再来...", at_sender=True)
|
await reimu.finish("今天已经没车了,请明天再来...", at_sender=True)
|
||||||
if _ulmt.check(event.user_id):
|
if _ulmt.check(event.user_id):
|
||||||
await reimu.finish("您还没下车呢,请稍等...", at_sender=True)
|
await reimu.finish("您还没下车呢,请稍等...", at_sender=True)
|
||||||
_ulmt.set_True(event.user_id)
|
_ulmt.set_true(event.user_id)
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
args = msg.split(" ")
|
args = msg.split(" ")
|
||||||
if msg in ["!", "!", "?", "?", ",", ",", ".", "。"]:
|
if msg in ["!", "!", "?", "?", ",", ",", ".", "。"]:
|
||||||
@@ -70,9 +70,9 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
|||||||
else:
|
else:
|
||||||
logger.error("Not found reimuInfo")
|
logger.error("Not found reimuInfo")
|
||||||
await reimu.send("没找着")
|
await reimu.send("没找着")
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
except:
|
except:
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
|
|
||||||
|
|
||||||
@scheduler.scheduled_job(
|
@scheduler.scheduled_job(
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import time
|
|||||||
from .data_source import rank
|
from .data_source import rank
|
||||||
from configs.config import MAX_RUSSIAN_BET_GOLD, NICKNAME
|
from configs.config import MAX_RUSSIAN_BET_GOLD, NICKNAME
|
||||||
|
|
||||||
__plugin_name__ = '俄罗斯轮盘'
|
__plugin_name__ = "俄罗斯轮盘"
|
||||||
|
|
||||||
__plugin_usage__ = '''俄罗斯轮盘帮助:
|
__plugin_usage__ = """俄罗斯轮盘帮助:
|
||||||
开启游戏:装弹 [子弹数] [金额](默认200金币) [at](指定决斗对象,为空则所有群友都可接受决斗)
|
开启游戏:装弹 [子弹数] [金额](默认200金币) [at](指定决斗对象,为空则所有群友都可接受决斗)
|
||||||
示例:装弹 1 10
|
示例:装弹 1 10
|
||||||
接受对决:接受对决/拒绝决斗
|
接受对决:接受对决/拒绝决斗
|
||||||
@@ -24,24 +24,37 @@ __plugin_usage__ = '''俄罗斯轮盘帮助:
|
|||||||
我的战绩:我的战绩
|
我的战绩:我的战绩
|
||||||
排行榜:胜场排行/败场排行/欧洲人排行/慈善家排行
|
排行榜:胜场排行/败场排行/欧洲人排行/慈善家排行
|
||||||
【注:同一时间群内只能有一场对决】
|
【注:同一时间群内只能有一场对决】
|
||||||
'''
|
"""
|
||||||
|
|
||||||
rs_player = {}
|
rs_player = {}
|
||||||
|
|
||||||
rssian = on_command('俄罗斯轮盘', aliases={'装弹', '俄罗斯转盘'}, permission=GROUP, priority=5, block=True)
|
rssian = on_command(
|
||||||
|
"俄罗斯轮盘", aliases={"装弹", "俄罗斯转盘"}, permission=GROUP, priority=5, block=True
|
||||||
|
)
|
||||||
|
|
||||||
accept = on_command('接受对决', aliases={'接受决斗', '接受挑战'}, permission=GROUP, priority=5, block=True)
|
accept = on_command(
|
||||||
|
"接受对决", aliases={"接受决斗", "接受挑战"}, permission=GROUP, priority=5, block=True
|
||||||
|
)
|
||||||
|
|
||||||
refuse = on_command('拒绝对决', aliases={'拒绝决斗', '拒绝挑战'}, permission=GROUP, priority=5, block=True)
|
refuse = on_command(
|
||||||
|
"拒绝对决", aliases={"拒绝决斗", "拒绝挑战"}, permission=GROUP, priority=5, block=True
|
||||||
|
)
|
||||||
|
|
||||||
shot = on_command('开枪', aliases={'咔', '嘭', '嘣'}, permission=GROUP, priority=5, block=True)
|
shot = on_command(
|
||||||
|
"开枪", aliases={"咔", "嘭", "嘣"}, permission=GROUP, priority=5, block=True
|
||||||
|
)
|
||||||
|
|
||||||
settlement = on_command('结算', permission=GROUP, priority=5, block=True)
|
settlement = on_command("结算", permission=GROUP, priority=5, block=True)
|
||||||
|
|
||||||
record = on_command('我的战绩', permission=GROUP, priority=5, block=True)
|
record = on_command("我的战绩", permission=GROUP, priority=5, block=True)
|
||||||
|
|
||||||
rssian_rank = on_command('胜场排行', aliases={'胜利排行', '败场排行', '失败排行',
|
rssian_rank = on_command(
|
||||||
'欧洲人排行', '慈善家排行'}, permission=GROUP, priority=5, block=True)
|
"胜场排行",
|
||||||
|
aliases={"胜利排行", "败场排行", "失败排行", "欧洲人排行", "慈善家排行", "最高连胜排行", "最高连败排行"},
|
||||||
|
permission=GROUP,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@accept.handle()
|
@accept.handle()
|
||||||
@@ -49,38 +62,51 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
global rs_player
|
global rs_player
|
||||||
try:
|
try:
|
||||||
if rs_player[event.group_id][1] == 0:
|
if rs_player[event.group_id][1] == 0:
|
||||||
await accept.finish('目前没有发起对决,你接受个啥?速速装弹!', at_sender=True)
|
await accept.finish("目前没有发起对决,你接受个啥?速速装弹!", at_sender=True)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
await accept.finish('目前没有进行的决斗,请发送 装弹 开启决斗吧!', at_sender=True)
|
await accept.finish("目前没有进行的决斗,请发送 装弹 开启决斗吧!", at_sender=True)
|
||||||
if rs_player[event.group_id][2] != 0:
|
if rs_player[event.group_id][2] != 0:
|
||||||
if rs_player[event.group_id][1] == event.user_id or rs_player[event.group_id][2] == event.user_id:
|
if (
|
||||||
await accept.finish(f'你已经身处决斗之中了啊,给我认真一点啊!', at_sender=True)
|
rs_player[event.group_id][1] == event.user_id
|
||||||
|
or rs_player[event.group_id][2] == event.user_id
|
||||||
|
):
|
||||||
|
await accept.finish(f"你已经身处决斗之中了啊,给我认真一点啊!", at_sender=True)
|
||||||
else:
|
else:
|
||||||
await accept.finish('已经有人接受对决了,你还是乖乖等待下一场吧!', at_sender=True)
|
await accept.finish("已经有人接受对决了,你还是乖乖等待下一场吧!", at_sender=True)
|
||||||
if rs_player[event.group_id][1] == event.user_id:
|
if rs_player[event.group_id][1] == event.user_id:
|
||||||
await accept.finish('请不要自己枪毙自己!换人来接受对决...', at_sender=True)
|
await accept.finish("请不要自己枪毙自己!换人来接受对决...", at_sender=True)
|
||||||
if rs_player[event.group_id]['at'] != 0 and rs_player[event.group_id]['at'] != event.user_id:
|
if (
|
||||||
await accept.finish(Message(f'这场对决是邀请 {at(rs_player[event.group_id]["at"])}的,不要捣乱!'), at_sender=True)
|
rs_player[event.group_id]["at"] != 0
|
||||||
if time.time() - rs_player[event.group_id]['time'] > 30:
|
and rs_player[event.group_id]["at"] != event.user_id
|
||||||
|
):
|
||||||
|
await accept.finish(
|
||||||
|
Message(f'这场对决是邀请 {at(rs_player[event.group_id]["at"])}的,不要捣乱!'),
|
||||||
|
at_sender=True,
|
||||||
|
)
|
||||||
|
if time.time() - rs_player[event.group_id]["time"] > 30:
|
||||||
rs_player[event.group_id] = {}
|
rs_player[event.group_id] = {}
|
||||||
await accept.finish('这场对决邀请已经过时了,请重新发起决斗...', at_sender=True)
|
await accept.finish("这场对决邀请已经过时了,请重新发起决斗...", at_sender=True)
|
||||||
|
|
||||||
user_money = await BagUser.get_gold(event.user_id, event.group_id)
|
user_money = await BagUser.get_gold(event.user_id, event.group_id)
|
||||||
if user_money < rs_player[event.group_id]['money']:
|
if user_money < rs_player[event.group_id]["money"]:
|
||||||
if rs_player[event.group_id]['at'] != 0 and rs_player[event.group_id]['at'] == event.user_id:
|
if (
|
||||||
|
rs_player[event.group_id]["at"] != 0
|
||||||
|
and rs_player[event.group_id]["at"] == event.user_id
|
||||||
|
):
|
||||||
rs_player[event.group_id] = {}
|
rs_player[event.group_id] = {}
|
||||||
await accept.finish('你的金币不足以接受这场对决!对决还未开始便结束了,请重新装弹!', at_sender=True)
|
await accept.finish("你的金币不足以接受这场对决!对决还未开始便结束了,请重新装弹!", at_sender=True)
|
||||||
else:
|
else:
|
||||||
await accept.finish('你的金币不足以接受这场对决!', at_sender=True)
|
await accept.finish("你的金币不足以接受这场对决!", at_sender=True)
|
||||||
|
|
||||||
player2_name = event.sender.card if event.sender.card else event.sender.nickname
|
player2_name = event.sender.card if event.sender.card else event.sender.nickname
|
||||||
|
|
||||||
rs_player[event.group_id][2] = event.user_id
|
rs_player[event.group_id][2] = event.user_id
|
||||||
rs_player[event.group_id]['player2'] = player2_name
|
rs_player[event.group_id]["player2"] = player2_name
|
||||||
rs_player[event.group_id]['time'] = time.time()
|
rs_player[event.group_id]["time"] = time.time()
|
||||||
|
|
||||||
await accept.send(Message(f'{player2_name}接受了对决!\n'
|
await accept.send(
|
||||||
f'请{at(rs_player[event.group_id][1])}先开枪!'))
|
Message(f"{player2_name}接受了对决!\n" f"请{at(rs_player[event.group_id][1])}先开枪!")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@refuse.handle()
|
@refuse.handle()
|
||||||
@@ -88,74 +114,107 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
global rs_player
|
global rs_player
|
||||||
try:
|
try:
|
||||||
if rs_player[event.group_id][1] == 0:
|
if rs_player[event.group_id][1] == 0:
|
||||||
await accept.finish('你要拒绝啥?明明都没有人发起对决的说!', at_sender=True)
|
await accept.finish("你要拒绝啥?明明都没有人发起对决的说!", at_sender=True)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
await refuse.finish('目前没有进行的决斗,请发送 装弹 开启决斗吧!', at_sender=True)
|
await refuse.finish("目前没有进行的决斗,请发送 装弹 开启决斗吧!", at_sender=True)
|
||||||
if rs_player[event.group_id]['at'] != 0 and event.user_id != rs_player[event.group_id]['at']:
|
if (
|
||||||
await accept.finish('又不是找你决斗,你拒绝什么啊!气!', at_sender=True)
|
rs_player[event.group_id]["at"] != 0
|
||||||
if rs_player[event.group_id]['at'] == event.user_id:
|
and event.user_id != rs_player[event.group_id]["at"]
|
||||||
at_player_name = (await GroupInfoUser.get_member_info(event.user_id, event.group_id)).user_name
|
):
|
||||||
await accept.send(Message(f'{at(rs_player[event.group_id][1])}\n'
|
await accept.finish("又不是找你决斗,你拒绝什么啊!气!", at_sender=True)
|
||||||
f'{at_player_name}拒绝了你的对决!'))
|
if rs_player[event.group_id]["at"] == event.user_id:
|
||||||
|
at_player_name = (
|
||||||
|
await GroupInfoUser.get_member_info(event.user_id, event.group_id)
|
||||||
|
).user_name
|
||||||
|
await accept.send(
|
||||||
|
Message(f"{at(rs_player[event.group_id][1])}\n" f"{at_player_name}拒绝了你的对决!")
|
||||||
|
)
|
||||||
rs_player[event.group_id] = {}
|
rs_player[event.group_id] = {}
|
||||||
|
|
||||||
|
|
||||||
@settlement.handle()
|
@settlement.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
global rs_player
|
global rs_player
|
||||||
if not rs_player.get(event.group_id) or rs_player[event.group_id][1] == 0 or rs_player[event.group_id][2] == 0:
|
if (
|
||||||
await settlement.finish('比赛并没有开始...无法结算...', at_sender=True)
|
not rs_player.get(event.group_id)
|
||||||
if event.user_id != rs_player[event.group_id][1] and event.user_id != rs_player[event.group_id][2]:
|
or rs_player[event.group_id][1] == 0
|
||||||
await settlement.finish('吃瓜群众不要捣乱!黄牌警告!', at_sender=True)
|
or rs_player[event.group_id][2] == 0
|
||||||
if time.time() - rs_player[event.group_id]['time'] <= 30:
|
):
|
||||||
await settlement.finish(f'{rs_player[event.group_id]["player1"]} 和'
|
await settlement.finish("比赛并没有开始...无法结算...", at_sender=True)
|
||||||
f' {rs_player[event.group_id]["player2"]} 比赛并未超时,请继续比赛...')
|
if (
|
||||||
win_name = rs_player[event.group_id]["player1"] if \
|
event.user_id != rs_player[event.group_id][1]
|
||||||
rs_player[event.group_id][2] == rs_player[event.group_id]['next'] else \
|
and event.user_id != rs_player[event.group_id][2]
|
||||||
rs_player[event.group_id]["player2"]
|
):
|
||||||
await settlement.send(f'这场对决是 {win_name} 胜利了')
|
await settlement.finish("吃瓜群众不要捣乱!黄牌警告!", at_sender=True)
|
||||||
|
if time.time() - rs_player[event.group_id]["time"] <= 30:
|
||||||
|
await settlement.finish(
|
||||||
|
f'{rs_player[event.group_id]["player1"]} 和'
|
||||||
|
f' {rs_player[event.group_id]["player2"]} 比赛并未超时,请继续比赛...'
|
||||||
|
)
|
||||||
|
win_name = (
|
||||||
|
rs_player[event.group_id]["player1"]
|
||||||
|
if rs_player[event.group_id][2] == rs_player[event.group_id]["next"]
|
||||||
|
else rs_player[event.group_id]["player2"]
|
||||||
|
)
|
||||||
|
await settlement.send(f"这场对决是 {win_name} 胜利了")
|
||||||
await end_game(bot, event)
|
await end_game(bot, event)
|
||||||
|
|
||||||
|
|
||||||
@rssian.args_parser
|
@rssian.args_parser
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
if msg in ['取消', '算了']:
|
if msg in ["取消", "算了"]:
|
||||||
await rssian.finish('已取消操作...')
|
await rssian.finish("已取消操作...")
|
||||||
try:
|
try:
|
||||||
if rs_player[event.group_id][1] != 0:
|
if rs_player[event.group_id][1] != 0:
|
||||||
await rssian.finish('决斗已开始...', at_sender=True)
|
await rssian.finish("决斗已开始...", at_sender=True)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
if not is_number(msg):
|
if not is_number(msg):
|
||||||
await rssian.reject('输入子弹数量必须是数字啊喂!')
|
await rssian.reject("输入子弹数量必须是数字啊喂!")
|
||||||
if int(msg) < 1 or int(msg) > 6:
|
if int(msg) < 1 or int(msg) > 6:
|
||||||
await rssian.reject('子弹数量必须大于0小于7!')
|
await rssian.reject("子弹数量必须大于0小于7!")
|
||||||
state['bullet_num'] = int(msg)
|
state["bullet_num"] = int(msg)
|
||||||
|
|
||||||
|
|
||||||
@rssian.handle()
|
@rssian.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
global rs_player
|
global rs_player
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
if msg == '帮助':
|
if msg == "帮助":
|
||||||
await rssian.finish(__plugin_usage__)
|
await rssian.finish(__plugin_usage__)
|
||||||
try:
|
try:
|
||||||
if rs_player[event.group_id][1] and not rs_player[event.group_id][2] and \
|
if (
|
||||||
time.time() - rs_player[event.group_id]['time'] <= 30:
|
rs_player[event.group_id][1]
|
||||||
await rssian.finish(f'现在是 {rs_player[event.group_id]["player1"]} 发起的对决\n请等待比赛结束后再开始下一轮...')
|
and not rs_player[event.group_id][2]
|
||||||
if rs_player[event.group_id][1] and rs_player[event.group_id][2] and\
|
and time.time() - rs_player[event.group_id]["time"] <= 30
|
||||||
time.time() - rs_player[event.group_id]['time'] <= 30:
|
):
|
||||||
await rssian.finish(f'{rs_player[event.group_id]["player1"]} 和'
|
await rssian.finish(
|
||||||
f' {rs_player[event.group_id]["player2"]}的对决还未结束!')
|
f'现在是 {rs_player[event.group_id]["player1"]} 发起的对决\n请等待比赛结束后再开始下一轮...'
|
||||||
if rs_player[event.group_id][1] and rs_player[event.group_id][2] and\
|
)
|
||||||
time.time() - rs_player[event.group_id]['time'] > 30:
|
if (
|
||||||
await shot.send('决斗已过时,强行结算...')
|
rs_player[event.group_id][1]
|
||||||
|
and rs_player[event.group_id][2]
|
||||||
|
and time.time() - rs_player[event.group_id]["time"] <= 30
|
||||||
|
):
|
||||||
|
await rssian.finish(
|
||||||
|
f'{rs_player[event.group_id]["player1"]} 和'
|
||||||
|
f' {rs_player[event.group_id]["player2"]}的对决还未结束!'
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
rs_player[event.group_id][1]
|
||||||
|
and rs_player[event.group_id][2]
|
||||||
|
and time.time() - rs_player[event.group_id]["time"] > 30
|
||||||
|
):
|
||||||
|
await shot.send("决斗已过时,强行结算...")
|
||||||
await end_game(bot, event)
|
await end_game(bot, event)
|
||||||
if not rs_player[event.group_id][2] and time.time() - rs_player[event.group_id]['time'] > 30:
|
if (
|
||||||
|
not rs_player[event.group_id][2]
|
||||||
|
and time.time() - rs_player[event.group_id]["time"] > 30
|
||||||
|
):
|
||||||
rs_player[event.group_id][1] = 0
|
rs_player[event.group_id][1] = 0
|
||||||
rs_player[event.group_id][2] = 0
|
rs_player[event.group_id][2] = 0
|
||||||
rs_player[event.group_id]['at'] = 0
|
rs_player[event.group_id]["at"] = 0
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
if msg:
|
if msg:
|
||||||
@@ -163,126 +222,167 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
if len(msg) == 1:
|
if len(msg) == 1:
|
||||||
msg = msg[0]
|
msg = msg[0]
|
||||||
if is_number(msg) and not (int(msg) < 1 or int(msg) > 6):
|
if is_number(msg) and not (int(msg) < 1 or int(msg) > 6):
|
||||||
state['bullet_num'] = int(msg)
|
state["bullet_num"] = int(msg)
|
||||||
else:
|
else:
|
||||||
money = msg[1].strip()
|
money = msg[1].strip()
|
||||||
msg = msg[0].strip()
|
msg = msg[0].strip()
|
||||||
if is_number(msg) and not (int(msg) < 1 or int(msg) > 6):
|
if is_number(msg) and not (int(msg) < 1 or int(msg) > 6):
|
||||||
state['bullet_num'] = int(msg)
|
state["bullet_num"] = int(msg)
|
||||||
if is_number(money) and 0 < int(money) <= MAX_RUSSIAN_BET_GOLD:
|
if is_number(money) and 0 < int(money) <= MAX_RUSSIAN_BET_GOLD:
|
||||||
state['money'] = int(money)
|
state["money"] = int(money)
|
||||||
else:
|
else:
|
||||||
state['money'] = 200
|
state["money"] = 200
|
||||||
await rssian.send(f'赌注金额超过限制(MAX_RUSSIAN_BET_GOLD),已改为200(默认)')
|
await rssian.send(f"赌注金额超过限制(MAX_RUSSIAN_BET_GOLD),已改为200(默认)")
|
||||||
state['at'] = get_message_at(event.json())
|
state["at"] = get_message_at(event.json())
|
||||||
|
|
||||||
|
|
||||||
@rssian.got("bullet_num", prompt='请输入装填子弹的数量!(最多6颗)')
|
@rssian.got("bullet_num", prompt="请输入装填子弹的数量!(最多6颗)")
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
global rs_player
|
global rs_player
|
||||||
bullet_num = state['bullet_num']
|
bullet_num = state["bullet_num"]
|
||||||
at_ = state['at'] if state.get('at') else []
|
at_ = state["at"] if state.get("at") else []
|
||||||
money = state['money'] if state.get('money') else 200
|
money = state["money"] if state.get("money") else 200
|
||||||
user_money = await BagUser.get_gold(event.user_id, event.group_id)
|
user_money = await BagUser.get_gold(event.user_id, event.group_id)
|
||||||
if bullet_num < 0 or bullet_num > 6:
|
if bullet_num < 0 or bullet_num > 6:
|
||||||
await rssian.reject('子弹数量必须大于0小于7!速速重新装弹!')
|
await rssian.reject("子弹数量必须大于0小于7!速速重新装弹!")
|
||||||
if money > MAX_RUSSIAN_BET_GOLD:
|
if money > MAX_RUSSIAN_BET_GOLD:
|
||||||
await rssian.finish(f'太多了!单次金额不能超过{MAX_RUSSIAN_BET_GOLD}!', at_sender=True)
|
await rssian.finish(f"太多了!单次金额不能超过{MAX_RUSSIAN_BET_GOLD}!", at_sender=True)
|
||||||
if money > user_money:
|
if money > user_money:
|
||||||
await rssian.finish('你没有足够的钱支撑起这场挑战', at_sender=True)
|
await rssian.finish("你没有足够的钱支撑起这场挑战", at_sender=True)
|
||||||
|
|
||||||
player1_name = event.sender.card if event.sender.card else event.sender.nickname
|
player1_name = event.sender.card if event.sender.card else event.sender.nickname
|
||||||
|
|
||||||
if at_:
|
if at_:
|
||||||
at_ = at_[0]
|
at_ = at_[0]
|
||||||
try:
|
try:
|
||||||
at_player_name = (await GroupInfoUser.get_member_info(at_, event.group_id)).user_name
|
at_player_name = (
|
||||||
|
await GroupInfoUser.get_member_info(at_, event.group_id)
|
||||||
|
).user_name
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
at_player_name = at(at_)
|
at_player_name = at(at_)
|
||||||
msg = f'{player1_name} 向 {at(at_)} 发起了决斗!请 {at_player_name} 在30秒内回复‘接受对决’ or ‘拒绝对决’,超时此次决斗作废!'
|
msg = f"{player1_name} 向 {at(at_)} 发起了决斗!请 {at_player_name} 在30秒内回复‘接受对决’ or ‘拒绝对决’,超时此次决斗作废!"
|
||||||
else:
|
else:
|
||||||
at_ = 0
|
at_ = 0
|
||||||
msg = '若30秒内无人接受挑战则此次对决作废【首次游玩请发送 ’俄罗斯轮盘帮助‘ 来查看命令】'
|
msg = "若30秒内无人接受挑战则此次对决作废【首次游玩请发送 ’俄罗斯轮盘帮助‘ 来查看命令】"
|
||||||
|
|
||||||
rs_player[event.group_id] = {1: event.user_id,
|
rs_player[event.group_id] = {
|
||||||
'player1': player1_name,
|
1: event.user_id,
|
||||||
2: 0,
|
"player1": player1_name,
|
||||||
'player2': '',
|
2: 0,
|
||||||
'at': at_,
|
"player2": "",
|
||||||
'next': event.user_id,
|
"at": at_,
|
||||||
'money': money,
|
"next": event.user_id,
|
||||||
'bullet': random_bullet(bullet_num),
|
"money": money,
|
||||||
'bullet_num': bullet_num,
|
"bullet": random_bullet(bullet_num),
|
||||||
'null_bullet_num': 7 - bullet_num,
|
"bullet_num": bullet_num,
|
||||||
'index': 0,
|
"null_bullet_num": 7 - bullet_num,
|
||||||
'time': time.time()}
|
"index": 0,
|
||||||
|
"time": time.time(),
|
||||||
|
}
|
||||||
|
|
||||||
await rssian.send(Message(('咔 ' * bullet_num)[:-1] + f',装填完毕\n挑战金额:{money}\n'
|
await rssian.send(
|
||||||
f'第一枪的概率为:{str(float(bullet_num) / 7.0 * 100)[:5]}%\n'
|
Message(
|
||||||
f'{msg}'))
|
("咔 " * bullet_num)[:-1] + f",装填完毕\n挑战金额:{money}\n"
|
||||||
|
f"第一枪的概率为:{str(float(bullet_num) / 7.0 * 100)[:5]}%\n"
|
||||||
|
f"{msg}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@shot.handle()
|
@shot.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
global rs_player
|
global rs_player
|
||||||
try:
|
try:
|
||||||
if time.time() - rs_player[event.group_id]['time'] > 30:
|
if time.time() - rs_player[event.group_id]["time"] > 30:
|
||||||
if rs_player[event.group_id][2] == 0:
|
if rs_player[event.group_id][2] == 0:
|
||||||
rs_player[event.group_id][1] = 0
|
rs_player[event.group_id][1] = 0
|
||||||
await shot.finish('这场对决已经过时了,请重新装弹吧!', at_sender=True)
|
await shot.finish("这场对决已经过时了,请重新装弹吧!", at_sender=True)
|
||||||
else:
|
else:
|
||||||
await shot.send('决斗已过时,强行结算...')
|
await shot.send("决斗已过时,强行结算...")
|
||||||
await end_game(bot, event)
|
await end_game(bot, event)
|
||||||
return
|
return
|
||||||
except KeyError:
|
except KeyError:
|
||||||
await shot.finish('目前没有进行的决斗,请发送 装弹 开启决斗吧!', at_sender=True)
|
await shot.finish("目前没有进行的决斗,请发送 装弹 开启决斗吧!", at_sender=True)
|
||||||
if rs_player[event.group_id][1] == 0:
|
if rs_player[event.group_id][1] == 0:
|
||||||
await shot.finish('没有对决,也还没装弹呢,请先输入 装弹 吧!', at_sender=True)
|
await shot.finish("没有对决,也还没装弹呢,请先输入 装弹 吧!", at_sender=True)
|
||||||
if rs_player[event.group_id][1] == event.user_id and rs_player[event.group_id][2] == 0:
|
if (
|
||||||
await shot.finish('baka,你是要枪毙自己嘛笨蛋!', at_sender=True)
|
rs_player[event.group_id][1] == event.user_id
|
||||||
|
and rs_player[event.group_id][2] == 0
|
||||||
|
):
|
||||||
|
await shot.finish("baka,你是要枪毙自己嘛笨蛋!", at_sender=True)
|
||||||
if rs_player[event.group_id][2] == 0:
|
if rs_player[event.group_id][2] == 0:
|
||||||
await shot.finish('请这位勇士先发送 接受对决 来站上擂台...', at_sender=True)
|
await shot.finish("请这位勇士先发送 接受对决 来站上擂台...", at_sender=True)
|
||||||
player1_name = rs_player[event.group_id]['player1']
|
player1_name = rs_player[event.group_id]["player1"]
|
||||||
player2_name = rs_player[event.group_id]['player2']
|
player2_name = rs_player[event.group_id]["player2"]
|
||||||
if rs_player[event.group_id]['next'] != event.user_id:
|
if rs_player[event.group_id]["next"] != event.user_id:
|
||||||
if event.user_id != rs_player[event.group_id][1] and event.user_id != rs_player[event.group_id][2]:
|
if (
|
||||||
await shot.finish(random.choice([
|
event.user_id != rs_player[event.group_id][1]
|
||||||
f'不要打扰 {player1_name} 和 {player2_name} 的决斗啊!',
|
and event.user_id != rs_player[event.group_id][2]
|
||||||
f'给我好好做好一个观众!不然{NICKNAME}就要生气了',
|
):
|
||||||
f'不要捣乱啊baka{(await GroupInfoUser.get_member_info(event.user_id, event.group_id)).user_name}!'
|
await shot.finish(
|
||||||
]), at_sender=True)
|
random.choice(
|
||||||
await shot.finish(f'你的左轮不是连发的!该 '
|
[
|
||||||
f'{(await GroupInfoUser.get_member_info(int(rs_player[event.group_id]["next"]), event.group_id)).user_name} 开枪了')
|
f"不要打扰 {player1_name} 和 {player2_name} 的决斗啊!",
|
||||||
if rs_player[event.group_id]['bullet'][rs_player[event.group_id]['index']] != 1:
|
f"给我好好做好一个观众!不然{NICKNAME}就要生气了",
|
||||||
await shot.send(Message(random.choice([
|
f"不要捣乱啊baka{(await GroupInfoUser.get_member_info(event.user_id, event.group_id)).user_name}!",
|
||||||
'呼呼,没有爆裂的声响,你活了下来',
|
]
|
||||||
'虽然黑洞洞的枪口很恐怖,但好在没有子弹射出来,你活下来了',
|
),
|
||||||
'\"咔\",你没死,看来运气不错',
|
at_sender=True,
|
||||||
]) + f'\n下一枪中弹的概率'
|
)
|
||||||
f':{str(float((rs_player[event.group_id]["bullet_num"])) / float(rs_player[event.group_id]["null_bullet_num"] - 1 + rs_player[event.group_id]["bullet_num"]) * 100)[:5]}%\n'
|
await shot.finish(
|
||||||
f'轮到 {at(rs_player[event.group_id][1] if event.user_id == rs_player[event.group_id][2] else rs_player[event.group_id][2])}了'))
|
f"你的左轮不是连发的!该 "
|
||||||
|
f'{(await GroupInfoUser.get_member_info(int(rs_player[event.group_id]["next"]), event.group_id)).user_name} 开枪了'
|
||||||
|
)
|
||||||
|
if rs_player[event.group_id]["bullet"][rs_player[event.group_id]["index"]] != 1:
|
||||||
|
await shot.send(
|
||||||
|
Message(
|
||||||
|
random.choice(
|
||||||
|
[
|
||||||
|
"呼呼,没有爆裂的声响,你活了下来",
|
||||||
|
"虽然黑洞洞的枪口很恐怖,但好在没有子弹射出来,你活下来了",
|
||||||
|
'"咔",你没死,看来运气不错',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+ f"\n下一枪中弹的概率"
|
||||||
|
f':{str(float((rs_player[event.group_id]["bullet_num"])) / float(rs_player[event.group_id]["null_bullet_num"] - 1 + rs_player[event.group_id]["bullet_num"]) * 100)[:5]}%\n'
|
||||||
|
f"轮到 {at(rs_player[event.group_id][1] if event.user_id == rs_player[event.group_id][2] else rs_player[event.group_id][2])}了"
|
||||||
|
)
|
||||||
|
)
|
||||||
rs_player[event.group_id]["null_bullet_num"] -= 1
|
rs_player[event.group_id]["null_bullet_num"] -= 1
|
||||||
rs_player[event.group_id]['next'] = rs_player[event.group_id][1] if \
|
rs_player[event.group_id]["next"] = (
|
||||||
event.user_id == rs_player[event.group_id][2] else rs_player[event.group_id][2]
|
rs_player[event.group_id][1]
|
||||||
rs_player[event.group_id]['time'] = time.time()
|
if event.user_id == rs_player[event.group_id][2]
|
||||||
rs_player[event.group_id]['index'] += 1
|
else rs_player[event.group_id][2]
|
||||||
|
)
|
||||||
|
rs_player[event.group_id]["time"] = time.time()
|
||||||
|
rs_player[event.group_id]["index"] += 1
|
||||||
else:
|
else:
|
||||||
await shot.send(random.choice([
|
await shot.send(
|
||||||
'\"嘭!\",你直接去世了',
|
random.choice(
|
||||||
'眼前一黑,你直接穿越到了异世界...(死亡)',
|
[
|
||||||
'终究还是你先走一步...',
|
'"嘭!",你直接去世了',
|
||||||
]) + f'\n第 {rs_player[event.group_id]["index"] + 1} 发子弹送走了你...', at_sender=True)
|
"眼前一黑,你直接穿越到了异世界...(死亡)",
|
||||||
win_name = player1_name if event.user_id == rs_player[event.group_id][2] else player2_name
|
"终究还是你先走一步...",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+ f'\n第 {rs_player[event.group_id]["index"] + 1} 发子弹送走了你...',
|
||||||
|
at_sender=True,
|
||||||
|
)
|
||||||
|
win_name = (
|
||||||
|
player1_name
|
||||||
|
if event.user_id == rs_player[event.group_id][2]
|
||||||
|
else player2_name
|
||||||
|
)
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
await shot.send(f'这场对决是 {win_name} 胜利了')
|
await shot.send(f"这场对决是 {win_name} 胜利了")
|
||||||
await end_game(bot, event)
|
await end_game(bot, event)
|
||||||
|
|
||||||
|
|
||||||
async def end_game(bot: Bot, event: GroupMessageEvent):
|
async def end_game(bot: Bot, event: GroupMessageEvent):
|
||||||
global rs_player
|
global rs_player
|
||||||
player1_name = rs_player[event.group_id]['player1']
|
player1_name = rs_player[event.group_id]["player1"]
|
||||||
player2_name = rs_player[event.group_id]['player2']
|
player2_name = rs_player[event.group_id]["player2"]
|
||||||
if rs_player[event.group_id]['next'] == rs_player[event.group_id][1]:
|
if rs_player[event.group_id]["next"] == rs_player[event.group_id][1]:
|
||||||
win_user_id = rs_player[event.group_id][2]
|
win_user_id = rs_player[event.group_id][2]
|
||||||
lose_user_id = rs_player[event.group_id][1]
|
lose_user_id = rs_player[event.group_id][1]
|
||||||
win_name = player2_name
|
win_name = player2_name
|
||||||
@@ -293,60 +393,74 @@ async def end_game(bot: Bot, event: GroupMessageEvent):
|
|||||||
win_name = player1_name
|
win_name = player1_name
|
||||||
lose_name = player2_name
|
lose_name = player2_name
|
||||||
rand = random.randint(0, 5)
|
rand = random.randint(0, 5)
|
||||||
money = rs_player[event.group_id]['money']
|
money = rs_player[event.group_id]["money"]
|
||||||
if money > 10:
|
if money > 10:
|
||||||
fee = int(money * float(rand) / 100)
|
fee = int(money * float(rand) / 100)
|
||||||
fee = 1 if fee < 1 and rand != 0 else fee
|
fee = 1 if fee < 1 and rand != 0 else fee
|
||||||
else:
|
else:
|
||||||
fee = 0
|
fee = 0
|
||||||
await RussianUser.add_count(win_user_id, event.group_id, 'win')
|
await RussianUser.add_count(win_user_id, event.group_id, "win")
|
||||||
await RussianUser.add_count(lose_user_id, event.group_id, 'lose')
|
await RussianUser.add_count(lose_user_id, event.group_id, "lose")
|
||||||
await RussianUser.money(win_user_id, event.group_id, 'win', money - fee)
|
await RussianUser.money(win_user_id, event.group_id, "win", money - fee)
|
||||||
await RussianUser.money(lose_user_id, event.group_id, 'lose', money)
|
await RussianUser.money(lose_user_id, event.group_id, "lose", money)
|
||||||
await BagUser.add_gold(win_user_id, event.group_id, money - fee)
|
await BagUser.add_gold(win_user_id, event.group_id, money - fee)
|
||||||
await BagUser.spend_gold(lose_user_id, event.group_id, money)
|
await BagUser.spend_gold(lose_user_id, event.group_id, money)
|
||||||
win_user = await RussianUser.ensure(win_user_id, event.group_id)
|
win_user = await RussianUser.ensure(win_user_id, event.group_id)
|
||||||
lose_user = await RussianUser.ensure(lose_user_id, event.group_id)
|
lose_user = await RussianUser.ensure(lose_user_id, event.group_id)
|
||||||
bullet_str = ''
|
bullet_str = ""
|
||||||
for x in rs_player[event.group_id]['bullet']:
|
for x in rs_player[event.group_id]["bullet"]:
|
||||||
bullet_str += '__ ' if x == 0 else '| '
|
bullet_str += "__ " if x == 0 else "| "
|
||||||
logger.info(f'俄罗斯轮盘:胜者:{win_name} - 败者:{lose_name} - 金币:{money}')
|
logger.info(f"俄罗斯轮盘:胜者:{win_name} - 败者:{lose_name} - 金币:{money}")
|
||||||
await bot.send(event, message=f'结算:\n'
|
await bot.send(
|
||||||
f'\t胜者:{win_name}\n'
|
event,
|
||||||
f'\t赢取金币:{money - fee}\n'
|
message=f"结算:\n"
|
||||||
f'\t累计胜场:{win_user.win_count}\n'
|
f"\t胜者:{win_name}\n"
|
||||||
f'\t累计赚取金币:{win_user.make_money}\n'
|
f"\t赢取金币:{money - fee}\n"
|
||||||
f'-------------------\n'
|
f"\t累计胜场:{win_user.win_count}\n"
|
||||||
f'\t败者:{lose_name}\n'
|
f"\t累计赚取金币:{win_user.make_money}\n"
|
||||||
f'\t输掉金币:{money}\n'
|
f"-------------------\n"
|
||||||
f'\t累计败场:{lose_user.fail_count}\n'
|
f"\t败者:{lose_name}\n"
|
||||||
f'\t累计输掉金币:{lose_user.lose_money}\n'
|
f"\t输掉金币:{money}\n"
|
||||||
f'-------------------\n'
|
f"\t累计败场:{lose_user.fail_count}\n"
|
||||||
f'哼哼,{NICKNAME}从中收取了 {float(rand)}%({fee}金币) 作为手续费!\n'
|
f"\t累计输掉金币:{lose_user.lose_money}\n"
|
||||||
f'子弹排列:{bullet_str[:-1]}')
|
f"-------------------\n"
|
||||||
|
f"哼哼,{NICKNAME}从中收取了 {float(rand)}%({fee}金币) 作为手续费!\n"
|
||||||
|
f"子弹排列:{bullet_str[:-1]}",
|
||||||
|
)
|
||||||
rs_player[event.group_id] = {}
|
rs_player[event.group_id] = {}
|
||||||
|
|
||||||
|
|
||||||
@record.handle()
|
@record.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
user = await RussianUser.ensure(event.user_id, event.group_id)
|
user = await RussianUser.ensure(event.user_id, event.group_id)
|
||||||
await record.send(f'俄罗斯轮盘\n'
|
await record.send(
|
||||||
f'胜利场次:{user.win_count}\n'
|
f"俄罗斯轮盘\n"
|
||||||
f'失败场次:{user.fail_count}\n'
|
f"总胜利场次:{user.win_count}\n"
|
||||||
f'赚取金币:{user.make_money}\n'
|
f"当前连胜:{user.winning_streak}\n"
|
||||||
f'输掉金币:{user.lose_money}', at_sender=True)
|
f"最高连胜:{user.max_winning_streak}\n"
|
||||||
|
f"总失败场次:{user.fail_count}\n"
|
||||||
|
f"当前连败:{user.losing_streak}\n"
|
||||||
|
f"最高连败:{user.max_losing_streak}\n"
|
||||||
|
f"赚取金币:{user.make_money}\n"
|
||||||
|
f"输掉金币:{user.lose_money}",
|
||||||
|
at_sender=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@rssian_rank.handle()
|
@rssian_rank.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
if state["_prefix"]["raw_command"] in ['胜场排行', '胜利排行']:
|
if state["_prefix"]["raw_command"] in ["胜场排行", "胜利排行"]:
|
||||||
await rssian_rank.finish(await rank(event.group_id, 'win_rank'))
|
await rssian_rank.finish(await rank(event.group_id, "win_rank"))
|
||||||
if state["_prefix"]["raw_command"] in ['败场排行', '失败排行']:
|
if state["_prefix"]["raw_command"] in ["败场排行", "失败排行"]:
|
||||||
await rssian_rank.finish(await rank(event.group_id, 'lose_rank'))
|
await rssian_rank.finish(await rank(event.group_id, "lose_rank"))
|
||||||
if state["_prefix"]["raw_command"] == '欧洲人排行':
|
if state["_prefix"]["raw_command"] == "欧洲人排行":
|
||||||
await rssian_rank.finish(await rank(event.group_id, 'make_money'))
|
await rssian_rank.finish(await rank(event.group_id, "make_money"))
|
||||||
if state["_prefix"]["raw_command"] == '慈善家排行':
|
if state["_prefix"]["raw_command"] == "慈善家排行":
|
||||||
await rssian_rank.finish(await rank(event.group_id, 'spend_money'))
|
await rssian_rank.finish(await rank(event.group_id, "spend_money"))
|
||||||
|
if state["_prefix"]["raw_command"] == "最高连胜排行":
|
||||||
|
await rssian_rank.finish(await rank(event.group_id, "max_winning_streak"))
|
||||||
|
if state["_prefix"]["raw_command"] == "最高连败排行":
|
||||||
|
await rssian_rank.finish(await rank(event.group_id, "max_losing_streak"))
|
||||||
|
|
||||||
|
|
||||||
# 随机子弹排列
|
# 随机子弹排列
|
||||||
|
|||||||
@@ -14,9 +14,15 @@ async def rank(group_id: int, itype) -> str:
|
|||||||
elif itype == 'make_money':
|
elif itype == 'make_money':
|
||||||
rank_name = '\t赢取金币排行榜\n'
|
rank_name = '\t赢取金币排行榜\n'
|
||||||
all_user_data = [user.make_money for user in all_users]
|
all_user_data = [user.make_money for user in all_users]
|
||||||
else:
|
elif itype == 'spend_money':
|
||||||
rank_name = '\t输掉金币排行榜\n'
|
rank_name = '\t输掉金币排行榜\n'
|
||||||
all_user_data = [user.lose_money for user in all_users]
|
all_user_data = [user.lose_money for user in all_users]
|
||||||
|
elif itype == 'max_winning_streak':
|
||||||
|
rank_name = '\t最高连胜排行榜\n'
|
||||||
|
all_user_data = [user.max_winning_streak for user in all_users]
|
||||||
|
else:
|
||||||
|
rank_name = '\t最高连败排行榜\n'
|
||||||
|
all_user_data = [user.max_losing_streak for user in all_users]
|
||||||
rst = ''
|
rst = ''
|
||||||
if all_users:
|
if all_users:
|
||||||
rst = await init_rank(all_user_id, all_user_data, group_id)
|
rst = await init_rank(all_user_id, all_user_data, group_id)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
if _ulmt.check(event.user_id):
|
if _ulmt.check(event.user_id):
|
||||||
await search_anime.finish("您有动漫正在搜索,请稍等...", at_sender=True)
|
await search_anime.finish("您有动漫正在搜索,请稍等...", at_sender=True)
|
||||||
_ulmt.set_True(event.user_id)
|
_ulmt.set_true(event.user_id)
|
||||||
if get_message_text(event.json()):
|
if get_message_text(event.json()):
|
||||||
state["anime"] = get_message_text(event.json())
|
state["anime"] = get_message_text(event.json())
|
||||||
|
|
||||||
@@ -55,4 +55,4 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
else:
|
else:
|
||||||
logger.warning(f"未找到番剧 {key_word}")
|
logger.warning(f"未找到番剧 {key_word}")
|
||||||
await search_anime.send(f"未找到番剧 {key_word}(也有可能是超时,再尝试一下?)")
|
await search_anime.send(f"未找到番剧 {key_word}(也有可能是超时,再尝试一下?)")
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
@search_skin.got("skin", prompt="要查询该武器的什么皮肤呢?")
|
@search_skin.got("skin", prompt="要查询该武器的什么皮肤呢?")
|
||||||
async def arg_handle(bot: Bot, event: MessageEvent, state: T_State):
|
async def arg_handle(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
result = ""
|
result = ""
|
||||||
_ulmt.set_True(event.user_id)
|
_ulmt.set_true(event.user_id)
|
||||||
if state["name"] in ["ak", "ak47"]:
|
if state["name"] in ["ak", "ak47"]:
|
||||||
state["name"] = "ak-47"
|
state["name"] = "ak-47"
|
||||||
name = state["name"] + " | " + state["skin"]
|
name = state["name"] + " | " + state["skin"]
|
||||||
@@ -53,7 +53,7 @@ async def arg_handle(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
await search_skin.finish(F'请先对{NICKNAME}说"设置cookie"来设置cookie!')
|
await search_skin.finish(F'请先对{NICKNAME}说"设置cookie"来设置cookie!')
|
||||||
if status_code in [996, 997, 998]:
|
if status_code in [996, 997, 998]:
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
await search_skin.finish(result)
|
await search_skin.finish(result)
|
||||||
if result:
|
if result:
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -61,7 +61,7 @@ async def arg_handle(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询皮肤:"
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询皮肤:"
|
||||||
+ name
|
+ name
|
||||||
)
|
)
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
await search_skin.finish(result)
|
await search_skin.finish(result)
|
||||||
else:
|
else:
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -69,7 +69,7 @@ async def arg_handle(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}"
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}"
|
||||||
f" 查询皮肤:{name} 没有查询到"
|
f" 查询皮肤:{name} 没有查询到"
|
||||||
)
|
)
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
await search_skin.finish("没有查询到哦,请检查格式吧")
|
await search_skin.finish("没有查询到哦,请检查格式吧")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,16 @@ __plugin_usage__ = (
|
|||||||
|
|
||||||
_flmt = FreqLimiter(1)
|
_flmt = FreqLimiter(1)
|
||||||
|
|
||||||
|
if "色图" in IMAGE_DIR_LIST:
|
||||||
|
IMAGE_DIR_LIST.remove("色图")
|
||||||
|
|
||||||
cmd = set(IMAGE_DIR_LIST)
|
cmd = set(IMAGE_DIR_LIST)
|
||||||
|
|
||||||
# print(cmd)
|
# print(cmd)
|
||||||
|
|
||||||
send_img = on_command("img", aliases=cmd, priority=5, block=True)
|
send_img = on_command("img", aliases=cmd, priority=5, block=True)
|
||||||
pa = on_keyword({"爬", "爪巴"}, priority=1, block=True)
|
pa = on_keyword({"丢人爬", "爪巴"}, priority=5, block=True)
|
||||||
search_img = on_regex(".*[份|发|张|个|次|点]图.*?", priority=6, block=True)
|
pa_reg = on_regex("^爬$", priority=5, block=True)
|
||||||
|
|
||||||
search_url = "https://api.fantasyzone.cc/tu/search.php"
|
search_url = "https://api.fantasyzone.cc/tu/search.php"
|
||||||
|
|
||||||
@@ -42,7 +45,7 @@ search_url = "https://api.fantasyzone.cc/tu/search.php"
|
|||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
img_id = get_message_text(event.json())
|
img_id = get_message_text(event.json())
|
||||||
path = cn2py(state["_prefix"]["raw_command"]) + "/"
|
path = cn2py(state["_prefix"]["raw_command"]) + "/"
|
||||||
if path in IMAGE_DIR_LIST:
|
if state["_prefix"]["raw_command"] in IMAGE_DIR_LIST:
|
||||||
if not os.path.exists(f"{IMAGE_PATH}/{path}/"):
|
if not os.path.exists(f"{IMAGE_PATH}/{path}/"):
|
||||||
os.mkdir(f"{IMAGE_PATH}/{path}/")
|
os.mkdir(f"{IMAGE_PATH}/{path}/")
|
||||||
length = len(os.listdir(IMAGE_PATH + path)) - 1
|
length = len(os.listdir(IMAGE_PATH + path)) - 1
|
||||||
@@ -71,15 +74,27 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
|
|
||||||
@pa.handle()
|
@pa.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
if isinstance(event, GroupMessageEvent):
|
if isinstance(event, GroupMessageEvent) and not await GroupRemind.get_status(
|
||||||
if await GroupRemind.get_status(event.group_id, "pa"):
|
event.group_id, "pa"
|
||||||
msg = get_message_text(event.json())
|
):
|
||||||
if not msg or str(event.get_message()[:2]) in ["开启", "关闭"]:
|
return
|
||||||
return
|
msg = get_message_text(event.json())
|
||||||
if not _flmt.check(event.user_id):
|
if not msg or str(event.get_message()[:2]) in ["开启", "关闭"]:
|
||||||
return
|
return
|
||||||
_flmt.start_cd(event.user_id)
|
if _flmt.check(event.user_id):
|
||||||
await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
|
_flmt.start_cd(event.user_id)
|
||||||
|
await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
|
||||||
|
|
||||||
|
|
||||||
|
@pa_reg.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
if isinstance(event, GroupMessageEvent) and not await GroupRemind.get_status(
|
||||||
|
event.group_id, "pa"
|
||||||
|
):
|
||||||
|
return
|
||||||
|
if _flmt.check(event.user_id):
|
||||||
|
_flmt.start_cd(event.user_id)
|
||||||
|
await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
|
||||||
|
|
||||||
|
|
||||||
num_key = {
|
num_key = {
|
||||||
@@ -96,70 +111,3 @@ num_key = {
|
|||||||
"九": 9,
|
"九": 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@search_img.handle()
|
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|
||||||
msg = get_message_text(event.json())
|
|
||||||
r = re.search("[来要]?(.*)[份发张个次点]图(.*)", msg)
|
|
||||||
num = r.group(1)
|
|
||||||
if num in num_key.keys():
|
|
||||||
num = num_key[num]
|
|
||||||
elif is_number(num):
|
|
||||||
num = int(num)
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
keyword = r.group(2)
|
|
||||||
params = {"search": keyword, "r18": 0}
|
|
||||||
async with aiohttp.ClientSession() as session:
|
|
||||||
exists_id = []
|
|
||||||
for _ in range(num):
|
|
||||||
for _ in range(10):
|
|
||||||
try:
|
|
||||||
async with session.get(
|
|
||||||
search_url, timeout=5, params=params
|
|
||||||
) as response:
|
|
||||||
data = json.loads(await response.text())
|
|
||||||
except TimeoutError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if data["id"] == "null":
|
|
||||||
await send_img.finish(f"没有搜索到 {keyword} 的图片...", at_sender=True)
|
|
||||||
if data["id"] in exists_id:
|
|
||||||
continue
|
|
||||||
title = data["title"]
|
|
||||||
author = data["userName"]
|
|
||||||
pid = data["id"]
|
|
||||||
img_url = data["url"]
|
|
||||||
exists_id.append(pid)
|
|
||||||
for _ in range(5):
|
|
||||||
try:
|
|
||||||
await download_pic(img_url, event.user_id, session)
|
|
||||||
except TimeoutError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
await search_img.finish("图片下载失败...", at_sender=True)
|
|
||||||
await search_img.send(
|
|
||||||
Message(
|
|
||||||
f"title:{title}\n"
|
|
||||||
f"pid:{pid}\n"
|
|
||||||
f"author:{author}\n"
|
|
||||||
f'{image(f"send_img_{event.user_id}.png", "temp")}'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
await search_img.send("图片下载惜败了....", at_sender=True)
|
|
||||||
logger.info(
|
|
||||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
|
||||||
f" 发送搜索了 {num} 张 {keyword} 的图片"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def download_pic(img_url: str, user_id: int, session):
|
|
||||||
async with session.get(img_url, timeout=2) as res:
|
|
||||||
async with aiofiles.open(
|
|
||||||
f"{IMAGE_PATH}/temp/send_img_{user_id}.png", "wb"
|
|
||||||
) as f:
|
|
||||||
await f.write(await res.read())
|
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import random
|
import random
|
||||||
from nonebot import on_command, on_regex
|
from nonebot import on_command, on_regex
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from models.sigin_group_user import SignGroupUser
|
from models.sign_group_user import SignGroupUser
|
||||||
from nonebot.exception import IgnoredException
|
from nonebot.message import run_postprocessor
|
||||||
from nonebot.message import run_preprocessor, run_postprocessor
|
|
||||||
from nonebot.matcher import Matcher
|
from nonebot.matcher import Matcher
|
||||||
from typing import Optional, Type
|
from typing import Optional, Type
|
||||||
from gino.exceptions import UninitializedError
|
from gino.exceptions import UninitializedError
|
||||||
from utils.utils import (
|
from utils.utils import (
|
||||||
FreqLimiter,
|
|
||||||
UserExistLimiter,
|
|
||||||
is_number,
|
is_number,
|
||||||
get_message_text,
|
get_message_text,
|
||||||
get_message_imgs,
|
get_message_imgs,
|
||||||
@@ -35,9 +32,8 @@ from .data_source import (
|
|||||||
)
|
)
|
||||||
from nonebot.adapters.cqhttp.exception import ActionFailed
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
from configs.config import ONLY_USE_LOCAL_SETU, WITHDRAW_SETU_TIME, NICKNAME
|
from configs.config import ONLY_USE_LOCAL_SETU, WITHDRAW_SETU_TIME, NICKNAME
|
||||||
from utils.message_builder import at
|
from utils.static_data import withdraw_message_id_manager
|
||||||
import re
|
import re
|
||||||
import asyncio
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
@@ -65,27 +61,7 @@ __plugin_usage__ = f"""示例:
|
|||||||
色图 萝莉|少女 白丝|黑丝
|
色图 萝莉|少女 白丝|黑丝
|
||||||
色图 萝莉 猫娘"""
|
色图 萝莉 猫娘"""
|
||||||
|
|
||||||
_flmt = FreqLimiter(5)
|
|
||||||
_ulmt = UserExistLimiter()
|
|
||||||
setu_data_list = []
|
setu_data_list = []
|
||||||
withdraw_message_id = []
|
|
||||||
|
|
||||||
|
|
||||||
@run_preprocessor
|
|
||||||
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
|
||||||
if isinstance(event, MessageEvent):
|
|
||||||
if matcher.module == "send_setu":
|
|
||||||
if _ulmt.check(event.user_id):
|
|
||||||
if isinstance(event, GroupMessageEvent):
|
|
||||||
await bot.send_group_msg(
|
|
||||||
group_id=event.group_id,
|
|
||||||
message=Message(f"{at(event.user_id)}您有色图正在处理,请稍等....."),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await bot.send_private_msg(
|
|
||||||
user_id=event.user_id, message=f"您有色图正在处理,请稍等....."
|
|
||||||
)
|
|
||||||
raise IgnoredException("色图正在处理!")
|
|
||||||
|
|
||||||
|
|
||||||
@run_postprocessor
|
@run_postprocessor
|
||||||
@@ -96,17 +72,9 @@ async def do_something(
|
|||||||
event: Event,
|
event: Event,
|
||||||
state: T_State,
|
state: T_State,
|
||||||
):
|
):
|
||||||
global setu_data_list, withdraw_message_id
|
global setu_data_list
|
||||||
if isinstance(event, MessageEvent):
|
if isinstance(event, MessageEvent):
|
||||||
if matcher.module == "send_setu":
|
if matcher.module == "send_setu":
|
||||||
# 解除占用
|
|
||||||
_ulmt.set_False(event.user_id)
|
|
||||||
tasks = []
|
|
||||||
# 撤回色图
|
|
||||||
for id_ in withdraw_message_id[:]:
|
|
||||||
tasks.append(asyncio.ensure_future(withdraw_message(bot, event, id_)))
|
|
||||||
withdraw_message_id.remove(id_)
|
|
||||||
await asyncio.gather(*tasks)
|
|
||||||
# 添加数据至数据库
|
# 添加数据至数据库
|
||||||
try:
|
try:
|
||||||
await add_data_to_database(setu_data_list)
|
await add_data_to_database(setu_data_list)
|
||||||
@@ -127,7 +95,6 @@ find_setu = on_command("查色图", priority=5, block=True)
|
|||||||
|
|
||||||
@setu.handle()
|
@setu.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
global withdraw_message_id
|
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
if isinstance(event, GroupMessageEvent):
|
if isinstance(event, GroupMessageEvent):
|
||||||
impression = (
|
impression = (
|
||||||
@@ -136,10 +103,6 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
luox = get_luoxiang(impression)
|
luox = get_luoxiang(impression)
|
||||||
if luox:
|
if luox:
|
||||||
await setu.finish(luox)
|
await setu.finish(luox)
|
||||||
_ulmt.set_True(event.user_id)
|
|
||||||
if not _flmt.check(event.user_id):
|
|
||||||
await setu.finish("您冲得太快了,请稍候再冲", at_sender=True)
|
|
||||||
_flmt.start_cd(event.user_id)
|
|
||||||
r18 = 0
|
r18 = 0
|
||||||
num = 1
|
num = 1
|
||||||
# 是否看r18
|
# 是否看r18
|
||||||
@@ -166,7 +129,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
f" 发送色图 {setu_list[0].local_id}.png"
|
f" 发送色图 {setu_list[0].local_id}.png"
|
||||||
)
|
)
|
||||||
withdraw_message_id.append(msg_id["message_id"])
|
if msg_id:
|
||||||
|
withdraw_message(event, msg_id["message_id"])
|
||||||
return
|
return
|
||||||
await send_setu_handle(setu, event, state["_prefix"]["raw_command"], msg, num, r18)
|
await send_setu_handle(setu, event, state["_prefix"]["raw_command"], msg, num, r18)
|
||||||
|
|
||||||
@@ -195,9 +159,6 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
luox = get_luoxiang(impression)
|
luox = get_luoxiang(impression)
|
||||||
if luox:
|
if luox:
|
||||||
await setu.finish(luox, at_sender=True)
|
await setu.finish(luox, at_sender=True)
|
||||||
if not _flmt.check(event.user_id):
|
|
||||||
await setu.finish("您冲得太快了,请稍候再冲", at_sender=True)
|
|
||||||
_flmt.start_cd(event.user_id)
|
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
num = 1
|
num = 1
|
||||||
msg = re.search(r"(.*)[份发张个次点](.*)[瑟涩色]图", msg)
|
msg = re.search(r"(.*)[份发张个次点](.*)[瑟涩色]图", msg)
|
||||||
@@ -251,16 +212,16 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
async def send_setu_handle(
|
async def send_setu_handle(
|
||||||
matcher: Type[Matcher], event: MessageEvent, command: str, msg: str, num: int, r18: int
|
matcher: Type[Matcher], event: MessageEvent, command: str, msg: str, num: int, r18: int
|
||||||
):
|
):
|
||||||
global setu_data_list, withdraw_message_id
|
global setu_data_list
|
||||||
error_info = ""
|
|
||||||
# 非 id,在线搜索
|
# 非 id,在线搜索
|
||||||
tags = msg.split()
|
tags = msg.split()
|
||||||
# 真寻的色图?怎么可能
|
# 真寻的色图?怎么可能
|
||||||
if f"{NICKNAME}" in tags:
|
if f"{NICKNAME}" in tags:
|
||||||
await matcher.finish("咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀")
|
await matcher.finish("咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀")
|
||||||
# 本地先拿图,下载失败补上去
|
# 本地先拿图,下载失败补上去
|
||||||
setu_list, code = await get_setu_list(tags=msg.split(), r18=r18)
|
setu_list, code = None, 200
|
||||||
if not ONLY_USE_LOCAL_SETU and (tags or not setu_list or num > len(setu_list)):
|
msg_id = None
|
||||||
|
if not ONLY_USE_LOCAL_SETU and tags:
|
||||||
# 先尝试获取在线图片
|
# 先尝试获取在线图片
|
||||||
urls, text_list, add_databases_list, code = await get_setu_urls(tags, num, r18, command)
|
urls, text_list, add_databases_list, code = await get_setu_urls(tags, num, r18, command)
|
||||||
for x in add_databases_list:
|
for x in add_databases_list:
|
||||||
@@ -280,8 +241,9 @@ async def send_setu_handle(
|
|||||||
f" 发送色图 {index}.png"
|
f" 发送色图 {index}.png"
|
||||||
)
|
)
|
||||||
msg_id = await matcher.send(Message(f"{text_list[i]}\n{setu_img}"))
|
msg_id = await matcher.send(Message(f"{text_list[i]}\n{setu_img}"))
|
||||||
withdraw_message_id.append(msg_id["message_id"])
|
|
||||||
else:
|
else:
|
||||||
|
if setu_list is None:
|
||||||
|
setu_list, _ = await get_setu_list(tags=tags, r18=r18)
|
||||||
if setu_list:
|
if setu_list:
|
||||||
setu_image = random.choice(setu_list)
|
setu_image = random.choice(setu_list)
|
||||||
setu_list.remove(setu_image)
|
setu_list.remove(setu_image)
|
||||||
@@ -298,17 +260,18 @@ async def send_setu_handle(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg_id = await matcher.send(text_list[i] + "\n" + setu_img)
|
msg_id = await matcher.send(text_list[i] + "\n" + setu_img)
|
||||||
withdraw_message_id.append(msg_id["message_id"])
|
if msg_id:
|
||||||
|
withdraw_message(event, msg_id["message_id"])
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
|
await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
|
||||||
return
|
return
|
||||||
# 本地无图 或 超过上下限
|
# 本地无图 或 超过上下限
|
||||||
if code != 200 or (not setu_list and ONLY_USE_LOCAL_SETU):
|
if code != 200:
|
||||||
if code == 999:
|
await matcher.finish('网络连接失败...', at_sender=True)
|
||||||
await matcher.finish('网络连接失败...', at_sender=True)
|
if setu_list is None:
|
||||||
await matcher.finish(setu_list[0], at_sender=True)
|
setu_list, code = await get_setu_list(tags=tags, r18=r18)
|
||||||
elif not setu_list:
|
if code != 200:
|
||||||
await matcher.finish(error_info, at_sender=True)
|
await matcher.finish(setu_list[0], at_sender=True)
|
||||||
# 开始发图
|
# 开始发图
|
||||||
for _ in range(num):
|
for _ in range(num):
|
||||||
if not setu_list:
|
if not setu_list:
|
||||||
@@ -322,7 +285,7 @@ async def send_setu_handle(
|
|||||||
+ (await check_local_exists_or_download(setu_image))[0]
|
+ (await check_local_exists_or_download(setu_image))[0]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
withdraw_message_id.append(msg_id["message_id"])
|
withdraw_message(event, msg_id["message_id"])
|
||||||
logger.info(
|
logger.info(
|
||||||
f"(USER {event.user_id}, GROUP "
|
f"(USER {event.user_id}, GROUP "
|
||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||||
@@ -333,13 +296,11 @@ async def send_setu_handle(
|
|||||||
|
|
||||||
|
|
||||||
# 撤回图片
|
# 撤回图片
|
||||||
async def withdraw_message(bot: Bot, event: MessageEvent, id_: int):
|
def withdraw_message(event: MessageEvent, id_: int):
|
||||||
if WITHDRAW_SETU_TIME[0]:
|
if WITHDRAW_SETU_TIME[0]:
|
||||||
if (
|
if (
|
||||||
(WITHDRAW_SETU_TIME[1] == 0 and isinstance(event, PrivateMessageEvent))
|
(WITHDRAW_SETU_TIME[1] == 0 and isinstance(event, PrivateMessageEvent))
|
||||||
or (WITHDRAW_SETU_TIME[1] == 1 and isinstance(event, GroupMessageEvent))
|
or (WITHDRAW_SETU_TIME[1] == 1 and isinstance(event, GroupMessageEvent))
|
||||||
or WITHDRAW_SETU_TIME[1] == 2
|
or WITHDRAW_SETU_TIME[1] == 2
|
||||||
):
|
):
|
||||||
await asyncio.sleep(WITHDRAW_SETU_TIME[0])
|
withdraw_message_id_manager['message_id'].append((id_, WITHDRAW_SETU_TIME[0]))
|
||||||
await bot.delete_msg(message_id=id_, self_id=int(bot.self_id))
|
|
||||||
logger.info(f"自动撤回色图 消息id:{id_}")
|
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ async def get_setu_urls(
|
|||||||
for x in random_idx:
|
for x in random_idx:
|
||||||
x_urls.append(urls[x])
|
x_urls.append(urls[x])
|
||||||
x_text_lst.append(text_list[x])
|
x_text_lst.append(text_list[x])
|
||||||
|
if not x_urls:
|
||||||
|
return ["没找到符合条件的色图..."], [], [], 401
|
||||||
return x_urls, x_text_lst, add_databases_list, 200
|
return x_urls, x_text_lst, add_databases_list, 200
|
||||||
else:
|
else:
|
||||||
return ["没找到符合条件的色图..."], [], [], 401
|
return ["没找到符合条件的色图..."], [], [], 401
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from nonebot.permission import SUPERUSER
|
|||||||
from nonebot.rule import to_me
|
from nonebot.rule import to_me
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from configs.config import NICKNAME
|
from configs.config import NICKNAME
|
||||||
|
from apscheduler.jobstores.base import ConflictingIdError
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
from models.sigin_group_user import SignGroupUser
|
from models.sign_group_user import SignGroupUser
|
||||||
|
|
||||||
|
|
||||||
async def effect(user_id: int, group_id: int, name: str) -> bool:
|
async def effect(user_id: int, group_id: int, name: str) -> bool:
|
||||||
if name == "好感双倍加持卡Ⅰ":
|
if name in ["好感双倍加持卡Ⅰ", "好感度双倍加持卡Ⅰ"]:
|
||||||
user = await SignGroupUser.ensure(user_id, group_id)
|
user = await SignGroupUser.ensure(user_id, group_id)
|
||||||
await user.update(add_probability=0.1).apply()
|
await user.update(add_probability=0.1).apply()
|
||||||
if name == "好感双倍加持卡Ⅱ":
|
if name in ["好感双倍加持卡Ⅱ", "好感度双倍加持卡Ⅱ"]:
|
||||||
user = await SignGroupUser.ensure(user_id, group_id)
|
user = await SignGroupUser.ensure(user_id, group_id)
|
||||||
await user.update(add_probability=0.2).apply()
|
await user.update(add_probability=0.2).apply()
|
||||||
if name == "好感双倍加持卡Ⅲ":
|
if name in ["好感双倍加持卡Ⅲ", "好感度双倍加持卡Ⅲ"]:
|
||||||
user = await SignGroupUser.ensure(user_id, group_id)
|
user = await SignGroupUser.ensure(user_id, group_id)
|
||||||
print(user.user_qq)
|
|
||||||
await user.update(add_probability=0.3).apply()
|
await user.update(add_probability=0.3).apply()
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
|||||||
from nonebot.adapters.cqhttp.permission import GROUP
|
from nonebot.adapters.cqhttp.permission import GROUP
|
||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
from nonebot import on_command
|
from nonebot import on_command
|
||||||
from utils.utils import get_message_text
|
from utils.utils import get_message_text, scheduler
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from configs.path_config import DATA_PATH
|
from configs.path_config import DATA_PATH
|
||||||
|
from services.log import logger
|
||||||
|
from .utils import clear_sign_data_pic
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
@@ -52,16 +54,18 @@ total_sign_rank = on_command(
|
|||||||
|
|
||||||
@sign.handle()
|
@sign.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
nickname = event.sender.card if event.sender.card else event.sender.nickname
|
||||||
await sign.send(
|
await sign.send(
|
||||||
await group_user_check_in(event.user_id, event.group_id),
|
await group_user_check_in(nickname, event.user_id, event.group_id),
|
||||||
at_sender=True,
|
at_sender=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@my_sign.handle()
|
@my_sign.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
nickname = event.sender.card if event.sender.card else event.sender.nickname
|
||||||
await my_sign.send(
|
await my_sign.send(
|
||||||
await group_user_check(event.user_id, event.group_id),
|
await group_user_check(nickname, event.user_id, event.group_id),
|
||||||
at_sender=True,
|
at_sender=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -89,3 +93,15 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
await total_sign_rank.send("设置成功,签到总榜将会显示您的头像名称以及好感度!", at_sender=True)
|
await total_sign_rank.send("设置成功,签到总榜将会显示您的头像名称以及好感度!", at_sender=True)
|
||||||
with open(_file, "w", encoding="utf8") as f:
|
with open(_file, "w", encoding="utf8") as f:
|
||||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
'interval',
|
||||||
|
hours=1,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
try:
|
||||||
|
clear_sign_data_pic()
|
||||||
|
logger.info('清理日常签到图片数据数据完成....')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f'清理日常签到图片数据数据失败..{type(e)}: {e}')
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
SIGN_RESOURCE_PATH = Path(IMAGE_PATH) / 'sign' / 'sign_res'
|
||||||
|
SIGN_TODAY_CARD_PATH = Path(IMAGE_PATH) / 'sign' / 'today_card'
|
||||||
|
SIGN_BORDER_PATH = Path(SIGN_RESOURCE_PATH) / 'border'
|
||||||
|
SIGN_BACKGROUND_PATH = Path(SIGN_RESOURCE_PATH) / 'background'
|
||||||
|
|
||||||
|
SIGN_TODAY_CARD_PATH.mkdir(exist_ok=True, parents=True)
|
||||||
|
SIGN_BORDER_PATH.mkdir(exist_ok=True, parents=True)
|
||||||
|
SIGN_BACKGROUND_PATH.mkdir(exist_ok=True, parents=True)
|
||||||
|
|
||||||
|
SIGN_CARD1_PROB = 0.2 # 好感度双倍加持卡Ⅰ
|
||||||
|
SIGN_CARD2_PROB = 0.09 # 好感度双倍加持卡Ⅱ
|
||||||
|
SIGN_CARD3_PROB = 0.05 # 好感度双倍加持卡Ⅲ
|
||||||
|
|
||||||
|
PROB_DATA = {
|
||||||
|
SIGN_CARD3_PROB: '好感度双倍加持卡Ⅲ',
|
||||||
|
SIGN_CARD2_PROB: '好感度双倍加持卡Ⅱ',
|
||||||
|
SIGN_CARD1_PROB: '好感度双倍加持卡Ⅰ'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lik2relation = {
|
||||||
|
'0': '路人',
|
||||||
|
'1': '陌生',
|
||||||
|
'2': '初识',
|
||||||
|
'3': '普通',
|
||||||
|
'4': '熟悉',
|
||||||
|
'5': '信赖',
|
||||||
|
'6': '相知',
|
||||||
|
'7': '厚谊',
|
||||||
|
'8': '亲密'
|
||||||
|
}
|
||||||
|
|
||||||
|
level2attitude = {
|
||||||
|
'0': '排斥',
|
||||||
|
'1': '警惕',
|
||||||
|
'2': '可以交流',
|
||||||
|
'3': '一般',
|
||||||
|
'4': '是个好人',
|
||||||
|
'5': '好朋友',
|
||||||
|
'6': '可以分享小秘密',
|
||||||
|
'7': '喜欢',
|
||||||
|
'8': '恋人'
|
||||||
|
}
|
||||||
|
|
||||||
|
weekdays = {
|
||||||
|
1: 'Mon',
|
||||||
|
2: 'Tue',
|
||||||
|
3: 'Wed',
|
||||||
|
4: 'Thu',
|
||||||
|
5: 'Fri',
|
||||||
|
6: 'Sat',
|
||||||
|
7: 'Sun'
|
||||||
|
}
|
||||||
|
|
||||||
|
lik2level = {
|
||||||
|
9999: '9',
|
||||||
|
400: '8',
|
||||||
|
270: '7',
|
||||||
|
200: '6',
|
||||||
|
140: '5',
|
||||||
|
90: '4',
|
||||||
|
50: '3',
|
||||||
|
25: '2',
|
||||||
|
10: '1',
|
||||||
|
0: '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,39 +1,47 @@
|
|||||||
import random
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from io import BytesIO
|
from models.sign_group_user import SignGroupUser
|
||||||
from services.log import logger
|
|
||||||
from services.db_context import db
|
|
||||||
from models.sigin_group_user import SignGroupUser
|
|
||||||
from models.group_member_info import GroupInfoUser
|
from models.group_member_info import GroupInfoUser
|
||||||
from models.bag_user import BagUser
|
from models.bag_user import BagUser
|
||||||
from configs.config import MAX_SIGN_GOLD, NICKNAME
|
from configs.config import NICKNAME
|
||||||
from utils.image_utils import CreateImg
|
from nonebot.adapters.cqhttp import MessageSegment
|
||||||
import aiohttp
|
|
||||||
from asyncio.exceptions import TimeoutError
|
from asyncio.exceptions import TimeoutError
|
||||||
|
from utils.image_utils import CreateImg
|
||||||
|
from services.db_context import db
|
||||||
|
from .utils import get_card, SIGN_TODAY_CARD_PATH
|
||||||
|
from services.log import logger
|
||||||
|
from .random_event import random_event
|
||||||
|
from io import BytesIO
|
||||||
|
import random
|
||||||
|
import aiohttp
|
||||||
import math
|
import math
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
async def group_user_check_in(user_qq: int, group: int) -> str:
|
async def group_user_check_in(
|
||||||
|
nickname: str, user_qq: int, group: int
|
||||||
|
) -> MessageSegment:
|
||||||
"Returns string describing the result of checking in"
|
"Returns string describing the result of checking in"
|
||||||
present = datetime.now()
|
present = datetime.now()
|
||||||
async with db.transaction():
|
async with db.transaction():
|
||||||
# 取得相应用户
|
# 取得相应用户
|
||||||
user = await SignGroupUser.ensure(user_qq, group, for_update=True)
|
user = await SignGroupUser.ensure(user_qq, group, for_update=True)
|
||||||
# 如果同一天签到过,特殊处理
|
# 如果同一天签到过,特殊处理
|
||||||
if user.checkin_time_last.date() == present.date():
|
if (
|
||||||
return _handle_already_checked_in(user)
|
user.checkin_time_last + timedelta(hours=8)
|
||||||
return await _handle_check_in(user_qq, group, present) # ok
|
).date() >= present.date() or f"{user}_{group}_sign_{datetime.now().date()}" in os.listdir(
|
||||||
|
SIGN_TODAY_CARD_PATH
|
||||||
|
):
|
||||||
|
gold = await BagUser.get_gold(user_qq, group)
|
||||||
|
return await get_card(user, nickname, -1, gold, "")
|
||||||
|
return await _handle_check_in(nickname, user_qq, group, present) # ok
|
||||||
|
|
||||||
|
|
||||||
def _handle_already_checked_in(user: SignGroupUser) -> str:
|
async def _handle_check_in(
|
||||||
return f"已经签到过啦~ 好感度:{user.impression:.2f}"
|
nickname: str, user_qq: int, group: int, present: datetime
|
||||||
|
) -> MessageSegment:
|
||||||
|
|
||||||
async def _handle_check_in(user_qq: int, group: int, present: datetime) -> str:
|
|
||||||
user = await SignGroupUser.ensure(user_qq, group, for_update=True)
|
user = await SignGroupUser.ensure(user_qq, group, for_update=True)
|
||||||
impression_added = random.random()
|
impression_added = random.random()
|
||||||
present = present + timedelta(hours=8)
|
|
||||||
critx2 = random.random()
|
critx2 = random.random()
|
||||||
add_probability = user.add_probability
|
add_probability = user.add_probability
|
||||||
specify_probability = user.specify_probability
|
specify_probability = user.specify_probability
|
||||||
@@ -41,56 +49,36 @@ async def _handle_check_in(user_qq: int, group: int, present: datetime) -> str:
|
|||||||
impression_added *= 2
|
impression_added *= 2
|
||||||
elif critx2 < specify_probability:
|
elif critx2 < specify_probability:
|
||||||
impression_added *= 2
|
impression_added *= 2
|
||||||
new_impression = user.impression + impression_added
|
await SignGroupUser.sign(user, impression_added, present)
|
||||||
message = random.choice(
|
|
||||||
(
|
|
||||||
"谢谢,你是个好人!",
|
|
||||||
"对了,来喝杯茶吗?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
await user.update(
|
|
||||||
checkin_count=user.checkin_count + 1,
|
|
||||||
checkin_time_last=present,
|
|
||||||
impression=new_impression,
|
|
||||||
add_probability=0,
|
|
||||||
specify_probability=0,
|
|
||||||
).apply()
|
|
||||||
# glod = await random_glod(user_qq, group, specify_probability)
|
|
||||||
if user.impression < 1:
|
|
||||||
impression = 1
|
|
||||||
else:
|
|
||||||
impression = user.impression
|
|
||||||
gold = random.randint(1, 100)
|
gold = random.randint(1, 100)
|
||||||
imgold = random.randint(1, int(impression))
|
gift, gift_type = random_event(user.impression)
|
||||||
if imgold > MAX_SIGN_GOLD:
|
if gift_type == "gold":
|
||||||
imgold = MAX_SIGN_GOLD
|
await BagUser.add_gold(user_qq, group, gold + gift)
|
||||||
await BagUser.add_gold(user_qq, group, gold + imgold)
|
gift = f"额外金币 + {gift}"
|
||||||
|
else:
|
||||||
|
await BagUser.add_props(user_qq, group, gift)
|
||||||
|
gift += ' + 1'
|
||||||
if critx2 + add_probability > 0.97 or critx2 < specify_probability:
|
if critx2 + add_probability > 0.97 or critx2 < specify_probability:
|
||||||
logger.info(
|
logger.info(
|
||||||
f"(USER {user.user_qq}, GROUP {user.belonging_group})"
|
f"(USER {user.user_qq}, GROUP {user.belonging_group})"
|
||||||
f" CHECKED IN successfully. score: {new_impression:.2f} (+{impression_added * 2:.2f}).获取金币:{gold+imgold}"
|
f" CHECKED IN successfully. score: {user.impression:.2f} "
|
||||||
|
f"(+{impression_added * 2:.2f}).获取金币:{gold + gift if gift == 'gold' else gold}"
|
||||||
)
|
)
|
||||||
return f"{message} 好感度:{new_impression:.2f} (+{impression_added/2:.2f}×2)!!!\n获取金币:{gold} \n好感度额外获得金币:{imgold}"
|
return await get_card(user, nickname, impression_added, gold, gift, True)
|
||||||
else:
|
else:
|
||||||
logger.info(
|
logger.info(
|
||||||
f"(USER {user.user_qq}, GROUP {user.belonging_group})"
|
f"(USER {user.user_qq}, GROUP {user.belonging_group})"
|
||||||
f" CHECKED IN successfully. score: {new_impression:.2f} (+{impression_added:.2f}).获取金币:{gold+imgold}"
|
f" CHECKED IN successfully. score: {user.impression:.2f} "
|
||||||
|
f"(+{impression_added:.2f}).获取金币:{gold + gift if gift == 'gold' else gold}"
|
||||||
)
|
)
|
||||||
return f"{message} 好感度:{new_impression:.2f} (+{impression_added:.2f})\n获取金币:{gold} \n好感度额外获得金币:{imgold}"
|
return await get_card(user, nickname, impression_added, gold, gift)
|
||||||
|
|
||||||
|
|
||||||
async def group_user_check(user_qq: int, group: int) -> str:
|
async def group_user_check(nickname: str, user_qq: int, group: int) -> MessageSegment:
|
||||||
# heuristic: if users find they have never checked in they are probable to check in
|
# heuristic: if users find they have never checked in they are probable to check in
|
||||||
user = await SignGroupUser.ensure(user_qq, group)
|
user = await SignGroupUser.ensure(user_qq, group)
|
||||||
gold = await BagUser.get_gold(user_qq, group)
|
gold = await BagUser.get_gold(user_qq, group)
|
||||||
return "好感度:{:.2f}\n金币:{}\n历史签到数:{}\n上次签到日期:{}".format(
|
return await get_card(user, nickname, None, gold, "", is_card_view=True)
|
||||||
user.impression,
|
|
||||||
gold,
|
|
||||||
user.checkin_count,
|
|
||||||
user.checkin_time_last.date()
|
|
||||||
if user.checkin_time_last != datetime.min
|
|
||||||
else "从未",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def group_impression_rank(group: int) -> str:
|
async def group_impression_rank(group: int) -> str:
|
||||||
@@ -108,7 +96,7 @@ async def group_impression_rank(group: int) -> str:
|
|||||||
user_name = (
|
user_name = (
|
||||||
await GroupInfoUser.get_member_info(user_qq, group)
|
await GroupInfoUser.get_member_info(user_qq, group)
|
||||||
).user_name
|
).user_name
|
||||||
except Exception as e:
|
except AttributeError:
|
||||||
logger.info(f"USER {user_qq}, GROUP {group} 不在群内")
|
logger.info(f"USER {user_qq}, GROUP {group} 不在群内")
|
||||||
_count += 1
|
_count += 1
|
||||||
impression_list.remove(impression)
|
impression_list.remove(impression)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
from configs.config import MAX_SIGN_GOLD
|
||||||
|
from typing import Union
|
||||||
|
from .config import PROB_DATA
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def random_event(impression: float) -> 'Union[str, int], str':
|
||||||
|
"""
|
||||||
|
签到随机事件
|
||||||
|
:param impression: 好感度
|
||||||
|
:return: 额外奖励 和 类型
|
||||||
|
"""
|
||||||
|
rand = random.random() - impression / 1000
|
||||||
|
for prob in PROB_DATA.keys():
|
||||||
|
if rand <= prob:
|
||||||
|
return PROB_DATA[prob], 'props'
|
||||||
|
gold = random.randint(1, random.randint(1, int(1 if impression < 1 else impression)))
|
||||||
|
gold = MAX_SIGN_GOLD if gold > MAX_SIGN_GOLD else gold
|
||||||
|
return gold, 'gold'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,333 @@
|
|||||||
|
from .config import (
|
||||||
|
SIGN_RESOURCE_PATH,
|
||||||
|
SIGN_TODAY_CARD_PATH,
|
||||||
|
SIGN_BORDER_PATH,
|
||||||
|
SIGN_BACKGROUND_PATH,
|
||||||
|
lik2level,
|
||||||
|
lik2relation,
|
||||||
|
level2attitude,
|
||||||
|
weekdays,
|
||||||
|
)
|
||||||
|
from models.sign_group_user import SignGroupUser
|
||||||
|
from models.group_member_info import GroupInfoUser
|
||||||
|
from nonebot.adapters.cqhttp import MessageSegment
|
||||||
|
from utils.image_utils import CreateImg
|
||||||
|
from utils.message_builder import image
|
||||||
|
from configs.config import NICKNAME
|
||||||
|
from pathlib import Path
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional, List
|
||||||
|
from nonebot import Driver
|
||||||
|
from io import BytesIO
|
||||||
|
import asyncio
|
||||||
|
import nonebot
|
||||||
|
import aiohttp
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def init_image():
|
||||||
|
SIGN_RESOURCE_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
|
await GroupInfoUser.add_member_info(114514, 114514, "", datetime.min, 0)
|
||||||
|
_u = await GroupInfoUser.get_member_info(114514, 114514)
|
||||||
|
if _u.uid is None:
|
||||||
|
await _u.update(uid=0).apply()
|
||||||
|
generate_progress_bar_pic()
|
||||||
|
clear_sign_data_pic()
|
||||||
|
|
||||||
|
|
||||||
|
async def _get_pic(qq):
|
||||||
|
url = f"http://q1.qlogo.cn/g?b=qq&nk={qq}&s=100"
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(url, timeout=5) as response:
|
||||||
|
return await response.read()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_card(
|
||||||
|
user: "SignGroupUser",
|
||||||
|
nickname: str,
|
||||||
|
add_impression: Optional[float],
|
||||||
|
gold: Optional[int],
|
||||||
|
gift: str,
|
||||||
|
is_double: bool = False,
|
||||||
|
is_card_view: bool = False,
|
||||||
|
) -> MessageSegment:
|
||||||
|
user_id = user.user_qq
|
||||||
|
date = datetime.now().date()
|
||||||
|
_type = 'view' if is_card_view else 'sign'
|
||||||
|
card_file = Path(SIGN_TODAY_CARD_PATH) / f"{user_id}_{user.belonging_group}_{_type}_{date}.png"
|
||||||
|
if card_file.exists():
|
||||||
|
return image(f"{user_id}_{user.belonging_group}_{_type}_{date}.png", "sign/today_card")
|
||||||
|
else:
|
||||||
|
if add_impression == -1:
|
||||||
|
card_file = Path(SIGN_TODAY_CARD_PATH) / f"{user_id}_{user.belonging_group}_view_{date}.png"
|
||||||
|
if card_file.exists():
|
||||||
|
return image(f"{user_id}_{user.belonging_group}_view_{date}.png", "sign/today_card")
|
||||||
|
is_card_view = True
|
||||||
|
ava = BytesIO(await _get_pic(user_id))
|
||||||
|
uid = await GroupInfoUser.get_group_member_uid(
|
||||||
|
user.user_qq, user.belonging_group
|
||||||
|
)
|
||||||
|
impression_list = None
|
||||||
|
if is_card_view:
|
||||||
|
_, impression_list, _ = await SignGroupUser.get_all_impression(
|
||||||
|
user.belonging_group
|
||||||
|
)
|
||||||
|
return await asyncio.get_event_loop().run_in_executor(
|
||||||
|
None,
|
||||||
|
_generate_card,
|
||||||
|
user,
|
||||||
|
nickname,
|
||||||
|
user_id,
|
||||||
|
add_impression,
|
||||||
|
gold,
|
||||||
|
gift,
|
||||||
|
uid,
|
||||||
|
ava,
|
||||||
|
impression_list,
|
||||||
|
is_double,
|
||||||
|
is_card_view,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_card(
|
||||||
|
user: "SignGroupUser",
|
||||||
|
nickname: str,
|
||||||
|
user_id: int,
|
||||||
|
impression: Optional[float],
|
||||||
|
gold: Optional[int],
|
||||||
|
gift: str,
|
||||||
|
uid: str,
|
||||||
|
ava_bytes: BytesIO,
|
||||||
|
impression_list: List[float],
|
||||||
|
is_double: bool = False,
|
||||||
|
is_card_view: bool = False,
|
||||||
|
) -> MessageSegment:
|
||||||
|
ava_bk = CreateImg(140, 140, is_alpha=True)
|
||||||
|
ava_border = CreateImg(
|
||||||
|
140,
|
||||||
|
140,
|
||||||
|
background=SIGN_BORDER_PATH / 'ava_border_01.png',
|
||||||
|
)
|
||||||
|
ava = CreateImg(102, 102, background=ava_bytes)
|
||||||
|
ava.circle()
|
||||||
|
ava_bk.paste(ava, center_type="center")
|
||||||
|
ava_bk.paste(ava_border, alpha=True, center_type="center")
|
||||||
|
|
||||||
|
info_img = CreateImg(250, 150, color=(255, 255, 255, 0), font_size=15)
|
||||||
|
level, next_impression, previous_impression = get_level_and_next_impression(
|
||||||
|
user.impression
|
||||||
|
)
|
||||||
|
info_img.text((0, 0), f"· 好感度等级:{level} [{lik2relation[level]}]")
|
||||||
|
info_img.text((0, 20), f"· {NICKNAME}对你的态度:{level2attitude[level]}")
|
||||||
|
info_img.text((0, 40), f"· 距离升级还差 {next_impression - user.impression:.2f} 好感度")
|
||||||
|
|
||||||
|
bar_bk = CreateImg(220, 20, background=SIGN_RESOURCE_PATH / "bar_white.png")
|
||||||
|
bar = CreateImg(220, 20, background=SIGN_RESOURCE_PATH / "bar.png")
|
||||||
|
bar_bk.paste(
|
||||||
|
bar,
|
||||||
|
(
|
||||||
|
-int(
|
||||||
|
220
|
||||||
|
* (
|
||||||
|
(next_impression - user.impression)
|
||||||
|
/ (next_impression - previous_impression)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
font_size = 30
|
||||||
|
if '好感度双倍加持卡' in gift:
|
||||||
|
font_size = 20
|
||||||
|
gift_border = CreateImg(
|
||||||
|
270, 100, background=SIGN_BORDER_PATH / "gift_border_02.png", font_size=font_size
|
||||||
|
)
|
||||||
|
gift_border.text((0, 0), gift, center_type="center")
|
||||||
|
|
||||||
|
bk = CreateImg(
|
||||||
|
876, 424, background=SIGN_BACKGROUND_PATH / "background_01.jpg", font_size=25
|
||||||
|
)
|
||||||
|
A = CreateImg(876, 274, background=SIGN_RESOURCE_PATH / "white.png")
|
||||||
|
line = CreateImg(2, 180, color="black")
|
||||||
|
A.transparent(2)
|
||||||
|
A.paste(ava_bk, (25, 80), True)
|
||||||
|
A.paste(line, (200, 70))
|
||||||
|
|
||||||
|
nickname_img = CreateImg(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=nickname,
|
||||||
|
color=(255, 255, 255, 0),
|
||||||
|
font_size=50,
|
||||||
|
font_color=(255, 255, 255),
|
||||||
|
)
|
||||||
|
if uid:
|
||||||
|
uid = f"{uid}".rjust(12, "0")
|
||||||
|
uid = uid[:4] + " " + uid[4:8] + " " + uid[8:]
|
||||||
|
else:
|
||||||
|
uid = "XXXX XXXX XXXX"
|
||||||
|
uid_img = CreateImg(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=f"UID: {uid}",
|
||||||
|
color=(255, 255, 255, 0),
|
||||||
|
font_size=30,
|
||||||
|
font_color=(255, 255, 255),
|
||||||
|
)
|
||||||
|
sign_day_img = CreateImg(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=f"{user.checkin_count}",
|
||||||
|
color=(255, 255, 255, 0),
|
||||||
|
font_size=40,
|
||||||
|
font_color=(211, 64, 33),
|
||||||
|
)
|
||||||
|
lik_text1_img = CreateImg(
|
||||||
|
0, 0, plain_text="当前", color=(255, 255, 255, 0), font_size=20
|
||||||
|
)
|
||||||
|
lik_text2_img = CreateImg(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=f"好感度:{user.impression:.2f}",
|
||||||
|
color=(255, 255, 255, 0),
|
||||||
|
font_size=30,
|
||||||
|
)
|
||||||
|
watermark = CreateImg(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=f"{NICKNAME}@{datetime.now().year}",
|
||||||
|
color=(255, 255, 255, 0),
|
||||||
|
font_size=15,
|
||||||
|
font_color=(155, 155, 155),
|
||||||
|
)
|
||||||
|
today_data = CreateImg(300, 300, color=(255, 255, 255, 0), font_size=20)
|
||||||
|
if is_card_view:
|
||||||
|
today_sign_text_img = CreateImg(
|
||||||
|
0, 0, plain_text="", color=(255, 255, 255, 0), font_size=30
|
||||||
|
)
|
||||||
|
if impression_list:
|
||||||
|
impression_list.sort(reverse=True)
|
||||||
|
index = impression_list.index(user.impression)
|
||||||
|
rank_img = CreateImg(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=f"* 此群好感排名第 {index + 1} 位",
|
||||||
|
color=(255, 255, 255, 0),
|
||||||
|
font_size=30,
|
||||||
|
)
|
||||||
|
A.paste(rank_img, ((A.w - rank_img.w - 10), 20), True)
|
||||||
|
today_data.text(
|
||||||
|
(0, 0),
|
||||||
|
f"上次签到日期:{'从未' if user.checkin_time_last == datetime.min else user.checkin_time_last.date()}",
|
||||||
|
)
|
||||||
|
today_data.text((0, 25), f"总金币:{gold}")
|
||||||
|
today_data.text((0, 50), f'色图概率:{(70 + user.impression if user.impression < 100 else 100):.2f}%')
|
||||||
|
today_data.text((0, 75), f'开箱次数:{(20 + int(user.impression / 3))}')
|
||||||
|
_type = "view"
|
||||||
|
else:
|
||||||
|
A.paste(gift_border, (570, 140), True)
|
||||||
|
today_sign_text_img = CreateImg(
|
||||||
|
0, 0, plain_text="今日签到", color=(255, 255, 255, 0), font_size=30
|
||||||
|
)
|
||||||
|
if is_double:
|
||||||
|
today_data.text((0, 0), f"好感度 + {impression / 2:.2f} × 2")
|
||||||
|
else:
|
||||||
|
today_data.text((0, 0), f"好感度 + {impression:.2f}")
|
||||||
|
today_data.text((0, 25), f"金币 + {gold}")
|
||||||
|
_type = "sign"
|
||||||
|
current_date = datetime.now()
|
||||||
|
week = current_date.isoweekday()
|
||||||
|
data = current_date.date()
|
||||||
|
hour = current_date.hour
|
||||||
|
minute = current_date.minute
|
||||||
|
second = current_date.second
|
||||||
|
data_img = CreateImg(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=f"时间:{data} {weekdays[week]} {hour}:{minute}:{second}",
|
||||||
|
color=(255, 255, 255, 0),
|
||||||
|
font_size=20,
|
||||||
|
)
|
||||||
|
bk.paste(nickname_img, (30, 15), True)
|
||||||
|
bk.paste(uid_img, (30, 85), True)
|
||||||
|
bk.paste(A, (0, 150), alpha=True)
|
||||||
|
bk.text((30, 167), "Accumulative check-in for")
|
||||||
|
_x = bk.getsize("Accumulative check-in for")[0] + sign_day_img.w + 45
|
||||||
|
bk.paste(sign_day_img, (346, 158), True)
|
||||||
|
bk.text((_x, 167), "days")
|
||||||
|
bk.paste(data_img, (220, 370), True)
|
||||||
|
bk.paste(lik_text1_img, (220, 240), True)
|
||||||
|
bk.paste(lik_text2_img, (262, 234), True)
|
||||||
|
bk.paste(bar_bk, (225, 275), True)
|
||||||
|
bk.paste(info_img, (220, 305), True)
|
||||||
|
bk.paste(today_sign_text_img, (550, 180), True)
|
||||||
|
bk.paste(today_data, (580, 220), True)
|
||||||
|
bk.paste(watermark, (15, 400), True)
|
||||||
|
bk.save(SIGN_TODAY_CARD_PATH / f"{user_id}_{user.belonging_group}_{_type}_{data}.png")
|
||||||
|
return image(f"{user_id}_{user.belonging_group}_{_type}_{data}.png", "sign/today_card")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_progress_bar_pic():
|
||||||
|
bg_2 = (254, 1, 254)
|
||||||
|
bg_1 = (0, 245, 246)
|
||||||
|
|
||||||
|
bk = CreateImg(1000, 50, is_alpha=True)
|
||||||
|
img_x = CreateImg(50, 50, color=bg_2)
|
||||||
|
img_x.circle()
|
||||||
|
img_x.crop((25, 0, 50, 50))
|
||||||
|
img_y = CreateImg(50, 50, color=bg_1)
|
||||||
|
img_y.circle()
|
||||||
|
img_y.crop((0, 0, 25, 50))
|
||||||
|
A = CreateImg(950, 50)
|
||||||
|
width, height = A.size
|
||||||
|
|
||||||
|
step_r = (bg_2[0] - bg_1[0]) / width
|
||||||
|
step_g = (bg_2[1] - bg_1[1]) / width
|
||||||
|
step_b = (bg_2[2] - bg_1[2]) / width
|
||||||
|
|
||||||
|
for y in range(0, width):
|
||||||
|
bg_r = round(bg_1[0] + step_r * y)
|
||||||
|
bg_g = round(bg_1[1] + step_g * y)
|
||||||
|
bg_b = round(bg_1[2] + step_b * y)
|
||||||
|
for x in range(0, height):
|
||||||
|
A.point((y, x), fill=(bg_r, bg_g, bg_b))
|
||||||
|
bk.paste(img_y, (0, 0), True)
|
||||||
|
bk.paste(A, (25, 0))
|
||||||
|
bk.paste(img_x, (975, 0), True)
|
||||||
|
bk.save(SIGN_RESOURCE_PATH / "bar.png")
|
||||||
|
|
||||||
|
A = CreateImg(950, 50)
|
||||||
|
bk = CreateImg(1000, 50, is_alpha=True)
|
||||||
|
img_x = CreateImg(50, 50)
|
||||||
|
img_x.circle()
|
||||||
|
img_x.crop((25, 0, 50, 50))
|
||||||
|
img_y = CreateImg(50, 50)
|
||||||
|
img_y.circle()
|
||||||
|
img_y.crop((0, 0, 25, 50))
|
||||||
|
bk.paste(img_y, (0, 0), True)
|
||||||
|
bk.paste(A, (25, 0))
|
||||||
|
bk.paste(img_x, (975, 0), True)
|
||||||
|
bk.save(SIGN_RESOURCE_PATH / "bar_white.png")
|
||||||
|
|
||||||
|
|
||||||
|
def get_level_and_next_impression(impression: float):
|
||||||
|
if impression == 0:
|
||||||
|
return lik2level[10], 10, 0
|
||||||
|
keys = list(lik2level.keys())
|
||||||
|
for i in range(len(keys)):
|
||||||
|
if impression > keys[i]:
|
||||||
|
return lik2level[keys[i]], keys[i - 1], keys[i]
|
||||||
|
return lik2level[10], 10, 0
|
||||||
|
|
||||||
|
|
||||||
|
def clear_sign_data_pic():
|
||||||
|
date = datetime.now().date()
|
||||||
|
for file in os.listdir(SIGN_TODAY_CARD_PATH):
|
||||||
|
if str(date) not in file:
|
||||||
|
os.remove(SIGN_TODAY_CARD_PATH / file)
|
||||||
|
|
||||||
@@ -183,7 +183,10 @@ async def _():
|
|||||||
for data in [_prefix_count_dict, _prefix_user_count_dict]:
|
for data in [_prefix_count_dict, _prefix_user_count_dict]:
|
||||||
for x in _prefix_count_dict["day_statistics"].keys():
|
for x in _prefix_count_dict["day_statistics"].keys():
|
||||||
for key in _prefix_count_dict["day_statistics"][x].keys():
|
for key in _prefix_count_dict["day_statistics"][x].keys():
|
||||||
data["day_statistics"][x][key] = 0
|
try:
|
||||||
|
data["day_statistics"][x][key] = 0
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
data["day_index"] += 1
|
data["day_index"] += 1
|
||||||
with open(DATA_PATH + "_prefix_count.json", "w", encoding="utf8") as f:
|
with open(DATA_PATH + "_prefix_count.json", "w", encoding="utf8") as f:
|
||||||
json.dump(_prefix_count_dict, f, indent=4, ensure_ascii=False)
|
json.dump(_prefix_count_dict, f, indent=4, ensure_ascii=False)
|
||||||
|
|||||||
@@ -225,14 +225,15 @@ def _clear_data() -> float:
|
|||||||
size = 0
|
size = 0
|
||||||
for dir_name in ['temp', 'rar', 'r18_rar']:
|
for dir_name in ['temp', 'rar', 'r18_rar']:
|
||||||
dir_name = f'{IMAGE_PATH}/{dir_name}'
|
dir_name = f'{IMAGE_PATH}/{dir_name}'
|
||||||
for file in os.listdir(dir_name):
|
if os.path.exists(dir_name):
|
||||||
try:
|
for file in os.listdir(dir_name):
|
||||||
file_size = os.path.getsize(os.path.join(dir_name, file))
|
try:
|
||||||
os.remove(os.path.join(dir_name, file))
|
file_size = os.path.getsize(os.path.join(dir_name, file))
|
||||||
except Exception as e:
|
os.remove(os.path.join(dir_name, file))
|
||||||
logger.error(f"清理临时数据错误...e:{e}")
|
except Exception as e:
|
||||||
file_size = 0
|
logger.error(f"清理临时数据错误...e:{e}")
|
||||||
size += file_size
|
file_size = 0
|
||||||
|
size += file_size
|
||||||
return float(size)
|
return float(size)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from utils.message_builder import image
|
|||||||
result = """超级用户帮助:
|
result = """超级用户帮助:
|
||||||
*:可多个类型参数 ?:可省略参数
|
*:可多个类型参数 ?:可省略参数
|
||||||
1.添加/删除管理 [at] [level]
|
1.添加/删除管理 [at] [level]
|
||||||
2.查看群组/查看好友
|
2.所有群组/好友
|
||||||
3.广播- [msg]
|
3.广播- [msg]
|
||||||
4.更新色图
|
4.更新色图
|
||||||
5./t命令帮助
|
5./t命令帮助
|
||||||
@@ -19,14 +19,14 @@ result = """超级用户帮助:
|
|||||||
7.开启/关闭广播通知 [群号]
|
7.开启/关闭广播通知 [群号]
|
||||||
8.退群 [群号]
|
8.退群 [群号]
|
||||||
9.自检
|
9.自检
|
||||||
10.更新价格/更加图片 [武器箱]
|
10.更新价格/更加图片 ?[武器箱]
|
||||||
11.更新好友信息
|
11.更新好友信息
|
||||||
12.更新群群信息
|
12.更新群群信息
|
||||||
13.重载原神/方舟/赛马娘/坎公骑冠剑卡池
|
13.重载原神/方舟/赛马娘/坎公骑冠剑卡池
|
||||||
14.添加商品 [名称]-[价格]-[描述]-[折扣]-[限时时间]
|
14.添加商品 [名称]-[价格]-[描述]-[折扣]-[限时时间]
|
||||||
15.删除商品 [名称(序号)]
|
15.删除商品 [名称(序号)]
|
||||||
16.修改商品 -name [名称(序号)] -price [价格] -des [描述] -discount [折扣] -time [限时]
|
16.修改商品 -name [名称(序号)] -price [价格] -des [描述] -discount [折扣] -time [限时]
|
||||||
17.节日红包 [金额] [数量] [祝福语](可省) *?[指定群
|
17.节日红包 [金额] [数量] ?[祝福语] *?[指定群]
|
||||||
18.更新原神今日素材
|
18.更新原神今日素材
|
||||||
19.更新原神资源信息
|
19.更新原神资源信息
|
||||||
20.添加pix关键词/uid/pid *[关键词/uid/pid] ?[-f](强制通过不检测)
|
20.添加pix关键词/uid/pid *[关键词/uid/pid] ?[-f](强制通过不检测)
|
||||||
@@ -36,10 +36,13 @@ result = """超级用户帮助:
|
|||||||
24.删除pix图片 *[pid] ?[-b](同时加入黑名单)
|
24.删除pix图片 *[pid] ?[-b](同时加入黑名单)
|
||||||
25.查看pix图库 [keyword]
|
25.查看pix图库 [keyword]
|
||||||
26.pix检测更新 [update]
|
26.pix检测更新 [update]
|
||||||
27.检查更新真寻
|
27.pix [-s/-r] ?[tag]
|
||||||
28.真寻重启
|
28.检查更新真寻
|
||||||
29.添加/删除群白名单 *[群号]
|
29.真寻重启
|
||||||
30.关闭[功能] ?[群号/private/group](有群号时禁用指定群)"""
|
30.添加/删除群白名单 *[群号]
|
||||||
|
31.关闭[功能] ?[群号/private/group](有群号时禁用指定群)
|
||||||
|
32.功能状态
|
||||||
|
33.查看群白名单"""
|
||||||
|
|
||||||
height = len(result.split('\n')) * 24
|
height = len(result.split('\n')) * 24
|
||||||
A = CreateImg(1000, height, font_size=20)
|
A = CreateImg(1000, height, font_size=20)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
await lasted_gocqhttp.finish("gocqhttp没有更新!")
|
await lasted_gocqhttp.finish("gocqhttp没有更新!")
|
||||||
if _ulmt.check(event.group_id):
|
if _ulmt.check(event.group_id):
|
||||||
await lasted_gocqhttp.finish("gocqhttp正在更新,请勿重复使用该命令", at_sender=True)
|
await lasted_gocqhttp.finish("gocqhttp正在更新,请勿重复使用该命令", at_sender=True)
|
||||||
_ulmt.set_True(event.group_id)
|
_ulmt.set_true(event.group_id)
|
||||||
try:
|
try:
|
||||||
for file in os.listdir(path):
|
for file in os.listdir(path):
|
||||||
await upload_gocq_lasted(path, file, event.group_id)
|
await upload_gocq_lasted(path, file, event.group_id)
|
||||||
@@ -39,7 +39,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
await lasted_gocqhttp.send(f"gocqhttp更新了,已上传成功!\n更新内容:\n{info}")
|
await lasted_gocqhttp.send(f"gocqhttp更新了,已上传成功!\n更新内容:\n{info}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"更新gocq错误 e:{e}")
|
logger.error(f"更新gocq错误 e:{e}")
|
||||||
_ulmt.set_False(event.group_id)
|
_ulmt.set_false(event.group_id)
|
||||||
|
|
||||||
|
|
||||||
# 更新gocq
|
# 更新gocq
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ from nonebot import on_command
|
|||||||
from nonebot.rule import to_me
|
from nonebot.rule import to_me
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
|
||||||
|
|
||||||
|
from configs.config import IMAGE_DIR_LIST
|
||||||
from utils.utils import get_message_imgs, get_message_text
|
from utils.utils import get_message_imgs, get_message_text
|
||||||
from .data_source import upload_image_to_local
|
from .data_source import upload_image_to_local
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
@what_anime.got("img_url", prompt="虚空识番?来图来图GKD")
|
@what_anime.got("img_url", prompt="虚空识番?来图来图GKD")
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
img_url = state["img_url"][0]
|
img_url = state["img_url"][0]
|
||||||
_ulmt.set_True(event.user_id)
|
_ulmt.set_true(event.user_id)
|
||||||
await what_anime.send("开始识别.....")
|
await what_anime.send("开始识别.....")
|
||||||
anime_data_report = await get_anime(img_url)
|
anime_data_report = await get_anime(img_url)
|
||||||
if anime_data_report:
|
if anime_data_report:
|
||||||
@@ -58,4 +58,4 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
|
|||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'} 识番 {img_url} 未找到!!"
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'} 识番 {img_url} 未找到!!"
|
||||||
)
|
)
|
||||||
await what_anime.send(f"没有寻找到该番剧,果咩..", at_sender=True)
|
await what_anime.send(f"没有寻找到该番剧,果咩..", at_sender=True)
|
||||||
_ulmt.set_False(event.user_id)
|
_ulmt.set_false(event.user_id)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
withdraw_msg = on_command('撤回', priority=5, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@withdraw_msg.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
r = re.search(r'\[CQ:reply,id=(\d*)]', event.raw_message)
|
||||||
|
if r:
|
||||||
|
await bot.delete_msg(message_id=int(r.group(1)), self_id=int(bot.self_id))
|
||||||
|
|
||||||
@@ -15,16 +15,17 @@ yiqing = on_command("疫情", aliases={"查询疫情", "疫情查询"}, priority
|
|||||||
@yiqing.handle()
|
@yiqing.handle()
|
||||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
msg = get_message_text(event.json())
|
msg = get_message_text(event.json())
|
||||||
result = await get_yiqing_data(msg)
|
if msg:
|
||||||
if result:
|
result = await get_yiqing_data(msg)
|
||||||
await yiqing.send(result)
|
if result:
|
||||||
logger.info(
|
await yiqing.send(result)
|
||||||
f"(USER {event.user_id}, GROUP "
|
logger.info(
|
||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情: {msg}"
|
f"(USER {event.user_id}, GROUP "
|
||||||
)
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情: {msg}"
|
||||||
else:
|
)
|
||||||
await yiqing.send("查询失败!!!!", at_sender=True)
|
else:
|
||||||
logger.info(
|
await yiqing.send("查询失败!!!!", at_sender=True)
|
||||||
f"(USER {event.user_id}, GROUP "
|
logger.info(
|
||||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情失败"
|
f"(USER {event.user_id}, GROUP "
|
||||||
)
|
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情失败"
|
||||||
|
)
|
||||||
|
|||||||
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 153 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 41 KiB |