update v0.0.8.0

This commit is contained in:
HibiKier 2022-01-05 22:32:59 +08:00
parent 5e5168f804
commit 30b56583bd
47 changed files with 1521 additions and 1281 deletions

4
.gitignore vendored
View File

@ -142,4 +142,6 @@ test.py
server.py
member_activity_handle.py
Yu-Gi-Oh/
search_image/
black_word/
csgo/

401
README.md
View File

@ -20,7 +20,7 @@
## 未完成的文档
[传送门](https://hibikier.github.io/zhenxun_bot/)
# [传送门](https://hibikier.github.io/zhenxun_bot/)
## 真寻的帮助
请对真寻说: '真寻帮助' or '管理员帮助' or '超级用户帮助' or '真寻帮助 指令'
@ -29,6 +29,17 @@
[AkashiCoin/nonebot_plugins_zhenxun_bot](https://github.com/AkashiCoin/nonebot_plugins_zhenxun_bot)
## 来点优点?
一.作为bot
* 实现了许多功能,且提供了大量功能管理命令
* __..... 更多详细请通过`传送门`查看文档__
二.作为框架?:
* 通过Config配置项将所有插件配置统计保存至config.yaml利于统一用户修改
* 方便增删插件原生nonebot2 matcher不需要额外修改仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息`
* 提供了cd阻塞每日次数等限制仅仅通过简单的属性就可以生成一个限制例如`__plugin_cd_limit__`
* __..... 更多详细请通过`传送门`查看文档__
## 功能列表
<details>
@ -210,6 +221,20 @@ python bot.py
## 更新
### 2021/1/5 \[v0.0.7.2]
* 提供金币消费hook可在plugins2settings.yaml中配置该功能需要消费的金币
* 商店插件将作为内置插件移动至basic_plugins
* 商店插件通过export提供了方法不需要修改商店插件代码添加商品数据和生效方法
* 修改了hook插件顺序主要以auth_hook为主
* 修改商店图片样式
* 取消每次启动更新城市列表首次除外采用定时更新加快bot启动速度
* 取消每次启动时截取今日素材采用调用时截取保存加快bot启动速度
* 更新色图时当图片404时会删除并替换
* 疫情消息回复改为图片
* 修复商店折扣和限时时间无法生效
* 修复原神玩家查询尘歌壶缺少图片
### 2021/12/26
* 修复群词条问题 空格 会被录入导致不断回复
@ -221,7 +246,7 @@ python bot.py
### 2021/12/20
* 只有当真的发布新动态/视频的时候才获取并推送 [@pull/96](https://github.com/HibiKier/zhenxun_bot/pull/96)
* 只有发布小于存储时间的新动态/视频的时候才获取并推送 [@pull/96](https://github.com/HibiKier/zhenxun_bot/pull/96)
### 2021/12/16 \[v0.0.7.0]
@ -246,366 +271,26 @@ python bot.py
* 修改了权限插件加载顺序防止小概率优先加载权限插件引起报错
* 本地图库新图库会统一建立在resource/img/image_management文件夹下如果该文件夹内未找到图库会从上级目录查找resource/img/
### 2021/12/1 \[v0.0.6.5/6]
<br>
* 群权限-1时超级用户命令依旧生效
* 修复以真寻为开头的词条不会被回复
* 修复购买道具可以为负数
* P站排行/搜图提供配置项,将略过大于指定张数的作品
* 昵称提供关键词屏蔽配置项,会将指定关键词替换为“*”
* 取消了自动更新,改为自动检测版本
* 自动更新不再覆盖config.py和移动config.yaml
### 2021/11/29 \[v0.0.6.4]
* 新增cos图撤回配置项
* 新增默认群权限配置项
* 修复权限等级类配置无法正常应用
### 2021/11/24 \[v0.0.6.3]
* 修复在线搜索色图出错
* 修复pix无法正确获取HIBIAPI
### 2021/11/23 \[v0.0.6.2]
* 替换cos API
* 提供私聊b了即跨群b了用户
* 修复游戏抽卡导入角色失败(原神)
* 修复无Pixiv代理时报错
* 将项目中大部分aiohttp替换为httpx
* 删除了丘丘人翻译插件
* 新增群词条
* 修复游戏抽卡碧蓝航线bwiki格式更改导致获取报错
* 首次启动会生成配置文件后停止程序,配置后再次启动即可
### 2021/11/18
* 修复超级用户无法正确拉真寻入群
### 2021/11/14
* 修复功能总开关无法正确开启
### 2021/11/12
* 修复PIX无法url无法正确获取
### 2021/11/10
* 修复PIX表重复创建导致首次无法运行
* 检测Omage图库改为命令方式检测omega图库
### 2021/11/9
* 修复管理员帮助无法正常响应
* 修复被ban时会一直回复被ban提醒
### 2021/11/5
* 修复ai没有图灵key时报错
* 提供图片路径resource/img/background/check
### 2021/11/4
* 通用排行榜改用图片消息,且可以自定义排行榜人数
* 优化CreateMat排行榜数据显示
* 修复了pix更新多余参数导致失败的问题
* 修复滴滴滴-注入风险
* 修复无法正常关闭滴滴滴,戳一戳
* 添加了发送图片撤回配置项WITHDRAW_IMAGE_TIME
* 修复了天气regex文本过长时会正则匹配过久导致nb卡顿
* message_build新增custom_forward_msg用于快捷生成转发消息
* 插件配置改为yaml存储新增Config用于获取和新增插件配置
* 新增 当插件加载失败时,会发送消息提醒超级用户,且在功能状态中对应失败插件写上[ERROR]
* 修复当查看-spuer插件帮助时无法正确回复
* 群内帮助图片会随群内功能开关和插件总开关变化
* 自检改为图像形式
* 更新色图删除了rar_setur18_rar和rar文件夹压缩将统一在temp文件夹
* 更新色图只有在有更新数量或报错时才会提醒超级用户
* 群欢迎消息加入cd
* 加入资源管理resources_manager
* 新增 好友请求/群聊邀请 控制命令
### 2021/10/15
* 适配了原神资源查询米游社地图返回的新格式
### 2021/10/8
* 修复疫情省份查询失效
* 修复功能调用统计全局下统计可能发生错误
### 2021/10/4
* 修复了功能调用统计失效问题
* 当色图库中没有色图时,会在线搜索色图而不是‘没找到符合条件的色图...
* 快速更新权限再给超级用户发送错误日志
* 修复疫情未加载省份城市无法正常使用
### 2021/10/3
* 对插件进行分离
* 重写了插件与限制管理器以及帮助获取
* 修改一些插件目录和数据存储目录
* 插件通用配置与限制数据将以ymal文件存储 \[路径data/configs]
* 所有商店相关操作调用统计合并为商店(包括之前已经保存的数据,会先进行备份)
* 简化了点歌的代码相关
* 修复了碧蓝航线抽卡新框导致报错无法正常初始化
* 修复了P站排行/搜图在PC端无法正常显示
* 添加了插件对超级用户是否限制的配置 limit_superuser
* 添加命令 ‘重载插件配置’,用于生效手动修改配文件
* 超级用户帮助可以添加 -super 来显示该插件的超级用户帮助,示例:帮助.ban -super
* 原神黄历改为网页截图
* 修改了鲁迅说逻辑结构
* 修改了统计图表样式改为自定义CreateMat
* 节日红包不再被24小时限制群内多个节日红包将会覆盖
* 当群权限为-1时不会对群发送修改权限通知并屏蔽此群一切命令包括提醒
* 修复了红包数量可以过大或为负数,红包数量大于群员数量时会修改为群员数量
* 修复了负数开箱
* 签到最低好感度设置为0.01 [@pull/53](https://github.com/HibiKier/zhenxun_bot/pull/53)
* pip安装新依赖 ruamel.yaml
* 修复功能 EPIC [@pull/58](https://github.com/HibiKier/zhenxun_bot/pull/58)
### 2021/9/10
* 修复撤回消息有时无法正确获取消息id
### 2021/9/9
* 替换coser API
* 修复签到uid可能不默认为0
* 修复签到可能重复的问题
* 修复无订阅时递归出错
* 启用了plugins2info_dict, plugins2cd_dict, plugins2exists_dict配置文件通过USE_CONFIG_FILE=True开启
* 修复涩图local_id会被固定为50
* 优化图库数量查询
* 修复原神大地图过大无法打开报错
* 修复无法显示正确的涩图上限
### 2021/9/7
* 修改 update_info.json
* 修改 更新信息 图片大小
* 修复 查看订阅 命令 UP和番剧无法正常显示
* 修复订阅推送无法正确推送
* 修复搜图返回列表为空时无法正确回复 [@pull/40](https://github.com/HibiKier/zhenxun_bot/pull/40)
### 2021/9/5
* 添加配置PIX_IMAGE_SIZE调整PIX下载图片大小当设置的图片404时改为原图
* 新增配置DEFAULT_GROUP_LEVEL默认群等级
* 新增超级用户功能 super ban将屏蔽被ban用户的所有消息指令b了
* b站转发解析支持纯BV号解析且五分钟内不会解析相同url
* 俄罗斯轮盘新增 连胜/最高连胜/连败/最高连败 纪录,新增 最高连胜排行榜/最高连败排行榜
* 增加扩展图库 OmegaPixivIllusts不想自己找图的人福音[Ailitonia](https://github.com/Ailitonia) 佬的高质量精品手筛图库)([传送门](https://github.com/Ailitonia/omega-miya/blob/master/archive_data/db_pixiv.7z) )可以手动导入图库也可以将解压文件放在bot.py同级目录重启bot
* 增加配置PIX_OMEGA_PIXIV_RATIOPIX功能发送PIX图库和扩展图库OmegaPixivIllusts图片的比例如果没有使用扩展图库OmegaPixivIllusts请设置为(10, 0)
* 增加配置WITHDRAW_PIX_TIME用于配置在开关PIX图片在群私聊的自动撤回
* 上传图库cases 开箱 也可以连抽(未更新过没有价格)
* 新增命令 查看群白名单
* plugins2info_dict新增键"default_status",设置加入新群时功能的默认开关状态
* 增加配置plugins2exists_dict可自定义是否阻塞某命令同时触发多次
* 增加配置plugins2cd_dict可自定义为命令添加cd
* 新增B站订阅直播/番剧/UP[测试],提供命令:添加订阅 [主播/UP/番剧] [id/链接/番名],删除订阅 [id],查看订阅
* 优化pix和色图的数据库查询
* 触发已关闭的功能的正则时不再触发ai
* 更换coser API
* PIX搜索pid功能在群聊无法搜索PIX图库的r18和OmegaPixivIllusts的r15以及r18超级用户除外
* PIX单次搜索的图片张数超级用户限制为至多30张普通用户10张
* PIX超级用户新增-s-r可以通过pix -s 查看图库的涩图pix -r查看图库的r18图支持搜索当然pix图库只区分了r18和非r18如果-s查询到不色的图也问题不大
* 优化P站排行和搜图现在需要艾特改为使用HIBIAPI在群内时将使用合并消息群聊搜图会屏蔽R-18
* win10下playwright相关功能无法使用但是不再需要删除文件
* 签到大改,优化签到方式与逻辑,改为图片形式发送,有概率额外获得随机道具(好感度有加成)
* 修改撤回功能,改为回复撤回,回复发送撤回
* 更改logging为loguru
* 删除了 发送图片 中的 [N]张图[keyword] 功能
* 修复私聊 关闭[功能] 默认不为 全部 而要添加参数 a
* 修复0权限用户可以修改禁言检测相关设置
### 2021/8/17
* 新增配置CHECK_NOTICE_INFO_CD修改群权限个人权限检测各种检测的提示消息cd
* 新增功能连续上传图片功能直到输入stop停止
* 新增功能维护时白名单以及对应命令(白名单中的群聊不受维护限制)
* 新增ALAPI功能微博热搜可以通过序号来查看部分热搜内容
* 新增配置NICKNAME偶尔也想换换名字的说自我介绍仅当NICKNAME=真寻时生效)
* 提供 更新信息 命令,可以使群员查看更新内容(可开关,与其他功能无异,但不会被统计,该命令图片由自动更新生成)
* 超级用户可以通过私聊来对指定qq进行ban/unban
* 超级用户帮助改为图片形式
* 公开图库删除‘色图’
* 群权限检测,个人权限检测,功能开关检测合并,权限检测顺序:个人权限 > 群权限 > 插件开关 >超级用户禁用某群插件 > 超级用户限制群里插件 > 插件维护检测
* 重写群功能管理,超级用户可对群/私聊分别禁用,也可禁用指定群指定功能,新增命令‘功能状态’,超级用户关闭功能提供参数(默认ALL)group/g群聊private/p私聊
* 超级用户不会被任何权限等检测阻挡
* 不会重复复读,复读消息只会发送一次
* b站转发解析支持b23.tvwww.bilibili.com链接cv专栏(playwright截图压缩倍率0.5,较慢且文字可能不清晰,后优化)
* 我有一个朋友功能,当艾特一个对象时,‘朋友’改为艾特对象的群名片或昵称
* 修复‘上传/删除/移动图片’目录不正确
* 修复天气功能,当城市名在‘天气’后时报错
* 修复配置INITIAL_SETU_PROBABILITY不生效
### 2021/8/10
* 重复的好友请求和邀群提示在5分钟内不会重复提示
* 疫情会优先检查城市,城市省份市区重名时请添加‘市’
* 添加命令原神资源查找设置cookie
* 添加配置AUTO_UPDATE_ZHENXUN是否自动更新真寻默认True
* 添加配置MAX_RUSSIAN_BET_GOLD俄罗斯轮盘赌注最大金额默认1000
* 检查更新真寻定时任务时间改为12 : 00
* 添加功能能不能好好说话(nbnhhsh)
* 添加功能随机roll无参为数字有参为随机参数
* 添加linux重启脚本以及重启命令重启建议首次生成restart.sh先查看命令是否正确
* 修复管理员功能的权限检测
* 修复丢人爬开关
### 2021/8/6
* 天气查询会优先遍历城市
* 添加自动更新真寻命令
##### 如果你的版本为 2021/8/4可以直接复制plugins/check_zhenxun_update后通过指令来更新真寻
### 2021/8/4
* 修改天气与疫情城市数据改为api获取丰富疫情的回复消息
* 原神资源查询大地图将被压缩至9M且启动时当大地图存在时不再自动更新地图
* 下载数据库内色图时将直接存储至_setu不再存储至临时文件
* 重复的好友请求或邀请请求在一定时间不会重复发送提醒
* 添加每日自动清理临时图片定时任务
* 修复金币排行显示
* 修复无法正常关闭戳一戳功能
### 2021/7/30
* 重构代码,进行优化,添加注释,删除冗余代码,降低代码耦合
* 添加功能PIX一套快捷的pixiv存图命令自建图库存储url等信息意在获取自己或群友xp的图
* 添加功能清理临时图片文件temp/rar/r18_rar文件夹
* 添加额外定时任务5分钟检测一次解决加入新群时无法及时为管理员提供权限
* 添加配置ALAPI_AI_CHECK开关AI回复文本检测
* 添加配置IMPORT_DEFAULT_SHOP_GOODS控制是否导入内置的三个商品好感度加持卡ⅡⅢ
* 添加配置ONLY_USE_LOCAL_SETU仅仅使用本地色图有的话提升速度但无法在线搜索色图和保存链接
* 添加配置WITHDRAW_SETU_TIME是否需要延迟撤回色图可配置仅群里私聊或全部
* 好友请求,入群请求,滴滴滴-/t被踢出群提醒的提示消息更加丰富
* 彻底重写原神资源查找,添加规划路线(路线残缺缺缺缺版,有空补)添加命令‘更新原神资源信息’,强制更新地图等资源
* 优化色图和P站排行/搜图检测用户是否正在触发命令代码
* 当群最后发言大于36小时也会关闭广播通知
* 功能维护时超级用户依然可以调用(苦了谁都不能苦了自己)
* 修复获取赛马娘UP公告
* 重写 色图/更新色图
* 色图数据存储改为数据库,启动时会更新之前的色图数据(有的话),更新完毕后会删除原数据文件,如果需要保留请提前备份,
* lolicon api改为v2
* 取消r18次数限制
* 单次搜索至多保存100条链接
* 添加定时撤回
* 暂时取消上传/删除色图
*
* 更新建议不要替换你的data和resources文件夹
* 删除configspluginsservicesutilsmodels文件夹重新clone
* 删除多余文件夹resources/img/genshin/seek_god_eye
* 清空resources/img/genshin/genshin_icon文件夹仅保留box.png和box_alpha.png
* 替换bot.py
### 2021/7/27
* 原神今日素材改为单张截图+拼图更新文件utils/img_utils.py及plugins/genshin/material_remind/__init__.py
### 2021/7/26
* 修复原神今日素材稻妻城开放后截图不完整的问题
### 2021/7/14
* 原神今日素材自动更新时间由 00:01 -> 04:01 [#issues7](https://github.com/HibiKier/zhenxun_bot/issues/7)
* 小问题的修复和优化
### 2021/7/12
* 修复开箱功能单抽出金时存储格式错误导致 ‘我的金色’ 无法正常发送图片
* 小问题的修复和优化
### 2021/7/6
* 识番功能 trace.moe 替换为新API旧API已失效
* 小问题的修复和优化
### 2021/6/30
* 将plugin2name和plugin2level合并为plugin2info
* util改为utils。。
* 修复当用户发送速度极快时开箱会突破每日限制
* 新增功能通过PID获取图片
* 发送图片新增功能:搜索图片
* 功能统计可视化
* 新增命令:好感度总排行
* 原神每日素材改为从"可莉特调"截图,提供命令‘更新原神每日素材’和定时任务
* 修复月功能统计错误的问题
### 2021/6/24
* 添加了一些ALAPI网易云热评获取b站视频封面古诗需要填写ALAPI_TOKEN
* 如果填写了ALAPI_TOKEN将会检测备用接口回复的文本是否合规
* 优化了色图当搜索色图下载失败时会从本地色图库中发送相关tag色图
* 当网易云点歌繁忙时会尝试多次点歌
### 2021/6/23
* 添加功能群权限所以说内鬼都快爬可以在configs/config.py中修改各个功能的权限等级
* 优化了数据统计将以7天30天为周期为将来更方便实现数据可视化
* 更新坎公骑冠剑UP卡池
* 修复赛马娘UP卡池
* 修复一些小问题
### 2021/6/18
* 修复p站排行搜图因网络问题爆炸时没有具体回复
* 更换色图显示方式为 idtitleauthorpid
* 修复修改商品后商品顺序改变
* 滴滴滴- 和 /t支持图片回复
* 将/t回复更加简单(可以通过序号),且可以直接发送群
* 修复bt功能无法交互
### 2021/6/17
* 修复p站排行搜图因网络问题爆炸时没有具体回复
* 更换色图显示方式为 idtitleauthorpid
### 2021/6/15
* 修改了‘帮助’功能,具体为‘帮助 指令名’,未指定指令名时则为查看全部功能列表
* 修改了色图的存储数据格式
* 色图功能搜索的色图改为随机从urls中随机抽取
* 将商品数据存储入数据库,提供 '增加/删除/修改商品' 指令
* 商店列表图片不再使用固定背景图,改为直接拼图
* 增加功能:俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
* 增加功能:金币红包(节日红包与群红包相互独立)
* 金币排行
* 重写一个朋友插件
* 其他微小调整
### 2021/6/4
* 重写BT功能
* 进行一些BUG修复和微小调整
* 添加撤回功能[nonebot-plugin-withdraw](https://github.com/MeetWq/nonebot-plugin-withdraw)
* 为色图功能添加额外的 上传色图 和 删除色图方法影响hash
### 2021/5/26
* 将语录源更换为一言api
__..... 更多更新信息请查看文档__
## Todo
- [ ] 提供更多对插件的控制
- [ ] 明日方舟卡片式的签到..(大概)
- [ ] 更多的群管理功能
- [ ] 数据清理控制
- [ ] docker容器
- [ ] web管理
## 感谢
[Onebot](https://github.com/howmanybots/onebot)
[go-cqhttp](https://github.com/Mrs4s/go-cqhttp)
[nonebot2](https://github.com/nonebot/nonebot2)
[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)
[cappuccilo_plugins](https://github.com/pcrbot/cappuccilo_plugins#%E7%94%9F%E6%88%90%E5%99%A8%E6%8F%92%E4%BB%B6)
[nonebot-plugin-withdraw](https://github.com/MeetWq/nonebot-plugin-withdraw)
[nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2)
[nonebot_plugin_manager](https://github.com/Jigsaw111/nonebot_plugin_manager)
[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)
[nonebot2_luxun_says](https://github.com/NothAmor/nonebot2_luxun_says)
[AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus)
[omega-miya](https://github.com/Ailitonia/omega-miya)
[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异步机器人框架
[Angel-Hair / XUN_Bot](https://github.com/Angel-Hair/XUN_Bot) 一个基于NoneBot和酷Q的功能性QQ机器人
[pcrbot / cappuccilo_plugins](https://github.com/pcrbot/cappuccilo_plugins) hoshino插件合集
[MeetWq /nonebot-plugin-withdraw](https://github.com/MeetWq/nonebot-plugin-withdraw) A simple withdraw plugin for Nonebot2
[maxesisn / nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2) 适用于nonebot2的点歌插件
[nonepkg / nonebot-plugin-manager](https://github.com/nonepkg/nonebot-plugin-manager) Nonebot Plugin Manager base on import hook
[H-K-Y / Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot) 原神bot这是一个基于nonebot和HoshinoBot的原神娱乐及信息查询插件
[NothAmor / nonebot2_luxun_says](https://github.com/NothAmor/nonebot2_luxun_says) 基于nonebot2机器人框架的鲁迅说插件
[Kyomotoi / AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus) :一个~~特二刺螈~~文爱的适用于任何bot的词库
[Ailitonia / omega-miya](https://github.com/Ailitonia/omega-miya) 基于nonebot2的qq机器人
[KimigaiiWuyi / GenshinUID]("https://github.com/KimigaiiWuyi/GenshinUID") 一个基于HoshinoBot/NoneBot2的原神UID查询插件

View File

@ -1 +1 @@
__version__: v0.0.7.1
__version__: v0.0.8.0

View File

@ -1,19 +1,29 @@
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException
from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
from nonebot.adapters.cqhttp.exception import ActionFailed
from models.friend_user import FriendUser
from models.group_member_info import GroupInfoUser
from models.bag_user import BagUser
from utils.manager import (
plugins2settings_manager,
admin_manager,
group_manager,
plugins_manager,
plugins2cd_manager,
plugins2block_manager,
plugins2count_manager
)
from .utils import set_block_limit_false, status_message_manager
from nonebot.typing import T_State
from typing import Optional
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent,
PokeNotifyEvent
PokeNotifyEvent,
PrivateMessageEvent,
Message,
Event
)
from configs.config import Config
from models.ban_user import BanUser
@ -22,13 +32,11 @@ from utils.message_builder import at
from models.level_user import LevelUser
import nonebot
_flmt = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
_flmt_g = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
_flmt_s = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
_flmt_c = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
ignore_rst_module = ["ai", "poke", "dialogue"]
@ -37,15 +45,27 @@ ignore_rst_module = ["ai", "poke", "dialogue"]
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
module = matcher.module
plugins2info_dict = plugins2settings_manager.get_data()
# 功能的金币检测 #######################################
# 功能的金币检测 #######################################
# 功能的金币检测 #######################################
cost_gold = 0
if isinstance(event, GroupMessageEvent) and plugins2settings_manager.get_plugin_data(module).get('cost_gold'):
cost_gold = plugins2settings_manager.get_plugin_data(module).get('cost_gold')
if await BagUser.get_gold(event.user_id, event.group_id) < cost_gold:
await send_msg(f"金币不足..该功能需要{cost_gold}金币..", bot, event)
raise IgnoredException(f"{module} 金币限制...")
# 当插件不阻塞超级用户时,超级用户提前扣除金币
if str(event.user_id) in bot.config.superusers and not plugins2info_dict[module]["limit_superuser"]:
await BagUser.spend_gold(event.user_id, event.group_id, cost_gold)
try:
if (
(not isinstance(event, MessageEvent) and module != "poke")
or await BanUser.is_ban(event.user_id)
and str(event.user_id) not in bot.config.superusers
(not isinstance(event, MessageEvent) and module != "poke")
or await BanUser.is_ban(event.user_id)
and str(event.user_id) not in bot.config.superusers
) or (
str(event.user_id) in bot.config.superusers
and plugins2info_dict.get(module)
and not plugins2info_dict[module]["limit_superuser"]
str(event.user_id) in bot.config.superusers
and plugins2info_dict.get(module)
and not plugins2info_dict[module]["limit_superuser"]
):
return
except AttributeError:
@ -56,8 +76,8 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
_module = _plugin.module
plugin_name = _module.__getattribute__("__zx_plugin_name__")
if (
"[superuser]" in plugin_name.lower()
and str(event.user_id) in bot.config.superusers
"[superuser]" in plugin_name.lower()
and str(event.user_id) in bot.config.superusers
):
return
except AttributeError:
@ -79,12 +99,12 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if isinstance(event, GroupMessageEvent):
# 个人权限
if (
not await LevelUser.check_level(
event.user_id,
event.group_id,
admin_manager.get_plugin_level(module),
)
and admin_manager.get_plugin_level(module) > 0
not await LevelUser.check_level(
event.user_id,
event.group_id,
admin_manager.get_plugin_level(module),
)
and admin_manager.get_plugin_level(module) > 0
):
try:
if _flmt.check(event.user_id):
@ -92,7 +112,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
await bot.send_group_msg(
group_id=event.group_id,
message=f"{at(event.user_id)}你的权限不足喔,该功能需要的权限等级:"
f"{admin_manager.get_plugin_level(module)}",
f"{admin_manager.get_plugin_level(module)}",
)
except ActionFailed:
pass
@ -102,7 +122,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
raise IgnoredException("权限不足")
else:
if not await LevelUser.check_level(
event.user_id, 0, admin_manager.get_plugin_level(module)
event.user_id, 0, admin_manager.get_plugin_level(module)
):
try:
await bot.send_private_msg(
@ -118,12 +138,12 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if module in plugins2info_dict.keys() and matcher.priority not in [1, 9]:
# 戳一戳单独判断
if isinstance(event, GroupMessageEvent) or (
isinstance(event, PokeNotifyEvent) and event.group_id
isinstance(event, PokeNotifyEvent) and event.group_id
):
if status_message_manager.get(event.group_id) is None:
status_message_manager.delete(event.group_id)
if plugins2info_dict[module]["level"] > group_manager.get_group_level(
event.group_id
event.group_id
):
try:
if _flmt_g.check(event.user_id) and module not in ignore_rst_module:
@ -141,7 +161,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if not group_manager.get_plugin_status(module, event.group_id):
try:
if module not in ignore_rst_module and _flmt_s.check(
event.group_id
event.group_id
):
_flmt_s.start_cd(event.group_id)
await bot.send_group_msg(
@ -157,8 +177,8 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if not group_manager.get_plugin_status(f"{module}:super", event.group_id):
try:
if (
_flmt_s.check(event.group_id)
and module not in ignore_rst_module
_flmt_s.check(event.group_id)
and module not in ignore_rst_module
):
_flmt_s.start_cd(event.group_id)
await bot.send_group_msg(
@ -174,8 +194,8 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if not plugins_manager.get_plugin_status(module, block_type="group"):
try:
if (
_flmt_c.check(event.group_id)
and module not in ignore_rst_module
_flmt_c.check(event.group_id)
and module not in ignore_rst_module
):
_flmt_c.start_cd(event.group_id)
await bot.send_group_msg(
@ -205,14 +225,14 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
# 维护
if not plugins_manager.get_plugin_status(module, block_type="all"):
if isinstance(
event, GroupMessageEvent
event, GroupMessageEvent
) and group_manager.check_group_is_white(event.group_id):
return
try:
if isinstance(event, GroupMessageEvent):
if (
_flmt_c.check(event.group_id)
and module not in ignore_rst_module
_flmt_c.check(event.group_id)
and module not in ignore_rst_module
):
_flmt_c.start_cd(event.group_id)
await bot.send_group_msg(
@ -233,3 +253,154 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
status_message_manager.add(id_)
set_block_limit_false(event, module)
raise IgnoredException("此功能正在维护...")
# 以下为限制检测 #######################################################
# 以下为限制检测 #######################################################
# 以下为限制检测 #######################################################
# 以下为限制检测 #######################################################
# 以下为限制检测 #######################################################
# 以下为限制检测 #######################################################
# Cd
if plugins2cd_manager.check_plugin_cd_status(module):
plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
check_type = plugin_cd_data["check_type"]
limit_type = plugin_cd_data["limit_type"]
rst = plugin_cd_data["rst"]
if (
(isinstance(event, PrivateMessageEvent) and check_type == "private")
or (isinstance(event, GroupMessageEvent) and check_type == "group")
or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all"
):
cd_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
cd_type_ = event.group_id
if not plugins2cd_manager.check(module, cd_type_):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{module} 正在cd中...")
else:
plugins2cd_manager.start_cd(module, cd_type_)
module = matcher.module
if (
isinstance(event, GroupMessageEvent)
and status_message_manager.get(event.group_id) is None
):
status_message_manager.delete(event.group_id)
# Cd
if plugins2cd_manager.check_plugin_cd_status(module):
plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
check_type = plugin_cd_data["check_type"]
limit_type = plugin_cd_data["limit_type"]
rst = plugin_cd_data["rst"]
if (
(isinstance(event, PrivateMessageEvent) and check_type == "private")
or (isinstance(event, GroupMessageEvent) and check_type == "group")
or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all"
):
cd_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
cd_type_ = event.group_id
if not plugins2cd_manager.check(module, cd_type_):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{module} 正在cd中...")
else:
plugins2cd_manager.start_cd(module, cd_type_)
# Block
if plugins2block_manager.check_plugin_block_status(module):
plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
check_type = plugin_block_data["check_type"]
limit_type = plugin_block_data["limit_type"]
rst = plugin_block_data["rst"]
if (
(isinstance(event, PrivateMessageEvent) and check_type == "private")
or (isinstance(event, GroupMessageEvent) and check_type == "group")
or check_type == "all"
):
block_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
block_type_ = event.group_id
if plugins2block_manager.check(block_type_, module):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{event.user_id}正在调用{module}....")
else:
plugins2block_manager.set_true(block_type_, module)
# Count
if (
plugins2count_manager.check_plugin_count_status(module)
and event.user_id not in bot.config.superusers
):
plugin_count_data = plugins2count_manager.get_plugin_count_data(module)
limit_type = plugin_count_data["limit_type"]
rst = plugin_count_data["rst"]
count_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
count_type_ = event.group_id
if not plugins2count_manager.check(module, count_type_):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{module} count次数限制...")
else:
plugins2count_manager.increase(module, count_type_)
# 功能花费的金币 #######################################
# 功能花费的金币 #######################################
if cost_gold:
await BagUser.spend_gold(event.user_id, event.group_id, cost_gold)
async def send_msg(rst: str, bot: Bot, event: MessageEvent):
"""
发送信息
:param rst: pass
:param bot: pass
:param event: pass
"""
rst = await init_rst(rst, event)
try:
if isinstance(event, GroupMessageEvent):
status_message_manager.add(event.group_id)
await bot.send_group_msg(group_id=event.group_id, message=Message(rst))
else:
status_message_manager.add(event.user_id)
await bot.send_private_msg(user_id=event.user_id, message=Message(rst))
except ActionFailed:
pass
# 解除命令block阻塞
@run_postprocessor
async def _(
matcher: Matcher,
exception: Optional[Exception],
bot: Bot,
event: Event,
state: T_State,
):
if not isinstance(event, MessageEvent) and matcher.module != "poke":
return
module = matcher.module
set_block_limit_false(event, module)
async def init_rst(rst: str, event: MessageEvent):
if "[uname]" in rst:
uname = event.sender.card if event.sender.card else event.sender.nickname
rst = rst.replace("[uname]", uname)
if "[nickname]" in rst:
if isinstance(event, GroupMessageEvent):
nickname = await GroupInfoUser.get_group_member_nickname(
event.user_id, event.group_id
)
else:
nickname = await FriendUser.get_friend_nickname(event.user_id)
rst = rst.replace("[nickname]", nickname)
if "[at]" in rst and isinstance(event, GroupMessageEvent):
rst = rst.replace("[at]", str(at(event.user_id)))
return rst

View File

@ -1,146 +0,0 @@
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
from nonebot.adapters.cqhttp.exception import ActionFailed
from models.friend_user import FriendUser
from models.group_member_info import GroupInfoUser
from utils.message_builder import at
from .utils import status_message_manager, set_block_limit_false
from utils.manager import (
plugins2cd_manager,
plugins2block_manager,
plugins2count_manager,
)
from typing import Optional
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import (
Bot,
Event,
MessageEvent,
PrivateMessageEvent,
GroupMessageEvent,
Message,
)
# 命令cd | 命令阻塞 | 命令次数
@run_preprocessor
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if not isinstance(event, MessageEvent) and matcher.module != "poke":
return
module = matcher.module
if (
isinstance(event, GroupMessageEvent)
and status_message_manager.get(event.group_id) is None
):
status_message_manager.delete(event.group_id)
# Count
if (
plugins2count_manager.check_plugin_count_status(module)
and event.user_id not in bot.config.superusers
):
plugin_count_data = plugins2count_manager.get_plugin_count_data(module)
limit_type = plugin_count_data["limit_type"]
rst = plugin_count_data["rst"]
count_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
count_type_ = event.group_id
if not plugins2count_manager.check(module, count_type_):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{module} count次数限制...")
else:
plugins2count_manager.increase(module, count_type_)
# Cd
if plugins2cd_manager.check_plugin_cd_status(module):
plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
check_type = plugin_cd_data["check_type"]
limit_type = plugin_cd_data["limit_type"]
rst = plugin_cd_data["rst"]
if (
(isinstance(event, PrivateMessageEvent) and check_type == "private")
or (isinstance(event, GroupMessageEvent) and check_type == "group")
or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all"
):
cd_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
cd_type_ = event.group_id
if not plugins2cd_manager.check(module, cd_type_):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{module} 正在cd中...")
else:
plugins2cd_manager.start_cd(module, cd_type_)
# Block
if plugins2block_manager.check_plugin_block_status(module):
plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
check_type = plugin_block_data["check_type"]
limit_type = plugin_block_data["limit_type"]
rst = plugin_block_data["rst"]
if (
(isinstance(event, PrivateMessageEvent) and check_type == "private")
or (isinstance(event, GroupMessageEvent) and check_type == "group")
or check_type == "all"
):
block_type_ = event.user_id
if limit_type == "group" and isinstance(event, GroupMessageEvent):
block_type_ = event.group_id
if plugins2block_manager.check(block_type_, module):
if rst:
rst = await init_rst(rst, event)
await send_msg(rst, bot, event)
raise IgnoredException(f"{event.user_id}正在调用{module}....")
else:
plugins2block_manager.set_true(block_type_, module)
async def send_msg(rst: str, bot: Bot, event: MessageEvent):
"""
发送信息
:param rst: pass
:param bot: pass
:param event: pass
"""
rst = await init_rst(rst, event)
try:
if isinstance(event, GroupMessageEvent):
status_message_manager.add(event.group_id)
await bot.send_group_msg(group_id=event.group_id, message=Message(rst))
else:
status_message_manager.add(event.user_id)
await bot.send_private_msg(user_id=event.user_id, message=Message(rst))
except ActionFailed:
pass
# 解除命令block阻塞
@run_postprocessor
async def _(
matcher: Matcher,
exception: Optional[Exception],
bot: Bot,
event: Event,
state: T_State,
):
if not isinstance(event, MessageEvent) and matcher.module != "poke":
return
module = matcher.module
set_block_limit_false(event, module)
async def init_rst(rst: str, event: MessageEvent):
if "[uname]" in rst:
uname = event.sender.card if event.sender.card else event.sender.nickname
rst = rst.replace("[uname]", uname)
if "[nickname]" in rst:
if isinstance(event, GroupMessageEvent):
nickname = await GroupInfoUser.get_group_member_nickname(
event.user_id, event.group_id
)
else:
nickname = await FriendUser.get_friend_nickname(event.user_id)
rst = rst.replace("[nickname]", nickname)
if "[at]" in rst and isinstance(event, GroupMessageEvent):
rst = rst.replace("[at]", str(at(event.user_id)))
return rst

View File

@ -71,6 +71,8 @@ def init_plugins_settings(data_path: str):
plugin_settings = _module.__getattribute__(
"__plugin_settings__"
)
if plugin_settings.get('cost_gold') is None:
plugin_settings['cost_gold'] = 0
if (
plugin_settings["cmd"] is not None
and plugin_name not in plugin_settings["cmd"]
@ -97,7 +99,7 @@ def init_plugins_settings(data_path: str):
plugins2settings_manager.add_plugin_settings(
matcher.module,
plugin_type=plugin_type,
data_dict=plugin_settings,
**plugin_settings,
)
except AttributeError:
pass

View File

@ -7,6 +7,7 @@ from services.log import logger
from configs.path_config import TEXT_PATH
from asyncio.exceptions import TimeoutError
from utils.http_utils import AsyncHttpx
from utils.utils import scheduler
from pathlib import Path
import nonebot
@ -27,31 +28,32 @@ async def update_city():
"""
china_city = Path(TEXT_PATH) / "china_city.json"
data = {}
try:
res = await AsyncHttpx.get(
"http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
)
res.encoding = "utf8"
provinces_data = json.loads(res.text)
for province in provinces_data.keys():
data[provinces_data[province]] = []
if not china_city.exists():
try:
res = await AsyncHttpx.get(
f"http://www.weather.com.cn/data/city3jdata/provshi/{province}.html",
timeout=5,
"http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
)
res.encoding = "utf8"
city_data = json.loads(res.text)
for city in city_data.keys():
data[provinces_data[province]].append(city_data[city])
with open(china_city, "w", encoding="utf8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
logger.info("自动更新城市列表完成.....")
except TimeoutError:
logger.warning("自动更新城市列表超时.....")
except ValueError:
logger.warning("自动城市列表失败.....")
except Exception as e:
logger.error(f"自动城市列表未知错误 {type(e)}{e}")
provinces_data = json.loads(res.text)
for province in provinces_data.keys():
data[provinces_data[province]] = []
res = await AsyncHttpx.get(
f"http://www.weather.com.cn/data/city3jdata/provshi/{province}.html",
timeout=5,
)
res.encoding = "utf8"
city_data = json.loads(res.text)
for city in city_data.keys():
data[provinces_data[province]].append(city_data[city])
with open(china_city, "w", encoding="utf8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
logger.info("自动更新城市列表完成.....")
except TimeoutError:
logger.warning("自动更新城市列表超时.....")
except ValueError:
logger.warning("自动城市列表失败.....")
except Exception as e:
logger.error(f"自动城市列表未知错误 {type(e)}{e}")
@driver.on_startup
@ -101,3 +103,13 @@ async def _(bot: Bot):
else:
await GroupInfo.delete_group_info(group_id)
logger.info(f"移除不存在的群聊信息:{group_id}")
# 自动更新城市列表
@scheduler.scheduled_job(
"cron",
hour=6,
minute=1,
)
async def _():
await update_city()

View File

@ -11,4 +11,4 @@ Config.add_plugin_config(
)
nonebot.load_plugins("plugins/shop")
nonebot.load_plugins("basic_plugins/shop")

175
plugins/shop/buy.py → basic_plugins/shop/buy.py Executable file → Normal file
View File

@ -1,89 +1,86 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from utils.utils import get_message_text, is_number
from models.bag_user import BagUser
from services.db_context import db
from nonebot.adapters.cqhttp.permission import GROUP
from .models.goods_info import GoodsInfo
__zx_plugin_name__ = "商店 - 购买道具"
__plugin_usage__ = """
usage
购买道具
指令
购买 [序号或名称] ?[数量=1]
示例购买 好感双倍加持卡Ⅰ
示例购买 1 4
""".strip()
__plugin_des__ = "商店 - 购买道具"
__plugin_cmd__ = ["购买 [序号或名称] ?[数量=1]"]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店", "购买道具"],
}
buy = on_command("购买", aliases={"购买道具"}, priority=5, block=True, permission=GROUP)
@buy.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if get_message_text(event.json()) in ["神秘药水"]:
await buy.finish("你们看看就好啦,这是不可能卖给你们的~", at_sender=True)
goods_lst = await GoodsInfo.get_all_goods()
goods_name_lst = [x.goods_name for x in goods_lst]
msg = get_message_text(event.json()).strip().split(" ")
num = 1
if len(msg) > 1:
if is_number(msg[1]) and int(msg[1]) > 0:
num = int(msg[1])
else:
await buy.finish("购买的数量要是数字且大于0", at_sender=True)
# print(msg, num)
if is_number(msg[0]):
msg = int(msg[0])
if msg > len(goods_lst) or msg < 1:
await buy.finish("请输入正确的商品id", at_sender=True)
goods = goods_lst[msg - 1]
else:
if msg[0] in goods_name_lst:
for i in range(len(goods_name_lst)):
if msg[0] == goods_name_lst[i]:
goods = goods_lst[i]
break
else:
await buy.finish("请输入正确的商品名称!")
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:
await buy.finish("您的金币好像不太够哦", at_sender=True)
if await BagUser.spend_gold(
event.user_id, event.group_id, goods.goods_price * num
):
for _ in range(num):
await BagUser.add_props(event.user_id, event.group_id, goods.goods_name)
await buy.send(
f"花费 {goods.goods_price*num} 金币购买 {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} 成功!"
)
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_name} ×{num} 失败!"
)
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from utils.utils import get_message_text, is_number
from models.bag_user import BagUser
from services.db_context import db
from nonebot.adapters.cqhttp.permission import GROUP
from models.goods_info import GoodsInfo
__zx_plugin_name__ = "商店 - 购买道具"
__plugin_usage__ = """
usage
购买道具
指令
购买 [序号或名称] ?[数量=1]
示例购买 好感双倍加持卡Ⅰ
示例购买 1 4
""".strip()
__plugin_des__ = "商店 - 购买道具"
__plugin_cmd__ = ["购买 [序号或名称] ?[数量=1]"]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店", "购买道具"],
}
buy = on_command("购买", aliases={"购买道具"}, priority=5, block=True, permission=GROUP)
@buy.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
goods = None
if get_message_text(event.json()) in ["神秘药水"]:
await buy.finish("你们看看就好啦,这是不可能卖给你们的~", at_sender=True)
goods_lst = await GoodsInfo.get_all_goods()
goods_name_lst = [x.goods_name for x in goods_lst]
msg = get_message_text(event.json()).split()
num = 1
if len(msg) > 1:
if is_number(msg[1]) and int(msg[1]) > 0:
num = int(msg[1])
else:
await buy.finish("购买的数量要是数字且大于0", at_sender=True)
# print(msg, num)
if is_number(msg[0]):
msg = int(msg[0])
if msg > len(goods_lst) or msg < 1:
await buy.finish("请输入正确的商品id", at_sender=True)
goods = goods_lst[msg - 1]
else:
if msg[0] in goods_name_lst:
for i in range(len(goods_name_lst)):
if msg[0] == goods_name_lst[i]:
goods = goods_lst[i]
break
else:
await buy.finish("请输入正确的商品名称!")
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)
if await BagUser.buy_props(event.user_id, event.group_id, goods, num):
await buy.send(
f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!",
at_sender=True,
)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} "
f"花费 {goods.goods_price*num} 金币购买 {goods.goods_name} ×{num} 成功!"
)
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} 失败!"
)

0
plugins/shop/gold.py → basic_plugins/shop/gold.py Executable file → Normal file
View File

View File

@ -1,52 +1,52 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from models.bag_user import BagUser
from nonebot.adapters.cqhttp.permission import GROUP
__zx_plugin_name__ = "商店 - 我的道具"
__plugin_usage__ = """
usage
我的道具
指令
我的道具
""".strip()
__plugin_des__ = "商店 - 我的道具"
__plugin_cmd__ = ["我的道具"]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店", "我的道具"],
}
my_props = on_command("我的道具", priority=5, block=True, permission=GROUP)
@my_props.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
props = await BagUser.get_props(event.user_id, event.group_id)
if props:
pname_list = []
pnum_list = []
rst = ""
props = props[:-1].split(",")
for p in props:
if p != "":
if p in pname_list:
pnum_list[pname_list.index(p)] += 1
else:
pname_list.append(p)
pnum_list.append(1)
for i in range(len(pname_list)):
rst += f"{i+1}.{pname_list[i]}\t×{pnum_list[i]}\n"
await my_props.send("\n" + rst[:-1], at_sender=True)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 查看我的道具")
else:
await my_props.finish("您的背包里没有任何的道具噢~", at_sender=True)
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from models.bag_user import BagUser
from nonebot.adapters.cqhttp.permission import GROUP
__zx_plugin_name__ = "商店 - 我的道具"
__plugin_usage__ = """
usage
我的道具
指令
我的道具
""".strip()
__plugin_des__ = "商店 - 我的道具"
__plugin_cmd__ = ["我的道具"]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店", "我的道具"],
}
my_props = on_command("我的道具", priority=5, block=True, permission=GROUP)
@my_props.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
props = await BagUser.get_props(event.user_id, event.group_id)
if props:
pname_list = []
pnum_list = []
rst = ""
props = props[:-1].split(",")
for p in props:
if p != "":
if p in pname_list:
pnum_list[pname_list.index(p)] += 1
else:
pname_list.append(p)
pnum_list.append(1)
for i in range(len(pname_list)):
rst += f"{i+1}.{pname_list[i]}\t×{pnum_list[i]}\n"
await my_props.send("\n" + rst[:-1], at_sender=True)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 查看我的道具")
else:
await my_props.finish("您的背包里没有任何的道具噢~", at_sender=True)

View File

@ -1,26 +1,26 @@
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}")
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}")

View File

@ -0,0 +1,133 @@
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
from nonebot.typing import T_State
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from .data_source import create_shop_help, delete_goods, update_goods, registered_goods, parse_goods_info
from nonebot.permission import SUPERUSER
from utils.utils import get_message_text, is_number
from nonebot.plugin import export
from services.log import logger
import os
__zx_plugin_name__ = "商店"
__plugin_usage__ = """
usage
商店项目这可不是奸商
指令
商店
""".strip()
__plugin_superuser_usage__ = """
usage
商品操作
指令
添加商品 name:[名称] price:[价格] des:[描述] ?discount:[折扣](小数) ?limit_time:[限时时间](小时)
删除商品 [名称或序号]
修改商品 name:[名称或序号] price:[价格] des:[描述] discount:[折扣] limit_time:[限时]
示例添加商品 name:萝莉酒杯 price:9999 des:普通的酒杯但是里面.. discount:0.4 limit_time:90
示例添加商品 name:可疑的药 price:5 des:效果未知
示例删除商品 2
示例修改商品 name:1 price:900 修改序号为1的商品的价格为900
* 修改商品只需添加需要值即可 *
""".strip()
__plugin_des__ = "商店系统[金币回收计划]"
__plugin_cmd__ = [
"商店",
"添加商品 name:[名称] price:[价格] des:[描述] ?discount:[折扣](小数) ?limit_time:[限时时间](小时)) [_superuser]",
"删除商品 [名称或序号] [_superuser]",
"修改商品 name:[名称或序号] price:[价格] des:[描述] discount:[折扣] limit_time:[限时] [_superuser]",
]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店"],
}
__plugin_block_limit__ = {
"limit_type": "group"
}
# 导出方法供其他插件使用
export = export()
export.registered_goods = registered_goods
export.delete_goods = delete_goods
export.update_goods = update_goods
shop_help = on_command("商店", priority=5, block=True)
shop_add_goods = on_command("添加商品", priority=5, permission=SUPERUSER, block=True)
shop_del_goods = on_command("删除商品", priority=5, permission=SUPERUSER, block=True)
shop_update_goods = on_command("修改商品", priority=5, permission=SUPERUSER, block=True)
@shop_help.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await shop_help.send(image(b64=await create_shop_help()))
@shop_add_goods.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
data = parse_goods_info(msg)
if isinstance(data, str):
await shop_add_goods.finish(data)
if not data.get("name") or not data.get("price") or not data.get("des"):
await shop_add_goods.finish("name:price:des 参数不可缺少!")
if await registered_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)
logger.info(f"USER {event.user_id} 添加商品 {msg} 成功")
else:
await shop_add_goods.send(f"添加商品 {msg} 失败了...", at_sender=True)
logger.warning(f"USER {event.user_id} 添加商品 {msg} 失败")
@shop_del_goods.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
name = ""
id_ = 0
if is_number(msg):
id_ = int(msg)
else:
name = msg
rst, goods_name, code = await delete_goods(name, id_)
if code == 200:
await shop_del_goods.send(f"删除商品 {goods_name} 成功了...", at_sender=True)
if os.path.exists(f"{IMAGE_PATH}/shop_help.png"):
os.remove(f"{IMAGE_PATH}/shop_help.png")
logger.info(f"USER {event.user_id} 删除商品 {goods_name} 成功")
else:
await shop_del_goods.send(f"删除商品 {goods_name} 失败了...", at_sender=True)
logger.info(f"USER {event.user_id} 删除商品 {goods_name} 失败")
@shop_update_goods.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
data = parse_goods_info(msg)
if isinstance(data, str):
await shop_add_goods.finish(data)
if not data.get("name"):
await shop_add_goods.finish("name 参数不可缺少!")
flag, name, text = await update_goods(**data)
if flag:
await shop_update_goods.send(f"修改商品 {name} 成功了...\n{text}", at_sender=True)
logger.info(f"USER {event.user_id} 修改商品 {name} 数据 {text} 成功")
else:
await shop_update_goods.send(f"修改商品 {name} 失败了...", at_sender=True)
logger.info(f"USER {event.user_id} 修改商品 {name} 数据 {text} 失败")

View File

@ -0,0 +1,281 @@
from models.goods_info import GoodsInfo
from utils.image_utils import BuildImage
from models.sign_group_user import SignGroupUser
from utils.utils import is_number
from configs.path_config import IMAGE_PATH
from typing import Optional, Union
from configs.config import Config
from nonebot import Driver
from nonebot.plugin import require
import nonebot
import time
driver: Driver = nonebot.get_driver()
use = require("use")
@driver.on_startup
async def init_default_shop_goods():
"""
导入内置的三个商品
"""
async def sign_card_1(**kwargs):
user_id = kwargs['user_id']
group_id = kwargs['group_id']
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.1).apply()
async def sign_card_2(**kwargs):
user_id = kwargs['user_id']
group_id = kwargs['group_id']
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.2).apply()
async def sign_card_3(**kwargs):
user_id = kwargs['user_id']
group_id = kwargs['group_id']
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.3).apply()
if Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS"):
await registered_goods(
"好感度双倍加持卡Ⅰ", 30, "下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)"
)
use.registered_use("好感度双倍加持卡Ⅰ", sign_card_1)
await registered_goods("好感度双倍加持卡Ⅱ", 150, "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)")
use.registered_use("好感度双倍加持卡Ⅱ", sign_card_2)
await registered_goods(
"好感度双倍加持卡Ⅲ", 250, "下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)"
)
use.registered_use("好感度双倍加持卡Ⅲ", sign_card_3)
# 创建商店界面
async def create_shop_help() -> str:
"""
制作商店图片
:return: 图片base64
"""
goods_lst = await GoodsInfo.get_all_goods()
idx = 1
_dc = {}
font_h = BuildImage(0, 0).getsize("")[1]
h = 10
_list = []
for goods in goods_lst:
if goods.goods_limit_time == 0 or time.time() < goods.goods_limit_time:
h += len(goods.goods_description.strip().split("\n")) * font_h + 80
_list.append(goods)
A = BuildImage(1000, h, color="#f9f6f2")
current_h = 0
for goods in _list:
bk = BuildImage(
700, 80, font_size=15, color="#f9f6f2", font="CJGaoDeGuo.otf"
)
goods_image = BuildImage(
600, 80, font_size=20, color="#a29ad6", font="CJGaoDeGuo.otf"
)
name_image = BuildImage(
580, 40, font_size=25, color="#e67b6b", font="CJGaoDeGuo.otf"
)
await name_image.atext(
(15, 0), f"{idx}.{goods.goods_name}", center_type="by_height"
)
await name_image.aline((380, -5, 280, 45), "#a29ad6", 5)
await name_image.atext((390, 0), "售价:", center_type="by_height")
await name_image.atext(
(440, 0), str(goods.goods_price), (255, 255, 255), center_type="by_height"
)
await name_image.atext(
(
440
+ BuildImage(0, 0, plain_text=str(goods.goods_price), font_size=25).w,
0,
),
" 金币",
center_type="by_height",
)
await name_image.acircle_corner(5)
await goods_image.apaste(name_image, (0, 5), True, center_type="by_width")
await goods_image.atext((15, 50), f"简介:{goods.goods_description}")
await goods_image.acircle_corner(20)
await bk.apaste(goods_image, alpha=True)
# 添加限时图标和时间
if goods.goods_limit_time > 0:
_limit_time_logo = BuildImage(40, 40, background=f"{IMAGE_PATH}/other/time.png")
await bk.apaste(_limit_time_logo, (600, 0), True)
await bk.apaste(BuildImage(0, 0, plain_text="限时!", font_size=23, font="CJGaoDeGuo.otf"), (640, 10), True)
limit_time = time.strftime("%Y-%m-%d %H:%M", time.localtime(goods.goods_limit_time)).split()
y_m_d = limit_time[0]
_h_m = limit_time[1].split(":")
h_m = _h_m[0] + "" + _h_m[1] + ""
await bk.atext((605, 38), str(y_m_d))
await bk.atext((615, 57), str(h_m))
await bk.aline((550, -1, 710, -1), "#a29ad6", 5)
await bk.aline((550, 80, 710, 80), "#a29ad6", 5)
idx += 1
await A.apaste(bk, (0, current_h), True)
current_h += 90
w = 1000
h = A.h + 230 + 100
h = 1000 if h < 1000 else h
shop_logo = BuildImage(100, 100, background=f"{IMAGE_PATH}/other/shop_text.png")
shop = BuildImage(w, h, font_size=20, color="#f9f6f2")
shop.paste(A, (20, 230))
zx_img = BuildImage(0, 0, background=f"{IMAGE_PATH}/zhenxun/toukan.png")
zx_img.replace_color_tran(((240, 240, 240), (255, 255, 255)), (249, 246, 242))
await shop.apaste(zx_img, (780, 100))
await shop.apaste(shop_logo, (450, 30), True)
shop.text(
(int((1000 - shop.getsize("注【通过 序号 或者 商品名称 购买】")[0]) / 2), 170),
"注【通过 序号 或者 商品名称 购买】",
)
shop.text((20, h - 100), "神秘药水\t\t售价9999999金币\n\t\t鬼知道会有什么效果~")
return shop.pic2bs4()
async def registered_goods(
name: str,
price: int,
des: str,
discount: Optional[float] = 1,
limit_time: Optional[int] = 0,
**kwargs,
):
"""
添加商品
例如 折扣可选参数 限时时间:可选单位为小时
添加商品 name:萝莉酒杯 price:9999 des:普通的酒杯但是里面.. discount:0.4 limit_time:90
添加商品 name:可疑的药 price:5 des:效果未知
:param name: 商品名称
:param price: 商品价格
:param des: 商品简介
:param discount: 商品折扣
:param limit_time: 商品限时销售时间单位为小时
:param kwargs: kwargs
:return: 是否添加成功
"""
if kwargs:
name = kwargs.get("name")
price = kwargs.get("price")
des = kwargs.get("des")
discount = kwargs.get("discount")
limit_time = kwargs.get("time_limit")
limit_time = float(limit_time) if limit_time else limit_time
discount = discount if discount is None else 1
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
)
# 删除商品
async def delete_goods(name: str, id_: int) -> "str, str, int":
"""
删除商品
:param name: 商品名称
:param id_: 商品id
:return: 删除状况
"""
goods_lst = await GoodsInfo.get_all_goods()
if id_:
if id_ < 1 or id_ > len(goods_lst):
return "序号错误,没有该序号商品...", "", 999
goods_name = goods_lst[id_ - 1].goods_name
if await GoodsInfo.delete_goods(goods_name):
return f"删除商品 {goods_name} 成功!", goods_name, 200
else:
return f"删除商品 {goods_name} 失败!", goods_name, 999
if name:
if await GoodsInfo.delete_goods(name):
return f"删除商品 {name} 成功!", name, 200
else:
return f"删除商品 {name} 失败!", name, 999
# 更新商品信息
async def update_goods(**kwargs) -> "str, str, int":
"""
更新商品信息
:param kwargs: kwargs
:return: 更新状况
"""
if kwargs:
goods_lst = await GoodsInfo.get_all_goods()
if is_number(kwargs["name"]):
if int(kwargs["name"]) < 1 or int(kwargs["name"]) > len(goods_lst):
return "序号错误,没有该序号的商品...", "", 999
goods = goods_lst[int(kwargs["name"]) - 1]
else:
goods = await GoodsInfo.get_goods_info(kwargs["name"])
if not goods:
return "名称错误,没有该名称的商品...", "", 999
name = goods.goods_name
price = goods.goods_price
des = goods.goods_description
discount = goods.goods_discount
limit_time = goods.goods_limit_time
new_time = 0
tmp = ""
if kwargs.get("price"):
tmp += f'价格:{price} --> {kwargs["price"]}\n'
price = kwargs["price"]
if kwargs.get("des"):
tmp += f'描述:{des} --> {kwargs["des"]}\n'
des = kwargs["des"]
if kwargs.get("discount"):
tmp += f'折扣:{discount} --> {kwargs["discount"]}\n'
discount = kwargs["discount"]
if kwargs.get("limit_time"):
new_time = time.strftime(
"%Y-%m-%d %H:%M:%S",
time.localtime(time.time() + int(kwargs["limit_time"] * 60 * 60)),
)
tmp += f"折扣至: {new_time}\n"
limit_time = kwargs["limit_time"]
return (
await GoodsInfo.update_goods(
name,
int(price),
des,
float(discount),
int(time.time() + limit_time * 60 * 60 if limit_time != 0 and new_time else 0),
),
name,
tmp[:-1],
)
def parse_goods_info(msg: str) -> Union[dict, str]:
"""
解析格式数据
:param msg: 消息
:return: 解析完毕的数据data
"""
if "name:" not in msg:
return "必须指定修改的商品名称或序号!"
data = {}
for x in msg.split():
sp = x.split(":", maxsplit=1)
if str(sp[1]).strip():
sp[1] = sp[1].strip()
print(sp)
if sp[0] == "name":
data["name"] = sp[1]
elif sp[0] == "price":
if not is_number(sp[1]) or int(sp[1]) < 0:
return "price参数不合法必须大于等于0"
data["price"] = sp[1]
elif sp[0] == "des":
data["des"] = sp[1]
elif sp[0] == "discount":
if not is_number(sp[1]) or float(sp[1]) < 0:
return "discount参数不合法必须大于0"
data["discount"] = sp[1]
elif sp[0] == "limit_time":
if not is_number(sp[1]) or float(sp[1]) < 0:
return "limit_time参数不合法必须大于0"
data["limit_time"] = sp[1]
return data

View File

@ -1,71 +1,76 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from utils.utils import is_number, get_message_text
from models.bag_user import BagUser
from nonebot.adapters.cqhttp.permission import GROUP
from services.db_context import db
from .data_source import effect
__zx_plugin_name__ = "商店 - 使用道具"
__plugin_usage__ = """
usage
普通的使用道具
指令
使用道具 [序号或道具名称]
* 序号以 我的道具 为准 *
""".strip()
__plugin_des__ = "商店 - 使用道具"
__plugin_cmd__ = ["使用道具 [序号或道具名称]"]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店", "使用道具"],
}
use_props = on_command("使用道具", priority=5, block=True, permission=GROUP)
@use_props.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg in ["", "帮助"]:
await use_props.finish(__plugin_usage__)
props = await BagUser.get_props(event.user_id, event.group_id)
if props:
async with db.transaction():
pname_list = []
props = props[:-1].split(",")
for p in props:
if p != "":
if p not in pname_list:
pname_list.append(p)
if is_number(msg):
if 0 < int(msg) <= len(pname_list):
name = pname_list[int(msg) - 1]
else:
await use_props.finish("仔细看看自己的道具仓库有没有这个道具?", at_sender=True)
else:
if msg not in pname_list:
await use_props.finish("道具名称错误!", at_sender=True)
name = msg
if await BagUser.del_props(
event.user_id, event.group_id, name
) and await effect(event.user_id, event.group_id, name):
await use_props.send(f"使用道具 {name} 成功!", at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 成功"
)
else:
await use_props.send(f"使用道具 {name} 失败!", at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 失败"
)
else:
await use_props.send("您的背包里没有任何的道具噢~", at_sender=True)
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from utils.utils import is_number, get_message_text
from models.bag_user import BagUser
from nonebot.adapters.cqhttp.permission import GROUP
from services.db_context import db
from nonebot.plugin import export
from .data_source import effect, registered_use
__zx_plugin_name__ = "商店 - 使用道具"
__plugin_usage__ = """
usage
普通的使用道具
指令
使用道具 [序号或道具名称]
* 序号以 我的道具 为准 *
""".strip()
__plugin_des__ = "商店 - 使用道具"
__plugin_cmd__ = ["使用道具 [序号或道具名称]"]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店", "使用道具"],
}
# 导出方法供其他插件使用
export = export()
export.registered_use = registered_use
use_props = on_command("使用道具", priority=5, block=True, permission=GROUP)
@use_props.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg in ["", "帮助"]:
await use_props.finish(__plugin_usage__)
props = await BagUser.get_props(event.user_id, event.group_id)
if props:
async with db.transaction():
pname_list = []
props = props[:-1].split(",")
for p in props:
if p != "":
if p not in pname_list:
pname_list.append(p)
if is_number(msg):
if 0 < int(msg) <= len(pname_list):
name = pname_list[int(msg) - 1]
else:
await use_props.finish("仔细看看自己的道具仓库有没有这个道具?", at_sender=True)
else:
if msg not in pname_list:
await use_props.finish("道具名称错误!", at_sender=True)
name = msg
if await BagUser.del_props(
event.user_id, event.group_id, name
) and await effect(event.user_id, event.group_id, name):
await use_props.send(f"使用道具 {name} 成功!", at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 成功"
)
else:
await use_props.send(f"使用道具 {name} 失败!", at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 失败"
)
else:
await use_props.send("您的背包里没有任何的道具噢~", at_sender=True)

View File

@ -0,0 +1,45 @@
import asyncio
from services.log import logger
_use_func_data = {}
async def effect(user_id: int, group_id: int, goods_name: str) -> bool:
"""
商品生效
:param user_id: 用户id
:param group_id: 群号
:param goods_name: 商品名称
:return: 使用是否成功
"""
# 优先使用注册的商品插件
try:
if _use_func_data.get(goods_name):
_kwargs = _use_func_data[goods_name]["kwargs"]
_kwargs["goods_name"] = goods_name
_kwargs["user_id"] = user_id
_kwargs["group_id"] = group_id
if asyncio.iscoroutinefunction(_use_func_data[goods_name]["func"]):
await _use_func_data[goods_name]["func"](
**_kwargs,
)
else:
_use_func_data[goods_name]["func"](
**_kwargs,
)
return True
except Exception as e:
logger.error(f"use 商品生效函数effect 发生错误 {type(e)}{e}")
return False
def registered_use(goods_name: str, func, **kwargs):
"""
注册商品使用方法
:param goods_name: 商品名称
:param func: 使用函数
:param kwargs: kwargs
"""
if goods_name in _use_func_data.keys():
raise ValueError("该商品使用函数已被注册!")
_use_func_data[goods_name] = {"func": func, "kwargs": kwargs}

View File

@ -1,5 +1,6 @@
from services.db_context import db
from typing import Optional, List
from services.log import logger
class BagUser(db.Model):
@ -85,7 +86,7 @@ class BagUser(db.Model):
return ""
@classmethod
async def add_gold(cls, user_qq: int, belonging_group: int, num: int) -> bool:
async def add_gold(cls, user_qq: int, belonging_group: int, num: int):
"""
说明
增加金币
@ -99,27 +100,23 @@ class BagUser(db.Model):
)
query = query.with_for_update()
user = await query.gino.first()
try:
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,
belonging_group=belonging_group,
gold=100 + num,
get_total_gold=num,
get_today_gold=num,
)
return True
except Exception:
return False
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,
belonging_group=belonging_group,
gold=100 + num,
get_total_gold=num,
get_today_gold=num,
)
@classmethod
async def spend_gold(cls, user_qq: int, belonging_group: int, num: int) -> bool:
async def spend_gold(cls, user_qq: int, belonging_group: int, num: int):
"""
说明
花费金币
@ -133,27 +130,23 @@ class BagUser(db.Model):
)
query = query.with_for_update()
user = await query.gino.first()
try:
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,
belonging_group=belonging_group,
gold=100 - num,
spend_total_gold=num,
spend_today_gold=num,
)
return True
except Exception:
return False
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,
belonging_group=belonging_group,
gold=100 - num,
spend_total_gold=num,
spend_today_gold=num,
)
@classmethod
async def add_props(cls, user_qq: int, belonging_group: int, name: str) -> bool:
async def add_props(cls, user_qq: int, belonging_group: int, name: str):
"""
说明
增加道具
@ -167,16 +160,12 @@ class BagUser(db.Model):
)
query = query.with_for_update()
user = await query.gino.first()
try:
if user:
await user.update(props=user.props + f"{name},").apply()
else:
await cls.create(
user_qq=user_qq, belonging_group=belonging_group, props=f"{name},"
)
return True
except Exception:
return False
if user:
await user.update(props=user.props + f"{name},").apply()
else:
await cls.create(
user_qq=user_qq, belonging_group=belonging_group, props=f"{name},"
)
@classmethod
async def del_props(cls, user_qq: int, belonging_group: int, name: str) -> bool:
@ -193,27 +182,48 @@ class BagUser(db.Model):
)
query = query.with_for_update()
user = await query.gino.first()
try:
if user:
rst = ""
props = user.props
if props.find(name) != -1:
props = props.split(",")
try:
index = props.index(name)
except ValueError:
return False
props = props[:index] + props[index + 1 :]
for p in props:
if p != "":
rst += p + ","
await user.update(props=rst).apply()
return True
else:
if user:
rst = ""
props = user.props
if props.find(name) != -1:
props = props.split(",")
try:
index = props.index(name)
except ValueError:
return False
props = props[:index] + props[index + 1 :]
for p in props:
if p != "":
rst += p + ","
await user.update(props=rst).apply()
return True
else:
return False
except Exception:
else:
return False
@classmethod
async def buy_props(
cls, user_qq: int, belonging_group: int, goods: "GoodsInfo", goods_num: int
) -> bool:
"""
说明
购买道具
参数
:param user_qq: 用户qq
:param belonging_group: 所在群聊
:param goods: 商品
:param goods_num: 商品数量
"""
try:
# 折扣后金币
spend_gold = goods.goods_discount * goods.goods_price * goods_num
await BagUser.spend_gold(user_qq, belonging_group, spend_gold)
for _ in range(goods_num):
await BagUser.add_props(user_qq, belonging_group, goods.goods_name)
return True
except Exception as e:
logger.error(f"buy_props 发生错误 {type(e)}{e}")
return False
@classmethod

View File

@ -1,5 +1,6 @@
from services.db_context import db
from typing import Optional, List
from services.log import logger
class GoodsInfo(db.Model):
@ -34,16 +35,18 @@ class GoodsInfo(db.Model):
:param goods_limit_time: 商品限时
"""
try:
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,
)
return True
except Exception:
return False
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,
)
return True
except Exception as e:
logger.error(f"GoodsInfo add_goods 发生错误 {type(e)}{e}")
return False
@classmethod
async def delete_goods(cls, goods_name: str) -> bool:
@ -99,7 +102,8 @@ class GoodsInfo(db.Model):
if goods_limit_time:
await query.update(goods_limit_time=goods_limit_time).apply()
return True
except Exception:
except Exception as e:
logger.error(f"GoodsInfo update_goods 发生错误 {type(e)}{e}")
return False
@classmethod

View File

@ -40,7 +40,7 @@ def is_expired(data: dict):
# 检查写入
def check_write(data: dict, up_char_file):
if not is_expired(data['char']):
if is_expired(data['char']):
for x in list(data.keys()):
data[x]['title'] = ''
else:

View File

@ -146,12 +146,14 @@ def _format_card_information(_count: int, user_id, pool_name):
five_index_list = []
five_list = []
five_dict = {}
_start_add_count = 72 if pool_name == 'char' else 62
_x = 90 if pool_name == 'char' else 80 # 保底
add = 0.0
if genshin_count.get(user_id) and _count <= 90:
if genshin_count.get(user_id) and _count <= _x:
f_count = genshin_count[user_id]
else:
f_count = 0
if genshin_pl_count.get(user_id) and _count <= 90:
if genshin_pl_count.get(user_id) and _count <= _x:
count = genshin_pl_count[user_id]
else:
count = 0
@ -159,23 +161,23 @@ def _format_card_information(_count: int, user_id, pool_name):
count += 1
f_count += 1
# 十连保底
if count == 10 and f_count != 90:
if f_count >= 72:
if count == 10 and f_count != _x:
if f_count >= _start_add_count:
add += I72_ADD
char, code = _get_genshin_card(2, pool_name, add=add)
count = 0
# 大保底
elif f_count == 90:
elif f_count == _x:
char, code = _get_genshin_card(3, pool_name)
else:
if f_count >= 72:
if f_count >= _start_add_count:
add += I72_ADD
char, code = _get_genshin_card(pool_name=pool_name, add=add)
if code == 1:
count = 0
star_list[code] += 1
if code == 0:
if _count <= 90:
if _count <= _x:
genshin_five[user_id] = f_count
add = 0.0
f_count = 0
@ -186,7 +188,7 @@ def _format_card_information(_count: int, user_id, pool_name):
except KeyError:
five_dict[char.name] = 1
char_list.append(char)
if _count <= 90:
if _count <= _x:
genshin_count[user_id] = f_count
genshin_pl_count[user_id] = count
return char_list, five_list, five_index_list, five_dict, star_list

View File

@ -7,9 +7,10 @@ from utils.browser import get_browser
from configs.path_config import IMAGE_PATH
import nonebot
from services.log import logger
from utils.utils import scheduler
from nonebot.permission import SUPERUSER
from pathlib import Path
from typing import List
from datetime import datetime, timedelta
import os
import asyncio
import time
@ -52,9 +53,12 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
if time.strftime("%w") == "0":
await material.send("今天是周日,所有材料副本都开放了。")
return
file_name = str((datetime.now() - timedelta(hours=4)).date())
if not (Path(IMAGE_PATH) / "genshin" / "material" / f"{file_name}.png").exists():
await update_image()
await material.send(
Message(
image("daily_material.png", "genshin/material")
image(f"{file_name}.png", "genshin/material")
+ "\n※ 每日素材数据来源于 genshin.pub"
)
)
@ -73,7 +77,6 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
await super_cmd.send(f"更新失败...")
@driver.on_startup
async def update_image():
page = None
try:
@ -140,7 +143,8 @@ async def update_image():
background_img.paste(x, (current_width, current_height))
current_height += x.size[1]
current_width += 600
background_img.save(f"{IMAGE_PATH}/genshin/material/daily_material.png")
file_name = str((datetime.now() - timedelta(hours=4)).date())
background_img.save(f"{IMAGE_PATH}/genshin/material/{file_name}.png")
await page.close()
return True
except Exception as e:
@ -163,16 +167,3 @@ def get_background_height(weapons_imgs: List[str]) -> int:
return height
@scheduler.scheduled_job(
"cron",
hour=4,
minute=1,
)
async def _():
for _ in range(5):
try:
await update_image()
logger.info(f"更新每日天赋素材成功...")
break
except Exception as e:
logger.error(f"更新每日天赋素材出错 e{e}")

View File

@ -64,7 +64,7 @@ async def get_image(
"affix_level": char["weapon"]["affix_level"],
}
await init_image(char_data_list, _x)
await init_image(char_data_list, _x, home_data_list)
return await get_genshin_image(
user_id,
uid,

View File

@ -510,11 +510,12 @@ def get_char_data_image(
return region, _h
async def init_image(char_data_list: List[Dict], char_detailed_dict: dict):
async def init_image(char_data_list: List[Dict], char_detailed_dict: dict, home_data_list: List[Dict]):
"""
下载头像
:param char_data_list: 角色列表
:param char_detailed_dict: 角色武器
:param home_data_list: 家园列表
"""
for char in char_data_list:
file = image_path / "chars" / f'{char["name"]}.png'
@ -528,3 +529,10 @@ async def init_image(char_data_list: List[Dict], char_detailed_dict: dict):
await AsyncHttpx.download_file(
char_detailed_dict[char]["weapon_image"], file
)
for home in home_data_list:
file = image_path / "homes" / f'{home["name"]}.png'
file.parent.mkdir(parents=True, exist_ok=True)
if not file.exists():
await AsyncHttpx.download_file(
home["icon"], file
)

View File

@ -41,8 +41,19 @@ usage
示例塞红包 1000
示例塞红包 1000 10
""".strip()
__plugin_superuser_usage__ = """
usage
节日全群红包指令
指令
节日红包 [金额] [数量] ?[祝福语] ?[指定群]
""".strip()
__plugin_des__ = "运气项目又来了"
__plugin_cmd__ = ["塞红包 [金币数] ?[红包数=5]", "开/抢", "退回"]
__plugin_cmd__ = [
"塞红包 [金币数] ?[红包数=5]",
"开/抢",
"退回",
"节日红包 [金额] [数量] ?[祝福语] ?[指定群] [_superuser]",
]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
@ -51,9 +62,7 @@ __plugin_settings__ = {
"limit_superuser": False,
"cmd": ["金币红包", "塞红包"],
}
__plugin_resources__ = {
"prts": IMAGE_PATH
}
__plugin_resources__ = {"prts": IMAGE_PATH}
gold_redbag = on_command(
"塞红包", aliases={"金币红包"}, priority=5, block=True, permission=GROUP
@ -143,10 +152,12 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
flag, amount = await check_gold(event.user_id, event.group_id, amount)
if not flag:
await gold_redbag.finish(amount, at_sender=True)
group_member_num = (await bot.get_group_info(group_id=event.group_id))['member_count']
group_member_num = (await bot.get_group_info(group_id=event.group_id))[
"member_count"
]
num = int(num)
if num > group_member_num:
await gold_redbag.send('你发的红包数量也太多了,已经为你修改成与本群人数相同的红包数量...')
await gold_redbag.send("你发的红包数量也太多了,已经为你修改成与本群人数相同的红包数量...")
num = group_member_num
nickname = event.sender.card if event.sender.card else event.sender.nickname
flag, result = init_redbag(
@ -181,7 +192,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
.replace("", "")
)
if msg:
if '红包' not in msg:
if "红包" not in msg:
return
flag1 = True
flag2 = True
@ -306,7 +317,9 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
await end_festive_redbag(bot, g)
except JobLookupError:
pass
init_redbag(int(bot.self_id), g, f"{NICKNAME}", amount, num, int(bot.self_id), 1)
init_redbag(
int(bot.self_id), g, f"{NICKNAME}", amount, num, int(bot.self_id), 1
)
scheduler.add_job(
end_festive_redbag,
"date",

View File

@ -20,7 +20,7 @@ except ModuleNotFoundError:
__zx_plugin_name__ = "本地图库"
__plugin_usage__ = f"""
usage
发送指定图库下的随机或指定id图片
发送指定图库下的随机或指定id图片genshin_memo
指令
{Config.get_config("image_management", "IMAGE_DIR_LIST")} ?[id]
示例美图

View File

@ -105,7 +105,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
path = get_message_imgs(event.json())
if path in Config.get_config("image_management", "IMAGE_DIR_LIST"):
state["path"] = path
await continuous_upload_img.send("图来!!")
await continuous_upload_img.send("图来!!【停止请发送 stop 开始上传】")
state["tmp"] = []

View File

@ -124,6 +124,27 @@ class Setu(db.Model):
).gino.first()
)
@classmethod
async def delete_image(cls, pid: int) -> int:
"""
说明
删除图片并替换
参数
:param pid: 图片pid
"""
query = await cls.query.where(cls.pid == pid).gino.first()
if query:
is_r18 = query.is_r18
num = await cls.get_image_count(is_r18)
x = await cls.query.where((cls.is_r18 == is_r18) & (cls.local_id == num - 1)).gino.first()
_tmp_local_id = x.local_id
if x:
x.update(local_id=query.local_id).apply()
await cls.delete.where(cls.pid == pid).gino.status()
return _tmp_local_id
return -1
@classmethod
async def update_setu_data(
cls,

View File

@ -3,7 +3,7 @@ from services.log import logger
from datetime import datetime
from utils.image_utils import compressed_image, get_img_hash
from utils.utils import get_bot
from asyncio.exceptions import TimeoutError
from PIL import UnidentifiedImageError
from ..model import Setu
from asyncpg.exceptions import UniqueViolationError
from configs.config import Config
@ -142,6 +142,14 @@ async def update_setu_img():
continue
img_hash = str(get_img_hash(f"{path}/{image.local_id}.jpg"))
await Setu.update_setu_data(image.pid, img_hash=img_hash)
except UnidentifiedImageError:
# 图片已删除
with open(local_image, 'r') as f:
if '404 Not Found' in f.read():
max_num = await Setu.delete_image(image.pid)
local_image.unlink()
os.rename(path / f"{max_num}.jpg", local_image)
logger.warning(f"更新色图 PID{image.pid} 404已删除并替换")
except Exception as e:
_success -= 1
logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")

36
plugins/server_ip.py Normal file
View File

@ -0,0 +1,36 @@
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, PrivateMessageEvent, GroupMessageEvent
from nonebot.typing import T_State
from nonebot.rule import to_me
__zx_plugin_name__ = "服务器 [Hidden]"
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
server_ip = on_command("服务器", aliases={"ip"}, rule=to_me(), priority=5, block=True)
@server_ip.handle()
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
await server_ip.finish(
"|* 请不要发给其他人! *|\n"
"\t121.40.195.22\n"
"|* 请不要发给其他人! *|\n"
"csgo ~号键控制台输入 connect 121.40.195.22 进入服务器\n"
"然后再公屏输入 !diy 来使用皮肤(英文感叹号,注意)\n"
"【说不定可以凑到内战噢,欢迎~{娱乐为主}",
at_sender=True,
)
@server_ip.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if event.group_id == 698279647:
await server_ip.finish(
"嗨呀!当前服务器地址是:" "\n\tay: 121.40.195.22" "\n\t夜之北枭: 101.132.170.254"
)
elif event.group_id == 1046451860:
await server_ip.finish("嗨呀!当前服务器地址是:\n121.40.195.22\n !diy")
else:
await server_ip.finish("不好意思呀小真寻不能为你使用此功能因为服务器IP是真寻的小秘密呀", at_sender=True)

View File

@ -1 +0,0 @@
from .goods_info import *

View File

@ -1,154 +0,0 @@
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
from nonebot.typing import T_State
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from .data_source import create_shop_help, add_goods, del_goods, update_goods
from nonebot.permission import SUPERUSER
from utils.utils import get_message_text, is_number
from services.log import logger
import os
import time
__zx_plugin_name__ = "商店"
__plugin_usage__ = """
usage
商店项目这可不是奸商
指令
商店
""".strip()
__plugin_superuser_usage__ = """
usage
商品操作
指令
添加商品 [名称]-[价格]-[描述]-?[折扣](小数)-?[限时时间](分钟)
删除商品 [名称或序号]
修改商品 -name [名称或序号] -price [价格] -des [描述] -discount [折扣] -time [限时]
示例添加商品-昏睡红茶-300-一杯上好的奇怪红茶-0.9-60
示例删除商品 2
示例修改商品 -name 1 -price 900: 修改序号为1的商品的价格为900
* 修改商品只需添加需要值即可 *
""".strip()
__plugin_des__ = "商店系统[金币回收计划]"
__plugin_cmd__ = [
"商店",
"添加商品 [名称]-[价格]-[描述]-?[折扣](小数)-?[限时时间](分钟) [_superuser]",
"删除商品 [名称或序号] [_superuser]",
"修改商品 -name [名称或序号] -price [价格] -des [描述] -discount [折扣] -time [限时] [_superuser]",
]
__plugin_type__ = ('商店',)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["商店"],
}
shop_help = on_command("商店", priority=5, block=True)
shop_add_goods = on_command("添加商品", priority=5, permission=SUPERUSER, block=True)
shop_del_goods = on_command("删除商品", priority=5, permission=SUPERUSER, block=True)
shop_update_goods = on_command("修改商品", priority=5, permission=SUPERUSER, block=True)
@shop_help.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if not os.path.exists(f"{IMAGE_PATH}/shop_help.png"):
await create_shop_help()
await shop_help.send(image("shop_help.png"))
@shop_add_goods.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
msg = msg.split("-")
if len(msg) < 3:
await shop_add_goods.finish("商品参数不完全...", at_sender=True)
if not is_number(msg[1]):
await shop_add_goods.finish("商品的价格必须是合法数字!", at_sender=True)
msg[1] = int(msg[1])
if len(msg) > 3:
if not is_number(msg[3]):
await shop_add_goods.finish("商品的折扣要小数啊!", at_sender=True)
msg[3] = float(msg[3])
if len(msg) > 4:
if not is_number(msg[4]):
await shop_add_goods.finish("商品的限时时间是要写多少分钟噢!", at_sender=True)
msg[4] = time.time() + int(msg[4]) * 60
if await add_goods(msg):
await shop_add_goods.send(f"添加商品 {msg[0]} 成功...", at_sender=True)
if os.path.exists(f"{IMAGE_PATH}/shop_help.png"):
os.remove(f"{IMAGE_PATH}/shop_help.png")
logger.info(f"USER {event.user_id} 上传商品 {msg} 成功")
else:
await shop_add_goods.send(f"添加商品 {msg[0]} 失败了...", at_sender=True)
logger.warning(f"USER {event.user_id} 上传商品 {msg} 失败")
@shop_del_goods.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
name = ""
id_ = 0
if is_number(msg):
id_ = int(msg)
else:
name = msg
rst, goods_name, code = await del_goods(name, id_)
if code == 200:
await shop_del_goods.send(f"删除商品 {goods_name} 成功了...", at_sender=True)
if os.path.exists(f"{IMAGE_PATH}/shop_help.png"):
os.remove(f"{IMAGE_PATH}/shop_help.png")
logger.info(f"USER {event.user_id} 删除商品 {goods_name} 成功")
else:
await shop_del_goods.send(f"删除商品 {goods_name} 失败了...", at_sender=True)
logger.info(f"USER {event.user_id} 删除商品 {goods_name} 失败")
@shop_update_goods.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg:
tmp = {}
msg = msg.split("-")
for x in msg:
if x.find("name") != -1:
tmp["name"] = x.split(" ")[1].strip()
elif x.find("price") != -1:
tmp["price"] = x.split(" ")[1].strip()
if not is_number(tmp["price"]):
await shop_update_goods.finish("价格必须是数字啊!", at_sender=True)
tmp["price"] = int(tmp["price"])
elif x.find("des") != -1:
tmp["des"] = x.split(" ")[1].strip()
elif x.find("discount") != -1:
tmp["discount"] = x.split(" ")[1].strip()
if not is_number(tmp["discount"]):
await shop_update_goods.finish("折扣必须是数字啊!", at_sender=True)
tmp["discount"] = float(tmp["discount"])
elif x.find("time") != -1:
tmp["time"] = x.split(" ")[1].strip()
if not is_number(tmp["time"]):
await shop_update_goods.finish("限时时间必须是数字啊!", at_sender=True)
tmp["time"] = time.time() + tmp["time"] * 60
if not tmp.get("name"):
await shop_update_goods.finish("未指定商品名称(序号也可)", at_sender=True)
if is_number(tmp["name"]):
tmp["name"] = int(tmp["name"])
flag, name, text = await update_goods(tmp)
if flag:
await shop_update_goods.send(f"修改商品 {name} 成功了...\n{text}", at_sender=True)
if os.path.exists(f"{IMAGE_PATH}/shop_help.png"):
os.remove(f"{IMAGE_PATH}/shop_help.png")
logger.info(f"USER {event.user_id} 修改商品 {name} 数据 {tmp} 成功")
else:
await shop_update_goods.send(f"修改商品 {name} 失败了...", at_sender=True)
logger.info(f"USER {event.user_id} 修改商品 {name} 数据 {tmp} 失败")

View File

@ -1,126 +0,0 @@
from ..models.goods_info import GoodsInfo
from utils.image_utils import BuildImage
from utils.utils import is_number
from configs.path_config import IMAGE_PATH
from configs.config import Config
from nonebot import Driver
import nonebot
import time
import os
driver: Driver = nonebot.get_driver()
# 导入内置商品 | 重新生成商店图片
@driver.on_startup
async def init_default_shop_goods():
if os.path.exists(f"{IMAGE_PATH}/shop_help.png"):
os.remove(f"{IMAGE_PATH}/shop_help.png")
if Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS"):
await add_goods(["好感度双倍加持卡Ⅰ", 30, "下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)"])
await add_goods(["好感度双倍加持卡Ⅱ", 150, "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)"])
await add_goods(["好感度双倍加持卡Ⅲ", 250, "下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)"])
# 创建商店界面
async def create_shop_help():
goods_lst = await GoodsInfo.get_all_goods()
tmp = ""
idx = 1
for goods in goods_lst:
tmp += (
f"{idx}.{goods.goods_name}\t\t售价:{goods.goods_price}金币\n"
f"\t\t{goods.goods_description}\n"
)
idx += 1
w = 1000
h = 400 + len(goods_lst) * 40
h = 1000 if h < 1000 else h
shop_logo = BuildImage(100, 100, background=f"{IMAGE_PATH}/other/shop_text.png")
shop = BuildImage(w, h, font_size=20)
zhenxun_img = BuildImage(525, 581, background=f"{IMAGE_PATH}/zhenxun/toukan_2.png")
shop.paste(zhenxun_img, (780, 100))
shop.paste(shop_logo, (450, 30), True)
shop.text(
(int((1000 - shop.getsize("注【通过 序号 或者 商品名称 购买】")[0]) / 2), 170),
"注【通过 序号 或者 商品名称 购买】",
)
shop.text((20, 230), tmp[:-1])
shop.text((20, h - 100), "神秘药水\t\t售价9999999金币\n\t\t鬼知道会有什么效果~")
shop.save(f"{IMAGE_PATH}/shop_help.png")
# 添加商品
async def add_goods(msg: list):
data = {
"名称": None,
"价格": None,
"描述": None,
"折扣": 1,
"限时": 0,
}
keys = list(data.keys())
idx = 0
for x in msg:
data[keys[idx]] = x
idx += 1
return await GoodsInfo.add_goods(
data["名称"], data["价格"], data["描述"], data["折扣"], data["限时"]
)
# 删除商品
async def del_goods(name: str, id_: int):
goods_lst = await GoodsInfo.get_all_goods()
if id_:
if id_ < 1 or id_ > len(goods_lst):
return "序号错误,没有该序号商品...", "", 999
goods_name = goods_lst[id_ - 1].goods_name
if await GoodsInfo.delete_goods(goods_name):
return f"删除商品 {goods_name} 成功!", goods_name, 200
else:
return f"删除商品 {goods_name} 失败!", goods_name, 999
if name:
if await GoodsInfo.delete_goods(name):
return f"删除商品 {name} 成功!", name, 200
else:
return f"删除商品 {name} 失败!", name, 999
# 更新商品信息
async def update_goods(data: dict):
goods_lst = await GoodsInfo.get_all_goods()
if is_number(data["name"]):
if data["name"] < 1 or data["name"] > len(goods_lst):
return "序号错误,没有该序号的商品...", "", 999
goods = goods_lst[data["name"] - 1]
else:
goods = await GoodsInfo.get_goods_info(data["name"])
if not goods:
return "名称错误,没有该名称的商品...", "", 999
name = goods.goods_name
price = goods.goods_price
des = goods.goods_description
discount = goods.goods_discount
limit_time = goods.goods_limit_time
tmp = ""
if data.get("price"):
tmp += f'价格:{price} --> {data["price"]}\n'
price = data["price"]
if data.get("des"):
tmp += f'描述:{des} --> {data["des"]}\n'
des = data["des"]
if data.get("discount"):
tmp += f'折扣:{discount} --> {data["discount"]}\n'
discount = data["discount"]
if data.get("time"):
old_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(limit_time))
new_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(data["time"]))
tmp += f"折扣:{old_time} --> {new_time}\n"
limit_time = data["time"]
return (
await GoodsInfo.update_goods(name, price, des, discount, limit_time),
name,
tmp[:-1],
)

View File

@ -1,14 +0,0 @@
from models.sign_group_user import SignGroupUser
async def effect(user_id: int, group_id: int, name: str) -> bool:
if name in ["好感双倍加持卡Ⅰ", "好感度双倍加持卡Ⅰ"]:
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.1).apply()
if name in ["好感双倍加持卡Ⅱ", "好感度双倍加持卡Ⅱ"]:
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.2).apply()
if name in ["好感双倍加持卡Ⅲ", "好感度双倍加持卡Ⅲ"]:
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(add_probability=0.3).apply()
return True

View File

@ -28,14 +28,14 @@ usage
每日签到
会影响色图概率和开箱次数以及签到的随机道具获取
指令
签到
签到 ?[all]: all代表签到所有群
我的签到
好感度排行
好感度总排行
* 签到时有 3% 概率 * 2 *
""".strip()
__plugin_des__ = "每日签到,证明你在这里"
__plugin_cmd__ = ["签到", "我的签到", "好感度排行", "好感度总排行"]
__plugin_cmd__ = ["签到 ?[all]", "我的签到", "好感度排行", "好感度总排行"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {

View File

@ -59,7 +59,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
await yiqing.send(rely)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情失败"
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情成功"
)
else:
await yiqing.send(f"{NICKNAME}没有查到{msg}的疫情查询...")

View File

@ -1,7 +1,10 @@
from configs.path_config import TEXT_PATH
from typing import List
from typing import List, Union
from pathlib import Path
from utils.http_utils import AsyncHttpx
from utils.image_utils import text2image
from utils.message_builder import image
from nonebot.adapters.cqhttp import MessageSegment
import ujson as json
china_city = Path(TEXT_PATH) / "china_city.json"
@ -12,7 +15,7 @@ data = {}
url = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5"
async def get_yiqing_data(area: str):
async def get_yiqing_data(area: str) -> Union[str, MessageSegment]:
"""
查看疫情数据
:param area: 省份/城市
@ -40,16 +43,16 @@ async def get_yiqing_data(area: str):
if area == "中国":
data_ = epidemic_data["areaTree"][0]
else:
data_ = [
x
for x in epidemic_data["areaTree"][0]["children"]
if x["name"] == province
][0]
if city:
try:
try:
data_ = [
x
for x in epidemic_data["areaTree"][0]["children"]
if x["name"] == province
][0]
if city:
data_ = [x for x in data_["children"] if x["name"] == city][0]
except IndexError:
return "未查询到..."
except IndexError:
return "未查询到..."
confirm = data_["total"]["confirm"] # 累计确诊
heal = data_["total"]["heal"] # 累计治愈
dead = data_["total"]["dead"] # 累计死亡
@ -59,20 +62,22 @@ async def get_yiqing_data(area: str):
suspect = data_["total"]["suspect"] # 疑似
add_confirm = data_["today"]["confirm"] # 新增确诊
x = f"{city}" if city else f"{province}{province_type}"
return (
f"{x} 疫情数据:\n"
f"\t目前确诊:\n"
f"\t\t确诊人数:{now_confirm}(+{add_confirm})\n"
f"\t\t疑似人数:{suspect}\n"
f"==================\n"
f"\t累计数据:\n"
f"\t\t确诊人数:{confirm}\n"
f"\t\t治愈人数:{heal}\n"
f"\t\t死亡人数:{dead}\n"
f"\t治愈率:{heal_rate}%\n"
f"\t死亡率:{dead_rate}%\n"
f"更新日期:{last_update_time}"
)
return image(b64=await text2image(
f"""
{x} 疫情数据
目前确诊
确诊人数<f font_color=red>{now_confirm}(+{add_confirm})</f>
疑似人数{suspect}
-----------------
累计数据
确诊人数<f font_color=red>{confirm}</f>
治愈人数<f font_color=#39de4b>{heal}</f>
死亡人数<f font_color=#191d19>{dead}</f>
治愈率{heal_rate}%
死亡率{dead_rate}%
更新日期{last_update_time}
""", font_size=30, color="#f9f6f2"
))
def get_city_and_province_list() -> List[str]:

View File

@ -6,8 +6,12 @@
# @File : other_than.py
# @Software: PyCharm
from utils.http_utils import AsyncHttpx
from nonebot.adapters.cqhttp import MessageSegment
from typing import Optional
from services.log import logger
from utils.image_utils import text2image
from utils.message_builder import image
from json.decoder import JSONDecodeError
import re
import json
@ -23,50 +27,66 @@ def intcomma(value) -> str:
return new if orig == new else intcomma(new)
async def get_other_data(place: str) -> Optional[str]:
async def get_other_data(place: str, count: int = 0) -> Optional[MessageSegment]:
"""
:param place: 地名
:param count: 递归次数
:return: 格式化字符串
"""
if count == 5:
return None
try:
html = (
(await AsyncHttpx.get("https://news.ifeng.com/c/special/7uLj4F83Cqm"))
.text.replace("\n", "")
.replace(" ", "")
)
find_data = re.compile(r"varallData=(.*?);</script>")
sum_ = re.findall(find_data, html)[0]
sum_ = json.loads(sum_)
except JSONDecodeError:
return await get_other_data(place, count + 1)
except Exception as e:
logger.error(f"疫情查询发生错误 {type(e)}{e}")
return None
find_data = re.compile(r"varallData=(.*?);</script>")
sum_ = re.findall(find_data, html)[0]
try:
sum_ = json.loads(sum_)
other_country = sum_["yiqing_v2"]["dataList"][29]["child"]
for country in other_country:
if place == country["name2"]:
return (
f"{place} 疫情数据:\n"
"——————————————\n"
f"新增病例:{intcomma(country['quezhen_add'])}\n"
f"现有确诊:{intcomma(country['quezhen_xianyou'])}\n"
f"累计确诊:{intcomma(country['quezhen'])}\n"
f"累计治愈:{intcomma(country['zhiyu'])}\n"
f"死亡:{intcomma(country['siwang'])}\n"
"——————————————"
# f"更新时间:{country['sys_publishDateTime']}"
# 时间无法精确到分钟网页用了js我暂时找不到
return image(
b64=await text2image(
f" {place} 疫情数据:\n"
"——————————————\n"
f" 新增病例:<f font_color=red>{intcomma(country['quezhen_add'])}</f>\n"
f" 现有确诊:<f font_color=red>{intcomma(country['quezhen_xianyou'])}</f>\n"
f" 累计确诊:<f font_color=red>{intcomma(country['quezhen'])}</f>\n"
f" 累计治愈:<f font_color=#39de4b>{intcomma(country['zhiyu'])}</f>\n"
f" 死亡:{intcomma(country['siwang'])}\n"
"——————————————"
# f"更新时间:{country['sys_publishDateTime']}"
# 时间无法精确到分钟网页用了js我暂时找不到
,
font_size=30,
color="#f9f6f2",
padding=15
)
)
else:
for city in country["child"]:
if place == city["name3"]:
return (
f"{place} 疫情数据:\n"
"——————————————\n"
f"新增病例:{intcomma(city['quezhen_add'])}\n"
f"累计确诊:{intcomma(city['quezhen'])}\n"
f"累计治愈:{intcomma(city['zhiyu'])}\n"
f"死亡:{intcomma(city['siwang'])}\n"
"——————————————"
return image(
b64=await text2image(
f"\n{place} 疫情数据:\n"
"——————————————\n"
f"\t新增病例:<f font_color=red>{intcomma(city['quezhen_add'])}</f>\n"
f"\t累计确诊:<f font_color=red>{intcomma(city['quezhen'])}</f>\n"
f"\t累计治愈:<f font_color=#39de4b>{intcomma(city['zhiyu'])}</f>\n"
f"\t死亡:{intcomma(city['siwang'])}\n"
"——————————————\n",
font_size=30,
color="#f9f6f2",
padding=15
)
)
except Exception as e:
logger.error(f"疫情查询发生错误 {type(e)}{e}")

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -17,7 +17,7 @@ async def init():
await db.gino.create_all()
logger.info(f'Database loaded successfully!')
except Exception as e:
raise Exception(f'数据库连接错误.... e: {e}')
raise Exception(f'数据库连接错误.... {type(e)}: {e}')
async def disconnect():

View File

@ -2,11 +2,10 @@
"update_file": [
"plugins",
"models",
"basic_plugins",
"utils",
"services",
"configs/utils",
"utils",
"resources/ttf"
],
"add_file": ["resources/img/genshin/genshin_card", "resources/img/genshin/genshin_memo"],
"add_file": ["resources/img/other/time.png"],
"delete_file": []
}

View File

@ -11,6 +11,7 @@ import random
import cv2
import base64
import imagehash
import re
ImageFile.LOAD_TRUNCATED_IMAGES = True
Image.MAX_IMAGE_PIXELS = None
@ -136,6 +137,178 @@ def is_valid(file: str) -> bool:
return valid
async def text2image(
text: str,
auto_parse: bool = True,
font_size: int = 20,
color: Union[str, Tuple[int, int, int], Tuple[int, int, int, int]] = "white",
font: str = "CJGaoDeGuo.otf",
font_color: Union[str, Tuple[int, int, int]] = "black",
padding: Union[int, Tuple[int, int, int, int]] = 0,
) -> str:
"""
说明
解析文本并转为图片
使用标签
<f> </f>
可选配置项
font: str -> 特殊文本字体
font_size: int -> 特殊文本大小
font_color: str -> 特殊文本颜色
示例
在不在<f font=YSHaoShenTi-2.ttf font_size=30 font_color=red>HibiKi小姐</f>
你最近还好吗<f font_size=15 font_color=black>我非常想你</f>这段时间我非常不好过
<f font_size=25>抽卡抽不到金色</f>这让我很痛苦
参数
:param text: 文本
:param auto_parse: 是否自动解析否则原样发送
:param font_size: 普通字体大小
:param color: 背景颜色
:param font: 普通字体
:param font_color: 普通字体颜色
:param padding: 文本外边距元组类型时为
"""
if auto_parse and re.search(r"<f(.*)>(.*)</f>", text):
_data = []
new_text = ""
placeholder_index = 0
for s in text.split("</f>"):
r = re.search(r"<f(.*)>(.*)", s)
if r:
start, end = r.span()
if start != 0 and (t := s[:start]):
new_text += t
_data.append(
[
(start, end),
f"[placeholder_{placeholder_index}]",
r.group(1).strip(),
r.group(2),
]
)
new_text += f"[placeholder_{placeholder_index}]"
placeholder_index += 1
new_text += text.split("</f>")[-1]
image_list = []
current_placeholder_index = 0
# 切分换行,每行为单张图片
for s in new_text.split("\n"):
_tmp_text = s
img_height = BuildImage(0, 0, font_size=font_size).getsize("")[1]
img_width = 0
_tmp_index = current_placeholder_index
for _ in range(s.count("[placeholder_")):
placeholder = _data[_tmp_index]
if "font_size" in placeholder[2]:
r = re.search(r"font_size=['\"]?(\d+)", placeholder[2])
if r:
w, h = BuildImage(0, 0, font_size=int(r.group(1))).getsize(
placeholder[3]
)
img_height = img_height if img_height > h else h
img_width += w
else:
img_width += BuildImage(0, 0, font_size=font_size).getsize(
placeholder[3]
)[0]
_tmp_text = _tmp_text.replace(f"[placeholder_{_tmp_index}]", "")
_tmp_index += 1
img_width += BuildImage(0, 0, font_size=font_size).getsize(_tmp_text)[0]
# img_width += len(_tmp_text) * font_size
# 开始画图
A = BuildImage(
img_width, img_height, color=color, font=font, font_size=font_size
)
basic_font_h = A.getsize("")[1]
current_width = 0
# 遍历占位符
for _ in range(s.count("[placeholder_")):
if not s.startswith(f"[placeholder_{current_placeholder_index}]"):
slice_ = s.split(f"[placeholder_{current_placeholder_index}]")
await A.atext(
(current_width, A.h - basic_font_h - 1), slice_[0], font_color
)
current_width += A.getsize(slice_[0])[0]
placeholder = _data[current_placeholder_index]
# 解析配置
_font = font
_font_size = font_size
_font_color = font_color
for e in placeholder[2].split():
if e.startswith("font="):
_font = e.split("=")[-1]
if e.startswith("font_size="):
_font_size = int(e.split("=")[-1])
if _font_size > 1000:
_font_size = 1000
if _font_size < 1:
_font_size = 1
if e.startswith("font_color"):
_font_color = e.split("=")[-1]
text_img = BuildImage(
0,
0,
plain_text=placeholder[3],
font_size=_font_size,
font_color=_font_color,
font=_font,
)
_img_h = (
int(A.h / 2 - text_img.h / 2)
if new_text == "[placeholder_0]"
else A.h - text_img.h
)
await A.apaste(text_img, (current_width, _img_h - 1), True)
current_width += text_img.w
s = s[
s.index(f"[placeholder_{current_placeholder_index}]")
+ len(f"[placeholder_{current_placeholder_index}]") :
]
current_placeholder_index += 1
if s:
slice_ = s.split(f"[placeholder_{current_placeholder_index}]")
await A.atext((current_width, A.h - basic_font_h), slice_[0])
current_width += A.getsize(slice_[0])[0]
A.crop((0, 0, current_width, A.h))
# A.show()
image_list.append(A)
height = 0
width = 0
for img in image_list:
height += img.h
width = width if width > img.w else img.w
top_padding = left_padding = 0
if padding:
if isinstance(padding, int):
width += padding * 2
height += padding * 2
top_padding = left_padding = padding
elif isinstance(padding, tuple):
width += padding[0] + padding[2]
height += padding[1] + padding[3]
top_padding = padding[0]
left_padding = padding[1]
A = BuildImage(width + left_padding, height + top_padding, color=color)
current_height = top_padding
for img in image_list:
await A.apaste(img, (left_padding, current_height), True)
current_height += img.h
# A.show()
return A.pic2bs4()
else:
width = 0
height = 0
_tmp = BuildImage(0, 0, font_size=font_size)
for x in text.split("\n"):
w, h = _tmp.getsize(x)
height += h
width = width if width > w else w
A = BuildImage(width, height, font_size=font_size, color=color)
await A.atext((0, 0), text, font_color)
# A.show()
return A.pic2bs4()
class BuildImage:
"""
快捷生成图片与操作图片的工具类
@ -155,7 +328,7 @@ class BuildImage:
ratio: float = 1,
is_alpha: bool = False,
plain_text: Optional[str] = None,
font_color: Optional[Tuple[int, int, int]] = None,
font_color: Optional[Union[str, Tuple[int, int, int]]] = None,
):
"""
参数
@ -167,7 +340,7 @@ class BuildImage:
:param image_mode: 图片的类型
:param font_size: 文字大小
:param background: 打开图片的路径
:param ttf: 字体默认在 resource/ttf/ 路径下
:param font: 字体默认在 resource/ttf/ 路径下
:param ratio: 倍率压缩
:param is_alpha: 是否背景透明
:param plain_text: 纯文字文本
@ -367,7 +540,7 @@ class BuildImage:
self,
pos: Tuple[int, int],
text: str,
fill: Tuple[int, int, int] = (0, 0, 0),
fill: Union[str, Tuple[int, int, int]] = (0, 0, 0),
center_type: Optional[Literal["center", "by_height", "by_width"]] = None,
):
"""
@ -385,7 +558,7 @@ class BuildImage:
self,
pos: Tuple[int, int],
text: str,
fill: Tuple[int, int, int] = (0, 0, 0),
fill: Union[str, Tuple[int, int, int]] = (0, 0, 0),
center_type: Optional[Literal["center", "by_height", "by_width"]] = None,
):
"""
@ -620,7 +793,7 @@ class BuildImage:
async def aline(
self,
xy: Tuple[int, int, int, int],
fill: Optional[Tuple[int, int, int]] = None,
fill: Optional[Union[str, Tuple[int, int, int]]] = None,
width: int = 1,
):
"""
@ -636,7 +809,7 @@ class BuildImage:
def line(
self,
xy: Tuple[int, int, int, int],
fill: Optional[Tuple[int, int, int]] = None,
fill: Optional[Union[Tuple[int, int, int], str]] = None,
width: int = 1,
):
"""
@ -784,6 +957,58 @@ class BuildImage:
self.markImg = self.markImg.filter(_x)
self.draw = ImageDraw.Draw(self.markImg)
async def areplace_color_tran(
self,
src_color: Union[
Tuple[int, int, int], Tuple[Tuple[int, int, int], Tuple[int, int, int]]
],
replace_color: Tuple[int, int, int],
):
"""
说明
异步 颜色替换
参数
:param src_color: 目标颜色或者使用列表设置阈值
:param replace_color: 替换颜色
"""
self.loop.run_in_executor(
None, self.replace_color_tran, src_color, replace_color
)
def replace_color_tran(
self,
src_color: Union[
Tuple[int, int, int], Tuple[Tuple[int, int, int], Tuple[int, int, int]]
],
replace_color: Tuple[int, int, int],
):
"""
说明
颜色替换
参数
:param src_color: 目标颜色或者使用元祖设置阈值
:param replace_color: 替换颜色
"""
if isinstance(src_color, tuple):
start_ = src_color[0]
end_ = src_color[1]
else:
start_ = src_color
end_ = None
for i in range(self.w):
for j in range(self.h):
r, g, b = self.markImg.getpixel((i, j))
if not end_:
if r == start_[0] and g == start_[1] and b == start_[2]:
self.markImg.putpixel((i, j), replace_color)
else:
if (
start_[0] <= r <= end_[0]
and start_[1] <= g <= end_[1]
and start_[2] <= b <= end_[2]
):
self.markImg.putpixel((i, j), replace_color)
#
def getchannel(self, type_):
self.markImg = self.markImg.getchannel(type_)

View File

@ -21,6 +21,9 @@ class Plugins2settingsManager(StaticData):
self._data = (
self._data["PluginSettings"] if self._data["PluginSettings"] else {}
)
for x in self._data.keys():
if self._data[x].get("cost_gold") is None:
self._data[x]["cost_gold"] = 0
def add_plugin_settings(
self,
@ -30,7 +33,8 @@ class Plugins2settingsManager(StaticData):
level: Optional[int] = 5,
limit_superuser: Optional[bool] = False,
plugin_type: Tuple[Union[str, int]] = ("normal",),
data_dict: Optional[dict] = None,
cost_gold: int = 0,
**kwargs
):
"""
添加一个插件设置
@ -40,21 +44,22 @@ class Plugins2settingsManager(StaticData):
:param level: 功能权限等级
:param limit_superuser: 功能状态是否限制超级用户
:param plugin_type: 插件类型
:param data_dict: 封装好的字典数据
:param cost_gold: 需要消费的金币
"""
if data_dict:
level = data_dict.get("level") if data_dict.get("level") is not None else 5
if kwargs:
level = kwargs.get("level") if kwargs.get("level") is not None else 5
default_status = (
data_dict.get("default_status")
if data_dict.get("default_status") is not None
kwargs.get("default_status")
if kwargs.get("default_status") is not None
else True
)
limit_superuser = (
data_dict.get("limit_superuser")
if data_dict.get("limit_superuser") is not None
kwargs.get("limit_superuser")
if kwargs.get("limit_superuser") is not None
else False
)
cmd = data_dict.get("cmd") if data_dict.get("cmd") is not None else []
cmd = kwargs.get("cmd") if kwargs.get("cmd") is not None else []
cost_gold = cost_gold if kwargs.get("cost_gold") else 0
self._data[plugin] = {
"level": level if level is not None else 5,
"default_status": default_status if default_status is not None else True,
@ -65,6 +70,7 @@ class Plugins2settingsManager(StaticData):
"plugin_type": list(
plugin_type if plugin_type is not None else ("normal",)
),
"cost_gold": cost_gold,
}
def get_plugin_data(self, module: str) -> dict: