mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 06:12:53 +08:00
Merge branch 'main' into main
This commit is contained in:
commit
fef85190c5
4
.gitignore
vendored
4
.gitignore
vendored
@ -156,8 +156,9 @@ data/
|
||||
.env.dev
|
||||
/resources/text/
|
||||
/resources/image/
|
||||
/resources/temp/
|
||||
!/resources/template/
|
||||
configs/config.py
|
||||
/configs/config.py
|
||||
configs/config.yaml
|
||||
./.env
|
||||
./.env.dev
|
||||
@ -165,3 +166,4 @@ plugins/csgo_server/
|
||||
plugins/activity/
|
||||
!/resources/image/genshin/alc/back.png
|
||||
!/data/genshin_alc/
|
||||
.vscode/launch.json
|
||||
330
README.md
330
README.md
@ -5,22 +5,27 @@
|
||||

|
||||
|
||||
# 绪山真寻Bot
|
||||
|
||||
****
|
||||
此项目基于 Nonebot2 和 go-cqhttp 开发,以 postgresql 作为数据库的QQ群娱乐机器人
|
||||
|
||||
## 关于
|
||||
|
||||
用爱发电,某些功能学习借鉴了大佬们的代码,因为绪山真寻实在太可爱了因此开发了
|
||||
绪山真寻bot,实现了一些对群友的娱乐功能和实用功能(大概)。
|
||||
|
||||
如果该项目的图片等等侵犯猫豆腐老师权益请联系我删除!
|
||||
|
||||
是新手!希望有个地方讨论绪山真寻Bot,或者有问题或建议,可以发送issues或加入[ <strong>[是真寻酱哒](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) </strong>]
|
||||
是新手!希望有个地方讨论绪山真寻Bot,或者有问题或建议,可以发送issues或加入[ <strong>[是真寻酱哒(萌新版)](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) </strong>]
|
||||
|
||||
更喜欢讨论可爱的真寻,讨论插件开发,nonebot2开发,可以加入[ <strong>[真寻酱的技术群](https://jq.qq.com/?_wv=1027&k=E6sUkMzo) </strong>])
|
||||
[//]: # (是老手!讨论插件开发,nonebot2开发,可以加入[ <strong>[真寻酱的技术群](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) </strong>])
|
||||
|
||||
## 声明
|
||||
|
||||
此项目仅用于学习交流,请勿用于非法用途
|
||||
|
||||
# Nonebot2
|
||||
|
||||
<img style="height: 200px;width: 200px;" src="https://camo.githubusercontent.com/0ef71e86056da694c540790aa4a4e314396884d6c4fdb95362a7538b27a1b034/68747470733a2f2f76322e6e6f6e65626f742e6465762f6c6f676f2e706e67">
|
||||
|
||||
非常 [ **[NICE](https://github.com/nonebot/nonebot2)** ] 的OneBot框架
|
||||
@ -30,18 +35,23 @@
|
||||
# [传送门](https://hibikier.github.io/zhenxun_bot/)
|
||||
|
||||
## 真寻的帮助
|
||||
|
||||
请对真寻说: '真寻帮助' or '管理员帮助' or '超级用户帮助' or '真寻帮助 指令'
|
||||
|
||||
## 普通帮助图片
|
||||
|
||||

|
||||
|
||||
## HTML版帮助图片
|
||||
|
||||

|
||||
|
||||
## Web UI
|
||||
|
||||
[zhenxun_bot_webui](https://github.com/HibiKier/zhenxun_bot_webui)
|
||||
|
||||
## 一键安装脚本
|
||||
|
||||
[zhenxun_bot-deploy](https://github.com/AkashiCoin/zhenxun_bot-deploy)
|
||||
|
||||
## 提供符合真寻标准的插件仓库
|
||||
@ -50,152 +60,164 @@
|
||||
|
||||
## 来点优点?
|
||||
|
||||
* 实现了许多功能,且提供了大量功能管理命令
|
||||
* 通过Config配置项将所有插件配置统计保存至config.yaml,利于统一用户修改
|
||||
* 方便增删插件,原生nonebot2 matcher,不需要额外修改,仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息`
|
||||
* 提供了cd,阻塞,每日次数等限制,仅仅通过简单的属性就可以生成一个限制,例如:`__plugin_cd_limit__`
|
||||
* __..... 更多详细请通过`传送门`查看文档!__
|
||||
|
||||
* 实现了许多功能,且提供了大量功能管理命令
|
||||
* 通过Config配置项将所有插件配置统计保存至config.yaml,利于统一用户修改
|
||||
* 方便增删插件,原生nonebot2 matcher,不需要额外修改,仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息`
|
||||
* 提供了cd,阻塞,每日次数等限制,仅仅通过简单的属性就可以生成一个限制,例如:`__plugin_cd_limit__`
|
||||
* __..... 更多详细请通过`传送门`查看文档!__
|
||||
|
||||
## 功能列表
|
||||
|
||||
<details>
|
||||
<summary>已实现的功能</summary>
|
||||
|
||||
### 已实现的常用功能
|
||||
- [x] 昵称系统(群与群与私聊分开.)
|
||||
- [x] 图灵AI(会把'你'等关键字替换为你的昵称),且带有 [AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus),够味
|
||||
- [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置)
|
||||
- [x] 发送某文件夹下的随机图片(支持自定义,默认:美图,萝莉,壁纸)
|
||||
- [x] 色图(这不是基础功能嘛喂)
|
||||
- [x] coser
|
||||
- [x] 黑白草图生成器
|
||||
- [x] 鸡汤/语录
|
||||
- [x] 骂我(钉宫语音)
|
||||
- [x] 戳一戳(概率发送美图,钉宫语音或者戳回去)
|
||||
- [x] 模拟开箱/我的开箱/群开箱统计/我的金色/设置cookie(csgo,内置爬虫脚本,需要提前抓取数据和图片,需要session,可能需要代理,阿里云服务器等ip也许已经被ban了(我无代理访问失败),如果访问太多账号API调用可能被禁止访问api!)
|
||||
- [x] 鲁迅说过
|
||||
- [x] 构造假消息(自定义的分享链接)
|
||||
- [x] 商店/我的金币/购买道具/使用道具
|
||||
- [x] 8种手游抽卡 (查看 [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw))
|
||||
- [x] 我有一个朋友想问问..(借鉴pcrbot插件)
|
||||
- [x] 原神黄历
|
||||
- [x] 原神今日素材
|
||||
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
|
||||
- [x] 原神便笺查询
|
||||
- [x] 原神玩家查询
|
||||
- [x] 原神树脂提醒
|
||||
- [x] 原神签到/自动签到
|
||||
- [x] 金币红包
|
||||
- [x] 微博热搜
|
||||
- [x] B站主播/UP/番剧订阅
|
||||
|
||||
- [x] pil对图片的一些操作
|
||||
- [x] BUFF饰品底价查询(需要session)
|
||||
- [x] 天气查询
|
||||
- [x] 疫情查询
|
||||
- [x] bt磁力搜索(咳咳,这功能我想dddd)
|
||||
- [x] reimu搜索(上车) (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
|
||||
- [x] 靠图识番 (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
|
||||
- [x] 以图搜图 (使用[nonebot_plugin_picsearcher](https://github.com/synodriver/nonebot_plugin_picsearcher)插件)
|
||||
- [x] 搜番
|
||||
- [x] 点歌 [nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2)插件(删除了选歌和评论)
|
||||
- [x] epic免费游戏
|
||||
- [x] p站排行榜
|
||||
- [x] p站搜图
|
||||
- [x] 翻译(日英韩)
|
||||
- [x] pix图库(一个自己的图库,含有增删查改,黑名单等命令)
|
||||
* [x] 昵称系统(群与群与私聊分开.)
|
||||
|
||||
- [x] 查看当前群欢迎消息
|
||||
- [x] 查看该群自己的权限
|
||||
- [x] 我的信息(只是为了看看什么时候入群)
|
||||
- [x] 更新信息(如果继续更新的话)
|
||||
- [x] go-cqhttp最新版下载和上传(不需要请删除)
|
||||
- [x] 撤回
|
||||
- [x] 滴滴滴-(用户对超级用户发送消息)
|
||||
- [x] 金币红包/金币排行
|
||||
- [x] 俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
|
||||
- [x] 网易云热评
|
||||
- [x] 念首古诗
|
||||
- [x] 获取b站视频封面
|
||||
- [x] 通过PID获取图片
|
||||
- [x] 功能统计可视化
|
||||
- [x] 词云
|
||||
- [x] 关于
|
||||
* [x] 图灵AI(会把'你'等关键字替换为你的昵称),且带有 [AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus),够味
|
||||
* [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置)
|
||||
* [x] 发送某文件夹下的随机图片(支持自定义,默认:美图,萝莉,壁纸)
|
||||
* [x] 色图(这不是基础功能嘛喂)
|
||||
* [x] coser
|
||||
* [x] 黑白草图生成器
|
||||
* [x] 鸡汤/语录
|
||||
* [x] 骂我(钉宫语音)
|
||||
* [x] 戳一戳(概率发送美图,钉宫语音或者戳回去)
|
||||
* [x] 模拟开箱/我的开箱/群开箱统计/我的金色/设置cookie(csgo,内置爬虫脚本,需要提前抓取数据和图片,需要session,可能需要代理,阿里云服务器等ip也许已经被ban了(我无代理访问失败),如果访问太多账号API调用可能被禁止访问api!)
|
||||
* [x] 鲁迅说过
|
||||
* [x] 构造假消息(自定义的分享链接)
|
||||
* [x] 商店/我的金币/购买道具/使用道具
|
||||
* [x] 8种手游抽卡 (查看 [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw))
|
||||
* [x] 我有一个朋友想问问..(借鉴pcrbot插件)
|
||||
* [x] 原神黄历
|
||||
* [x] 原神今日素材
|
||||
* [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
|
||||
* [x] 原神便笺查询
|
||||
* [x] 原神玩家查询
|
||||
* [x] 原神树脂提醒
|
||||
* [x] 原神签到/自动签到
|
||||
* [x] 金币红包
|
||||
* [x] 微博热搜
|
||||
* [x] B站主播/UP/番剧订阅
|
||||
|
||||
* [x] pil对图片的一些操作
|
||||
* [x] BUFF饰品底价查询(需要session)
|
||||
* [x] 天气查询
|
||||
* [x] 疫情查询
|
||||
* [x] bt磁力搜索(咳咳,这功能我想dddd)
|
||||
* [x] reimu搜索(上车) (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
|
||||
* [x] 靠图识番 (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
|
||||
* [x] 以图搜图 (使用[nonebot_plugin_picsearcher](https://github.com/synodriver/nonebot_plugin_picsearcher)插件)
|
||||
* [x] 搜番
|
||||
* [x] 点歌 [nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2)插件(删除了选歌和评论)
|
||||
* [x] epic免费游戏
|
||||
* [x] p站排行榜
|
||||
* [x] p站搜图
|
||||
* [x] 翻译(日英韩)
|
||||
* [x] pix图库(一个自己的图库,含有增删查改,黑名单等命令)
|
||||
|
||||
* [x] 查看当前群欢迎消息
|
||||
* [x] 查看该群自己的权限
|
||||
* [x] 我的信息(只是为了看看什么时候入群)
|
||||
* [x] 更新信息(如果继续更新的话)
|
||||
* [x] go-cqhttp最新版下载和上传(不需要请删除)
|
||||
* [x] 撤回
|
||||
* [x] 滴滴滴-(用户对超级用户发送消息)
|
||||
* [x] 金币红包/金币排行
|
||||
* [x] 俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
|
||||
* [x] 网易云热评
|
||||
* [x] 念首古诗
|
||||
* [x] 获取b站视频封面
|
||||
* [x] 通过PID获取图片
|
||||
* [x] 功能统计可视化
|
||||
* [x] 词云
|
||||
* [x] 关于
|
||||
|
||||
### 已实现的管理员功能
|
||||
- [x] 更新群组成员信息
|
||||
- [x] 95%的群功能开关
|
||||
- [x] 查看群内被动技能状态
|
||||
- [x] 自定义群欢迎消息(是真寻的不是管家的!)
|
||||
- [x] .ban/.unban(支持设置ban时长)= 黑白名单
|
||||
- [x] 刷屏禁言相关:刷屏检测设置/设置禁言时长/设置检测次数
|
||||
- [x] 上传图片/连续上传图片 (上传图片至指定图库)
|
||||
- [x] 移动图片 (同上)
|
||||
- [x] 删除图片 (同上)
|
||||
- [x] 群内B站订阅
|
||||
- [x] 词条设置
|
||||
- [x] 休息吧/醒来
|
||||
|
||||
* [x] 更新群组成员信息
|
||||
|
||||
* [x] 95%的群功能开关
|
||||
* [x] 查看群内被动技能状态
|
||||
* [x] 自定义群欢迎消息(是真寻的不是管家的!)
|
||||
* [x] .ban/.unban(支持设置ban时长)= 黑白名单
|
||||
* [x] 刷屏禁言相关:刷屏检测设置/设置禁言时长/设置检测次数
|
||||
* [x] 上传图片/连续上传图片 (上传图片至指定图库)
|
||||
* [x] 移动图片 (同上)
|
||||
* [x] 删除图片 (同上)
|
||||
* [x] 群内B站订阅
|
||||
* [x] 词条设置
|
||||
* [x] 休息吧/醒来
|
||||
|
||||
### 已实现的超级用户功能
|
||||
- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
|
||||
- [x] 开启/关闭指定群的广播通知
|
||||
- [x] 广播
|
||||
- [x] 自检(检查系统状态)
|
||||
- [x] 所有群组/所有好友
|
||||
- [x] 退出指定群
|
||||
- [x] 更新好友信息/更新群信息
|
||||
- [x] /t(对用户进行回复或发送消息)
|
||||
- [x] 上传/删除/修改商品(需要编写对应的商品功能)
|
||||
- [x] 节日红包发送
|
||||
- [x] 修改群权限
|
||||
- [x] ban
|
||||
- [x] 更新色图
|
||||
- [x] 更新价格/更加图片(csgo开箱)
|
||||
- [x] 重载原神/方舟/赛马娘/坎公骑冠剑卡池
|
||||
- [x] 更新原神今日素材/更新原神资源信息
|
||||
- [x] PIX相关操作
|
||||
- [x] 检查更新真寻
|
||||
- [x] 重启
|
||||
- [x] 添加/删除/查看群白名单
|
||||
- [x] 功能开关(更多设置)
|
||||
- [x] 功能状态
|
||||
- [x] b了
|
||||
- [x] 执行sql
|
||||
- [x] 重载配置
|
||||
- [x] 清理临时数据
|
||||
- [x] 增删群认证
|
||||
- [x] 同意/拒绝好友/群聊请求
|
||||
- [x] 配置重载
|
||||
|
||||
* [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
|
||||
|
||||
* [x] 开启/关闭指定群的广播通知
|
||||
* [x] 广播
|
||||
* [x] 自检(检查系统状态)
|
||||
* [x] 所有群组/所有好友
|
||||
* [x] 退出指定群
|
||||
* [x] 更新好友信息/更新群信息
|
||||
* [x] /t(对用户进行回复或发送消息)
|
||||
* [x] 上传/删除/修改商品(需要编写对应的商品功能)
|
||||
* [x] 节日红包发送
|
||||
* [x] 修改群权限
|
||||
* [x] ban
|
||||
* [x] 更新色图
|
||||
* [x] 更新价格/更加图片(csgo开箱)
|
||||
* [x] 重载原神/方舟/赛马娘/坎公骑冠剑卡池
|
||||
* [x] 更新原神今日素材/更新原神资源信息
|
||||
* [x] PIX相关操作
|
||||
* [x] 检查更新真寻
|
||||
* [x] 重启
|
||||
* [x] 添加/删除/查看群白名单
|
||||
* [x] 功能开关(更多设置)
|
||||
* [x] 功能状态
|
||||
* [x] b了
|
||||
* [x] 执行sql
|
||||
* [x] 重载配置
|
||||
* [x] 清理临时数据
|
||||
* [x] 增删群认证
|
||||
* [x] 同意/拒绝好友/群聊请求
|
||||
* [x] 配置重载
|
||||
|
||||
#### 超级用户的被动技能
|
||||
- [x] 邀请入群提醒(别人邀请真寻入群)
|
||||
- [x] 添加好友提醒(别人添加真寻好友)
|
||||
|
||||
* [x] 邀请入群提醒(别人邀请真寻入群)
|
||||
|
||||
* [x] 添加好友提醒(别人添加真寻好友)
|
||||
|
||||
### 已实现的被动技能
|
||||
- [x] 进群欢迎消息
|
||||
- [x] 群早晚安
|
||||
- [x] 每日开箱重置提醒
|
||||
- [x] b站转发解析(解析b站分享信息,支持bv,bilibili链接,b站手机端转发卡片,cv,b23.tv),且5分钟内不解析相同url
|
||||
- [x] 丢人爬(爬表情包)
|
||||
- [x] epic通知(每日发送epic免费游戏链接)
|
||||
- [x] 原神黄历提醒
|
||||
- [x] 复读
|
||||
|
||||
### 已实现的看不见的技能!
|
||||
- [x] 刷屏禁言检测
|
||||
- [x] 功能调用统计
|
||||
- [x] 检测恶意触发命令(将被最高权限ban掉30分钟,只有最高权限(9级)可以进行unban)
|
||||
- [x] 自动同意好友请求,加群请求将会提醒管理员,退群提示,加群欢迎等等
|
||||
- [x] 群聊时间检测(当群聊最后一人发言时间大于当前36小时后将关闭该群所有通知(即被动技能))
|
||||
- [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限
|
||||
- [x] 群权限系统
|
||||
- [x] 定时更新权限
|
||||
- [x] 自动配置重载
|
||||
* [x] 进群欢迎消息
|
||||
|
||||
* [x] 群早晚安
|
||||
* [x] 每日开箱重置提醒
|
||||
* [x] b站转发解析(解析b站分享信息,支持bv,bilibili链接,b站手机端转发卡片,cv,b23.tv),且5分钟内不解析相同url
|
||||
* [x] 丢人爬(爬表情包)
|
||||
* [x] epic通知(每日发送epic免费游戏链接)
|
||||
* [x] 原神黄历提醒
|
||||
* [x] 复读
|
||||
|
||||
### 已实现的看不见的技能
|
||||
|
||||
* [x] 刷屏禁言检测
|
||||
|
||||
* [x] 功能调用统计
|
||||
* [x] 检测恶意触发命令(将被最高权限ban掉30分钟,只有最高权限(9级)可以进行unban)
|
||||
* [x] 自动同意好友请求,加群请求将会提醒管理员,退群提示,加群欢迎等等
|
||||
* [x] 群聊时间检测(当群聊最后一人发言时间大于当前36小时后将关闭该群所有通知(即被动技能))
|
||||
* [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限
|
||||
* [x] 群权限系统
|
||||
* [x] 定时更新权限
|
||||
* [x] 自动配置重载
|
||||
|
||||
</details>
|
||||
|
||||
## 详细配置请前往文档,以下为最简部署和配置,如果你有基础并学习过nonebot2的话
|
||||
|
||||
|
||||
## 简单部署
|
||||
|
||||
```
|
||||
@ -238,26 +260,38 @@ python bot.py
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 使用Docker
|
||||
__Docker 单机版(仅真寻Bot)__
|
||||
|
||||
**Docker 单机版(仅真寻Bot)**
|
||||
**点击下方的 GitHub 徽标查看教程**
|
||||
[](https://github.com/Sakuracio/zhenxun_bot_docker)
|
||||
[](https://hub.docker.com/r/hibikier/zhenxun_bot)
|
||||
__Docker 全量版(包含 真寻Bot PostgreSQL数据库 go-cqhttp webui等)__
|
||||
**Docker 全量版(包含 真寻Bot PostgreSQL数据库 go-cqhttp webui等)**
|
||||
[](https://github.com/SinKy-Yan/zhenxunbot-docker)
|
||||
[](https://hub.docker.com/r/jyishit/zhenxun_bot)
|
||||
**点击上方的 GitHub 徽标查看教程**
|
||||
PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能无法正常启动全量版容器**
|
||||
|
||||
## [爱发电](https://afdian.net/@HibiKier)
|
||||
|
||||
<details>
|
||||
<summary>爱发电 以及 感谢投喂 </summary>
|
||||
<img width="365px" height="450px" src="https://user-images.githubusercontent.com/45528451/175059389-cfeb8174-fa07-4939-80ab-a039087a50f6.png">
|
||||
|
||||
### 感谢名单
|
||||
(可以告诉我你的 __github__ 地址,我偷偷换掉0v|)
|
||||
|
||||
(可以告诉我你的 **github** 地址,我偷偷换掉0v|)
|
||||
|
||||
[shenqi](https://afdian.net/u/fa923a8cfe3d11eba61752540025c377)
|
||||
[A_Kyuu](https://afdian.net/u/b83954fc2c1211eba9eb52540025c377)
|
||||
[疯狂混沌](https://afdian.net/u/789a2f9200cd11edb38352540025c377)
|
||||
[投冥](https://afdian.net/a/144514mm)
|
||||
[茶喵](https://afdian.net/u/fd22382eac4d11ecbfc652540025c377)
|
||||
[AemokpaTNR](https://afdian.net/u/1169bb8c8a9611edb0c152540025c377)
|
||||
[爱发电用户_wrxn](https://afdian.net/u/4aa03d20db4311ecb1e752540025c377)
|
||||
[qqw](https://afdian.net/u/b71db4e2cc3e11ebb76652540025c377)
|
||||
[溫一壺月光下酒](https://afdian.net/u/ad667a5c650c11ed89bf52540025c377)
|
||||
[伝木](https://afdian.net/u/246b80683f9511edba7552540025c377)
|
||||
[阿奎](https://afdian.net/u/da41f72845d511ed930d52540025c377)
|
||||
[醉梦尘逸](https://afdian.net/u/bc11d2683cd011ed99b552540025c377)
|
||||
[Abc](https://afdian.net/u/870dc10a3cd311ed828852540025c377)
|
||||
@ -280,25 +314,37 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
|
||||
[ln](https://afdian.net/u/b51914ba1c6611ed8a4e52540025c377)
|
||||
[爱发电用户_b9S4](https://afdian.net/u/3d8f30581a2911edba6d52540025c377)
|
||||
[爱发电用户_c58s](https://afdian.net/u/a6ad8dda195e11ed9a4152540025c377)
|
||||
[爱发电用户_eNr9](https://afdian.net/u/05fdb41c0c9a11ed814952540025c377)
|
||||
[MangataAkihi](https://github.com/Sakuracio)
|
||||
[炀](https://afdian.net/u/69b76e9ec77b11ec874f52540025c377)
|
||||
[爱发电用户_eNr9](https://afdian.net/u/05fdb41c0c9a11ed814952540025c377)
|
||||
[MangataAkihi](https://github.com/Sakuracio)
|
||||
[炀](https://afdian.net/u/69b76e9ec77b11ec874f52540025c377)
|
||||
[爱发电用户_Bc6j](https://afdian.net/u/8546be24f44111eca64052540025c377)
|
||||
[大魔王](https://github.com/xipesoy)
|
||||
[大魔王](https://github.com/xipesoy)
|
||||
[CopilotLaLaLa](https://github.com/CopilotLaLaLa)
|
||||
[嘿小欧](https://afdian.net/u/daa4bec4f24911ec82e552540025c377)
|
||||
[嘿小欧](https://afdian.net/u/daa4bec4f24911ec82e552540025c377)
|
||||
[回忆的秋千](https://afdian.net/u/e315d9c6f14f11ecbeef52540025c377)
|
||||
[十年くん](https://github.com/shinianj)
|
||||
[哇](https://afdian.net/u/9b266244f23911eca19052540025c377)
|
||||
[yajiwa](https://github.com/yajiwa)
|
||||
[爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377)
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
## 更新
|
||||
|
||||
### 2022/2/18
|
||||
|
||||
* 数据库舍弃`gino`使用`tortoise`
|
||||
* 昵称提供命令`全局昵称设置`
|
||||
* `manager_group`群管理操作中`退群`,`修改群权限`,`添加/删除群白名单`,`添加/删除群认证`在群聊中使用命令时且未指定群聊时,默认指定当前群聊
|
||||
|
||||
### 2022/1/31
|
||||
|
||||
* 修复B站转发卡片BUG [@pull/1249](https://github.com/HibiKier/zhenxun_bot/pull/1249)
|
||||
|
||||
### 2022/1/27
|
||||
|
||||
* 替换pixiv反向代理地址 [@pull/1244](https://github.com/HibiKier/zhenxun_bot/pull/1244)
|
||||
|
||||
### 2022/12/31
|
||||
|
||||
* 修复epic报错,优化简介 [@pull/1226](https://github.com/HibiKier/zhenxun_bot/pull/1226)
|
||||
@ -457,7 +503,7 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
|
||||
|
||||
### 2022/9/27
|
||||
|
||||
* 更新b站转发解析 [@pull/1117](https://github.com/HibiKier/zhenxun_bot/pull/1117)
|
||||
* 更新b站转发解析 [@pull/1117](https://github.com/HibiKier/zhenxun_bot/pull/1117)
|
||||
|
||||
### 2022/9/24
|
||||
|
||||
@ -556,12 +602,14 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
|
||||
|
||||
<br>
|
||||
|
||||
__..... 更多更新信息请查看文档__
|
||||
**..... 更多更新信息请查看文档**
|
||||
|
||||
## Todo
|
||||
- [x] web管理
|
||||
|
||||
* [x] web管理
|
||||
|
||||
## 感谢
|
||||
|
||||
[botuniverse / onebot](https://github.com/botuniverse/onebot) :超棒的机器人协议
|
||||
[Mrs4s / go-cqhttp](https://github.com/Mrs4s/go-cqhttp) :cqhttp的golang实现,轻量、原生跨平台.
|
||||
[nonebot / nonebot2](https://github.com/nonebot/nonebot2) :跨平台Python异步机器人框架
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
import ujson as json
|
||||
from nonebot.adapters.onebot.v11.message import MessageSegment
|
||||
from services.log import logger
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import DATA_PATH, IMAGE_PATH
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from models.level_user import LevelUser
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.manager import group_manager, plugins2settings_manager, plugins_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import get_bot, get_matchers
|
||||
from pathlib import Path
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from datetime import datetime
|
||||
from services.db_context import db
|
||||
from models.level_user import LevelUser
|
||||
from configs.config import Config
|
||||
from utils.manager import group_manager, plugins2settings_manager, plugins_manager
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import asyncio
|
||||
import time
|
||||
import os
|
||||
import ujson as json
|
||||
|
||||
|
||||
custom_welcome_msg_json = (
|
||||
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
|
||||
)
|
||||
|
||||
ICON_PATH = IMAGE_PATH / 'other'
|
||||
ICON_PATH = IMAGE_PATH / "other"
|
||||
|
||||
|
||||
async def group_current_status(group_id: int) -> str:
|
||||
@ -38,7 +38,9 @@ async def group_current_status(group_id: int) -> str:
|
||||
for i, task in enumerate(_data):
|
||||
name = _data[task]
|
||||
name_image = BuildImage(0, 0, plain_text=f"{i+1}.{name}", font_size=20)
|
||||
bk = BuildImage(name_image.w + 200, name_image.h + 20, color=(103, 177, 109), font_size=15)
|
||||
bk = BuildImage(
|
||||
name_image.w + 200, name_image.h + 20, color=(103, 177, 109), font_size=15
|
||||
)
|
||||
await bk.apaste(name_image, (10, 0), True, "by_height")
|
||||
a_icon = BuildImage(40, 40, background=ICON_PATH / "btn_false.png")
|
||||
if group_manager.check_group_task_status(group_id, task):
|
||||
@ -123,7 +125,7 @@ def change_global_task_status(cmd: str) -> str:
|
||||
task_data = group_manager.get_task_data()
|
||||
status = cmd[:2]
|
||||
_cmd = cmd[4:]
|
||||
if '全部被动' in cmd:
|
||||
if "全部被动" in cmd:
|
||||
for task in task_data:
|
||||
if status == "开启":
|
||||
group_manager.open_global_task(task)
|
||||
@ -134,7 +136,7 @@ def change_global_task_status(cmd: str) -> str:
|
||||
else:
|
||||
modules = [x for x in task_data if task_data[x].lower() == _cmd.lower()]
|
||||
if not modules:
|
||||
return '未查询到该被动任务'
|
||||
return "未查询到该被动任务"
|
||||
if status == "开启":
|
||||
group_manager.open_global_task(modules[0])
|
||||
else:
|
||||
@ -301,50 +303,40 @@ async def update_member_info(group_id: int, remind_superuser: bool = False) -> b
|
||||
# try:
|
||||
for user_info in _group_user_list:
|
||||
nickname = user_info["card"] or user_info["nickname"]
|
||||
async with db.transaction():
|
||||
# 更新权限
|
||||
if user_info["role"] in [
|
||||
"owner",
|
||||
"admin",
|
||||
] and not await LevelUser.is_group_flag(user_info["user_id"], group_id):
|
||||
await LevelUser.set_level(
|
||||
user_info["user_id"],
|
||||
user_info["group_id"],
|
||||
Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
|
||||
)
|
||||
if str(user_info["user_id"]) in bot.config.superusers:
|
||||
await LevelUser.set_level(
|
||||
user_info["user_id"], user_info["group_id"], 9
|
||||
)
|
||||
user = await GroupInfoUser.get_member_info(
|
||||
user_info["user_id"], user_info["group_id"]
|
||||
)
|
||||
if user:
|
||||
if user.user_name != nickname:
|
||||
await user.update(user_name=nickname).apply()
|
||||
logger.info(
|
||||
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
|
||||
)
|
||||
_exist_member_list.append(int(user_info["user_id"]))
|
||||
continue
|
||||
join_time = datetime.strptime(
|
||||
time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
|
||||
),
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
if await GroupInfoUser.add_member_info(
|
||||
# 更新权限
|
||||
if user_info["role"] in [
|
||||
"owner",
|
||||
"admin",
|
||||
] and not await LevelUser.is_group_flag(user_info["user_id"], group_id):
|
||||
await LevelUser.set_level(
|
||||
user_info["user_id"],
|
||||
user_info["group_id"],
|
||||
nickname,
|
||||
join_time,
|
||||
):
|
||||
_exist_member_list.append(int(user_info["user_id"]))
|
||||
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
|
||||
else:
|
||||
_error_member_list.append(
|
||||
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败\n"
|
||||
Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
|
||||
)
|
||||
if str(user_info["user_id"]) in bot.config.superusers:
|
||||
await LevelUser.set_level(user_info["user_id"], user_info["group_id"], 9)
|
||||
user = await GroupInfoUser.filter(
|
||||
user_qq=user_info["user_id"], group_id=user_info["group_id"]
|
||||
).first()
|
||||
if user:
|
||||
if user.user_name != nickname:
|
||||
await user.update(user_name=nickname).apply()
|
||||
logger.info(
|
||||
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
|
||||
)
|
||||
_exist_member_list.append(int(user_info["user_id"]))
|
||||
continue
|
||||
join_time = datetime.strptime(
|
||||
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])),
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
await GroupInfoUser.update_or_create(
|
||||
user_qq=user_info["user_id"],
|
||||
group_id=user_info["group_id"],
|
||||
defaults={"user_name": nickname, "user_join_time": join_time},
|
||||
)
|
||||
_exist_member_list.append(int(user_info["user_id"]))
|
||||
logger.info("更新成功", "更新成员信息", user_info["user_id"], user_info["group_id"])
|
||||
_del_member_list = list(
|
||||
set(_exist_member_list).difference(
|
||||
set(await GroupInfoUser.get_group_member_id_list(group_id))
|
||||
@ -352,10 +344,8 @@ async def update_member_info(group_id: int, remind_superuser: bool = False) -> b
|
||||
)
|
||||
if _del_member_list:
|
||||
for del_user in _del_member_list:
|
||||
if await GroupInfoUser.delete_member_info(del_user, group_id):
|
||||
logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
|
||||
else:
|
||||
logger.info(f"退群用户{del_user} 所属{group_id} 删除失败")
|
||||
await GroupInfoUser.filter(user_qq=del_user, group_id=group_id).delete()
|
||||
logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
|
||||
if _error_member_list and remind_superuser:
|
||||
result = ""
|
||||
for error_user in _error_member_list:
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
from nonebot import on_notice
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import GroupAdminNoticeEvent
|
||||
from models.level_user import LevelUser
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from configs.config import Config
|
||||
|
||||
from configs.config import Config
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from models.level_user import LevelUser
|
||||
from services.log import logger
|
||||
|
||||
__zx_plugin_name__ = "群管理员变动监测 [Hidden]"
|
||||
__plugin_version__ = 0.1
|
||||
@ -16,11 +16,11 @@ admin_notice = on_notice(priority=5)
|
||||
|
||||
@admin_notice.handle()
|
||||
async def _(event: GroupAdminNoticeEvent):
|
||||
try:
|
||||
nickname = (
|
||||
await GroupInfoUser.get_member_info(event.user_id, event.group_id)
|
||||
).user_name
|
||||
except AttributeError:
|
||||
if user := await GroupInfoUser.filter(
|
||||
user_qq=event.user_id, group_id=event.group_id
|
||||
).first():
|
||||
nickname = user.nickname
|
||||
else:
|
||||
nickname = event.user_id
|
||||
if event.sub_type == "set":
|
||||
await LevelUser.set_level(
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
from typing import List
|
||||
|
||||
from configs.config import Config
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
|
||||
from nonebot.params import CommandArg
|
||||
from ._data_source import custom_group_welcome
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from configs.config import Config
|
||||
from nonebot.params import CommandArg
|
||||
from services.log import logger
|
||||
from utils.depends import ImageList
|
||||
|
||||
from ._data_source import custom_group_welcome
|
||||
|
||||
__zx_plugin_name__ = "自定义进群欢迎消息 [Admin]"
|
||||
__plugin_usage__ = """
|
||||
@ -19,12 +19,14 @@ usage:
|
||||
Note:可以通过[at]来确认是否艾特新成员
|
||||
示例:自定义进群欢迎消息 欢迎你[at]
|
||||
""".strip()
|
||||
__plugin_des__ = '简易的自定义群欢迎消息'
|
||||
__plugin_cmd__ = ['自定义群欢迎消息 ?[文本] ?[图片]']
|
||||
__plugin_des__ = "简易的自定义群欢迎消息"
|
||||
__plugin_cmd__ = ["自定义群欢迎消息 ?[文本] ?[图片]"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = 'HibiKier'
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"admin_level": Config.get_config("admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL"),
|
||||
"admin_level": Config.get_config(
|
||||
"admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL"
|
||||
),
|
||||
}
|
||||
|
||||
custom_welcome = on_command(
|
||||
@ -37,7 +39,9 @@ custom_welcome = on_command(
|
||||
|
||||
|
||||
@custom_welcome.handle()
|
||||
async def _(event: GroupMessageEvent, arg: Message = CommandArg(), img: List[str] = ImageList()):
|
||||
async def _(
|
||||
event: GroupMessageEvent, arg: Message = CommandArg(), img: List[str] = ImageList()
|
||||
):
|
||||
msg = arg.extract_plain_text().strip()
|
||||
if not msg and not img:
|
||||
await custom_welcome.finish(__plugin_usage__)
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
from utils.utils import scheduler, get_bot
|
||||
from ._data_source import update_member_info
|
||||
from services.log import logger
|
||||
from models.group_info import GroupInfo
|
||||
from asyncpg.exceptions import ConnectionDoesNotExistError, UndefinedColumnError
|
||||
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from utils.utils import get_bot, scheduler
|
||||
|
||||
__zx_plugin_name__ = '管理方面定时任务 [Hidden]'
|
||||
__plugin_usage__ = '无'
|
||||
__plugin_des__ = '成员信息和管理权限的定时更新'
|
||||
from ._data_source import update_member_info
|
||||
|
||||
__zx_plugin_name__ = "管理方面定时任务 [Hidden]"
|
||||
__plugin_usage__ = "无"
|
||||
__plugin_des__ = "成员信息和管理权限的定时更新"
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = 'HibiKier'
|
||||
__plugin_author__ = "HibiKier"
|
||||
|
||||
|
||||
# 自动更新群员信息
|
||||
@ -42,7 +43,7 @@ async def _():
|
||||
if bot:
|
||||
gl = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in gl]
|
||||
all_group = [x.group_id for x in await GroupInfo.get_all_group()]
|
||||
all_group = [x.group_id for x in await GroupInfo.all()]
|
||||
for g in gl:
|
||||
if g not in all_group:
|
||||
await update_member_info(g, False)
|
||||
|
||||
@ -1,18 +1,22 @@
|
||||
from utils.message_builder import image
|
||||
from utils.utils import scheduler, get_bot
|
||||
from nonebot import on_message
|
||||
from services.log import logger
|
||||
from models.group_info import GroupInfo
|
||||
from models.friend_user import FriendUser
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
from configs.config import NICKNAME, Config
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import nonebot
|
||||
from nonebot import on_message
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from models.friend_user import FriendUser
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from utils.message_builder import image
|
||||
from utils.utils import broadcast_group, get_bot, scheduler
|
||||
|
||||
__zx_plugin_name__ = "定时任务相关 [Hidden]"
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_task__ = {'zwa': '早晚安'}
|
||||
__plugin_task__ = {"zwa": "早晚安"}
|
||||
|
||||
|
||||
Config.add_plugin_config(
|
||||
@ -24,20 +28,23 @@ Config.add_plugin_config(
|
||||
)
|
||||
|
||||
Config.add_plugin_config(
|
||||
"_backup",
|
||||
"BACKUP_FLAG",
|
||||
True,
|
||||
help_="是否开启文件备份",
|
||||
default_value=True
|
||||
"_backup", "BACKUP_FLAG", True, help_="是否开启文件备份", default_value=True
|
||||
)
|
||||
|
||||
Config.add_plugin_config(
|
||||
"_backup",
|
||||
"BACKUP_DIR_OR_FILE",
|
||||
['data/black_word', 'data/configs', 'data/statistics', 'data/word_bank', 'data/manager', 'configs'],
|
||||
[
|
||||
"data/black_word",
|
||||
"data/configs",
|
||||
"data/statistics",
|
||||
"data/word_bank",
|
||||
"data/manager",
|
||||
"configs",
|
||||
],
|
||||
name="文件备份",
|
||||
help_="备份的文件夹或文件",
|
||||
default_value=[]
|
||||
default_value=[],
|
||||
)
|
||||
|
||||
|
||||
@ -51,18 +58,9 @@ cx = on_message(priority=9999, block=False, rule=lambda: False)
|
||||
minute=1,
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
bot = get_bot()
|
||||
gl = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in gl]
|
||||
for g in gl:
|
||||
result = image("zao.jpg", "zhenxun")
|
||||
try:
|
||||
await bot.send_group_msg(group_id=g, message="[[_task|zwa]]早上好" + result)
|
||||
except ActionFailed:
|
||||
logger.warning(f"{g} 发送早安失败")
|
||||
except Exception as e:
|
||||
logger.error(f"早晚安错误 e:{e}")
|
||||
img = image(IMAGE_PATH / "zhenxun" / "zao.jpg")
|
||||
await broadcast_group("[[_task|zwa]]早上好" + img, log_cmd="被动早晚安")
|
||||
logger.info("每日早安发送")
|
||||
|
||||
|
||||
# 睡觉了
|
||||
@ -72,20 +70,9 @@ async def _():
|
||||
minute=59,
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
bot = get_bot()
|
||||
gl = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in gl]
|
||||
for g in gl:
|
||||
result = image("sleep.jpg", "zhenxun")
|
||||
try:
|
||||
await bot.send_group_msg(
|
||||
group_id=g, message=f"[[_task|zwa]]{NICKNAME}要睡觉了,你们也要早点睡呀" + result
|
||||
)
|
||||
except ActionFailed:
|
||||
logger.warning(f"{g} 发送晚安失败")
|
||||
except Exception as e:
|
||||
logger.error(f"早晚安错误 e:{e}")
|
||||
img = image(IMAGE_PATH / "zhenxun" / "sleep.jpg")
|
||||
await broadcast_group("[[_task|zwa]]{NICKNAME}要睡觉了,你们也要早点睡呀" + img, log_cmd="被动早晚安")
|
||||
logger.info("每日晚安发送")
|
||||
|
||||
|
||||
# 自动更新群组信息
|
||||
@ -95,22 +82,27 @@ async def _():
|
||||
minute=1,
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
bot = get_bot()
|
||||
gl = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in gl]
|
||||
for g in gl:
|
||||
group_info = await bot.get_group_info(group_id=g)
|
||||
await GroupInfo.add_group_info(
|
||||
group_info["group_id"],
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1
|
||||
)
|
||||
logger.info(f"自动更新群组 {g} 信息成功")
|
||||
except Exception as e:
|
||||
logger.error(f"自动更新群组信息错误 e:{e}")
|
||||
bots = nonebot.get_bots()
|
||||
_used_group = []
|
||||
for bot in bots.values():
|
||||
try:
|
||||
group_list = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in group_list if g["group_id"] not in _used_group]
|
||||
for g in gl:
|
||||
_used_group.append(g)
|
||||
group_info = await bot.get_group_info(group_id=g)
|
||||
await GroupInfo.update_or_create(
|
||||
group_id=group_info["group_id"],
|
||||
defaults={
|
||||
"group_name": group_info["group_name"],
|
||||
"max_member_count": group_info["max_member_count"],
|
||||
"member_count": group_info["member_count"],
|
||||
"group_flag": 1,
|
||||
},
|
||||
)
|
||||
logger.info(f"自动更新群组信息成功", group_id=g)
|
||||
except Exception as e:
|
||||
logger.error(f"Bot: {bot.self_id} 自动更新群组信息", e=e)
|
||||
|
||||
|
||||
# 自动更新好友信息
|
||||
@ -124,10 +116,10 @@ async def _():
|
||||
bot = get_bot()
|
||||
fl = await bot.get_friend_list()
|
||||
for f in fl:
|
||||
if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
|
||||
logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
|
||||
else:
|
||||
logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
|
||||
await FriendUser.create(user_id=f["user_id"], user_name=f["nickname"])
|
||||
logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
|
||||
# else:
|
||||
# logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
|
||||
except Exception as e:
|
||||
logger.error(f"自动更新群组信息错误 e:{e}")
|
||||
|
||||
@ -140,7 +132,7 @@ async def _():
|
||||
)
|
||||
async def _():
|
||||
if Config.get_config("_backup", "BACKUP_FLAG"):
|
||||
_backup_path = Path() / 'backup'
|
||||
_backup_path = Path() / "backup"
|
||||
_backup_path.mkdir(exist_ok=True, parents=True)
|
||||
for x in Config.get_config("_backup", "BACKUP_DIR_OR_FILE"):
|
||||
try:
|
||||
@ -155,12 +147,13 @@ async def _():
|
||||
if _p.exists():
|
||||
_p.unlink()
|
||||
shutil.copy(x, _p)
|
||||
logger.info(f'已完成自动备份:{x}')
|
||||
logger.info(f"已完成自动备份:{x}")
|
||||
except Exception as e:
|
||||
logger.error(f"自动备份文件 {x} 发生错误 {type(e)}:{e}")
|
||||
|
||||
|
||||
# 一次性任务
|
||||
|
||||
|
||||
# 固定时间触发,仅触发一次:
|
||||
#
|
||||
# from datetime import datetime
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
from typing import Tuple, List
|
||||
from typing import List
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
GroupMessageEvent,
|
||||
Message,
|
||||
MessageEvent,
|
||||
PrivateMessageEvent,
|
||||
)
|
||||
from nonebot.params import CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from models.ban_user import BanUser
|
||||
from models.level_user import LevelUser
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import (Bot, GroupMessageEvent, Message,
|
||||
MessageEvent, PrivateMessageEvent)
|
||||
from nonebot.params import Command, CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
from services.log import logger
|
||||
from utils.depends import AtList
|
||||
from utils.utils import get_message_at, is_number
|
||||
from utils.depends import AtList, OneCommand
|
||||
from utils.utils import is_number
|
||||
|
||||
from .data_source import a_ban, parse_ban_time
|
||||
|
||||
@ -68,46 +74,38 @@ super_ban = on_command("b了", permission=SUPERUSER, priority=5, block=True)
|
||||
async def _(
|
||||
bot: Bot,
|
||||
event: GroupMessageEvent,
|
||||
cmd: Tuple[str, ...] = Command(),
|
||||
cmd: str = OneCommand(),
|
||||
arg: Message = CommandArg(),
|
||||
qq: List[int] = AtList()
|
||||
at_list: List[int] = AtList(),
|
||||
):
|
||||
cmd = cmd[0]
|
||||
result = ""
|
||||
if qq:
|
||||
qq = qq[0]
|
||||
user_name = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||
user_name = user_name["card"] or user_name["nickname"]
|
||||
if at_list:
|
||||
qq = at_list[0]
|
||||
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||
user_name = user["card"] or user["nickname"]
|
||||
msg = arg.extract_plain_text().strip()
|
||||
time = parse_ban_time(msg)
|
||||
if isinstance(time, str):
|
||||
await ban.finish(time, at_sender=True)
|
||||
user_level = await LevelUser.get_user_level(event.user_id, event.group_id)
|
||||
is_not_superuser = str(event.user_id) not in bot.config.superusers
|
||||
if cmd in [".ban", "/ban"]:
|
||||
if (
|
||||
await LevelUser.get_user_level(event.user_id, event.group_id)
|
||||
<= await LevelUser.get_user_level(qq, event.group_id)
|
||||
and str(event.user_id) not in bot.config.superusers
|
||||
):
|
||||
at_user_level = await LevelUser.get_user_level(qq, event.group_id)
|
||||
if user_level <= at_user_level and is_not_superuser:
|
||||
await ban.finish(
|
||||
f"您的权限等级比对方低或相等, {NICKNAME}不能为您使用此功能!",
|
||||
at_sender=True,
|
||||
)
|
||||
logger.info(f"用户封禁 时长: {time}", cmd, event.user_id, event.group_id, qq)
|
||||
result = await a_ban(qq, time, user_name, event)
|
||||
else:
|
||||
if (
|
||||
await BanUser.check_ban_level(
|
||||
qq, await LevelUser.get_user_level(event.user_id, event.group_id)
|
||||
)
|
||||
and str(event.user_id) not in bot.config.superusers
|
||||
):
|
||||
if await BanUser.check_ban_level(qq, user_level) and is_not_superuser:
|
||||
await ban.finish(
|
||||
f"ban掉 {user_name} 的管理员权限比您高,无法进行unban", at_sender=True
|
||||
)
|
||||
if await BanUser.unban(qq):
|
||||
logger.info(
|
||||
f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 解禁"
|
||||
)
|
||||
result = f"已经把 {user_name} 从黑名单中删除了!"
|
||||
logger.info(f"解除用户封禁", cmd, event.user_id, event.group_id, qq)
|
||||
result = f"已经将 {user_name} 从黑名单中删除了!"
|
||||
else:
|
||||
result = f"{user_name} 不在黑名单!"
|
||||
else:
|
||||
@ -119,54 +117,62 @@ async def _(
|
||||
async def _(
|
||||
bot: Bot,
|
||||
event: PrivateMessageEvent,
|
||||
cmd: Tuple[str, ...] = Command(),
|
||||
cmd: str = OneCommand(),
|
||||
arg: Message = CommandArg(),
|
||||
):
|
||||
cmd = cmd[0]
|
||||
msg = arg.extract_plain_text().strip()
|
||||
if msg:
|
||||
if str(event.user_id) in bot.config.superusers:
|
||||
msg_splt = msg.split()
|
||||
if is_number(msg_splt[0]):
|
||||
qq = int(msg_splt[0])
|
||||
msg = msg_splt[1:]
|
||||
if cmd in [".ban", "/ban"]:
|
||||
time = parse_ban_time(" ".join(msg))
|
||||
if isinstance(time, str):
|
||||
await ban.finish(time)
|
||||
result = await a_ban(qq, time, str(qq), event, 9)
|
||||
else:
|
||||
if await BanUser.unban(qq):
|
||||
logger.info(f"USER {event.user_id} 将 USER {qq} 解禁")
|
||||
result = f"已经把 {qq} 从黑名单中删除了!"
|
||||
else:
|
||||
result = f"{qq} 不在黑名单!"
|
||||
await ban.send(result)
|
||||
if msg and str(event.user_id) in bot.config.superusers:
|
||||
msg_split = msg.split()
|
||||
if msg_split and is_number(msg_split[0]):
|
||||
qq = int(msg_split[0])
|
||||
param = msg_split[1:]
|
||||
if cmd in [".ban", "/ban"]:
|
||||
time = parse_ban_time(" ".join(param))
|
||||
if isinstance(time, str):
|
||||
logger.info(time, cmd, event.user_id, target=qq)
|
||||
await ban.finish(time)
|
||||
result = await a_ban(qq, time, str(qq), event, 9)
|
||||
else:
|
||||
await ban.finish(
|
||||
"qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?", at_sender=True
|
||||
)
|
||||
if await BanUser.unban(qq):
|
||||
result = f"已经把 {qq} 从黑名单中删除了!"
|
||||
else:
|
||||
result = f"{qq} 不在黑名单!"
|
||||
await ban.send(result)
|
||||
logger.info(result, cmd, event.user_id, target=qq)
|
||||
else:
|
||||
await ban.send("参数不正确!\n格式:.ban [qq] [hour]? [minute]?", at_sender=True)
|
||||
|
||||
|
||||
@super_ban.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
async def _(
|
||||
bot: Bot,
|
||||
event: MessageEvent,
|
||||
cmd: str = OneCommand(),
|
||||
arg: Message = CommandArg(),
|
||||
at_list: List[int] = AtList(),
|
||||
):
|
||||
user_name = ""
|
||||
qq = None
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
qq = get_message_at(event.json())
|
||||
if qq:
|
||||
qq = qq[0]
|
||||
if at_list:
|
||||
qq = at_list[0]
|
||||
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||
user_name = user["card"] or user["nickname"]
|
||||
else:
|
||||
qq = arg.extract_plain_text().strip()
|
||||
if not is_number(qq):
|
||||
msg = arg.extract_plain_text().strip()
|
||||
if not is_number(msg):
|
||||
await super_ban.finish("对象qq必须为纯数字...")
|
||||
qq = int(qq)
|
||||
user_name = qq
|
||||
qq = int(msg)
|
||||
user_name = msg
|
||||
if qq:
|
||||
if not await BanUser.ban(qq, 10, 99999999):
|
||||
await BanUser.unban(qq)
|
||||
await BanUser.ban(qq, 10, 99999999)
|
||||
await BanUser.ban(qq, 10, 99999999)
|
||||
await ban.send(f"已将 {user_name} 拉入黑名单!")
|
||||
logger.info(
|
||||
f"已将 {user_name} 拉入黑名单!",
|
||||
cmd,
|
||||
event.user_id,
|
||||
event.group_id if isinstance(event, GroupMessageEvent) else None,
|
||||
qq,
|
||||
)
|
||||
else:
|
||||
await super_ban.send("需要添加被super ban的对象,可以使用at或者指定qq..")
|
||||
await super_ban.send("需要提供被super ban的对象,可以使用at或者指定qq...")
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
|
||||
from typing import Optional, Union
|
||||
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
|
||||
from configs.config import NICKNAME
|
||||
from models.level_user import LevelUser
|
||||
from utils.utils import is_number
|
||||
from models.ban_user import BanUser
|
||||
from models.level_user import LevelUser
|
||||
from services.log import logger
|
||||
from typing import Union
|
||||
from utils.utils import is_number
|
||||
|
||||
|
||||
def parse_ban_time(msg: str) -> Union[int, str]:
|
||||
@ -12,21 +14,31 @@ def parse_ban_time(msg: str) -> Union[int, str]:
|
||||
解析ban时长
|
||||
:param msg: 文本消息
|
||||
"""
|
||||
if not msg:
|
||||
return -1
|
||||
msg = msg.split()
|
||||
if len(msg) == 1:
|
||||
if not is_number(msg[0].strip()):
|
||||
return "参数必须是数字!"
|
||||
return int(msg[0]) * 60 * 60
|
||||
else:
|
||||
if not is_number(msg[0].strip()) or not is_number(msg[1].strip()):
|
||||
return "参数必须是数字!"
|
||||
return int(msg[0]) * 60 * 60 + int(msg[1]) * 60
|
||||
try:
|
||||
if not msg:
|
||||
return -1
|
||||
msg_split = msg.split()
|
||||
if len(msg_split) == 1:
|
||||
if not is_number(msg_split[0].strip()):
|
||||
return "参数必须是数字!"
|
||||
return int(msg_split[0]) * 60 * 60
|
||||
else:
|
||||
if not is_number(msg_split[0].strip()) or not is_number(
|
||||
msg_split[1].strip()
|
||||
):
|
||||
return "参数必须是数字!"
|
||||
return int(msg_split[0]) * 60 * 60 + int(msg_split[1]) * 60
|
||||
except ValueError as e:
|
||||
logger.error("解析ban时长错误", ".ban", e=e)
|
||||
return "时长不可以带小数点!"
|
||||
|
||||
|
||||
async def a_ban(
|
||||
qq: int, time: int, user_name: str, event: MessageEvent, ban_level: int = None
|
||||
qq: int,
|
||||
time: int,
|
||||
user_name: str,
|
||||
event: MessageEvent,
|
||||
ban_level: Optional[int] = None,
|
||||
) -> str:
|
||||
"""
|
||||
ban
|
||||
@ -36,12 +48,15 @@ async def a_ban(
|
||||
:param event: event
|
||||
:param ban_level: ban级别
|
||||
"""
|
||||
group_id = None
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
group_id = event.group_id
|
||||
ban_level = await LevelUser.get_user_level(event.user_id, event.group_id)
|
||||
if not ban_level:
|
||||
return "未查询到ban级用户权限"
|
||||
if await BanUser.ban(qq, ban_level, time):
|
||||
logger.info(
|
||||
f"USER {event.user_id} GROUP"
|
||||
f" {event.group_id if isinstance(event, GroupMessageEvent) else ''} 将 USER {qq} 封禁 时长 {time / 60} 分钟"
|
||||
f"将 [Target]({qq})封禁 时长 {time / 60} 分钟", ".ban", event.user_id, group_id
|
||||
)
|
||||
result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
|
||||
if time != -1:
|
||||
@ -49,14 +64,14 @@ async def a_ban(
|
||||
else:
|
||||
result += f"将在 ∞ 分钟后解封"
|
||||
else:
|
||||
time = await BanUser.check_ban_time(qq)
|
||||
if is_number(time):
|
||||
time = abs(int(time))
|
||||
if time < 60:
|
||||
time = str(time) + " 秒"
|
||||
ban_time = await BanUser.check_ban_time(qq)
|
||||
if isinstance(ban_time, int):
|
||||
ban_time = abs(float(ban_time))
|
||||
if ban_time < 60:
|
||||
ban_time = str(ban_time) + " 秒"
|
||||
else:
|
||||
time = str(int(time / 60)) + " 分钟"
|
||||
ban_time = str(int(ban_time / 60)) + " 分钟"
|
||||
else:
|
||||
time += " 分钟"
|
||||
result = f"{user_name} 已在黑名单!预计 {time}后解封"
|
||||
ban_time += " 分钟"
|
||||
result = f"{user_name} 已在黑名单!预计 {ban_time}后解封"
|
||||
return result
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
from configs.config import Config
|
||||
from models.chat_history import ChatHistory
|
||||
from nonebot import on_message
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
|
||||
from configs.config import Config
|
||||
from models.chat_history import ChatHistory
|
||||
from services.log import logger
|
||||
from utils.depends import PlaintText
|
||||
from utils.utils import scheduler
|
||||
|
||||
from ._rule import rule
|
||||
|
||||
@ -19,14 +22,38 @@ Config.add_plugin_config(
|
||||
chat_history = on_message(rule=rule, priority=1, block=False)
|
||||
|
||||
|
||||
TEMP_LIST = []
|
||||
|
||||
|
||||
@chat_history.handle()
|
||||
async def _(event: MessageEvent, msg: str = PlaintText()):
|
||||
group_id = None
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
await ChatHistory.add_chat_msg(
|
||||
event.user_id, event.group_id, str(event.get_message()), msg
|
||||
)
|
||||
else:
|
||||
await ChatHistory.add_chat_msg(event.user_id, None, str(event.get_message()), msg)
|
||||
group_id = event.group_id
|
||||
TEMP_LIST.append(
|
||||
{
|
||||
"user_qq": event.user_id,
|
||||
"group_id": group_id,
|
||||
"text": str(event.get_message()),
|
||||
"plain_text": msg,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@scheduler.scheduled_job(
|
||||
"interval",
|
||||
minutes=1,
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
message_list = TEMP_LIST.copy()
|
||||
TEMP_LIST.clear()
|
||||
if message_list:
|
||||
model_list = [ChatHistory(**x) for x in message_list]
|
||||
await ChatHistory.bulk_create(model_list)
|
||||
logger.debug(f"批量添加聊天记录 {len(message_list)} 条", "定时任务")
|
||||
except Exception as e:
|
||||
logger.error(f"定时批量添加聊天记录", "定时任务", e=e)
|
||||
|
||||
|
||||
# @test.handle()
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Tuple
|
||||
|
||||
import pytz
|
||||
from models.chat_history import ChatHistory
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from nonebot import on_regex
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent
|
||||
from nonebot.params import RegexGroup
|
||||
from utils.image_utils import BuildImage, text2image
|
||||
from utils.utils import is_number
|
||||
from utils.message_builder import image
|
||||
from typing import Tuple, Any
|
||||
|
||||
from models.chat_history import ChatHistory
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from utils.image_utils import BuildImage, text2image
|
||||
from utils.message_builder import image
|
||||
from utils.utils import is_number
|
||||
|
||||
__zx_plugin_name__ = "消息统计"
|
||||
__plugin_usage__ = """
|
||||
@ -29,12 +29,7 @@ usage:
|
||||
消息统计n=15
|
||||
""".strip()
|
||||
__plugin_des__ = "发言消息排行"
|
||||
__plugin_cmd__ = [
|
||||
"消息统计",
|
||||
"周消息统计",
|
||||
"月消息统计",
|
||||
"日消息统计"
|
||||
]
|
||||
__plugin_cmd__ = ["消息统计", "周消息统计", "月消息统计", "日消息统计"]
|
||||
__plugin_type__ = ("数据统计", 1)
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
@ -44,7 +39,9 @@ __plugin_settings__ = {
|
||||
}
|
||||
|
||||
|
||||
msg_handler = on_regex(r"^(周|月|日)?消息统计(des|DES)?(n=[0-9]{1,2})?$", priority=5, block=True)
|
||||
msg_handler = on_regex(
|
||||
r"^(周|月|日)?消息统计(des|DES)?(n=[0-9]{1,2})?$", priority=5, block=True
|
||||
)
|
||||
|
||||
|
||||
@msg_handler.handle()
|
||||
@ -56,7 +53,9 @@ async def _(event: GroupMessageEvent, reg_group: Tuple[Any, ...] = RegexGroup())
|
||||
if num and is_number(num) and 10 < int(num) < 50:
|
||||
num = int(num)
|
||||
time_now = datetime.now()
|
||||
zero_today = time_now - timedelta(hours=time_now.hour, minutes=time_now.minute, seconds=time_now.second)
|
||||
zero_today = time_now - timedelta(
|
||||
hours=time_now.hour, minutes=time_now.minute, seconds=time_now.second
|
||||
)
|
||||
if date in ["日"]:
|
||||
date_scope = (zero_today, time_now)
|
||||
elif date in ["周"]:
|
||||
@ -70,9 +69,9 @@ async def _(event: GroupMessageEvent, reg_group: Tuple[Any, ...] = RegexGroup())
|
||||
num_str = "发言次数:\n\n"
|
||||
idx = 1
|
||||
for uid, num in rank_data:
|
||||
try:
|
||||
user_name = (await GroupInfoUser.get_member_info(uid, gid)).user_name
|
||||
except AttributeError:
|
||||
if user := await GroupInfoUser.filter(user_qq=uid, group_id=gid).first():
|
||||
user_name = user.user_name
|
||||
else:
|
||||
user_name = uid
|
||||
name += f"\t{idx}.{user_name} \n\n"
|
||||
num_str += f"\t{num}\n\n"
|
||||
|
||||
@ -1,26 +1,27 @@
|
||||
from nonebot import on_notice, on_request
|
||||
from configs.path_config import IMAGE_PATH, DATA_PATH
|
||||
from models.level_user import LevelUser
|
||||
from utils.message_builder import image
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from datetime import datetime
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
GroupIncreaseNoticeEvent,
|
||||
GroupDecreaseNoticeEvent,
|
||||
)
|
||||
from utils.manager import group_manager, plugins2settings_manager, requests_manager
|
||||
from configs.config import NICKNAME
|
||||
from models.group_info import GroupInfo
|
||||
from utils.utils import FreqLimiter
|
||||
from configs.config import Config
|
||||
from pathlib import Path
|
||||
import random
|
||||
import os
|
||||
import ujson as json
|
||||
import random
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import ujson as json
|
||||
from nonebot import on_notice, on_request
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
ActionFailed,
|
||||
Bot,
|
||||
GroupDecreaseNoticeEvent,
|
||||
GroupIncreaseNoticeEvent,
|
||||
)
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from configs.path_config import DATA_PATH, IMAGE_PATH
|
||||
from models.group_info import GroupInfo
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from models.level_user import LevelUser
|
||||
from services.log import logger
|
||||
from utils.depends import GetConfig
|
||||
from utils.manager import group_manager, plugins2settings_manager, requests_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import FreqLimiter
|
||||
|
||||
__zx_plugin_name__ = "群事件处理 [Hidden]"
|
||||
__plugin_version__ = 0.1
|
||||
@ -65,7 +66,7 @@ add_group = on_request(priority=1, block=False)
|
||||
@group_increase_handle.handle()
|
||||
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
|
||||
if event.user_id == int(bot.self_id):
|
||||
group = await GroupInfo.get_group_info(event.group_id)
|
||||
group = await GroupInfo.filter(group_id=event.group_id).first()
|
||||
# 群聊不存在或被强制拉群,退出该群
|
||||
if (not group or group.group_flag == 0) and Config.get_config(
|
||||
"invite_manager", "flag"
|
||||
@ -115,15 +116,12 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
|
||||
user_info = await bot.get_group_member_info(
|
||||
group_id=event.group_id, user_id=event.user_id
|
||||
)
|
||||
if await GroupInfoUser.add_member_info(
|
||||
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:
|
||||
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
|
||||
await GroupInfoUser.update_or_create(
|
||||
user_qq=user_info["user_id"],
|
||||
group_id=user_info["group_id"],
|
||||
defaults={"user_name": user_info["nickname"], "user_join_time": join_time},
|
||||
)
|
||||
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
|
||||
|
||||
# 群欢迎消息
|
||||
if _flmt.check(event.group_id):
|
||||
@ -152,7 +150,11 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
|
||||
else:
|
||||
await group_increase_handle.send(
|
||||
"[[_task|group_welcome]]新人快跑啊!!本群现状↓(快使用自定义!)"
|
||||
+ image(random.choice(os.listdir(IMAGE_PATH / "qxz")), "qxz")
|
||||
+ image(
|
||||
IMAGE_PATH
|
||||
/ "qxz"
|
||||
/ random.choice(os.listdir(IMAGE_PATH / "qxz"))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -162,13 +164,13 @@ async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
|
||||
if event.sub_type == "kick_me":
|
||||
group_id = event.group_id
|
||||
operator_id = event.operator_id
|
||||
try:
|
||||
operator_name = (
|
||||
await GroupInfoUser.get_member_info(event.operator_id, event.group_id)
|
||||
).user_name
|
||||
except AttributeError:
|
||||
if user := await GroupInfoUser.get_or_none(
|
||||
user_qq=event.operator_id, group_id=event.group_id
|
||||
):
|
||||
operator_name = user.user_name
|
||||
else:
|
||||
operator_name = "None"
|
||||
group = await GroupInfo.get_group_info(group_id)
|
||||
group = await GroupInfo.filter(group_id=group_id).first()
|
||||
group_name = group.group_name if group else ""
|
||||
coffee = int(list(bot.config.superusers)[0])
|
||||
await bot.send_private_msg(
|
||||
@ -182,16 +184,19 @@ async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
|
||||
if event.user_id == int(bot.self_id):
|
||||
group_manager.delete_group(event.group_id)
|
||||
return
|
||||
try:
|
||||
user_name = (
|
||||
await GroupInfoUser.get_member_info(event.user_id, event.group_id)
|
||||
).user_name
|
||||
except AttributeError:
|
||||
user_name = str(event.user_id)
|
||||
if await GroupInfoUser.delete_member_info(event.user_id, event.group_id):
|
||||
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除成功")
|
||||
if user := await GroupInfoUser.get_or_none(
|
||||
user_qq=event.user_id, group_id=event.group_id
|
||||
):
|
||||
user_name = user.user_name
|
||||
else:
|
||||
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除失败")
|
||||
user_name = f"{event.user_id}"
|
||||
await GroupInfoUser.filter(user_qq=event.user_id, group_id=event.group_id).delete()
|
||||
logger.info(
|
||||
f"名称: {user_name} 退出群聊",
|
||||
"group_decrease_handle",
|
||||
event.user_id,
|
||||
event.group_id,
|
||||
)
|
||||
rst = ""
|
||||
if event.sub_type == "leave":
|
||||
rst = f"{user_name}离开了我们..."
|
||||
|
||||
@ -1,39 +1,40 @@
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
import nonebot
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
GroupMessageEvent,
|
||||
PrivateMessageEvent,
|
||||
Bot,
|
||||
Event,
|
||||
MessageEvent,
|
||||
GroupMessageEvent,
|
||||
Message,
|
||||
MessageEvent,
|
||||
PokeNotifyEvent,
|
||||
PrivateMessageEvent,
|
||||
)
|
||||
from nonebot.exception import ActionFailed, IgnoredException
|
||||
from nonebot.internal.matcher import Matcher
|
||||
|
||||
from configs.config import Config
|
||||
from models.bag_user import BagUser
|
||||
from models.ban_user import BanUser
|
||||
from models.friend_user import FriendUser
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from models.level_user import LevelUser
|
||||
from models.user_shop_gold_log import UserShopGoldLog
|
||||
from services.log import logger
|
||||
from utils.decorator import Singleton
|
||||
from utils.manager import (
|
||||
plugins2block_manager,
|
||||
StaticData,
|
||||
plugins2settings_manager,
|
||||
group_manager,
|
||||
admin_manager,
|
||||
plugins_manager,
|
||||
group_manager,
|
||||
plugins2block_manager,
|
||||
plugins2cd_manager,
|
||||
plugins2count_manager,
|
||||
plugins2settings_manager,
|
||||
plugins_manager,
|
||||
)
|
||||
from utils.message_builder import at
|
||||
from utils.utils import FreqLimiter
|
||||
from configs.config import Config
|
||||
import time
|
||||
|
||||
ignore_rst_module = ["ai", "poke", "dialogue"]
|
||||
|
||||
@ -97,11 +98,11 @@ async def send_msg(msg: str, bot: Bot, event: MessageEvent):
|
||||
msg = msg.replace("[uname]", uname)
|
||||
if "[nickname]" in msg:
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
nickname = await GroupInfoUser.get_group_member_nickname(
|
||||
nickname = await GroupInfoUser.get_user_nickname(
|
||||
event.user_id, event.group_id
|
||||
)
|
||||
else:
|
||||
nickname = await FriendUser.get_friend_nickname(event.user_id)
|
||||
nickname = await FriendUser.get_user_nickname(event.user_id)
|
||||
msg = msg.replace("[nickname]", nickname)
|
||||
if "[at]" in msg and isinstance(event, GroupMessageEvent):
|
||||
msg = msg.replace("[at]", str(at(event.user_id)))
|
||||
@ -142,16 +143,19 @@ class AuthChecker:
|
||||
:param event: event
|
||||
"""
|
||||
try:
|
||||
plugin_name = matcher.plugin_name
|
||||
cost_gold = await self.auth_cost(plugin_name, bot, event)
|
||||
if hasattr(event, "user_id") and str(event.user_id) not in bot.config.superusers:
|
||||
await self.auth_basic(plugin_name, bot, event)
|
||||
self.auth_group(plugin_name, bot, event)
|
||||
await self.auth_admin(plugin_name, matcher, bot, event)
|
||||
await self.auth_plugin(plugin_name, matcher, bot, event)
|
||||
await self.auth_limit(plugin_name, bot, event)
|
||||
if cost_gold:
|
||||
await BagUser.spend_gold(event.user_id, event.group_id, cost_gold)
|
||||
if plugin_name := matcher.plugin_name:
|
||||
cost_gold = await self.auth_cost(plugin_name, bot, event)
|
||||
user_id = getattr(event, "user_id", None)
|
||||
if user_id and str(user_id) not in bot.config.superusers:
|
||||
await self.auth_basic(plugin_name, bot, event)
|
||||
self.auth_group(plugin_name, bot, event)
|
||||
await self.auth_admin(plugin_name, matcher, bot, event)
|
||||
await self.auth_plugin(plugin_name, matcher, bot, event)
|
||||
await self.auth_limit(plugin_name, bot, event)
|
||||
if cost_gold:
|
||||
await BagUser.spend_gold(
|
||||
event.user_id, event.group_id, cost_gold
|
||||
)
|
||||
except IsSuperuserException:
|
||||
return
|
||||
|
||||
@ -221,7 +225,9 @@ class AuthChecker:
|
||||
else:
|
||||
plugins2count_manager.increase(plugin_name, count_type_)
|
||||
|
||||
async def auth_plugin(self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event):
|
||||
async def auth_plugin(
|
||||
self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
插件状态
|
||||
@ -345,6 +351,7 @@ class AuthChecker:
|
||||
and plugin_name not in ignore_rst_module
|
||||
):
|
||||
self._flmt_c.start_cd(event.group_id)
|
||||
logger.info(f"{event.user_id} ||XXXXXX: {matcher.module}")
|
||||
await bot.send_group_msg(
|
||||
group_id=event.group_id, message="此功能正在维护..."
|
||||
)
|
||||
@ -364,7 +371,9 @@ class AuthChecker:
|
||||
set_block_limit_false(event, plugin_name)
|
||||
raise IgnoredException("此功能正在维护...")
|
||||
|
||||
async def auth_admin(self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event):
|
||||
async def auth_admin(
|
||||
self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
管理员命令 个人权限
|
||||
@ -504,8 +513,13 @@ class AuthChecker:
|
||||
await BagUser.spend_gold(
|
||||
event.user_id, event.group_id, psm.cost_gold
|
||||
)
|
||||
await UserShopGoldLog.add_shop_log(
|
||||
event.user_id, event.group_id, 2, plugin_name, psm.cost_gold, 1
|
||||
await UserShopGoldLog.create(
|
||||
user_qq=event.user_id,
|
||||
group_id=event.group_id,
|
||||
type=2,
|
||||
name=plugin_name,
|
||||
num=1,
|
||||
spend_gold=psm.cost_gold,
|
||||
)
|
||||
cost_gold = psm.cost_gold
|
||||
return cost_gold
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import run_preprocessor, IgnoredException
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
ActionFailed,
|
||||
Bot,
|
||||
Event,
|
||||
MessageEvent,
|
||||
ActionFailed,
|
||||
PokeNotifyEvent,
|
||||
GroupMessageEvent,
|
||||
MessageEvent,
|
||||
PokeNotifyEvent,
|
||||
)
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import IgnoredException, run_preprocessor
|
||||
from nonebot.typing import T_State
|
||||
|
||||
from configs.config import Config
|
||||
from models.ban_user import BanUser
|
||||
from utils.utils import is_number, static_flmt, FreqLimiter
|
||||
from utils.message_builder import at
|
||||
from ._utils import ignore_rst_module, other_limit_plugins
|
||||
from utils.utils import FreqLimiter, is_number, static_flmt
|
||||
|
||||
from ._utils import ignore_rst_module, other_limit_plugins
|
||||
|
||||
Config.add_plugin_config(
|
||||
"hook",
|
||||
@ -49,7 +50,7 @@ async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
|
||||
and str(event.user_id) not in bot.config.superusers
|
||||
):
|
||||
time = await BanUser.check_ban_time(event.user_id)
|
||||
if is_number(time):
|
||||
if isinstance(time, int):
|
||||
time = abs(int(time))
|
||||
if time < 60:
|
||||
time = str(time) + " 秒"
|
||||
|
||||
@ -28,12 +28,12 @@ async def _(matcher: Matcher, bot: Bot, event: GroupMessageEvent, state: T_State
|
||||
if matcher.type == "message" and matcher.priority not in [1, 999]:
|
||||
if state["_prefix"]["raw_command"]:
|
||||
if _blmt.check(f'{event.user_id}{state["_prefix"]["raw_command"]}'):
|
||||
if await BanUser.ban(
|
||||
await BanUser.ban(
|
||||
event.user_id,
|
||||
9,
|
||||
Config.get_config("hook", "MALICIOUS_BAN_TIME") * 60,
|
||||
):
|
||||
logger.info(f"USER {event.user_id} 触发了恶意触发检测")
|
||||
)
|
||||
logger.info(f"USER {event.user_id} 触发了恶意触发检测")
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
try:
|
||||
await bot.send_group_msg(
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
import nonebot
|
||||
from nonebot import Driver
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
|
||||
from configs.path_config import DATA_PATH
|
||||
from .init_group_manager import init_group_manager, group_manager
|
||||
from services.log import logger
|
||||
|
||||
from .check_plugin_status import check_plugin_status
|
||||
from .init import init
|
||||
from .init_none_plugin_count_manager import init_none_plugin_count_manager
|
||||
from .init_plugin_info import init_plugin_info
|
||||
from .init_plugins_config import init_plugins_config
|
||||
from .init_plugins_data import init_plugins_data, plugins_manager
|
||||
from .init_none_plugin_count_manager import init_none_plugin_count_manager
|
||||
from .init_plugins_resources import init_plugins_resources
|
||||
from .init_plugins_settings import init_plugins_settings
|
||||
from .init_plugin_info import init_plugin_info
|
||||
from .init_plugins_limit import (
|
||||
init_plugins_block_limit,
|
||||
init_plugins_count_limit,
|
||||
init_plugins_cd_limit,
|
||||
init_plugins_count_limit,
|
||||
)
|
||||
from .init import init
|
||||
from .check_plugin_status import check_plugin_status
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
from services.log import logger
|
||||
from nonebot import Driver
|
||||
import nonebot
|
||||
|
||||
from .init_plugins_resources import init_plugins_resources
|
||||
from .init_plugins_settings import init_plugins_settings
|
||||
|
||||
__zx_plugin_name__ = "初始化插件数据 [Hidden]"
|
||||
__plugin_version__ = 0.1
|
||||
@ -44,10 +44,6 @@ async def _():
|
||||
init_plugins_config()
|
||||
init_plugins_resources()
|
||||
init_none_plugin_count_manager()
|
||||
# x = group_manager.get_super_old_data()
|
||||
# if x:
|
||||
# for key in x.keys():
|
||||
# plugins_manager.block_plugin(key, block_type=x[key])
|
||||
if _flag:
|
||||
raise Exception("首次运行,已在configs目录下生成配置文件config.yaml,修改后重启即可...")
|
||||
logger.info("初始化数据完成...")
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
from pathlib import Path
|
||||
from utils.manager import group_manager
|
||||
from services.db_context import db
|
||||
from asyncpg.exceptions import DuplicateColumnError
|
||||
from services.log import logger
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
except ModuleNotFoundError:
|
||||
import json
|
||||
try:
|
||||
from models.group_remind import GroupRemind
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
|
||||
|
||||
async def init_group_manager():
|
||||
"""
|
||||
旧数据格式替换为新格式
|
||||
初始化数据
|
||||
"""
|
||||
old_group_level_file = Path() / "data" / "manager" / "group_level.json"
|
||||
old_plugin_list_file = Path() / "data" / "manager" / "plugin_list.json"
|
||||
if old_group_level_file.exists():
|
||||
data = json.load(open(old_group_level_file, "r", encoding="utf8"))
|
||||
for key in data.keys():
|
||||
group = key
|
||||
level = data[key]
|
||||
group_manager.set_group_level(group, level)
|
||||
old_group_level_file.unlink()
|
||||
group_manager.save()
|
||||
|
||||
if old_plugin_list_file.exists():
|
||||
data = json.load(open(old_plugin_list_file, "r", encoding="utf8"))
|
||||
for plugin in data.keys():
|
||||
for group in data[plugin].keys():
|
||||
if group == "default" and not data[plugin]["default"]:
|
||||
group_manager.block_plugin(plugin)
|
||||
elif not data[plugin][group]:
|
||||
group_manager.block_plugin(plugin, group)
|
||||
old_plugin_list_file.unlink()
|
||||
old_data_table = Path() / "models" / "group_remind.py"
|
||||
try:
|
||||
if old_data_table.exists():
|
||||
b = {
|
||||
"hy": "group_welcome",
|
||||
"kxcz": "open_case_reset_remind",
|
||||
"zwa": "zwa",
|
||||
"blpar": "bilibili_parse",
|
||||
"epic": "epic_free_game",
|
||||
"pa": "pa",
|
||||
"almanac": "genshin_alc",
|
||||
}
|
||||
for group in group_manager.get_data()["group_manager"]:
|
||||
for remind in b:
|
||||
try:
|
||||
status = await GroupRemind.get_status(int(group), remind)
|
||||
if status is not None:
|
||||
if status:
|
||||
await group_manager.open_group_task(group, b[remind])
|
||||
logger.info(f"读取旧数据-->{group} 开启 {b[remind]}")
|
||||
else:
|
||||
await group_manager.close_group_task(group, b[remind])
|
||||
logger.info(f"读取旧数据-->{group} 关闭 {b[remind]}")
|
||||
except Exception as e:
|
||||
pass
|
||||
query = db.text("DROP TABLE group_reminds;")
|
||||
await db.first(query)
|
||||
old_data_table.unlink()
|
||||
logger.info("旧数据读取完毕,删除了舍弃表 group_reminds...")
|
||||
except (ModuleNotFoundError, DuplicateColumnError):
|
||||
pass
|
||||
group_manager.save()
|
||||
@ -27,6 +27,8 @@ def init_plugins_settings():
|
||||
else:
|
||||
if plugin_data := plugin_data_manager.get(matcher.plugin_name):
|
||||
if plugin_settings := plugin_data.plugin_setting:
|
||||
if (name := _module.__getattribute__("__zx_plugin_name__")) not in plugin_settings.cmd:
|
||||
plugin_settings.cmd.append(name)
|
||||
# 管理员命令
|
||||
if plugin_data.plugin_type == PluginType.ADMIN:
|
||||
admin_manager.add_admin_plugin_settings(
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
from nonebot import on_request, on_message
|
||||
import asyncio
|
||||
import re
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from nonebot import on_message, on_request
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
Bot,
|
||||
FriendRequestEvent,
|
||||
GroupRequestEvent,
|
||||
MessageEvent,
|
||||
)
|
||||
from models.friend_user import FriendUser
|
||||
from datetime import datetime
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from utils.manager import requests_manager
|
||||
from models.friend_user import FriendUser
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from utils.manager import requests_manager
|
||||
from utils.utils import scheduler
|
||||
import asyncio
|
||||
import time
|
||||
import re
|
||||
|
||||
from .utils import time_manager
|
||||
|
||||
__zx_plugin_name__ = "好友群聊处理请求 [Hidden]"
|
||||
__plugin_version__ = 0.1
|
||||
@ -27,101 +32,109 @@ friend_req = on_request(priority=5, block=True)
|
||||
group_req = on_request(priority=5, block=True)
|
||||
x = on_message(priority=999, block=False, rule=lambda: False)
|
||||
|
||||
exists_data = {"private": {}, "group": {}}
|
||||
|
||||
|
||||
@friend_req.handle()
|
||||
async def _(bot: Bot, event: FriendRequestEvent):
|
||||
global exists_data
|
||||
if exists_data["private"].get(event.user_id):
|
||||
if time.time() - exists_data["private"][event.user_id] < 60 * 5:
|
||||
return
|
||||
exists_data["private"][event.user_id] = time.time()
|
||||
user = await bot.get_stranger_info(user_id=event.user_id)
|
||||
nickname = user["nickname"]
|
||||
sex = user["sex"]
|
||||
age = str(user["age"])
|
||||
comment = event.comment
|
||||
await bot.send_private_msg(
|
||||
user_id=int(list(bot.config.superusers)[0]),
|
||||
message=f"*****一份好友申请*****\n"
|
||||
f"昵称:{nickname}({event.user_id})\n"
|
||||
f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
|
||||
f"日期:{str(datetime.now()).split('.')[0]}\n"
|
||||
f"备注:{event.comment}",
|
||||
)
|
||||
if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
|
||||
await bot.set_friend_add_request(flag=event.flag, approve=True)
|
||||
await FriendUser.add_friend_info(user["user_id"], user["nickname"])
|
||||
else:
|
||||
requests_manager.add_request(
|
||||
event.user_id,
|
||||
"private",
|
||||
event.flag,
|
||||
nickname=nickname,
|
||||
sex=sex,
|
||||
age=age,
|
||||
comment=comment,
|
||||
if time_manager.add_user_request(event.user_id):
|
||||
logger.debug(f"收录 用户[{event.user_id}] 好友请求", "好友请求")
|
||||
user = await bot.get_stranger_info(user_id=event.user_id)
|
||||
nickname = user["nickname"]
|
||||
sex = user["sex"]
|
||||
age = str(user["age"])
|
||||
comment = event.comment
|
||||
await bot.send_private_msg(
|
||||
user_id=int(list(bot.config.superusers)[0]),
|
||||
message=f"*****一份好友申请*****\n"
|
||||
f"昵称:{nickname}({event.user_id})\n"
|
||||
f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
|
||||
f"日期:{str(datetime.now()).split('.')[0]}\n"
|
||||
f"备注:{event.comment}",
|
||||
)
|
||||
if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
|
||||
logger.debug(f"已开启好友请求自动同意,成功通过该请求", "好友请求", target=event.user_id)
|
||||
await bot.set_friend_add_request(flag=event.flag, approve=True)
|
||||
await FriendUser.create(user_id=user["user_id"], user_name=user["nickname"])
|
||||
else:
|
||||
requests_manager.add_request(
|
||||
event.user_id,
|
||||
"private",
|
||||
event.flag,
|
||||
nickname=nickname,
|
||||
sex=sex,
|
||||
age=age,
|
||||
comment=comment,
|
||||
)
|
||||
else:
|
||||
logger.debug(f"好友请求五分钟内重复, 已忽略", "好友请求", target=event.user_id)
|
||||
|
||||
|
||||
@group_req.handle()
|
||||
async def _(bot: Bot, event: GroupRequestEvent):
|
||||
global exists_data
|
||||
# 邀请
|
||||
if event.sub_type == "invite":
|
||||
if str(event.user_id) in bot.config.superusers:
|
||||
try:
|
||||
if await GroupInfo.get_group_info(event.group_id):
|
||||
await GroupInfo.set_group_flag(event.group_id, 1)
|
||||
else:
|
||||
group_info = await bot.get_group_info(group_id=event.group_id)
|
||||
await GroupInfo.add_group_info(
|
||||
group_info["group_id"],
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1,
|
||||
)
|
||||
logger.debug(
|
||||
f"超级用户自动同意加入群聊", "群聊请求", event.user_id, target=event.group_id
|
||||
)
|
||||
await bot.set_group_add_request(
|
||||
flag=event.flag, sub_type="invite", approve=True
|
||||
)
|
||||
except ActionFailed:
|
||||
pass
|
||||
group_info = await bot.get_group_info(group_id=event.group_id)
|
||||
await GroupInfo.update_or_create(
|
||||
group_id=group_info["group_id"],
|
||||
defaults={
|
||||
"group_name": group_info["group_name"],
|
||||
"max_member_count": group_info["max_member_count"],
|
||||
"member_count": group_info["member_count"],
|
||||
"group_flag": 1,
|
||||
},
|
||||
)
|
||||
except ActionFailed as e:
|
||||
logger.error(
|
||||
"超级用户自动同意加入群聊发生错误",
|
||||
"群聊请求",
|
||||
event.user_id,
|
||||
target=event.group_id,
|
||||
e=e,
|
||||
)
|
||||
else:
|
||||
user = await bot.get_stranger_info(user_id=event.user_id)
|
||||
sex = user["sex"]
|
||||
age = str(user["age"])
|
||||
if exists_data["group"].get(f"{event.user_id}:{event.group_id}"):
|
||||
if (
|
||||
time.time()
|
||||
- exists_data["group"][f"{event.user_id}:{event.group_id}"]
|
||||
< 60 * 5
|
||||
):
|
||||
return
|
||||
exists_data["group"][f"{event.user_id}:{event.group_id}"] = time.time()
|
||||
nickname = await FriendUser.get_user_name(event.user_id)
|
||||
await bot.send_private_msg(
|
||||
user_id=int(list(bot.config.superusers)[0]),
|
||||
message=f"*****一份入群申请*****\n"
|
||||
f"申请人:{nickname}({event.user_id})\n"
|
||||
f"群聊:{event.group_id}\n"
|
||||
f"邀请日期:{str(datetime.now()).split('.')[0]}",
|
||||
)
|
||||
await bot.send_private_msg(
|
||||
user_id=event.user_id,
|
||||
message=f"想要邀请我偷偷入群嘛~已经提醒{NICKNAME}的管理员大人了\n"
|
||||
"请确保已经群主或群管理沟通过!\n"
|
||||
"等待管理员处理吧!",
|
||||
)
|
||||
requests_manager.add_request(
|
||||
event.user_id,
|
||||
"group",
|
||||
event.flag,
|
||||
invite_group=event.group_id,
|
||||
nickname=nickname,
|
||||
sex=sex,
|
||||
age=age,
|
||||
)
|
||||
if time_manager.add_group_request(event.user_id, event.group_id):
|
||||
logger.debug(
|
||||
f"收录 用户[{event.user_id}] 群聊[{event.group_id}] 群聊请求", "群聊请求"
|
||||
)
|
||||
user = await bot.get_stranger_info(user_id=event.user_id)
|
||||
sex = user["sex"]
|
||||
age = str(user["age"])
|
||||
nickname = await FriendUser.get_user_name(event.user_id)
|
||||
await bot.send_private_msg(
|
||||
user_id=int(list(bot.config.superusers)[0]),
|
||||
message=f"*****一份入群申请*****\n"
|
||||
f"申请人:{nickname}({event.user_id})\n"
|
||||
f"群聊:{event.group_id}\n"
|
||||
f"邀请日期:{datetime.now().replace(microsecond=0)}",
|
||||
)
|
||||
await bot.send_private_msg(
|
||||
user_id=event.user_id,
|
||||
message=f"想要邀请我偷偷入群嘛~已经提醒{NICKNAME}的管理员大人了\n"
|
||||
"请确保已经群主或群管理沟通过!\n"
|
||||
"等待管理员处理吧!",
|
||||
)
|
||||
requests_manager.add_request(
|
||||
event.user_id,
|
||||
"group",
|
||||
event.flag,
|
||||
invite_group=event.group_id,
|
||||
nickname=nickname,
|
||||
sex=sex,
|
||||
age=age,
|
||||
)
|
||||
else:
|
||||
logger.debug(
|
||||
f"群聊请求五分钟内重复, 已忽略",
|
||||
"群聊请求",
|
||||
target=f"{event.user_id}:{event.group_id}",
|
||||
)
|
||||
|
||||
|
||||
@x.handle()
|
||||
@ -145,5 +158,4 @@ async def _(event: MessageEvent):
|
||||
minutes=5,
|
||||
)
|
||||
async def _():
|
||||
global exists_data
|
||||
exists_data = {"private": {}, "group": {}}
|
||||
time_manager.clear()
|
||||
|
||||
87
basic_plugins/invite_manager/utils.py
Normal file
87
basic_plugins/invite_manager/utils.py
Normal file
@ -0,0 +1,87 @@
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict
|
||||
|
||||
|
||||
@dataclass
|
||||
class PrivateRequest:
|
||||
|
||||
"""
|
||||
好友请求
|
||||
"""
|
||||
|
||||
user_id: int
|
||||
time: float = time.time()
|
||||
|
||||
|
||||
@dataclass
|
||||
class GroupRequest:
|
||||
|
||||
"""
|
||||
群聊请求
|
||||
"""
|
||||
|
||||
user_id: int
|
||||
group_id: int
|
||||
time: float = time.time()
|
||||
|
||||
|
||||
class RequestTimeManage:
|
||||
|
||||
"""
|
||||
过滤五分钟以内的重复请求
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self._group: Dict[str, GroupRequest] = {}
|
||||
self._user: Dict[int, PrivateRequest] = {}
|
||||
|
||||
def add_user_request(self, user_id: int) -> bool:
|
||||
"""
|
||||
添加请求时间
|
||||
|
||||
Args:
|
||||
user_id (int): 用户id
|
||||
|
||||
Returns:
|
||||
bool: 是否满足时间
|
||||
"""
|
||||
if user := self._user.get(user_id):
|
||||
if time.time() - user.time < 60 * 5:
|
||||
return False
|
||||
self._user[user_id] = PrivateRequest(user_id)
|
||||
return True
|
||||
|
||||
def add_group_request(self, user_id: int, group_id: int) -> bool:
|
||||
"""
|
||||
添加请求时间
|
||||
|
||||
Args:
|
||||
user_id (int): 用户id
|
||||
group_id (int): 邀请群聊
|
||||
|
||||
Returns:
|
||||
bool: 是否满足时间
|
||||
"""
|
||||
key = f"{user_id}:{group_id}"
|
||||
if group := self._group.get(key):
|
||||
if time.time() - group.time < 60 * 5:
|
||||
return False
|
||||
self._group[key] = GroupRequest(user_id=user_id, group_id=group_id)
|
||||
return True
|
||||
|
||||
def clear(self):
|
||||
"""
|
||||
清理过期五分钟请求
|
||||
"""
|
||||
now = time.time()
|
||||
for user_id in self._user:
|
||||
if now - self._user[user_id].time < 60 * 5:
|
||||
del self._user[user_id]
|
||||
for key in self._group:
|
||||
if now - self._group[key].time < 60 * 5:
|
||||
del self._group[key]
|
||||
|
||||
|
||||
time_manager = RequestTimeManage()
|
||||
@ -1,121 +1,162 @@
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, PrivateMessageEvent, Message, MessageEvent
|
||||
from nonebot import on_command
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.rule import to_me
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from models.friend_user import FriendUser
|
||||
from models.ban_user import BanUser
|
||||
from services.log import logger
|
||||
from configs.config import NICKNAME, Config
|
||||
from nonebot.params import CommandArg
|
||||
import random
|
||||
from typing import Any, Tuple
|
||||
|
||||
from nonebot import on_command, on_regex
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.internal.matcher import Matcher
|
||||
from nonebot.internal.params import Depends
|
||||
from nonebot.params import CommandArg, RegexGroup
|
||||
from nonebot.rule import to_me
|
||||
|
||||
from configs.config import NICKNAME
|
||||
from models.ban_user import BanUser
|
||||
from models.friend_user import FriendUser
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from services.log import logger
|
||||
from utils.depends import GetConfig
|
||||
|
||||
__zx_plugin_name__ = "昵称系统"
|
||||
__plugin_usage__ = f"""
|
||||
usage:
|
||||
个人昵称系统,群聊 与 私聊 昵称相互独立
|
||||
个人昵称,将替换真寻称呼你的名称,群聊 与 私聊 昵称相互独立,全局昵称设置将更改您目前所有群聊中及私聊的昵称
|
||||
指令:
|
||||
以后叫我 [昵称]
|
||||
以后叫我 [昵称]: 设置当前群聊/私聊的昵称
|
||||
全局昵称设置 [昵称]: 设置当前所有群聊和私聊的昵称
|
||||
{NICKNAME}我是谁
|
||||
""".strip()
|
||||
__plugin_des__ = "区区昵称,才不想叫呢!"
|
||||
__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
|
||||
__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁", "全局昵称设置 [昵称]"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["昵称", "昵称系统"],
|
||||
"cmd": ["昵称"],
|
||||
}
|
||||
__plugin_configs__ = {
|
||||
"BLACK_WORD": {
|
||||
"value": ["爸", "爹", "爷", "父亲"],
|
||||
"help": "昵称所屏蔽的关键词,会被替换为 *",
|
||||
"default_value": None
|
||||
"value": ["爸", "爹", "爷", "父"],
|
||||
"help": "昵称所屏蔽的关键词,已设置的昵称会被替换为 *,未设置的昵称会在设置时提示",
|
||||
"default_value": None,
|
||||
}
|
||||
}
|
||||
|
||||
nickname = on_command(
|
||||
"nickname",
|
||||
aliases={"以后叫我", "以后请叫我", "称呼我", "以后请称呼我", "以后称呼我", "叫我", "请叫我"},
|
||||
nickname = on_regex(
|
||||
"(?:以后)?(?:叫我|请叫我|称呼我)(.*)",
|
||||
rule=to_me(),
|
||||
priority=5,
|
||||
block=True,
|
||||
)
|
||||
|
||||
my_nickname = on_command(
|
||||
"my_name", aliases={"我叫什么", "我是谁", "我的名字"}, rule=to_me(), priority=5, block=True
|
||||
"我叫什么", aliases={"我是谁", "我的名字"}, rule=to_me(), priority=5, block=True
|
||||
)
|
||||
|
||||
global_nickname = on_regex("设置全局昵称(.*)", rule=to_me(), priority=5, block=True)
|
||||
|
||||
|
||||
cancel_nickname = on_command("取消昵称", rule=to_me(), priority=5, block=True)
|
||||
|
||||
|
||||
@nickname.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
msg = arg.extract_plain_text().strip()
|
||||
if not msg:
|
||||
await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
|
||||
if len(msg) > 10:
|
||||
await nickname.finish("昵称可不能超过10个字!", at_sender=True)
|
||||
if msg in bot.config.superusers:
|
||||
await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
|
||||
_tmp = ""
|
||||
black_word = Config.get_config("nickname", "BLACK_WORD")
|
||||
if black_word:
|
||||
for x in msg:
|
||||
_tmp += "*" if x in black_word else x
|
||||
msg = _tmp
|
||||
def CheckNickname():
|
||||
"""
|
||||
说明:
|
||||
检查名称是否合法
|
||||
"""
|
||||
|
||||
async def dependency(
|
||||
bot: Bot,
|
||||
matcher: Matcher,
|
||||
event: MessageEvent,
|
||||
reg_group: Tuple[Any, ...] = RegexGroup(),
|
||||
black_word: Any = GetConfig(config="BLACK_WORD"),
|
||||
):
|
||||
(msg,) = reg_group
|
||||
logger.debug(f"昵称检查: {msg}", "昵称设置", event.user_id)
|
||||
if not msg:
|
||||
await matcher.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
|
||||
if str(event.user_id) in bot.config.superusers:
|
||||
logger.debug(f"超级用户设置昵称, 跳过合法检测: {msg}", "昵称设置", event.user_id)
|
||||
return
|
||||
if len(msg) > 20:
|
||||
await nickname.finish("昵称可不能超过20个字!", at_sender=True)
|
||||
if msg in bot.config.nickname:
|
||||
await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
|
||||
if black_word:
|
||||
for x in msg:
|
||||
if x in black_word:
|
||||
logger.debug("昵称设置禁止字符: [{x}]", "昵称设置", event.user_id)
|
||||
await nickname.finish(f"字符 [{x}] 为禁止字符!", at_sender=True)
|
||||
for word in black_word:
|
||||
if word in msg:
|
||||
logger.debug("昵称设置禁止字符: [{word}]", "昵称设置", event.user_id)
|
||||
await nickname.finish(f"字符 [{word}] 为禁止字符!", at_sender=True)
|
||||
|
||||
return Depends(dependency)
|
||||
|
||||
|
||||
@global_nickname.handle(parameterless=[CheckNickname()])
|
||||
async def _(
|
||||
event: MessageEvent,
|
||||
reg_group: Tuple[Any, ...] = RegexGroup(),
|
||||
):
|
||||
(msg,) = reg_group
|
||||
await FriendUser.set_user_nickname(event.user_id, msg)
|
||||
await GroupInfoUser.filter(user_qq=event.user_id).update(nickname=msg)
|
||||
logger.info(f"设置全局昵称成功: {msg}", "设置全局昵称", event.user_id)
|
||||
await global_nickname.send(f"设置全局昵称成功!亲爱的{msg}")
|
||||
|
||||
|
||||
@nickname.handle(parameterless=[CheckNickname()])
|
||||
async def _(
|
||||
event: MessageEvent,
|
||||
reg_group: Tuple[Any, ...] = RegexGroup(),
|
||||
):
|
||||
(msg,) = reg_group
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
if await GroupInfoUser.set_group_member_nickname(
|
||||
event.user_id, event.group_id, msg
|
||||
):
|
||||
if len(msg) < 5:
|
||||
if random.random() < 0.3:
|
||||
msg = "~".join(msg)
|
||||
await nickname.send(
|
||||
random.choice(
|
||||
[
|
||||
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
||||
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
||||
f"好突然,突然要叫你昵称什么的...{msg}..",
|
||||
f"{NICKNAME}会好好记住{msg}的,放心吧",
|
||||
f"好..好.,那窝以后就叫你{msg}了.",
|
||||
]
|
||||
)
|
||||
await GroupInfoUser.set_user_nickname(event.user_id, event.group_id, msg)
|
||||
if len(msg) < 5:
|
||||
if random.random() < 0.3:
|
||||
msg = "~".join(msg)
|
||||
await nickname.send(
|
||||
random.choice(
|
||||
[
|
||||
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
||||
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
||||
f"好突然,突然要叫你昵称什么的...{msg}..",
|
||||
f"{NICKNAME}会好好记住{msg}的,放心吧",
|
||||
f"好..好.,那窝以后就叫你{msg}了.",
|
||||
]
|
||||
)
|
||||
logger.info(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg}")
|
||||
else:
|
||||
await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
|
||||
logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
|
||||
)
|
||||
logger.info(f"设置群昵称成功: {msg}", "昵称设置", event.user_id, event.group_id)
|
||||
else:
|
||||
if await FriendUser.set_friend_nickname(event.user_id, msg):
|
||||
await nickname.send(
|
||||
random.choice(
|
||||
[
|
||||
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
||||
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
||||
f"好突然,突然要叫你昵称什么的...{msg}..",
|
||||
f"{NICKNAME}会好好记住{msg}的,放心吧",
|
||||
f"好..好.,那窝以后就叫你{msg}了.",
|
||||
]
|
||||
)
|
||||
await FriendUser.set_user_nickname(event.user_id, msg)
|
||||
await nickname.send(
|
||||
random.choice(
|
||||
[
|
||||
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
||||
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
||||
f"好突然,突然要叫你昵称什么的...{msg}..",
|
||||
f"{NICKNAME}会好好记住{msg}的,放心吧",
|
||||
f"好..好.,那窝以后就叫你{msg}了.",
|
||||
]
|
||||
)
|
||||
logger.info(f"USER {event.user_id} 设置昵称 {msg}")
|
||||
else:
|
||||
await nickname.send("设置昵称失败了,明天再来试一试!或联系管理员更新好友!", at_sender=True)
|
||||
logger.warning(f"USER {event.user_id} 设置昵称 {msg} 失败")
|
||||
)
|
||||
logger.info(f"设置私聊昵称成功: {msg}", "昵称设置", event.user_id)
|
||||
|
||||
|
||||
@my_nickname.handle()
|
||||
async def _(event: GroupMessageEvent):
|
||||
try:
|
||||
nickname_ = await GroupInfoUser.get_group_member_nickname(
|
||||
event.user_id, event.group_id
|
||||
)
|
||||
except AttributeError:
|
||||
nickname_ = ""
|
||||
async def _(event: MessageEvent):
|
||||
nickname_ = None
|
||||
card = None
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
nickname_ = await GroupInfoUser.get_user_nickname(event.user_id, event.group_id)
|
||||
card = event.sender.card or event.sender.nickname
|
||||
else:
|
||||
nickname_ = await FriendUser.get_user_nickname(event.user_id)
|
||||
card = event.sender.nickname
|
||||
if nickname_:
|
||||
await my_nickname.send(
|
||||
random.choice(
|
||||
@ -130,44 +171,20 @@ async def _(event: GroupMessageEvent):
|
||||
)
|
||||
)
|
||||
else:
|
||||
nickname_ = event.sender.card or event.sender.nickname
|
||||
await my_nickname.send(
|
||||
random.choice(
|
||||
["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
|
||||
).format(nickname_)
|
||||
)
|
||||
|
||||
|
||||
@my_nickname.handle()
|
||||
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
||||
nickname_ = await FriendUser.get_friend_nickname(event.user_id)
|
||||
if nickname_:
|
||||
await my_nickname.send(
|
||||
random.choice(
|
||||
[
|
||||
f"我肯定记得你啊,你是{nickname_}啊",
|
||||
f"我不会忘记你的,你也不要忘记我!{nickname_}",
|
||||
f"哼哼,{NICKNAME}记忆力可是很好的,{nickname_}",
|
||||
f"嗯?你是失忆了嘛...{nickname_}..",
|
||||
f"不要小看{NICKNAME}的记忆力啊!笨蛋{nickname_}!QAQ",
|
||||
f"哎?{nickname_}..怎么了吗..突然这样问..",
|
||||
]
|
||||
)
|
||||
)
|
||||
else:
|
||||
nickname_ = (await bot.get_stranger_info(user_id=event.user_id))["nickname"]
|
||||
await my_nickname.send(
|
||||
random.choice(
|
||||
["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
|
||||
).format(nickname_)
|
||||
).format(card)
|
||||
)
|
||||
|
||||
|
||||
@cancel_nickname.handle()
|
||||
async def _(event: GroupMessageEvent):
|
||||
nickname_ = await GroupInfoUser.get_group_member_nickname(
|
||||
event.user_id, event.group_id
|
||||
)
|
||||
async def _(event: MessageEvent):
|
||||
nickname_ = None
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
nickname_ = await GroupInfoUser.get_user_nickname(event.user_id, event.group_id)
|
||||
else:
|
||||
nickname_ = await FriendUser.get_user_nickname(event.user_id)
|
||||
if nickname_:
|
||||
await cancel_nickname.send(
|
||||
random.choice(
|
||||
@ -180,28 +197,10 @@ async def _(event: GroupMessageEvent):
|
||||
]
|
||||
)
|
||||
)
|
||||
await GroupInfoUser.set_group_member_nickname(event.user_id, event.group_id, "")
|
||||
await BanUser.ban(event.user_id, 9, 60)
|
||||
else:
|
||||
await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
|
||||
|
||||
|
||||
@cancel_nickname.handle()
|
||||
async def _(event: PrivateMessageEvent):
|
||||
nickname_ = await FriendUser.get_friend_nickname(event.user_id)
|
||||
if nickname_:
|
||||
await cancel_nickname.send(
|
||||
random.choice(
|
||||
[
|
||||
f"呜..{NICKNAME}睡一觉就会忘记的..和梦一样..{nickname_}",
|
||||
f"窝知道了..{nickname_}..",
|
||||
f"是{NICKNAME}哪里做的不好嘛..好吧..晚安{nickname_}",
|
||||
f"呃,{nickname_},下次我绝对绝对绝对不会再忘记你!",
|
||||
f"可..可恶!{nickname_}!太可恶了!呜",
|
||||
]
|
||||
)
|
||||
)
|
||||
await FriendUser.get_user_name(event.user_id)
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
await GroupInfoUser.set_user_nickname(event.user_id, event.group_id, "")
|
||||
else:
|
||||
await FriendUser.set_user_nickname(event.user_id, "")
|
||||
await BanUser.ban(event.user_id, 9, 60)
|
||||
else:
|
||||
await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
from nonebot import on_command, on_regex
|
||||
|
||||
from .data_source import show_plugin_repo, install_plugin, uninstall_plugin, download_json
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import CommandArg
|
||||
|
||||
from utils.message_builder import image
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from services.log import logger
|
||||
from utils.message_builder import image
|
||||
|
||||
from .data_source import (
|
||||
download_json,
|
||||
install_plugin,
|
||||
show_plugin_repo,
|
||||
uninstall_plugin,
|
||||
)
|
||||
|
||||
__zx_plugin_name__ = "插件商店 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
@ -28,23 +32,29 @@ show_repo = on_regex("^查看插件仓库$", priority=1, block=True, permission=
|
||||
|
||||
update_repo = on_regex("^更新插件仓库$", priority=1, block=True, permission=SUPERUSER)
|
||||
|
||||
install_plugin_matcher = on_command("安装插件", priority=1, block=True, permission=SUPERUSER)
|
||||
install_plugin_matcher = on_command(
|
||||
"安装插件", priority=1, block=True, permission=SUPERUSER
|
||||
)
|
||||
|
||||
uninstall_plugin_matcher = on_command("卸载插件", priority=1, block=True, permission=SUPERUSER)
|
||||
uninstall_plugin_matcher = on_command(
|
||||
"卸载插件", priority=1, block=True, permission=SUPERUSER
|
||||
)
|
||||
|
||||
|
||||
@install_plugin_matcher.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
arg = arg.extract_plain_text().strip()
|
||||
msg = await install_plugin(arg)
|
||||
name = arg.extract_plain_text().strip()
|
||||
msg = await install_plugin(name)
|
||||
await install_plugin_matcher.send(msg)
|
||||
logger.info(f"安装插件: {name}", "安装插件", event.user_id)
|
||||
|
||||
|
||||
@uninstall_plugin_matcher.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
arg = arg.extract_plain_text().strip()
|
||||
msg = await uninstall_plugin(arg)
|
||||
name = arg.extract_plain_text().strip()
|
||||
msg = await uninstall_plugin(name)
|
||||
await install_plugin_matcher.send(msg)
|
||||
logger.info(f"卸载插件: {name}", "卸载插件", event.user_id)
|
||||
|
||||
|
||||
@update_repo.handle()
|
||||
@ -53,16 +63,13 @@ async def _(bot: Bot, event: MessageEvent):
|
||||
if code == 200:
|
||||
await update_repo.finish("更新插件仓库信息成功!")
|
||||
await update_repo.send("更新插件仓库信息失败!")
|
||||
|
||||
logger.info("更新插件仓库信息", "更新插件仓库信息", event.user_id)
|
||||
|
||||
|
||||
@show_repo.handle()
|
||||
async def _(bot: Bot, event: MessageEvent):
|
||||
msg = await show_plugin_repo()
|
||||
if isinstance(msg, int):
|
||||
await show_repo.finish("文件下载失败或解压失败..")
|
||||
await show_repo.send(image(b64=msg))
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 查看插件仓库"
|
||||
)
|
||||
|
||||
await show_repo.send(image(msg))
|
||||
logger.info("查看插件仓库", "查看插件仓库", event.user_id)
|
||||
|
||||
@ -2,15 +2,15 @@ import os
|
||||
import shutil
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Union, Tuple
|
||||
from utils.manager import plugins_manager
|
||||
from typing import Tuple, Union
|
||||
|
||||
import ujson as json
|
||||
|
||||
from configs.path_config import DATA_PATH, TEMP_PATH
|
||||
from services import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.path_config import TEMP_PATH, DATA_PATH
|
||||
from utils.image_utils import text2image, BuildImage
|
||||
from utils.image_utils import BuildImage, text2image
|
||||
from utils.manager import plugins_manager
|
||||
from utils.utils import is_number
|
||||
|
||||
path = DATA_PATH / "plugin_shop"
|
||||
@ -48,7 +48,7 @@ async def install_plugin(name: str) -> str:
|
||||
if zip_file.exists():
|
||||
zip_file.unlink()
|
||||
if await AsyncHttpx.download_file(url, zip_file):
|
||||
logger.debug("开始解压插件压缩包...")
|
||||
logger.debug("开始解压插件压缩包...", "安装插件", target=name)
|
||||
# 解压
|
||||
zf = zipfile.ZipFile(zip_file, "r")
|
||||
extract_path = TEMP_PATH / f"{name}"
|
||||
@ -58,32 +58,34 @@ async def install_plugin(name: str) -> str:
|
||||
for file in zf.namelist():
|
||||
zf.extract(file, extract_path)
|
||||
zf.close()
|
||||
logger.debug("解压插件压缩包完成...")
|
||||
logger.debug("开始移动插件文件夹...")
|
||||
logger.debug("解压插件压缩包完成...", "安装插件", target=name)
|
||||
logger.debug("开始移动插件文件夹...", "安装插件", target=name)
|
||||
if (extensive_plugin_path / f"{name}").exists():
|
||||
logger.debug("extensive_plugin目录下文件夹已存在,删除该目录插件文件夹...")
|
||||
logger.debug(
|
||||
"extensive_plugin目录下文件夹已存在,删除该目录插件文件夹...", "安装插件", target=name
|
||||
)
|
||||
shutil.rmtree(
|
||||
(extensive_plugin_path / f"{name}").absolute(), ignore_errors=True
|
||||
)
|
||||
extract_path.rename(extensive_plugin_path / f"{name}")
|
||||
tmp = ""
|
||||
prompt = ""
|
||||
if "pyproject.toml" in os.listdir(extensive_plugin_path / f"{name}"):
|
||||
tmp = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
|
||||
prompt = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
|
||||
os.system(
|
||||
f"poetry run pip install -r {(extensive_plugin_path / f'{name}' / 'pyproject.toml').absolute()}"
|
||||
)
|
||||
elif "requirements.txt" in os.listdir(extensive_plugin_path / f"{name}"):
|
||||
tmp = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
|
||||
prompt = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
|
||||
os.system(
|
||||
f"poetry run pip install -r {(extensive_plugin_path / f'{name}' / 'requirements.txt').absolute()}"
|
||||
)
|
||||
with open(extensive_plugin_path / f"{name}" / "plugin_info.json", "w") as f:
|
||||
json.dump(data[name], f, ensure_ascii=False, indent=4)
|
||||
logger.debug("移动插件文件夹完成...")
|
||||
logger.info(f"成功安装插件 {name} 成功!\n{tmp}")
|
||||
logger.debug("移动插件文件夹完成...", "安装插件", target=name)
|
||||
logger.info(f"成功安装插件 {name} 成功!\n{prompt}", "安装插件", target=name)
|
||||
return f"成功安装插件 {name},请重启真寻!"
|
||||
except Exception as e:
|
||||
logger.error(f"安装插件 {name} 失败 {type(e)}:{e}")
|
||||
logger.error(f"安装插失败", "安装插件", target=name, e=e)
|
||||
return f"安装插件 {name} 失败 {type(e)}:{e}"
|
||||
|
||||
|
||||
@ -138,7 +140,7 @@ async def show_plugin_repo() -> Union[int, str]:
|
||||
version = f"<f font_color=#1a7e30>[{plugins_data[key].version}]</f>"
|
||||
s = (
|
||||
f'id:{i+1}\n名称:{plugin_info[key]["plugin_name"]}'
|
||||
f' \t\t{status}\n'
|
||||
f" \t\t{status}\n"
|
||||
f"模块:{key}\n"
|
||||
f'作者:{plugin_info[key]["author"]}\n'
|
||||
f'版本:{plugin_info[key]["version"]} \t\t{version}\n'
|
||||
|
||||
@ -1,23 +1,16 @@
|
||||
import random
|
||||
|
||||
from asyncpg.exceptions import (
|
||||
DuplicateColumnError,
|
||||
UndefinedColumnError,
|
||||
PostgresSyntaxError,
|
||||
)
|
||||
from nonebot import Driver
|
||||
from services.db_context import db
|
||||
from models.group_info import GroupInfo
|
||||
from models.bag_user import BagUser
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
from services.log import logger
|
||||
from configs.path_config import TEXT_PATH
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from typing import List
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.utils import GDict
|
||||
from utils.utils import scheduler
|
||||
|
||||
import nonebot
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
from nonebot.drivers import Driver
|
||||
|
||||
from configs.path_config import TEXT_PATH
|
||||
from models.bag_user import BagUser
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.utils import GDict, scheduler
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@ -38,6 +31,7 @@ async def update_city():
|
||||
data = {}
|
||||
if not china_city.exists():
|
||||
try:
|
||||
logger.debug("开始更新城市列表...")
|
||||
res = await AsyncHttpx.get(
|
||||
"http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
|
||||
)
|
||||
@ -56,103 +50,97 @@ async def update_city():
|
||||
with open(china_city, "w", encoding="utf8") as f:
|
||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||
logger.info("自动更新城市列表完成.....")
|
||||
except TimeoutError:
|
||||
logger.warning("自动更新城市列表超时.....")
|
||||
except ValueError:
|
||||
logger.warning("自动城市列表失败.....")
|
||||
except TimeoutError as e:
|
||||
logger.warning("自动更新城市列表超时...", e=e)
|
||||
except ValueError as e:
|
||||
logger.warning("自动城市列表失败.....", e=e)
|
||||
except Exception as e:
|
||||
logger.error(f"自动城市列表未知错误 {type(e)}:{e}")
|
||||
logger.error(f"自动城市列表未知错误", e=e)
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
"""
|
||||
数据库表结构变换
|
||||
"""
|
||||
_flag = []
|
||||
sql_str = [
|
||||
(
|
||||
"ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;",
|
||||
"group_info",
|
||||
), # group_info表添加一个group_flag
|
||||
(
|
||||
"ALTER TABLE bag_users rename belonging_group To group_id;",
|
||||
"bag_users",
|
||||
), # 将 bag_users 的 belonging_group 改为 group_id
|
||||
(
|
||||
"ALTER TABLE group_info_users rename belonging_group To group_id;",
|
||||
"group_info_users",
|
||||
),
|
||||
(
|
||||
"ALTER TABLE sign_group_users rename belonging_group To group_id;",
|
||||
"sign_group_users",
|
||||
),
|
||||
(
|
||||
"ALTER TABLE open_cases_users rename belonging_group To group_id;",
|
||||
"open_cases_users",
|
||||
),
|
||||
(
|
||||
"ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';",
|
||||
"bag_users",
|
||||
), # bag_users 新增字段 property 替代 props
|
||||
(
|
||||
"ALTER TABLE genshin ADD auto_sign_time timestamp with time zone;",
|
||||
"genshin"
|
||||
), # 新增原神自动签到字段
|
||||
(
|
||||
"ALTER TABLE genshin ADD resin_remind boolean DEFAULT False;",
|
||||
"genshin"
|
||||
), # 新增原神自动签到字段
|
||||
(
|
||||
"ALTER TABLE genshin ADD resin_recovery_time timestamp with time zone;",
|
||||
"genshin"
|
||||
), # 新增原神自动签到字段
|
||||
(
|
||||
"ALTER TABLE genshin ADD bind_group Integer;",
|
||||
"genshin"
|
||||
), # 新增原神群号绑定字段
|
||||
(
|
||||
"ALTER TABLE genshin ADD login_ticket VARCHAR(255) DEFAULT '';",
|
||||
"genshin"
|
||||
), # 新增米游社login_ticket绑定字段
|
||||
(
|
||||
"ALTER TABLE genshin ADD stuid VARCHAR(255) DEFAULT '';",
|
||||
"genshin"
|
||||
), # 新增米游社stuid绑定字段
|
||||
(
|
||||
"ALTER TABLE genshin ADD stoken VARCHAR(255) DEFAULT '';",
|
||||
"genshin"
|
||||
), # 新增米游社stoken绑定字段
|
||||
(
|
||||
"ALTER TABLE chat_history ADD plain_text Text;",
|
||||
"chat_history"
|
||||
), # 新增纯文本
|
||||
(
|
||||
"ALTER TABLE goods_info ADD daily_limit Integer DEFAULT 0;",
|
||||
"goods_info"
|
||||
), # 新增纯文本
|
||||
(
|
||||
"ALTER TABLE goods_info ADD daily_purchase_limit Json DEFAULT '{}';",
|
||||
"goods_info"
|
||||
), # 新增纯文本
|
||||
]
|
||||
for sql in sql_str + GDict.get('run_sql', []):
|
||||
try:
|
||||
if isinstance(sql, str):
|
||||
flag = f'{random.randint(1, 10000)}'
|
||||
else:
|
||||
flag = sql[1]
|
||||
sql = sql[0]
|
||||
query = db.text(sql)
|
||||
await db.first(query)
|
||||
logger.info(f"完成sql操作:{sql}")
|
||||
_flag.append(flag)
|
||||
except (DuplicateColumnError, UndefinedColumnError):
|
||||
pass
|
||||
except PostgresSyntaxError:
|
||||
logger.error(f"语法错误:执行sql失败:{sql}")
|
||||
# bag_user 将文本转为字典格式
|
||||
await __database_script(_flag)
|
||||
# @driver.on_startup
|
||||
# async def _():
|
||||
# """
|
||||
# 数据库表结构变换
|
||||
# """
|
||||
# _flag = []
|
||||
# sql_str = [
|
||||
# (
|
||||
# "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;",
|
||||
# "group_info",
|
||||
# ), # group_info表添加一个group_flag
|
||||
# (
|
||||
# "ALTER TABLE bag_users rename belonging_group To group_id;",
|
||||
# "bag_users",
|
||||
# ), # 将 bag_users 的 belonging_group 改为 group_id
|
||||
# (
|
||||
# "ALTER TABLE group_info_users rename belonging_group To group_id;",
|
||||
# "group_info_users",
|
||||
# ),
|
||||
# (
|
||||
# "ALTER TABLE sign_group_users rename belonging_group To group_id;",
|
||||
# "sign_group_users",
|
||||
# ),
|
||||
# (
|
||||
# "ALTER TABLE open_cases_users rename belonging_group To group_id;",
|
||||
# "open_cases_users",
|
||||
# ),
|
||||
# (
|
||||
# "ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';",
|
||||
# "bag_users",
|
||||
# ), # bag_users 新增字段 property 替代 props
|
||||
# (
|
||||
# "ALTER TABLE genshin ADD auto_sign_time timestamp with time zone;",
|
||||
# "genshin",
|
||||
# ), # 新增原神自动签到字段
|
||||
# (
|
||||
# "ALTER TABLE genshin ADD resin_remind boolean DEFAULT False;",
|
||||
# "genshin",
|
||||
# ), # 新增原神自动签到字段
|
||||
# (
|
||||
# "ALTER TABLE genshin ADD resin_recovery_time timestamp with time zone;",
|
||||
# "genshin",
|
||||
# ), # 新增原神自动签到字段
|
||||
# ("ALTER TABLE genshin ADD bind_group Integer;", "genshin"), # 新增原神群号绑定字段
|
||||
# (
|
||||
# "ALTER TABLE genshin ADD login_ticket VARCHAR(255) DEFAULT '';",
|
||||
# "genshin",
|
||||
# ), # 新增米游社login_ticket绑定字段
|
||||
# (
|
||||
# "ALTER TABLE genshin ADD stuid VARCHAR(255) DEFAULT '';",
|
||||
# "genshin",
|
||||
# ), # 新增米游社stuid绑定字段
|
||||
# (
|
||||
# "ALTER TABLE genshin ADD stoken VARCHAR(255) DEFAULT '';",
|
||||
# "genshin",
|
||||
# ), # 新增米游社stoken绑定字段
|
||||
# ("ALTER TABLE chat_history ADD plain_text Text;", "chat_history"), # 新增纯文本
|
||||
# (
|
||||
# "ALTER TABLE goods_info ADD daily_limit Integer DEFAULT 0;",
|
||||
# "goods_info",
|
||||
# ), # 新增纯文本
|
||||
# (
|
||||
# "ALTER TABLE goods_info ADD daily_purchase_limit Json DEFAULT '{}';",
|
||||
# "goods_info",
|
||||
# ), # 新增纯文本
|
||||
# ]
|
||||
# for sql in sql_str + GDict.get("run_sql", []):
|
||||
# try:
|
||||
# if isinstance(sql, str):
|
||||
# flag = f"{random.randint(1, 10000)}"
|
||||
# else:
|
||||
# flag = sql[1]
|
||||
# sql = sql[0]
|
||||
# query = db.text(sql)
|
||||
# await db.first(query)
|
||||
# logger.info(f"完成sql操作:{sql}")
|
||||
# _flag.append(flag)
|
||||
# except (DuplicateColumnError, UndefinedColumnError):
|
||||
# pass
|
||||
# except PostgresSyntaxError:
|
||||
# logger.error(f"语法错误:执行sql失败:{sql}")
|
||||
# bag_user 将文本转为字典格式
|
||||
# await __database_script(_flag)
|
||||
|
||||
|
||||
@driver.on_bot_connect
|
||||
@ -161,51 +149,57 @@ async def _(bot: Bot):
|
||||
版本某些需要的变换
|
||||
"""
|
||||
# 清空不存在的群聊信息,并将已所有已存在的群聊group_flag设置为1(认证所有已存在的群)
|
||||
if not await GroupInfo.get_group_info(114514):
|
||||
if not await GroupInfo.get_or_none(group_id=114514):
|
||||
# 标识符,该功能只需执行一次
|
||||
await GroupInfo.add_group_info(114514, "114514", 114514, 114514, 1)
|
||||
await GroupInfo.create(
|
||||
group_id=114514,
|
||||
group_name="114514",
|
||||
max_member_count=114514,
|
||||
member_count=114514,
|
||||
group_flag=1,
|
||||
)
|
||||
group_list = await bot.get_group_list()
|
||||
group_list = [g["group_id"] for g in group_list]
|
||||
_gl = [x.group_id for x in await GroupInfo.get_all_group()]
|
||||
_gl = [x.group_id for x in await GroupInfo.all()]
|
||||
if 114514 in _gl:
|
||||
_gl.remove(114514)
|
||||
for group_id in _gl:
|
||||
if group_id in group_list:
|
||||
if await GroupInfo.get_group_info(group_id):
|
||||
await GroupInfo.set_group_flag(group_id, 1)
|
||||
if group := await GroupInfo.get_or_none(group_id=group_id):
|
||||
await group.update_or_create(group_flag=1)
|
||||
else:
|
||||
group_info = await bot.get_group_info(group_id=group_id)
|
||||
await GroupInfo.add_group_info(
|
||||
group_info["group_id"],
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1,
|
||||
await GroupInfo.create(
|
||||
group_id=group_info["group_id"],
|
||||
group_name=group_info["group_name"],
|
||||
max_member_count=group_info["max_member_count"],
|
||||
member_count=group_info["member_count"],
|
||||
group_flag=1,
|
||||
)
|
||||
logger.info(f"已将群聊 {group_id} 添加认证...")
|
||||
logger.info(f"已添加群认证...", group_id=group_id)
|
||||
else:
|
||||
await GroupInfo.delete_group_info(group_id)
|
||||
logger.info(f"移除不存在的群聊信息:{group_id}")
|
||||
await GroupInfo.filter(group_id=group_id).delete()
|
||||
logger.info(f"移除不存在的群聊信息", group_id=group_id)
|
||||
|
||||
|
||||
async def __database_script(_flag: List[str]):
|
||||
# bag_user 将文本转为字典格式
|
||||
if "bag_users" in _flag:
|
||||
for x in await BagUser.get_all_users():
|
||||
props = {}
|
||||
if x.props:
|
||||
for prop in [p for p in x.props.split(",") if p]:
|
||||
if props.get(prop):
|
||||
props[prop] += 1
|
||||
else:
|
||||
props[prop] = 1
|
||||
logger.info(
|
||||
f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}"
|
||||
)
|
||||
await x.update(
|
||||
property=props,
|
||||
props="",
|
||||
).apply()
|
||||
# async def __database_script(_flag: List[str]):
|
||||
# # bag_user 将文本转为字典格式
|
||||
# if "bag_users" in _flag:
|
||||
# for x in await BagUser.get_all_users():
|
||||
# props = {}
|
||||
# if x.props:
|
||||
# for prop in [p for p in x.props.split(",") if p]:
|
||||
# if props.get(prop):
|
||||
# props[prop] += 1
|
||||
# else:
|
||||
# props[prop] = 1
|
||||
# logger.info(
|
||||
# f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}"
|
||||
# )
|
||||
# await x.update(
|
||||
# property=props,
|
||||
# props="",
|
||||
# ).apply()
|
||||
|
||||
|
||||
# 自动更新城市列表
|
||||
|
||||
@ -1,21 +1,40 @@
|
||||
from configs.config import Config
|
||||
from nonebot import Driver
|
||||
from utils.decorator.shop import shop_register
|
||||
from pathlib import Path
|
||||
|
||||
import nonebot
|
||||
from nonebot.drivers import Driver
|
||||
|
||||
from configs.config import Config
|
||||
from utils.decorator.shop import shop_register
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
|
||||
Config.add_plugin_config(
|
||||
"shop",
|
||||
"IMPORT_DEFAULT_SHOP_GOODS",
|
||||
True,
|
||||
help_="导入商店自带的三个商品",
|
||||
default_value=True
|
||||
"shop", "IMPORT_DEFAULT_SHOP_GOODS", True, help_="导入商店自带的三个商品", default_value=True
|
||||
)
|
||||
|
||||
|
||||
nonebot.load_plugins("basic_plugins/shop")
|
||||
nonebot.load_plugins(str(Path(__file__).parent.resolve()))
|
||||
|
||||
|
||||
@shop_register(
|
||||
name=("好感度双倍加持卡Ⅰ", "好感度双倍加持卡Ⅱ", "好感度双倍加持卡Ⅲ"),
|
||||
price=(30, 150, 250),
|
||||
des=(
|
||||
"下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)",
|
||||
"下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)",
|
||||
"下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)",
|
||||
),
|
||||
load_status=bool(Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS")),
|
||||
icon=(
|
||||
"favorability_card_1.png",
|
||||
"favorability_card_2.png",
|
||||
"favorability_card_3.png",
|
||||
),
|
||||
**{"好感度双倍加持卡Ⅰ_prob": 0.1, "好感度双倍加持卡Ⅱ_prob": 0.2, "好感度双倍加持卡Ⅲ_prob": 0.3},
|
||||
)
|
||||
async def sign_card(user_id: int, group_id: int):
|
||||
pass
|
||||
|
||||
|
||||
@driver.on_bot_connect
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
from nonebot import on_command
|
||||
|
||||
from models.user_shop_gold_log import UserShopGoldLog
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
|
||||
from nonebot.params import CommandArg
|
||||
from utils.utils import is_number
|
||||
from models.bag_user import BagUser
|
||||
from services.db_context import db
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from models.goods_info import GoodsInfo
|
||||
import time
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from nonebot.params import CommandArg
|
||||
|
||||
from models.bag_user import BagUser
|
||||
from models.goods_info import GoodsInfo
|
||||
from models.user_shop_gold_log import UserShopGoldLog
|
||||
from services.log import logger
|
||||
from utils.utils import is_number
|
||||
|
||||
__zx_plugin_name__ = "商店 - 购买道具"
|
||||
__plugin_usage__ = """
|
||||
@ -71,39 +70,40 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
await buy.finish("请输入正确的商品名称!")
|
||||
else:
|
||||
await buy.finish("请输入正确的商品名称!", at_sender=True)
|
||||
async with db.transaction():
|
||||
if (
|
||||
await BagUser.get_gold(event.user_id, event.group_id)
|
||||
) < goods.goods_price * num * goods.goods_discount:
|
||||
await buy.finish("您的金币好像不太够哦", at_sender=True)
|
||||
flag, n = await GoodsInfo.check_user_daily_purchase(
|
||||
goods, event.user_id, event.group_id, num
|
||||
)
|
||||
if flag:
|
||||
await buy.finish(f"该次购买将超过每日次数限制,目前该道具还可以购买{n}次哦", at_sender=True)
|
||||
if await BagUser.buy_property(event.user_id, event.group_id, goods, num):
|
||||
await GoodsInfo.add_user_daily_purchase(
|
||||
goods, event.user_id, event.group_id, num
|
||||
)
|
||||
await buy.send(
|
||||
f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!",
|
||||
at_sender=True,
|
||||
)
|
||||
logger.info(
|
||||
f"USER {event.user_id} GROUP {event.group_id} "
|
||||
f"花费 {goods.goods_price*num} 金币购买 {goods.goods_name} ×{num} 成功!"
|
||||
)
|
||||
await UserShopGoldLog.add_shop_log(
|
||||
event.user_id,
|
||||
event.group_id,
|
||||
0,
|
||||
goods.goods_name,
|
||||
num,
|
||||
goods.goods_price * num * goods.goods_discount,
|
||||
)
|
||||
else:
|
||||
await buy.send(f"{goods.goods_name} 购买失败!", at_sender=True)
|
||||
logger.info(
|
||||
f"USER {event.user_id} GROUP {event.group_id} "
|
||||
f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 失败!"
|
||||
)
|
||||
if (
|
||||
await BagUser.get_gold(event.user_id, event.group_id)
|
||||
) < goods.goods_price * num * goods.goods_discount:
|
||||
await buy.finish("您的金币好像不太够哦", at_sender=True)
|
||||
flag, n = await GoodsInfo.check_user_daily_purchase(
|
||||
goods, event.user_id, event.group_id, num
|
||||
)
|
||||
if flag:
|
||||
await buy.finish(f"该次购买将超过每日次数限制,目前该道具还可以购买{n}次哦", at_sender=True)
|
||||
spend_gold = int(goods.goods_discount * goods.goods_price * num)
|
||||
await BagUser.spend_gold(event.user_id, event.group_id, spend_gold)
|
||||
await BagUser.add_property(event.user_id, event.group_id, goods.goods_name, num)
|
||||
await GoodsInfo.add_user_daily_purchase(goods, event.user_id, event.group_id, num)
|
||||
await buy.send(
|
||||
f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!",
|
||||
at_sender=True,
|
||||
)
|
||||
logger.info(
|
||||
f"花费 {goods.goods_price*num} 金币购买 {goods.goods_name} ×{num} 成功!",
|
||||
"购买道具",
|
||||
event.user_id,
|
||||
event.group_id,
|
||||
)
|
||||
await UserShopGoldLog.create(
|
||||
user_qq=event.user_id,
|
||||
group_id=event.group_id,
|
||||
type=0,
|
||||
name=goods.goods_name,
|
||||
num=num,
|
||||
spend_gold=goods.goods_price * num * goods.goods_discount,
|
||||
)
|
||||
# else:
|
||||
# await buy.send(f"{goods.goods_name} 购买失败!", at_sender=True)
|
||||
# logger.info(
|
||||
# f"USER {event.user_id} GROUP {event.group_id} "
|
||||
# f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 失败!"
|
||||
# )
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, ActionFailed
|
||||
from nonebot.params import CommandArg
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed, GroupMessageEvent, Message
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from utils.data_utils import init_rank
|
||||
from nonebot.params import CommandArg
|
||||
|
||||
from models.bag_user import BagUser
|
||||
from utils.data_utils import init_rank
|
||||
from utils.image_utils import text2image
|
||||
from utils.message_builder import image
|
||||
from utils.utils import is_number
|
||||
@ -39,7 +40,9 @@ async def _(event: GroupMessageEvent):
|
||||
try:
|
||||
await my_gold.send(msg)
|
||||
except ActionFailed:
|
||||
await my_gold.send(image(b64=(await text2image(msg, color="#f9f6f2", padding=10)).pic2bs4()))
|
||||
await my_gold.send(
|
||||
image(b64=(await text2image(msg, color="#f9f6f2", padding=10)).pic2bs4())
|
||||
)
|
||||
|
||||
|
||||
@gold_rank.handle()
|
||||
@ -49,9 +52,11 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
num = int(num)
|
||||
else:
|
||||
num = 10
|
||||
all_users = await BagUser.get_all_users(event.group_id)
|
||||
all_users = await BagUser.filter(group_id=event.group_id)
|
||||
all_user_id = [user.user_qq for user in all_users]
|
||||
all_user_data = [user.gold for user in all_users]
|
||||
rank_image = await init_rank("金币排行", all_user_id, all_user_data, event.group_id, num)
|
||||
rank_image = await init_rank(
|
||||
"金币排行", all_user_id, all_user_data, event.group_id, num
|
||||
)
|
||||
if rank_image:
|
||||
await gold_rank.finish(image(b64=rank_image.pic2bs4()))
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
from nonebot import on_command
|
||||
|
||||
from utils.message_builder import image
|
||||
from ._data_source import create_bag_image
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent
|
||||
from models.bag_user import BagUser
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
|
||||
from models.bag_user import BagUser
|
||||
from services.log import logger
|
||||
from utils.message_builder import image
|
||||
|
||||
from ._data_source import create_bag_image
|
||||
|
||||
__zx_plugin_name__ = "商店 - 我的道具"
|
||||
__plugin_usage__ = """
|
||||
@ -17,7 +17,7 @@ usage:
|
||||
""".strip()
|
||||
__plugin_des__ = "商店 - 我的道具"
|
||||
__plugin_cmd__ = ["我的道具"]
|
||||
__plugin_type__ = ('商店',)
|
||||
__plugin_type__ = ("商店",)
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
@ -36,10 +36,6 @@ async def _(event: GroupMessageEvent):
|
||||
props = await BagUser.get_property(event.user_id, event.group_id)
|
||||
if props:
|
||||
await my_props.send(image(b64=await create_bag_image(props)))
|
||||
# rst = ""
|
||||
# for i, p in enumerate(props.keys()):
|
||||
# rst += f"{i+1}.{p}\t×{props[p]}\n"
|
||||
# await my_props.send("\n" + rst[:-1], at_sender=True)
|
||||
logger.info(f"USER {event.user_id} GROUP {event.group_id} 查看我的道具")
|
||||
else:
|
||||
await my_props.finish("您的背包里没有任何的道具噢~", at_sender=True)
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
from utils.utils import scheduler
|
||||
from models.bag_user import BagUser
|
||||
from services.log import logger
|
||||
|
||||
|
||||
__zx_plugin_name__ = "每日金币重置 [Hidden]"
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
|
||||
|
||||
# 重置每日金币
|
||||
@scheduler.scheduled_job(
|
||||
"cron",
|
||||
hour=0,
|
||||
minute=1,
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
user_list = await BagUser.get_all_users()
|
||||
for user in user_list:
|
||||
await user.update(
|
||||
get_today_gold=0,
|
||||
spend_today_gold=0,
|
||||
).apply()
|
||||
except Exception as e:
|
||||
logger.error(f"重置每日金币错误 e:{e}")
|
||||
@ -1,14 +1,24 @@
|
||||
from .data_source import create_shop_help, delete_goods, update_goods, register_goods, parse_goods_info, GoodsInfo
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, Message
|
||||
from nonebot import on_command
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.message_builder import image
|
||||
from nonebot.permission import SUPERUSER
|
||||
from utils.utils import is_number, scheduler
|
||||
from nonebot.params import CommandArg
|
||||
from services.log import logger
|
||||
import os
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Message, MessageEvent
|
||||
from nonebot.params import CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from models.bag_user import BagUser
|
||||
from services.log import logger
|
||||
from utils.message_builder import image
|
||||
from utils.utils import is_number, scheduler
|
||||
|
||||
from .data_source import (
|
||||
GoodsInfo,
|
||||
create_shop_help,
|
||||
delete_goods,
|
||||
parse_goods_info,
|
||||
register_goods,
|
||||
update_goods,
|
||||
)
|
||||
|
||||
__zx_plugin_name__ = "商店"
|
||||
__plugin_usage__ = """
|
||||
@ -37,7 +47,7 @@ __plugin_cmd__ = [
|
||||
"删除商品 [名称或序号] [_superuser]",
|
||||
"修改商品 name:[名称或序号] price:[价格] des:[描述] discount:[折扣] limit_time:[限时] [_superuser]",
|
||||
]
|
||||
__plugin_type__ = ('商店',)
|
||||
__plugin_type__ = ("商店",)
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
@ -46,9 +56,7 @@ __plugin_settings__ = {
|
||||
"limit_superuser": False,
|
||||
"cmd": ["商店"],
|
||||
}
|
||||
__plugin_block_limit__ = {
|
||||
"limit_type": "group"
|
||||
}
|
||||
__plugin_block_limit__ = {"limit_type": "group"}
|
||||
|
||||
|
||||
shop_help = on_command("商店", priority=5, block=True)
|
||||
@ -75,12 +83,15 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||
if not data.get("name") or not data.get("price") or not data.get("des"):
|
||||
await shop_add_goods.finish("name:price:des 参数不可缺少!")
|
||||
if await register_goods(**data):
|
||||
await shop_add_goods.send(f"添加商品 {data['name']} 成功!\n"
|
||||
f"名称:{data['name']}\n"
|
||||
f"价格:{data['price']}金币\n"
|
||||
f"简介:{data['des']}\n"
|
||||
f"折扣:{data.get('discount')}\n"
|
||||
f"限时:{data.get('limit_time')}", at_sender=True)
|
||||
await shop_add_goods.send(
|
||||
f"添加商品 {data['name']} 成功!\n"
|
||||
f"名称:{data['name']}\n"
|
||||
f"价格:{data['price']}金币\n"
|
||||
f"简介:{data['des']}\n"
|
||||
f"折扣:{data.get('discount')}\n"
|
||||
f"限时:{data.get('limit_time')}",
|
||||
at_sender=True,
|
||||
)
|
||||
logger.info(f"USER {event.user_id} 添加商品 {msg} 成功")
|
||||
else:
|
||||
await shop_add_goods.send(f"添加商品 {msg} 失败了...", at_sender=True)
|
||||
@ -133,7 +144,19 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
await GoodsInfo.reset_daily_purchase()
|
||||
await GoodsInfo.all().update(daily_purchase_limit={})
|
||||
logger.info("商品每日限购次数重置成功...")
|
||||
except Exception as e:
|
||||
logger.error(f"商品每日限购次数重置发生错误 {type(e)}:{e}")
|
||||
logger.error(f"商品每日限购次数重置出错 {type(e)}:{e}")
|
||||
|
||||
|
||||
@scheduler.scheduled_job(
|
||||
"cron",
|
||||
hour=0,
|
||||
minute=1,
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
await BagUser.all().update(get_today_gold=0, spend_today_gold=0)
|
||||
except Exception as e:
|
||||
logger.error(f"重置每日金币", "定时任务", e=e)
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
import time
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from models.goods_info import GoodsInfo
|
||||
from utils.image_utils import BuildImage, text2image
|
||||
from utils.utils import is_number
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from typing import Optional, Union, Tuple
|
||||
from utils.utils import GDict
|
||||
import time
|
||||
from utils.utils import GDict, is_number
|
||||
|
||||
icon_path = IMAGE_PATH / 'shop_icon'
|
||||
icon_path = IMAGE_PATH / "shop_icon"
|
||||
|
||||
|
||||
GDict['run_sql'].append("ALTER TABLE goods_info ADD is_passive boolean DEFAULT False;")
|
||||
GDict['run_sql'].append("ALTER TABLE goods_info ADD icon VARCHAR(255);")
|
||||
GDict["run_sql"].append("ALTER TABLE goods_info ADD is_passive boolean DEFAULT False;")
|
||||
GDict["run_sql"].append("ALTER TABLE goods_info ADD icon VARCHAR(255);")
|
||||
|
||||
|
||||
# 创建商店界面
|
||||
@ -43,17 +43,31 @@ async def create_shop_help() -> str:
|
||||
await name_image.atext((390, 0), "售价:", center_type="by_height")
|
||||
if goods.goods_discount != 1:
|
||||
discount_price = int(goods.goods_discount * goods.goods_price)
|
||||
old_price_image = BuildImage(0, 0, plain_text=str(goods.goods_price), font_color=(194, 194, 194), font="CJGaoDeGuo.otf", font_size=15)
|
||||
await old_price_image.aline((0, int(old_price_image.h / 2), old_price_image.w + 1, int(old_price_image.h / 2)), (0, 0, 0))
|
||||
await name_image.apaste(
|
||||
old_price_image, (440, 0), True
|
||||
old_price_image = BuildImage(
|
||||
0,
|
||||
0,
|
||||
plain_text=str(goods.goods_price),
|
||||
font_color=(194, 194, 194),
|
||||
font="CJGaoDeGuo.otf",
|
||||
font_size=15,
|
||||
)
|
||||
await name_image.atext(
|
||||
(440, 15), str(discount_price), (255, 255, 255)
|
||||
await old_price_image.aline(
|
||||
(
|
||||
0,
|
||||
int(old_price_image.h / 2),
|
||||
old_price_image.w + 1,
|
||||
int(old_price_image.h / 2),
|
||||
),
|
||||
(0, 0, 0),
|
||||
)
|
||||
await name_image.apaste(old_price_image, (440, 0), True)
|
||||
await name_image.atext((440, 15), str(discount_price), (255, 255, 255))
|
||||
else:
|
||||
await name_image.atext(
|
||||
(440, 0), str(goods.goods_price), (255, 255, 255), center_type="by_height"
|
||||
(440, 0),
|
||||
str(goods.goods_price),
|
||||
(255, 255, 255),
|
||||
center_type="by_height",
|
||||
)
|
||||
await name_image.atext(
|
||||
(
|
||||
@ -68,38 +82,48 @@ async def create_shop_help() -> str:
|
||||
font_img = BuildImage(
|
||||
600, 80, font_size=20, color="#a29ad6", font="CJGaoDeGuo.otf"
|
||||
)
|
||||
p = font_img.getsize('简介:')[0] + 20
|
||||
p = font_img.getsize("简介:")[0] + 20
|
||||
if goods.goods_description:
|
||||
des_list = goods.goods_description.split('\n')
|
||||
desc = ''
|
||||
des_list = goods.goods_description.split("\n")
|
||||
desc = ""
|
||||
for des in des_list:
|
||||
if font_img.getsize(des)[0] > font_img.w - p - 20:
|
||||
msg = ''
|
||||
tmp = ''
|
||||
msg = ""
|
||||
tmp = ""
|
||||
for i in range(len(des)):
|
||||
if font_img.getsize(tmp)[0] < font_img.w - p - 20:
|
||||
tmp += des[i]
|
||||
else:
|
||||
msg += tmp + '\n'
|
||||
msg += tmp + "\n"
|
||||
tmp = des[i]
|
||||
desc += msg
|
||||
if tmp:
|
||||
desc += tmp
|
||||
else:
|
||||
desc += des + '\n'
|
||||
if desc[-1] == '\n':
|
||||
desc += des + "\n"
|
||||
if desc[-1] == "\n":
|
||||
desc = desc[:-1]
|
||||
des_image = await text2image(desc, color="#a29ad6")
|
||||
goods_image = BuildImage(
|
||||
600, (50 + des_image.h) if des_image else 50, font_size=20, color="#a29ad6", font="CJGaoDeGuo.otf"
|
||||
600,
|
||||
(50 + des_image.h) if des_image else 50,
|
||||
font_size=20,
|
||||
color="#a29ad6",
|
||||
font="CJGaoDeGuo.otf",
|
||||
)
|
||||
if des_image:
|
||||
await goods_image.atext((15, 50), '简介:')
|
||||
await goods_image.atext((15, 50), "简介:")
|
||||
await goods_image.apaste(des_image, (p, 50))
|
||||
await name_image.acircle_corner(5)
|
||||
await goods_image.apaste(name_image, (0, 5), True, center_type="by_width")
|
||||
await goods_image.acircle_corner(20)
|
||||
bk = BuildImage(1180, (50 + des_image.h) if des_image else 50, font_size=15, color="#f9f6f2", font="CJGaoDeGuo.otf")
|
||||
bk = BuildImage(
|
||||
1180,
|
||||
(50 + des_image.h) if des_image else 50,
|
||||
font_size=15,
|
||||
color="#f9f6f2",
|
||||
font="CJGaoDeGuo.otf",
|
||||
)
|
||||
if goods.icon and (icon_path / goods.icon).exists():
|
||||
icon = BuildImage(70, 70, background=icon_path / goods.icon)
|
||||
await bk.apaste(icon)
|
||||
@ -129,7 +153,9 @@ async def create_shop_help() -> str:
|
||||
_w += 140
|
||||
if goods.goods_discount != 1:
|
||||
n += 140
|
||||
_discount_logo = BuildImage(30, 30, background=f"{IMAGE_PATH}/other/discount.png")
|
||||
_discount_logo = BuildImage(
|
||||
30, 30, background=f"{IMAGE_PATH}/other/discount.png"
|
||||
)
|
||||
await bk.apaste(_discount_logo, (_w + 50, 10), True)
|
||||
await bk.apaste(
|
||||
BuildImage(0, 0, plain_text="折扣!", font_size=23, font="CJGaoDeGuo.otf"),
|
||||
@ -137,14 +163,23 @@ async def create_shop_help() -> str:
|
||||
True,
|
||||
)
|
||||
await bk.apaste(
|
||||
BuildImage(0, 0, plain_text=f"{10 * goods.goods_discount:.1f} 折", font_size=30, font="CJGaoDeGuo.otf", font_color=(85, 156, 75)),
|
||||
BuildImage(
|
||||
0,
|
||||
0,
|
||||
plain_text=f"{10 * goods.goods_discount:.1f} 折",
|
||||
font_size=30,
|
||||
font="CJGaoDeGuo.otf",
|
||||
font_color=(85, 156, 75),
|
||||
),
|
||||
(_w + 50, 44),
|
||||
True,
|
||||
)
|
||||
_w += 140
|
||||
if goods.daily_limit != 0:
|
||||
n += 140
|
||||
_daily_limit_logo = BuildImage(35, 35, background=f"{IMAGE_PATH}/other/daily_limit.png")
|
||||
_daily_limit_logo = BuildImage(
|
||||
35, 35, background=f"{IMAGE_PATH}/other/daily_limit.png"
|
||||
)
|
||||
await bk.apaste(_daily_limit_logo, (_w + 50, 10), True)
|
||||
await bk.apaste(
|
||||
BuildImage(0, 0, plain_text="限购!", font_size=23, font="CJGaoDeGuo.otf"),
|
||||
@ -152,7 +187,13 @@ async def create_shop_help() -> str:
|
||||
True,
|
||||
)
|
||||
await bk.apaste(
|
||||
BuildImage(0, 0, plain_text=f"{goods.daily_limit}", font_size=30, font="CJGaoDeGuo.otf"),
|
||||
BuildImage(
|
||||
0,
|
||||
0,
|
||||
plain_text=f"{goods.daily_limit}",
|
||||
font_size=30,
|
||||
font="CJGaoDeGuo.otf",
|
||||
),
|
||||
(_w + 72, 45),
|
||||
True,
|
||||
)
|
||||
@ -220,22 +261,30 @@ async def register_goods(
|
||||
:param icon: 图标
|
||||
:return: 是否添加成功
|
||||
"""
|
||||
if not await GoodsInfo.get_goods_info(name):
|
||||
limit_time = float(limit_time) if limit_time else limit_time
|
||||
if not await GoodsInfo.get_or_none(goods_name=name):
|
||||
limit_time_ = float(limit_time) if limit_time else limit_time
|
||||
discount = discount if discount is not None else 1
|
||||
limit_time = (
|
||||
int(time.time() + limit_time * 60 * 60)
|
||||
if limit_time is not None and limit_time != 0
|
||||
limit_time_ = (
|
||||
int(time.time() + limit_time_ * 60 * 60)
|
||||
if limit_time_ is not None and limit_time_ != 0
|
||||
else 0
|
||||
)
|
||||
return await GoodsInfo.add_goods(
|
||||
name, int(price), des, float(discount), limit_time, daily_limit, is_passive, icon
|
||||
await GoodsInfo.create(
|
||||
goods_name=name,
|
||||
goods_price=int(price),
|
||||
goods_description=des,
|
||||
goods_discount=float(discount),
|
||||
goods_limit_time=limit_time_,
|
||||
daily_limit=daily_limit,
|
||||
is_passive=is_passive,
|
||||
icon=icon,
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# 删除商品
|
||||
async def delete_goods(name: str, id_: int) -> "str, str, int":
|
||||
async def delete_goods(name: str, id_: int) -> Tuple[str, str, int]:
|
||||
"""
|
||||
删除商品
|
||||
:param name: 商品名称
|
||||
@ -256,6 +305,7 @@ async def delete_goods(name: str, id_: int) -> "str, str, int":
|
||||
return f"删除商品 {name} 成功!", name, 200
|
||||
else:
|
||||
return f"删除商品 {name} 失败!", name, 999
|
||||
return "获取商品失败", "", 999
|
||||
|
||||
|
||||
# 更新商品信息
|
||||
@ -272,7 +322,7 @@ async def update_goods(**kwargs) -> Tuple[bool, str, str]:
|
||||
return False, "序号错误,没有该序号的商品...", ""
|
||||
goods = goods_lst[int(kwargs["name"]) - 1]
|
||||
else:
|
||||
goods = await GoodsInfo.get_goods_info(kwargs["name"])
|
||||
goods = await GoodsInfo.filter(goods_name=kwargs["name"]).first()
|
||||
if not goods:
|
||||
return False, "名称错误,没有该名称的商品...", ""
|
||||
name: str = goods.goods_name
|
||||
@ -295,14 +345,22 @@ async def update_goods(**kwargs) -> Tuple[bool, str, str]:
|
||||
discount = kwargs["discount"]
|
||||
if kwargs.get("limit_time"):
|
||||
kwargs["limit_time"] = float(kwargs["limit_time"])
|
||||
new_time = time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
time.localtime(time.time() + kwargs["limit_time"] * 60 * 60),
|
||||
) if kwargs["limit_time"] != 0 else 0
|
||||
new_time = (
|
||||
time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
time.localtime(time.time() + kwargs["limit_time"] * 60 * 60),
|
||||
)
|
||||
if kwargs["limit_time"] != 0
|
||||
else 0
|
||||
)
|
||||
tmp += f"限时至: {new_time}\n" if new_time else "取消了限时\n"
|
||||
limit_time = kwargs["limit_time"]
|
||||
if kwargs.get("daily_limit"):
|
||||
tmp += f'每日购买限制:{daily_limit} --> {kwargs["daily_limit"]}\n' if daily_limit else "取消了购买限制\n"
|
||||
tmp += (
|
||||
f'每日购买限制:{daily_limit} --> {kwargs["daily_limit"]}\n'
|
||||
if daily_limit
|
||||
else "取消了购买限制\n"
|
||||
)
|
||||
daily_limit = int(kwargs["daily_limit"])
|
||||
if kwargs.get("is_passive"):
|
||||
tmp += f'被动道具:{is_passive} --> {kwargs["is_passive"]}\n'
|
||||
@ -318,9 +376,13 @@ async def update_goods(**kwargs) -> Tuple[bool, str, str]:
|
||||
else 0
|
||||
),
|
||||
daily_limit,
|
||||
is_passive
|
||||
is_passive,
|
||||
)
|
||||
return (
|
||||
True,
|
||||
name,
|
||||
tmp[:-1],
|
||||
)
|
||||
return True, name, tmp[:-1],
|
||||
|
||||
|
||||
def parse_goods_info(msg: str) -> Union[dict, str]:
|
||||
|
||||
@ -1,19 +1,17 @@
|
||||
from typing import Any, Tuple
|
||||
|
||||
from nonebot import on_command, on_regex
|
||||
|
||||
from models.user_shop_gold_log import UserShopGoldLog
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from nonebot.params import CommandArg, RegexGroup
|
||||
|
||||
from models.bag_user import BagUser
|
||||
from models.user_shop_gold_log import UserShopGoldLog
|
||||
from services.log import logger
|
||||
from utils.decorator.shop import NotMeetUseConditionsException
|
||||
from utils.utils import is_number
|
||||
from models.bag_user import BagUser
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from services.db_context import db
|
||||
from .data_source import effect, register_use, func_manager, build_params
|
||||
|
||||
from .data_source import build_params, effect, func_manager, register_use
|
||||
|
||||
__zx_plugin_name__ = "商店 - 使用道具"
|
||||
__plugin_usage__ = """
|
||||
@ -75,17 +73,25 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
if prop_n not in property_.keys():
|
||||
await use_props.finish("道具名称错误!", at_sender=True)
|
||||
name = prop_n
|
||||
if not name:
|
||||
await use_props.finish("未获取到道具名称", at_sender=True)
|
||||
_user_prop_count = property_[name]
|
||||
if num > _user_prop_count:
|
||||
await use_props.finish(f"道具数量不足,无法使用{num}次!")
|
||||
if num > (n := func_manager.get_max_num_limit(name)):
|
||||
await use_props.finish(f"该道具单次只能使用 {n} 个!")
|
||||
model, kwargs = build_params(bot, event, name, num, text)
|
||||
try:
|
||||
await func_manager.run_handle(type_="before_handle", param=model, **kwargs)
|
||||
except NotMeetUseConditionsException as e:
|
||||
await use_props.finish(e.get_info(), at_sender=True)
|
||||
async with db.transaction():
|
||||
model, kwargs = build_params(bot, event, name, num, text)
|
||||
except KeyError:
|
||||
logger.warning(f"{name} 未注册使用函数")
|
||||
await use_props.finish(f"{name} 未注册使用方法")
|
||||
else:
|
||||
try:
|
||||
await func_manager.run_handle(
|
||||
type_="before_handle", param=model, **kwargs
|
||||
)
|
||||
except NotMeetUseConditionsException as e:
|
||||
await use_props.finish(e.get_info(), at_sender=True)
|
||||
if await BagUser.delete_property(event.user_id, event.group_id, name, num):
|
||||
if func_manager.check_send_success_message(name):
|
||||
await use_props.send(f"使用道具 {name} {num} 次成功!", at_sender=True)
|
||||
@ -94,14 +100,18 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
logger.info(
|
||||
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次成功"
|
||||
)
|
||||
await UserShopGoldLog.add_shop_log(
|
||||
event.user_id, event.group_id, 1, name, num
|
||||
await UserShopGoldLog.create(
|
||||
user_qq=event.user_id,
|
||||
group_id=event.group_id,
|
||||
type=1,
|
||||
name=name,
|
||||
num=num,
|
||||
)
|
||||
else:
|
||||
await use_props.send(f"使用道具 {name} {num} 次失败!", at_sender=True)
|
||||
logger.info(
|
||||
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次失败"
|
||||
)
|
||||
await func_manager.run_handle(type_="after_handle", param=model, **kwargs)
|
||||
await func_manager.run_handle(type_="after_handle", param=model, **kwargs)
|
||||
else:
|
||||
await use_props.send("您的背包里没有任何的道具噢", at_sender=True)
|
||||
|
||||
@ -108,7 +108,7 @@ class GoodsUseFuncManager:
|
||||
)
|
||||
|
||||
async def run_handle(self, goods_name: str, type_: str, param: ShopParam, **kwargs):
|
||||
if self._data[goods_name].get(type_):
|
||||
if self._data.get(goods_name) and self._data[goods_name].get(type_):
|
||||
for func in self._data[goods_name].get(type_):
|
||||
args = inspect.signature(func).parameters
|
||||
if args and list(args.keys())[0] != "kwargs":
|
||||
@ -170,7 +170,6 @@ def build_params(
|
||||
:param goods_name: 商品名称
|
||||
:param num: 数量
|
||||
:param text: 其他信息
|
||||
:return:
|
||||
"""
|
||||
_kwargs = func_manager.get_kwargs(goods_name)
|
||||
return (
|
||||
|
||||
@ -1,11 +1,5 @@
|
||||
import nonebot
|
||||
from pathlib import Path
|
||||
|
||||
import nonebot
|
||||
|
||||
nonebot.load_plugins(str(Path(__file__).parent.resolve()))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.adapters.onebot.v11 import Bot, Message
|
||||
from nonebot.params import Command, CommandArg
|
||||
from typing import Tuple
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
|
||||
from nonebot.params import Command, CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.rule import to_me
|
||||
from utils.utils import is_number
|
||||
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from utils.depends import OneCommand
|
||||
from utils.manager import requests_manager
|
||||
from utils.message_builder import image
|
||||
from models.group_info import GroupInfo
|
||||
|
||||
from utils.utils import is_number
|
||||
|
||||
__zx_plugin_name__ = "显示所有好友群组 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
@ -76,8 +79,7 @@ async def _(bot: Bot):
|
||||
|
||||
|
||||
@friend_handle.handle()
|
||||
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
cmd = cmd[0]
|
||||
async def _(bot: Bot, cmd: str = OneCommand(), arg: Message = CommandArg()):
|
||||
id_ = arg.extract_plain_text().strip()
|
||||
if is_number(id_):
|
||||
id_ = int(id_)
|
||||
@ -97,8 +99,9 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
|
||||
|
||||
|
||||
@group_handle.handle()
|
||||
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
cmd = cmd[0]
|
||||
async def _(
|
||||
bot: Bot, event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()
|
||||
):
|
||||
id_ = arg.extract_plain_text().strip()
|
||||
flag = None
|
||||
if is_number(id_):
|
||||
@ -106,20 +109,21 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
|
||||
if cmd[:2] == "同意":
|
||||
rid = requests_manager.get_group_id(id_)
|
||||
if rid:
|
||||
if await GroupInfo.get_group_info(rid):
|
||||
await GroupInfo.set_group_flag(rid, 1)
|
||||
if group := await GroupInfo.filter(group_id=rid).first():
|
||||
await group.update_or_create(group_flag=1)
|
||||
else:
|
||||
group_info = await bot.get_group_info(group_id=rid)
|
||||
await GroupInfo.add_group_info(
|
||||
rid,
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1
|
||||
await GroupInfo.create(
|
||||
group_id=rid,
|
||||
group_name=group_info["group_name"],
|
||||
max_member_count=group_info["max_member_count"],
|
||||
member_count=group_info["member_count"],
|
||||
group_flag=1,
|
||||
)
|
||||
flag = await requests_manager.approve(bot, id_, "group")
|
||||
else:
|
||||
await group_handle.send("同意群聊请求失败,未找到此id的请求..")
|
||||
logger.info("同意群聊请求失败,未找到此id的请求..", cmd, event.user_id)
|
||||
else:
|
||||
flag = await requests_manager.refused(bot, id_, "group")
|
||||
if flag == 1:
|
||||
@ -139,15 +143,15 @@ async def _():
|
||||
for type_ in ["private", "group"]:
|
||||
msg = await requests_manager.show(type_)
|
||||
if msg:
|
||||
_str += image(b64=msg)
|
||||
_str += image(msg)
|
||||
else:
|
||||
_str += "没有任何好友请求.." if type_ == "private" else "没有任何群聊请求.."
|
||||
if type_ == "private":
|
||||
_str += '\n--------------------\n'
|
||||
_str += "\n--------------------\n"
|
||||
await cls_request.send(Message(_str))
|
||||
|
||||
|
||||
@clear_request.handle()
|
||||
async def _():
|
||||
requests_manager.clear()
|
||||
await clear_request.send("已清空所有好友/群聊请求..")
|
||||
await clear_request.send("已清空所有好友/群聊请求..")
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.permission import SUPERUSER
|
||||
from configs.path_config import TEMP_PATH
|
||||
from nonebot.rule import to_me
|
||||
from utils.utils import scheduler
|
||||
|
||||
from configs.path_config import TEMP_PATH
|
||||
from services.log import logger
|
||||
from utils.manager import resources_manager
|
||||
import asyncio
|
||||
import time
|
||||
import os
|
||||
from utils.utils import scheduler
|
||||
|
||||
__zx_plugin_name__ = "清理临时数据 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
@ -37,22 +39,29 @@ async def _():
|
||||
await clear_data.send("开始清理临时数据....")
|
||||
size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
|
||||
await clear_data.send("共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
|
||||
logger.info("清理临时数据完成," + "共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
|
||||
|
||||
|
||||
def _clear_data() -> float:
|
||||
logger.debug("开始清理临时文件...")
|
||||
size = 0
|
||||
for dir_ in resources_manager.get_temp_data_dir():
|
||||
if dir_.exists():
|
||||
for file in os.listdir(dir_):
|
||||
file = dir_ / file
|
||||
if file.is_file():
|
||||
try:
|
||||
if time.time() - os.path.getatime(file) > 300:
|
||||
file_size = os.path.getsize(file)
|
||||
file.unlink()
|
||||
size += file_size
|
||||
except Exception as e:
|
||||
logger.error(f"清理临时数据错误...{type(e)}:{e}")
|
||||
dir_list = [dir_ for dir_ in resources_manager.get_temp_data_dir() if dir_.exists()]
|
||||
for dir_ in dir_list:
|
||||
logger.debug(f"尝试清理文件夹: {dir_.absolute()}", "清理临时数据")
|
||||
dir_size = 0
|
||||
for file in os.listdir(dir_):
|
||||
file = dir_ / file
|
||||
if file.is_file():
|
||||
try:
|
||||
if time.time() - os.path.getatime(file) > 10:
|
||||
file_size = os.path.getsize(file)
|
||||
file.unlink()
|
||||
size += file_size
|
||||
dir_size += file_size
|
||||
logger.debug(f"移除临时文件: {file.absolute()}", "清理临时数据")
|
||||
except Exception as e:
|
||||
logger.error(f"清理临时数据错误,临时文件夹: {dir_.absolute()}...", "清理临时数据", e=e)
|
||||
logger.debug("清理临时文件夹大小: {:.2f}MB".format(size / 1024 / 1024), "清理临时数据")
|
||||
return float(size)
|
||||
|
||||
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
from nonebot.adapters.onebot.v11 import Message, Bot, MessageEvent
|
||||
import asyncio
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.rule import to_me
|
||||
from utils.message_builder import custom_forward_msg
|
||||
from services.db_context import db
|
||||
from nonebot.params import CommandArg
|
||||
from services.log import logger
|
||||
from tortoise import Tortoise
|
||||
|
||||
import asyncio
|
||||
from services.db_context import TestSQL
|
||||
from services.log import logger
|
||||
from utils.message_builder import custom_forward_msg
|
||||
|
||||
__zx_plugin_name__ = "执行sql [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
@ -18,9 +20,7 @@ usage:
|
||||
查看所有表
|
||||
""".strip()
|
||||
__plugin_des__ = "执行一段sql语句"
|
||||
__plugin_cmd__ = [
|
||||
"exec [sql语句]",
|
||||
]
|
||||
__plugin_cmd__ = ["exec [sql语句]", "查看所有表"]
|
||||
__plugin_version__ = 0.2
|
||||
__plugin_author__ = "HibiKier"
|
||||
|
||||
@ -32,55 +32,61 @@ tables = on_command("查看所有表", rule=to_me(), permission=SUPERUSER, prior
|
||||
@exec_.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
sql = arg.extract_plain_text().strip()
|
||||
async with db.transaction():
|
||||
if not sql:
|
||||
await exec_.finish("未接受到sql语句")
|
||||
db = Tortoise.get_connection("default")
|
||||
# try:
|
||||
# 判断是否为SELECT语句
|
||||
if sql.lower().startswith("select"):
|
||||
pass
|
||||
# # 分割语句
|
||||
try:
|
||||
# 判断是否为SELECT语句
|
||||
if sql.lower().startswith("select"):
|
||||
# 分割语句
|
||||
try:
|
||||
page = int(sql.split(" ")[-1]) - 1
|
||||
sql_list = sql.split(" ")[:-1]
|
||||
except ValueError:
|
||||
page = 0
|
||||
sql_list = sql.split(" ")
|
||||
# 拼接语句
|
||||
sql = " ".join(sql_list)
|
||||
query = db.text(sql)
|
||||
res = await db.all(query)
|
||||
msg_list = [f"第{page+1}页查询结果:"]
|
||||
# logger.info(res)
|
||||
# 获取所有字段
|
||||
keys = res[0].keys()
|
||||
# 每页10条
|
||||
for i in res[page * 10 : (page + 1) * 10]:
|
||||
msg = ""
|
||||
for key in keys:
|
||||
msg += f"{key}: {i[key]}\n"
|
||||
msg += f"第{page+1}页第{res.index(i)+1}条"
|
||||
msg_list.append(msg)
|
||||
# 检查是私聊还是群聊
|
||||
try:
|
||||
forward_msg_list = custom_forward_msg(msg_list, bot.self_id)
|
||||
await bot.send_group_forward_msg(group_id=event.group_id, messages=forward_msg_list)
|
||||
except:
|
||||
for msg in msg_list:
|
||||
await exec_.send(msg)
|
||||
await asyncio.sleep(0.2)
|
||||
return
|
||||
query = db.text(sql)
|
||||
await db.first(query)
|
||||
await exec_.send("执行 sql 语句成功.")
|
||||
except Exception as e:
|
||||
await exec_.send(f"执行 sql 语句失败 {type(e)}:{e}")
|
||||
logger.error(f"执行 sql 语句失败 {type(e)}:{e}")
|
||||
page = int(sql.split(" ")[-1]) - 1
|
||||
sql_list = sql.split(" ")[:-1]
|
||||
except ValueError:
|
||||
page = 0
|
||||
sql_list = sql.split(" ")
|
||||
# 拼接语句
|
||||
sql = " ".join(sql_list)
|
||||
res = await db.execute_query_dict(sql)
|
||||
msg_list = [f"第{page+1}页查询结果:"]
|
||||
# logger.info(res)
|
||||
# 获取所有字段
|
||||
keys = res[0].keys()
|
||||
# 每页10条
|
||||
for i in res[page * 10 : (page + 1) * 10]:
|
||||
msg = ""
|
||||
for key in keys:
|
||||
msg += f"{key}: {i[key]}\n"
|
||||
msg += f"第{page+1}页第{res.index(i)+1}条"
|
||||
msg_list.append(msg)
|
||||
# 检查是私聊还是群聊
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
forward_msg_list = custom_forward_msg(msg_list, bot.self_id)
|
||||
await bot.send_group_forward_msg(
|
||||
group_id=event.group_id, messages=forward_msg_list
|
||||
)
|
||||
else:
|
||||
for msg in msg_list:
|
||||
await exec_.send(msg)
|
||||
await asyncio.sleep(0.2)
|
||||
return
|
||||
else:
|
||||
await TestSQL.raw(sql)
|
||||
await exec_.send("执行 sql 语句成功.")
|
||||
# except Exception as e:
|
||||
# await exec_.send(f"执行 sql 语句失败 {type(e)}:{e}")
|
||||
# logger.error(f"执行 sql 语句失败 {type(e)}:{e}")
|
||||
|
||||
|
||||
@tables.handle()
|
||||
async def _(bot: Bot, event: MessageEvent):
|
||||
# 获取所有表
|
||||
query = db.text("select tablename from pg_tables where schemaname = 'public'")
|
||||
res = await db.all(query)
|
||||
db = Tortoise.get_connection("default")
|
||||
query = await db.execute_query_dict(
|
||||
"select tablename from pg_tables where schemaname = 'public'"
|
||||
)
|
||||
msg = "数据库中的所有表名:\n"
|
||||
for tablename in res:
|
||||
for tablename in query:
|
||||
msg += str(tablename["tablename"]) + "\n"
|
||||
await tables.finish(msg)
|
||||
|
||||
@ -1,35 +1,39 @@
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
MessageEvent,
|
||||
GROUP,
|
||||
GroupMessageEvent,
|
||||
Message,
|
||||
ActionFailed,
|
||||
)
|
||||
from nonebot import on_command, on_regex
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.rule import to_me
|
||||
from utils.utils import is_number
|
||||
from utils.manager import group_manager, plugins2settings_manager
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from configs.config import NICKNAME
|
||||
from nonebot.params import Command, CommandArg
|
||||
from typing import Tuple
|
||||
|
||||
from nonebot import on_command, on_regex
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
GROUP,
|
||||
Bot,
|
||||
GroupMessageEvent,
|
||||
Message,
|
||||
MessageEvent,
|
||||
)
|
||||
from nonebot.params import Command, CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.rule import to_me
|
||||
|
||||
from configs.config import NICKNAME
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from utils.depends import OneCommand
|
||||
from utils.image_utils import text2image
|
||||
from utils.manager import group_manager, plugins2settings_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import is_number
|
||||
|
||||
__zx_plugin_name__ = "管理群操作 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
群权限 | 群白名单 | 退出群 操作
|
||||
指令:
|
||||
退群 [group_id]
|
||||
退群,添加/删除群白名单,添加/删除群认证,当在群聊中这五个命令且没有指定群号时,默认指定当前群聊
|
||||
指令:
|
||||
退群 ?[group_id]
|
||||
修改群权限 [group_id] [等级]
|
||||
添加群白名单 *[group_id]
|
||||
删除群白名单 *[group_id]
|
||||
添加群认证 *[group_id]
|
||||
删除群认证 *[group_id]
|
||||
修改群权限 [等级]: 该命令仅在群聊时生效,默认修改当前群聊
|
||||
添加群白名单 ?*[group_id]
|
||||
删除群白名单 ?*[group_id]
|
||||
添加群认证 ?*[group_id]
|
||||
删除群认证 ?*[group_id]
|
||||
查看群白名单
|
||||
""".strip()
|
||||
__plugin_des__ = "管理群操作"
|
||||
@ -53,7 +57,7 @@ my_group_level = on_command(
|
||||
"查看群权限", aliases={"群权限"}, priority=5, permission=GROUP, block=True
|
||||
)
|
||||
what_up_group_level = on_regex(
|
||||
".*?(提高|提升|升高|增加|加上)(.*?)群权限.*?",
|
||||
"(:?提高|提升|升高|增加|加上).*?群权限",
|
||||
rule=to_me(),
|
||||
priority=5,
|
||||
permission=GROUP,
|
||||
@ -73,47 +77,57 @@ group_auth = on_command(
|
||||
|
||||
|
||||
@del_group.handle()
|
||||
async def _(bot: Bot, arg: Message = CommandArg()):
|
||||
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
group_id = arg.extract_plain_text().strip()
|
||||
if not group_id and isinstance(event, GroupMessageEvent):
|
||||
group_id = event.group_id
|
||||
if group_id:
|
||||
if is_number(group_id):
|
||||
group_list = [x["group_id"] for x in await bot.get_group_list()]
|
||||
group_id = int(group_id)
|
||||
if group_id not in group_list:
|
||||
logger.debug("群聊不存在", "退群", event.user_id, target=group_id)
|
||||
await del_group.finish(f"{NICKNAME}未在该群聊中...")
|
||||
try:
|
||||
await bot.set_group_leave(group_id=int(group_id))
|
||||
logger.info(f"退出群聊 {group_id} 成功")
|
||||
await bot.set_group_leave(group_id=group_id)
|
||||
logger.info(f"{NICKNAME}退出群聊成功", "退群", event.user_id, target=group_id)
|
||||
await del_group.send(f"退出群聊 {group_id} 成功", at_sender=True)
|
||||
group_manager.delete_group(int(group_id))
|
||||
await GroupInfo.delete_group_info(int(group_id))
|
||||
group_manager.delete_group(group_id)
|
||||
await GroupInfo.filter(group_id=group_id).delete()
|
||||
except Exception as e:
|
||||
logger.info(f"退出群聊 {group_id} 失败 e:{e}")
|
||||
logger.error(f"退出群聊失败", "退群", event.user_id, target=group_id, e=e)
|
||||
await del_group.send(f"退出群聊 {group_id} 失败", at_sender=True)
|
||||
else:
|
||||
await del_group.finish(f"请输入正确的群号", at_sender=True)
|
||||
await del_group.send(f"请输入正确的群号", at_sender=True)
|
||||
else:
|
||||
await del_group.finish(f"请输入群号", at_sender=True)
|
||||
await del_group.send(f"请输入群号", at_sender=True)
|
||||
|
||||
|
||||
@add_group_level.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
msg = arg.extract_plain_text().strip()
|
||||
msg = msg.split()
|
||||
group_id = 0
|
||||
level = 0
|
||||
if isinstance(event, GroupMessageEvent) and len(msg) == 1:
|
||||
msg = [event.group_id, msg[0]]
|
||||
if not msg:
|
||||
await add_group_level.finish("用法:修改群权限 [group] [level]")
|
||||
msg = msg.split()
|
||||
await add_group_level.finish("缺失参数...")
|
||||
if len(msg) < 2:
|
||||
await add_group_level.finish("参数不完全..[group] [level]")
|
||||
await add_group_level.finish("缺失参数...")
|
||||
if is_number(msg[0]) and is_number(msg[1]):
|
||||
group_id = msg[0]
|
||||
group_id = int(msg[0])
|
||||
level = int(msg[1])
|
||||
else:
|
||||
await add_group_level.finish("参数错误...group和level必须是数字..")
|
||||
await add_group_level.finish("参数错误...群号和等级必须是数字..")
|
||||
old_level = group_manager.get_group_level(group_id)
|
||||
group_manager.set_group_level(group_id, level)
|
||||
await add_group_level.send("修改成功...", at_sender=True)
|
||||
if level > -1:
|
||||
await bot.send_group_msg(
|
||||
group_id=int(group_id), message=f"管理员修改了此群权限:{old_level} -> {level}"
|
||||
group_id=group_id, message=f"管理员修改了此群权限:{old_level} -> {level}"
|
||||
)
|
||||
logger.info(f"{event.user_id} 修改了 {group_id} 的权限:{level}")
|
||||
logger.info(f"修改群权限:{level}", "修改群权限", event.user_id, target=group_id)
|
||||
|
||||
|
||||
@my_group_level.handle()
|
||||
@ -127,78 +141,104 @@ async def _(event: GroupMessageEvent):
|
||||
if plugin_name == "pixiv":
|
||||
plugin_name = "搜图 p站排行"
|
||||
tmp += f"{plugin_name}\n"
|
||||
if tmp:
|
||||
tmp = "\n目前无法使用的功能:\n" + tmp
|
||||
await my_group_level.finish(f"当前群权限:{level}{tmp}")
|
||||
if not tmp:
|
||||
await my_group_level.finish(f"当前群权限:{level}")
|
||||
await my_group_level.finish(
|
||||
f"当前群权限:{level}\n目前无法使用的功能:\n"
|
||||
+ image(await text2image(tmp, padding=10, color="#f9f6f2"))
|
||||
)
|
||||
|
||||
|
||||
@what_up_group_level.handle()
|
||||
async def _():
|
||||
await what_up_group_level.finish(
|
||||
f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.管理员修改权限"
|
||||
f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.超级管理员修改权限"
|
||||
)
|
||||
|
||||
|
||||
@manager_group_whitelist.handle()
|
||||
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
cmd = cmd[0]
|
||||
async def _(
|
||||
bot: Bot, event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()
|
||||
):
|
||||
msg = arg.extract_plain_text().strip().split()
|
||||
if not msg and isinstance(event, GroupMessageEvent):
|
||||
msg = [event.group_id]
|
||||
if not msg:
|
||||
await manager_group_whitelist.finish("请输入群号")
|
||||
all_group = [g["group_id"] for g in await bot.get_group_list()]
|
||||
error_group = []
|
||||
group_list = []
|
||||
for group in msg:
|
||||
if is_number(group) and int(group) in all_group:
|
||||
group_list.append(int(group))
|
||||
for group_id in msg:
|
||||
if is_number(group_id) and int(group_id) in all_group:
|
||||
group_list.append(int(group_id))
|
||||
else:
|
||||
logger.debug(f"群号不合法或不存在", cmd, target=group_id)
|
||||
error_group.append(group_id)
|
||||
if group_list:
|
||||
for group in group_list:
|
||||
for group_id in group_list:
|
||||
if cmd in ["添加群白名单"]:
|
||||
group_manager.add_group_white_list(group)
|
||||
group_manager.add_group_white_list(group_id)
|
||||
else:
|
||||
group_manager.delete_group_white_list(group)
|
||||
group_manager.delete_group_white_list(group_id)
|
||||
group_list = [str(x) for x in group_list]
|
||||
await manager_group_whitelist.send("已成功将 " + "\n".join(group_list) + " " + cmd)
|
||||
else:
|
||||
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
|
||||
group_manager.save()
|
||||
if error_group:
|
||||
await manager_group_whitelist.send("以下群聊不合法或不存在:\n" + "\n".join(error_group))
|
||||
|
||||
|
||||
@show_group_whitelist.handle()
|
||||
async def _():
|
||||
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("没有任何群在群白名单...")
|
||||
group = [str(g) for g in group_manager.get_group_white_list()]
|
||||
if not group:
|
||||
await show_group_whitelist.finish("没有任何群在群白名单...")
|
||||
await show_group_whitelist.send("目前的群白名单:\n" + "\n".join(group))
|
||||
|
||||
|
||||
@group_auth.handle()
|
||||
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
cmd = cmd[0]
|
||||
async def _(
|
||||
bot: Bot, event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()
|
||||
):
|
||||
msg = arg.extract_plain_text().strip().split()
|
||||
if isinstance(event, GroupMessageEvent) and not msg:
|
||||
msg = [event.group_id]
|
||||
if not msg:
|
||||
await manager_group_whitelist.finish("请输入群号")
|
||||
error_group = []
|
||||
all_group = [g["group_id"] for g in await bot.get_group_list()]
|
||||
for group_id in msg:
|
||||
if not is_number(group_id):
|
||||
await group_auth.send(f"{group_id}非纯数字,已跳过该项..")
|
||||
group_id = int(group_id)
|
||||
if cmd[:2] == "添加":
|
||||
if await GroupInfo.get_group_info(group_id):
|
||||
await GroupInfo.set_group_flag(group_id, 1)
|
||||
else:
|
||||
if is_number(group_id) and group_id in all_group:
|
||||
if cmd[:2] == "添加":
|
||||
try:
|
||||
group_info = await bot.get_group_info(group_id=group_id)
|
||||
except ActionFailed:
|
||||
group_info = {
|
||||
"group_id": group_id,
|
||||
"group_name": "_",
|
||||
"max_member_count": -1,
|
||||
"member_count": -1,
|
||||
}
|
||||
await GroupInfo.add_group_info(
|
||||
group_info["group_id"],
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1,
|
||||
)
|
||||
await GroupInfo.update_or_create(
|
||||
group_id=group_info["group_id"],
|
||||
defaults={
|
||||
"group_flag": 1,
|
||||
"group_name": group_info["group_name"],
|
||||
"max_member_count": group_info["max_member_count"],
|
||||
"member_count": group_info["member_count"],
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
await group_auth.send(f"添加群认证 {group_id} 发生错误!")
|
||||
logger.error(f"添加群认证发生错误", cmd, target=group_id, e=e)
|
||||
else:
|
||||
await group_auth.send(f"已为 {group_id} {cmd[:2]}群认证..")
|
||||
logger.info(f"添加群认证成功", cmd, target=group_id)
|
||||
else:
|
||||
if group := await GroupInfo.filter(group_id=group_id).first():
|
||||
await group.update_or_create(
|
||||
group_id=group_id, defaults={"group_flag": 0}
|
||||
)
|
||||
await group_auth.send(f"已删除 {group_id} 群认证..")
|
||||
logger.info(f"删除群认证成功", cmd, target=group_id)
|
||||
else:
|
||||
await group_auth.send(f"未查找到群聊: {group_id}")
|
||||
logger.info(f"未找到群聊", cmd, target=group_id)
|
||||
else:
|
||||
if await GroupInfo.get_group_info(group_id):
|
||||
await GroupInfo.set_group_flag(group_id, 0)
|
||||
await group_auth.send(f"已为 {group_id} {cmd[:2]}群认证..")
|
||||
logger.debug(f"群号不合法或不存在", cmd, target=group_id)
|
||||
error_group.append(str(group_id))
|
||||
if error_group:
|
||||
await manager_group_whitelist.send("以下群聊不合法或不存在:\n" + "\n".join(error_group))
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.rule import to_me
|
||||
from utils.manager import (
|
||||
plugins2cd_manager,
|
||||
plugins2settings_manager,
|
||||
plugins2block_manager,
|
||||
group_manager,
|
||||
)
|
||||
|
||||
from configs.config import Config
|
||||
from services.log import logger
|
||||
from utils.manager import (
|
||||
group_manager,
|
||||
plugins2block_manager,
|
||||
plugins2cd_manager,
|
||||
plugins2settings_manager,
|
||||
)
|
||||
from utils.utils import scheduler
|
||||
|
||||
|
||||
__zx_plugin_name__ = "重载插件配置 [Superuser]"
|
||||
__zx_plugin_name__ = "重载配置 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
重载插件配置
|
||||
重载配置
|
||||
plugins2settings,
|
||||
plugins2cd
|
||||
plugins2block
|
||||
@ -23,23 +23,15 @@ usage:
|
||||
指令:
|
||||
重载插件配置
|
||||
""".strip()
|
||||
__plugin_des__ = "重载插件配置"
|
||||
__plugin_des__ = "重载配置"
|
||||
__plugin_cmd__ = [
|
||||
"重载插件配置",
|
||||
"重载配置",
|
||||
]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_version__ = 0.2
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_configs__ = {
|
||||
"AUTO_RELOAD": {
|
||||
"value": False,
|
||||
"help": "自动重载配置文件",
|
||||
"default_value": False
|
||||
},
|
||||
"AUTO_RELOAD_TIME": {
|
||||
"value": 180,
|
||||
"help": "控制自动重载配置文件时长",
|
||||
"default_value": 180
|
||||
}
|
||||
"AUTO_RELOAD": {"value": False, "help": "自动重载配置文件", "default_value": False},
|
||||
"AUTO_RELOAD_TIME": {"value": 180, "help": "控制自动重载配置文件时长", "default_value": 180},
|
||||
}
|
||||
|
||||
|
||||
@ -59,7 +51,7 @@ async def _():
|
||||
|
||||
|
||||
@scheduler.scheduled_job(
|
||||
'interval',
|
||||
"interval",
|
||||
seconds=Config.get_config("reload_setting", "AUTO_RELOAD_TIME", 180),
|
||||
)
|
||||
async def _():
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
from typing import List, Tuple
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.exception import ActionFailed
|
||||
from nonebot.params import CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from models.level_user import LevelUser
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
|
||||
from utils.utils import get_message_at, is_number
|
||||
from services.log import logger
|
||||
from utils.depends import AtList, OneCommand
|
||||
from utils.message_builder import at
|
||||
from nonebot.params import Command, CommandArg
|
||||
from typing import Tuple
|
||||
from utils.utils import is_number
|
||||
|
||||
__zx_plugin_name__ = "用户权限管理 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
@ -16,12 +20,14 @@ usage:
|
||||
添加权限 [at] [权限]
|
||||
添加权限 [qq] [group_id] [权限]
|
||||
删除权限 [at]
|
||||
删除权限 [qq] [group_id]
|
||||
""".strip()
|
||||
__plugin_des__ = "增删改用户的权限"
|
||||
__plugin_cmd__ = [
|
||||
"添加权限 [at] [权限]",
|
||||
"添加权限 [qq] [group_id] [权限]",
|
||||
"删除权限 [at]",
|
||||
"删除权限 [qq] [group_id]",
|
||||
]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
@ -40,21 +46,22 @@ super_cmd = on_command(
|
||||
async def _(
|
||||
bot: Bot,
|
||||
event: MessageEvent,
|
||||
cmd: Tuple[str, ...] = Command(),
|
||||
cmd: str = OneCommand(),
|
||||
arg: Message = CommandArg(),
|
||||
at_list: List[int] = AtList(),
|
||||
):
|
||||
group_id = event.group_id if isinstance(event, GroupMessageEvent) else -1
|
||||
level = None
|
||||
args = arg.extract_plain_text().strip().split()
|
||||
qq = get_message_at(event.json())
|
||||
flag = 2
|
||||
qq = None
|
||||
try:
|
||||
if qq:
|
||||
qq = qq[0]
|
||||
if cmd[0][:2] == "添加" and args and is_number(args[0]):
|
||||
if at_list:
|
||||
qq = at_list[0]
|
||||
if cmd[:2] == "添加" and args and is_number(args[0]):
|
||||
level = int(args[0])
|
||||
else:
|
||||
if cmd[0][:2] == "添加":
|
||||
if cmd[:2] == "添加":
|
||||
if (
|
||||
len(args) > 2
|
||||
and is_number(args[0])
|
||||
@ -69,33 +76,39 @@ async def _(
|
||||
qq = int(args[0])
|
||||
group_id = int(args[1])
|
||||
flag = 1
|
||||
level = -1 if cmd[0][:2] == "删除" else level
|
||||
level = -1 if cmd[:2] == "删除" else level
|
||||
if group_id == -1 or not level or not qq:
|
||||
raise IndexError()
|
||||
except IndexError:
|
||||
await super_cmd.finish(__plugin_usage__)
|
||||
if not qq:
|
||||
await super_cmd.finish("未指定对象...")
|
||||
try:
|
||||
if cmd[0][:2] == "添加":
|
||||
if await LevelUser.set_level(qq, group_id, level, 1):
|
||||
result = f"添加管理成功, 权限: {level}"
|
||||
else:
|
||||
result = f"管理已存在, 更新权限: {level}"
|
||||
if cmd[:2] == "添加":
|
||||
await LevelUser.set_level(qq, group_id, level, 1)
|
||||
result = f"设置权限成功, 权限: {level}"
|
||||
else:
|
||||
if await LevelUser.delete_level(qq, event.group_id):
|
||||
if await LevelUser.delete_level(qq, group_id):
|
||||
result = "删除管理成功!"
|
||||
else:
|
||||
result = "该账号无管理权限!"
|
||||
if flag == 2:
|
||||
await super_cmd.send(result)
|
||||
elif flag == 1:
|
||||
await bot.send_group_msg(
|
||||
group_id=group_id,
|
||||
message=Message(
|
||||
f"{at(qq)}管理员修改了你的权限"
|
||||
f"\n--------\n你当前的权限等级:{level if level != -1 else 0}"
|
||||
),
|
||||
)
|
||||
try:
|
||||
await bot.send_group_msg(
|
||||
group_id=group_id,
|
||||
message=Message(
|
||||
f"{at(qq)}管理员修改了你的权限"
|
||||
f"\n--------\n你当前的权限等级:{level if level != -1 else 0}"
|
||||
),
|
||||
)
|
||||
except ActionFailed:
|
||||
pass
|
||||
await super_cmd.send("修改成功")
|
||||
logger.info(
|
||||
f"修改权限: {level if level != -1 else 0}", cmd, event.user_id, group_id, qq
|
||||
)
|
||||
except Exception as e:
|
||||
await super_cmd.send("执行指令失败!")
|
||||
logger.error(f"执行指令失败 e:{e}")
|
||||
logger.error(f"执行指令失败", cmd, event.user_id, group_id, qq, e=e)
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message
|
||||
from nonebot.rule import to_me
|
||||
from utils.utils import is_number
|
||||
from services.log import logger
|
||||
from utils.manager import group_manager
|
||||
from nonebot.params import Command, CommandArg
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
__zx_plugin_name__ = "超级用户被动开关 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
超级用户被动开关
|
||||
指令:
|
||||
开启/关闭广播通知
|
||||
""".strip()
|
||||
__plugin_des__ = "超级用户被动开关"
|
||||
__plugin_cmd__ = [
|
||||
"开启/关闭广播通知",
|
||||
]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
|
||||
|
||||
oc_gb = on_command(
|
||||
"开启广播通知",
|
||||
aliases={"关闭广播通知"},
|
||||
rule=to_me(),
|
||||
permission=SUPERUSER,
|
||||
priority=1,
|
||||
block=True,
|
||||
)
|
||||
|
||||
|
||||
@oc_gb.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
cmd = cmd[0]
|
||||
group = arg.extract_plain_text().strip()
|
||||
if group:
|
||||
if is_number(group):
|
||||
group = int(group)
|
||||
for g in await bot.get_group_list():
|
||||
if g["group_id"] == group:
|
||||
break
|
||||
else:
|
||||
await oc_gb.finish("没有加入这个群...", at_sender=True)
|
||||
if cmd == "开启广播通知":
|
||||
logger.info(f"USER {event.user_id} 开启了 GROUP {group} 的广播")
|
||||
await oc_gb.finish(await group_manager.open_group_task(group, "broadcast",), at_sender=True)
|
||||
else:
|
||||
logger.info(f"USER {event.user_id} 关闭了 GROUP {group} 的广播")
|
||||
await oc_gb.finish(await group_manager.close_group_task(group, "broadcast"), at_sender=True)
|
||||
else:
|
||||
await oc_gb.finish("请输入正确的群号", at_sender=True)
|
||||
else:
|
||||
await oc_gb.finish("请输入要关闭广播的群号", at_sender=True)
|
||||
@ -1,11 +1,11 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.rule import to_me
|
||||
from utils.utils import get_bot
|
||||
from services.log import logger
|
||||
from models.group_info import GroupInfo
|
||||
from models.friend_user import FriendUser
|
||||
|
||||
from models.friend_user import FriendUser
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
|
||||
__zx_plugin_name__ = "更新群/好友信息 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
@ -32,39 +32,46 @@ update_friend_info = on_command(
|
||||
|
||||
|
||||
@update_group_info.handle()
|
||||
async def _():
|
||||
bot = get_bot()
|
||||
async def _(bot: Bot, event: MessageEvent):
|
||||
gl = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in gl]
|
||||
num = 0
|
||||
rst = ""
|
||||
for g in gl:
|
||||
group_info = await bot.get_group_info(group_id=g)
|
||||
if await GroupInfo.add_group_info(
|
||||
group_info["group_id"],
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1
|
||||
):
|
||||
try:
|
||||
group_info = await bot.get_group_info(group_id=g)
|
||||
await GroupInfo.update_or_create(
|
||||
group_id=group_info["group_id"],
|
||||
defaults={
|
||||
"group_name": group_info["group_name"],
|
||||
"max_member_count": group_info["max_member_count"],
|
||||
"member_count": group_info["member_count"],
|
||||
},
|
||||
)
|
||||
num += 1
|
||||
logger.info(f"自动更新群组 {g} 信息成功")
|
||||
else:
|
||||
logger.info(f"自动更新群组 {g} 信息失败")
|
||||
rst += f"{g} 更新失败\n"
|
||||
await update_group_info.send(f"成功更新了 {num} 个群的信息\n{rst[:-1]}")
|
||||
logger.debug(
|
||||
"群聊信息更新成功", "更新群信息", event.user_id, target=group_info["group_id"]
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"更新群聊信息失败", "更新群信息", event.user_id, target=g, e=e)
|
||||
await update_group_info.send(f"成功更新了 {len(gl)} 个群的信息")
|
||||
logger.info(f"更新群聊信息完成,共更新了 {len(gl)} 个群的信息", "更新群信息", event.user_id)
|
||||
|
||||
|
||||
@update_friend_info.handle()
|
||||
async def _():
|
||||
async def _(bot: Bot, event: MessageEvent):
|
||||
num = 0
|
||||
rst = ""
|
||||
fl = await get_bot().get_friend_list()
|
||||
error_list = []
|
||||
fl = await bot.get_friend_list()
|
||||
for f in fl:
|
||||
if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
|
||||
logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
|
||||
try:
|
||||
await FriendUser.update_or_create(
|
||||
user_id=f["user_id"], defaults={"nickname": f["nickname"]}
|
||||
)
|
||||
logger.debug(f"更新好友信息成功", "更新好友信息", event.user_id, target=f["user_id"])
|
||||
num += 1
|
||||
else:
|
||||
logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
|
||||
rst += f'{f["user_id"]} 更新失败\n'
|
||||
await update_friend_info.send(f"成功更新了 {num} 个好友的信息\n{rst[:-1]}")
|
||||
except Exception as e:
|
||||
logger.error(f"更新好友信息失败", "更新好友信息", event.user_id, target=f["user_id"], e=e)
|
||||
await update_friend_info.send(f"成功更新了 {num} 个好友的信息")
|
||||
if error_list:
|
||||
await update_friend_info.send(f"以下好友更新失败:\n" + "\n".join(error_list))
|
||||
logger.info(f"更新好友信息完成,共更新了 {num} 个群的信息", "更新好友信息", event.user_id)
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.rule import to_me
|
||||
|
||||
from utils.message_builder import image
|
||||
from .data_source import create_help_image, SUPERUSER_HELP_IMAGE
|
||||
|
||||
from .data_source import SUPERUSER_HELP_IMAGE, create_help_image
|
||||
|
||||
__zx_plugin_name__ = '超级用户帮助 [Superuser]'
|
||||
__zx_plugin_name__ = "超级用户帮助 [Superuser]"
|
||||
|
||||
|
||||
if SUPERUSER_HELP_IMAGE.exists():
|
||||
@ -20,5 +21,4 @@ super_help = on_command(
|
||||
async def _():
|
||||
if not SUPERUSER_HELP_IMAGE.exists():
|
||||
await create_help_image()
|
||||
x = image(SUPERUSER_HELP_IMAGE)
|
||||
await super_help.finish(x)
|
||||
await super_help.finish(image(SUPERUSER_HELP_IMAGE))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from nonebot import on_command
|
||||
from utils.message_builder import image
|
||||
|
||||
from utils.message_builder import image
|
||||
|
||||
__zx_plugin_name__ = "更新信息"
|
||||
__plugin_usage__ = """
|
||||
@ -26,8 +26,7 @@ update_info = on_command("更新信息", aliases={"更新日志"}, priority=5, b
|
||||
|
||||
@update_info.handle()
|
||||
async def _():
|
||||
img = image("update_info.png")
|
||||
if img:
|
||||
if img := image("update_info.png"):
|
||||
await update_info.finish(image("update_info.png"))
|
||||
else:
|
||||
await update_info.finish("目前没有更新信息哦")
|
||||
|
||||
@ -1,11 +1,18 @@
|
||||
from typing import Optional
|
||||
import platform
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from .utils import ConfigsManager
|
||||
|
||||
import platform
|
||||
if platform.system() == "Linux":
|
||||
import os
|
||||
hostip = os.popen("cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }'").read().replace("\n","")
|
||||
|
||||
hostip = (
|
||||
os.popen("cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }'")
|
||||
.read()
|
||||
.replace("\n", "")
|
||||
)
|
||||
|
||||
|
||||
# 回复消息名称
|
||||
NICKNAME: str = "小真寻"
|
||||
@ -14,7 +21,7 @@ NICKNAME: str = "小真寻"
|
||||
# 如果填写了bind就不需要再填写后面的字段了#)
|
||||
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
|
||||
bind: str = "" # 数据库连接链接
|
||||
sql_name: str = "postgresql"
|
||||
sql_name: str = "postgres"
|
||||
user: str = "" # 数据用户名
|
||||
password: str = "" # 数据库密码
|
||||
address: str = "" # 数据库地址
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import copy
|
||||
from typing import Optional, Any, Union
|
||||
from pathlib import Path
|
||||
from ruamel.yaml import YAML
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from ruamel import yaml
|
||||
from ruamel.yaml import YAML
|
||||
from ruamel.yaml.scanner import ScannerError
|
||||
|
||||
|
||||
@ -50,7 +51,7 @@ class ConfigsManager:
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
help_: Optional[str] = None,
|
||||
default_value: Optional[str] = None,
|
||||
default_value: Optional[Any] = None,
|
||||
_override: bool = False,
|
||||
):
|
||||
"""
|
||||
|
||||
@ -1,24 +1,37 @@
|
||||
from services.db_context import db
|
||||
from typing import Dict
|
||||
from typing import Optional, List
|
||||
from services.log import logger
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
from .goods_info import GoodsInfo
|
||||
|
||||
|
||||
class BagUser(db.Model):
|
||||
__tablename__ = "bag_users"
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
gold = db.Column(db.Integer(), default=100)
|
||||
props = db.Column(db.TEXT(), nullable=False, default="") # 旧道具字段(废弃)
|
||||
spend_total_gold = db.Column(db.Integer(), default=0)
|
||||
get_total_gold = db.Column(db.Integer(), default=0)
|
||||
get_today_gold = db.Column(db.Integer(), default=0)
|
||||
spend_today_gold = db.Column(db.Integer(), default=0)
|
||||
property = db.Column(db.JSON(), nullable=False, default={}) # 新道具字段
|
||||
class BagUser(Model):
|
||||
|
||||
_idx1 = db.Index("bag_group_users_idx1", "user_qq", "group_id", unique=True)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
gold = fields.IntField(default=100)
|
||||
"""金币数量"""
|
||||
spend_total_gold = fields.IntField(default=0)
|
||||
"""花费金币总数"""
|
||||
get_total_gold = fields.IntField(default=0)
|
||||
"""获取金币总数"""
|
||||
get_today_gold = fields.IntField(default=0)
|
||||
"""今日获取金币"""
|
||||
spend_today_gold = fields.IntField(default=0)
|
||||
"""今日获取金币"""
|
||||
property: Dict[str, int] = fields.JSONField(default={})
|
||||
"""道具"""
|
||||
|
||||
class Meta:
|
||||
table = "bag_users"
|
||||
table_description = "用户道具数据表"
|
||||
unique_together = ("user_qq", "group_id")
|
||||
|
||||
@classmethod
|
||||
async def get_user_total_gold(cls, user_qq: int, group_id: int) -> str:
|
||||
@ -29,13 +42,7 @@ class BagUser(db.Model):
|
||||
:param user_qq: qq号
|
||||
:param group_id: 所在群号
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
user = await query.gino.first()
|
||||
if not user:
|
||||
user = await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
)
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
return (
|
||||
f"当前金币:{user.gold}\n今日获取金币:{user.get_today_gold}\n今日花费金币:{user.spend_today_gold}"
|
||||
f"\n今日收益:{user.get_today_gold - user.spend_today_gold}"
|
||||
@ -51,19 +58,13 @@ class BagUser(db.Model):
|
||||
:param user_qq: qq号
|
||||
:param group_id: 所在群号
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
return user.gold
|
||||
else:
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
)
|
||||
return 100
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
return user.gold
|
||||
|
||||
@classmethod
|
||||
async def get_property(cls, user_qq: int, group_id: int, only_active: bool = False) -> Dict[str, int]:
|
||||
async def get_property(
|
||||
cls, user_qq: int, group_id: int, only_active: bool = False
|
||||
) -> Dict[str, int]:
|
||||
"""
|
||||
说明:
|
||||
获取当前道具
|
||||
@ -72,22 +73,18 @@ class BagUser(db.Model):
|
||||
:param group_id: 所在群号
|
||||
:param only_active: 仅仅获取主动使用的道具
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
if only_active and user.property:
|
||||
data = {}
|
||||
name_list = [x.goods_name for x in await GoodsInfo.get_all_goods() if not x.is_passive]
|
||||
for key in [x for x in user.property.keys() if x in name_list]:
|
||||
data[key] = user.property[key]
|
||||
return data
|
||||
return user.property
|
||||
else:
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
)
|
||||
return {}
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
if only_active and user.property:
|
||||
data = {}
|
||||
name_list = [
|
||||
x.goods_name
|
||||
for x in await GoodsInfo.get_all_goods()
|
||||
if not x.is_passive
|
||||
]
|
||||
for key in [x for x in user.property if x in name_list]:
|
||||
data[key] = user.property[key]
|
||||
return data
|
||||
return user.property
|
||||
|
||||
@classmethod
|
||||
async def add_gold(cls, user_qq: int, group_id: int, num: int):
|
||||
@ -99,23 +96,11 @@ class BagUser(db.Model):
|
||||
:param group_id: 所在群号
|
||||
:param num: 金币数量
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(
|
||||
gold=user.gold + num,
|
||||
get_total_gold=user.get_total_gold + num,
|
||||
get_today_gold=user.get_today_gold + num,
|
||||
).apply()
|
||||
else:
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
gold=100 + num,
|
||||
get_total_gold=num,
|
||||
get_today_gold=num,
|
||||
)
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
user.gold = user.gold + num
|
||||
user.get_total_gold = user.get_total_gold + num
|
||||
user.get_today_gold = user.get_today_gold + num
|
||||
await user.save(update_fields=["gold", "get_today_gold", "get_total_gold"])
|
||||
|
||||
@classmethod
|
||||
async def spend_gold(cls, user_qq: int, group_id: int, num: int):
|
||||
@ -127,26 +112,14 @@ class BagUser(db.Model):
|
||||
:param group_id: 所在群号
|
||||
:param num: 金币数量
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(
|
||||
gold=user.gold - num,
|
||||
spend_total_gold=user.spend_total_gold + num,
|
||||
spend_today_gold=user.spend_today_gold + num,
|
||||
).apply()
|
||||
else:
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
gold=100 - num,
|
||||
spend_total_gold=num,
|
||||
spend_today_gold=num,
|
||||
)
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
user.gold = user.gold - num
|
||||
user.spend_total_gold = user.spend_total_gold + num
|
||||
user.spend_today_gold = user.spend_today_gold + num
|
||||
await user.save(update_fields=["gold", "spend_total_gold", "spend_today_gold"])
|
||||
|
||||
@classmethod
|
||||
async def add_property(cls, user_qq: int, group_id: int, name: str):
|
||||
async def add_property(cls, user_qq: int, group_id: int, name: str, num: int = 1):
|
||||
"""
|
||||
说明:
|
||||
增加道具
|
||||
@ -154,19 +127,15 @@ class BagUser(db.Model):
|
||||
:param user_qq: qq号
|
||||
:param group_id: 所在群号
|
||||
:param name: 道具名称
|
||||
:param num: 道具数量
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
p = user.property
|
||||
if p.get(name) is None:
|
||||
p[name] = 1
|
||||
else:
|
||||
p[name] += 1
|
||||
await user.update(property=p).apply()
|
||||
else:
|
||||
await cls.create(user_qq=user_qq, group_id=group_id, property={name: 1})
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
property_ = user.property
|
||||
if property_.get(name) is None:
|
||||
property_[name] = 0
|
||||
property_[name] += num
|
||||
user.property = property_
|
||||
await user.save(update_fields=["property"])
|
||||
|
||||
@classmethod
|
||||
async def delete_property(
|
||||
@ -181,54 +150,15 @@ class BagUser(db.Model):
|
||||
:param name: 道具名称
|
||||
:param num: 使用个数
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
property_ = user.property
|
||||
if name in property_:
|
||||
if property_.get(name) == num:
|
||||
del property_[name]
|
||||
else:
|
||||
property_[name] -= num
|
||||
await user.update(property=property_).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def buy_property(
|
||||
cls, user_qq: int, group_id: int, goods: "GoodsInfo", goods_num: int
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
购买道具
|
||||
参数:
|
||||
:param user_qq: 用户qq
|
||||
:param group_id: 所在群聊
|
||||
:param goods: 商品
|
||||
:param goods_num: 商品数量
|
||||
"""
|
||||
try:
|
||||
# 折扣后金币
|
||||
spend_gold = goods.goods_discount * goods.goods_price * goods_num
|
||||
await BagUser.spend_gold(user_qq, group_id, spend_gold)
|
||||
for _ in range(goods_num):
|
||||
await BagUser.add_property(user_qq, group_id, goods.goods_name)
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
property_ = user.property
|
||||
if name in property_:
|
||||
if (n := property_.get(name, 0)) < num:
|
||||
return False
|
||||
if n == num:
|
||||
del property_[name]
|
||||
else:
|
||||
property_[name] -= num
|
||||
await user.save(update_fields=["property"])
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"buy_property 发生错误 {type(e)}:{e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_all_users(cls, group_id: Optional[int] = None) -> List["BagUser"]:
|
||||
"""
|
||||
说明:
|
||||
获取所有用户数据
|
||||
参数:
|
||||
:param group_id: 群号
|
||||
"""
|
||||
if not group_id:
|
||||
query = await cls.query.gino.all()
|
||||
else:
|
||||
query = await cls.query.where((cls.group_id == group_id)).gino.all()
|
||||
return query
|
||||
|
||||
@ -1,16 +1,26 @@
|
||||
from services.db_context import db
|
||||
import time
|
||||
from typing import Union
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
from services.log import logger
|
||||
|
||||
|
||||
class BanUser(db.Model):
|
||||
__tablename__ = "ban_users"
|
||||
class BanUser(Model):
|
||||
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False, primary_key=True)
|
||||
ban_level = db.Column(db.Integer(), nullable=False)
|
||||
ban_time = db.Column(db.BigInteger())
|
||||
duration = db.Column(db.BigInteger())
|
||||
user_qq = fields.IntField(pk=True)
|
||||
"""用户id"""
|
||||
ban_level = fields.IntField()
|
||||
"""使用ban命令的用户等级"""
|
||||
ban_time = fields.BigIntField()
|
||||
"""ban开始的时间"""
|
||||
duration = fields.BigIntField()
|
||||
"""ban时长"""
|
||||
|
||||
_idx1 = db.Index("ban_group_users_idx1", "user_qq", unique=True)
|
||||
class Meta:
|
||||
table = "ban_users"
|
||||
table_description = ".ban/b了 封禁人员数据表"
|
||||
|
||||
@classmethod
|
||||
async def check_ban_level(cls, user_qq: int, level: int) -> bool:
|
||||
@ -21,30 +31,34 @@ class BanUser(db.Model):
|
||||
:param user_qq: unban用户的qq号
|
||||
:param level: ban掉目标用户的权限等级
|
||||
"""
|
||||
user = await cls.query.where((cls.user_qq == user_qq)).gino.first()
|
||||
if not user:
|
||||
return False
|
||||
if user.ban_level > level:
|
||||
return True
|
||||
user = await cls.filter(user_qq=user_qq).first()
|
||||
if user:
|
||||
logger.debug(
|
||||
f"检测用户被ban等级,user_level: {user.ban_level},level: {level}",
|
||||
target=user_qq,
|
||||
)
|
||||
return bool(user and user.ban_level > level)
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def check_ban_time(cls, user_qq: int) -> str:
|
||||
async def check_ban_time(cls, user_qq: int) -> Union[str, int]:
|
||||
"""
|
||||
说明:
|
||||
检测用户被ban时长
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq))
|
||||
user = await query.gino.first()
|
||||
if not user:
|
||||
return ""
|
||||
if time.time() - (user.ban_time + user.duration) > 0 and user.duration != -1:
|
||||
return ""
|
||||
if user.duration == -1:
|
||||
return "∞"
|
||||
return time.time() - user.ban_time - user.duration
|
||||
logger.debug(f"获取用户ban时长", target=user_qq)
|
||||
if user := await cls.filter(user_qq=user_qq).first():
|
||||
if (
|
||||
time.time() - (user.ban_time + user.duration) > 0
|
||||
and user.duration != -1
|
||||
):
|
||||
return ""
|
||||
if user.duration == -1:
|
||||
return "∞"
|
||||
return int(time.time() - user.ban_time - user.duration)
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
async def is_ban(cls, user_qq: int) -> bool:
|
||||
@ -54,28 +68,29 @@ class BanUser(db.Model):
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
"""
|
||||
logger.debug(f"检测是否被ban", target=user_qq)
|
||||
if await cls.check_ban_time(user_qq):
|
||||
return True
|
||||
else:
|
||||
await cls.unban(user_qq)
|
||||
return False
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def is_super_ban(cls, user_qq: int) -> bool:
|
||||
"""
|
||||
说明:
|
||||
判断用户是否被ban
|
||||
判断用户是否被超级用户ban / b了
|
||||
参数:
|
||||
: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
|
||||
logger.debug(f"检测是否被超级用户权限封禁", target=user_qq)
|
||||
if user := await cls.filter(user_qq=user_qq).first():
|
||||
if user.ban_level == 10:
|
||||
return True
|
||||
return False
|
||||
|
||||
@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):
|
||||
"""
|
||||
说明:
|
||||
ban掉目标用户
|
||||
@ -84,22 +99,15 @@ class BanUser(db.Model):
|
||||
:param ban_level: 使用ban命令用户的权限
|
||||
:param duration: ban时长,秒
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
if not await cls.check_ban_time(user_qq):
|
||||
logger.debug(f"封禁用户,等级:{ban_level},时长: {duration}", target=user_qq)
|
||||
if await cls.filter(user_qq=user_qq).first():
|
||||
await cls.unban(user_qq)
|
||||
user = None
|
||||
if user is None:
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
ban_level=ban_level,
|
||||
ban_time=time.time(),
|
||||
duration=duration,
|
||||
)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
ban_level=ban_level,
|
||||
ban_time=time.time(),
|
||||
duration=duration,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def unban(cls, user_qq: int) -> bool:
|
||||
@ -109,11 +117,8 @@ class BanUser(db.Model):
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user is None:
|
||||
return False
|
||||
else:
|
||||
await cls.delete.where((cls.user_qq == user_qq)).gino.status()
|
||||
logger.debug("解除封禁", target=user_qq)
|
||||
if user := await cls.filter(user_qq=user_qq).first():
|
||||
await user.delete()
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -1,81 +1,30 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Literal, Optional, Tuple, Union
|
||||
from typing import Any, List, Literal, Optional, Tuple, Union
|
||||
|
||||
from services.db_context import db
|
||||
from tortoise import fields
|
||||
from tortoise.functions import Count
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class ChatHistory(db.Model):
|
||||
__tablename__ = "chat_history"
|
||||
class ChatHistory(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger())
|
||||
text = db.Column(db.Text())
|
||||
plain_text = db.Column(db.Text())
|
||||
create_time = db.Column(db.DateTime(timezone=True), nullable=False)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
text = fields.TextField()
|
||||
"""文本内容"""
|
||||
plain_text = fields.TextField()
|
||||
"""纯文本"""
|
||||
create_time = fields.DatetimeField(auto_now_add=True)
|
||||
"""创建时间"""
|
||||
|
||||
@classmethod
|
||||
async def add_chat_msg(cls, user_qq: int, group_id: Optional[int], text: str, plain_text: str):
|
||||
await cls.create(
|
||||
user_qq=user_qq, group_id=group_id, text=text, plain_text=plain_text, create_time=datetime.now()
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get_user_msg(
|
||||
cls,
|
||||
uid: int,
|
||||
msg_type: Optional[Literal["private", "group"]],
|
||||
days: Optional[int] = None,
|
||||
) -> List["ChatHistory"]:
|
||||
"""
|
||||
说明:
|
||||
获取用户消息
|
||||
参数:
|
||||
:param uid: 用户qq
|
||||
:param msg_type: 消息类型,私聊或群聊
|
||||
:param days: 限制日期
|
||||
"""
|
||||
return await cls._get_msg(uid, None, "user", msg_type, days).gino.all()
|
||||
|
||||
@classmethod
|
||||
async def get_group_user_msg(
|
||||
cls,
|
||||
uid: int,
|
||||
gid: int,
|
||||
limit: int = 10,
|
||||
date_scope: Tuple[datetime, datetime] = None,
|
||||
) -> List["ChatHistory"]:
|
||||
"""
|
||||
说明:
|
||||
获取群聊指定用户聊天记录
|
||||
参数:
|
||||
:param uid: qq
|
||||
:param gid: 群号
|
||||
:param limit: 获取数量
|
||||
:param date_scope: 日期范围,默认None为全搜索
|
||||
"""
|
||||
return (
|
||||
await cls._get_msg(uid, gid, "group", days=date_scope)
|
||||
.limit(limit)
|
||||
.gino.all()
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get_group_user_msg_count(cls, uid: int, gid: int) -> Optional[int]:
|
||||
"""
|
||||
说明:
|
||||
查询群聊指定用户的聊天记录数量
|
||||
参数:
|
||||
:param uid: qq
|
||||
:param gid: 群号
|
||||
"""
|
||||
if x := await db.first(
|
||||
db.text(
|
||||
f"SELECT COUNT(id) as sum FROM public.chat_history WHERE user_qq = {uid} AND group_id = {gid}"
|
||||
)
|
||||
):
|
||||
return x[0]
|
||||
return None
|
||||
class Meta:
|
||||
table = "chat_history"
|
||||
table_description = "聊天记录数据表"
|
||||
|
||||
@classmethod
|
||||
async def get_group_msg_rank(
|
||||
@ -84,7 +33,7 @@ class ChatHistory(db.Model):
|
||||
limit: int = 10,
|
||||
order: str = "DESC",
|
||||
date_scope: Optional[Tuple[datetime, datetime]] = None,
|
||||
) -> Optional[Tuple[int, int]]:
|
||||
) -> List["ChatHistory"]:
|
||||
"""
|
||||
说明:
|
||||
获取排行数据
|
||||
@ -94,89 +43,39 @@ class ChatHistory(db.Model):
|
||||
:param order: 排序类型,desc,des
|
||||
:param date_scope: 日期范围
|
||||
"""
|
||||
sql = f"SELECT user_qq, COUNT(id) as sum FROM public.chat_history WHERE group_id = {gid} "
|
||||
if date_scope:
|
||||
sql += f"AND create_time BETWEEN '{date_scope[0]}' AND '{date_scope[1]}' "
|
||||
sql += f"GROUP BY user_qq ORDER BY sum {order if order and order.upper() != 'DES' else ''} LIMIT {limit}"
|
||||
return await db.all(db.text(sql))
|
||||
return list(
|
||||
await cls.filter(group_id=gid, create_time__range=date_scope)
|
||||
.annotate(count=Count("user_qq"))
|
||||
.order_by(order)
|
||||
.group_by("user_qq")
|
||||
.limit(limit)
|
||||
.values_list("user_qq", "count")
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get_group_first_msg_datetime(cls, gid: int) -> Optional[datetime]:
|
||||
async def get_group_first_msg_datetime(cls, group_id: int) -> Optional[datetime]:
|
||||
"""
|
||||
说明:
|
||||
获取群第一条记录消息时间
|
||||
参数:
|
||||
:param gid:
|
||||
:param group_id: 群聊id
|
||||
"""
|
||||
if (
|
||||
msg := await cls.query.where(cls.group_id == gid)
|
||||
.order_by(cls.create_time)
|
||||
.gino.first()
|
||||
message := await cls.filter(group_id=group_id)
|
||||
.order_by("create_time")
|
||||
.first()
|
||||
):
|
||||
return msg.create_time
|
||||
return None
|
||||
return message.create_time
|
||||
|
||||
@classmethod
|
||||
async def get_user_msg_count(
|
||||
cls,
|
||||
uid: int,
|
||||
msg_type: Optional[Literal["private", "group"]],
|
||||
days: Optional[int] = None,
|
||||
) -> int:
|
||||
"""
|
||||
说明:
|
||||
获取用户消息数量
|
||||
参数:
|
||||
:param uid: 用户qq
|
||||
:param msg_type: 消息类型,私聊或群聊
|
||||
:param days: 限制日期
|
||||
"""
|
||||
return (
|
||||
await cls._get_msg(uid, None, "user", msg_type, days, True).gino.first()
|
||||
)[0]
|
||||
|
||||
@classmethod
|
||||
async def get_group_msg(
|
||||
cls,
|
||||
gid: int,
|
||||
days: Optional[int] = None,
|
||||
) -> List["ChatHistory"]:
|
||||
"""
|
||||
说明:
|
||||
获取群聊消息
|
||||
参数:
|
||||
:param gid: 用户qq
|
||||
:param days: 限制日期
|
||||
"""
|
||||
return await cls._get_msg(None, gid, "group", None, days).gino.all()
|
||||
|
||||
@classmethod
|
||||
async def get_group_msg_count(
|
||||
cls,
|
||||
gid: int,
|
||||
days: Optional[int] = None,
|
||||
) -> List["ChatHistory"]:
|
||||
"""
|
||||
说明:
|
||||
获取群聊消息数量
|
||||
参数:
|
||||
:param gid: 用户qq
|
||||
:param days: 限制日期
|
||||
"""
|
||||
return (await cls._get_msg(None, gid, "group", None, days, True).gino.first())[
|
||||
0
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _get_msg(
|
||||
async def get_message(
|
||||
cls,
|
||||
uid: Optional[int],
|
||||
gid: Optional[int],
|
||||
type_: Literal["user", "group"],
|
||||
msg_type: Optional[Literal["private", "group"]] = None,
|
||||
days: Optional[Union[int, Tuple[datetime, datetime]]] = None,
|
||||
is_select_count: bool = False,
|
||||
):
|
||||
) -> List["ChatHistory"]:
|
||||
"""
|
||||
说明:
|
||||
获取消息查询query
|
||||
@ -187,28 +86,21 @@ class ChatHistory(db.Model):
|
||||
:param msg_type: 消息类型,用户或群聊
|
||||
:param days: 限制日期
|
||||
"""
|
||||
if is_select_count:
|
||||
setattr(ChatHistory, "count", db.func.count(cls.id).label("count"))
|
||||
query = cls.select("count")
|
||||
else:
|
||||
query = cls.query
|
||||
if type_ == "user":
|
||||
query = query.where(cls.user_qq == uid)
|
||||
query = cls.filter(user_qq=uid)
|
||||
if msg_type == "private":
|
||||
query = query.where(cls.group_id == None)
|
||||
query = query.filter(group_id__isnull=True)
|
||||
elif msg_type == "group":
|
||||
query = query.where(cls.group_id != None)
|
||||
query = query.filter(group_id__not_isnull=True)
|
||||
else:
|
||||
query = query.where(cls.group_id == gid)
|
||||
query = cls.filter(group_id=gid)
|
||||
if uid:
|
||||
query = query.where(cls.user_qq == uid)
|
||||
query = query.filter(user_qq=uid)
|
||||
if days:
|
||||
if isinstance(days, int):
|
||||
query = query.where(
|
||||
cls.create_time >= datetime.now() - timedelta(days=days)
|
||||
query = query.filter(
|
||||
create_time__gte=datetime.now() - timedelta(days=days)
|
||||
)
|
||||
elif isinstance(days, tuple):
|
||||
query = query.where(cls.create_time >= days[0]).where(
|
||||
cls.create_time <= days[1]
|
||||
)
|
||||
return query
|
||||
query = query.filter(create_at__range=days)
|
||||
return await query.all()
|
||||
|
||||
@ -1,16 +1,23 @@
|
||||
from services.db_context import db
|
||||
from tortoise import fields
|
||||
|
||||
from configs.config import Config
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class FriendUser(db.Model):
|
||||
__tablename__ = "friend_users"
|
||||
class FriendUser(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_id = db.Column(db.BigInteger(), nullable=False)
|
||||
user_name = db.Column(db.Unicode(), nullable=False, default="")
|
||||
nickname = db.Column(db.Unicode())
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_id = fields.BigIntField(unique=True)
|
||||
"""用户id"""
|
||||
user_name = fields.CharField(max_length=255, default="")
|
||||
"""用户名称"""
|
||||
nickname = fields.CharField(max_length=255, null=True)
|
||||
"""私聊下自定义昵称"""
|
||||
|
||||
_idx1 = db.Index("friend_users_idx1", "user_id", unique=True)
|
||||
class Meta:
|
||||
table = "friend_users"
|
||||
table_description = "好友信息数据表"
|
||||
|
||||
@classmethod
|
||||
async def get_user_name(cls, user_id: int) -> str:
|
||||
@ -20,77 +27,29 @@ class FriendUser(db.Model):
|
||||
参数:
|
||||
:param user_id: qq号
|
||||
"""
|
||||
query = cls.query.where(cls.user_id == user_id)
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
if user := await cls.get_or_none(user_id=user_id):
|
||||
return user.user_name
|
||||
else:
|
||||
return ""
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
async def add_friend_info(cls, user_id: int, user_name: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
添加好友信息
|
||||
参数:
|
||||
:param user_id: qq号
|
||||
:param user_name: 用户名称
|
||||
"""
|
||||
try:
|
||||
query = cls.query.where(cls.user_id == user_id)
|
||||
user = await query.with_for_update().gino.first()
|
||||
if not user:
|
||||
await cls.create(
|
||||
user_id=user_id,
|
||||
user_name=user_name,
|
||||
)
|
||||
else:
|
||||
await user.update(
|
||||
user_name=user_name,
|
||||
).apply()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def delete_friend_info(cls, user_id: int) -> bool:
|
||||
"""
|
||||
说明:
|
||||
删除好友信息
|
||||
参数:
|
||||
:param user_id: qq号
|
||||
"""
|
||||
try:
|
||||
query = cls.query.where(cls.user_id == user_id)
|
||||
user = await query.with_for_update().gino.first()
|
||||
if user:
|
||||
await user.delete()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_friend_nickname(cls, user_id: int) -> str:
|
||||
async def get_user_nickname(cls, user_id: int) -> str:
|
||||
"""
|
||||
说明:
|
||||
获取用户昵称
|
||||
参数:
|
||||
:param user_id: qq号
|
||||
"""
|
||||
query = cls.query.where(cls.user_id == user_id)
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
if user := await cls.get_or_none(user_id=user_id):
|
||||
if user.nickname:
|
||||
_tmp = ""
|
||||
black_word = Config.get_config("nickname", "BLACK_WORD")
|
||||
if black_word:
|
||||
if black_word := Config.get_config("nickname", "BLACK_WORD"):
|
||||
for x in user.nickname:
|
||||
_tmp += "*" if x in black_word else x
|
||||
return _tmp
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
async def set_friend_nickname(cls, user_id: int, nickname: str) -> bool:
|
||||
async def set_user_nickname(cls, user_id: int, nickname: str):
|
||||
"""
|
||||
说明:
|
||||
设置用户昵称
|
||||
@ -98,18 +57,4 @@ class FriendUser(db.Model):
|
||||
:param user_id: qq号
|
||||
:param nickname: 昵称
|
||||
"""
|
||||
try:
|
||||
query = cls.query.where(cls.user_id == user_id)
|
||||
user = await query.with_for_update().gino.first()
|
||||
if not user:
|
||||
await cls.create(
|
||||
user_id=user_id,
|
||||
nickname=nickname,
|
||||
)
|
||||
else:
|
||||
await user.update(
|
||||
nickname=nickname,
|
||||
).apply()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
await cls.update_or_create(user_id=user_id, defaults={"nickname": nickname})
|
||||
|
||||
@ -1,38 +1,50 @@
|
||||
from services.db_context import db
|
||||
from typing import Optional, List, Tuple
|
||||
from services.log import logger
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class GoodsInfo(db.Model):
|
||||
class GoodsInfo(Model):
|
||||
__tablename__ = "goods_info"
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
goods_name = db.Column(db.TEXT(), nullable=False) # 名称
|
||||
goods_price = db.Column(db.Integer(), nullable=False) # 价格
|
||||
goods_description = db.Column(db.TEXT(), nullable=False) # 商品描述
|
||||
goods_discount = db.Column(db.Numeric(scale=3, asdecimal=False), default=1) # 打折
|
||||
goods_limit_time = db.Column(db.BigInteger(), default=0) # 限时
|
||||
daily_limit = db.Column(db.Integer(), nullable=False, default=0) # 每日购买限制
|
||||
daily_purchase_limit = db.Column(
|
||||
db.JSON(), nullable=False, default={}
|
||||
) # 每日购买限制数据存储
|
||||
is_passive = db.Column(db.Boolean(), nullable=False, default=0) # 是否为被动
|
||||
icon = db.Column(db.String(), default=0) # 图标
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
goods_name = fields.CharField(255, unique=True)
|
||||
"""商品名称"""
|
||||
goods_price = fields.IntField()
|
||||
"""价格"""
|
||||
goods_description = fields.TextField()
|
||||
"""描述"""
|
||||
goods_discount = fields.FloatField(default=1)
|
||||
"""折扣"""
|
||||
goods_limit_time = fields.BigIntField(default=0)
|
||||
"""限时"""
|
||||
daily_limit = fields.IntField(default=0)
|
||||
"""每日限购"""
|
||||
daily_purchase_limit: Dict[str, Dict[str, int]] = fields.JSONField(default={})
|
||||
"""用户限购记录"""
|
||||
is_passive = fields.BooleanField(default=False)
|
||||
"""是否为被动道具"""
|
||||
icon = fields.TextField(null=True)
|
||||
"""图标路径"""
|
||||
|
||||
_idx1 = db.Index("goods_group_users_idx1", "goods_name", unique=True)
|
||||
class Meta:
|
||||
table = "goods_info"
|
||||
table_description = "商品数据表"
|
||||
|
||||
@classmethod
|
||||
async def add_goods(
|
||||
cls,
|
||||
goods_name: str,
|
||||
goods_price: int,
|
||||
goods_description: str,
|
||||
goods_discount: float = 1,
|
||||
goods_limit_time: int = 0,
|
||||
daily_limit: int = 0,
|
||||
is_passive: bool = False,
|
||||
icon: Optional[str] = None,
|
||||
) -> bool:
|
||||
cls,
|
||||
goods_name: str,
|
||||
goods_price: int,
|
||||
goods_description: str,
|
||||
goods_discount: float = 1,
|
||||
goods_limit_time: int = 0,
|
||||
daily_limit: int = 0,
|
||||
is_passive: bool = False,
|
||||
icon: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
添加商品
|
||||
@ -46,22 +58,17 @@ class GoodsInfo(db.Model):
|
||||
:param is_passive: 是否为被动道具
|
||||
:param icon: 图标
|
||||
"""
|
||||
try:
|
||||
if not await cls.get_goods_info(goods_name):
|
||||
await cls.create(
|
||||
goods_name=goods_name,
|
||||
goods_price=goods_price,
|
||||
goods_description=goods_description,
|
||||
goods_discount=goods_discount,
|
||||
goods_limit_time=goods_limit_time,
|
||||
daily_limit=daily_limit,
|
||||
is_passive=is_passive,
|
||||
icon=icon
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"GoodsInfo add_goods {goods_name} 发生错误 {type(e)}:{e}")
|
||||
return False
|
||||
if not await cls.filter(goods_name=goods_name).first():
|
||||
await cls.create(
|
||||
goods_name=goods_name,
|
||||
goods_price=goods_price,
|
||||
goods_description=goods_description,
|
||||
goods_discount=goods_discount,
|
||||
goods_limit_time=goods_limit_time,
|
||||
daily_limit=daily_limit,
|
||||
is_passive=is_passive,
|
||||
icon=icon,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def delete_goods(cls, goods_name: str) -> bool:
|
||||
@ -71,28 +78,23 @@ class GoodsInfo(db.Model):
|
||||
参数:
|
||||
:param goods_name: 商品名称
|
||||
"""
|
||||
query = (
|
||||
await cls.query.where(cls.goods_name == goods_name)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
if not query:
|
||||
return False
|
||||
await query.delete()
|
||||
return True
|
||||
if goods := await cls.get_or_none(goods_name=goods_name):
|
||||
await goods.delete()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def update_goods(
|
||||
cls,
|
||||
goods_name: str,
|
||||
goods_price: Optional[int] = None,
|
||||
goods_description: Optional[str] = None,
|
||||
goods_discount: Optional[float] = None,
|
||||
goods_limit_time: Optional[int] = None,
|
||||
daily_limit: Optional[int] = None,
|
||||
is_passive: Optional[bool] = None,
|
||||
icon: Optional[str] = None,
|
||||
) -> bool:
|
||||
cls,
|
||||
goods_name: str,
|
||||
goods_price: Optional[int] = None,
|
||||
goods_description: Optional[str] = None,
|
||||
goods_discount: Optional[float] = None,
|
||||
goods_limit_time: Optional[int] = None,
|
||||
daily_limit: Optional[int] = None,
|
||||
is_passive: Optional[bool] = None,
|
||||
icon: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
更新商品信息
|
||||
@ -106,37 +108,25 @@ class GoodsInfo(db.Model):
|
||||
:param is_passive: 是否为被动
|
||||
:param icon: 图标
|
||||
"""
|
||||
try:
|
||||
query = (
|
||||
await cls.query.where(cls.goods_name == goods_name)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
if goods := await cls.get_or_none(goods_name=goods_name):
|
||||
await cls.update_or_create(
|
||||
goods_name=goods_name,
|
||||
defaults={
|
||||
"goods_price": goods_price or goods.goods_price,
|
||||
"goods_description": goods_description or goods.goods_description,
|
||||
"goods_discount": goods_discount or goods.goods_discount,
|
||||
"goods_limit_time": goods_limit_time
|
||||
if goods_limit_time is not None
|
||||
else goods.goods_limit_time,
|
||||
"daily_limit": daily_limit
|
||||
if daily_limit is not None
|
||||
else goods.daily_limit,
|
||||
"is_passive": is_passive
|
||||
if is_passive is not None
|
||||
else goods.is_passive,
|
||||
"icon": icon or goods.icon,
|
||||
},
|
||||
)
|
||||
if not query:
|
||||
return False
|
||||
await query.update(
|
||||
goods_price=goods_price or query.goods_price,
|
||||
goods_description=goods_description or query.goods_description,
|
||||
goods_discount=goods_discount or query.goods_discount,
|
||||
goods_limit_time=goods_limit_time if goods_limit_time is not None else query.goods_limit_time,
|
||||
daily_limit=daily_limit if daily_limit is not None else query.daily_limit,
|
||||
is_passive=is_passive if is_passive is not None else query.is_passive,
|
||||
icon=icon or query.icon
|
||||
).apply()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"GoodsInfo update_goods 发生错误 {type(e)}:{e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_goods_info(cls, goods_name: str) -> "GoodsInfo":
|
||||
"""
|
||||
说明:
|
||||
获取商品对象
|
||||
参数:
|
||||
:param goods_name: 商品名称
|
||||
"""
|
||||
return await cls.query.where(cls.goods_name == goods_name).gino.first()
|
||||
|
||||
@classmethod
|
||||
async def get_all_goods(cls) -> List["GoodsInfo"]:
|
||||
@ -144,7 +134,7 @@ class GoodsInfo(db.Model):
|
||||
说明:
|
||||
获得全部有序商品对象
|
||||
"""
|
||||
query = await cls.query.gino.all()
|
||||
query = await cls.all()
|
||||
id_lst = [x.id for x in query]
|
||||
goods_lst = []
|
||||
for _ in range(len(query)):
|
||||
@ -155,7 +145,7 @@ class GoodsInfo(db.Model):
|
||||
|
||||
@classmethod
|
||||
async def add_user_daily_purchase(
|
||||
cls, goods: "GoodsInfo", user_id: int, group_id: int, num: int = 1
|
||||
cls, goods: "GoodsInfo", user_id_: int, group_id_: int, num: int = 1
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
@ -166,19 +156,19 @@ class GoodsInfo(db.Model):
|
||||
:param group_id: 群号
|
||||
:param num: 数量
|
||||
"""
|
||||
user_id = str(user_id)
|
||||
group_id = str(group_id)
|
||||
user_id = str(user_id_)
|
||||
group_id = str(group_id_)
|
||||
if goods and goods.daily_limit and goods.daily_limit > 0:
|
||||
if not goods.daily_purchase_limit.get(group_id):
|
||||
goods.daily_purchase_limit[group_id] = {}
|
||||
if not goods.daily_purchase_limit[group_id].get(user_id):
|
||||
goods.daily_purchase_limit[group_id][user_id] = 0
|
||||
goods.daily_purchase_limit[group_id][user_id] += num
|
||||
await goods.update(daily_purchase_limit=goods.daily_purchase_limit).apply()
|
||||
await goods.save(update_fields=["daily_purchase_limit"])
|
||||
|
||||
@classmethod
|
||||
async def check_user_daily_purchase(
|
||||
cls, goods: "GoodsInfo", user_id: int, group_id: int, num: int = 1
|
||||
cls, goods: "GoodsInfo", user_id_: int, group_id_: int, num: int = 1
|
||||
) -> Tuple[bool, int]:
|
||||
"""
|
||||
说明:
|
||||
@ -189,8 +179,8 @@ class GoodsInfo(db.Model):
|
||||
:param group_id: 群号
|
||||
:param num: 数量
|
||||
"""
|
||||
user_id = str(user_id)
|
||||
group_id = str(group_id)
|
||||
user_id = str(user_id_)
|
||||
group_id = str(group_id_)
|
||||
if goods and goods.daily_limit > 0:
|
||||
if (
|
||||
not goods.daily_limit
|
||||
@ -204,10 +194,3 @@ class GoodsInfo(db.Model):
|
||||
goods.daily_limit - goods.daily_purchase_limit[group_id][user_id],
|
||||
)
|
||||
return False, 0
|
||||
|
||||
@classmethod
|
||||
async def reset_daily_purchase(cls):
|
||||
"""
|
||||
重置每次次数限制
|
||||
"""
|
||||
await cls.update.values(daily_purchase_limit={}).gino.status()
|
||||
|
||||
@ -1,111 +1,24 @@
|
||||
from services.db_context import db
|
||||
from services.log import logger
|
||||
from typing import List, Optional
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
class GroupInfo(db.Model):
|
||||
__tablename__ = "group_info"
|
||||
from services.db_context import Model
|
||||
from services.log import logger
|
||||
|
||||
group_id = db.Column(db.BigInteger(), nullable=False, primary_key=True)
|
||||
group_name = db.Column(db.Unicode(), nullable=False, default="")
|
||||
max_member_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
member_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
group_flag = db.Column(db.Integer(), nullable=False, default=0)
|
||||
|
||||
_idx1 = db.Index("group_info_idx1", "group_id", unique=True)
|
||||
class GroupInfo(Model):
|
||||
|
||||
@classmethod
|
||||
async def get_group_info(cls, group_id: int) -> "GroupInfo":
|
||||
"""
|
||||
说明:
|
||||
获取群信息
|
||||
参数:
|
||||
:param group_id: 群号
|
||||
"""
|
||||
query = cls.query.where(cls.group_id == group_id)
|
||||
return await query.gino.first()
|
||||
group_id = fields.BigIntField(pk=True)
|
||||
"""群聊id"""
|
||||
group_name = fields.TextField(default="")
|
||||
"""群聊名称"""
|
||||
max_member_count = fields.IntField(default=0)
|
||||
"""最大人数"""
|
||||
member_count = fields.IntField(default=0)
|
||||
"""当前人数"""
|
||||
group_flag: int = fields.IntField(default=0)
|
||||
"""群认证标记"""
|
||||
|
||||
@classmethod
|
||||
async def add_group_info(
|
||||
cls,
|
||||
group_id: int,
|
||||
group_name: str,
|
||||
max_member_count: int,
|
||||
member_count: int,
|
||||
group_flag: Optional[int] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
添加群信息
|
||||
参数:
|
||||
:param group_id: 群号
|
||||
:param group_name: 群名称
|
||||
:param max_member_count: 群员最大数量
|
||||
:param member_count: 群员数量
|
||||
:param group_flag: 群认证,0为未认证,1为认证
|
||||
"""
|
||||
try:
|
||||
group = (
|
||||
await cls.query.where(cls.group_id == group_id)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
if group:
|
||||
await group.update(
|
||||
group_name=group_name,
|
||||
max_member_count=max_member_count,
|
||||
member_count=member_count,
|
||||
).apply()
|
||||
if group_flag is not None:
|
||||
await group.update(group_flag=group_flag).apply()
|
||||
else:
|
||||
await cls.create(
|
||||
group_id=group_id,
|
||||
group_name=group_name,
|
||||
max_member_count=max_member_count,
|
||||
member_count=member_count,
|
||||
group_flag=group_flag,
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.info(f"GroupInfo 调用 add_group_info 发生错误 {type(e)}:{e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def delete_group_info(cls, group_id: int):
|
||||
"""
|
||||
说明:
|
||||
删除群信息
|
||||
参数:
|
||||
:param group_id: 群号
|
||||
"""
|
||||
await cls.delete.where(cls.group_id == group_id).gino.status()
|
||||
|
||||
@classmethod
|
||||
async def get_all_group(cls) -> List["GroupInfo"]:
|
||||
"""
|
||||
说明:
|
||||
获取所有群对象
|
||||
"""
|
||||
query = await cls.query.gino.all()
|
||||
return query
|
||||
|
||||
@classmethod
|
||||
async def set_group_flag(cls, group_id: int, group_flag: int) -> bool:
|
||||
"""
|
||||
设置群认证
|
||||
:param group_id: 群号
|
||||
:param group_flag: 群认证,0为未认证,1为认证
|
||||
"""
|
||||
group = (
|
||||
await cls.query.where(cls.group_id == group_id)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
if group:
|
||||
if group.group_flag != group_flag:
|
||||
await group.update(
|
||||
group_flag=group_flag,
|
||||
).apply()
|
||||
return True
|
||||
return False
|
||||
class Meta:
|
||||
table = "group_info"
|
||||
table_description = "群聊信息表"
|
||||
|
||||
@ -1,116 +1,48 @@
|
||||
from datetime import datetime
|
||||
from typing import List, Optional, Set
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from configs.config import Config
|
||||
from services.db_context import db
|
||||
from typing import List, Optional
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class GroupInfoUser(db.Model):
|
||||
__tablename__ = "group_info_users"
|
||||
class GroupInfoUser(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
user_name = db.Column(db.Unicode(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
user_join_time = db.Column(db.DateTime(), nullable=False)
|
||||
nickname = db.Column(db.Unicode())
|
||||
uid = db.Column(db.BigInteger())
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
user_name = fields.CharField(255, default="")
|
||||
"""用户昵称"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
user_join_time = fields.DatetimeField(null=True)
|
||||
"""用户入群时间"""
|
||||
nickname = fields.CharField(255, null=True)
|
||||
"""群聊昵称"""
|
||||
uid = fields.BigIntField(null=True)
|
||||
"""用户uid"""
|
||||
|
||||
_idx1 = db.Index("info_group_users_idx1", "user_qq", "group_id", unique=True)
|
||||
class Meta:
|
||||
table = "group_info_users"
|
||||
table_description = "群员信息数据表"
|
||||
unique_together = ("user_qq", "group_id")
|
||||
|
||||
@classmethod
|
||||
async def add_member_info(
|
||||
cls,
|
||||
user_qq: int,
|
||||
group_id: int,
|
||||
user_name: str,
|
||||
user_join_time: datetime,
|
||||
uid: Optional[int] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
添加群内用户信息
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
:param user_name: 用户名称
|
||||
:param user_join_time: 入群时间
|
||||
:param uid: 用户唯一 id(自动生成)
|
||||
"""
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
try:
|
||||
if not await query.gino.first():
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
user_name=user_name,
|
||||
group_id=group_id,
|
||||
user_join_time=user_join_time,
|
||||
uid=uid
|
||||
)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_member_info(
|
||||
cls, user_qq: int, group_id: int
|
||||
) -> "GroupInfoUser":
|
||||
"""
|
||||
说明:
|
||||
查询群员信息
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
"""
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
return await query.gino.first()
|
||||
|
||||
@classmethod
|
||||
async def delete_member_info(cls, user_qq: int, group_id: int) -> bool:
|
||||
"""
|
||||
说明:
|
||||
删除群员信息
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
"""
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
try:
|
||||
if user is None:
|
||||
return True
|
||||
else:
|
||||
await cls.delete.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
).gino.status()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_group_member_id_list(cls, group_id: int) -> List[int]:
|
||||
async def get_group_member_id_list(cls, group_id: int) -> Set[int]:
|
||||
"""
|
||||
说明:
|
||||
获取该群所有用户qq
|
||||
参数:
|
||||
:param group_id: 群号
|
||||
"""
|
||||
member_list = []
|
||||
query = cls.query.where((cls.group_id == group_id))
|
||||
for user in await query.gino.all():
|
||||
member_list.append(user.user_qq)
|
||||
return member_list
|
||||
return set(
|
||||
await cls.filter(group_id=group_id).values_list("user_qq", flat=True)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def set_group_member_nickname(
|
||||
cls, user_qq: int, group_id: int, nickname: str
|
||||
) -> bool:
|
||||
async def set_user_nickname(cls, user_qq: int, group_id: int, nickname: str):
|
||||
"""
|
||||
说明:
|
||||
设置群员在该群内的昵称
|
||||
@ -119,14 +51,11 @@ class GroupInfoUser(db.Model):
|
||||
:param group_id: 群号
|
||||
:param nickname: 昵称
|
||||
"""
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
await cls.update_or_create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
defaults={"nickname": nickname},
|
||||
)
|
||||
user = await query.with_for_update().gino.first()
|
||||
if user:
|
||||
await user.update(nickname=nickname).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_user_all_group(cls, user_qq: int) -> List[int]:
|
||||
@ -136,13 +65,12 @@ class GroupInfoUser(db.Model):
|
||||
参数:
|
||||
:param user_qq: 用户qq
|
||||
"""
|
||||
query = await cls.query.where(cls.user_qq == user_qq).gino.all()
|
||||
if query:
|
||||
query = [x.group_id for x in query]
|
||||
return query
|
||||
return list(
|
||||
await cls.filter(user_qq=user_qq).values_list("group_id", flat=True)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get_group_member_nickname(cls, user_qq: int, group_id: int) -> str:
|
||||
async def get_user_nickname(cls, user_qq: int, group_id: int) -> str:
|
||||
"""
|
||||
说明:
|
||||
获取用户在该群的昵称
|
||||
@ -150,46 +78,34 @@ class GroupInfoUser(db.Model):
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
"""
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
|
||||
if user.nickname:
|
||||
_tmp = ""
|
||||
black_word = Config.get_config("nickname", "BLACK_WORD")
|
||||
if black_word:
|
||||
nickname = ""
|
||||
if black_word := Config.get_config("nickname", "BLACK_WORD"):
|
||||
for x in user.nickname:
|
||||
_tmp += "*" if x in black_word else x
|
||||
return _tmp
|
||||
nickname += "*" if x in black_word else x
|
||||
return nickname
|
||||
return user.nickname
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
async def get_group_member_uid(cls, user_qq: int, group_id: int) -> Optional[str]:
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
user = await query.gino.first()
|
||||
_max_uid = cls.query.where((cls.user_qq == 114514) & (cls.group_id == 114514)).with_for_update()
|
||||
_max_uid_user = await _max_uid.gino.first()
|
||||
async def get_group_member_uid(cls, user_qq: int, group_id: int) -> Optional[int]:
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
_max_uid_user, _ = await cls.get_or_create(user_qq=114514, group_id=114514)
|
||||
_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()
|
||||
if not user.uid:
|
||||
all_user = await cls.filter(user_qq=user_qq).all()
|
||||
for x in all_user:
|
||||
if x.uid:
|
||||
return x.uid
|
||||
else:
|
||||
if not user:
|
||||
await GroupInfoUser.add_member_info(user_qq, group_id, '', datetime.min)
|
||||
user = await cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
).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
|
||||
user.uid = _max_uid + 1
|
||||
_max_uid_user.uid = _max_uid + 1
|
||||
await cls.bulk_update([user, _max_uid_user], ["uid"])
|
||||
return user.uid
|
||||
|
||||
@classmethod
|
||||
async def _run_script(cls):
|
||||
await cls.raw(
|
||||
"alter table group_info_users alter user_join_time drop not null;"
|
||||
)
|
||||
"""允许 user_join_time 为空"""
|
||||
|
||||
@ -1,18 +1,25 @@
|
||||
from asyncpg import UniqueViolationError
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import db
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class LevelUser(db.Model):
|
||||
__tablename__ = "level_users"
|
||||
class LevelUser(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
user_level = db.Column(db.BigInteger(), nullable=False)
|
||||
group_flag = db.Column(db.Integer(), nullable=False, default=0)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
user_level = fields.BigIntField()
|
||||
"""用户权限等级"""
|
||||
group_flag = fields.IntField(default=0)
|
||||
"""特殊标记,是否随群管理员变更而设置权限"""
|
||||
|
||||
_idx1 = db.Index("level_group_users_idx1", "user_qq", "group_id", unique=True)
|
||||
class Meta:
|
||||
table = "level_users"
|
||||
table_description = "用户权限数据库"
|
||||
unique_together = ("user_qq", "group_id")
|
||||
|
||||
@classmethod
|
||||
async def get_user_level(cls, user_qq: int, group_id: int) -> int:
|
||||
@ -23,17 +30,14 @@ class LevelUser(db.Model):
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
|
||||
return user.user_level
|
||||
else:
|
||||
return -1
|
||||
return -1
|
||||
|
||||
@classmethod
|
||||
async def set_level(
|
||||
cls, user_qq: int, group_id: int, level: int, group_flag: int = 0
|
||||
) -> bool:
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
设置用户在群内的权限
|
||||
@ -43,23 +47,11 @@ class LevelUser(db.Model):
|
||||
:param level: 权限等级
|
||||
:param group_flag: 是否被自动更新刷新权限 0:是,1:否
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
try:
|
||||
if not user:
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
user_level=level,
|
||||
group_flag=group_flag,
|
||||
)
|
||||
return True
|
||||
else:
|
||||
await user.update(user_level=level, group_flag=group_flag).apply()
|
||||
return False
|
||||
except UniqueViolationError:
|
||||
return False
|
||||
await cls.update_or_create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
defaults={"user_level": level, "group_flag": group_flag},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def delete_level(cls, user_qq: int, group_id: int) -> bool:
|
||||
@ -70,14 +62,10 @@ class LevelUser(db.Model):
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user is None:
|
||||
return False
|
||||
else:
|
||||
if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
|
||||
await user.delete()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def check_level(cls, user_qq: int, group_id: int, level: int) -> bool:
|
||||
@ -89,25 +77,14 @@ class LevelUser(db.Model):
|
||||
:param group_id: 群号
|
||||
:param level: 权限等级
|
||||
"""
|
||||
if group_id != 0:
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
user = await query.gino.first()
|
||||
if user is None:
|
||||
return False
|
||||
user_level = user.user_level
|
||||
if group_id:
|
||||
if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
|
||||
return user.user_level > level
|
||||
else:
|
||||
query = cls.query.where(cls.user_qq == user_qq)
|
||||
highest_level = 0
|
||||
for user in await query.gino.all():
|
||||
if user.user_level > highest_level:
|
||||
highest_level = user.user_level
|
||||
user_level = highest_level
|
||||
if user_level >= level:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
user_list = await cls.filter(user_qq=user_qq).all()
|
||||
user = max(user_list, key=lambda x: x.user_level)
|
||||
return user.user_level > level
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def is_group_flag(cls, user_qq: int, group_id: int) -> bool:
|
||||
@ -118,12 +95,6 @@ class LevelUser(db.Model):
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
"""
|
||||
user = await cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
).gino.first()
|
||||
if not user:
|
||||
return False
|
||||
if user.group_flag == 1:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
|
||||
return user.group_flag == 1
|
||||
return False
|
||||
|
||||
@ -1,99 +1,78 @@
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
from services.db_context import db
|
||||
from typing import Dict, List, Literal, Optional, Tuple, Union
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class SignGroupUser(db.Model):
|
||||
__tablename__ = "sign_group_users"
|
||||
class SignGroupUser(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
checkin_count = db.Column(db.Integer(), nullable=False)
|
||||
checkin_time_last = db.Column(db.DateTime(timezone=True), nullable=False)
|
||||
impression = db.Column(db.Numeric(scale=3, asdecimal=False), nullable=False)
|
||||
add_probability = db.Column(
|
||||
db.Numeric(scale=3, asdecimal=False), nullable=False, default=0
|
||||
)
|
||||
specify_probability = db.Column(
|
||||
db.Numeric(scale=3, asdecimal=False), nullable=False, default=0
|
||||
)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
checkin_count = fields.IntField(default=0)
|
||||
"""签到次数"""
|
||||
checkin_time_last = fields.DatetimeField(auto_now=True)
|
||||
"""最后签到时间"""
|
||||
impression = fields.DecimalField(10, 3, default=0)
|
||||
"""好感度"""
|
||||
add_probability = fields.DecimalField(10, 3, default=0)
|
||||
"""双倍签到增加概率"""
|
||||
specify_probability = fields.DecimalField(10, 3, default=0)
|
||||
"""使用指定双倍概率"""
|
||||
# specify_probability = fields.DecimalField(10, 3, default=0)
|
||||
|
||||
_idx1 = db.Index("sign_group_users_idx1", "user_qq", "group_id", unique=True)
|
||||
class Meta:
|
||||
table = "sign_group_users"
|
||||
table_description = "群员签到数据表"
|
||||
unique_together = ("user_qq", "group_id")
|
||||
|
||||
@classmethod
|
||||
async def ensure(
|
||||
cls, user_qq: int, group_id: int, for_update: bool = False
|
||||
) -> "SignGroupUser":
|
||||
"""
|
||||
说明:
|
||||
获取签到用户
|
||||
参数:
|
||||
:param user_qq: 用户qq
|
||||
:param group_id: 所在群聊
|
||||
:param for_update: 是否存在修改数据
|
||||
"""
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
if for_update:
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
return user or await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
checkin_count=0,
|
||||
checkin_time_last=datetime.min, # 从未签到过
|
||||
impression=0,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get_user_all_data(cls, user_qq: int) -> List["SignGroupUser"]:
|
||||
"""
|
||||
说明:
|
||||
获取某用户所有数据
|
||||
参数:
|
||||
:param user_qq: 用户qq
|
||||
"""
|
||||
query = cls.query.where(cls.user_qq == user_qq)
|
||||
query = query.with_for_update()
|
||||
return await query.gino.all()
|
||||
|
||||
@classmethod
|
||||
async def sign(cls, user: "SignGroupUser", impression: float, checkin_time_last: datetime):
|
||||
async def sign(cls, user: "SignGroupUser", impression: float):
|
||||
"""
|
||||
说明:
|
||||
签到
|
||||
说明:
|
||||
:param user: 用户
|
||||
:param impression: 增加的好感度
|
||||
:param checkin_time_last: 签到时间
|
||||
"""
|
||||
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()
|
||||
user.checkin_count = user.checkin_count + 1
|
||||
user.add_probability = 0
|
||||
user.specify_probability = 0
|
||||
user.impression = float(user.impression) + impression
|
||||
await user.save(
|
||||
update_fields=[
|
||||
"checkin_count",
|
||||
"add_probability",
|
||||
"specify_probability",
|
||||
"impression",
|
||||
]
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get_all_impression(cls, group_id: int) -> "list, list, list":
|
||||
async def get_all_impression(
|
||||
cls, group_id: Optional[int]
|
||||
) -> Tuple[List[int], List[int], List[float]]:
|
||||
"""
|
||||
说明:
|
||||
获取该群所有用户 id 及对应 好感度
|
||||
参数:
|
||||
:param group_id: 群号
|
||||
"""
|
||||
impression_list = []
|
||||
user_qq_list = []
|
||||
user_group = []
|
||||
if group_id:
|
||||
query = cls.query.where(cls.group_id == group_id)
|
||||
query = cls.filter(group_id=group_id)
|
||||
else:
|
||||
query = cls.query
|
||||
for user in await query.gino.all():
|
||||
impression_list.append(user.impression)
|
||||
user_qq_list.append(user.user_qq)
|
||||
user_group.append(user.group_id)
|
||||
return user_qq_list, impression_list, user_group
|
||||
query = cls
|
||||
value_list = await query.all().values_list("user_qq", "group_id", "impression") # type: ignore
|
||||
qq_list = []
|
||||
group_list = []
|
||||
impression_list = []
|
||||
for value in value_list:
|
||||
qq_list.append(value[0])
|
||||
group_list.append(value[1])
|
||||
impression_list.append(float(value[2]))
|
||||
return qq_list, impression_list, group_list
|
||||
|
||||
@ -1,59 +1,29 @@
|
||||
from datetime import datetime
|
||||
|
||||
from services.db_context import db
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class UserShopGoldLog(db.Model):
|
||||
__tablename__ = "user_shop_gold_log"
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
type = db.Column(db.Integer(), nullable=False) # 0: 购买,1: 使用,2: 插件
|
||||
name = db.Column(db.String())
|
||||
spend_gold = db.Column(db.Integer(), nullable=False)
|
||||
num = db.Column(db.Integer(), nullable=False)
|
||||
create_time = db.Column(db.DateTime(timezone=True), nullable=False)
|
||||
class UserShopGoldLog(Model):
|
||||
|
||||
@classmethod
|
||||
async def add_shop_log(
|
||||
cls,
|
||||
user_qq: int,
|
||||
group_id: int,
|
||||
type_: int,
|
||||
name: str,
|
||||
num: int,
|
||||
spend_gold: int = 0,
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
添加商店购买或使用日志
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 所在群号
|
||||
:param type_: 类型
|
||||
:param name: 商品名称
|
||||
:param num: 数量
|
||||
:param spend_gold: 花费金币
|
||||
"""
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
type=type_,
|
||||
name=name,
|
||||
num=num,
|
||||
spend_gold=spend_gold,
|
||||
create_time=datetime.now(),
|
||||
)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
type = fields.IntField()
|
||||
"""金币使用类型 0: 购买, 1: 使用, 2: 插件"""
|
||||
name = fields.CharField(255)
|
||||
"""商品/插件 名称"""
|
||||
spend_gold = fields.IntField(default=0)
|
||||
"""花费金币"""
|
||||
num = fields.IntField()
|
||||
"""数量"""
|
||||
create_time = fields.DatetimeField(auto_now_add=True)
|
||||
"""创建时间"""
|
||||
|
||||
@classmethod
|
||||
async def get_user_log(cls, user_qq: int, group_id: int) -> "UserShopGoldLog":
|
||||
"""
|
||||
说明:
|
||||
获取用户日志
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 所在群号
|
||||
"""
|
||||
return await cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_qq == group_id)
|
||||
).first()
|
||||
class Meta:
|
||||
table = "user_shop_gold_log"
|
||||
table_description = "金币使用日志表"
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
from utils.message_builder import image
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from nonebot import on_command
|
||||
from nonebot.rule import to_me
|
||||
import os
|
||||
import random
|
||||
|
||||
from nonebot import on_command, on_keyword
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from utils.utils import FreqLimiter
|
||||
from configs.config import NICKNAME
|
||||
import random
|
||||
from nonebot import on_keyword
|
||||
import os
|
||||
from nonebot.rule import to_me
|
||||
|
||||
from configs.config import NICKNAME
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.message_builder import image
|
||||
from utils.utils import FreqLimiter
|
||||
|
||||
__zx_plugin_name__ = "基本设置 [Hidden]"
|
||||
__plugin_usage__ = "用法: 无"
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = 'HibiKier'
|
||||
__plugin_author__ = "HibiKier"
|
||||
|
||||
|
||||
_flmt = FreqLimiter(300)
|
||||
@ -29,7 +29,7 @@ async def _(event: GroupMessageEvent):
|
||||
return
|
||||
_flmt.start_cd(event.group_id)
|
||||
await config_play_game.finish(
|
||||
image(random.choice(os.listdir(IMAGE_PATH / "dayouxi")), "dayouxi")
|
||||
image(IMAGE_PATH / random.choice(os.listdir(IMAGE_PATH / "dayouxi")))
|
||||
)
|
||||
|
||||
|
||||
@ -40,14 +40,14 @@ self_introduction = on_command(
|
||||
|
||||
@self_introduction.handle()
|
||||
async def _():
|
||||
if NICKNAME.find('真寻') != -1:
|
||||
if NICKNAME.find("真寻") != -1:
|
||||
result = (
|
||||
"我叫绪山真寻\n"
|
||||
"你们可以叫我真寻,小真寻,哪怕你们叫我小寻子我也能接受!\n"
|
||||
"年龄的话我还是个**岁初中生(至少现在是)\n"
|
||||
"身高保密!!!(也就比美波里(姐姐..(妹妹))矮一点)\n"
|
||||
"我生日是在3月6号, 能记住的话我会很高兴的\n现在是自宅警备系的现役JC\n"
|
||||
"最好的朋友是椛!\n" + image("zhenxun")
|
||||
"最好的朋友是椛!\n" + image("zhenxun.jpg")
|
||||
)
|
||||
await self_introduction.finish(result)
|
||||
|
||||
@ -57,5 +57,4 @@ my_wife = on_keyword({"老婆"}, rule=to_me(), priority=5, block=True)
|
||||
|
||||
@my_wife.handle()
|
||||
async def _():
|
||||
await my_wife.finish(image("laopo.jpg", "other"))
|
||||
|
||||
await my_wife.finish(image(IMAGE_PATH / "other" / "laopo.jpg"))
|
||||
|
||||
@ -1,18 +1,14 @@
|
||||
|
||||
from nonebot import on_message
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
GroupMessageEvent,
|
||||
Message,
|
||||
MessageEvent,
|
||||
)
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.rule import to_me
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from models.friend_user import FriendUser
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from services.log import logger
|
||||
from utils.utils import get_message_img, get_message_text
|
||||
|
||||
from .data_source import get_chat_result, hello, no_result
|
||||
from configs.config import NICKNAME, Config
|
||||
|
||||
__zx_plugin_name__ = "AI"
|
||||
__plugin_usage__ = f"""
|
||||
@ -61,11 +57,9 @@ async def _(bot: Bot, event: MessageEvent):
|
||||
await ai.finish(hello())
|
||||
img = img[0] if img else ""
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
nickname = await GroupInfoUser.get_group_member_nickname(
|
||||
event.user_id, event.group_id
|
||||
)
|
||||
nickname = await GroupInfoUser.get_user_nickname(event.user_id, event.group_id)
|
||||
else:
|
||||
nickname = await FriendUser.get_friend_nickname(event.user_id)
|
||||
nickname = await FriendUser.get_user_nickname(event.user_id)
|
||||
if not nickname:
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
nickname = event.sender.card or event.sender.nickname
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.path_config import IMAGE_PATH, DATA_PATH
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from configs.path_config import DATA_PATH, IMAGE_PATH
|
||||
from services.log import logger
|
||||
from utils.message_builder import image, face
|
||||
from configs.config import Config, NICKNAME
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.message_builder import face, image
|
||||
|
||||
from .utils import ai_message_manager
|
||||
|
||||
try:
|
||||
@ -124,7 +126,9 @@ async def xie_ai(text: str) -> str:
|
||||
:param text: 问题
|
||||
:return: 青云可回复
|
||||
"""
|
||||
res = await AsyncHttpx.get(f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}")
|
||||
res = await AsyncHttpx.get(
|
||||
f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}"
|
||||
)
|
||||
content = ""
|
||||
try:
|
||||
data = json.loads(res.text)
|
||||
@ -176,9 +180,9 @@ def hello() -> str:
|
||||
)
|
||||
img = random.choice(os.listdir(IMAGE_PATH / "zai"))
|
||||
if img[-4:] == ".gif":
|
||||
result += image(img, "zai")
|
||||
result += image(IMAGE_PATH / "zai" / img)
|
||||
else:
|
||||
result += image(img, "zai")
|
||||
result += image(IMAGE_PATH / "zai" / img)
|
||||
return result
|
||||
|
||||
|
||||
@ -187,17 +191,16 @@ def no_result() -> str:
|
||||
"""
|
||||
没有回答时的回复
|
||||
"""
|
||||
return (
|
||||
random.choice(
|
||||
[
|
||||
"你在说啥子?",
|
||||
f"纯洁的{NICKNAME}没听懂",
|
||||
"下次再告诉你(下次一定)",
|
||||
"你觉得我听懂了吗?嗯?",
|
||||
"我!不!知!道!",
|
||||
]
|
||||
)
|
||||
+ image(random.choice(os.listdir(IMAGE_PATH / "noresult")), "noresult")
|
||||
return random.choice(
|
||||
[
|
||||
"你在说啥子?",
|
||||
f"纯洁的{NICKNAME}没听懂",
|
||||
"下次再告诉你(下次一定)",
|
||||
"你觉得我听懂了吗?嗯?",
|
||||
"我!不!知!道!",
|
||||
]
|
||||
) + image(
|
||||
IMAGE_PATH / "noresult" / random.choice(os.listdir(IMAGE_PATH / "noresult"))
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -1,28 +1,29 @@
|
||||
from nonebot import on_command, on_regex
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
|
||||
from typing import Any, Optional, Tuple
|
||||
|
||||
import nonebot
|
||||
from nonebot import Driver, on_command, on_regex
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import ArgStr, CommandArg, RegexGroup
|
||||
from nonebot.typing import T_State
|
||||
|
||||
from configs.config import Config
|
||||
from models.level_user import LevelUser
|
||||
from services.log import logger
|
||||
from utils.image_utils import text2image
|
||||
from utils.manager import group_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import get_bot, is_number, scheduler
|
||||
|
||||
from .data_source import (
|
||||
BilibiliSub,
|
||||
SubManager,
|
||||
add_live_sub,
|
||||
delete_sub,
|
||||
add_up_sub,
|
||||
add_season_sub,
|
||||
add_up_sub,
|
||||
delete_sub,
|
||||
get_media_id,
|
||||
get_sub_status,
|
||||
SubManager,
|
||||
BilibiliSub,
|
||||
)
|
||||
from models.level_user import LevelUser
|
||||
from utils.manager import group_manager
|
||||
from configs.config import Config
|
||||
from utils.utils import is_number, scheduler, get_bot
|
||||
from typing import Optional, Tuple, Any
|
||||
from services.log import logger
|
||||
from nonebot import Driver
|
||||
from nonebot.params import CommandArg, ArgStr, RegexGroup
|
||||
import nonebot
|
||||
|
||||
__zx_plugin_name__ = "B站订阅"
|
||||
__plugin_usage__ = """
|
||||
@ -168,20 +169,20 @@ async def _(
|
||||
sub_user: str = ArgStr("sub_user"),
|
||||
):
|
||||
if sub_type in ["主播", "直播"]:
|
||||
result = await BilibiliSub.delete_bilibili_sub(int(id_),sub_user,"live")
|
||||
result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user, "live")
|
||||
elif sub_type.lower() in ["up", "用户"]:
|
||||
result = await BilibiliSub.delete_bilibili_sub(int(id_),sub_user,"up")
|
||||
else: result = await BilibiliSub.delete_bilibili_sub(int(id_),sub_user)
|
||||
result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user, "up")
|
||||
else:
|
||||
result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user)
|
||||
if result:
|
||||
await del_sub.send(f"删除订阅id:{id_} 成功...")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 删除订阅 {id_}"
|
||||
)
|
||||
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:{id_} 失败...")
|
||||
|
||||
|
||||
|
||||
@show_sub_info.handle()
|
||||
@ -190,7 +191,7 @@ async def _(event: MessageEvent):
|
||||
id_ = f"{event.group_id}"
|
||||
else:
|
||||
id_ = f"{event.user_id}"
|
||||
data = await BilibiliSub.get_sub_data(id_)
|
||||
data = await BilibiliSub.filter(sub_users__contains=id_).all()
|
||||
live_rst = ""
|
||||
up_rst = ""
|
||||
season_rst = ""
|
||||
@ -217,11 +218,9 @@ async def _(event: MessageEvent):
|
||||
)
|
||||
await show_sub_info.send(
|
||||
image(
|
||||
b64=(
|
||||
await text2image(
|
||||
live_rst + up_rst + season_rst, padding=10, color="#f9f6f2"
|
||||
)
|
||||
).pic2bs4()
|
||||
await text2image(
|
||||
live_rst + up_rst + season_rst, padding=10, color="#f9f6f2"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@ -277,7 +276,9 @@ async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
|
||||
):
|
||||
rst = "[CQ:at,qq=all]\n" + rst
|
||||
if group_manager.get_plugin_status("bilibili_sub", group_id):
|
||||
await bot.send_group_msg(group_id=group_id, message=Message(rst))
|
||||
await bot.send_group_msg(
|
||||
group_id=group_id, message=Message(rst)
|
||||
)
|
||||
else:
|
||||
await bot.send_private_msg(user_id=int(x), message=Message(rst))
|
||||
except Exception as e:
|
||||
|
||||
@ -1,34 +1,33 @@
|
||||
from bilireq.exceptions import ResponseCodeError
|
||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||
|
||||
from utils.manager import resources_manager
|
||||
import random
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from utils.utils import get_bot
|
||||
from .model import BilibiliSub
|
||||
from bilireq.live import get_room_info_by_id
|
||||
from .utils import get_meta, get_user_card
|
||||
from utils.message_builder import image
|
||||
from bilireq.user import get_videos
|
||||
# from .utils import get_videos
|
||||
from bilireq import dynamic
|
||||
from typing import Optional, Tuple
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from datetime import datetime
|
||||
from utils.browser import get_browser
|
||||
from services.db_context import db
|
||||
from bilireq.exceptions import ResponseCodeError
|
||||
from bilireq.live import get_room_info_by_id
|
||||
from bilireq.user import get_videos
|
||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||
|
||||
from configs.path_config import IMAGE_PATH, TEMP_PATH
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import random
|
||||
from utils.browser import get_browser
|
||||
from utils.http_utils import AsyncHttpx, AsyncPlaywright
|
||||
from utils.manager import resources_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import get_bot
|
||||
|
||||
from .model import BilibiliSub
|
||||
from .utils import get_meta, get_user_card
|
||||
|
||||
SEARCH_URL = "https://api.bilibili.com/x/web-interface/search/all/v2"
|
||||
|
||||
DYNAMIC_PATH = IMAGE_PATH / "bilibili_sub" / "dynamic"
|
||||
DYNAMIC_PATH.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
|
||||
|
||||
dynamic_path = IMAGE_PATH / "bilibili_sub" / "dynamic"
|
||||
dynamic_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
resources_manager.add_temp_dir(dynamic_path)
|
||||
resources_manager.add_temp_dir(DYNAMIC_PATH)
|
||||
|
||||
|
||||
async def add_live_sub(live_id: int, sub_user: str) -> str:
|
||||
@ -49,7 +48,7 @@ async def add_live_sub(live_id: int, sub_user: str) -> str:
|
||||
short_id = live_info["short_id"]
|
||||
title = live_info["title"]
|
||||
live_status = live_info["live_status"]
|
||||
if await BilibiliSub.add_bilibili_sub(
|
||||
if await BilibiliSub.sub_handle(
|
||||
room_id,
|
||||
"live",
|
||||
sub_user,
|
||||
@ -58,14 +57,14 @@ async def add_live_sub(live_id: int, sub_user: str) -> str:
|
||||
live_status=live_status,
|
||||
):
|
||||
await _get_up_status(room_id)
|
||||
uname = (await BilibiliSub.get_sub(room_id)).uname
|
||||
uname = (await BilibiliSub.get_or_none(sub_id=room_id)).uname
|
||||
return (
|
||||
"已成功订阅主播:\n"
|
||||
f"\ttitle:{title}\n"
|
||||
f"\tname: {uname}\n"
|
||||
f"\tlive_id:{room_id}\n"
|
||||
f"\tuid:{uid}"
|
||||
)
|
||||
)
|
||||
else:
|
||||
return "添加订阅失败..."
|
||||
except Exception as e:
|
||||
@ -80,35 +79,34 @@ async def add_up_sub(uid: int, sub_user: str) -> str:
|
||||
:param sub_user: 订阅用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
"""bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
|
||||
user_info = await get_user_card(uid)
|
||||
except ResponseCodeError:
|
||||
return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
|
||||
uname = user_info["name"]
|
||||
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
|
||||
dynamic_info = await dynamic.get_user_dynamics(uid)
|
||||
dynamic_upload_time = 0
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
"""bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
|
||||
video_info = await get_videos(uid)
|
||||
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 "添加订阅失败..."
|
||||
try:
|
||||
"""bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
|
||||
user_info = await get_user_card(uid)
|
||||
except ResponseCodeError:
|
||||
return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
|
||||
uname = user_info["name"]
|
||||
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
|
||||
dynamic_info = await dynamic.get_user_dynamics(uid)
|
||||
dynamic_upload_time = 0
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
"""bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
|
||||
video_info = await get_videos(uid)
|
||||
latest_video_created = 0
|
||||
if video_info["list"].get("vlist"):
|
||||
latest_video_created = video_info["list"]["vlist"][0]["created"]
|
||||
if await BilibiliSub.sub_handle(
|
||||
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 "添加订阅失败..."
|
||||
@ -121,30 +119,29 @@ async def add_season_sub(media_id: int, sub_user: str) -> str:
|
||||
:param sub_user: 订阅用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
"""bilibili_api.bangumi库中get_meta改为bilireq.bangumi库的get_meta方法"""
|
||||
season_info = await get_meta(media_id)
|
||||
except ResponseCodeError:
|
||||
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 "添加订阅失败..."
|
||||
try:
|
||||
"""bilibili_api.bangumi库中get_meta改为bilireq.bangumi库的get_meta方法"""
|
||||
season_info = await get_meta(media_id)
|
||||
except ResponseCodeError:
|
||||
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.sub_handle(
|
||||
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 "添加订阅失败..."
|
||||
@ -171,9 +168,7 @@ async def get_media_id(keyword: str) -> dict:
|
||||
for _ in range(3):
|
||||
try:
|
||||
_season_data = {}
|
||||
response = await AsyncHttpx.get(
|
||||
bilibili_search_url, params=params, timeout=5
|
||||
)
|
||||
response = await AsyncHttpx.get(SEARCH_URL, params=params, timeout=5)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get("data"):
|
||||
@ -227,9 +222,9 @@ async def _get_live_status(id_: int) -> Optional[str]:
|
||||
room_id = live_info["room_id"]
|
||||
live_status = live_info["live_status"]
|
||||
cover = live_info["user_cover"]
|
||||
sub = await BilibiliSub.get_sub(id_)
|
||||
sub = await BilibiliSub.get_or_none(sub_id=id_)
|
||||
if sub.live_status != live_status:
|
||||
await BilibiliSub.update_sub_info(id_, live_status=live_status)
|
||||
await BilibiliSub.sub_handle(id_, live_status=live_status)
|
||||
if sub.live_status in [0, 2] and live_status == 1:
|
||||
return (
|
||||
f""
|
||||
@ -247,7 +242,7 @@ async def _get_up_status(id_: int) -> Optional[str]:
|
||||
:param id_: 订阅 id
|
||||
:return:
|
||||
"""
|
||||
_user = await BilibiliSub.get_sub(id_)
|
||||
_user = await BilibiliSub.get_or_none(sub_id=id_)
|
||||
"""bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
|
||||
user_info = await get_user_card(_user.uid)
|
||||
uname = user_info["name"]
|
||||
@ -257,14 +252,14 @@ async def _get_up_status(id_: int) -> Optional[str]:
|
||||
video = None
|
||||
dividing_line = "\n-------------\n"
|
||||
if _user.uname != uname:
|
||||
await BilibiliSub.update_sub_info(id_, uname=uname)
|
||||
await BilibiliSub.sub_handle(id_, uname=uname)
|
||||
dynamic_img, dynamic_upload_time, link = await get_user_dynamic(_user.uid, _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)
|
||||
await BilibiliSub.sub_handle(id_, dynamic_upload_time=dynamic_upload_time)
|
||||
rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n{link}"
|
||||
if (
|
||||
latest_video_created
|
||||
@ -273,9 +268,7 @@ async def _get_up_status(id_: int) -> Optional[str]:
|
||||
and _user.latest_video_created < latest_video_created
|
||||
):
|
||||
rst = rst + dividing_line if rst else rst
|
||||
await BilibiliSub.update_sub_info(
|
||||
id_, latest_video_created=latest_video_created
|
||||
)
|
||||
await BilibiliSub.sub_handle(id_, latest_video_created=latest_video_created)
|
||||
rst += (
|
||||
f'{image(video["pic"])}\n'
|
||||
f"{uname} 投稿了新视频啦\n"
|
||||
@ -295,10 +288,10 @@ async def _get_season_status(id_) -> Optional[str]:
|
||||
"""bilibili_api.bangumi库中get_meta改为bilireq.bangumi库的get_meta方法"""
|
||||
season_info = await get_meta(id_)
|
||||
title = season_info["media"]["title"]
|
||||
_idx = (await BilibiliSub.get_sub(id_)).season_current_episode
|
||||
_idx = (await BilibiliSub.get_or_none(sub_id=id_)).season_current_episode
|
||||
new_ep = season_info["media"]["new_ep"]["index"]
|
||||
if new_ep != _idx:
|
||||
await BilibiliSub.update_sub_info(
|
||||
await BilibiliSub.sub_handle(
|
||||
id_, season_current_episode=new_ep, season_update_time=datetime.now()
|
||||
)
|
||||
return (
|
||||
@ -320,55 +313,22 @@ async def get_user_dynamic(
|
||||
"""
|
||||
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
|
||||
dynamic_info = await dynamic.get_user_dynamics(uid)
|
||||
browser = await get_browser()
|
||||
if dynamic_info.get("cards") and browser:
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
dynamic_id = dynamic_info["cards"][0]["desc"]["dynamic_id"]
|
||||
if local_user.dynamic_upload_time < dynamic_upload_time:
|
||||
context = await browser.new_context()
|
||||
page = await context.new_page()
|
||||
try:
|
||||
await page.goto(
|
||||
f"https://t.bilibili.com/{dynamic_id}",
|
||||
wait_until="networkidle",
|
||||
timeout=10000,
|
||||
)
|
||||
# await page.set_viewport_size({"width": 2560, "height": 1080, "timeout": 10000*20}) # timeout: 200s
|
||||
# 删除置顶
|
||||
# await page.evaluate(
|
||||
# """
|
||||
# xs = document.getElementsByClassName('bili-dyn-item__tag');
|
||||
# for (x of xs) {
|
||||
# x.parentNode.parentNode.remove();
|
||||
# }
|
||||
# """
|
||||
# )
|
||||
# async with page.expect_popup() as popup_info:
|
||||
# await page.locator(".bili-rich-text__content").click()
|
||||
# details_page = await popup_info.value
|
||||
await page.set_viewport_size(
|
||||
{"width": 2560, "height": 1080, "timeout": 10000 * 20}
|
||||
)
|
||||
await page.wait_for_selector(".bili-dyn-item__main")
|
||||
card = page.locator(".bili-dyn-item__main")
|
||||
await card.wait_for()
|
||||
await card.screenshot(
|
||||
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"B站订阅:获取用户动态 发送错误 {type(e)}:{e}")
|
||||
finally:
|
||||
await context.close()
|
||||
await page.close()
|
||||
return (
|
||||
image(
|
||||
f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||
"bilibili_sub/dynamic",
|
||||
),
|
||||
dynamic_upload_time,
|
||||
f"https://t.bilibili.com/{dynamic_id}"
|
||||
image = await AsyncPlaywright.screenshot(
|
||||
f"https://t.bilibili.com/{dynamic_id}",
|
||||
DYNAMIC_PATH / f"sub_{local_user.sub_id}.png",
|
||||
".bili-dyn-item__main",
|
||||
wait_until="networkidle",
|
||||
)
|
||||
return None, 0, ''
|
||||
return (
|
||||
image,
|
||||
dynamic_upload_time,
|
||||
f"https://t.bilibili.com/{dynamic_id}",
|
||||
)
|
||||
return None, 0, ""
|
||||
|
||||
|
||||
class SubManager:
|
||||
|
||||
@ -1,43 +1,58 @@
|
||||
from services.log import logger
|
||||
from services.db_context import db
|
||||
from datetime import datetime
|
||||
from typing import Optional, List
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
from services.log import logger
|
||||
|
||||
|
||||
class BilibiliSub(db.Model):
|
||||
__tablename__ = "bilibili_sub"
|
||||
class BilibiliSub(Model):
|
||||
|
||||
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())
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
sub_id = fields.IntField()
|
||||
"""订阅id"""
|
||||
sub_type = fields.CharField(255)
|
||||
"""订阅类型"""
|
||||
sub_users = fields.TextField()
|
||||
"""订阅用户"""
|
||||
live_short_id = fields.IntField(null=True)
|
||||
"""直播短id"""
|
||||
live_status = fields.IntField(null=True)
|
||||
"""直播状态 0: 停播 1: 直播"""
|
||||
uid = fields.BigIntField(null=True)
|
||||
"""主播/UP UID"""
|
||||
uname = fields.CharField(255, null=True)
|
||||
"""主播/UP 名称"""
|
||||
latest_video_created = fields.BigIntField(null=True)
|
||||
"""最后视频上传时间"""
|
||||
dynamic_upload_time = fields.BigIntField(null=True, default=0)
|
||||
"""动态发布时间"""
|
||||
season_name = fields.CharField(255, null=True)
|
||||
"""番剧名称"""
|
||||
season_id = fields.IntField(null=True)
|
||||
"""番剧id"""
|
||||
season_current_episode = fields.CharField(255, null=True)
|
||||
"""番剧最新集数"""
|
||||
season_update_time = fields.DateField(null=True)
|
||||
"""番剧更新日期"""
|
||||
|
||||
_idx1 = db.Index("bilibili_sub_idx1", "sub_id", "sub_type", unique=True)
|
||||
class Meta:
|
||||
table = "bilibili_sub"
|
||||
table_description = "B站订阅数据表"
|
||||
unique_together = ("sub_id", "sub_type")
|
||||
|
||||
@classmethod
|
||||
async def add_bilibili_sub(
|
||||
async def sub_handle(
|
||||
cls,
|
||||
sub_id: int,
|
||||
sub_type: str,
|
||||
sub_user: str,
|
||||
sub_type: Optional[str] = None,
|
||||
sub_user: str = "",
|
||||
*,
|
||||
live_short_id: Optional[int] = None,
|
||||
live_status: Optional[int] = None,
|
||||
dynamic_upload_time: Optional[int] = None,
|
||||
dynamic_upload_time: int = 0,
|
||||
uid: Optional[int] = None,
|
||||
uname: Optional[str] = None,
|
||||
latest_video_created: Optional[int] = None,
|
||||
@ -64,50 +79,60 @@ class BilibiliSub(db.Model):
|
||||
:param season_current_episode: 番剧最新集数
|
||||
:param season_update_time: 番剧更新时间
|
||||
"""
|
||||
try:
|
||||
query = (
|
||||
await cls.query.where( (cls.sub_id == sub_id) & (cls.sub_type == sub_type) )
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
# try:
|
||||
data = {
|
||||
"sub_type": sub_type,
|
||||
"sub_user": sub_user,
|
||||
"live_short_id": live_short_id,
|
||||
"live_status": live_status,
|
||||
"dynamic_upload_time": dynamic_upload_time,
|
||||
"uid": uid,
|
||||
"uname": uname,
|
||||
"latest_video_created": latest_video_created,
|
||||
"season_name": season_name,
|
||||
"season_id": season_id,
|
||||
"season_current_episode": season_current_episode,
|
||||
"season_update_time": season_update_time,
|
||||
}
|
||||
if sub_user:
|
||||
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
|
||||
sub = None
|
||||
if sub_type:
|
||||
sub = await cls.get_or_none(sub_id=sub_id, sub_type=sub_type)
|
||||
else:
|
||||
sub = await cls.get_or_none(sub_id=sub_id)
|
||||
if sub:
|
||||
sub_users = sub.sub_users + sub_user
|
||||
data["sub_type"] = sub_type or sub.sub_type
|
||||
data["sub_user"] = sub_users
|
||||
data["live_short_id"] = live_short_id or sub.live_short_id
|
||||
data["live_status"] = (
|
||||
live_status if live_status is not None else sub.live_status
|
||||
)
|
||||
data["dynamic_upload_time"] = dynamic_upload_time or sub.dynamic_upload_time
|
||||
data["uid"] = uid or sub.uid
|
||||
data["uname"] = uname or sub.uname
|
||||
data["latest_video_created"] = (
|
||||
latest_video_created or sub.latest_video_created
|
||||
)
|
||||
data["season_name"] = season_name or sub.season_name
|
||||
data["season_id"] = season_id or sub.season_id
|
||||
data["season_current_episode"] = (
|
||||
season_current_episode or sub.season_current_episode
|
||||
)
|
||||
data["season_update_time"] = season_update_time or sub.season_update_time
|
||||
else:
|
||||
await cls.create(sub_id=sub_id, sub_type=sub_type, sub_users=sub_user)
|
||||
await cls.update_or_create(sub_id=sub_id, defaults=data)
|
||||
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,sub_type: Optional[str] = None) -> bool:
|
||||
async def delete_bilibili_sub(
|
||||
cls, sub_id: int, sub_user: str, sub_type: Optional[str] = None
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
删除订阅
|
||||
@ -116,129 +141,30 @@ class BilibiliSub(db.Model):
|
||||
:param sub_user: 删除此条目的用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
if sub_type:
|
||||
query = (
|
||||
await cls.query.where(
|
||||
(cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user) & (cls.sub_type == sub_type))
|
||||
)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
else:
|
||||
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
|
||||
if sub_type:
|
||||
sub = await cls.filter(
|
||||
sub_id=sub_id, sub_type=sub_type, sub_users__contains=sub_user
|
||||
).first()
|
||||
else:
|
||||
sub = await cls.filter(
|
||||
sub_id=sub_id, sub_users__contains=sub_user
|
||||
).first()
|
||||
if not sub:
|
||||
return False
|
||||
sub.sub_users = sub.sub_users.replace(f"{sub_user},", "")
|
||||
if sub.sub_users.strip():
|
||||
await sub.save(update_fields=["sub_users"])
|
||||
else:
|
||||
await sub.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]":
|
||||
) -> Tuple[List["BilibiliSub"], List["BilibiliSub"], List["BilibiliSub"]]:
|
||||
"""
|
||||
说明:
|
||||
分类获取所有数据
|
||||
@ -246,7 +172,7 @@ class BilibiliSub(db.Model):
|
||||
live_data = []
|
||||
up_data = []
|
||||
season_data = []
|
||||
query = await cls.query.gino.all()
|
||||
query = await cls.all()
|
||||
for x in query:
|
||||
if x.sub_type == "live":
|
||||
live_data.append(x)
|
||||
|
||||
@ -1,28 +1,30 @@
|
||||
from datetime import datetime
|
||||
from typing import Any, Tuple
|
||||
|
||||
from nonebot import on_command, on_message, on_regex
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
Event,
|
||||
MessageEvent,
|
||||
GroupMessageEvent,
|
||||
Message,
|
||||
Bot,
|
||||
MessageEvent,
|
||||
)
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import run_preprocessor
|
||||
from nonebot.params import CommandArg, RegexGroup
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from models.ban_user import BanUser
|
||||
from services.log import logger
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.manager import group_manager
|
||||
from utils.utils import get_message_text, is_number
|
||||
from nonebot.params import RegexGroup, CommandArg
|
||||
from .utils import black_word_manager
|
||||
from nonebot import on_command, on_message, on_regex
|
||||
from configs.config import Config, NICKNAME
|
||||
from nonebot.permission import SUPERUSER
|
||||
from .data_source import show_black_text_image, set_user_punish
|
||||
from services.log import logger
|
||||
from models.ban_user import BanUser
|
||||
from datetime import datetime
|
||||
from utils.message_builder import image
|
||||
from .model import BlackWord
|
||||
from typing import Tuple, Any
|
||||
from utils.utils import get_message_text, is_number
|
||||
|
||||
from .data_source import set_user_punish, show_black_text_image
|
||||
from .model import BlackWord
|
||||
from .utils import black_word_manager
|
||||
|
||||
__zx_plugin_name__ = "敏感词检测"
|
||||
__plugin_usage__ = """
|
||||
@ -38,7 +40,7 @@ usage:
|
||||
设置惩罚id需要通过 '记录名单u:xxxxxxxx' 获取
|
||||
指令:
|
||||
记录名单
|
||||
设置惩罚 [user_id] [id] [punish_level]
|
||||
设置惩罚 [user_id] [下标] [惩罚等级]
|
||||
示例:记录名单
|
||||
示例:记录名单u:12345678
|
||||
示例:设置惩罚 12345678 1 4
|
||||
@ -150,24 +152,32 @@ async def _(
|
||||
matcher: Matcher,
|
||||
event: Event,
|
||||
):
|
||||
msg = get_message_text(event.json())
|
||||
if (
|
||||
isinstance(event, MessageEvent)
|
||||
and event.is_tome()
|
||||
and matcher.plugin_name == "black_word"
|
||||
and not await BanUser.is_ban(event.user_id)
|
||||
and str(event.user_id) not in bot.config.superusers
|
||||
and not get_message_text(event.json()).startswith("原神绑定")
|
||||
and not msg.startswith("原神绑定")
|
||||
):
|
||||
# 屏蔽群权限-1的群
|
||||
if isinstance(event, GroupMessageEvent) and group_manager.get_group_level(event.group_id) < 0:
|
||||
return
|
||||
user_id = event.user_id
|
||||
group_id = event.group_id if isinstance(event, GroupMessageEvent) else None
|
||||
msg = get_message_text(event.json())
|
||||
if await black_word_manager.check(user_id, group_id, msg) and Config.get_config(
|
||||
"black_word", "CONTAIN_BLACK_STOP_PROPAGATION"
|
||||
# if str(event.user_id) not in bot.config.superusers:
|
||||
# return logger.debug(f"超级用户跳过黑名单词汇检查 Message: {msg}", target=event.user_id)
|
||||
if (
|
||||
event.is_tome()
|
||||
and matcher.plugin_name == "black_word"
|
||||
and not await BanUser.is_ban(event.user_id)
|
||||
):
|
||||
matcher.stop_propagation()
|
||||
# 屏蔽群权限-1的群
|
||||
if (
|
||||
isinstance(event, GroupMessageEvent)
|
||||
and group_manager.get_group_level(event.group_id) < 0
|
||||
):
|
||||
return
|
||||
user_id = event.user_id
|
||||
group_id = event.group_id if isinstance(event, GroupMessageEvent) else None
|
||||
msg = get_message_text(event.json())
|
||||
if await black_word_manager.check(
|
||||
user_id, group_id, msg
|
||||
) and Config.get_config("black_word", "CONTAIN_BLACK_STOP_PROPAGATION"):
|
||||
matcher.stop_propagation()
|
||||
|
||||
|
||||
@show_black.handle()
|
||||
|
||||
@ -1,47 +1,34 @@
|
||||
from services.db_context import db
|
||||
from typing import Optional, List
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class BlackWord(db.Model):
|
||||
__tablename__ = "black_word"
|
||||
class BlackWord(Model):
|
||||
# __tablename__ = "black_word"
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False, primary_key=True)
|
||||
group_id = db.Column(db.BigInteger())
|
||||
plant_text = db.Column(db.String())
|
||||
black_word = db.Column(db.String())
|
||||
punish = db.Column(db.String(), default="")
|
||||
punish_level = db.Column(db.Integer())
|
||||
create_time = db.Column(db.DateTime(timezone=True), nullable=False)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField(null=True)
|
||||
"""群聊id"""
|
||||
plant_text = fields.TextField()
|
||||
"""检测文本"""
|
||||
black_word = fields.TextField()
|
||||
"""黑名单词语"""
|
||||
punish = fields.TextField(default="")
|
||||
"""惩罚内容"""
|
||||
punish_level = fields.IntField()
|
||||
"""惩罚等级"""
|
||||
create_time = fields.DatetimeField(auto_now_add=True)
|
||||
"""创建时间"""
|
||||
|
||||
@classmethod
|
||||
async def add_user_black_word(
|
||||
cls,
|
||||
user_qq: int,
|
||||
group_id: Optional[int],
|
||||
black_word: str,
|
||||
plant_text: str,
|
||||
punish_level: int,
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
添加用户发送的敏感词
|
||||
参数:
|
||||
:param user_qq: 用户id
|
||||
:param group_id: 群号
|
||||
:param black_word: 黑名单词汇
|
||||
:param plant_text: 消息文本
|
||||
:param punish_level: 惩罚等级
|
||||
"""
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
plant_text=plant_text,
|
||||
black_word=black_word,
|
||||
punish_level=punish_level,
|
||||
create_time=datetime.now(),
|
||||
)
|
||||
class Meta:
|
||||
table = "black_word"
|
||||
table_description = "惩罚机制数据表"
|
||||
|
||||
@classmethod
|
||||
async def set_user_punish(
|
||||
@ -63,17 +50,21 @@ class BlackWord(db.Model):
|
||||
user = None
|
||||
if (not black_word and not id_) or not punish:
|
||||
return False
|
||||
query = cls.query.where(cls.user_qq == user_qq).with_for_update()
|
||||
if black_word:
|
||||
user = await query.where(cls.black_word == black_word).order_by(cls.id.desc()).gino.first()
|
||||
user = (
|
||||
await cls.filter(user_qq=user_qq, black_word=black_word)
|
||||
.order_by("id")
|
||||
.first()
|
||||
)
|
||||
elif id_:
|
||||
user_list = await query.gino.all()
|
||||
user_list = await cls.filter(user_qq=user_qq).order_by("id").all()
|
||||
if len(user_list) == 0 or (id_ < 0 or id_ > len(user_list)):
|
||||
return False
|
||||
user = user_list[id_]
|
||||
if not user:
|
||||
return False
|
||||
await user.update(punish=cls.punish + punish + " ").apply()
|
||||
user.punish = f"{user.punish}{punish} "
|
||||
await user.save(update_fields=["punish"])
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
@ -88,15 +79,14 @@ class BlackWord(db.Model):
|
||||
:param days: 周期天数
|
||||
:param punish_level: 惩罚等级
|
||||
"""
|
||||
setattr(BlackWord, "count", db.func.count(cls.id).label("count"))
|
||||
query = cls.select("count").where(
|
||||
(cls.user_qq == user_qq)
|
||||
& (cls.punish_level != -1)
|
||||
& (cls.create_time > datetime.now() - timedelta(days=days))
|
||||
query = cls.filter(
|
||||
user_qq=user_qq,
|
||||
create_time__gte=datetime.now() - timedelta(days=days),
|
||||
punish_level__not_in=[-1],
|
||||
)
|
||||
if punish_level is not None:
|
||||
query = query.where(cls.punish_level == punish_level)
|
||||
return (await query.gino.first())[0]
|
||||
query = query.filter(punish_level=punish_level)
|
||||
return await query.count()
|
||||
|
||||
@classmethod
|
||||
async def get_user_punish_level(cls, user_qq: int, days: int = 7) -> Optional[int]:
|
||||
@ -108,12 +98,14 @@ class BlackWord(db.Model):
|
||||
:param days: 周期天数
|
||||
"""
|
||||
if (
|
||||
query := await cls.query.where(cls.user_qq == user_qq)
|
||||
.where(cls.create_time > datetime.now() - timedelta(days=days))
|
||||
.order_by(cls.id.desc())
|
||||
.gino.first()
|
||||
user := await cls.filter(
|
||||
user_qq=user_qq,
|
||||
create_time__gte=datetime.now() - timedelta(days=days),
|
||||
)
|
||||
.order_by("id")
|
||||
.first()
|
||||
):
|
||||
return query.punish_level
|
||||
return user.punish_level
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
@ -133,16 +125,18 @@ class BlackWord(db.Model):
|
||||
:param date: 日期
|
||||
:param date_type: 日期查询类型
|
||||
"""
|
||||
query = cls.query
|
||||
query = cls
|
||||
if user_qq:
|
||||
query = query.where(cls.user_qq == user_qq)
|
||||
query = query.filter(user_qq=user_qq)
|
||||
if group_id:
|
||||
query = query.where(cls.group_id == group_id)
|
||||
query = query.filter(group_id=group_id)
|
||||
if date:
|
||||
if date_type == "=":
|
||||
query = query.where(cls.create_time == date)
|
||||
query = query.filter(
|
||||
create_time__range=[date, date + timedelta(days=1)]
|
||||
)
|
||||
elif date_type == ">":
|
||||
query = query.where(cls.create_time > date)
|
||||
query = query.filter(create_time__gte=date)
|
||||
elif date_type == "<":
|
||||
query = query.where(cls.create_time < date)
|
||||
return await query.gino.all()
|
||||
query = query.filter(create_time__lte=date)
|
||||
return await query.order_by("id").all()
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
from utils.utils import cn2py, get_bot
|
||||
from configs.path_config import DATA_PATH
|
||||
from typing import Optional, Union, Tuple
|
||||
from .model import BlackWord
|
||||
from configs.config import Config
|
||||
from pathlib import Path
|
||||
from services.log import logger
|
||||
from models.ban_user import BanUser
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import random
|
||||
from pathlib import Path
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import DATA_PATH
|
||||
from models.ban_user import BanUser
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.utils import cn2py, get_bot
|
||||
|
||||
from .model import BlackWord
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@ -49,7 +52,7 @@ class BlackWordManager:
|
||||
"hanbi",
|
||||
"hanpi",
|
||||
"laji",
|
||||
"fw"
|
||||
"fw",
|
||||
],
|
||||
"5": [],
|
||||
}
|
||||
@ -94,9 +97,9 @@ class BlackWordManager:
|
||||
user_id, group_id, data[0], message, int(data[1])
|
||||
)
|
||||
return True
|
||||
if Config.get_config(
|
||||
"black_word", "ALAPI_CHECK_FLAG"
|
||||
) and not await check_text(message):
|
||||
if Config.get_config("black_word", "ALAPI_CHECK_FLAG") and not await check_text(
|
||||
message
|
||||
):
|
||||
await send_msg(
|
||||
0, None, f"USER {user_id} GROUP {group_id} ALAPI 疑似检测:{message}"
|
||||
)
|
||||
@ -146,8 +149,12 @@ async def _add_user_black_word(
|
||||
"black_word", "AUTO_ADD_PUNISH_LEVEL"
|
||||
) and user_count > Config.get_config("black_word", "ADD_PUNISH_LEVEL_TO_COUNT"):
|
||||
punish_level -= 1
|
||||
await BlackWord.add_user_black_word(
|
||||
user_id, group_id, black_word, message, punish_level
|
||||
await BlackWord.create(
|
||||
user_qq=user_id,
|
||||
group_id=group_id,
|
||||
plant_text=message,
|
||||
black_word=black_word,
|
||||
punish_level=punish_level,
|
||||
)
|
||||
logger.info(
|
||||
f"已将 USER {user_id} GROUP {group_id} 添加至黑名单词汇记录 Black_word:{black_word} Plant_text:{message}"
|
||||
@ -172,7 +179,9 @@ async def _punish_handle(
|
||||
# 用户周期内触发punish_level级惩罚的次数
|
||||
user_count = await BlackWord.get_user_count(user_id, cycle_days, punish_level)
|
||||
# 获取最近一次的惩罚等级,将在此基础上增加
|
||||
punish_level = await BlackWord.get_user_punish_level(user_id, cycle_days) or punish_level
|
||||
punish_level = (
|
||||
await BlackWord.get_user_punish_level(user_id, cycle_days) or punish_level
|
||||
)
|
||||
# 容忍次数:List[int]
|
||||
tolerate_count = Config.get_config("black_word", "TOLERATE_COUNT")
|
||||
if not tolerate_count or len(tolerate_count) < 5:
|
||||
@ -226,15 +235,17 @@ async def _get_punish(
|
||||
ban_4_duration = Config.get_config("black_word", "BAN_4_DURATION")
|
||||
# 口头警告内容
|
||||
warning_result = Config.get_config("black_word", "WARNING_RESULT")
|
||||
try:
|
||||
uname = (await GroupInfoUser.get_member_info(user_id, group_id)).user_name
|
||||
except AttributeError:
|
||||
if user := await GroupInfoUser.get_or_none(user_qq=user_id, group_id=group_id):
|
||||
uname = user.user_name
|
||||
else:
|
||||
uname = user_id
|
||||
# 永久ban
|
||||
if id_ == 1:
|
||||
if str(user_id) not in bot.config.superusers:
|
||||
await BanUser.ban(user_id, 10, 99999999)
|
||||
await send_msg(user_id, group_id, f"BlackWordChecker 永久ban USER {uname}({user_id})")
|
||||
await send_msg(
|
||||
user_id, group_id, f"BlackWordChecker 永久ban USER {uname}({user_id})"
|
||||
)
|
||||
logger.info(f"BlackWord 永久封禁 USER {user_id}...")
|
||||
# 删除好友(有的话
|
||||
elif id_ == 2:
|
||||
@ -319,4 +330,7 @@ async def check_text(text: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
black_word_manager = BlackWordManager(DATA_PATH / "black_word" / "black_word.json", DATA_PATH / "black_word" / "black_py.json")
|
||||
black_word_manager = BlackWordManager(
|
||||
DATA_PATH / "black_word" / "black_word.json",
|
||||
DATA_PATH / "black_word" / "black_py.json",
|
||||
)
|
||||
|
||||
@ -1,13 +1,7 @@
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.config import Config
|
||||
from bs4 import BeautifulSoup
|
||||
import platform
|
||||
|
||||
# if platform.system() == "Windows":
|
||||
# import asyncio
|
||||
#
|
||||
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||
|
||||
from configs.config import Config
|
||||
from utils.http_utils import AsyncHttpx
|
||||
|
||||
url = "http://www.eclzz.love"
|
||||
|
||||
@ -28,10 +22,7 @@ async def get_bt_info(keyword: str, page: int):
|
||||
for item in item_lst[:bt_max_num]:
|
||||
divs = item.find_all("div")
|
||||
title = (
|
||||
str(divs[0].find("a").text)
|
||||
.replace("<em>", "")
|
||||
.replace("</em>", "")
|
||||
.strip()
|
||||
str(divs[0].find("a").text).replace("<em>", "").replace("</em>", "").strip()
|
||||
)
|
||||
spans = divs[2].find_all("span")
|
||||
type_ = spans[0].text
|
||||
|
||||
@ -65,4 +65,4 @@ async def _():
|
||||
mes = "[[_task|genshin_alc]]" + alc_img
|
||||
for gid in gl:
|
||||
if group_manager.check_group_task_status(gid, "genshin_alc"):
|
||||
await bot.send_group_msg(group_id=int(gid), message="" + mes)
|
||||
await bot.send_group_msg(group_id=int(gid), message=mes)
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
from nonebot import on_command, Driver
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, Message, GroupMessageEvent
|
||||
from utils.message_builder import image
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.browser import get_browser
|
||||
from configs.path_config import IMAGE_PATH
|
||||
import nonebot
|
||||
from services.log import logger
|
||||
from nonebot.permission import SUPERUSER
|
||||
from typing import List
|
||||
from datetime import datetime, timedelta
|
||||
import os
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List
|
||||
|
||||
import nonebot
|
||||
from nonebot import Driver, on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from services.log import logger
|
||||
from utils.browser import get_browser
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.message_builder import image
|
||||
|
||||
__zx_plugin_name__ = "今日素材"
|
||||
__plugin_usage__ = """
|
||||
@ -114,5 +115,3 @@ def get_background_height(weapons_img: List[str]) -> int:
|
||||
last_weapon.save(weapons_img[-1])
|
||||
|
||||
return height
|
||||
|
||||
|
||||
|
||||
@ -1,219 +1,49 @@
|
||||
from services.db_context import db
|
||||
from typing import Optional, Union, List
|
||||
from datetime import datetime, timedelta
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional
|
||||
|
||||
import pytz
|
||||
from tortoise import fields
|
||||
from tortoise.contrib.postgres.functions import Random
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class Genshin(db.Model):
|
||||
__tablename__ = "genshin"
|
||||
class Genshin(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
uid = db.Column(db.BigInteger())
|
||||
mys_id = db.Column(db.BigInteger())
|
||||
cookie = db.Column(db.String(), default="")
|
||||
today_query_uid = db.Column(db.String(), default="") # 该cookie今日查询的uid
|
||||
auto_sign = db.Column(db.Boolean(), default=False)
|
||||
auto_sign_time = db.Column(db.DateTime(timezone=True))
|
||||
resin_remind = db.Column(db.Boolean(), default=False) # 树脂提醒
|
||||
resin_recovery_time = db.Column(db.DateTime(timezone=True)) # 满树脂提醒日期
|
||||
bind_group = db.Column(db.BigInteger())
|
||||
login_ticket = db.Column(db.String(), default="")
|
||||
stuid = db.Column(db.String(), default="")
|
||||
stoken = db.Column(db.String(), default="")
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
uid = fields.BigIntField()
|
||||
"""uid"""
|
||||
mys_id: int = fields.BigIntField(null=True)
|
||||
"""米游社id"""
|
||||
cookie: str = fields.TextField(default="")
|
||||
"""米游社cookie"""
|
||||
auto_sign = fields.BooleanField(default=False)
|
||||
"""是否自动签到"""
|
||||
today_query_uid = fields.TextField(default="")
|
||||
"""cookie今日查询uid"""
|
||||
auto_sign_time = fields.DatetimeField(null=True)
|
||||
"""签到日期时间"""
|
||||
resin_remind = fields.BooleanField(default=False)
|
||||
"""树脂提醒"""
|
||||
resin_recovery_time = fields.DatetimeField(null=True)
|
||||
"""满树脂提醒日期"""
|
||||
bind_group: int = fields.BigIntField(null=True)
|
||||
"""发送提示 绑定群聊"""
|
||||
login_ticket = fields.TextField(default="")
|
||||
"""login_ticket"""
|
||||
stuid: str = fields.TextField(default="")
|
||||
"""stuid"""
|
||||
stoken: str = fields.TextField(default="")
|
||||
"""stoken"""
|
||||
|
||||
_idx1 = db.Index("genshin_uid_idx1", "user_qq", "uid", unique=True)
|
||||
|
||||
@classmethod
|
||||
async def add_uid(cls, user_qq: int, uid: int):
|
||||
"""
|
||||
说明:
|
||||
添加一个uid
|
||||
参数:
|
||||
:param user_qq: 用户qq
|
||||
:param uid: 原神uid
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.uid == uid))
|
||||
user = await query.gino.first()
|
||||
if not user:
|
||||
await cls.create(
|
||||
user_qq=user_qq,
|
||||
uid=uid,
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_mys_id(cls, uid: int, mys_id: int) -> bool:
|
||||
"""
|
||||
说明:
|
||||
设置米游社id
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param mys_id: 米游社id
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(mys_id=mys_id).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_bind_group(cls, uid: int, bind_group) -> bool:
|
||||
"""
|
||||
说明:
|
||||
绑定group_id,除私聊外的提醒将在此群发送
|
||||
参数:
|
||||
:param uid: uid
|
||||
:param bind_group: 群号
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(bind_group=bind_group).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_bind_group(cls, uid: int) -> Optional[int]:
|
||||
"""
|
||||
说明:
|
||||
获取用户绑定的群聊
|
||||
参数:
|
||||
:param uid: uid
|
||||
"""
|
||||
user = await cls.query.where(cls.uid == uid).gino.first()
|
||||
if user:
|
||||
return user.bind_group
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def set_cookie(cls, uid: int, cookie: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
设置cookie
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param cookie: 米游社id
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(cookie=cookie).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_resin_remind(cls, uid: int, flag: bool) -> bool:
|
||||
"""
|
||||
说明:
|
||||
设置体力提醒
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param flag: 开关状态
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(resin_remind=flag).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_user_resin_recovery_time(cls, uid: int, date: datetime):
|
||||
"""
|
||||
说明:
|
||||
设置体力完成时间
|
||||
参数:
|
||||
:param uid: uid
|
||||
:param date: 提醒日期
|
||||
"""
|
||||
u = await cls.query.where(cls.uid == uid).gino.first()
|
||||
if u:
|
||||
await u.update(resin_recovery_time=date).apply()
|
||||
|
||||
@classmethod
|
||||
async def get_user_resin_recovery_time(cls, uid: int) -> Optional[datetime]:
|
||||
"""
|
||||
说明:
|
||||
获取体力完成时间
|
||||
参数:
|
||||
:param uid: uid
|
||||
"""
|
||||
u = await cls.query.where(cls.uid == uid).gino.first()
|
||||
if u:
|
||||
return u.resin_recovery_time.astimezone(pytz.timezone("Asia/Shanghai"))
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def get_all_resin_remind_user(cls) -> List["Genshin"]:
|
||||
"""
|
||||
说明:
|
||||
获取所有开启体力提醒的用户
|
||||
"""
|
||||
return await cls.query.where(cls.resin_remind == True).gino.all()
|
||||
|
||||
@classmethod
|
||||
async def clear_resin_remind_time(cls, uid: int) -> bool:
|
||||
"""
|
||||
说明:
|
||||
清空提醒日期
|
||||
参数:
|
||||
:param uid: uid
|
||||
"""
|
||||
user = await cls.query.where(cls.uid == uid).gino.first()
|
||||
if user:
|
||||
await user.update(resin_recovery_time=None).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_auto_sign(cls, uid: int, flag: bool) -> bool:
|
||||
"""
|
||||
说明:
|
||||
设置米游社/原神自动签到
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param flag: 开关状态
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(auto_sign=flag).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_all_auto_sign_user(cls) -> List["Genshin"]:
|
||||
"""
|
||||
说明:
|
||||
获取所有开启自动签到的用户
|
||||
"""
|
||||
return await cls.query.where(cls.auto_sign == True).gino.all()
|
||||
|
||||
@classmethod
|
||||
async def get_all_sign_user(cls) -> List["Genshin"]:
|
||||
"""
|
||||
说明:
|
||||
获取 原神 所有今日签到用户
|
||||
"""
|
||||
return await cls.query.where(cls.auto_sign_time != None).gino.all()
|
||||
|
||||
@classmethod
|
||||
async def clear_sign_time(cls, uid: int) -> bool:
|
||||
"""
|
||||
说明:
|
||||
清空签到日期
|
||||
参数:
|
||||
:param uid: uid
|
||||
"""
|
||||
user = await cls.query.where(cls.uid == uid).gino.first()
|
||||
if user:
|
||||
await user.update(auto_sign_time=None).apply()
|
||||
return True
|
||||
return False
|
||||
class Meta:
|
||||
table = "genshin"
|
||||
table_description = "原神数据表"
|
||||
unique_together = ("user_qq", "uid")
|
||||
|
||||
@classmethod
|
||||
async def random_sign_time(cls, uid: int) -> Optional[datetime]:
|
||||
@ -223,262 +53,43 @@ class Genshin(db.Model):
|
||||
说明:
|
||||
:param uid: uid
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
user = await cls.get_or_none(uid=uid)
|
||||
if user and user.cookie:
|
||||
if user.auto_sign_time and user.auto_sign_time.astimezone(
|
||||
pytz.timezone("Asia/Shanghai")
|
||||
pytz.timezone("Asia/Shanghai")
|
||||
) - timedelta(seconds=2) >= datetime.now(pytz.timezone("Asia/Shanghai")):
|
||||
return user.auto_sign_time.astimezone(pytz.timezone("Asia/Shanghai"))
|
||||
hours = int(str(datetime.now()).split()[1].split(":")[0])
|
||||
minutes = int(str(datetime.now()).split()[1].split(":")[1])
|
||||
date = (
|
||||
datetime.now()
|
||||
+ timedelta(days=1)
|
||||
- timedelta(hours=hours)
|
||||
- timedelta(minutes=minutes - 1)
|
||||
datetime.now()
|
||||
+ timedelta(days=1)
|
||||
- timedelta(hours=hours)
|
||||
- timedelta(minutes=minutes - 1)
|
||||
)
|
||||
random_hours = random.randint(0, 22)
|
||||
random_minutes = random.randint(1, 59)
|
||||
date += timedelta(hours=random_hours) + timedelta(minutes=random_minutes)
|
||||
await user.update(auto_sign_time=date).apply()
|
||||
user.auto_sign_time = date
|
||||
await user.save(update_fields=["auto_sign_time"])
|
||||
return date
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def get_query_cookie(cls, uid: int) -> Optional[str]:
|
||||
async def random_cookie(cls, uid: int) -> Optional[str]:
|
||||
"""
|
||||
说明:
|
||||
获取查询角色信息cookie
|
||||
随机获取查询角色信息cookie
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
"""
|
||||
# 查找用户今日是否已经查找过,防止重复
|
||||
query = cls.query.where(cls.today_query_uid.contains(str(uid)))
|
||||
x = await query.gino.first()
|
||||
if x:
|
||||
await cls._add_query_uid(uid, uid)
|
||||
return x.cookie
|
||||
for u in await cls.query.where(cls.cookie != "").order_by(db.func.random()).gino.all():
|
||||
if not u.today_query_uid or len(u.today_query_uid[:-1].split()) < 30:
|
||||
await cls._add_query_uid(uid, u.uid)
|
||||
return u.cookie
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def get_user_cookie(cls, uid: int, flag: bool = False) -> Optional[str]:
|
||||
"""
|
||||
说明:
|
||||
获取用户cookie
|
||||
参数:
|
||||
:param uid:原神uid
|
||||
:param flag:必须使用自己的cookie
|
||||
"""
|
||||
cookie = await cls._get_user_data(None, uid, "cookie")
|
||||
if not cookie and not flag:
|
||||
cookie = await cls.get_query_cookie(uid)
|
||||
return cookie
|
||||
|
||||
@classmethod
|
||||
async def get_user_by_qq(cls, user_qq: int) -> Optional["Genshin"]:
|
||||
"""
|
||||
说明:
|
||||
通过qq获取用户对象
|
||||
参数:
|
||||
:param user_qq: qq
|
||||
"""
|
||||
return await cls.query.where(cls.user_qq == user_qq).gino.first()
|
||||
|
||||
@classmethod
|
||||
async def get_user_by_uid(cls, uid: int) -> Optional["Genshin"]:
|
||||
"""
|
||||
说明:
|
||||
通过uid获取用户对象
|
||||
参数:
|
||||
:param uid: qq
|
||||
"""
|
||||
return await cls.query.where(cls.uid == uid).gino.first()
|
||||
|
||||
@classmethod
|
||||
async def get_user_uid(cls, user_qq: int) -> Optional[int]:
|
||||
"""
|
||||
说明:
|
||||
获取用户uid
|
||||
参数:
|
||||
:param user_qq:用户qq
|
||||
"""
|
||||
return await cls._get_user_data(user_qq, None, "uid")
|
||||
|
||||
@classmethod
|
||||
async def get_user_mys_id(cls, uid: int) -> Optional[int]:
|
||||
"""
|
||||
说嘛:
|
||||
获取用户米游社id
|
||||
参数:
|
||||
:param uid:原神id
|
||||
"""
|
||||
return await cls._get_user_data(None, uid, "mys_id")
|
||||
|
||||
@classmethod
|
||||
async def delete_user_cookie(cls, uid: int):
|
||||
"""
|
||||
说明:
|
||||
删除用户cookie
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
user = await cls.get_or_none(today_query_uid__contains=str(uid))
|
||||
if user:
|
||||
await user.update(cookie="").apply()
|
||||
|
||||
@classmethod
|
||||
async def delete_user(cls, user_qq: int):
|
||||
"""
|
||||
说明:
|
||||
删除用户数据
|
||||
参数:
|
||||
:param user_qq: 用户qq
|
||||
"""
|
||||
query = cls.query.where(cls.user_qq == user_qq).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if not user:
|
||||
return False
|
||||
await user.delete()
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
async def _add_query_uid(cls, uid: int, cookie_uid: int):
|
||||
"""
|
||||
说明:
|
||||
添加每日查询重复uid的cookie
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param cookie_uid: cookie的uid
|
||||
"""
|
||||
query = cls.query.where(cls.uid == cookie_uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
await user.update(today_query_uid=user.today_query_uid + f"{uid} ").apply()
|
||||
|
||||
@classmethod
|
||||
async def _get_user_data(
|
||||
cls, user_qq: Optional[int], uid: Optional[int], type_: str
|
||||
) -> Optional[Union[int, str]]:
|
||||
"""
|
||||
说明:
|
||||
获取用户数据
|
||||
参数:
|
||||
:param user_qq: 用户qq
|
||||
:param uid: uid
|
||||
:param type_: 数据类型
|
||||
"""
|
||||
if type_ == "uid":
|
||||
user = await cls.query.where(cls.user_qq == user_qq).gino.first()
|
||||
return user.uid if user else None
|
||||
user = await cls.query.where(cls.uid == uid).gino.first()
|
||||
if not user:
|
||||
return None
|
||||
if type_ == "mys_id":
|
||||
return user.mys_id
|
||||
elif type_ == "cookie":
|
||||
return user.cookie
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def reset_today_query_uid(cls):
|
||||
for u in await cls.query.with_for_update().gino.all():
|
||||
if u.today_query_uid:
|
||||
await u.update(today_query_uid="").apply()
|
||||
|
||||
@classmethod
|
||||
async def set_stuid(cls, uid: int, stuid: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
设置stuid
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param stuid: stuid
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(stuid=stuid).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_stoken(cls, uid: int, stoken: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
设置stoken
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param stoken: stoken
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(stoken=stoken).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_login_ticket(cls, uid: int, login_ticket: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
设置login_ticket
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
:param login_ticket: login_ticket
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid).with_for_update()
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
await user.update(login_ticket=login_ticket).apply()
|
||||
return True
|
||||
return False
|
||||
|
||||
# 获取login_ticket
|
||||
@classmethod
|
||||
async def get_login_ticket(cls, uid: int) -> Optional[str]:
|
||||
"""
|
||||
说明:
|
||||
获取login_ticket
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid)
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
return user.login_ticket
|
||||
return None
|
||||
|
||||
# 获取stuid
|
||||
@classmethod
|
||||
async def get_stuid(cls, uid: int) -> Optional[str]:
|
||||
"""
|
||||
说明:
|
||||
获取stuid
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid)
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
return user.stuid
|
||||
return None
|
||||
|
||||
# 获取stoken
|
||||
@classmethod
|
||||
async def get_stoken(cls, uid: int) -> Optional[str]:
|
||||
"""
|
||||
说明:
|
||||
获取stoken
|
||||
参数:
|
||||
:param uid: 原神uid
|
||||
"""
|
||||
query = cls.query.where(cls.uid == uid)
|
||||
user = await query.gino.first()
|
||||
if user:
|
||||
return user.stoken
|
||||
for user in await cls.filter(cookie__not="").annotate(rand=Random()).all():
|
||||
if not user.today_query_uid or len(user.today_query_uid[:-1].split()) < 30:
|
||||
user.today_query_uid = user.today_query_uid + f"{uid} "
|
||||
await user.save(update_fields=["today_query_uid"])
|
||||
return user.cookie
|
||||
return None
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
from configs.config import Config
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
import hashlib
|
||||
import json
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
|
||||
from configs.config import Config
|
||||
|
||||
|
||||
def _md5(text):
|
||||
@ -15,7 +16,7 @@ def _md5(text):
|
||||
def get_old_ds() -> str:
|
||||
n = Config.get_config("genshin", "n")
|
||||
i = str(int(time.time()))
|
||||
r = ''.join(random.sample(string.ascii_lowercase + string.digits, 6))
|
||||
r = "".join(random.sample(string.ascii_lowercase + string.digits, 6))
|
||||
c = _md5("salt=" + n + "&t=" + i + "&r=" + r)
|
||||
return i + "," + r + "," + c
|
||||
|
||||
@ -33,7 +34,7 @@ def get_ds(q: str = "", b: dict = None) -> str:
|
||||
|
||||
|
||||
def random_hex(length: int) -> str:
|
||||
result = hex(random.randint(0, 16 ** length)).replace("0x", "").upper()
|
||||
result = hex(random.randint(0, 16**length)).replace("0x", "").upper()
|
||||
if len(result) < length:
|
||||
result = "0" * (length - len(result)) + result
|
||||
return result
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
|
||||
from utils.utils import is_number
|
||||
from .._models import Genshin
|
||||
from services.log import logger
|
||||
from nonebot.params import CommandArg, Command
|
||||
from typing import Tuple
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import json
|
||||
from typing import Tuple
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import Command, CommandArg
|
||||
|
||||
from services.log import logger
|
||||
from utils.depends import OneCommand
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.utils import is_number
|
||||
|
||||
from .._models import Genshin
|
||||
|
||||
__zx_plugin_name__ = "原神绑定"
|
||||
__plugin_usage__ = """
|
||||
@ -43,82 +46,94 @@ unbind = on_command("原神解绑", priority=5, block=True)
|
||||
|
||||
web_Api = "https://api-takumi.mihoyo.com"
|
||||
bbs_Cookie_url = "https://webapi.account.mihoyo.com/Api/cookie_accountinfo_by_loginticket?login_ticket={}"
|
||||
bbs_Cookie_url2 = web_Api + "/auth/api/getMultiTokenByLoginTicket?login_ticket={}&token_types=3&uid={}"
|
||||
bbs_Cookie_url2 = (
|
||||
web_Api
|
||||
+ "/auth/api/getMultiTokenByLoginTicket?login_ticket={}&token_types=3&uid={}"
|
||||
)
|
||||
|
||||
|
||||
@bind.handle()
|
||||
async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
cmd = cmd[0]
|
||||
async def _(event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()):
|
||||
msg = arg.extract_plain_text().strip()
|
||||
user = await Genshin.get_or_none(user_qq=event.user_id)
|
||||
if cmd in ["原神绑定uid", "原神绑定米游社id"]:
|
||||
if not is_number(msg):
|
||||
await bind.finish("uid/id必须为纯数字!", at_senders=True)
|
||||
msg = int(msg)
|
||||
if cmd == "原神绑定uid":
|
||||
uid = await Genshin.get_user_uid(event.user_id)
|
||||
if uid:
|
||||
await bind.finish(f"您已绑定过uid:{uid},如果希望更换uid,请先发送原神解绑")
|
||||
flag = await Genshin.add_uid(event.user_id, msg)
|
||||
if not flag:
|
||||
if user:
|
||||
await bind.finish(f"您已绑定过uid:{user.uid},如果希望更换uid,请先发送原神解绑")
|
||||
if await Genshin.get_or_none(user_qq=event.user_id, uid=msg):
|
||||
await bind.finish("添加失败,该uid可能已存在...")
|
||||
user = await Genshin.create(user_qq=event.user_id, uid=msg)
|
||||
_x = f"已成功添加原神uid:{msg}"
|
||||
elif cmd == "原神绑定米游社id":
|
||||
uid = await Genshin.get_user_uid(event.user_id)
|
||||
if not uid:
|
||||
if not user:
|
||||
await bind.finish("请先绑定原神uid..")
|
||||
await Genshin.set_mys_id(uid, msg)
|
||||
_x = f"已成功为uid:{uid} 设置米游社id:{msg}"
|
||||
user.mys_id = int(msg)
|
||||
_x = f"已成功为uid:{user.uid} 设置米游社id:{msg}"
|
||||
else:
|
||||
if not msg:
|
||||
await bind.finish("""私聊发送!!
|
||||
await bind.finish(
|
||||
"""私聊发送!!
|
||||
1.以无痕模式打开浏览器(Edge请新建InPrivate窗口)
|
||||
2.打开http://bbs.mihoyo.com/ys/并登陆
|
||||
2.打开http://bbs.mihoyo.com/ys/ 并登陆
|
||||
3.登陆后打开http://user.mihoyo.com/进行登陆
|
||||
4.按下F12,打开控制台,输入以下命令:
|
||||
var cookie=document.cookie;var ask=confirm('Cookie:'+cookie+'\\n\\nDo you want to copy the cookie to the clipboard?');if(ask==true){copy(cookie);msg=cookie}else{msg='Cancel'}
|
||||
5.私聊发送:原神绑定cookie 刚刚复制的cookie""")
|
||||
5.私聊发送:原神绑定cookie 刚刚复制的cookie"""
|
||||
)
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
await bind.finish("请立即撤回你的消息并私聊发送!")
|
||||
uid = await Genshin.get_user_uid(event.user_id)
|
||||
if not uid:
|
||||
if not user:
|
||||
await bind.finish("请先绑定原神uid..")
|
||||
if msg.startswith('"') or msg.startswith("'"):
|
||||
msg = msg[1:]
|
||||
if msg.endswith('"') or msg.endswith("'"):
|
||||
msg = msg[:-1]
|
||||
await Genshin.set_cookie(uid, msg)
|
||||
cookie = msg
|
||||
# 用: 代替=, ,代替;
|
||||
cookie = '{"' + cookie.replace('=', '": "').replace("; ", '","') + '"}'
|
||||
print(cookie)
|
||||
cookie = '{"' + cookie.replace("=", '": "').replace("; ", '","') + '"}'
|
||||
# print(cookie)
|
||||
cookie_json = json.loads(cookie)
|
||||
print(cookie_json)
|
||||
if 'login_ticket' not in cookie_json:
|
||||
# print(cookie_json)
|
||||
if "login_ticket" not in cookie_json:
|
||||
await bind.finish("请发送正确完整的cookie!")
|
||||
login_ticket = cookie_json['login_ticket']
|
||||
user.cookie = str(msg)
|
||||
login_ticket = cookie_json["login_ticket"]
|
||||
# try:
|
||||
res = await AsyncHttpx.get(url=bbs_Cookie_url.format(login_ticket))
|
||||
res.encoding = "utf-8"
|
||||
data = json.loads(res.text)
|
||||
print(data)
|
||||
# print(data)
|
||||
if "成功" in data["data"]["msg"]:
|
||||
stuid = str(data["data"]["cookie_info"]["account_id"])
|
||||
res = await AsyncHttpx.get(url=bbs_Cookie_url2.format(
|
||||
login_ticket, stuid))
|
||||
res = await AsyncHttpx.get(url=bbs_Cookie_url2.format(login_ticket, stuid))
|
||||
res.encoding = "utf-8"
|
||||
data = json.loads(res.text)
|
||||
stoken = data["data"]["list"][0]["token"]
|
||||
# await Genshin.set_cookie(uid, cookie)
|
||||
await Genshin.set_stoken(uid, stoken)
|
||||
await Genshin.set_stuid(uid, stuid)
|
||||
await Genshin.set_login_ticket(uid, login_ticket)
|
||||
user.stoken = stoken
|
||||
user.stuid = stuid
|
||||
user.login_ticket = login_ticket
|
||||
# except Exception as e:
|
||||
# await bind.finish("获取登陆信息失败,请检查cookie是否正确或更新cookie")
|
||||
elif data["data"]["msg"] == "登录信息已失效,请重新登录":
|
||||
await bind.finish("登录信息失效,请重新获取最新cookie进行绑定")
|
||||
_x = f"已成功为uid:{uid} 设置cookie"
|
||||
_x = f"已成功为uid:{user.uid} 设置cookie"
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
await Genshin.set_bind_group(uid, event.group_id)
|
||||
user.bind_group = event.group_id
|
||||
if user:
|
||||
await user.save(
|
||||
update_fields=[
|
||||
"mys_id",
|
||||
"cookie",
|
||||
"stoken",
|
||||
"stuid",
|
||||
"login_ticket",
|
||||
"bind_group",
|
||||
]
|
||||
)
|
||||
await bind.send(_x)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, "
|
||||
@ -129,12 +144,10 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message
|
||||
|
||||
@unbind.handle()
|
||||
async def _(event: MessageEvent):
|
||||
if await Genshin.delete_user(event.user_id):
|
||||
await unbind.send("用户数据删除成功...")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f"原神解绑"
|
||||
)
|
||||
else:
|
||||
await unbind.send("该用户数据不存在..")
|
||||
await Genshin.filter(user_qq=event.user_id).delete()
|
||||
await unbind.send("用户数据删除成功...")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f"原神解绑"
|
||||
)
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
from .data_source import get_sign_reward_list, genshin_sign
|
||||
from ..mihoyobbs_sign import mihoyobbs_sign
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
|
||||
from nonebot import on_command
|
||||
from services.log import logger
|
||||
from .init_task import add_job, scheduler, _sign
|
||||
from apscheduler.jobstores.base import JobLookupError
|
||||
from .._models import Genshin
|
||||
from nonebot.params import Command
|
||||
from typing import Tuple
|
||||
|
||||
from apscheduler.jobstores.base import JobLookupError
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
from nonebot.params import Command
|
||||
|
||||
from services.log import logger
|
||||
from utils.depends import OneCommand
|
||||
|
||||
from .._models import Genshin
|
||||
from ..mihoyobbs_sign import mihoyobbs_sign
|
||||
from .data_source import genshin_sign, get_sign_reward_list
|
||||
from .init_task import _sign, add_job, scheduler
|
||||
|
||||
__zx_plugin_name__ = "原神自动签到"
|
||||
__plugin_usage__ = """
|
||||
@ -39,45 +42,46 @@ genshin_matcher = on_command(
|
||||
|
||||
|
||||
@genshin_matcher.handle()
|
||||
async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
|
||||
cmd = cmd[0]
|
||||
uid = await Genshin.get_user_uid(event.user_id)
|
||||
async def _(event: MessageEvent, cmd: str = OneCommand()):
|
||||
user = await Genshin.get_or_none(user_qq=event.user_id)
|
||||
if not user:
|
||||
await genshin_matcher.finish("请先绑定user.uid...")
|
||||
if cmd == "查看我的cookie":
|
||||
my_cookie = await Genshin.get_user_cookie(uid, True)
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
await genshin_matcher.finish("请私聊查看您的cookie!")
|
||||
await genshin_matcher.finish("您的cookie为" + my_cookie)
|
||||
if not uid or not await Genshin.get_user_cookie(uid, True):
|
||||
await genshin_matcher.finish("请先绑定uid和cookie!")
|
||||
# if "account_id" not in await Genshin.get_user_cookie(uid, True):
|
||||
await genshin_matcher.finish("您的cookie为" + user.cookie)
|
||||
if not user.uid or not user.cookie:
|
||||
await genshin_matcher.finish("请先绑定user.uid和cookie!")
|
||||
# if "account_id" not in await Genshin.get_user_cookie(user.uid, True):
|
||||
# await genshin_matcher.finish("请更新cookie!")
|
||||
if cmd == "原神我硬签":
|
||||
try:
|
||||
await genshin_matcher.send("正在进行签到...", at_sender=True)
|
||||
msg = await genshin_sign(uid)
|
||||
msg = await genshin_sign(user.uid)
|
||||
return_data = await mihoyobbs_sign(event.user_id)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, "
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{uid} 原神签到"
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{user.uid} 原神签到"
|
||||
)
|
||||
logger.info(msg)
|
||||
# 硬签,移除定时任务
|
||||
try:
|
||||
for i in range(3):
|
||||
scheduler.remove_job(f"genshin_auto_sign_{uid}_{event.user_id}_{i}",)
|
||||
scheduler.remove_job(
|
||||
f"genshin_auto_sign_{user.uid}_{event.user_id}_{i}",
|
||||
)
|
||||
except JobLookupError:
|
||||
pass
|
||||
u = await Genshin.get_user_by_uid(uid)
|
||||
if u and u.auto_sign:
|
||||
await u.clear_sign_time(uid)
|
||||
next_date = await Genshin.random_sign_time(uid)
|
||||
add_job(event.user_id, uid, next_date)
|
||||
if user.auto_sign:
|
||||
user.auto_sign_time = None
|
||||
next_date = await Genshin.random_sign_time(user.uid)
|
||||
add_job(event.user_id, user.uid, next_date)
|
||||
msg += f"\n{return_data}\n因开启自动签到\n下一次签到时间为:{next_date.replace(microsecond=0)}"
|
||||
except Exception as e:
|
||||
msg = "原神签到失败..请尝试检查cookie或报告至管理员!"
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, "
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{uid} 原神签到发生错误 "
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{user.uid} 原神签到发生错误 "
|
||||
f"{type(e)}:{e}"
|
||||
)
|
||||
msg = msg or "请检查cookie是否更新!"
|
||||
@ -85,13 +89,16 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
|
||||
else:
|
||||
for i in range(3):
|
||||
try:
|
||||
scheduler.remove_job(f"genshin_auto_sign_{uid}_{event.user_id}_{i}")
|
||||
scheduler.remove_job(
|
||||
f"genshin_auto_sign_{user.uid}_{event.user_id}_{i}"
|
||||
)
|
||||
except JobLookupError:
|
||||
pass
|
||||
if cmd[0] == "开":
|
||||
await Genshin.set_auto_sign(uid, True)
|
||||
next_date = await Genshin.random_sign_time(uid)
|
||||
add_job(event.user_id, uid, next_date)
|
||||
next_date = await Genshin.random_sign_time(user.uid)
|
||||
user.auto_sign = True
|
||||
user.auto_sign_time = next_date
|
||||
add_job(event.user_id, user.uid, next_date)
|
||||
await genshin_matcher.send(
|
||||
f"已开启原神自动签到!\n下一次签到时间为:{next_date.replace(microsecond=0)}",
|
||||
at_sender=True,
|
||||
@ -102,11 +109,13 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
|
||||
f" 开启原神自动签到"
|
||||
)
|
||||
else:
|
||||
await Genshin.set_auto_sign(uid, False)
|
||||
await Genshin.clear_sign_time(uid)
|
||||
user.auto_sign = False
|
||||
user.auto_sign_time = None
|
||||
await genshin_matcher.send(f"已关闭原神自动签到!", at_sender=True)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 关闭原神自动签到"
|
||||
)
|
||||
if user:
|
||||
await user.save(update_fields=["auto_sign_time", "auto_sign"])
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.config import Config
|
||||
from services.log import logger
|
||||
from ..mihoyobbs_sign.setting import *
|
||||
from .._models import Genshin
|
||||
from typing import Optional, Dict
|
||||
import hashlib
|
||||
import random
|
||||
import string
|
||||
import uuid
|
||||
import time
|
||||
import uuid
|
||||
from typing import Dict, Optional
|
||||
|
||||
from configs.config import Config
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
|
||||
from .._models import Genshin
|
||||
from ..mihoyobbs_sign.setting import *
|
||||
|
||||
|
||||
async def genshin_sign(uid: int) -> Optional[str]:
|
||||
@ -28,10 +30,10 @@ async def genshin_sign(uid: int) -> Optional[str]:
|
||||
sign_list = await get_sign_reward_list()
|
||||
get_reward = sign_list["data"]["awards"][
|
||||
int(sign_info["total_sign_day"]) - 1
|
||||
]["name"]
|
||||
]["name"]
|
||||
reward_num = sign_list["data"]["awards"][
|
||||
int(sign_info["total_sign_day"]) - 1
|
||||
]["cnt"]
|
||||
]["cnt"]
|
||||
get_im = f"本次签到获得:{get_reward}x{reward_num}"
|
||||
logger.info("get_im:" + get_im + "\nsign_info:" + str(sign_info))
|
||||
if status == "OK" and sign_info["is_sign"]:
|
||||
@ -64,7 +66,7 @@ def timestamp() -> int:
|
||||
|
||||
|
||||
def random_text(num: int) -> str:
|
||||
return ''.join(random.sample(string.ascii_lowercase + string.digits, num))
|
||||
return "".join(random.sample(string.ascii_lowercase + string.digits, num))
|
||||
|
||||
|
||||
def md5(text: str) -> str:
|
||||
@ -75,8 +77,7 @@ def md5(text: str) -> str:
|
||||
|
||||
# 生成一个device id
|
||||
def get_device_id(cookie) -> str:
|
||||
return str(uuid.uuid3(uuid.NAMESPACE_URL, cookie)).replace(
|
||||
'-', '').upper()
|
||||
return str(uuid.uuid3(uuid.NAMESPACE_URL, cookie)).replace("-", "").upper()
|
||||
|
||||
|
||||
async def _sign(uid: int, server_id: str = "cn_gf01") -> Optional[Dict[str, str]]:
|
||||
@ -88,18 +89,20 @@ async def _sign(uid: int, server_id: str = "cn_gf01") -> Optional[Dict[str, str]
|
||||
if str(uid)[0] == "5":
|
||||
server_id = "cn_qd01"
|
||||
try:
|
||||
cookie = await Genshin.get_user_cookie(uid, True)
|
||||
headers['DS'] = get_ds(web=True)
|
||||
headers['Referer'] = 'https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?bbs_auth_required=true' \
|
||||
f'&act_id={genshin_Act_id}&utm_source=bbs&utm_medium=mys&utm_campaign=icon'
|
||||
headers['Cookie'] = cookie
|
||||
headers['x-rpc-device_id'] = get_device_id(cookie)
|
||||
req = await AsyncHttpx.post(
|
||||
url=genshin_Signurl,
|
||||
headers=headers,
|
||||
json={"act_id": genshin_Act_id, "uid": uid, "region": server_id},
|
||||
)
|
||||
return req.json()
|
||||
if user := await Genshin.get_or_none(uid=uid):
|
||||
headers["DS"] = get_ds(web=True)
|
||||
headers["Referer"] = (
|
||||
"https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?bbs_auth_required=true"
|
||||
f"&act_id={genshin_Act_id}&utm_source=bbs&utm_medium=mys&utm_campaign=icon"
|
||||
)
|
||||
headers["Cookie"] = user.cookie
|
||||
headers["x-rpc-device_id"] = get_device_id(user.cookie)
|
||||
req = await AsyncHttpx.post(
|
||||
url=genshin_Signurl,
|
||||
headers=headers,
|
||||
json={"act_id": genshin_Act_id, "uid": uid, "region": server_id},
|
||||
)
|
||||
return req.json()
|
||||
except Exception as e:
|
||||
logger.error(f"米游社签到发生错误 UID:{uid} {type(e)}:{e}")
|
||||
return None
|
||||
@ -129,17 +132,22 @@ async def _get_sign_info(uid: int, server_id: str = "cn_gf01"):
|
||||
if str(uid)[0] == "5":
|
||||
server_id = "cn_qd01"
|
||||
try:
|
||||
req = await AsyncHttpx.get(
|
||||
url=f"https://api-takumi.mihoyo.com/event/bbs_sign_reward/info?act_id=e202009291139501®ion={server_id}&uid={uid}",
|
||||
headers={
|
||||
"x-rpc-app_version": str(Config.get_config("genshin", "mhyVersion")),
|
||||
"Cookie": await Genshin.get_user_cookie(int(uid), True),
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": str(Config.get_config("genshin", "client_type")),
|
||||
"Referer": "https://webstatic.mihoyo.com/",
|
||||
},
|
||||
)
|
||||
return req.json()
|
||||
if user := await Genshin.get_or_none(uid=uid):
|
||||
req = await AsyncHttpx.get(
|
||||
url=f"https://api-takumi.mihoyo.com/event/bbs_sign_reward/info?act_id=e202009291139501®ion={server_id}&uid={uid}",
|
||||
headers={
|
||||
"x-rpc-app_version": str(
|
||||
Config.get_config("genshin", "mhyVersion")
|
||||
),
|
||||
"Cookie": user.cookie,
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": str(
|
||||
Config.get_config("genshin", "client_type")
|
||||
),
|
||||
"Referer": "https://webstatic.mihoyo.com/",
|
||||
},
|
||||
)
|
||||
return req.json()
|
||||
except Exception as e:
|
||||
logger.error(f"获取签到信息发生错误 UID:{uid} {type(e)}:{e}")
|
||||
return None
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
from .data_source import genshin_sign
|
||||
from ..mihoyobbs_sign import mihoyobbs_sign
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from utils.message_builder import at
|
||||
from services.log import logger
|
||||
from utils.utils import scheduler, get_bot
|
||||
from apscheduler.jobstores.base import ConflictingIdError
|
||||
from .._models import Genshin
|
||||
from datetime import datetime, timedelta
|
||||
from nonebot import Driver
|
||||
import nonebot
|
||||
import random
|
||||
import pytz
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import nonebot
|
||||
import pytz
|
||||
from apscheduler.jobstores.base import ConflictingIdError
|
||||
from nonebot import Driver
|
||||
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from services.log import logger
|
||||
from utils.message_builder import at
|
||||
from utils.utils import get_bot, scheduler
|
||||
|
||||
from .._models import Genshin
|
||||
from ..mihoyobbs_sign import mihoyobbs_sign
|
||||
from .data_source import genshin_sign
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
@ -21,7 +23,7 @@ async def _():
|
||||
"""
|
||||
启动时分配定时任务
|
||||
"""
|
||||
g_list = await Genshin.get_all_auto_sign_user()
|
||||
g_list = await Genshin.filter(auto_sign=True).all()
|
||||
for u in g_list:
|
||||
if u.auto_sign_time:
|
||||
if date := await Genshin.random_sign_time(u.uid):
|
||||
@ -33,7 +35,8 @@ async def _():
|
||||
args=[u.user_qq, u.uid, 0],
|
||||
)
|
||||
logger.info(
|
||||
f"genshin_sign add_job:USER:{u.user_qq} UID:{u.uid} " f"{date} 原神自动签到"
|
||||
f"genshin_sign add_job:USER:{u.user_qq} UID:{u.uid} "
|
||||
f"{date} 原神自动签到"
|
||||
)
|
||||
|
||||
|
||||
@ -110,10 +113,12 @@ async def _sign(user_id: int, uid: int, count: int):
|
||||
await bot.send_private_msg(user_id=user_id, message=return_data)
|
||||
await bot.send_private_msg(user_id=user_id, message=msg)
|
||||
else:
|
||||
if not (group_id := await Genshin.get_bind_group(uid)):
|
||||
group_list = await GroupInfoUser.get_user_all_group(user_id)
|
||||
if group_list:
|
||||
group_id = group_list[0]
|
||||
await bot.send_group_msg(
|
||||
group_id=group_id, message=at(user_id) + msg
|
||||
)
|
||||
if user := await Genshin.get_or_none(uid=uid):
|
||||
group_id = user.bind_group
|
||||
if not group_id:
|
||||
if group_list := await GroupInfoUser.get_user_all_group(user_id):
|
||||
group_id = group_list[0]
|
||||
if group_id:
|
||||
await bot.send_group_msg(
|
||||
group_id=group_id, message=at(user_id) + msg
|
||||
)
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent
|
||||
from typing import Tuple
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent
|
||||
from nonebot.params import Command
|
||||
|
||||
from services.log import logger
|
||||
|
||||
# from .init_task import add_job, scheduler, _sign
|
||||
# from apscheduler.jobstores.base import JobLookupError
|
||||
from .._models import Genshin
|
||||
from nonebot.params import Command
|
||||
from typing import Tuple
|
||||
from .mihoyobbs import *
|
||||
|
||||
|
||||
__zx_plugin_name__ = "米游社自动签到"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
@ -28,12 +30,10 @@ __plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["原神签到"],
|
||||
"cmd": ["米游社签到"],
|
||||
}
|
||||
|
||||
mihoyobbs_matcher = on_command(
|
||||
"米游社签到", aliases={"米游社我硬签"}, priority=5, block=True
|
||||
)
|
||||
mihoyobbs_matcher = on_command("米游社签到", aliases={"米游社我硬签"}, priority=5, block=True)
|
||||
|
||||
|
||||
@mihoyobbs_matcher.handle()
|
||||
@ -47,24 +47,29 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
|
||||
|
||||
|
||||
async def mihoyobbs_sign(user_id):
|
||||
uid = await Genshin.get_user_uid(user_id)
|
||||
if not uid or not await Genshin.get_user_cookie(uid, True):
|
||||
user = await Genshin.get_or_none(user_qq=user_id)
|
||||
if not user or not user.uid or not user.cookie:
|
||||
await mihoyobbs_matcher.finish("请先绑定uid和cookie!", at_sender=True)
|
||||
stuid = await Genshin.get_stuid(uid)
|
||||
stoken = await Genshin.get_stoken(uid)
|
||||
cookie = await Genshin.get_user_cookie(uid)
|
||||
bbs = mihoyobbs.Mihoyobbs(stuid=stuid, stoken=stoken, cookie=cookie)
|
||||
bbs = mihoyobbs.Mihoyobbs(stuid=user.stuid, stoken=user.stoken, cookie=user.cookie)
|
||||
await bbs.init()
|
||||
return_data = ""
|
||||
if bbs.Task_do["bbs_Sign"] and bbs.Task_do["bbs_Read_posts"] and bbs.Task_do["bbs_Like_posts"] and \
|
||||
bbs.Task_do["bbs_Share"]:
|
||||
return_data += f"今天的米游社签到任务已经全部完成了!\n" \
|
||||
f"一共获得{mihoyobbs.today_have_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
|
||||
logger.info(f"今天已经全部完成了!一共获得{mihoyobbs.today_have_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币")
|
||||
if (
|
||||
bbs.Task_do["bbs_Sign"]
|
||||
and bbs.Task_do["bbs_Read_posts"]
|
||||
and bbs.Task_do["bbs_Like_posts"]
|
||||
and bbs.Task_do["bbs_Share"]
|
||||
):
|
||||
return_data += (
|
||||
f"今天的米游社签到任务已经全部完成了!\n"
|
||||
f"一共获得{mihoyobbs.today_have_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
|
||||
)
|
||||
logger.info(
|
||||
f"今天已经全部完成了!一共获得{mihoyobbs.today_have_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币"
|
||||
)
|
||||
else:
|
||||
i = 0
|
||||
print("开始签到")
|
||||
print(mihoyobbs.today_have_get_coins)
|
||||
# print("开始签到")
|
||||
# print(mihoyobbs.today_have_get_coins)
|
||||
while mihoyobbs.today_get_coins != 0 and i < 3:
|
||||
# if i > 0:
|
||||
await bbs.refresh_list()
|
||||
@ -74,8 +79,12 @@ async def mihoyobbs_sign(user_id):
|
||||
await bbs.share_post()
|
||||
await bbs.get_tasks_list()
|
||||
i += 1
|
||||
return_data += "\n" + f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币\n" \
|
||||
f"还能获得{mihoyobbs.today_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
|
||||
logger.info(f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币,"
|
||||
f"还能获得{mihoyobbs.today_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币")
|
||||
return_data += (
|
||||
"\n" + f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币\n"
|
||||
f"还能获得{mihoyobbs.today_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
|
||||
)
|
||||
logger.info(
|
||||
f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币,"
|
||||
f"还能获得{mihoyobbs.today_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币"
|
||||
)
|
||||
return return_data
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
|
||||
from services.log import logger
|
||||
from .data_source import get_user_memo, get_memo
|
||||
from .._models import Genshin
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
|
||||
from services.log import logger
|
||||
|
||||
from .._models import Genshin
|
||||
from .data_source import get_memo, get_user_memo
|
||||
|
||||
__zx_plugin_name__ = "原神便笺查询"
|
||||
__plugin_usage__ = """
|
||||
@ -27,30 +28,27 @@ __plugin_settings__ = {
|
||||
__plugin_block_limit__ = {}
|
||||
|
||||
|
||||
query_memo_matcher = on_command("原神便签查询", aliases={"原神便笺查询", "yss"}, priority=5, block=True)
|
||||
query_memo_matcher = on_command(
|
||||
"原神便签查询", aliases={"原神便笺查询", "yss"}, priority=5, block=True
|
||||
)
|
||||
|
||||
|
||||
@query_memo_matcher.handle()
|
||||
async def _(event: MessageEvent):
|
||||
uid = await Genshin.get_user_uid(event.user_id)
|
||||
if not uid or not await Genshin.get_user_cookie(uid, True):
|
||||
user = await Genshin.get_or_none(user_qq=event.user_id)
|
||||
if not user or not user.uid or not user.cookie:
|
||||
await query_memo_matcher.finish("请先绑定uid和cookie!")
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
uname = event.sender.card or event.sender.nickname
|
||||
else:
|
||||
uname = event.sender.nickname
|
||||
data = await get_user_memo(event.user_id, uid, uname)
|
||||
data = await get_user_memo(event.user_id, user.uid, uname)
|
||||
if data:
|
||||
await query_memo_matcher.send(data)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, "
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) "
|
||||
f"使用原神便笺查询 uid:{uid}"
|
||||
f"使用原神便笺查询 uid:{user.uid}"
|
||||
)
|
||||
else:
|
||||
await query_memo_matcher.send("未查询到数据...")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
from typing import Optional, Union
|
||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||
from configs.config import Config
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from services.log import logger
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.utils import get_user_avatar
|
||||
from utils.message_builder import image
|
||||
from .._utils import get_ds
|
||||
from .._models import Genshin
|
||||
from io import BytesIO
|
||||
from nonebot import Driver
|
||||
import asyncio
|
||||
import nonebot
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from io import BytesIO
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
import nonebot
|
||||
from nonebot import Driver
|
||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.message_builder import image
|
||||
from utils.utils import get_user_avatar
|
||||
|
||||
from .._models import Genshin
|
||||
from .._utils import get_ds
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
@ -26,10 +28,7 @@ memo_path.mkdir(exist_ok=True, parents=True)
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
for name, url in zip(
|
||||
[
|
||||
"resin.png", "task.png", "resin_discount.png", "chengehu.png",
|
||||
"zhibian.png"
|
||||
],
|
||||
["resin.png", "task.png", "resin_discount.png", "chengehu.png", "zhibian.png"],
|
||||
[
|
||||
"https://upload-bbs.mihoyo.com/upload/2021/09/29/8819732/54266243c7d15ba31690c8f5d63cc3c6_71491376413333325"
|
||||
"20.png?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,png",
|
||||
@ -45,8 +44,9 @@ async def _():
|
||||
logger.info(f"已下载原神便签资源 -> {file}...")
|
||||
|
||||
|
||||
async def get_user_memo(user_id: int, uid: int,
|
||||
uname: str) -> Optional[Union[str, MessageSegment]]:
|
||||
async def get_user_memo(
|
||||
user_id: int, uid: int, uname: str
|
||||
) -> Optional[Union[str, MessageSegment]]:
|
||||
uid = str(uid)
|
||||
if uid[0] in ["1", "2"]:
|
||||
server_id = "cn_gf01"
|
||||
@ -57,21 +57,17 @@ async def get_user_memo(user_id: int, uid: int,
|
||||
return await parse_data_and_draw(user_id, uid, server_id, uname)
|
||||
|
||||
|
||||
async def get_memo(uid: str, server_id: str) -> "Union[str, dict], int":
|
||||
async def get_memo(uid: str, server_id: str) -> Tuple[Union[str, dict], int]:
|
||||
try:
|
||||
req = await AsyncHttpx.get(
|
||||
url=
|
||||
f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/dailyNote?server={server_id}&role_id={uid}",
|
||||
url=f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/dailyNote?server={server_id}&role_id={uid}",
|
||||
headers={
|
||||
"DS": get_ds(f"role_id={uid}&server={server_id}"),
|
||||
"x-rpc-app_version": Config.get_config("genshin",
|
||||
"mhyVersion"),
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": Config.get_config("genshin",
|
||||
"client_type"),
|
||||
"x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": Config.get_config("genshin", "client_type"),
|
||||
"Referer": "https://webstatic.mihoyo.com/",
|
||||
"Cookie": await Genshin.get_user_cookie(int(uid))
|
||||
"Cookie": await Genshin.random_cookie(uid),
|
||||
},
|
||||
)
|
||||
data = req.json()
|
||||
@ -85,18 +81,13 @@ async def get_memo(uid: str, server_id: str) -> "Union[str, dict], int":
|
||||
return "发生了一些错误,请稍后再试", 998
|
||||
|
||||
|
||||
def create_border(image_name: str, content: str, notice_text: str,
|
||||
value: str) -> BuildImage:
|
||||
border = BuildImage(500,
|
||||
75,
|
||||
color="#E0D9D1",
|
||||
font="HYWenHei-85W.ttf",
|
||||
font_size=20)
|
||||
text_bk = BuildImage(350,
|
||||
75,
|
||||
color="#F5F1EB",
|
||||
font_size=23,
|
||||
font="HYWenHei-85W.ttf")
|
||||
def create_border(
|
||||
image_name: str, content: str, notice_text: str, value: str
|
||||
) -> BuildImage:
|
||||
border = BuildImage(500, 75, color="#E0D9D1", font="HYWenHei-85W.ttf", font_size=20)
|
||||
text_bk = BuildImage(
|
||||
350, 75, color="#F5F1EB", font_size=23, font="HYWenHei-85W.ttf"
|
||||
)
|
||||
_x = 70 if image_name == "resin.png" else 50
|
||||
_px = 10 if image_name == "resin.png" else 20
|
||||
text_bk.paste(
|
||||
@ -119,15 +110,14 @@ def create_border(image_name: str, content: str, notice_text: str,
|
||||
True,
|
||||
)
|
||||
font_width, _ = border.getsize(value)
|
||||
border.text((350 + 76 - int(font_width / 2), 0),
|
||||
value,
|
||||
center_type="by_height")
|
||||
border.text((350 + 76 - int(font_width / 2), 0), value, center_type="by_height")
|
||||
border.paste(text_bk, (2, 0), center_type="by_height")
|
||||
return border
|
||||
|
||||
|
||||
async def parse_data_and_draw(user_id: int, uid: str, server_id: str,
|
||||
uname: str) -> Union[str, MessageSegment]:
|
||||
async def parse_data_and_draw(
|
||||
user_id: int, uid: str, server_id: str, uname: str
|
||||
) -> Union[str, MessageSegment]:
|
||||
data, code = await get_memo(uid, server_id)
|
||||
if code != 200:
|
||||
return data
|
||||
@ -138,11 +128,13 @@ async def parse_data_and_draw(user_id: int, uid: str, server_id: str,
|
||||
if not role_avatar.exists():
|
||||
await AsyncHttpx.download_file(x["avatar_side_icon"], role_avatar)
|
||||
return await asyncio.get_event_loop().run_in_executor(
|
||||
None, _parse_data_and_draw, data, user_avatar, uid, uname)
|
||||
None, _parse_data_and_draw, data, user_avatar, uid, uname
|
||||
)
|
||||
|
||||
|
||||
def _parse_data_and_draw(data: dict, user_avatar: BytesIO, uid: int,
|
||||
uname: str) -> Union[str, MessageSegment]:
|
||||
def _parse_data_and_draw(
|
||||
data: dict, user_avatar: BytesIO, uid: int, uname: str
|
||||
) -> Union[str, MessageSegment]:
|
||||
current_resin = data["current_resin"] # 当前树脂
|
||||
max_resin = data["max_resin"] # 最大树脂
|
||||
resin_recovery_time = data["resin_recovery_time"] # 树脂全部回复时间
|
||||
@ -157,33 +149,24 @@ def _parse_data_and_draw(data: dict, user_avatar: BytesIO, uid: int,
|
||||
max_coin = data["max_home_coin"] # 最大宝钱
|
||||
coin_recovery_time = data["home_coin_recovery_time"] # 宝钱全部回复时间
|
||||
transformer_available = data["transformer"]["obtained"] # 参量质变仪可获取
|
||||
transformer_state = data["transformer"]["recovery_time"][
|
||||
"reached"] # 参量质变仪状态
|
||||
transformer_recovery_time = data["transformer"]["recovery_time"][
|
||||
"Day"] # 参量质变仪回复时间
|
||||
transformer_state = data["transformer"]["recovery_time"]["reached"] # 参量质变仪状态
|
||||
transformer_recovery_time = data["transformer"]["recovery_time"]["Day"] # 参量质变仪回复时间
|
||||
transformer_recovery_hour = data["transformer"]["recovery_time"][
|
||||
"Hour"] # 参量质变仪回复时间
|
||||
"Hour"
|
||||
] # 参量质变仪回复时间
|
||||
coin_minute, coin_second = divmod(int(coin_recovery_time), 60)
|
||||
coin_hour, coin_minute = divmod(coin_minute, 60)
|
||||
#print(data)
|
||||
# print(data)
|
||||
minute, second = divmod(int(resin_recovery_time), 60)
|
||||
hour, minute = divmod(minute, 60)
|
||||
|
||||
A = BuildImage(1030,
|
||||
570,
|
||||
color="#f1e9e1",
|
||||
font_size=15,
|
||||
font="HYWenHei-85W.ttf")
|
||||
A = BuildImage(1030, 570, color="#f1e9e1", font_size=15, font="HYWenHei-85W.ttf")
|
||||
A.text((10, 15), "原神便笺 | Create By ZhenXun", (198, 186, 177))
|
||||
ava = BuildImage(100, 100, background=user_avatar)
|
||||
ava.circle()
|
||||
A.paste(ava, (40, 40), True)
|
||||
A.paste(
|
||||
BuildImage(0,
|
||||
0,
|
||||
plain_text=uname,
|
||||
font_size=20,
|
||||
font="HYWenHei-85W.ttf"),
|
||||
BuildImage(0, 0, plain_text=uname, font_size=20, font="HYWenHei-85W.ttf"),
|
||||
(160, 62),
|
||||
True,
|
||||
)
|
||||
@ -225,40 +208,39 @@ def _parse_data_and_draw(data: dict, user_avatar: BytesIO, uid: int,
|
||||
"chengehu.png",
|
||||
"洞天财翁-洞天宝钱",
|
||||
"洞天财翁已达到存储上限"
|
||||
if current_coin == max_coin else f"{coin_hour}小时{coin_minute}分钟后存满",
|
||||
if current_coin == max_coin
|
||||
else f"{coin_hour}小时{coin_minute}分钟后存满",
|
||||
f"{current_coin}/{max_coin}",
|
||||
)
|
||||
A.paste(border, (10, 395))
|
||||
border = create_border(
|
||||
"zhibian.png",
|
||||
"参量质变仪",
|
||||
"不存在" if not transformer_available else
|
||||
"已准备完成 " if transformer_state else f"{transformer_recovery_hour}小时后可使用" if not transformer_recovery_time else f"{transformer_recovery_time}天后可使用",
|
||||
"不存在" if not transformer_available else
|
||||
"可使用" if transformer_state else "冷却中",
|
||||
"不存在"
|
||||
if not transformer_available
|
||||
else "已准备完成 "
|
||||
if transformer_state
|
||||
else f"{transformer_recovery_hour}小时后可使用"
|
||||
if not transformer_recovery_time
|
||||
else f"{transformer_recovery_time}天后可使用",
|
||||
"不存在" if not transformer_available else "可使用" if transformer_state else "冷却中",
|
||||
)
|
||||
A.paste(border, (10, 475))
|
||||
|
||||
expeditions_border = BuildImage(470,
|
||||
510,
|
||||
color="#E0D9D1",
|
||||
font="HYWenHei-85W.ttf",
|
||||
font_size=20)
|
||||
expeditions_text = BuildImage(466,
|
||||
506,
|
||||
color="#F5F1EB",
|
||||
font_size=23,
|
||||
font="HYWenHei-85W.ttf")
|
||||
expeditions_border = BuildImage(
|
||||
470, 510, color="#E0D9D1", font="HYWenHei-85W.ttf", font_size=20
|
||||
)
|
||||
expeditions_text = BuildImage(
|
||||
466, 506, color="#F5F1EB", font_size=23, font="HYWenHei-85W.ttf"
|
||||
)
|
||||
expeditions_text.text(
|
||||
(5, 5), f"探索派遣限制{current_expedition_num}/{max_expedition_num}",
|
||||
(100, 100, 98))
|
||||
(5, 5), f"探索派遣限制{current_expedition_num}/{max_expedition_num}", (100, 100, 98)
|
||||
)
|
||||
h = 45
|
||||
for x in expeditions:
|
||||
_bk = BuildImage(400,
|
||||
82,
|
||||
color="#ECE3D8",
|
||||
font="HYWenHei-85W.ttf",
|
||||
font_size=21)
|
||||
_bk = BuildImage(
|
||||
400, 82, color="#ECE3D8", font="HYWenHei-85W.ttf", font_size=21
|
||||
)
|
||||
file_name = x["avatar_side_icon"].split("_")[-1]
|
||||
role_avatar = memo_path / "role_avatar" / file_name
|
||||
_ava_img = BuildImage(75, 75, background=role_avatar)
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
from httpx import ConnectError
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
|
||||
from services.log import logger
|
||||
from .data_source import query_role_data
|
||||
from .._models import Genshin
|
||||
from utils.utils import is_number
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import CommandArg
|
||||
|
||||
from services.log import logger
|
||||
from utils.utils import is_number
|
||||
|
||||
from .._models import Genshin
|
||||
from .data_source import query_role_data
|
||||
|
||||
__zx_plugin_name__ = "原神玩家查询"
|
||||
__plugin_usage__ = """
|
||||
@ -29,7 +31,9 @@ __plugin_settings__ = {
|
||||
__plugin_block_limit__ = {}
|
||||
|
||||
|
||||
query_role_info_matcher = on_command("原神玩家查询", aliases={"原神玩家查找", "ys"}, priority=5, block=True)
|
||||
query_role_info_matcher = on_command(
|
||||
"原神玩家查询", aliases={"原神玩家查找", "ys"}, priority=5, block=True
|
||||
)
|
||||
|
||||
|
||||
@query_role_info_matcher.handle()
|
||||
@ -39,24 +43,25 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||
if not is_number(msg):
|
||||
await query_role_info_matcher.finish("查询uid必须为数字!")
|
||||
msg = int(msg)
|
||||
if not msg:
|
||||
uid = await Genshin.get_user_uid(event.user_id)
|
||||
uid = None
|
||||
user = await Genshin.get_or_none(user_qq=event.user_id)
|
||||
if not msg and user:
|
||||
uid = user.uid
|
||||
else:
|
||||
uid = msg
|
||||
if not uid: # or not await Genshin.get_user_cookie(uid):
|
||||
await query_role_info_matcher.finish("请先绑定uid和cookie!")
|
||||
nickname = event.sender.card or event.sender.nickname
|
||||
mys_id = await Genshin.get_user_mys_id(uid)
|
||||
data = await query_role_data(event.user_id, uid, mys_id, nickname)
|
||||
if data:
|
||||
await query_role_info_matcher.send(data)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, "
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 使用原神玩家查询 uid:{uid}"
|
||||
)
|
||||
else:
|
||||
await query_role_info_matcher.send("查询失败..")
|
||||
|
||||
|
||||
|
||||
|
||||
mys_id = user.mys_id if user else None
|
||||
try:
|
||||
data = await query_role_data(event.user_id, uid, mys_id, nickname)
|
||||
if data:
|
||||
await query_role_info_matcher.send(data)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, "
|
||||
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 使用原神玩家查询 uid:{uid}"
|
||||
)
|
||||
else:
|
||||
await query_role_info_matcher.send("查询失败..")
|
||||
except ConnectError:
|
||||
await query_role_info_matcher.send("网络出小差啦~")
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
from typing import Optional, List, Dict, Union
|
||||
from .draw_image import init_image, get_genshin_image
|
||||
from typing import Dict, List, Optional, Tuple, Union
|
||||
|
||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||
from .._utils import get_ds, element_mastery
|
||||
|
||||
from configs.config import Config
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.config import Config
|
||||
|
||||
from .._models import Genshin
|
||||
from .._utils import element_mastery, get_ds
|
||||
from .draw_image import get_genshin_image, init_image
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@ -96,66 +99,66 @@ b=body q=query
|
||||
"""
|
||||
|
||||
|
||||
async def get_info(uid_: str, server_id: str) -> "Optional[Union[dict, str]], int":
|
||||
try:
|
||||
req = await AsyncHttpx.get(
|
||||
url=f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/index?server={server_id}&role_id={uid_}",
|
||||
headers={
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"DS": get_ds(f"role_id={uid_}&server={server_id}"),
|
||||
"Origin": "https://webstatic.mihoyo.com",
|
||||
"x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
|
||||
"User-Agent": "Mozilla/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 miHoYoBBS/2.2.0",
|
||||
"x-rpc-client_type": Config.get_config("genshin", "client_type"),
|
||||
"Referer": "https://webstatic.mihoyo.com/app/community-game-records/index.html?v=6",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,en-US;q=0.8",
|
||||
"X-Requested-With": "com.mihoyo.hyperion",
|
||||
"Cookie": await Genshin.get_user_cookie(int(uid_))
|
||||
},
|
||||
)
|
||||
data = req.json()
|
||||
if data["message"] == "OK":
|
||||
return data["data"], 200
|
||||
return data["message"], 999
|
||||
except Exception as e:
|
||||
logger.error(f"访问失败,请重试! {type(e)}: {e}")
|
||||
async def get_info(uid_: str, server_id: str) -> Tuple[Optional[Union[dict, str]], int]:
|
||||
# try:
|
||||
req = await AsyncHttpx.get(
|
||||
url=f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/index?server={server_id}&role_id={uid_}",
|
||||
headers={
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"DS": get_ds(f"role_id={uid_}&server={server_id}"),
|
||||
"Origin": "https://webstatic.mihoyo.com",
|
||||
"x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
|
||||
"User-Agent": "Mozilla/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 miHoYoBBS/2.2.0",
|
||||
"x-rpc-client_type": Config.get_config("genshin", "client_type"),
|
||||
"Referer": "https://webstatic.mihoyo.com/app/community-game-records/index.html?v=6",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,en-US;q=0.8",
|
||||
"X-Requested-With": "com.mihoyo.hyperion",
|
||||
"Cookie": await Genshin.random_cookie(uid_),
|
||||
},
|
||||
)
|
||||
data = req.json()
|
||||
if data["message"] == "OK":
|
||||
return data["data"], 200
|
||||
return data["message"], 999
|
||||
# except Exception as e:
|
||||
# logger.error(f"访问失败,请重试! {type(e)}: {e}")
|
||||
return None, -1
|
||||
|
||||
|
||||
async def get_character(
|
||||
uid: str, character_ids: List[str], server_id="cn_gf01"
|
||||
) -> Optional[dict]:
|
||||
try:
|
||||
req = await AsyncHttpx.post(
|
||||
url="https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/character",
|
||||
headers={
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"DS": get_ds(
|
||||
"",
|
||||
{
|
||||
"character_ids": character_ids,
|
||||
"role_id": uid,
|
||||
"server": server_id,
|
||||
},
|
||||
),
|
||||
"Origin": "https://webstatic.mihoyo.com",
|
||||
"Cookie": await Genshin.get_user_cookie(int(uid)),
|
||||
"x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": "5",
|
||||
"Referer": "https://webstatic.mihoyo.com/",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,en-US;q=0.8",
|
||||
"X-Requested-With": "com.mihoyo.hyperion",
|
||||
},
|
||||
json={"character_ids": character_ids, "role_id": uid, "server": server_id},
|
||||
)
|
||||
data = req.json()
|
||||
if data["message"] == "OK":
|
||||
return data["data"]
|
||||
except Exception as e:
|
||||
logger.error(f"访问失败,请重试! {type(e)}: {e}")
|
||||
# try:
|
||||
req = await AsyncHttpx.post(
|
||||
url="https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/character",
|
||||
headers={
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"DS": get_ds(
|
||||
"",
|
||||
{
|
||||
"character_ids": character_ids,
|
||||
"role_id": uid,
|
||||
"server": server_id,
|
||||
},
|
||||
),
|
||||
"Origin": "https://webstatic.mihoyo.com",
|
||||
"Cookie": await Genshin.random_cookie(uid),
|
||||
"x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": "5",
|
||||
"Referer": "https://webstatic.mihoyo.com/",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,en-US;q=0.8",
|
||||
"X-Requested-With": "com.mihoyo.hyperion",
|
||||
},
|
||||
json={"character_ids": character_ids, "role_id": uid, "server": server_id},
|
||||
)
|
||||
data = req.json()
|
||||
if data["message"] == "OK":
|
||||
return data["data"]
|
||||
# except Exception as e:
|
||||
# logger.error(f"访问失败,请重试! {type(e)}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
@ -205,7 +208,7 @@ def parsed_data(
|
||||
"image": world["icon"],
|
||||
"name": world["name"],
|
||||
"offerings": world["offerings"],
|
||||
"icon": world["icon"]
|
||||
"icon": world["icon"],
|
||||
}
|
||||
world_data_dict[world["name"]] = _x
|
||||
home_data_list = []
|
||||
@ -231,21 +234,21 @@ async def get_mys_data(uid: str, mys_id: Optional[str]) -> Optional[List[Dict]]:
|
||||
:param mys_id: 米游社id
|
||||
"""
|
||||
if mys_id:
|
||||
try:
|
||||
req = await AsyncHttpx.get(
|
||||
url=f"https://api-takumi-record.mihoyo.com/game_record/card/wapi/getGameRecordCard?uid={mys_id}",
|
||||
headers={
|
||||
"DS": get_ds(f"uid={mys_id}"),
|
||||
"x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": "5",
|
||||
"Referer": "https://webstatic.mihoyo.com/",
|
||||
"Cookie": await Genshin.get_user_cookie(int(uid))
|
||||
},
|
||||
)
|
||||
data = req.json()
|
||||
if data["message"] == "OK":
|
||||
return data["data"]["list"]
|
||||
except Exception as e:
|
||||
logger.error(f"访问失败,请重试! {type(e)}: {e}")
|
||||
# try:
|
||||
req = await AsyncHttpx.get(
|
||||
url=f"https://api-takumi-record.mihoyo.com/game_record/card/wapi/getGameRecordCard?uid={mys_id}",
|
||||
headers={
|
||||
"DS": get_ds(f"uid={mys_id}"),
|
||||
"x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
|
||||
"x-rpc-client_type": "5",
|
||||
"Referer": "https://webstatic.mihoyo.com/",
|
||||
"Cookie": await Genshin.random_cookie(uid),
|
||||
},
|
||||
)
|
||||
data = req.json()
|
||||
if data["message"] == "OK":
|
||||
return data["data"]["list"]
|
||||
# except Exception as e:
|
||||
# logger.error(f"访问失败,请重试! {type(e)}: {e}")
|
||||
return None
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from utils.utils import scheduler
|
||||
from .._models import Genshin
|
||||
from services.log import logger
|
||||
from utils.utils import scheduler
|
||||
|
||||
from .._models import Genshin
|
||||
|
||||
|
||||
@scheduler.scheduled_job(
|
||||
@ -10,7 +11,7 @@ from services.log import logger
|
||||
)
|
||||
async def _():
|
||||
try:
|
||||
await Genshin.reset_today_query_uid()
|
||||
await Genshin.all().update(today_query_uid="")
|
||||
logger.warning(f"重置原神查询记录成功..")
|
||||
except Exception as e:
|
||||
logger.error(f"重置原神查询记录失败. {type(e)}:{e}")
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
|
||||
from apscheduler.jobstores.base import JobLookupError
|
||||
from services.log import logger
|
||||
from .init_task import scheduler, add_job
|
||||
from .._models import Genshin
|
||||
from nonebot.params import Command
|
||||
from typing import Tuple
|
||||
|
||||
from apscheduler.jobstores.base import JobLookupError
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
from nonebot.params import Command
|
||||
|
||||
from services.log import logger
|
||||
from utils.depends import OneCommand
|
||||
|
||||
from .._models import Genshin
|
||||
from .init_task import add_job, scheduler
|
||||
|
||||
__zx_plugin_name__ = "原神树脂提醒"
|
||||
__plugin_usage__ = """
|
||||
@ -33,31 +36,32 @@ __plugin_configs__ = {
|
||||
"AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND": {
|
||||
"value": True,
|
||||
"help": "当请求连续三次失败时,关闭用户的树脂提醒",
|
||||
"default_value": True
|
||||
"default_value": True,
|
||||
},
|
||||
"CUSTOM_RESIN_OVERFLOW_REMIND": {
|
||||
"value": 20,
|
||||
"help": "自定义树脂溢出指定数量时的提醒,空值是为关闭",
|
||||
"default_value": None
|
||||
}
|
||||
"default_value": None,
|
||||
},
|
||||
}
|
||||
|
||||
resin_remind = on_command("开原神树脂提醒", aliases={"关原神树脂提醒"}, priority=5, block=True)
|
||||
|
||||
|
||||
@resin_remind.handle()
|
||||
async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
|
||||
cmd = cmd[0]
|
||||
uid = await Genshin.get_user_uid(event.user_id)
|
||||
if not uid or not await Genshin.get_user_cookie(uid, True):
|
||||
async def _(event: MessageEvent, cmd: str = OneCommand()):
|
||||
user = await Genshin.get_or_none(user_qq=event.user_id)
|
||||
if not user or not user.uid or not user.cookie:
|
||||
await resin_remind.finish("请先绑定uid和cookie!")
|
||||
try:
|
||||
scheduler.remove_job(f"genshin_resin_remind_{uid}_{event.user_id}")
|
||||
scheduler.remove_job(f"genshin_resin_remind_{user.uid}_{event.user_id}")
|
||||
except JobLookupError:
|
||||
pass
|
||||
if cmd[0] == "开":
|
||||
await Genshin.set_resin_remind(uid, True)
|
||||
add_job(event.user_id, uid)
|
||||
if user.resin_remind:
|
||||
await resin_remind.finish("原神树脂提醒已经是开启状态,请勿重复开启!", at_sender=True)
|
||||
user.resin_remind = True
|
||||
add_job(event.user_id, user.uid)
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
@ -65,12 +69,15 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
|
||||
)
|
||||
await resin_remind.send("开启原神树脂提醒成功!", at_sender=True)
|
||||
else:
|
||||
await Genshin.set_resin_remind(uid, False)
|
||||
await Genshin.clear_resin_remind_time(uid)
|
||||
if not user.resin_remind:
|
||||
await resin_remind.finish("原神树脂提醒已经是开启状态,请勿重复开启!", at_sender=True)
|
||||
user.resin_remind = False
|
||||
user.resin_recovery_time = None
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 关闭原神体力提醒"
|
||||
)
|
||||
await resin_remind.send("已关闭原神树脂提醒..", at_sender=True)
|
||||
|
||||
if user:
|
||||
await user.save(update_fields=["resin_remind", "resin_recovery_time"])
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
|
||||
from utils.utils import get_bot, scheduler
|
||||
from utils.message_builder import at
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from apscheduler.jobstores.base import ConflictingIdError
|
||||
from nonebot import Driver
|
||||
from .._models import Genshin
|
||||
from datetime import datetime, timedelta
|
||||
from apscheduler.jobstores.base import JobLookupError
|
||||
from services.log import logger
|
||||
from nonebot.plugin import require
|
||||
from configs.config import Config
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import nonebot
|
||||
import pytz
|
||||
from apscheduler.jobstores.base import ConflictingIdError, JobLookupError
|
||||
from nonebot import Driver
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
from nonebot.plugin import require
|
||||
|
||||
from configs.config import Config
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from services.log import logger
|
||||
from utils.message_builder import at
|
||||
from utils.utils import get_bot, scheduler
|
||||
|
||||
from .._models import Genshin
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
@ -23,7 +23,6 @@ require("query_memo")
|
||||
|
||||
from ..query_memo import get_memo
|
||||
|
||||
|
||||
global_map = {}
|
||||
|
||||
|
||||
@ -80,12 +79,13 @@ async def _():
|
||||
"""
|
||||
启动时分配定时任务
|
||||
"""
|
||||
g_list = await Genshin.get_all_resin_remind_user()
|
||||
g_list = await Genshin.filter(resin_remind=True).all()
|
||||
update_list = []
|
||||
date = datetime.now(pytz.timezone("Asia/Shanghai")) + timedelta(seconds=30)
|
||||
for u in g_list:
|
||||
if u.resin_remind:
|
||||
if u.resin_recovery_time:
|
||||
if await Genshin.get_user_resin_recovery_time(u.uid) > datetime.now(
|
||||
if u.resin_recovery_time and u.resin_recovery_time > datetime.now(
|
||||
pytz.timezone("Asia/Shanghai")
|
||||
):
|
||||
# date = await Genshin.get_user_resin_recovery_time(u.uid) # 不能要,因为可能在这期间用户使用了树脂
|
||||
@ -101,7 +101,8 @@ async def _():
|
||||
f"genshin_resin_remind add_job:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
|
||||
)
|
||||
else:
|
||||
await Genshin.clear_resin_remind_time(u.uid)
|
||||
u.resin_recovery_time = None
|
||||
update_list.append(u)
|
||||
add_job(u.user_qq, u.uid)
|
||||
logger.info(
|
||||
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
|
||||
@ -111,6 +112,8 @@ async def _():
|
||||
logger.info(
|
||||
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
|
||||
)
|
||||
if update_list:
|
||||
await Genshin.bulk_update(update_list, ["resin_recovery_time"])
|
||||
|
||||
|
||||
def add_job(user_id: int, uid: int):
|
||||
@ -133,6 +136,7 @@ def add_job(user_id: int, uid: int):
|
||||
|
||||
|
||||
async def _remind(user_id: int, uid: str):
|
||||
user = await Genshin.get_or_none(user_qq=user_id, uid=int(uid))
|
||||
uid = str(uid)
|
||||
if uid[0] in ["1", "2"]:
|
||||
server_id = "cn_gf01"
|
||||
@ -158,7 +162,9 @@ async def _remind(user_id: int, uid: str):
|
||||
elif max_resin - 20 <= current_resin < max_resin:
|
||||
next_time = now + timedelta(minutes=(max_resin - current_resin) * 8)
|
||||
elif current_resin == max_resin:
|
||||
custom_overflow_resin = Config.get_config("resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND")
|
||||
custom_overflow_resin = Config.get_config(
|
||||
"resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND"
|
||||
)
|
||||
if user_manager.is_overflow(uid) and custom_overflow_resin:
|
||||
next_time = now + timedelta(minutes=custom_overflow_resin * 8)
|
||||
user_manager.add_overflow(uid)
|
||||
@ -178,28 +184,35 @@ async def _remind(user_id: int, uid: str):
|
||||
message=msg,
|
||||
)
|
||||
else:
|
||||
group_id = await Genshin.get_bind_group(int(uid))
|
||||
if not group_id:
|
||||
group_list = await GroupInfoUser.get_user_all_group(user_id)
|
||||
if group_list:
|
||||
group_id = group_list[0]
|
||||
try:
|
||||
await bot.send_group_msg(
|
||||
group_id=group_id,
|
||||
message=at(user_id) + msg
|
||||
)
|
||||
except ActionFailed as e:
|
||||
logger.error(f"树脂提醒推送发生错误 {type(e)}:{e}")
|
||||
if user:
|
||||
group_id = user.bind_group
|
||||
if not group_id:
|
||||
if group_list := await GroupInfoUser.get_user_all_group(
|
||||
user_id
|
||||
):
|
||||
group_id = group_list[0]
|
||||
try:
|
||||
await bot.send_group_msg(
|
||||
group_id=group_id, message=at(user_id) + msg
|
||||
)
|
||||
except ActionFailed as e:
|
||||
logger.error(f"树脂提醒推送发生错误 {type(e)}:{e}")
|
||||
|
||||
if not next_time:
|
||||
if user_manager.check(uid) and Config.get_config("resin_remind", "AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND"):
|
||||
await Genshin.set_resin_remind(int(uid), False)
|
||||
await Genshin.clear_resin_remind_time(int(uid))
|
||||
if user_manager.check(uid) and Config.get_config(
|
||||
"resin_remind", "AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND"
|
||||
):
|
||||
if user:
|
||||
user.resin_remind = False
|
||||
user.resin_recovery_time = None
|
||||
await user.save(update_fields=["resin_recovery_time", "resin_remind"])
|
||||
next_time = now + timedelta(minutes=(20 + random.randint(5, 20)) * 8)
|
||||
user_manager.add_error_count(uid)
|
||||
else:
|
||||
user_manager.remove_error_count(uid)
|
||||
await Genshin.set_user_resin_recovery_time(int(uid), next_time)
|
||||
if user:
|
||||
user.resin_recovery_time = next_time
|
||||
await user.save(update_fields=["resin_recovery_time", "resin_remind"])
|
||||
scheduler.add_job(
|
||||
_remind,
|
||||
"date",
|
||||
@ -208,6 +221,5 @@ async def _remind(user_id: int, uid: str):
|
||||
args=[user_id, uid],
|
||||
)
|
||||
logger.info(
|
||||
f"genshin_resin_remind add_job:USER:{user_id} UID:{uid} "
|
||||
f"{next_time} 原神树脂提醒"
|
||||
)
|
||||
f"genshin_resin_remind add_job:USER:{user_id} UID:{uid} " f"{next_time} 原神树脂提醒"
|
||||
)
|
||||
|
||||
@ -29,7 +29,6 @@ from nonebot.params import CommandArg
|
||||
import random
|
||||
import time
|
||||
|
||||
|
||||
__zx_plugin_name__ = "金币红包"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
@ -64,11 +63,16 @@ __plugin_settings__ = {
|
||||
}
|
||||
__plugin_resources__ = {"prts": IMAGE_PATH}
|
||||
|
||||
|
||||
async def rule(event: GroupMessageEvent) -> bool:
|
||||
return check_on_gold_red(event)
|
||||
|
||||
|
||||
gold_redbag = on_command(
|
||||
"塞红包", aliases={"金币红包"}, priority=5, block=True, permission=GROUP
|
||||
)
|
||||
|
||||
open_ = on_command("开", aliases={"抢"}, priority=5, block=True, permission=GROUP)
|
||||
open_ = on_command("开", aliases={"抢"}, priority=5, block=True, permission=GROUP, rule=rule)
|
||||
|
||||
poke_ = on_notice(priority=6, block=False)
|
||||
|
||||
@ -85,27 +89,11 @@ festive_redbag_data = {}
|
||||
|
||||
# 阻断其他poke
|
||||
@run_preprocessor
|
||||
async def _(matcher: Matcher, event: PokeNotifyEvent):
|
||||
async def _(matcher: Matcher, event: PokeNotifyEvent, ):
|
||||
try:
|
||||
if matcher.type == "notice" and event.self_id == event.target_id:
|
||||
flag1 = True
|
||||
flag2 = True
|
||||
try:
|
||||
if festive_redbag_data[event.group_id]["user_id"]:
|
||||
if (
|
||||
event.user_id
|
||||
in festive_redbag_data[event.group_id]["open_user"]
|
||||
):
|
||||
flag1 = False
|
||||
except KeyError:
|
||||
flag1 = False
|
||||
try:
|
||||
if redbag_data[event.group_id]["user_id"]:
|
||||
if event.user_id in redbag_data[event.group_id]["open_user"]:
|
||||
flag2 = False
|
||||
except KeyError:
|
||||
flag2 = False
|
||||
if flag1 or flag2:
|
||||
flag = check_on_gold_red(event)
|
||||
if flag:
|
||||
if matcher.plugin_name == "poke":
|
||||
raise IgnoredException("目前正在抢红包...")
|
||||
else:
|
||||
@ -121,8 +109,8 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
try:
|
||||
if time.time() - redbag_data[event.group_id]["time"] > 60:
|
||||
amount = (
|
||||
redbag_data[event.group_id]["amount"]
|
||||
- redbag_data[event.group_id]["open_amount"]
|
||||
redbag_data[event.group_id]["amount"]
|
||||
- redbag_data[event.group_id]["open_amount"]
|
||||
)
|
||||
await return_gold(redbag_data[event.group_id]["user_id"], event.group_id, amount)
|
||||
await gold_redbag.send(
|
||||
@ -185,43 +173,21 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
msg = arg.extract_plain_text().strip()
|
||||
msg = (
|
||||
msg.replace("!", "")
|
||||
.replace("!", "")
|
||||
.replace(",", "")
|
||||
.replace(",", "")
|
||||
.replace(".", "")
|
||||
.replace("。", "")
|
||||
.replace("!", "")
|
||||
.replace(",", "")
|
||||
.replace(",", "")
|
||||
.replace(".", "")
|
||||
.replace("。", "")
|
||||
)
|
||||
if msg:
|
||||
if "红包" not in msg:
|
||||
return
|
||||
flag1 = True
|
||||
flag2 = True
|
||||
open_flag1 = True
|
||||
open_flag2 = True
|
||||
try:
|
||||
if festive_redbag_data[event.group_id]["user_id"]:
|
||||
if event.user_id in festive_redbag_data[event.group_id]["open_user"]:
|
||||
open_flag1 = False
|
||||
except KeyError:
|
||||
open_flag1 = False
|
||||
flag1 = False
|
||||
try:
|
||||
if redbag_data[event.group_id]["user_id"]:
|
||||
if event.user_id in redbag_data[event.group_id]["open_user"]:
|
||||
open_flag2 = False
|
||||
except KeyError:
|
||||
flag2 = False
|
||||
if not flag1 and not flag2:
|
||||
await open_.finish("目前没有红包可以开...", at_sender=True)
|
||||
if open_flag1 or open_flag2:
|
||||
try:
|
||||
await open_.send(
|
||||
image(b64=await get_redbag_img(event.user_id, event.group_id)),
|
||||
at_sender=True,
|
||||
await open_.send(
|
||||
image(b64=await get_redbag_img(event.user_id, event.group_id)),
|
||||
at_sender=True,
|
||||
)
|
||||
except KeyError:
|
||||
await open_.finish("真贪心,明明已经开过这个红包了的说...", at_sender=True)
|
||||
else:
|
||||
except KeyError:
|
||||
await open_.finish("真贪心,明明已经开过这个红包了的说...", at_sender=True)
|
||||
|
||||
|
||||
@ -229,19 +195,8 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
async def _poke_(event: PokeNotifyEvent):
|
||||
global redbag_data, festive_redbag_data
|
||||
if event.self_id == event.target_id:
|
||||
flag1 = True
|
||||
flag2 = True
|
||||
try:
|
||||
if event.user_id in festive_redbag_data[event.group_id]["open_user"]:
|
||||
flag1 = False
|
||||
except KeyError:
|
||||
flag1 = False
|
||||
try:
|
||||
if event.user_id in redbag_data[event.group_id]["open_user"]:
|
||||
flag2 = False
|
||||
except KeyError:
|
||||
flag2 = False
|
||||
if not flag1 and not flag2:
|
||||
flag = check_on_gold_red(event)
|
||||
if not flag:
|
||||
return
|
||||
await poke_.send(
|
||||
image(b64=await get_redbag_img(event.user_id, event.group_id)),
|
||||
@ -331,7 +286,7 @@ async def _(bot: Bot, arg: Message = CommandArg()):
|
||||
await bot.send_group_msg(
|
||||
group_id=g,
|
||||
message=f"{NICKNAME}发起了金币红包\n金额:{amount}\n数量:{num}\n"
|
||||
+ image(
|
||||
+ image(
|
||||
b64=await generate_send_redbag_pic(int(bot.self_id), greetings)
|
||||
),
|
||||
)
|
||||
@ -342,13 +297,13 @@ async def _(bot: Bot, arg: Message = CommandArg()):
|
||||
|
||||
# 红包数据初始化
|
||||
def init_redbag(
|
||||
user_id: int,
|
||||
group_id: int,
|
||||
nickname: str,
|
||||
amount: int,
|
||||
num: int,
|
||||
bot_self_id: int,
|
||||
mode: int = 0,
|
||||
user_id: int,
|
||||
group_id: int,
|
||||
nickname: str,
|
||||
amount: int,
|
||||
num: int,
|
||||
bot_self_id: int,
|
||||
mode: int = 0,
|
||||
):
|
||||
global redbag_data, festive_redbag_data
|
||||
data = redbag_data if mode == 0 else festive_redbag_data
|
||||
@ -428,3 +383,27 @@ async def end_festive_redbag(bot: Bot, group_id: int):
|
||||
)
|
||||
await bot.send_group_msg(group_id=group_id, message=message)
|
||||
festive_redbag_data[group_id] = {}
|
||||
|
||||
|
||||
def check_on_gold_red(event) -> bool:
|
||||
flag1 = True
|
||||
flag2 = True
|
||||
try:
|
||||
if festive_redbag_data[event.group_id]["user_id"]:
|
||||
if (
|
||||
event.user_id
|
||||
in festive_redbag_data[event.group_id]["open_user"]
|
||||
):
|
||||
flag1 = False
|
||||
except KeyError:
|
||||
flag1 = False
|
||||
try:
|
||||
if redbag_data[event.group_id]["user_id"]:
|
||||
if event.user_id in redbag_data[event.group_id]["open_user"]:
|
||||
flag2 = False
|
||||
except KeyError:
|
||||
flag2 = False
|
||||
if flag1 or flag2:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@ -1,73 +1,58 @@
|
||||
from services.db_context import db
|
||||
from typing import List
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
class RedbagUser(db.Model):
|
||||
__tablename__ = "redbag_users"
|
||||
from services.db_context import Model
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
send_redbag_count = db.Column(db.Integer(), default=0)
|
||||
get_redbag_count = db.Column(db.Integer(), default=0)
|
||||
spend_gold = db.Column(db.Integer(), default=0)
|
||||
get_gold = db.Column(db.Integer(), default=0)
|
||||
|
||||
_idx1 = db.Index("redbag_group_users_idx1", "user_qq", "group_id", unique=True)
|
||||
class RedbagUser(Model):
|
||||
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
send_redbag_count = fields.IntField(default=0)
|
||||
"""发送红包次数"""
|
||||
get_redbag_count = fields.IntField(default=0)
|
||||
"""开启红包次数"""
|
||||
spend_gold = fields.IntField(default=0)
|
||||
"""发送红包花费金额"""
|
||||
get_gold = fields.IntField(default=0)
|
||||
"""开启红包获取金额"""
|
||||
|
||||
class Meta:
|
||||
table = "redbag_users"
|
||||
table_description = "红包统计数据表"
|
||||
unique_together = ("user_qq", "group_id")
|
||||
|
||||
@classmethod
|
||||
async def add_redbag_data(cls, user_qq: int, group_id: int, itype: str, money: int):
|
||||
async def add_redbag_data(
|
||||
cls, user_qq: int, group_id: int, i_type: str, money: int
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
添加收发红包数据
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
:param itype: 收或发
|
||||
:param i_type: 收或发
|
||||
:param money: 金钱数量
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
user = await query.with_for_update().gino.first() or await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
)
|
||||
if itype == "get":
|
||||
await user.update(
|
||||
get_redbag_count=user.get_redbag_count + 1,
|
||||
get_gold=user.get_gold + money,
|
||||
).apply()
|
||||
else:
|
||||
await user.update(
|
||||
send_redbag_count=user.send_redbag_count + 1,
|
||||
spend_gold=user.spend_gold + money,
|
||||
).apply()
|
||||
|
||||
@classmethod
|
||||
async def ensure(cls, user_qq: int, group_id: int) -> bool:
|
||||
"""
|
||||
说明:
|
||||
获取用户对象
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
"""
|
||||
query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
|
||||
user = await query.gino.first() or await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
)
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
async def get_user_all(cls, group_id: int = None) -> List["RedbagUser"]:
|
||||
"""
|
||||
说明:
|
||||
获取所有用户对象
|
||||
参数:
|
||||
:param group_id: 群号
|
||||
"""
|
||||
if not group_id:
|
||||
query = await cls.query.gino.all()
|
||||
user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
|
||||
if i_type == "get":
|
||||
user.get_redbag_count = user.get_redbag_count + 1
|
||||
user.get_gold = user.get_gold + money
|
||||
else:
|
||||
query = await cls.query.where((cls.group_id == group_id)).gino.all()
|
||||
return query
|
||||
user.send_redbag_count = user.send_redbag_count + 1
|
||||
user.spend_gold = user.spend_gold + money
|
||||
await user.save(
|
||||
update_fields=[
|
||||
"get_redbag_count",
|
||||
"get_gold",
|
||||
"send_redbag_count",
|
||||
"spend_gold",
|
||||
]
|
||||
)
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
from nonebot import on_message, on_regex
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.message_builder import image
|
||||
from utils.utils import is_number, get_message_text
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
|
||||
from utils.utils import FreqLimiter, cn2py
|
||||
from configs.config import Config
|
||||
from utils.manager import withdraw_message_manager
|
||||
from .rule import rule
|
||||
import random
|
||||
import os
|
||||
import random
|
||||
|
||||
from nonebot import on_message, on_regex
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from services.log import logger
|
||||
from utils.manager import withdraw_message_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import FreqLimiter, cn2py, get_message_text, is_number
|
||||
|
||||
from .rule import rule
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@ -66,16 +68,14 @@ async def _(event: MessageEvent):
|
||||
if len(msg) > 1:
|
||||
img_id = msg[1]
|
||||
path = _path / cn2py(gallery)
|
||||
if gallery in Config.get_config(
|
||||
"image_management", "IMAGE_DIR_LIST"
|
||||
):
|
||||
if gallery in Config.get_config("image_management", "IMAGE_DIR_LIST"):
|
||||
if not path.exists() and (path.parent.parent / cn2py(gallery)).exists():
|
||||
path = IMAGE_PATH / cn2py(gallery)
|
||||
else:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
length = len(os.listdir(path))
|
||||
if length == 0:
|
||||
logger.warning(f'图库 {cn2py(gallery)} 为空,调用取消!')
|
||||
logger.warning(f"图库 {cn2py(gallery)} 为空,调用取消!")
|
||||
await send_img.finish("该图库中没有图片噢")
|
||||
index = img_id if img_id else str(random.randint(0, length - 1))
|
||||
if not is_number(index):
|
||||
@ -87,8 +87,7 @@ async def _(event: MessageEvent):
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) "
|
||||
f"发送{cn2py(gallery)}:"
|
||||
+ result
|
||||
f"发送{cn2py(gallery)}:" + result
|
||||
)
|
||||
msg_id = await send_img.send(
|
||||
f"id:{index}" + result
|
||||
@ -113,4 +112,6 @@ async def _(event: MessageEvent):
|
||||
async def _(event: MessageEvent):
|
||||
if _flmt.check(event.user_id):
|
||||
_flmt.start_cd(event.user_id)
|
||||
await pa_reg.finish(image(random.choice(os.listdir(IMAGE_PATH / "pa")), "pa"))
|
||||
await pa_reg.finish(
|
||||
image(IMAGE_PATH / "pa" / random.choice(os.listdir(IMAGE_PATH / "pa")))
|
||||
)
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from datetime import timedelta
|
||||
from models.level_user import LevelUser
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from models.level_user import LevelUser
|
||||
|
||||
__zx_plugin_name__ = "个人信息权限查看"
|
||||
__plugin_usage__ = """
|
||||
@ -31,13 +32,13 @@ async def _(event: GroupMessageEvent):
|
||||
|
||||
|
||||
async def get_member_info(user_qq: int, group_id: int) -> str:
|
||||
user = await GroupInfoUser.get_member_info(user_qq, group_id)
|
||||
if user is None:
|
||||
if user := await GroupInfoUser.get_or_none(user_qq=user_qq, group_id=group_id):
|
||||
result = ""
|
||||
result += "昵称:" + user.user_name + "\n"
|
||||
result += "加群时间:" + str(user.user_join_time.date())
|
||||
return result
|
||||
else:
|
||||
return "该群员不在列表中,请更新群成员信息"
|
||||
result = ""
|
||||
result += "昵称:" + user.user_name + "\n"
|
||||
result += "加群时间:" + str(user.user_join_time.date() + timedelta(hours=8))
|
||||
return result
|
||||
|
||||
|
||||
@my_level.handle()
|
||||
|
||||
@ -1,35 +1,23 @@
|
||||
|
||||
from datetime import datetime
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import db
|
||||
from services.db_context import Model
|
||||
|
||||
# 1.狂牙武器箱
|
||||
|
||||
|
||||
class BuffPrice(db.Model):
|
||||
__tablename__ = 'buff_prices'
|
||||
__table_args__ = {'extend_existing': True}
|
||||
class BuffPrice(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
case_id = db.Column(db.Integer(), nullable=False)
|
||||
skin_name = db.Column(db.Unicode(), nullable=False)
|
||||
skin_price = db.Column(db.Float(), nullable=False)
|
||||
update_date = db.Column(db.DateTime(), nullable=False)
|
||||
|
||||
_idx1 = db.Index('buff_price_idx1', 'skin_name', unique=True)
|
||||
|
||||
@classmethod
|
||||
async def ensure(cls, skin_name: str, for_update: bool = False) -> 'BuffPrice':
|
||||
query = cls.query.where(
|
||||
(cls.skin_name == skin_name)
|
||||
)
|
||||
if for_update:
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
return user or await cls.create(
|
||||
case_id=1,
|
||||
skin_name=skin_name,
|
||||
skin_price=0,
|
||||
update_date=datetime.min,
|
||||
)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
case_id = fields.IntField()
|
||||
"""箱子id"""
|
||||
skin_name = fields.CharField(255, unique=True)
|
||||
"""皮肤名称"""
|
||||
skin_price = fields.FloatField()
|
||||
"""皮肤价格"""
|
||||
update_date = fields.DatetimeField()
|
||||
|
||||
class Meta:
|
||||
table = "buff_prices"
|
||||
table_description = "Buff价格数据表"
|
||||
|
||||
@ -1,60 +1,51 @@
|
||||
from datetime import datetime
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import db
|
||||
|
||||
|
||||
class OpenCasesUser(db.Model):
|
||||
__tablename__ = 'open_cases_users'
|
||||
__table_args__ = {'extend_existing': True}
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
total_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
blue_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
blue_st_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
purple_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
purple_st_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
pink_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
pink_st_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
red_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
red_st_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
knife_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
knife_st_count = db.Column(db.Integer(), nullable=False, default=0)
|
||||
spend_money = db.Column(db.Integer(), nullable=False, default=0)
|
||||
make_money = db.Column(db.Float(), nullable=False, default=0)
|
||||
today_open_total = db.Column(db.Integer(), nullable=False, default=0)
|
||||
open_cases_time_last = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.now())
|
||||
knifes_name = db.Column(db.Unicode(), nullable=False, default="")
|
||||
|
||||
_idx1 = db.Index('open_cases_group_users_idx1', 'user_qq', 'group_id', unique=True)
|
||||
|
||||
@classmethod
|
||||
async def ensure(cls, user_qq: int, group_id: int, for_update: bool = False) -> 'OpenCasesUser':
|
||||
query = cls.query.where(
|
||||
(cls.user_qq == user_qq) & (cls.group_id == group_id)
|
||||
)
|
||||
if for_update:
|
||||
query = query.with_for_update()
|
||||
user = await query.gino.first()
|
||||
return user or await cls.create(
|
||||
user_qq=user_qq,
|
||||
group_id=group_id,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get_user_all(cls, group_id: int = None) -> 'list':
|
||||
user_list = []
|
||||
if not group_id:
|
||||
query = await cls.query.gino.all()
|
||||
else:
|
||||
query = await cls.query.where(
|
||||
(cls.group_id == group_id)
|
||||
).gino.all()
|
||||
for user in query:
|
||||
user_list.append(user)
|
||||
return user_list
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class OpenCasesUser(Model):
|
||||
__tablename__ = "open_cases_users"
|
||||
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
total_count = fields.IntField(default=0)
|
||||
"""总开启次数"""
|
||||
blue_count = fields.IntField(default=0)
|
||||
"""蓝色"""
|
||||
blue_st_count = fields.IntField(default=0)
|
||||
"""蓝色暗金"""
|
||||
purple_count = fields.IntField(default=0)
|
||||
"""紫色"""
|
||||
purple_st_count = fields.IntField(default=0)
|
||||
"""紫色暗金"""
|
||||
pink_count = fields.IntField(default=0)
|
||||
"""粉色"""
|
||||
pink_st_count = fields.IntField(default=0)
|
||||
"""粉色暗金"""
|
||||
red_count = fields.IntField(default=0)
|
||||
"""紫色"""
|
||||
red_st_count = fields.IntField(default=0)
|
||||
"""紫色暗金"""
|
||||
knife_count = fields.IntField(default=0)
|
||||
"""金色"""
|
||||
knife_st_count = fields.IntField(default=0)
|
||||
"""金色暗金"""
|
||||
spend_money = fields.IntField(default=0)
|
||||
"""花费金币"""
|
||||
make_money = fields.IntField(default=0)
|
||||
"""赚取金币"""
|
||||
today_open_total = fields.IntField(default=0)
|
||||
"""今日开箱数量"""
|
||||
open_cases_time_last = fields.DatetimeField()
|
||||
"""最后开箱日期"""
|
||||
knifes_name = fields.TextField(default="")
|
||||
"""已获取金色"""
|
||||
|
||||
class Meta:
|
||||
table = "open_cases_users"
|
||||
table_description = "开箱统计数据表"
|
||||
unique_together = ("user_qq", "group_id")
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
from datetime import datetime, timedelta
|
||||
from .config import *
|
||||
from services.log import logger
|
||||
from services.db_context import db
|
||||
from .models.open_cases_user import OpenCasesUser
|
||||
from models.sign_group_user import SignGroupUser
|
||||
from utils.message_builder import image
|
||||
import pypinyin
|
||||
import random
|
||||
from .utils import get_price
|
||||
from .models.buff_prices import BuffPrice
|
||||
from PIL import Image
|
||||
from utils.image_utils import alpha2white_pil, BuildImage
|
||||
from configs.path_config import IMAGE_PATH
|
||||
import asyncio
|
||||
from utils.utils import cn2py
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pypinyin
|
||||
from PIL import Image
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from models.sign_group_user import SignGroupUser
|
||||
from services.log import logger
|
||||
from utils.image_utils import BuildImage, alpha2white_pil
|
||||
from utils.message_builder import image
|
||||
from utils.utils import cn2py
|
||||
|
||||
from .config import *
|
||||
from .models.buff_prices import BuffPrice
|
||||
from .models.open_cases_user import OpenCasesUser
|
||||
from .utils import get_price
|
||||
|
||||
|
||||
async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动") -> str:
|
||||
@ -26,71 +28,76 @@ async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动"
|
||||
case = ""
|
||||
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
|
||||
case += "".join(i)
|
||||
impression = (await SignGroupUser.ensure(user_qq, group)).impression
|
||||
user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
|
||||
impression = user.impression
|
||||
rand = random.random()
|
||||
async with db.transaction():
|
||||
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
|
||||
# 一天次数上限
|
||||
if user.today_open_total >= int(
|
||||
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
|
||||
+ int(impression)
|
||||
/ Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
|
||||
):
|
||||
return _handle_is_MAX_COUNT()
|
||||
skin, mosun = get_color_quality(rand, case_name)
|
||||
# 调侃
|
||||
if skin[:2] == "军规":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[0] = 1
|
||||
else:
|
||||
uplist[1] = 1
|
||||
ridicule_result = random.choice(["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"])
|
||||
if skin[:2] == "受限":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[2] = 1
|
||||
else:
|
||||
uplist[3] = 1
|
||||
ridicule_result = random.choice(
|
||||
["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."]
|
||||
)
|
||||
if skin[:2] == "保密":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[4] = 1
|
||||
else:
|
||||
uplist[5] = 1
|
||||
ridicule_result = random.choice(
|
||||
["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"]
|
||||
)
|
||||
if skin[:2] == "隐秘":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[6] = 1
|
||||
else:
|
||||
uplist[7] = 1
|
||||
ridicule_result = random.choice(
|
||||
["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"]
|
||||
)
|
||||
if skin[:2] == "罕见":
|
||||
knifes_flag = True
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[8] = 1
|
||||
else:
|
||||
uplist[9] = 1
|
||||
ridicule_result = random.choice(
|
||||
["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."]
|
||||
)
|
||||
if skin.find("(") != -1:
|
||||
cskin = skin.split("(")
|
||||
skin = cskin[0].strip() + "(" + cskin[1].strip()
|
||||
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
|
||||
# 价格
|
||||
if skin.find("无涂装") == -1:
|
||||
dbprice = await BuffPrice.ensure(skin[9:])
|
||||
await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group)
|
||||
# user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
|
||||
user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group)
|
||||
if not user:
|
||||
user = await OpenCasesUser.create(
|
||||
user_qq=user_qq, group_id=group, open_cases_time_last=datetime.now()
|
||||
)
|
||||
# 一天次数上限
|
||||
if user.today_open_total >= int(
|
||||
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
|
||||
+ int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
|
||||
):
|
||||
return _handle_is_MAX_COUNT()
|
||||
skin, mosun = get_color_quality(rand, case_name)
|
||||
# 调侃
|
||||
if skin[:2] == "军规":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[0] = 1
|
||||
else:
|
||||
dbprice = await BuffPrice.ensure(skin[9 : skin.rfind("(")].strip())
|
||||
if dbprice.skin_price != 0:
|
||||
price_result = dbprice.skin_price
|
||||
logger.info("数据库查询到价格: ", dbprice.skin_price)
|
||||
uplist[10] = dbprice.skin_price
|
||||
uplist[1] = 1
|
||||
ridicule_result = random.choice(["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"])
|
||||
if skin[:2] == "受限":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[2] = 1
|
||||
else:
|
||||
uplist[3] = 1
|
||||
ridicule_result = random.choice(
|
||||
["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."]
|
||||
)
|
||||
if skin[:2] == "保密":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[4] = 1
|
||||
else:
|
||||
uplist[5] = 1
|
||||
ridicule_result = random.choice(["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"])
|
||||
if skin[:2] == "隐秘":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[6] = 1
|
||||
else:
|
||||
uplist[7] = 1
|
||||
ridicule_result = random.choice(
|
||||
["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"]
|
||||
)
|
||||
if skin[:2] == "罕见":
|
||||
knifes_flag = True
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[8] = 1
|
||||
else:
|
||||
uplist[9] = 1
|
||||
ridicule_result = random.choice(
|
||||
["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."]
|
||||
)
|
||||
if skin.find("(") != -1:
|
||||
cskin = skin.split("(")
|
||||
skin = cskin[0].strip() + "(" + cskin[1].strip()
|
||||
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
|
||||
# 价格
|
||||
if skin.find("无涂装") == -1:
|
||||
search_name = skin[9:]
|
||||
else:
|
||||
search_name = skin[9 : skin.rfind("(")].strip()
|
||||
price_result = 0
|
||||
if data := await BuffPrice.get_or_none(skin_name=search_name):
|
||||
if data.skin_price != 0:
|
||||
price_result = data.skin_price
|
||||
logger.info("数据库查询到价格: ", data.skin_price)
|
||||
uplist[10] = data.skin_price
|
||||
else:
|
||||
price = -1
|
||||
price_result = "未查询到"
|
||||
@ -102,55 +109,56 @@ async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动"
|
||||
price = float(pcp[1].strip())
|
||||
break
|
||||
if price != -1:
|
||||
logger.info("存储入数据库---->", price)
|
||||
logger.info("存储入数据库---->{price}")
|
||||
uplist[10] = price
|
||||
price_result = str(price)
|
||||
await dbprice.update(
|
||||
skin_price=price,
|
||||
update_date=datetime.now(),
|
||||
).apply()
|
||||
# sp = skin.split("|")
|
||||
# cskin_word = sp[1][:sp[1].find("(") - 1].strip()
|
||||
if knifes_flag:
|
||||
await user.update(
|
||||
knifes_name=user.knifes_name
|
||||
+ f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]}, 价格:{uplist[10]},"
|
||||
).apply()
|
||||
cskin_word = skin.split(":")[1].replace("|", "-").replace("(StatTrak™)", "")
|
||||
cskin_word = cskin_word[: cskin_word.rfind("(")].strip()
|
||||
skin_name = cn2py(
|
||||
cskin_word.replace("|", "-").replace("(StatTrak™)", "").strip()
|
||||
data.skin_price = price
|
||||
data.update_date = datetime.now()
|
||||
await data.save(update_fields=["skin_price", "update_date"])
|
||||
# sp = skin.split("|")
|
||||
# cskin_word = sp[1][:sp[1].find("(") - 1].strip()
|
||||
if knifes_flag:
|
||||
await user.update(
|
||||
knifes_name=user.knifes_name
|
||||
+ f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]}, 价格:{uplist[10]},"
|
||||
).apply()
|
||||
cskin_word = skin.split(":")[1].replace("|", "-").replace("(StatTrak™)", "")
|
||||
cskin_word = cskin_word[: cskin_word.rfind("(")].strip()
|
||||
skin_name = cn2py(cskin_word.replace("|", "-").replace("(StatTrak™)", "").strip())
|
||||
img = image(IMAGE_PATH / "cases" / case / f"{skin_name}.png")
|
||||
# if knifes_flag:
|
||||
# await user.update(
|
||||
# knifes_name=user.knifes_name + f"{skin} 磨损:{mosun}, 价格:{uplist[10]}"
|
||||
# ).apply()
|
||||
if await update_user_total(user, uplist):
|
||||
logger.info(
|
||||
f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新成功"
|
||||
)
|
||||
img = image(f"{skin_name}.png", "cases/" + case)
|
||||
# if knifes_flag:
|
||||
# await user.update(
|
||||
# knifes_name=user.knifes_name + f"{skin} 磨损:{mosun}, 价格:{uplist[10]}"
|
||||
# ).apply()
|
||||
if await update_user_total(user, uplist):
|
||||
logger.info(
|
||||
f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新成功"
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新失败"
|
||||
)
|
||||
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
|
||||
over_count = int(
|
||||
else:
|
||||
logger.warning(
|
||||
f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新失败"
|
||||
)
|
||||
user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
|
||||
over_count = (
|
||||
int(
|
||||
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
|
||||
+ int(impression)
|
||||
/ Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
|
||||
) - user.today_open_total
|
||||
return (
|
||||
f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" + img + "\n" + f"皮肤:{skin}\n"
|
||||
f"磨损:{mosun:.9f}\n"
|
||||
f"价格:{price_result}\n"
|
||||
f"{ridicule_result}"
|
||||
)
|
||||
- user.today_open_total
|
||||
)
|
||||
return (
|
||||
f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" + img + "\n" + f"皮肤:{skin}\n"
|
||||
f"磨损:{mosun:.9f}\n"
|
||||
f"价格:{price_result}\n"
|
||||
f"{ridicule_result}"
|
||||
)
|
||||
|
||||
|
||||
async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int = 10):
|
||||
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
|
||||
impression = (await SignGroupUser.ensure(user_qq, group)).impression
|
||||
user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
|
||||
sign_user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
|
||||
impression = sign_user.impression
|
||||
max_count = int(
|
||||
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
|
||||
+ int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
|
||||
@ -162,11 +170,10 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
|
||||
f"今天开箱次数不足{num}次噢,请单抽试试看(也许单抽运气更好?)"
|
||||
f"\n剩余开箱次数:{max_count - user.today_open_total}"
|
||||
)
|
||||
await user.update(
|
||||
total_count=user.total_count + num,
|
||||
spend_money=user.spend_money + 17 * num,
|
||||
today_open_total=user.today_open_total + num,
|
||||
).apply()
|
||||
user.total_count = user.total_count + num
|
||||
user.spend_money = user.spend_money + 17 * num
|
||||
user.today_open_total = user.today_open_total + num
|
||||
await user.save(update_fields=["total_count", "spend_money", "today_open_total"])
|
||||
if num < 5:
|
||||
h = 270
|
||||
elif num % 5 == 0:
|
||||
@ -180,46 +187,46 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
|
||||
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0]
|
||||
img_list = []
|
||||
name_list = ["蓝", "蓝(暗金)", "紫", "紫(暗金)", "粉", "粉(暗金)", "红", "红(暗金)", "金", "金(暗金)"]
|
||||
async with db.transaction():
|
||||
for _ in range(num):
|
||||
knifes_flag = False
|
||||
rand = random.random()
|
||||
skin, mosun = get_color_quality(rand, case_name)
|
||||
if skin[:2] == "军规":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[0] += 1
|
||||
else:
|
||||
uplist[1] += 1
|
||||
if skin[:2] == "受限":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[2] += 1
|
||||
else:
|
||||
uplist[3] += 1
|
||||
if skin[:2] == "保密":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[4] += 1
|
||||
else:
|
||||
uplist[5] += 1
|
||||
if skin[:2] == "隐秘":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[6] += 1
|
||||
else:
|
||||
uplist[7] += 1
|
||||
if skin[:2] == "罕见":
|
||||
knifes_flag = True
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[8] += 1
|
||||
else:
|
||||
uplist[9] += 1
|
||||
if skin.find("(") != -1:
|
||||
cskin = skin.split("(")
|
||||
skin = cskin[0].strip() + "(" + cskin[1].strip()
|
||||
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
|
||||
# 价格
|
||||
if skin.find("无涂装") == -1:
|
||||
dbprice = await BuffPrice.ensure(skin[9:])
|
||||
for _ in range(num):
|
||||
knifes_flag = False
|
||||
rand = random.random()
|
||||
skin, mosun = get_color_quality(rand, case_name)
|
||||
if skin[:2] == "军规":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[0] += 1
|
||||
else:
|
||||
dbprice = await BuffPrice.ensure(skin[9 : skin.rfind("(")].strip())
|
||||
uplist[1] += 1
|
||||
if skin[:2] == "受限":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[2] += 1
|
||||
else:
|
||||
uplist[3] += 1
|
||||
if skin[:2] == "保密":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[4] += 1
|
||||
else:
|
||||
uplist[5] += 1
|
||||
if skin[:2] == "隐秘":
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[6] += 1
|
||||
else:
|
||||
uplist[7] += 1
|
||||
if skin[:2] == "罕见":
|
||||
knifes_flag = True
|
||||
if skin.find("StatTrak") == -1:
|
||||
uplist[8] += 1
|
||||
else:
|
||||
uplist[9] += 1
|
||||
if skin.find("(") != -1:
|
||||
cskin = skin.split("(")
|
||||
skin = cskin[0].strip() + "(" + cskin[1].strip()
|
||||
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
|
||||
# 价格
|
||||
if skin.find("无涂装") == -1:
|
||||
search_name = skin[9:]
|
||||
else:
|
||||
search_name = skin[9 : skin.rfind("(")].strip()
|
||||
if dbprice := await BuffPrice.get_or_none(skin_name=search_name):
|
||||
if dbprice.skin_price != 0:
|
||||
price_result = dbprice.skin_price
|
||||
uplist[10] += price_result
|
||||
@ -238,7 +245,6 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
|
||||
style=pypinyin.NORMAL,
|
||||
):
|
||||
skin_name += "".join(i)
|
||||
# img = image(skin_name, "cases/" + case, "png")
|
||||
wImg = BuildImage(200, 270, 200, 200)
|
||||
wImg.paste(
|
||||
alpha2white_pil(
|
||||
@ -296,7 +302,7 @@ def _handle_is_MAX_COUNT() -> str:
|
||||
|
||||
async def update_user_total(user: OpenCasesUser, up_list: list, num: int = 1) -> bool:
|
||||
try:
|
||||
await user.update(
|
||||
await user.update_or_create(
|
||||
total_count=user.total_count + num,
|
||||
blue_count=user.blue_count + up_list[0],
|
||||
blue_st_count=user.blue_st_count + up_list[1],
|
||||
@ -312,36 +318,35 @@ async def update_user_total(user: OpenCasesUser, up_list: list, num: int = 1) ->
|
||||
make_money=user.make_money + up_list[10],
|
||||
today_open_total=user.today_open_total + num,
|
||||
open_cases_time_last=datetime.now(),
|
||||
).apply()
|
||||
)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
async def total_open_statistics(user_qq: int, group: int) -> str:
|
||||
async with db.transaction():
|
||||
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
|
||||
return (
|
||||
f"开箱总数:{user.total_count}\n"
|
||||
f"今日开箱:{user.today_open_total}\n"
|
||||
f"蓝色军规:{user.blue_count}\n"
|
||||
f"蓝色暗金:{user.blue_st_count}\n"
|
||||
f"紫色受限:{user.purple_count}\n"
|
||||
f"紫色暗金:{user.purple_st_count}\n"
|
||||
f"粉色保密:{user.pink_count}\n"
|
||||
f"粉色暗金:{user.pink_st_count}\n"
|
||||
f"红色隐秘:{user.red_count}\n"
|
||||
f"红色暗金:{user.red_st_count}\n"
|
||||
f"金色罕见:{user.knife_count}\n"
|
||||
f"金色暗金:{user.knife_st_count}\n"
|
||||
f"花费金额:{user.spend_money}\n"
|
||||
f"获取金额:{user.make_money:.2f}\n"
|
||||
f"最后开箱日期:{(user.open_cases_time_last + timedelta(hours=8)).date()}"
|
||||
)
|
||||
user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
|
||||
return (
|
||||
f"开箱总数:{user.total_count}\n"
|
||||
f"今日开箱:{user.today_open_total}\n"
|
||||
f"蓝色军规:{user.blue_count}\n"
|
||||
f"蓝色暗金:{user.blue_st_count}\n"
|
||||
f"紫色受限:{user.purple_count}\n"
|
||||
f"紫色暗金:{user.purple_st_count}\n"
|
||||
f"粉色保密:{user.pink_count}\n"
|
||||
f"粉色暗金:{user.pink_st_count}\n"
|
||||
f"红色隐秘:{user.red_count}\n"
|
||||
f"红色暗金:{user.red_st_count}\n"
|
||||
f"金色罕见:{user.knife_count}\n"
|
||||
f"金色暗金:{user.knife_st_count}\n"
|
||||
f"花费金额:{user.spend_money}\n"
|
||||
f"获取金额:{user.make_money:.2f}\n"
|
||||
f"最后开箱日期:{user.open_cases_time_last.date()}"
|
||||
)
|
||||
|
||||
|
||||
async def group_statistics(group: int):
|
||||
user_list = await OpenCasesUser.get_user_all(group)
|
||||
user_list = await OpenCasesUser.filter(group_id=group).all()
|
||||
# lan zi fen hong jin pricei
|
||||
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0]
|
||||
for user in user_list:
|
||||
@ -377,7 +382,8 @@ async def group_statistics(group: int):
|
||||
|
||||
|
||||
async def my_knifes_name(user_id: int, group: int):
|
||||
knifes_name = (await OpenCasesUser.ensure(user_id, group)).knifes_name
|
||||
user, _ = await OpenCasesUser.get_or_create(user_qq=user_id, group_id=group)
|
||||
knifes_name = user.knifes_name
|
||||
if knifes_name:
|
||||
knifes_list = knifes_name[:-1].split(",")
|
||||
length = len(knifes_list)
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
from .models.buff_prices import BuffPrice
|
||||
from services.db_context import db
|
||||
from datetime import datetime, timedelta
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from .models.open_cases_user import OpenCasesUser
|
||||
from services.log import logger
|
||||
from utils.utils import get_bot, cn2py
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
from configs.config import Config
|
||||
from utils.manager import group_manager
|
||||
from .config import *
|
||||
import os
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.manager import group_manager
|
||||
from utils.utils import cn2py, get_bot
|
||||
|
||||
from .config import *
|
||||
from .models.buff_prices import BuffPrice
|
||||
from .models.open_cases_user import OpenCasesUser
|
||||
|
||||
url = "https://buff.163.com/api/market/goods"
|
||||
# proxies = 'http://49.75.59.242:3128'
|
||||
@ -49,108 +51,102 @@ async def util_get_buff_price(case_name: str = "狂牙大行动") -> str:
|
||||
"骷髅匕首 | 无涂装",
|
||||
]:
|
||||
skin = skin.split("|")[0].strip()
|
||||
async with db.transaction():
|
||||
name_list = []
|
||||
price_list = []
|
||||
parameter = {"game": "csgo", "page_num": "1", "search": skin}
|
||||
try:
|
||||
response = await AsyncHttpx.get(url, proxy=Config.get_config("open_cases", "BUFF_PROXY"),
|
||||
name_list = []
|
||||
price_list = []
|
||||
parameter = {"game": "csgo", "page_num": "1", "search": skin}
|
||||
try:
|
||||
response = await AsyncHttpx.get(
|
||||
url,
|
||||
proxy=Config.get_config("open_cases", "BUFF_PROXY"),
|
||||
params=parameter,
|
||||
cookies=cookie,)
|
||||
if response.status_code == 200:
|
||||
data = response.json()["data"]
|
||||
total_page = data["total_page"]
|
||||
data = data["items"]
|
||||
flag = False
|
||||
if (
|
||||
skin.find("|") == -1
|
||||
): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
|
||||
for i in range(1, total_page + 1):
|
||||
name_list = []
|
||||
price_list = []
|
||||
parameter = {
|
||||
"game": "csgo",
|
||||
"page_num": f"{i}",
|
||||
"search": skin,
|
||||
}
|
||||
res = await AsyncHttpx.get(url, params=parameter, cookies=cookie)
|
||||
data = res.json()["data"][
|
||||
"items"
|
||||
]
|
||||
for j in range(len(data)):
|
||||
if data[j]["name"] in [f"{skin}(★)"]:
|
||||
name = data[j]["name"]
|
||||
price = data[j][
|
||||
"sell_reference_price"
|
||||
]
|
||||
name_list.append(
|
||||
name.split("(")[0].strip()
|
||||
+ " | 无涂装"
|
||||
)
|
||||
price_list.append(price)
|
||||
flag = True
|
||||
break
|
||||
if flag:
|
||||
cookies=cookie,
|
||||
)
|
||||
if response.status_code == 200:
|
||||
data = response.json()["data"]
|
||||
total_page = data["total_page"]
|
||||
data = data["items"]
|
||||
flag = False
|
||||
if (
|
||||
skin.find("|") == -1
|
||||
): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
|
||||
for i in range(1, total_page + 1):
|
||||
name_list = []
|
||||
price_list = []
|
||||
parameter = {
|
||||
"game": "csgo",
|
||||
"page_num": f"{i}",
|
||||
"search": skin,
|
||||
}
|
||||
res = await AsyncHttpx.get(
|
||||
url, params=parameter, cookies=cookie
|
||||
)
|
||||
data = res.json()["data"]["items"]
|
||||
for j in range(len(data)):
|
||||
if data[j]["name"] in [f"{skin}(★)"]:
|
||||
name = data[j]["name"]
|
||||
price = data[j]["sell_reference_price"]
|
||||
name_list.append(
|
||||
name.split("(")[0].strip() + " | 无涂装"
|
||||
)
|
||||
price_list.append(price)
|
||||
flag = True
|
||||
break
|
||||
else:
|
||||
try:
|
||||
for _ in range(total_page):
|
||||
for i in range(len(data)):
|
||||
name = data[i]["name"]
|
||||
price = data[i]["sell_reference_price"]
|
||||
name_list.append(name)
|
||||
price_list.append(price)
|
||||
except Exception as e:
|
||||
failed_list.append(skin)
|
||||
logger.warning(f"{skin}更新失败")
|
||||
if flag:
|
||||
break
|
||||
else:
|
||||
failed_list.append(skin)
|
||||
logger.warning(f"{skin}更新失败")
|
||||
except Exception:
|
||||
try:
|
||||
for _ in range(total_page):
|
||||
for i in range(len(data)):
|
||||
name = data[i]["name"]
|
||||
price = data[i]["sell_reference_price"]
|
||||
name_list.append(name)
|
||||
price_list.append(price)
|
||||
except Exception as e:
|
||||
failed_list.append(skin)
|
||||
logger.warning(f"{skin}更新失败")
|
||||
else:
|
||||
failed_list.append(skin)
|
||||
logger.warning(f"{skin}更新失败")
|
||||
continue
|
||||
for i in range(len(name_list)):
|
||||
name = name_list[i].strip()
|
||||
price = float(price_list[i])
|
||||
if name.find("(★)") != -1:
|
||||
name = name[: name.find("(")] + name[name.find(")") + 1 :]
|
||||
if name.find("消音") != -1 and name.find("(S") != -1:
|
||||
name = name.split("(")[0][:-4] + "(" + name.split("(")[1]
|
||||
name = (
|
||||
name.split("|")[0].strip()
|
||||
+ " | "
|
||||
+ name.split("|")[1].strip()
|
||||
)
|
||||
elif name.find("消音") != -1:
|
||||
name = (
|
||||
name.split("|")[0][:-5].strip()
|
||||
+ " | "
|
||||
+ name.split("|")[1].strip()
|
||||
)
|
||||
if name.find(" 18 ") != -1 and name.find("(S") != -1:
|
||||
name = name.split("(")[0][:-5] + "(" + name.split("(")[1]
|
||||
name = (
|
||||
name.split("|")[0].strip()
|
||||
+ " | "
|
||||
+ name.split("|")[1].strip()
|
||||
)
|
||||
elif name.find(" 18 ") != -1:
|
||||
name = (
|
||||
name.split("|")[0][:-6].strip()
|
||||
+ " | "
|
||||
+ name.split("|")[1].strip()
|
||||
)
|
||||
dbskin = await BuffPrice.ensure(name, True)
|
||||
if (
|
||||
dbskin.update_date + timedelta(8)
|
||||
).date() == datetime.now().date():
|
||||
except Exception:
|
||||
failed_list.append(skin)
|
||||
logger.warning(f"{skin}更新失败")
|
||||
continue
|
||||
for i in range(len(name_list)):
|
||||
name = name_list[i].strip()
|
||||
price = float(price_list[i])
|
||||
if name.find("(★)") != -1:
|
||||
name = name[: name.find("(")] + name[name.find(")") + 1 :]
|
||||
if name.find("消音") != -1 and name.find("(S") != -1:
|
||||
name = name.split("(")[0][:-4] + "(" + name.split("(")[1]
|
||||
name = (
|
||||
name.split("|")[0].strip() + " | " + name.split("|")[1].strip()
|
||||
)
|
||||
elif name.find("消音") != -1:
|
||||
name = (
|
||||
name.split("|")[0][:-5].strip()
|
||||
+ " | "
|
||||
+ name.split("|")[1].strip()
|
||||
)
|
||||
if name.find(" 18 ") != -1 and name.find("(S") != -1:
|
||||
name = name.split("(")[0][:-5] + "(" + name.split("(")[1]
|
||||
name = (
|
||||
name.split("|")[0].strip() + " | " + name.split("|")[1].strip()
|
||||
)
|
||||
elif name.find(" 18 ") != -1:
|
||||
name = (
|
||||
name.split("|")[0][:-6].strip()
|
||||
+ " | "
|
||||
+ name.split("|")[1].strip()
|
||||
)
|
||||
if dbskin := await BuffPrice.get_or_none(skin_name=name):
|
||||
if dbskin.update_date.date() == datetime.now().date():
|
||||
continue
|
||||
await dbskin.update(
|
||||
case_id=case_id,
|
||||
skin_price=price,
|
||||
update_date=datetime.now(),
|
||||
).apply()
|
||||
dbskin.case_id = case_id
|
||||
dbskin.skin_price = price
|
||||
dbskin.update_date = datetime.now()
|
||||
await dbskin.save(
|
||||
update_fields=["case_id", "skin_price", "update_date"]
|
||||
)
|
||||
logger.info(f"{name_list[i]}---------->成功更新")
|
||||
result = None
|
||||
if failed_list:
|
||||
@ -186,14 +182,16 @@ async def util_get_buff_img(case_name: str = "狂牙大行动") -> str:
|
||||
logger.info(f"开始更新----->{skin}")
|
||||
skin_name = ""
|
||||
# try:
|
||||
response = await AsyncHttpx.get(url, proxy=Config.get_config("open_cases", "BUFF_PROXY"), params=parameter)
|
||||
response = await AsyncHttpx.get(
|
||||
url,
|
||||
proxy=Config.get_config("open_cases", "BUFF_PROXY"),
|
||||
params=parameter,
|
||||
)
|
||||
if response.status_code == 200:
|
||||
data = response.json()["data"]
|
||||
total_page = data["total_page"]
|
||||
flag = False
|
||||
if (
|
||||
skin.find("|") == -1
|
||||
): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
|
||||
if skin.find("|") == -1: # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
|
||||
for i in range(1, total_page + 1):
|
||||
res = await AsyncHttpx.get(url, params=parameter)
|
||||
data = res.json()["data"]["items"]
|
||||
@ -201,17 +199,21 @@ async def util_get_buff_img(case_name: str = "狂牙大行动") -> str:
|
||||
if data[j]["name"] in [f"{skin}(★)"]:
|
||||
img_url = data[j]["goods_info"]["icon_url"]
|
||||
skin_name = cn2py(skin + "无涂装")
|
||||
await AsyncHttpx.download_file(img_url, path / f"{skin_name}.png")
|
||||
await AsyncHttpx.download_file(
|
||||
img_url, path / f"{skin_name}.png"
|
||||
)
|
||||
flag = True
|
||||
break
|
||||
if flag:
|
||||
break
|
||||
else:
|
||||
img_url = (await response.json())["data"]["items"][0][
|
||||
"goods_info"
|
||||
]["icon_url"]
|
||||
img_url = (await response.json())["data"]["items"][0]["goods_info"][
|
||||
"icon_url"
|
||||
]
|
||||
skin_name += cn2py(skin.replace("|", "-").strip())
|
||||
if await AsyncHttpx.download_file(img_url, path / f"{skin_name}.png"):
|
||||
if await AsyncHttpx.download_file(
|
||||
img_url, path / f"{skin_name}.png"
|
||||
):
|
||||
logger.info(f"------->写入 {skin} 成功")
|
||||
else:
|
||||
logger.info(f"------->写入 {skin} 失败")
|
||||
@ -255,18 +257,15 @@ async def get_price(d_name):
|
||||
|
||||
async def update_count_daily():
|
||||
try:
|
||||
users = await OpenCasesUser.get_user_all()
|
||||
if users:
|
||||
for user in users:
|
||||
await user.update(
|
||||
today_open_total=0,
|
||||
).apply()
|
||||
await OpenCasesUser.all().update(today_open_total=0)
|
||||
bot = get_bot()
|
||||
gl = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in gl]
|
||||
for g in gl:
|
||||
try:
|
||||
await bot.send_group_msg(group_id=g, message="[[_task|open_case_reset_remind]]今日开箱次数重置成功")
|
||||
await bot.send_group_msg(
|
||||
group_id=g, message="[[_task|open_case_reset_remind]]今日开箱次数重置成功"
|
||||
)
|
||||
except ActionFailed:
|
||||
logger.warning(f"{g} 群被禁言,无法发送 开箱重置提醒")
|
||||
logger.info("今日开箱次数重置成功")
|
||||
|
||||
@ -1,22 +1,24 @@
|
||||
from nonebot import on_message
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, ActionFailed
|
||||
|
||||
from utils.manager import group_manager
|
||||
from utils.utils import get_message_json, get_local_proxy, is_number, get_message_text
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
from utils.message_builder import image
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.browser import get_browser
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.config import Config
|
||||
from utils.user_agent import get_user_agent
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
import aiohttp
|
||||
import ujson as json
|
||||
from bilireq import video
|
||||
from nonebot import on_message
|
||||
from nonebot.adapters.onebot.v11 import ActionFailed, GroupMessageEvent
|
||||
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import IMAGE_PATH, TEMP_PATH
|
||||
from services.log import logger
|
||||
from utils.browser import get_browser
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.manager import group_manager
|
||||
from utils.message_builder import image
|
||||
from utils.user_agent import get_user_agent
|
||||
from utils.utils import get_local_proxy, get_message_json, get_message_text, is_number
|
||||
|
||||
__zx_plugin_name__ = "B站转发解析"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
@ -39,7 +41,10 @@ Config.add_plugin_config(
|
||||
async def plugin_on_checker(event: GroupMessageEvent) -> bool:
|
||||
return group_manager.get_plugin_status("parse_bilibili_json", event.group_id)
|
||||
|
||||
parse_bilibili_json = on_message(priority=1, permission=GROUP, block=False, rule=plugin_on_checker)
|
||||
|
||||
parse_bilibili_json = on_message(
|
||||
priority=1, permission=GROUP, block=False, rule=plugin_on_checker
|
||||
)
|
||||
|
||||
_tmp = {}
|
||||
|
||||
@ -55,16 +60,14 @@ async def _(event: GroupMessageEvent):
|
||||
data = None
|
||||
if data:
|
||||
# 转发视频
|
||||
if data.get("desc") == "哔哩哔哩" or data.get('prompt').find('哔哩哔哩') != -1:
|
||||
async with aiohttp.ClientSession(
|
||||
headers=get_user_agent()
|
||||
) as session:
|
||||
if data.get("desc") == "哔哩哔哩" or "哔哩哔哩" in data.get("prompt"):
|
||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||
async with session.get(
|
||||
data["meta"]["detail_1"]["qqdocurl"],
|
||||
timeout=7,
|
||||
data["meta"]["detail_1"]["qqdocurl"],
|
||||
timeout=7,
|
||||
) as response:
|
||||
url = str(response.url).split("?")[0]
|
||||
if url[-1] == '/':
|
||||
if url[-1] == "/":
|
||||
url = url[:-1]
|
||||
bvid = url.split("/")[-1]
|
||||
vd_info = await video.get_video_base_info(bvid)
|
||||
@ -93,10 +96,11 @@ async def _(event: GroupMessageEvent):
|
||||
timeout=100000,
|
||||
)
|
||||
await asyncio.get_event_loop().run_in_executor(
|
||||
None, resize, f"{IMAGE_PATH}/temp/cv_{event.user_id}.png"
|
||||
None, resize, TEMP_PATH / f"cv_{event.user_id}.png"
|
||||
)
|
||||
await parse_bilibili_json.send(
|
||||
"[[_task|bilibili_parse]]" + image(f"cv_{event.user_id}.png", "temp")
|
||||
"[[_task|bilibili_parse]]"
|
||||
+ image(TEMP_PATH / f"cv_{event.user_id}.png")
|
||||
)
|
||||
await page.close()
|
||||
logger.info(
|
||||
@ -121,15 +125,13 @@ async def _(event: GroupMessageEvent):
|
||||
msg = msg[index + 2 : index + 11]
|
||||
if is_number(msg):
|
||||
url = f"https://www.bilibili.com/video/av{msg}"
|
||||
vd_info = await video.get_video_base_info('av' + msg)
|
||||
vd_info = await video.get_video_base_info("av" + msg)
|
||||
elif "https://b23.tv" in msg:
|
||||
url = "https://" + msg[msg.find("b23.tv"): msg.find("b23.tv") + 14]
|
||||
async with aiohttp.ClientSession(
|
||||
headers=get_user_agent()
|
||||
) as session:
|
||||
url = "https://" + msg[msg.find("b23.tv") : msg.find("b23.tv") + 14]
|
||||
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
|
||||
async with session.get(
|
||||
url,
|
||||
timeout=7,
|
||||
url,
|
||||
timeout=7,
|
||||
) as response:
|
||||
url = (str(response.url).split("?")[0]).strip("/")
|
||||
bvid = url.split("/")[-1]
|
||||
@ -150,8 +152,9 @@ async def _(event: GroupMessageEvent):
|
||||
date = time.strftime("%Y-%m-%d", time.localtime(vd_info["ctime"]))
|
||||
try:
|
||||
await parse_bilibili_json.send(
|
||||
"[[_task|bilibili_parse]]" +
|
||||
image(vd_info["pic"]) + f"\nav{aid}\n标题:{title}\n"
|
||||
"[[_task|bilibili_parse]]"
|
||||
+ image(vd_info["pic"])
|
||||
+ f"\nav{aid}\n标题:{title}\n"
|
||||
f"UP:{author}\n"
|
||||
f"上传日期:{date}\n"
|
||||
f"回复:{reply},收藏:{favorite},投币:{coin}\n"
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
from asyncio.exceptions import TimeoutError
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import Arg, CommandArg
|
||||
from nonebot.typing import T_State
|
||||
|
||||
from configs.config import Config
|
||||
from utils.utils import is_number, change_pixiv_image_links
|
||||
from utils.message_builder import image
|
||||
from configs.path_config import IMAGE_PATH, TEMP_PATH
|
||||
from services.log import logger
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.manager import withdraw_message_manager
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from nonebot.params import CommandArg, Arg
|
||||
|
||||
from utils.manager import withdraw_message_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import change_pixiv_image_links, is_number
|
||||
|
||||
__zx_plugin_name__ = "pid搜索"
|
||||
__plugin_usage__ = """
|
||||
@ -88,7 +88,7 @@ async def _g(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
|
||||
img_url = change_pixiv_image_links(img_url)
|
||||
if not await AsyncHttpx.download_file(
|
||||
img_url,
|
||||
IMAGE_PATH / "temp" / f"pid_search_{event.user_id}_{i}.png",
|
||||
TEMP_PATH / f"pid_search_{event.user_id}_{i}.png",
|
||||
headers=headers,
|
||||
):
|
||||
await pid_search.send("图片下载失败了....", at_sender=True)
|
||||
@ -101,7 +101,7 @@ async def _g(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
|
||||
f"pid:{pid}\n"
|
||||
f"author:{author}\n"
|
||||
f"author_id:{author_id}\n"
|
||||
f'{image(f"pid_search_{event.user_id}_{i}.png", "temp")}'
|
||||
f'{image(TEMP_PATH / f"pid_search_{event.user_id}_{i}.png")}'
|
||||
f"{tmp}"
|
||||
)
|
||||
)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from configs.config import Config
|
||||
from utils.utils import GDict
|
||||
import nonebot
|
||||
|
||||
from configs.config import Config
|
||||
from utils.utils import GDict
|
||||
|
||||
Config.add_plugin_config(
|
||||
"hibiapi",
|
||||
@ -10,59 +10,42 @@ Config.add_plugin_config(
|
||||
help_="如果没有自建或其他hibiapi请不要修改",
|
||||
default_value="https://api.obfs.dev",
|
||||
)
|
||||
Config.add_plugin_config(
|
||||
"pixiv",
|
||||
"PIXIV_NGINX_URL",
|
||||
"i.pximg.cf",
|
||||
help_="Pixiv反向代理"
|
||||
)
|
||||
Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pximg.cf", help_="Pixiv反向代理")
|
||||
Config.add_plugin_config(
|
||||
"pix",
|
||||
"PIX_IMAGE_SIZE",
|
||||
"master",
|
||||
name="PIX图库",
|
||||
help_="PIX图库下载的画质 可能的值:original:原图,master:缩略图(加快发送速度)",
|
||||
default_value="master"
|
||||
default_value="master",
|
||||
)
|
||||
Config.add_plugin_config(
|
||||
"pix",
|
||||
"SEARCH_HIBIAPI_BOOKMARKS",
|
||||
5000,
|
||||
help_="最低收藏,PIX使用HIBIAPI搜索图片时达到最低收藏才会添加至图库",
|
||||
default_value=5000
|
||||
default_value=5000,
|
||||
)
|
||||
Config.add_plugin_config(
|
||||
"pix",
|
||||
"WITHDRAW_PIX_MESSAGE",
|
||||
(0, 1),
|
||||
help_="自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
|
||||
default_value=(0, 1)
|
||||
default_value=(0, 1),
|
||||
)
|
||||
Config.add_plugin_config(
|
||||
"pix",
|
||||
"PIX_OMEGA_PIXIV_RATIO",
|
||||
(10, 0),
|
||||
help_="PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1:PIX图库 参2:OmegaPixivIllusts扩展图库(没有此图库请设置为0)",
|
||||
default_value=(10, 0)
|
||||
)
|
||||
Config.add_plugin_config(
|
||||
"pix",
|
||||
"TIMEOUT",
|
||||
10,
|
||||
help_="下载图片超时限制(秒)",
|
||||
default_value=10
|
||||
default_value=(10, 0),
|
||||
)
|
||||
Config.add_plugin_config("pix", "TIMEOUT", 10, help_="下载图片超时限制(秒)", default_value=10)
|
||||
|
||||
Config.add_plugin_config(
|
||||
"pix",
|
||||
"SHOW_INFO",
|
||||
True,
|
||||
help_="是否显示图片的基本信息,如PID等",
|
||||
default_value=True
|
||||
"pix", "SHOW_INFO", True, help_="是否显示图片的基本信息,如PID等", default_value=True
|
||||
)
|
||||
|
||||
GDict['run_sql'].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;")
|
||||
GDict["run_sql"].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;")
|
||||
|
||||
nonebot.load_plugins("plugins/pix_gallery")
|
||||
|
||||
|
||||
|
||||
@ -1,19 +1,23 @@
|
||||
from asyncpg.exceptions import UniqueViolationError
|
||||
from ._model.omega_pixiv_illusts import OmegaPixivIllusts
|
||||
from asyncio.locks import Semaphore
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from ._model.pixiv import Pixiv
|
||||
from typing import List, Optional
|
||||
from utils.utils import change_pixiv_image_links, change_img_md5
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from services.log import logger
|
||||
from configs.config import Config
|
||||
from configs.path_config import TEMP_PATH
|
||||
import aiofiles
|
||||
import platform
|
||||
import asyncio
|
||||
import math
|
||||
import platform
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from asyncio.locks import Semaphore
|
||||
from copy import deepcopy
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
import aiofiles
|
||||
from asyncpg.exceptions import UniqueViolationError
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import TEMP_PATH
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.utils import change_img_md5, change_pixiv_image_links
|
||||
|
||||
from ._model.omega_pixiv_illusts import OmegaPixivIllusts
|
||||
from ._model.pixiv import Pixiv
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@ -65,9 +69,7 @@ async def start_update_image_url(
|
||||
params = {"word": keyword, "page": page}
|
||||
tasks.append(
|
||||
asyncio.ensure_future(
|
||||
search_image(
|
||||
url, keyword, params, semaphore, page, black_pid
|
||||
)
|
||||
search_image(url, keyword, params, semaphore, page, black_pid)
|
||||
)
|
||||
)
|
||||
if keyword.startswith("pid:"):
|
||||
@ -101,96 +103,91 @@ async def search_image(
|
||||
pic_count = 0
|
||||
pid_count = 0
|
||||
async with semaphore:
|
||||
try:
|
||||
data = (await AsyncHttpx.get(url, params=params)).json()
|
||||
if (
|
||||
not data
|
||||
or data.get("error")
|
||||
or (not data.get("illusts") and not data.get("illust"))
|
||||
):
|
||||
return 0, 0
|
||||
if url != f"{HIBIAPI}/api/pixiv/illust":
|
||||
logger.info(f'{keyword}: 获取数据成功...数据总量:{len(data["illusts"])}')
|
||||
data = data["illusts"]
|
||||
# try:
|
||||
data = (await AsyncHttpx.get(url, params=params)).json()
|
||||
if (
|
||||
not data
|
||||
or data.get("error")
|
||||
or (not data.get("illusts") and not data.get("illust"))
|
||||
):
|
||||
return 0, 0
|
||||
if url != f"{HIBIAPI}/api/pixiv/illust":
|
||||
logger.info(f'{keyword}: 获取数据成功...数据总量:{len(data["illusts"])}')
|
||||
data = data["illusts"]
|
||||
else:
|
||||
logger.info(f'获取数据成功...PID:{params.get("id")}')
|
||||
data = [data["illust"]]
|
||||
img_data = {}
|
||||
for x in data:
|
||||
pid = x["id"]
|
||||
title = x["title"]
|
||||
width = x["width"]
|
||||
height = x["height"]
|
||||
view = x["total_view"]
|
||||
bookmarks = x["total_bookmarks"]
|
||||
uid = x["user"]["id"]
|
||||
author = x["user"]["name"]
|
||||
tags = []
|
||||
for tag in x["tags"]:
|
||||
for i in tag:
|
||||
if tag[i]:
|
||||
tags.append(tag[i])
|
||||
img_urls = []
|
||||
if x["page_count"] == 1:
|
||||
img_urls.append(x["meta_single_page"]["original_image_url"])
|
||||
else:
|
||||
logger.info(f'获取数据成功...PID:{params.get("id")}')
|
||||
data = [data["illust"]]
|
||||
img_data = {}
|
||||
for x in data:
|
||||
pid = x["id"]
|
||||
title = x["title"]
|
||||
width = x["width"]
|
||||
height = x["height"]
|
||||
view = x["total_view"]
|
||||
bookmarks = x["total_bookmarks"]
|
||||
uid = x["user"]["id"]
|
||||
author = x["user"]["name"]
|
||||
tags = []
|
||||
for tag in x["tags"]:
|
||||
for i in tag:
|
||||
if tag[i]:
|
||||
tags.append(tag[i])
|
||||
img_urls = []
|
||||
if x["page_count"] == 1:
|
||||
img_urls.append(x["meta_single_page"]["original_image_url"])
|
||||
else:
|
||||
for urls in x["meta_pages"]:
|
||||
img_urls.append(urls["image_urls"]["original"])
|
||||
if (
|
||||
(
|
||||
bookmarks
|
||||
>= Config.get_config("pix", "SEARCH_HIBIAPI_BOOKMARKS")
|
||||
or (
|
||||
url == f"{HIBIAPI}/api/pixiv/member_illust"
|
||||
and bookmarks >= 1500
|
||||
)
|
||||
or (url == f"{HIBIAPI}/api/pixiv/illust")
|
||||
for urls in x["meta_pages"]:
|
||||
img_urls.append(urls["image_urls"]["original"])
|
||||
if (
|
||||
(
|
||||
bookmarks >= Config.get_config("pix", "SEARCH_HIBIAPI_BOOKMARKS")
|
||||
or (
|
||||
url == f"{HIBIAPI}/api/pixiv/member_illust"
|
||||
and bookmarks >= 1500
|
||||
)
|
||||
and len(img_urls) < 10
|
||||
and _check_black(img_urls, black)
|
||||
or (url == f"{HIBIAPI}/api/pixiv/illust")
|
||||
)
|
||||
and len(img_urls) < 10
|
||||
and _check_black(img_urls, black)
|
||||
):
|
||||
img_data[pid] = {
|
||||
"pid": pid,
|
||||
"title": title,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"view": view,
|
||||
"bookmarks": bookmarks,
|
||||
"img_urls": img_urls,
|
||||
"uid": uid,
|
||||
"author": author,
|
||||
"tags": tags,
|
||||
}
|
||||
else:
|
||||
continue
|
||||
for x in img_data.keys():
|
||||
data = img_data[x]
|
||||
data_copy = deepcopy(data)
|
||||
del data_copy["img_urls"]
|
||||
for img_url in data["img_urls"]:
|
||||
img_p = img_url[img_url.rfind("_") + 1 : img_url.rfind(".")]
|
||||
data_copy["img_url"] = img_url
|
||||
data_copy["img_p"] = img_p
|
||||
data_copy["is_r18"] = "R-18" in data["tags"]
|
||||
if not await Pixiv.exists(
|
||||
pid=data["pid"], img_url=img_url, img_p=img_p
|
||||
):
|
||||
img_data[pid] = {
|
||||
"pid": pid,
|
||||
"title": title,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"view": view,
|
||||
"bookmarks": bookmarks,
|
||||
"img_urls": img_urls,
|
||||
"uid": uid,
|
||||
"author": author,
|
||||
"tags": tags,
|
||||
}
|
||||
data_copy["img_url"] = img_url
|
||||
await Pixiv.create(**data_copy)
|
||||
if data["pid"] not in tmp_pid:
|
||||
pid_count += 1
|
||||
tmp_pid.append(data["pid"])
|
||||
pic_count += 1
|
||||
logger.info(f'存储图片PID:{data["pid"]} IMG_P:{img_p}')
|
||||
else:
|
||||
continue
|
||||
for x in img_data.keys():
|
||||
data = img_data[x]
|
||||
for img_url in data["img_urls"]:
|
||||
img_p = img_url[img_url.rfind("_") + 1 : img_url.rfind(".")]
|
||||
try:
|
||||
if await Pixiv.add_image_data(
|
||||
data["pid"],
|
||||
data["title"],
|
||||
data["width"],
|
||||
data["height"],
|
||||
data["view"],
|
||||
data["bookmarks"],
|
||||
img_url,
|
||||
img_p,
|
||||
data["uid"],
|
||||
data["author"],
|
||||
",".join(data["tags"]),
|
||||
):
|
||||
if data["pid"] not in tmp_pid:
|
||||
pid_count += 1
|
||||
tmp_pid.append(data["pid"])
|
||||
pic_count += 1
|
||||
logger.info(f'存储图片PID:{data["pid"]} IMG_P:{img_p}')
|
||||
except UniqueViolationError:
|
||||
logger.warning(f'{data["pid"]} | {img_url} 已存在...')
|
||||
except Exception as e:
|
||||
logger.warning(f"PIX在线搜索图片错误,已再次调用 {type(e)}:{e}")
|
||||
await search_image(url, keyword, params, semaphore, page, black)
|
||||
logger.warning(f'{data["pid"]} | {img_url} 已存在...')
|
||||
# except Exception as e:
|
||||
# logger.warning(f"PIX在线搜索图片错误,已再次调用 {type(e)}:{e}")
|
||||
# await search_image(url, keyword, params, semaphore, page, black)
|
||||
return pid_count, pic_count
|
||||
|
||||
|
||||
@ -206,7 +203,9 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
|
||||
params = {"id": pid}
|
||||
for _ in range(3):
|
||||
try:
|
||||
response = await AsyncHttpx.get(f"{HIBIAPI}/api/pixiv/illust", params=params)
|
||||
response = await AsyncHttpx.get(
|
||||
f"{HIBIAPI}/api/pixiv/illust", params=params
|
||||
)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get("illust"):
|
||||
@ -215,22 +214,28 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
|
||||
"original_image_url"
|
||||
]
|
||||
else:
|
||||
img_url = data["illust"]["meta_pages"][0][
|
||||
"image_urls"
|
||||
]["original"]
|
||||
img_url = data["illust"]["meta_pages"][0]["image_urls"][
|
||||
"original"
|
||||
]
|
||||
break
|
||||
except TimeoutError:
|
||||
pass
|
||||
old_img_url = img_url
|
||||
img_url = change_pixiv_image_links(
|
||||
img_url, Config.get_config("pix", "PIX_IMAGE_SIZE"), Config.get_config("pixiv", "PIXIV_NGINX_URL")
|
||||
img_url,
|
||||
Config.get_config("pix", "PIX_IMAGE_SIZE"),
|
||||
Config.get_config("pixiv", "PIXIV_NGINX_URL"),
|
||||
)
|
||||
old_img_url = change_pixiv_image_links(
|
||||
old_img_url, None, Config.get_config("pixiv", "PIXIV_NGINX_URL")
|
||||
)
|
||||
for _ in range(3):
|
||||
try:
|
||||
response = await AsyncHttpx.get(img_url, headers=headers, timeout=Config.get_config("pix", "TIMEOUT"),)
|
||||
response = await AsyncHttpx.get(
|
||||
img_url,
|
||||
headers=headers,
|
||||
timeout=Config.get_config("pix", "TIMEOUT"),
|
||||
)
|
||||
if response.status_code == 404:
|
||||
img_url = old_img_url
|
||||
continue
|
||||
@ -238,7 +243,9 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
|
||||
TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg", "wb"
|
||||
) as f:
|
||||
await f.write(response.content)
|
||||
change_img_md5(TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg")
|
||||
change_img_md5(
|
||||
TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg"
|
||||
)
|
||||
return TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg"
|
||||
except TimeoutError:
|
||||
logger.warning(f"PIX:{img_url} 图片下载超时...")
|
||||
@ -264,7 +271,7 @@ async def uid_pid_exists(id_: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
async def get_keyword_num(keyword: str) -> "int, int, int, int, int":
|
||||
async def get_keyword_num(keyword: str) -> Tuple[int, int, int, int, int]:
|
||||
"""
|
||||
查看图片相关 tag 数量
|
||||
:param keyword: 关键词tag
|
||||
@ -276,7 +283,7 @@ async def get_keyword_num(keyword: str) -> "int, int, int, int, int":
|
||||
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: Optional[str]):
|
||||
"""
|
||||
删除置顶图片
|
||||
:param pid: pid
|
||||
@ -285,7 +292,10 @@ async def remove_image(pid: int, img_p: str) -> bool:
|
||||
if img_p:
|
||||
if "p" not in img_p:
|
||||
img_p = f"p{img_p}"
|
||||
return await Pixiv.remove_image_data(pid, img_p)
|
||||
if img_p:
|
||||
await Pixiv.filter(pid=pid, img_p=img_p).delete()
|
||||
else:
|
||||
await Pixiv.filter(pid=pid).delete()
|
||||
|
||||
|
||||
def gen_keyword_pic(
|
||||
@ -392,6 +402,3 @@ def _check_black(img_urls: List[str], black: List[str]) -> bool:
|
||||
if b in img_url:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,79 +1,50 @@
|
||||
from typing import Optional, List, Tuple
|
||||
from services.db_context import db
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from tortoise import fields
|
||||
from tortoise.contrib.postgres.functions import Random
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class OmegaPixivIllusts(db.Model):
|
||||
__tablename__ = "omega_pixiv_illusts"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
class OmegaPixivIllusts(Model):
|
||||
|
||||
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)
|
||||
classified = db.Column(db.Integer(), 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)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
pid = fields.BigIntField()
|
||||
"""pid"""
|
||||
uid = fields.BigIntField()
|
||||
"""uid"""
|
||||
title = fields.CharField(255)
|
||||
"""标题"""
|
||||
uname = fields.CharField(255)
|
||||
"""画师名称"""
|
||||
classified = fields.IntField()
|
||||
"""标记标签, 0=未标记, 1=已人工标记或从可信已标记来源获取"""
|
||||
nsfw_tag = fields.IntField()
|
||||
"""nsfw标签,-1=未标记, 0=safe, 1=setu. 2=r18"""
|
||||
width = fields.IntField()
|
||||
"""宽度"""
|
||||
height = fields.IntField()
|
||||
"""高度"""
|
||||
tags = fields.TextField()
|
||||
"""tags"""
|
||||
url = fields.CharField(255)
|
||||
"""pixiv url链接"""
|
||||
|
||||
_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,
|
||||
classified: int,
|
||||
nsfw_tag: int,
|
||||
tags: str,
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
添加图片信息
|
||||
参数:
|
||||
:param pid: pid
|
||||
:param title: 标题
|
||||
:param width: 宽度
|
||||
:param height: 长度
|
||||
:param url: url链接
|
||||
:param uid: 作者uid
|
||||
:param uname: 作者名称
|
||||
:param classified: 标记标签, 0=未标记, 1=已人工标记或从可信已标记来源获取
|
||||
:param nsfw_tag: nsfw标签,-1=未标记, 0=safe, 1=setu. 2=r18
|
||||
:param tags: 相关tag
|
||||
"""
|
||||
if not await cls.check_exists(pid):
|
||||
await cls.create(
|
||||
pid=pid,
|
||||
title=title,
|
||||
width=width,
|
||||
height=height,
|
||||
url=url,
|
||||
uid=uid,
|
||||
uname=uname,
|
||||
classified=classified,
|
||||
nsfw_tag=nsfw_tag,
|
||||
tags=tags,
|
||||
)
|
||||
return True
|
||||
return False
|
||||
class Meta:
|
||||
table = "omega_pixiv_illusts"
|
||||
table_description = "omega图库数据表"
|
||||
unique_together = ("pid", "url")
|
||||
|
||||
@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"]]:
|
||||
cls,
|
||||
keywords: Optional[List[str]] = None,
|
||||
uid: Optional[int] = None,
|
||||
pid: Optional[int] = None,
|
||||
nsfw_tag: Optional[int] = 0,
|
||||
num: int = 100,
|
||||
) -> List["OmegaPixivIllusts"]:
|
||||
"""
|
||||
说明:
|
||||
查找符合条件的图片
|
||||
@ -84,66 +55,38 @@ class OmegaPixivIllusts(db.Model):
|
||||
:param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
|
||||
:param num: 获取图片数量
|
||||
"""
|
||||
if not num:
|
||||
return []
|
||||
query = cls
|
||||
if nsfw_tag is not None:
|
||||
query = cls.query.where(cls.nsfw_tag == nsfw_tag)
|
||||
else:
|
||||
query = cls.query
|
||||
query = cls.filter(nsfw_tag=nsfw_tag)
|
||||
if keywords:
|
||||
for keyword in keywords:
|
||||
query = query.where(cls.tags.contains(keyword))
|
||||
query = query.filter(tags__contains=keyword)
|
||||
elif uid:
|
||||
query = query.where(cls.uid == uid)
|
||||
query = query.filter(uid=uid)
|
||||
elif pid:
|
||||
query = query.where(cls.uid == pid)
|
||||
query = query.order_by(db.func.random()).limit(num)
|
||||
return await query.gino.all()
|
||||
query = query.filter(pid=pid)
|
||||
query = query.annotate(rand=Random()).limit(num)
|
||||
return await query.all() # type: ignore
|
||||
|
||||
@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) -> Tuple[int, int, int]:
|
||||
async def get_keyword_num(
|
||||
cls, tags: Optional[List[str]] = None
|
||||
) -> Tuple[int, int, int]:
|
||||
"""
|
||||
说明:
|
||||
获取相关关键词(keyword, tag)在图库中的数量
|
||||
参数:
|
||||
:param tags: 关键词/Tag
|
||||
"""
|
||||
setattr(OmegaPixivIllusts, 'count', db.func.count(cls.pid).label('count'))
|
||||
query = cls.select('count')
|
||||
query = cls
|
||||
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]
|
||||
|
||||
# async def test(cls, nsfw_tag: int = 1):
|
||||
# if nsfw_tag is not None:
|
||||
# query = cls.query.where(cls.nsfw_tag == nsfw_tag)
|
||||
# else:
|
||||
# query = cls.query
|
||||
# query = query.where((cls.width - cls.height) < 50)
|
||||
# for x in await query.gino.all():
|
||||
# print(x.pid)
|
||||
|
||||
|
||||
|
||||
query = query.filter(tags__contains=tag)
|
||||
else:
|
||||
query = query.all()
|
||||
count = await query.filter(nsfw_tag=0).count()
|
||||
setu_count = await query.filter(nsfw_tag=1).count()
|
||||
r18_count = await query.filter(nsfw_tag=2).count()
|
||||
return count, setu_count, r18_count
|
||||
|
||||
@ -1,105 +1,43 @@
|
||||
from typing import Optional, List
|
||||
from services.db_context import db
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from tortoise import fields
|
||||
from tortoise.contrib.postgres.functions import Random
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class Pixiv(db.Model):
|
||||
__tablename__ = "pixiv"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
class Pixiv(Model):
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
pid = db.Column(db.BigInteger(), nullable=False)
|
||||
title = db.Column(db.String(), nullable=False)
|
||||
width = db.Column(db.Integer(), nullable=False)
|
||||
height = db.Column(db.Integer(), nullable=False)
|
||||
view = db.Column(db.Integer(), nullable=False)
|
||||
bookmarks = db.Column(db.Integer(), nullable=False)
|
||||
img_url = db.Column(db.String(), nullable=False)
|
||||
img_p = db.Column(db.String(), nullable=False)
|
||||
uid = db.Column(db.BigInteger(), nullable=False)
|
||||
author = db.Column(db.String(), nullable=False)
|
||||
is_r18 = db.Column(db.Boolean(), nullable=False)
|
||||
tags = db.Column(db.String(), nullable=False)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
pid = fields.BigIntField()
|
||||
"""pid"""
|
||||
uid = fields.BigIntField()
|
||||
"""uid"""
|
||||
author = fields.CharField(255)
|
||||
"""作者"""
|
||||
title = fields.CharField(255)
|
||||
"""标题"""
|
||||
width = fields.IntField()
|
||||
"""宽度"""
|
||||
height = fields.IntField()
|
||||
"""高度"""
|
||||
view = fields.IntField()
|
||||
"""pixiv查看数"""
|
||||
bookmarks = fields.IntField()
|
||||
"""收藏数"""
|
||||
tags = fields.TextField()
|
||||
"""tags"""
|
||||
img_url = fields.CharField(255)
|
||||
"""pixiv url链接"""
|
||||
img_p = fields.CharField(255)
|
||||
"""图片pN"""
|
||||
is_r18 = fields.BooleanField()
|
||||
|
||||
_idx1 = db.Index("pixiv_idx1", "pid", "img_url", unique=True)
|
||||
|
||||
@classmethod
|
||||
async def add_image_data(
|
||||
cls,
|
||||
pid: int,
|
||||
title: str,
|
||||
width: int,
|
||||
height: int,
|
||||
view: int,
|
||||
bookmarks: int,
|
||||
img_url: str,
|
||||
img_p: str,
|
||||
uid: int,
|
||||
author: str,
|
||||
tags: str,
|
||||
):
|
||||
"""
|
||||
说明:
|
||||
添加图片信息
|
||||
参数:
|
||||
:param pid: pid
|
||||
:param title: 标题
|
||||
:param width: 宽度
|
||||
:param height: 长度
|
||||
:param view: 被查看次数
|
||||
:param bookmarks: 收藏数
|
||||
:param img_url: url链接
|
||||
:param img_p: 张数
|
||||
:param uid: 作者uid
|
||||
:param author: 作者名称
|
||||
:param tags: 相关tag
|
||||
"""
|
||||
if not await cls.check_exists(pid, img_p):
|
||||
await cls.create(
|
||||
pid=pid,
|
||||
title=title,
|
||||
width=width,
|
||||
height=height,
|
||||
view=view,
|
||||
bookmarks=bookmarks,
|
||||
img_url=img_url,
|
||||
img_p=img_p,
|
||||
uid=uid,
|
||||
author=author,
|
||||
is_r18=True if "R-18" in tags else False,
|
||||
tags=tags,
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def remove_image_data(cls, pid: int, img_p: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
删除图片数据
|
||||
参数:
|
||||
:param pid: 图片pid
|
||||
:param img_p: 图片pid的张数,如:p0,p1
|
||||
"""
|
||||
try:
|
||||
if img_p:
|
||||
await cls.delete.where(
|
||||
(cls.pid == pid) & (cls.img_p == img_p)
|
||||
).gino.status()
|
||||
else:
|
||||
await cls.delete.where(cls.pid == pid).gino.status()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_all_pid(cls) -> List[int]:
|
||||
"""
|
||||
说明:
|
||||
获取所有PID
|
||||
"""
|
||||
query = await cls.query.select("pid").gino.first()
|
||||
pid = [x[0] for x in query]
|
||||
return list(set(pid))
|
||||
class Meta:
|
||||
table = "pixiv"
|
||||
table_description = "pix图库数据表"
|
||||
unique_together = ("pid", "img_url", "img_p")
|
||||
|
||||
# 0:非r18 1:r18 2:混合
|
||||
@classmethod
|
||||
@ -109,7 +47,7 @@ class Pixiv(db.Model):
|
||||
uid: Optional[int] = None,
|
||||
pid: Optional[int] = None,
|
||||
r18: Optional[int] = 0,
|
||||
num: int = 100
|
||||
num: int = 100,
|
||||
) -> List[Optional["Pixiv"]]:
|
||||
"""
|
||||
说明:
|
||||
@ -121,50 +59,37 @@ class Pixiv(db.Model):
|
||||
:param r18: 是否r18,0:非r18 1:r18 2:混合
|
||||
:param num: 查找图片的数量
|
||||
"""
|
||||
if not num:
|
||||
return []
|
||||
query = cls
|
||||
if r18 == 0:
|
||||
query = cls.query.where(cls.is_r18 == False)
|
||||
query = query.filter(is_r18=False)
|
||||
elif r18 == 1:
|
||||
query = cls.query.where(cls.is_r18 == True)
|
||||
else:
|
||||
query = cls.query
|
||||
query = query.filter(is_r18=True)
|
||||
if keywords:
|
||||
for keyword in keywords:
|
||||
query = query.where(cls.tags.contains(keyword))
|
||||
query = query.filter(tags__contains=keyword)
|
||||
elif uid:
|
||||
query = query.where(cls.uid == uid)
|
||||
query = query.filter(uid=uid)
|
||||
elif pid:
|
||||
query = query.where(cls.pid == pid)
|
||||
query = query.order_by(db.func.random()).limit(num)
|
||||
return await query.gino.all()
|
||||
query = query.filter(pid=pid)
|
||||
query = query.annotate(rand=Random()).limit(num)
|
||||
return await query.all() # type: ignore
|
||||
|
||||
@classmethod
|
||||
async def check_exists(cls, pid: int, img_p: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
检测pid是否已存在
|
||||
参数:
|
||||
:param pid: 图片PID
|
||||
:param img_p: 张数
|
||||
"""
|
||||
query = await cls.query.where(
|
||||
(cls.pid == pid) & (cls.img_p == img_p)
|
||||
).gino.all()
|
||||
return bool(query)
|
||||
|
||||
@classmethod
|
||||
async def get_keyword_num(cls, tags: List[str] = None) -> "int, int":
|
||||
async def get_keyword_num(cls, tags: Optional[List[str]] = None) -> Tuple[int, int]:
|
||||
"""
|
||||
说明:
|
||||
获取相关关键词(keyword, tag)在图库中的数量
|
||||
参数:
|
||||
:param tags: 关键词/Tag
|
||||
"""
|
||||
setattr(Pixiv, 'count', db.func.count(cls.pid).label('count'))
|
||||
query = cls.select('count')
|
||||
query = cls
|
||||
if tags:
|
||||
for tag in tags:
|
||||
query = query.where(cls.tags.contains(tag))
|
||||
count = await query.where(cls.is_r18 == False).gino.first()
|
||||
r18_count = await query.where(cls.is_r18 == True).gino.first()
|
||||
return count[0], r18_count[0]
|
||||
|
||||
query = query.filter(tags__contains=tag)
|
||||
else:
|
||||
query = query.all()
|
||||
count = await query.filter(is_r18=False).count()
|
||||
r18_count = await query.filter(is_r18=True).count()
|
||||
return count, r18_count
|
||||
|
||||
@ -1,101 +1,42 @@
|
||||
from services.db_context import db
|
||||
from typing import Set, List
|
||||
from typing import List, Set, Tuple
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
|
||||
|
||||
class PixivKeywordUser(db.Model):
|
||||
class PixivKeywordUser(Model):
|
||||
__tablename__ = "pixiv_keyword_users"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
user_qq = db.Column(db.BigInteger(), nullable=False)
|
||||
group_id = db.Column(db.BigInteger(), nullable=False)
|
||||
keyword = db.Column(db.String(), nullable=False)
|
||||
is_pass = db.Column(db.Boolean(), default=False)
|
||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||
"""自增id"""
|
||||
user_qq = fields.BigIntField()
|
||||
"""用户id"""
|
||||
group_id = fields.BigIntField()
|
||||
"""群聊id"""
|
||||
keyword = fields.CharField(255, unique=True)
|
||||
"""关键词"""
|
||||
is_pass = fields.BooleanField()
|
||||
"""是否通过"""
|
||||
|
||||
_idx1 = db.Index("pixiv_keyword_users_idx1", "keyword", unique=True)
|
||||
class Meta:
|
||||
table = "pixiv_keyword_users"
|
||||
table_description = "pixiv关键词数据表"
|
||||
|
||||
@classmethod
|
||||
async def add_keyword(
|
||||
cls, user_qq: int, group_id: int, keyword: str, superusers: Set[str]
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
添加搜图的关键词
|
||||
参数:
|
||||
:param user_qq: qq号
|
||||
:param group_id: 群号
|
||||
:param keyword: 关键词
|
||||
:param superusers: 是否为超级用户
|
||||
"""
|
||||
is_pass = True if str(user_qq) in superusers else False
|
||||
if not await cls._check_keyword_exists(keyword):
|
||||
await cls.create(
|
||||
user_qq=user_qq, group_id=group_id, keyword=keyword, is_pass=is_pass
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def delete_keyword(cls, keyword: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
删除关键词
|
||||
参数:
|
||||
:param keyword: 关键词
|
||||
"""
|
||||
if await cls._check_keyword_exists(keyword):
|
||||
query = cls.query.where(cls.keyword == keyword).with_for_update()
|
||||
query = await query.gino.first()
|
||||
await query.delete()
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def set_keyword_pass(cls, keyword: str, is_pass: bool) -> "int, int":
|
||||
"""
|
||||
说明:
|
||||
通过或禁用关键词
|
||||
参数:
|
||||
:param keyword: 关键词
|
||||
:param is_pass: 通过状态
|
||||
"""
|
||||
if await cls._check_keyword_exists(keyword):
|
||||
query = cls.query.where(cls.keyword == keyword).with_for_update()
|
||||
query = await query.gino.first()
|
||||
await query.update(
|
||||
is_pass=is_pass,
|
||||
).apply()
|
||||
return query.user_qq, query.group_id
|
||||
return 0, 0
|
||||
|
||||
@classmethod
|
||||
async def get_all_user_dict(cls) -> dict:
|
||||
"""
|
||||
说明:
|
||||
获取关键词数据库各个用户贡献的关键词字典
|
||||
"""
|
||||
tmp = {}
|
||||
query = await cls.query.gino.all()
|
||||
for user in query:
|
||||
if not tmp.get(user.user_qq):
|
||||
tmp[user.user_qq] = {"keyword": []}
|
||||
tmp[user.user_qq]["keyword"].append(user.keyword)
|
||||
return tmp
|
||||
|
||||
@classmethod
|
||||
async def get_current_keyword(cls) -> "List[str], List[str]":
|
||||
async def get_current_keyword(cls) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
说明:
|
||||
获取当前通过与未通过的关键词
|
||||
"""
|
||||
pass_keyword = []
|
||||
not_pass_keyword = []
|
||||
query = await cls.query.gino.all()
|
||||
for user in query:
|
||||
if user.is_pass:
|
||||
pass_keyword.append(user.keyword)
|
||||
for data in await cls.all().values_list("keyword", "is_pass"):
|
||||
if data[1]:
|
||||
pass_keyword.append(data[0])
|
||||
else:
|
||||
not_pass_keyword.append(user.keyword)
|
||||
not_pass_keyword.append(data[0])
|
||||
return pass_keyword, not_pass_keyword
|
||||
|
||||
@classmethod
|
||||
@ -105,23 +46,9 @@ class PixivKeywordUser(db.Model):
|
||||
获取黑名单PID
|
||||
"""
|
||||
black_pid = []
|
||||
query = await cls.query.where(cls.user_qq == 114514).gino.all()
|
||||
for image in query:
|
||||
black_pid.append(image.keyword[6:])
|
||||
keyword_list = await cls.filter(user_qq=114514).values_list(
|
||||
"keyword", flat=True
|
||||
)
|
||||
for image in keyword_list:
|
||||
black_pid.append(image[6:])
|
||||
return black_pid
|
||||
|
||||
@classmethod
|
||||
async def _check_keyword_exists(cls, keyword: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
检测关键词是否已存在
|
||||
参数:
|
||||
:param keyword: 关键词
|
||||
"""
|
||||
current_keyword = []
|
||||
query = await cls.query.gino.all()
|
||||
for user in query:
|
||||
current_keyword.append(user.keyword)
|
||||
if keyword in current_keyword:
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
from nonebot import on_command
|
||||
from utils.utils import is_number
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
|
||||
from nonebot.params import CommandArg, Command
|
||||
from typing import Tuple
|
||||
from ._data_source import uid_pid_exists
|
||||
from ._model.pixiv_keyword_user import PixivKeywordUser
|
||||
from ._model.pixiv import Pixiv
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import Command, CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from services.log import logger
|
||||
from utils.utils import is_number
|
||||
|
||||
from ._data_source import uid_pid_exists
|
||||
from ._model.pixiv import Pixiv
|
||||
from ._model.pixiv_keyword_user import PixivKeywordUser
|
||||
|
||||
__zx_plugin_name__ = "PIX关键词/UID/PID添加管理 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
@ -46,9 +49,16 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
group_id = event.group_id
|
||||
if msg:
|
||||
if await PixivKeywordUser.add_keyword(
|
||||
event.user_id, group_id, msg, bot.config.superusers
|
||||
):
|
||||
# if await PixivKeywordUser.add_keyword(
|
||||
# event.user_id, group_id, msg, bot.config.superusers
|
||||
# ):
|
||||
if not await PixivKeywordUser.exists(keyword=msg):
|
||||
await PixivKeywordUser.create(
|
||||
user_qq=event.user_id,
|
||||
group_id=group_id,
|
||||
keyword=msg,
|
||||
is_pass=str(event.user_id) in bot.config.superusers,
|
||||
)
|
||||
await add_keyword.send(
|
||||
f"已成功添加pixiv搜图关键词:{msg},请等待管理员通过该关键词!", at_sender=True
|
||||
)
|
||||
@ -63,7 +73,12 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
|
||||
|
||||
@add_uid_pid.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
async def _(
|
||||
bot: Bot,
|
||||
event: MessageEvent,
|
||||
cmd: Tuple[str, ...] = Command(),
|
||||
arg: Message = CommandArg(),
|
||||
):
|
||||
msg = arg.extract_plain_text().strip()
|
||||
exists_flag = True
|
||||
if msg.find("-f") != -1 and str(event.user_id) in bot.config.superusers:
|
||||
@ -77,16 +92,23 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
|
||||
msg = f"uid:{msg}"
|
||||
else:
|
||||
msg = f"pid:{msg}"
|
||||
if await Pixiv.check_exists(int(msg[4:]), "p0"):
|
||||
if await Pixiv.get_or_none(pid=int(msg[4:]), img_p="p0"):
|
||||
await add_uid_pid.finish(f"该PID:{msg[4:]}已存在...", at_sender=True)
|
||||
if not await uid_pid_exists(msg) and exists_flag:
|
||||
await add_uid_pid.finish("画师或作品不存在或搜索正在CD,请稍等...", at_sender=True)
|
||||
group_id = -1
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
group_id = event.group_id
|
||||
if await PixivKeywordUser.add_keyword(
|
||||
event.user_id, group_id, msg, bot.config.superusers
|
||||
):
|
||||
# if await PixivKeywordUser.add_keyword(
|
||||
# event.user_id, group_id, msg, bot.config.superusers
|
||||
# ):
|
||||
if not await PixivKeywordUser.exists(keyword=msg):
|
||||
await PixivKeywordUser.create(
|
||||
user_qq=event.user_id,
|
||||
group_id=group_id,
|
||||
keyword=msg,
|
||||
is_pass=str(event.user_id) in bot.config.superusers,
|
||||
)
|
||||
await add_uid_pid.send(
|
||||
f"已成功添加pixiv搜图UID/PID:{msg[4:]},请等待管理员通过!", at_sender=True
|
||||
)
|
||||
@ -106,12 +128,21 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
pid = pid[: pid.find("p")]
|
||||
if not is_number(pid):
|
||||
await add_black_pid.finish("PID必须全部是数字!", at_sender=True)
|
||||
if await PixivKeywordUser.add_keyword(
|
||||
114514,
|
||||
114514,
|
||||
f"black:{pid}{f'_p{img_p}' if img_p else ''}",
|
||||
bot.config.superusers,
|
||||
# if await PixivKeywordUser.add_keyword(
|
||||
# 114514,
|
||||
# 114514,
|
||||
# f"black:{pid}{f'_p{img_p}' if img_p else ''}",
|
||||
# bot.config.superusers,
|
||||
# ):
|
||||
if not await PixivKeywordUser.exists(
|
||||
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}"
|
||||
):
|
||||
await PixivKeywordUser.create(
|
||||
user_qq=114514,
|
||||
group_id=114514,
|
||||
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}",
|
||||
is_pass=str(event.user_id) in bot.config.superusers,
|
||||
)
|
||||
await add_black_pid.send(f"已添加PID:{pid} 至黑名单中...")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
from nonebot import on_command
|
||||
from utils.utils import is_number
|
||||
from utils.message_builder import at
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
|
||||
from nonebot.params import CommandArg, Command
|
||||
from nonebot.permission import SUPERUSER
|
||||
from ._data_source import remove_image
|
||||
from ._model.pixiv_keyword_user import PixivKeywordUser
|
||||
from ._model.pixiv import Pixiv
|
||||
from typing import Tuple
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
|
||||
from nonebot.params import Command, CommandArg
|
||||
from nonebot.permission import SUPERUSER
|
||||
|
||||
from services.log import logger
|
||||
from utils.message_builder import at
|
||||
from utils.utils import is_number
|
||||
|
||||
from ._data_source import remove_image
|
||||
from ._model.pixiv import Pixiv
|
||||
from ._model.pixiv_keyword_user import PixivKeywordUser
|
||||
|
||||
__zx_plugin_name__ = "PIX关键词/UID/PID删除管理 [Superuser]"
|
||||
__plugin_usage__ = """
|
||||
@ -60,7 +62,8 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||
msg = f"uid:{msg}"
|
||||
if msg.lower().startswith("pid"):
|
||||
msg = "pid:" + msg.replace("pid", "").replace(":", "")
|
||||
if await PixivKeywordUser.delete_keyword(msg):
|
||||
if data := await PixivKeywordUser.get_or_none(keyword=msg):
|
||||
await data.delete()
|
||||
await del_keyword.send(f"删除搜图关键词/UID:{msg} 成功...")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
@ -97,22 +100,31 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
if await remove_image(int(pid), img_p):
|
||||
msg += f'{pid}{f"_p{img_p}" if img_p else ""},'
|
||||
if flag:
|
||||
if await PixivKeywordUser.add_keyword(
|
||||
114514,
|
||||
114514,
|
||||
f"black:{pid}{f'_p{img_p}' if img_p else ''}",
|
||||
bot.config.superusers,
|
||||
# if await PixivKeywordUser.add_keyword(
|
||||
# 114514,
|
||||
# 114514,
|
||||
# f"black:{pid}{f'_p{img_p}' if img_p else ''}",
|
||||
# bot.config.superusers,
|
||||
# ):
|
||||
if await PixivKeywordUser.exists(
|
||||
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}"
|
||||
):
|
||||
await PixivKeywordUser.create(
|
||||
user_qq=114514,
|
||||
group_id=114514,
|
||||
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}",
|
||||
is_pass=False,
|
||||
)
|
||||
black_pid += f'{pid}{f"_p{img_p}" if img_p else ""},'
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 删除了PIX图片 PID:{pid}{f'_p{img_p}' if img_p else ''}"
|
||||
)
|
||||
else:
|
||||
await del_pic.send(
|
||||
f"PIX:删除pid:{pid}{f'_p{img_p}' if img_p else ''} 失败.."
|
||||
)
|
||||
# else:
|
||||
# await del_pic.send(
|
||||
# f"PIX:删除pid:{pid}{f'_p{img_p}' if img_p else ''} 失败.."
|
||||
# )
|
||||
else:
|
||||
await del_pic.send(
|
||||
f"PIX:图片pix:{pid}{f'_p{img_p}' if img_p else ''} 不存在...无法删除.."
|
||||
@ -127,7 +139,12 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
|
||||
|
||||
@pass_keyword.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
async def _(
|
||||
bot: Bot,
|
||||
event: MessageEvent,
|
||||
cmd: Tuple[str, ...] = Command(),
|
||||
arg: Message = CommandArg(),
|
||||
):
|
||||
tmp = {"group": {}, "private": {}}
|
||||
msg = arg.extract_plain_text().strip()
|
||||
if not msg:
|
||||
@ -145,7 +162,13 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
|
||||
if not is_number(x[4:]):
|
||||
await pass_keyword.send(f"UID/PID:{x} 非全数字,跳过该关键词...")
|
||||
continue
|
||||
user_id, group_id = await PixivKeywordUser.set_keyword_pass(x, flag)
|
||||
data = await PixivKeywordUser.get_or_none(keyword=x)
|
||||
user_id = 0
|
||||
group_id = 0
|
||||
if data:
|
||||
data.is_pass = flag
|
||||
await data.save(update_fields=["is_pass"])
|
||||
user_id, group_id = data.user_qq, data.group_id
|
||||
if not user_id:
|
||||
await pass_keyword.send(f"未找到关键词/UID:{x},请检查关键词/UID是否存在...")
|
||||
continue
|
||||
@ -163,7 +186,7 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
|
||||
else:
|
||||
tmp["group"][group_id][user_id]["keyword"].append(x)
|
||||
msg = " ".join(msg)
|
||||
await pass_keyword.send(f'已成功{cmd[0][:2]}搜图关键词:{msg}....')
|
||||
await pass_keyword.send(f"已成功{cmd[0][:2]}搜图关键词:{msg}....")
|
||||
for user in tmp["private"]:
|
||||
x = ",".join(tmp["private"][user]["keyword"])
|
||||
await bot.send_private_msg(
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
from nonebot import on_command
|
||||
from utils.message_builder import image
|
||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message
|
||||
from ._data_source import gen_keyword_pic, get_keyword_num
|
||||
from ._model.pixiv_keyword_user import PixivKeywordUser
|
||||
from nonebot.params import CommandArg
|
||||
import asyncio
|
||||
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
|
||||
from nonebot.params import CommandArg
|
||||
|
||||
from utils.message_builder import image
|
||||
|
||||
from ._data_source import gen_keyword_pic, get_keyword_num
|
||||
from ._model.pixiv_keyword_user import PixivKeywordUser
|
||||
|
||||
__zx_plugin_name__ = "查看pix图库"
|
||||
__plugin_usage__ = """
|
||||
@ -35,12 +37,12 @@ show_pix = on_command("查看pix图库", priority=1, block=True)
|
||||
|
||||
@my_keyword.handle()
|
||||
async def _(event: MessageEvent):
|
||||
data = await PixivKeywordUser.get_all_user_dict()
|
||||
if data.get(event.user_id) is None or not data[event.user_id]["keyword"]:
|
||||
await my_keyword.finish("您目前没有提供任何Pixiv搜图关键字...", at_sender=True)
|
||||
await my_keyword.send(
|
||||
f"您目前提供的如下关键字:\n\t" + ",".join(data[event.user_id]["keyword"])
|
||||
data = await PixivKeywordUser.filter(user_qq=event.user_id).values_list(
|
||||
"keyword", flat=True
|
||||
)
|
||||
if not data:
|
||||
await my_keyword.finish("您目前没有提供任何Pixiv搜图关键字...", at_sender=True)
|
||||
await my_keyword.send(f"您目前提供的如下关键字:\n\t" + ",".join(data))
|
||||
|
||||
|
||||
@show_keyword.handle()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user