763 Commits

Author SHA1 Message Date
acd5408552 🍱 更新xx用什么的数据集 2023-04-15 01:43:10 +08:00
31b6bc7de4 🍱 更新收集的宝箱数据 2023-04-14 11:58:26 +08:00
4db59f2b1d 🍱 更新新圣遗物数据 2023-04-13 14:21:48 +08:00
99496abd40 添加查询琦良良换xx圣遗物的支持 2023-04-13 01:09:17 +08:00
d372757f72 🍱 更新原神3.6版本的metadata 2023-04-12 01:01:56 +08:00
689efe6595 🍱 更新血量表等杂图资源 2023-04-09 00:56:57 +08:00
7ec5618d56 🍱 更新原石预估素材 2023-04-02 00:28:07 +08:00
b4817ef539 🍱 新增新角色的参考面板,优化体验 2023-04-01 00:49:27 +08:00
739a14237c 增加获取抽卡记录链接功能 (#449) 2023-03-26 13:18:41 +08:00
c7f7130db3 🍱 更新参考面板版本深渊内容 2023-03-25 13:24:52 +08:00
15671c5204 🐛 修复材料 (#470) 2023-03-21 17:13:38 +08:00
a9644b6af2 🍱 更新原石预估 2023-03-14 00:23:24 +08:00
ca793d9b50 新增导出v3数据 2023-03-09 23:15:46 +08:00
b2564f3303 新增gsrc (#463) 2023-03-08 22:27:56 +08:00
bf530c7c49 🐛 修复查询白术的数据异常 2023-03-02 22:24:25 +08:00
d3214bd468 🍱 补充部分原神3.6的数据资料 2023-03-02 21:49:46 +08:00
04e05d708a ️ 支持查询白术查询卡维,修复几个BUG,优化体验 2023-03-02 21:17:33 +08:00
986dc750de 🎨 删除通用获取成功log (#461) 2023-03-02 02:32:42 +08:00
e0f6e68fb8 🐛 修补MetaData, 调整BUG(#461) 2023-03-02 00:04:08 +08:00
94aaa52fd6 🍱 更新原神3.5版本MetaData 2023-03-01 01:12:37 +08:00
f684f0e833 add Python 3.11 tests 2023-02-23 11:52:00 +08:00
772d54ef99 ⬆️ update nonebug 2023-02-23 11:38:01 +08:00
b6c855c1ae 🎨 更新切换api的API地址 2023-02-15 21:06:38 +08:00
558f280996 🐛 修复下载全部资源的问题 2023-02-14 23:24:16 +08:00
d75a023d10 下载全部资源将会检查版本差异 2023-02-14 22:28:47 +08:00
cd2eb1d217 🐛 修复部分情况下,扫码登陆无法获取正确UID 2023-02-11 15:34:11 +08:00
1a69c787b2 🎨 扫码登陆功能改为群聊触发以降低封号概率 (#443)
* 将扫码登陆功能改为群聊降低封号概率,并且增加uid绑定检验。

* 将扫码登陆功能改为群聊降低封号概率,并且增加uid绑定检验。

* 将扫码登陆功能改为群聊降低封号概率,并且增加uid绑定检验。

* 🚨 auto fix by pre-commit-ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-02-09 21:55:31 +08:00
e77b8b74b4 新增强制刷新抽卡记录 2023-02-09 01:55:55 +08:00
5da43afd78 📝 合并雷神和薙刀效果 2023-02-08 00:26:19 +08:00
fa3319a48d 🚑️ 修复删除配置项错误的问题 2023-02-07 00:08:16 +08:00
4f349cd253 🎨 移除失效配置、新增随机图配置 2023-02-06 23:47:27 +08:00
955ff47542 🐛 修复查询雷神的数值错误 2023-02-06 23:40:16 +08:00
ae38504e7e 修复test_adv 2023-02-05 21:55:45 +08:00
03e31d6416 🔧 修复pre-commit 2023-02-05 21:07:55 +08:00
4f0a3202ea 📝 更新查询收集的最大值 2023-02-05 21:02:40 +08:00
32e15df3cd 👽️ 更换随机图接口地址 (#441) 2023-02-05 20:25:07 +08:00
3a202afd19 📝 更新攻略、gs帮助、修复伤害参考bug 2023-02-04 19:11:21 +08:00
28227236da 🎨 微调强制刷新界面` 2023-02-03 00:29:40 +08:00
ed68e42385 🎨 修改强制刷新界面 2023-02-02 00:27:40 +08:00
b850f099d1 👽 更新ENKA_API 2023-01-29 22:52:15 +08:00
768619e0c1 ⬆️ update poetry-core(#433) 2023-01-28 08:05:35 +08:00
137c83471e 🍱 更新3.4血量表抗性表 2023-01-27 23:44:25 +08:00
20319c02ac 🐛 修复注册时间 2023-01-26 20:28:11 +08:00
79d90deae0 🚨 移除重复导入 2023-01-26 19:35:35 +08:00
9fee49e090 新增原神注册时间命令 (#431) 2023-01-26 19:11:19 +08:00
cc145d9a5c 🐛 修复查询心海的伤害计算和毕业度错误 2023-01-25 20:58:00 +08:00
1fbecaee53 🎨扫码登陆套聊天记录 (#430)
* 更改了一下刷新抽卡失败的提示

* 为扫码登陆套聊天记录,加入免责声明

* 🚨 auto fix by pre-commit-ci

* Update qrlogin.py

* 🚨 auto fix by pre-commit-ci

* 🎨 移动通用函数至`message`

* 🚨 auto fix by pre-commit-ci

* 🚨 修复一些警告

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: KimigaiiWuyi <444835641@qq.com>
2023-01-25 16:33:21 +08:00
f7ff22ad4c 新增chbg文件夹以供查询角色的自定义图 2023-01-24 00:02:59 +08:00
416cc371fc 新增查成就查委托 2023-01-23 15:54:46 +08:00
e73cd9e6eb 🍱 更新一部分成就资源 2023-01-23 15:21:08 +08:00
ec622d1388 🍱 更新艾尔海森瑶瑶的参考面板 2023-01-22 23:03:27 +08:00
bdfc63a6c7 🍱 增加查询米卡的治疗量计算,修复旅行者BUG 2023-01-20 19:11:57 +08:00
0c7d737ab7 🐛 修复新角色基础数值错误的问题 2023-01-20 00:10:08 +08:00
e0ae84ac89 🍱 更新3.5版本角色的别名和有效词条 2023-01-19 23:37:12 +08:00
b9519acf89 🍱 支持部分3.5版本的角色和武器的替换 2023-01-19 23:19:37 +08:00
6f22752b07 🐛 修复签到 (#428) 2023-01-18 21:54:52 +08:00
e13b3e5a52 🍱 更新原神3.4版本MetaData 2023-01-18 02:02:51 +08:00
8b3771a3a0 🐛 修复原神每日签到奖励物品名称获取错误的问题 (#428)
* 修复原神每日签到奖励物品名称获取错误的问题

* 🚨 auto fix by pre-commit-ci

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-01-17 22:22:24 +08:00
4ec467e154 📝 修改ck帮助的说明 (#421) 2023-01-17 00:21:52 +08:00
5b6384764a 🎨 补充_pass内容 2023-01-17 00:15:16 +08:00
7838611f14 新增刷新全部CK(需SU用户) 2023-01-16 23:31:52 +08:00
24257cdf90 🐛 修复xx在哪的一部分使用体验 (#427) 2023-01-15 17:42:48 +08:00
7692e9799a 新增刷新CK(需要用户绑定SK) 2023-01-15 00:48:22 +08:00
bdff2b31c1 🎨 增加几个安柏计划API 2023-01-14 23:59:14 +08:00
052d3c1c73 🐛 修正暴击率低于0%时期望伤害低于普通值的问题 (#422)
* 修正暴击率低于0%时期望伤害低于普通值的问题

* 🚨 auto fix by pre-commit-ci

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-01-10 22:53:21 +08:00
e5824e407e 🍱 更新原始预估3.4 2023-01-10 22:50:40 +08:00
5540fab06a 🎨 修改convert_img方法 2023-01-08 00:53:55 +08:00
6240d020eb 🐛 修复错误的sp_base 2023-01-06 23:17:56 +08:00
59c93fd6ef 🍱 同步查询艾尔海森的倍率,新增查询夜兰的蒸发伤害 2023-01-05 23:49:31 +08:00
668ad813c8 🐛 修复特殊情况下几种默认反应倍率 2023-01-03 23:59:02 +08:00
5eb4675628 🐛 修复原神公告的部分详情出现https错误 2023-01-02 23:49:24 +08:00
261437f466 🐛 修复清除原神公告红点 2023-01-01 01:31:17 +08:00
b24708f913 📝 更新gs帮助 2022-12-30 00:30:11 +08:00
3ff5b4f2fa 🐛 修复查询绫人等几个角色的伤害异常(#413) 2022-12-29 23:36:56 +08:00
698d310684 🎨 improve config
genshinuid_disabled_plugins: 禁用的插件(meta 无效)
genshinuid_priority: GenshinUID 的优先级

e.g.
```env
genshinuid_disabled_plugins=["enka", "help", "map"]
genshinuid_priority=5
```
2022-12-29 22:02:05 +08:00
18ed57b93a 🐛 修复导入子插件不完整的问题 2022-12-28 23:54:31 +08:00
ea486f7ff5 🐛 修复SQLModel导包问题 2022-12-28 23:49:15 +08:00
cd4ecb462c 🎨 separation of test dependencies into a new group
only test: poetry install --with test --without dev
2022-12-28 22:55:55 +08:00
3c3785cd48 🚨 fix lint warnings 2022-12-28 22:38:37 +08:00
37a6d2f7a8 新增原神公告 (#409) 2022-12-28 21:38:31 +08:00
29c46a93d6 🚑 fix bbs coin error 2022-12-28 10:22:08 +08:00
5ba1ba09e6 新增扫码登陆 2022-12-27 23:57:57 +08:00
21c7049fdd use pypi source default 2022-12-27 23:03:14 +08:00
76469c56a7 fix tests 2022-12-27 22:22:27 +08:00
b30bd4fa9c 🎨 update metadatas 2022-12-27 22:07:19 +08:00
eb6e822b6f 新增版本深渊,后可跟版本号 2022-12-22 00:16:22 +08:00
80f8a12789 增加hhw_api的相关方法 2022-12-21 23:01:43 +08:00
278cbcaa63 🎨 调整添加CK时候的判定顺序,修复几个BUG 2022-12-20 00:42:56 +08:00
ac98c9f896 新增数据文件夹内bg文件夹,用于存放自定义图片 2022-12-19 00:04:30 +08:00
c02d1f2f07 新增查询探索, 重绘的查询收集 2022-12-18 19:51:00 +08:00
0f1a0b02c2 🎨 添加draw_bar绘图方法,重绘收集样式 2022-12-18 19:48:18 +08:00
f4d1d47554 🐛 修复已知BUG、修改参考数值和角色BUFF错误 2022-12-17 19:17:17 +08:00
fb4c6b569c 🐛 修复已知BUG,优化报错提示(#405) 2022-12-16 23:19:53 +08:00
5e52c9abd4 🎨 为多条推送信息添加换行符 (#403) 2022-12-14 12:12:37 +08:00
c413e7d65c 🐛 修正国际服七圣召唤api (#402) 2022-12-14 12:00:45 +08:00
9e6cd2a2a8 🐛 下载全部资源时判断是否为空文件名 2022-12-14 09:45:03 +08:00
38910e9a2b 🐛 查询时额外输出问题 2022-12-14 00:07:15 +08:00
933e97ff97 攻略换用本地攻略源 2022-12-13 23:23:04 +08:00
09aa9af93a 🎨 更新深渊概览API,添加自动下载攻略 2022-12-13 23:15:37 +08:00
f1ff90c423 🍱 补充3.3新角色的参考面板毕业度 2022-12-12 22:52:40 +08:00
897399b77e 📝 限制绑定uid位数, 补充gs帮助 2022-12-11 17:16:48 +08:00
0099d16072 🎨 一些响应方式的修改 2022-12-11 15:25:18 +08:00
519aef0ca1 🎨 修改资源文件名 (#400)
* 修改资源文件名

统一命名,去除卡牌资源文件结尾的符号

* 🚨 auto fix by pre-commit-ci

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-11 14:07:54 +08:00
a6f66c5231 🎨 update dependencies 2022-12-11 14:01:01 +08:00
63488e7bbf 新增七圣召唤命令,后可跟UID 2022-12-11 13:54:13 +08:00
c7ceb7a14c 🎨 添加七圣召唤的API,修复一部分BUG 2022-12-11 13:50:06 +08:00
49612280fa 🍱 补充一些遗漏资源,修复几个BUG 2022-12-09 23:15:04 +08:00
e18e69aeed 🍱 补充一部分3.4的资源文件 2022-12-09 20:25:52 +08:00
1b402defbc 新增原牌功能, 例如原牌狼末 2022-12-08 23:29:54 +08:00
245446e329 🍱 增加一些资源文件 2022-12-08 23:20:55 +08:00
0832d9d79e 📝 提高原神版本至3.3 2022-12-07 01:08:32 +08:00
376f537701 🍱 新增原神3.3版本的元数据 2022-12-07 01:05:54 +08:00
a5933222c5 🐛 修复低星圣遗物的错误 2022-12-05 23:39:38 +08:00
455e9207ff 🐛 修复抽卡记录平均UP错误和提纳里的毕业度 2022-12-04 17:03:39 +08:00
fee7e8a936 🎨 优化一部分API访问 2022-12-04 13:55:06 +08:00
ba2b4aa86f 🐛 修复截获CK字段的错误 2022-12-03 00:04:32 +08:00
76f18d9c7c 🍱 补充版本规划3.3 2022-12-02 22:51:23 +08:00
95dbe36cf9 🐛 修复深渊概览刷新失败 2022-12-02 22:45:24 +08:00
d0d56f1a6d 🐛 修复未绑定UID时签到指令异常返回 2022-11-30 23:53:00 +08:00
b3a64c8aec 🐛 修复查询妮露的不正确毕业度(#397) 2022-11-29 22:01:36 +08:00
9d34e463ec 🎨 强制刷新支持使用@别人查询(#396) 2022-11-29 21:14:53 +08:00
0cb727784b 🎨 优化毕业度的计算值 2022-11-29 21:09:23 +08:00
1b743e9096 🎨 重做的毕业度计算 2022-11-29 01:48:01 +08:00
1ec87752a4 🚑️ 补充错误获取的CK 2022-11-26 23:31:42 +08:00
94050454e6 新增深渊统计(深渊概览) 2022-11-26 15:12:15 +08:00
2886cbfebf 🐛 修复缓存获取CK的BUG 2022-11-26 15:06:46 +08:00
fddc85c91e 🐛 修复仅修改命座的报错 2022-11-24 11:57:02 +08:00
63f5d0686b 🐛 修复查询六命散兵换xx无法生效的问题 2022-11-24 00:34:03 +08:00
21a6a3eafc 支持查询公子换香菱沙类似用法,并可以任意组合 2022-11-24 00:23:24 +08:00
a7eb2a33cb 💥 修改PROXY配置至config.json 2022-11-23 22:02:33 +08:00
aaf7431c92 🐛 兼容国际服的ID至UID的转换, 尝试从绑定UID读取 2022-11-12 17:00:29 +08:00
49a77f7fb9 👽️ 判断v2版本的米游社CK(#383) 2022-11-12 16:18:02 +08:00
ef923c5ba9 🐛 修复 Actions 错误 (#371)
* 🐛 修复 Actions 错误
 - PR 仓库无法执行 pre-commit
 - metadata 单元测试出错

* 🐛 修复 etc 单元测试出错

* 🐛 修复 pre-commit Actions 在 PR 中 checkout 错误

* 🚧 添加 pre-commit Actions 权限

* 🚧 调整 `pull_request_target` 触发类型

* 🚧 区分 pre-commit 提交步骤

* 🐛 remove `pull_request` trigger

* 🚨 auto fix by pre-commit-ci

* 🔥 delete pre-commit workflow

Co-authored-by: MingxuanGame <MingxuanGame@outlook.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-11-12 00:33:54 +08:00
68c42305e5 🎨 改进一部分错误提示 2022-11-12 00:28:55 +08:00
7fb4a4d572 👽️ 增加mr出现验证码的错误提示(#379) 2022-11-11 23:42:44 +08:00
ecdb232beb 🎨 修改部分角色BUFF,修改部分UI表现 2022-11-11 22:51:06 +08:00
8cd9570e2d 支持查询beta角色(数据从安柏计划获取) 2022-11-10 01:39:37 +08:00
e42ef039d1 📝 增加WeChat适配器的相关描述 2022-11-09 00:32:22 +08:00
28dce2f15c 为校验全部Cookies功能添加国际服支持(#377) 2022-11-08 21:36:21 +08:00
5ee22c89bf 🍱 增加一部分提示, 更新血量表等资源(#364) 2022-11-07 00:08:43 +08:00
9ddba001be 🐛 修复纳西妲业障除的伤害计算错误 2022-11-06 20:33:41 +08:00
58cabae6ee 🚑强制刷新检查绑定的UID 2022-11-06 19:13:12 +08:00
b59b406027 久岐忍,刻晴等角色添加更多的反应, 修复一些效果错误 2022-11-06 18:42:44 +08:00
e6d4d452a5 🍱 更新纳西妲的参考面板 2022-11-06 15:41:17 +08:00
8d82fba7af 🎨 添加判断刻晴是不是up (#376) 2022-11-06 14:45:25 +08:00
0a81e2b9fa 🐛 修复抽卡记录兜底值 2022-11-06 01:05:45 +08:00
98e0174348 重做的抽卡记录 2022-11-06 00:47:11 +08:00
9596199a3a 🐛 修复导入抽卡数据的ID错误 2022-11-05 01:49:57 +08:00
b9406eb634 🐛 修复低星圣遗物面板刷新的问题(#360) 2022-11-05 01:17:03 +08:00
30f164b2a1 添加几个角色的反应伤害, 修复*海量BUG 2022-11-04 23:35:01 +08:00
66224ece5b 🐛 修复防御力不正确加成, 优化使用体验 2022-11-03 05:11:50 +00:00
db9860531b 🐛 圣遗物四件套情况少计算两件套效果 2022-11-03 00:45:33 +08:00
d8d2ede988 支持查询六命莱依拉带精五月光换公子圣遗物类似用法 2022-11-03 00:00:00 +08:00
044701e730 🐛 修复一些效果和标记问题 2022-11-02 22:12:14 +08:00
2d1f766d7c 🐛 修正国际服ds生成规则 (#370) 2022-11-02 20:52:42 +08:00
b01117c224 🔧 兼容 Poetry (#368) 2022-11-02 16:04:22 +08:00
8ca7237075 🚑 向下兼容Python版本 2022-11-02 15:40:50 +08:00
41f047a96f 🐛 临时对随机获取cookie过程进行服务器隔离防止互相污染 (#367) 2022-11-02 13:25:45 +08:00
ad3859ed71 🍱 更新原神3.2版本伤害数据 2022-11-02 13:13:14 +08:00
e62f9ba574 🍱 新增原神3.2版本的元数据 2022-11-02 08:47:41 +08:00
93bcf9fbbc 🎨 统一角色面板处理文件 2022-11-01 22:50:56 +08:00
3ac2267cee 🐛 修复更新记录的绘图越界 2022-11-01 21:50:37 +08:00
c46f14e59f 为部分功能添加国际服支持 (#366)
Signed-off-by: Chino Kafuu <twfx1207@gmail.com>
2022-11-01 21:12:53 +08:00
99be740d11 ♻️ 重构部分伤害计算相关代码 2022-11-01 21:10:39 +08:00
21ddfa3cd6 补全对PicMenu的支持 (#361) 2022-10-31 15:10:10 +08:00
00bdc5fccb 🍱 更新参考面板妮露, 修复已知Bug 2022-10-24 21:16:20 +08:00
918632ad71 🐛 向下兼容网页控制台 2022-10-23 22:18:26 +08:00
b4f8371e5d 网页控制台为无管理员权限用户新增添加CK功能(#347) 2022-10-23 21:32:08 +08:00
59cc1e35c4 🐛 修复替换武器时因未正确判断类型导致伤害错误 2022-10-22 00:47:25 +08:00
798069565a 🎨 更新角色别名配置 (#359)
* 🎨 更新角色别名配置

* 🐛 修复角色别名识别

不再考虑输入为别名中字符串子串的情况
2022-10-22 00:13:43 +08:00
0b3dddb870 新增更新记录 2022-10-22 00:06:23 +08:00
58a0df17b8 新增gs清除缓存(如查询相关异常可尝试) 2022-10-21 00:40:34 +08:00
bdd4f26fe3 调整数据库缓存清除逻辑 2022-10-21 00:34:16 +08:00
c3ae3ed0db 查询妮露增加丰穰之核伤害计算(默认算上双水双草Buff) 2022-10-20 23:48:41 +08:00
ecd7a57ef3 🐛 查询甘雨伤害大招加成计算有误 2022-10-20 01:20:40 +08:00
c231cb4267 gs开启随机图的面板回复开启原图功能 2022-10-18 22:33:23 +08:00
26eb980e5b 🚚 为资源文件夹添加TEMP目录 2022-10-18 22:31:42 +08:00
ffb2558fec 🐛 修复一个面板抗性引发的问题; 更新伤害乘区 2022-10-18 21:00:47 +08:00
a9f26bb102 📝 补充gs帮助文件 2022-10-18 00:55:20 +08:00
2c1ad1466b 🎨 利用fastapi_genshin_map重写地图逻辑 2022-10-18 00:33:12 +08:00
25ffbfc4bc 🐛 修复一个导致CK死循环的错误(#354) 2022-10-17 22:49:38 +08:00
34eb5093d9 🐛 修复查询满命妮露的问题 2022-10-16 13:46:58 +08:00
9ac01864c5 重做的活动列表和新增卡池列表 2022-10-14 22:26:12 +08:00
db3ba78639 🎨 更高容纳度的get_qq_avatar方法 2022-10-14 01:28:13 +08:00
7617c29b6d 🔧 重命名依赖项 2022-10-14 01:10:42 +08:00
62d8ee5cd3 🐛 活动列表现在可以使用 2022-10-13 22:42:45 +08:00
bec03e8acc 重做的毕业度统计 2022-10-12 23:56:08 +08:00
396015763b 🎨 新增复用绘图方法, 更换默认背景图 2022-10-12 23:51:15 +08:00
4a1c402c38 ️ 增加gs帮助的内容 2022-10-10 23:53:06 +08:00
5fc6df94f6 现在查询展柜角色以图片返回 2022-10-10 23:29:17 +08:00
c39ddf30c2 🎨 优化绘图方法, 从中间裁切, 更新部分默认背景 2022-10-10 23:27:04 +08:00
124de5aff3 🐛 修复旅行者ID问题 2022-10-10 09:58:37 +08:00
3e61f3411a 🐛 修复强制刷新旅行者无法显示 2022-10-10 08:45:13 +08:00
1488e3eebb 🍱 更新3.1角色的参考面板 2022-10-10 00:41:21 +08:00
f32e40d362 现在强制刷新以图片返回结果 2022-10-10 00:25:54 +08:00
60af532185 🎨 新增一些绘图方法, 简化代码 2022-10-10 00:16:14 +08:00
ff317b8f7c 🐛 修复在高版本的依赖下插件报错 2022-10-07 22:28:33 +08:00
a703593836 新增清除无效用户(#206) 2022-10-07 21:28:45 +08:00
5f801276f5 🚑️ 缺漏符号 2022-10-07 13:39:13 +08:00
a2a6228b66 🎨 修改网页控制台主页 2022-10-07 13:35:11 +08:00
712380c24b 🎨 拉大签到间隔时长 2022-10-06 23:38:31 +08:00
27db2e14c4 新增gs开启跳过无感验证 2022-10-06 23:15:02 +08:00
3005b435d2 🐛 网页控制台的HTML修改 2022-10-06 19:29:05 +08:00
46a6e846e6 新增查询公子成长曲线类似用法 2022-10-05 18:24:19 +08:00
954e1dd965 新增各种缺失的曲线数据,修复大量面板Bug 2022-10-05 18:21:33 +08:00
f40730e510 improve downloading files 2022-10-05 15:46:30 +08:00
a60baf7975 add tests for etcimg and guide 2022-10-04 22:03:42 +08:00
7b9aec2761 🐛 fix creating map 2022-10-04 20:01:27 +08:00
a40a0ea74d 🙈 update .gitignore 2022-10-04 17:46:26 +08:00
711fe2ad1c 🎨 why not use Chinese? 2022-10-04 17:43:25 +08:00
391bf0aa0b 新增gs开启多彩面板 2022-10-04 00:09:50 +08:00
56a609226b support changing primary key 2022-10-03 23:02:27 +08:00
bc17763617 🐛 fix changing config error 2022-10-03 19:33:46 +08:00
a5a418f51c 🚀 support deploying by docker
docker build -t genshinuid:v3.1.0 .

nonebot 在 /nb2/nb2,GenshinUID 在 /plugin,需要的可自行挂载(用 docker volume)

默认不带有 go-cqhttp 及 nonebot-plugin-gocqhttp 插件,暴露端口 8080,需要自己连接 go-cqhttp

build 前修改 deploy 文件夹下的 .env.dev 修改镜像的 nonebot2 配置,或者可以运行后挂载 nb2 目录修改
2022-10-03 18:17:18 +08:00
aeec83f982 🐛 fix tests 2022-10-02 23:49:07 +08:00
85171c0172 ✏️ rename branch 2022-10-02 23:45:42 +08:00
1c363b7ff3 init tests 2022-10-02 23:43:40 +08:00
19dd446219 🎨 限制触发条件 2022-10-02 22:52:13 +08:00
6c778f1fcb 新增血量排行 2022-10-02 22:42:49 +08:00
7dad667064 🎨 更新收集数据,血量表,抗性表 2022-10-02 22:37:57 +08:00
c0532c06dd 🐛 面板查询的几个遗留问题 2022-10-02 22:15:14 +08:00
245121b318 🐛 remove logger for settings 2022-10-02 21:57:22 +08:00
501e8398b0 🐛 fix pydantic checking error 2022-10-02 21:40:46 +08:00
bac4d7061c mount WebConsole to nonebot ASGI server
path: /genshinuid
2022-10-02 18:47:27 +08:00
2cddf1c481 🎨 修改收集的数据和生成地图相关问题 2022-10-02 16:28:01 +08:00
973c64a2dc ⬆️ update genshinmap from MingxuanGame/GenshinMap 2022-10-02 14:11:50 +08:00
d4fd84da9b 🎨 更新gs帮助以及补漏其他功能 2022-10-02 01:53:28 +08:00
fd1f366db3 🐛 原石札记中分母为0的情况(#346) 2022-10-02 01:17:46 +08:00
86cc55cf78 🍱 角色成长曲线数据 2022-10-02 01:13:46 +08:00
70bc3b5143 新增御神签(#344) 2022-10-02 00:09:58 +08:00
6838ce7d5a 新增抽表情(#344) 2022-10-01 21:56:12 +08:00
75269479be 🐛 原石札记的一些UI问题 2022-10-01 20:41:20 +08:00
5d426aa4b4 新增当前信息(#337) 2022-10-01 19:49:01 +08:00
34af5a7c27 增加draw_note_img方法(#337) 2022-10-01 19:05:18 +08:00
dbd60d4ac4 🎨 原石预估现在将会输出当前原神版本的对应图片 2022-09-29 21:56:52 +08:00
ad4af70e21 新增赛诺E渡荒之雷伤害计算及超激化, 修复大量bug 2022-09-29 21:49:02 +08:00
06fa1a71fa 🎨 计算基础天赋时,如果没有则跳过 2022-09-29 08:40:59 +08:00
8cffc3f070 🐛 每日空值忽略世界等级(#342) 2022-09-28 22:32:58 +08:00
670cf730e7 🐛 每日如果收到空值则忽略签名处理(#342) 2022-09-28 21:15:26 +08:00
76a350a834 🐛 一部分武器的效果异常 2022-09-28 10:45:34 +08:00
830a246d96 🍱 新增原神3.1版本的角色和武器数据 2022-09-28 10:13:10 +08:00
5f7dfb93fc 🎨 修改mask.png的所在位置 2022-09-26 22:57:23 +08:00
113613bc94 🍱 新增原神3.1版本的元数据 2022-09-26 22:36:43 +08:00
bb6a2666ff 🐛 伤害值增加的错误计算 2022-09-26 21:35:45 +08:00
0e90dd9613 🐛 修复磐岩结绿攻击力转化效果 (#340) 2022-09-26 09:57:40 +08:00
2a5144b1d6 🎨 忽略空值 (#336) 2022-09-25 17:28:20 +08:00
1591cc6052 🐛 修复查询旅行者的问题 2022-09-24 22:49:58 +08:00
d8ec80bcd2 支持查询六命公子换精五飞雷类似用法 2022-09-24 18:59:31 +08:00
a50f26ecdc 支持查询雷神换精三弓藏类似用法 2022-09-22 23:44:22 +08:00
e59d42e168 🐛 现在可以更换低星武器 2022-09-22 23:29:08 +08:00
0941cd1196 🐛 修复抽卡记录中可能获取到空字典的情况 2022-09-22 23:17:36 +08:00
3e22dae35f 🐛 修复查询公子换月华时生命不正确以及部分角色天赋问题 2022-09-22 23:02:37 +08:00
ca40fad6d3 支持查询公子换冬极类似用法 2022-09-22 01:40:57 +08:00
11bee5a2fc 🎨 改进一些奇怪的问题 2022-09-22 01:39:19 +08:00
9cd5fbd0dc 🐛 解决远程链接用户无法发送本地图片 2022-09-22 01:12:21 +08:00
5443ef8ae2 使用计算替代读取面板, 也可使用gs开启旧面板返回 2022-09-22 01:08:16 +08:00
6e90802e30 🐛 修复琴位于探索中每日失效的问题 2022-09-21 01:58:41 +08:00
79f9aa9237 新增原石统计3.1 2022-09-20 21:33:15 +08:00
81da9e5735 🎨 gs重启将会杀死windows进程 2022-09-19 21:18:00 +08:00
fe439f7fb8 📝 Update requirements.txt 2022-09-19 21:16:56 +08:00
2608259a14 🐛 更新gs帮助 2022-09-18 18:32:58 +08:00
ca49ee0682 📝 更新gs帮助 2022-09-18 18:28:47 +08:00
c0ab255b32 📝 优化gs更新提示 2022-09-18 16:56:11 +08:00
99146c70ac 🐛 使用driver替换@get_driver() 2022-09-18 01:53:13 +08:00
8b7a1f5da7 🎨 优化的gs重启 2022-09-18 01:51:13 +08:00
d1312c5ecc gs重启 2022-09-17 21:32:20 +08:00
f2e3687f17 🎨 优化gs更新返回提醒 2022-09-17 11:18:50 +08:00
fbc76e5f8c 📝 导入新子插件包 2022-09-17 01:37:11 +08:00
4511f6c6c2 gs更新,gs强制更新,gs强行强制更新 2022-09-17 01:23:08 +08:00
7d98e374ee 🎨 分离添加时发送的消息类型 2022-09-17 00:17:33 +08:00
c917459e79 🐛 修复五郎位于探索中每日失效的问题(#334) 2022-09-17 00:14:16 +08:00
63710928f4 🔧 增加GitPython,fastapi_user_auth,fastapi_amis_admin依赖 2022-09-17 00:11:07 +08:00
5d21214a65 新增gs开启网页控制台 2022-09-16 23:58:18 +08:00
ab83a6689f 🎨 改进部分写法以避免type ignore (#332) 2022-09-14 23:04:31 +08:00
c8238e83cf 🐛 查询云堇时毕业度不正确显示 2022-09-12 16:04:40 +08:00
79bb8c2595 🍱 毕业度计算增加多莉,钟离E总护盾量 2022-09-12 15:02:18 +08:00
2ba6701304 🎨 修正新角色的有效词条 2022-09-12 12:10:21 +08:00
29a5a1a8b5 🐛 使用绝对路径导出抽卡记录 2022-09-12 00:45:35 +08:00
0faeef3544 抽卡记录中角色祈愿将新增up标识 2022-09-12 00:26:50 +08:00
efb31d55af 🐛 查询角色时因随机图API导致的错误 2022-09-11 23:11:12 +08:00
997e024681 🎨 调整并发任务超时时间 2022-09-11 20:50:24 +08:00
1445e0decb 📝 add requirements.txt 2022-09-11 19:11:19 +08:00
2a55819cd5 增加删除CK的数据库方法(#206) 2022-09-11 19:08:23 +08:00
cbf8d26005 使用sqlmodel替换base基类(#319) 2022-09-11 17:52:28 +08:00
4dc93cb7c2 🐛 修复消息段类型不匹配导致无法发送消息 (#329) 2022-09-11 17:50:29 +08:00
43e1202499 🐛 修复伤害计算因暴击率造成的数值错误(#328) 2022-09-11 14:49:46 +08:00
47fbf74e29 更换为下载速度更快的MINIGGICU 2022-09-11 14:35:55 +08:00
27b343a95e 🐛 auto move: delete utils 2022-09-10 18:00:01 +08:00
e8642ac7d8 add auto move files script 2022-09-10 17:49:01 +08:00
ffd27fe2db 🐛 gs帮助在部分情况下无法发送成功 2022-09-10 15:25:55 +08:00
b8395ab3fe 🐛 提高等待时间 2022-09-10 15:22:11 +08:00
e95f1ce4e3 🐛 并发下载漏剩余文件 2022-09-10 15:18:56 +08:00
cf67c7f1ea 并发下载资源包 2022-09-10 15:14:38 +08:00
5bd4890add 🚑 exist_ok=True 2022-09-10 15:02:03 +08:00
38471d4f11 🔀 merge nonebot2-beta1-git into nonebot2-beta1 (#325)
 支持使用 pip/nb-cli 安装
2022-09-10 14:49:16 +08:00
d3e1b24fdb 🔊 change warning to info 2022-09-10 00:25:48 +08:00
3cefc786ff 🔥 remove poetry.lock 2022-09-10 00:21:31 +08:00
d2f9c95e95 🐛 init dir 2022-09-10 00:20:37 +08:00
bdfd5714d2 🐛 遗漏的路径 2022-09-09 23:46:13 +08:00
244e4ae414 🚚 移动资源路径 2022-09-09 23:32:33 +08:00
0f225418be 🚚 change the player data path 2022-09-09 22:58:29 +08:00
82f7b05a69 🎨 change the warning colors 2022-09-09 22:30:11 +08:00
78daf6a934 support installing by pip 2022-09-09 20:58:48 +08:00
843166211b 📝 更新README.md 2022-09-09 11:34:42 +08:00
9fffc3be60 🐛 修复新匹配算法带来的问题 2022-09-09 00:27:48 +08:00
0643b7d888 添加CK和SK时转为图片回复(#320) 2022-09-09 00:13:17 +08:00
0dff2bf76a 🎨 增加添加CK的返回图片 2022-09-09 00:11:25 +08:00
ee88d072a1 🎨 降低精通带来的毕业度提升 2022-09-08 23:16:43 +08:00
89181be54a 🎨 增加gs帮助内容 2022-09-08 21:48:57 +08:00
bc522c2259 🐛 修复计算毕业度时香菱的攻击加成 2022-09-08 13:01:45 +08:00
6f8c5b60e0 gs帮助现在可用 2022-09-08 02:31:29 +08:00
b5992535c8 draw_help_card.py 2022-09-08 02:29:57 +08:00
1354400e27 👽️ 修复Enka的返回值增加 2022-09-07 10:50:51 +08:00
a96cb5b92f 🐛 角色伤害加成获取有误 2022-09-07 10:23:05 +08:00
2682b0c807 💬 增加制作帮助图所需资源 2022-09-07 00:52:09 +08:00
7788067def 🐛 小鹿的英文简称错误 2022-09-06 19:55:09 +08:00
7ba36afa97 🐛 神里绫华Q+3不生效 2022-09-06 15:05:15 +08:00
3c6f46bf7b 🐛 伤害计算减防不生效 2022-09-06 15:04:37 +08:00
3c8a706d2d Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-09-06 10:36:53 +08:00
fe1dad35ab 🚑 fix unknown parameterless 2022-09-06 10:34:33 +08:00
7c6d123bff 📝 更新须弥宝箱数量(#318) 2022-09-06 09:35:17 +08:00
45e3781020 use rule to simplify code 2022-09-05 23:40:25 +08:00
40af1c28db 🎨 补充遗漏内容 2022-09-05 21:44:03 +08:00
f325cc136b 新增gs开启催命模式 2022-09-05 21:41:36 +08:00
31d3f6f783 🍱 更新血量表,抗性表, 增加雷神E协同攻击超激化 2022-09-04 14:08:40 +08:00
e8ca7f7853 新增任务<任务名>,任务<地区名> 2022-09-04 13:58:17 +08:00
ff4ee1929d 🔥 删除无用代码 2022-09-04 01:39:16 +08:00
1b8e05d02b 改进的毕业度计算 2022-09-04 01:22:04 +08:00
5dbea107ab 🎨 修复空UID仍然输出log(#316) 2022-09-03 17:45:45 +08:00
09b47a5f2d 🎨 增加几个角色的反应伤害;移除雷神A的超激化反应 2022-09-03 17:30:55 +08:00
03cc73696a 新增gs配置,gs开启定时签到,gs开启定时米游币 2022-09-03 11:07:08 +08:00
6cbb92423b draw_config_card.py 2022-09-03 11:03:19 +08:00
79dff3fe7c 🐛 值错误 2022-09-02 01:25:02 +08:00
0c4719dc07 🍻 修复之前bug造成的影响 2022-09-02 01:23:50 +08:00
f9e1c3f7dd 🐛 uigf_gacha_type映射关系 2022-09-02 01:18:32 +08:00
b67eed8089 Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-09-02 00:04:34 +08:00
f604d7a007 支持导出抽卡记录和导入抽卡记录 2022-09-02 00:04:00 +08:00
d222368ba8 Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-09-02 00:03:14 +08:00
2e361247c8 🐛 返回字段错误 2022-09-02 00:02:38 +08:00
46f389e5eb Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-09-02 00:01:54 +08:00
cbb7947dd0 👷 auto run pre-commit in pull requests 2022-09-02 00:01:09 +08:00
c52c2192e7 改进的导入导出方法 2022-09-01 23:41:02 +08:00
5402f034fe export and import.py 2022-09-01 00:22:28 +08:00
7d50cc134b 📝 新增xx用什么的须弥角色信息 2022-08-31 21:00:07 +08:00
71bcb82082 🐛 修复每月统计(#315) 2022-08-31 20:47:21 +08:00
7061832664 🐛 修复一些问题 2022-08-31 20:40:31 +08:00
bb119bfd6f 🐛 首次刷新抽卡记录可能失败 2022-08-31 02:44:56 +00:00
ee987c11ed 🐛 查询柯莱的蔓激化 2022-08-31 02:19:10 +00:00
d80706beaf 新增gs开启随机图 2022-08-31 01:39:52 +00:00
09f1f39d62 🐛 修复刷新抽卡记录 2022-08-30 23:55:34 +08:00
d95c1a0c2d 📝 增加更多的角色别名 2022-08-30 23:30:11 +08:00
10a0199fdb 🐛 尝试修复刷新抽卡记录的数据错误 2022-08-30 22:46:01 +08:00
edc86d456d 📝 修改收集命令数据为3.0版本 2022-08-30 22:25:17 +08:00
445d190d34 增加切换api 2022-08-30 22:22:50 +08:00
b84c00c6a1 🐛 现在可以使用草主推荐等旅行者攻略 2022-08-30 22:15:51 +08:00
de78a3b13c 新增刻晴, 提纳里, 柯莱, 北斗的草系反应 2022-08-30 22:14:06 +08:00
68baa744b2 🍱 增加新角色参考面板 2022-08-30 21:39:42 +08:00
0aaf186615 🐛 猎人之径的效果错误问题 2022-08-30 10:31:46 +08:00
22febab01c 添加插件帮助 (#311) 2022-08-30 09:00:02 +08:00
47929f764c 🐛 fix req.json() error 2022-08-30 08:40:27 +08:00
72ebb26b12 🐛 fix miHoYo BBS api error 2022-08-29 21:38:48 +08:00
8333d61eae use req.json() instead of json.loads 2022-08-29 19:31:38 +08:00
9efaf75c0a recover changes
This reverts commit 9bd0085982.
2022-08-29 14:55:36 +08:00
9bd0085982 🐛 httpx.ReadTimeout 2022-08-29 14:08:59 +08:00
21150c7514 🎨 refactor by sourcery 2022-08-29 01:21:58 +08:00
2a337ce8e9 🚨 fix codestyle warnings 2022-08-29 00:46:56 +08:00
51866deb99 🚨 fix F841 and E722 warnings 2022-08-29 00:07:17 +08:00
331198fa5a 🚨 fix import warning 2022-08-28 23:57:14 +08:00
017fbf6683 remove requests 2022-08-28 23:08:16 +08:00
6c68ba3657 🐛 fix import error 2022-08-28 22:30:42 +08:00
a05fdfb9b8 🚨 fix F405 warning(#308) 2022-08-28 21:51:30 +08:00
4a211dd32f 🐛 修复久岐忍大招的伤害显示问题, 增加草系反应 2022-08-28 18:31:26 +08:00
96628af1c8 🎨 适用于多种情形的convert_img 2022-08-28 17:26:13 +08:00
d53f920bb3 🎨 抽卡记录现在计算平均时会排除掉首个出金 2022-08-28 14:14:55 +08:00
4c84a729d0 🐛 直接添加Stoken无法添加成功的问题 2022-08-28 13:30:09 +08:00
3548477289 Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-08-28 13:04:26 +08:00
b836263039 🐛 修复一处提示文案错误 2022-08-28 00:28:01 +08:00
7ddf72ea17 🐛 修复刷新抽卡记录 2022-08-27 19:00:46 +08:00
e960a19060 增加部分草系反应的计算 2022-08-27 18:53:11 +08:00
44934543ea 🐛 修复地图黑色区域,重新生成地图即可 2022-08-27 02:42:26 +08:00
f9fc8539eb 🚨 meta中的错误格式 2022-08-26 22:54:12 +08:00
4002f8597a 🐛 解决合并冲突 2022-08-26 22:48:22 +08:00
fa490d744a 适配PicMenu插件(nonebot2版本需求上升至2.0.0b4 2022-08-26 22:41:45 +08:00
a6dfb9489c 新增刷新抽卡记录,抽卡记录 2022-08-26 22:33:59 +08:00
5f074c645c edit
edit

edit

edittttt
2022-08-26 22:33:50 +08:00
3b1e03a8ac 增加3.0新角色的伤害计算 2022-08-26 22:33:49 +08:00
10fb6c23f8 更换minigg.icu为资源自动下载站 2022-08-26 22:33:49 +08:00
6071903db4 edit 2022-08-26 01:13:46 +08:00
97eafe0c4f feat: 适配PicMenu插件(nonebot2版本需求上升至2.0.0b4 2022-08-25 02:36:39 +08:00
4f7ee1b8fc 🐛 尝试解决文件冲突问题 2022-08-24 23:33:31 +08:00
790c6c363a 🍱 增加部分3.0图片资源 2022-08-24 22:46:06 +08:00
a680fd40c0 🍱 新增部分3.0 map原始数据* 2022-08-24 01:06:18 +08:00
e7d6b90950 🎨 新增, 修复EnkaAPI 2022-08-22 05:15:30 +00:00
8dc4bf8b38 🚸 增加部分错误提示 2022-08-22 01:07:27 +08:00
372a03baaa 🐛 修复大部分武器常驻效果错误的问题 2022-08-21 20:36:22 +08:00
9a22c2f0a0 🐛 武器常驻被动不参与计算 2022-08-20 23:51:29 +08:00
e7f934342e 🐛 倍率和常量互相转换 2022-08-20 19:16:51 +08:00
b385d78655 🐛 修复伤害计算中可能的逻辑错误 2022-08-20 12:21:07 +08:00
d853a3bffe 🐛 查询神里绫华进行附魔 2022-08-19 22:42:44 +08:00
2331e54519 🐛 修复查询甘雨查询夜兰中特殊箭矢的重击计算 2022-08-19 22:31:01 +08:00
84111f11b9 🐛 修复添加CK字段中如果存在cookie_token会忽略login_ticket的bug 2022-08-19 21:15:51 +08:00
2120c5387c 🔨 update requirements.txt 2022-08-19 19:36:55 +08:00
0c1d0c8dd3 🐛 查询雷神梦想一刀伤害错误 2022-08-19 19:03:58 +08:00
ca81bbf131 Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-08-19 19:02:07 +08:00
418399abf2 🔨 add requirements.txt 2022-08-19 19:01:51 +08:00
1fca111eef 🐛 技能等级也应缩小一位 2022-08-19 13:19:26 +08:00
02627e9743 🐛 转换等级时应缩小一位 2022-08-19 09:18:15 +08:00
e0f19e144f 🐛 修复salt的问题导致的其他任务无法完成 2022-08-19 01:41:54 +08:00
2f88ca9f96 👽️ 修复因为米游社API变动导致的开始获取米游币失败 2022-08-19 01:35:14 +08:00
55296b8ca7 查询风系角色时,将会计算扩散伤害 2022-08-19 01:01:28 +08:00
a1ad2a2ab5 🐛 雷神满愿力的计算方式,角色偏移等 2022-08-18 20:37:30 +08:00
d7cd6b0955 查询胡桃等增加蒸发反应计算,查询雷神增加满愿力计算 2022-08-18 01:52:37 +08:00
5e706cc04d 新增血量表, 抗性表 2022-08-16 22:04:42 +08:00
18ae78863c 🐛 启动会下载多余的圣遗物图片 2022-08-16 22:00:51 +08:00
ab8cfe3290 优化 (#296)
* 优化资源下载

* 优化资源点查询
优化地图名称提示
优化查询语句匹配
2022-08-16 20:42:14 +08:00
91c4224b01 👽️ 再次增大重试间隔, 尝试修复全部重签 2022-08-16 01:00:32 +08:00
f60716f3fe 新增版本规划(版本规划2.8), 伤害乘区 2022-08-16 00:14:29 +08:00
8e4c3aa3e7 数据库会在凌晨0点进行备份,备份留存最近五天 2022-08-16 00:12:25 +08:00
0aa94deaae 查询面板现支持自定义图片;支持查询旅行者 2022-08-15 23:20:46 +08:00
2eafb87fe5 每日现在可以显示体力回满还需要多久 2022-08-15 21:56:18 +08:00
3205499096 🐛 genshinuid_map支持python3.8 2022-08-15 20:36:45 +08:00
9e13b43d8d 🐛 全部重签 2022-08-15 15:37:08 +08:00
efbfea22e1 👽 尝试通过重试修复签到全部重签 2022-08-15 13:32:21 +08:00
3f55b031b2 🐛 修复毕业度统计,修复查询魈伤害计算 2022-08-15 00:10:24 +08:00
df7245d9c7 🐛 ST to St 2022-08-14 23:02:55 +08:00
3191714394 🐛 genshinuid_enka伤害计算附魔问题 2022-08-14 22:51:08 +08:00
1bf87585cf Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-08-14 22:48:04 +08:00
e6be183259 🐛 修复mode引发的问题 2022-08-14 22:46:57 +08:00
ba1da7f328 🐛 兼容不使用米游币的数据库问题 2022-08-14 20:36:36 +08:00
32fd9c66e1 🐛 每日信息的存在性校验 2022-08-14 19:21:50 +08:00
e42fe4d745 🐛 handle_exc 2022-08-14 18:50:10 +08:00
88395108dc 🐛 List 2022-08-14 18:44:28 +08:00
6b01b98f1f 🐛 生成地图的链接错误 2022-08-14 18:42:34 +08:00
300f907985 🐛 生成地图的错误提示 2022-08-14 18:34:17 +08:00
9c196a7341 🐛 type hints 2022-08-14 18:22:57 +08:00
8dc2494bed 🐛 extend_existing 2022-08-14 16:55:23 +08:00
0da4c273e7 🐛 extend_existing 2022-08-14 16:37:10 +08:00
c371f64449 添加依赖sklearn和shapely 2022-08-14 16:08:38 +08:00
0f4f02c687 🎉 GenshinUID 3.0 beta 2022-08-14 14:34:32 +08:00
9bf5c26b22 Merge pull request #291 from lgc2333/patch-1
修复文本错误
2022-08-09 14:11:02 +08:00
641d4a5ad9 修复文本错误 2022-08-09 14:01:36 +08:00
816feb22e6 🐛 Enka UA 2022-08-08 12:08:50 +08:00
64c145c68d 👽️ 修复原神签到 2022-08-05 08:42:49 +08:00
a8b2ad5fbc ��️ 修复开始获取米游币 2022-08-05 00:40:34 +08:00
8a57b016cd 🐛 修复伤害计算 2022-07-20 21:08:57 +08:00
e76eff24fe 更新:查询收集的max_data 2022-07-20 16:59:46 +08:00
1105ff1ac7 Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-07-16 19:23:16 +08:00
cf6ea4bc6a 优化:伤害计算 2022-07-16 19:23:00 +08:00
a70061b158 修复:EnkaAPI 2022-07-16 14:11:44 +08:00
5fa9ef4b84 更新:用什么, 给谁用 2022-07-15 00:25:44 +08:00
bc02c23cee 修复:活动列表 2022-07-15 00:13:35 +08:00
beb9a566a3 修改:version 2022-07-14 22:24:56 +08:00
3480677c52 修复:鹿野院平藏资源问题 2022-07-14 08:54:54 +08:00
ea86619795 更新:2.8相关资源 2022-07-13 23:23:58 +08:00
e2d75b3752 修改:avatarCardOffsetMap.json 2022-07-11 10:37:48 +08:00
6269277b96 修复:毕业度统计 2022-07-11 10:35:23 +08:00
31941d31b2 优化:伤害计算区域对齐 2022-07-10 01:57:25 +08:00
55bfd25f64 新增:毕业度统计 2022-07-09 20:55:11 +08:00
6706fd1312 修改:UI贴图 2022-07-09 20:53:21 +08:00
35d0596f17 新增:查询展柜角色的伤害计算 2022-07-09 20:47:27 +08:00
5ab0693f7b 修复:命座影响天赋的map引入 2022-07-03 00:23:30 +08:00
4277a40450 修复:遗漏的图片 2022-07-03 00:09:17 +08:00
cfa3f91379 修复:班尼特的元素充能效率计算为有效词条 2022-07-02 23:16:18 +08:00
4b1ad04662 修改:查询角色面板的背景上色方式 2022-07-02 22:26:53 +08:00
c854194fcc 修复:因为地脉活动导致的活动列表错误问题 2022-07-02 17:12:40 +08:00
451e871d1b 新增:每日自动米游币任务结束后向SUPERUSER发送报告 2022-07-02 01:13:40 +08:00
4bc1533063 新增:校验全部Stoken 2022-07-02 00:51:08 +08:00
62649caa31 优化:命座显示天赋+3 2022-07-01 22:37:11 +08:00
0c9b291ee9 修复:特殊情况下查询深渊角色显示头像异常 2022-07-01 13:07:21 +08:00
29df398de6 新增:谁能用可以模糊查询圣遗物匹配信息 2022-06-30 23:47:28 +08:00
0694443bca 修复:推荐表内的换行问题 2022-06-30 23:43:57 +08:00
75b078810a 修复:能用啥的三星武器丢失问题 2022-06-30 23:18:31 +08:00
7aa07579db 修复:查询展柜角色中旅行者无法正常显示 2022-06-30 23:09:30 +08:00
a50a6167e2 优化:查询失败返回语句优化 2022-06-27 00:05:32 +08:00
382068070e 优化:全新的活动列表界面 2022-06-26 21:35:55 +08:00
782307e4bb chore(deps): Bump nonebot2 from 2.0.0b2 to 2.0.0b4 2022-06-25 20:16:58 +08:00
94f3c3a7cb 修复:天赋的tag问题 2022-06-25 11:45:54 +08:00
d441c25c51 优化:天赋的数字类型判断 2022-06-25 01:27:40 +08:00
675e8e4f65 更新:gs帮助 2022-06-25 01:00:32 +08:00
3a02a8f496 删除:无用的测试代码 2022-06-25 00:50:24 +08:00
387f618c59 修复:查询词云 2022-06-25 00:47:09 +08:00
0bacc8c674 修复:天赋中存在数字错乱的问题 2022-06-25 00:18:07 +08:00
ee74e054d8 修复:查询展柜角色 元素充能效率 -> 充能效率 2022-06-24 19:36:43 +08:00
83681c8e15 修复:久岐忍的探索派遣状态问题 2022-06-24 00:33:38 +08:00
27572a3af4 更新:gs帮助内容 2022-06-24 00:31:23 +08:00
2ad9b6242e 修复:烟绯的毕业度计算问题 2022-06-23 19:35:28 +08:00
01de70c1af 新增:完善dmgMap.json的制作方式 2022-06-22 21:54:58 +08:00
00c5280ec6 新增:久岐忍有效词条的计算 2022-06-22 01:11:58 +08:00
cca8c34bba 优化:圣遗物评分将变为有效词条计数 2022-06-22 01:00:23 +08:00
bf259f805d 修改:强制刷新返回字段,减少风控 2022-06-21 13:02:54 +08:00
ebdbec5fcd 修复:抗性区的计算问题 2022-06-21 12:53:49 +08:00
d96c7b0e06 修复:伤害计算错误 2022-06-19 21:05:02 +08:00
a6130424d5 优化:查询展柜角色优化整体UI 2022-06-19 15:50:51 +08:00
b8ce462636 修复:部分文案重叠 2022-06-19 14:48:45 +08:00
7c1508fd23 修复:完善全角色查询展柜角色毕业度的计算 2022-06-18 20:29:33 +08:00
5581b85332 查询展柜角色中完善角色立绘偏移 2022-06-17 00:28:47 +08:00
5dc5110ee3 '新增:引入avatarOffsetMap.json' 2022-06-14 00:24:17 +08:00
fe31910a09 修改:开始获取米游币的回复描述 2022-06-13 19:44:50 +08:00
04a486a256 '修复:计算毕业度时,绫人,绫华,迪奥娜,霄宫,九条的异常问题' 2022-06-13 00:05:26 +08:00
d1ca4da918 '新增:查询xx页面新增角色毕业度' 2022-06-12 22:56:55 +08:00
75d6083419 修复:强制刷新造成的安柏数据错误;新增:equipSets字段 2022-06-11 17:29:39 +08:00
c2e87458a1 更新:参考面板水新增夜兰 2022-06-07 19:22:42 +08:00
202e86ee77 Update README.md 2022-06-07 12:57:31 +08:00
27eef2e13e 优化:武器命令(防止两个Bot互刷) 2022-06-06 13:06:44 +08:00
9c9bae7cc6 新增:数据库将保留五天备份 2022-06-05 22:24:21 +08:00
6c41b75e42 修复:查询收集小数问题 & 更新数据 2022-06-05 20:26:14 +08:00
bfbf3140ac 优化:查询攻略图片前校验URL是否存在 2022-06-05 18:26:36 +08:00
a2305773a9 支持通过uid方式查询其他玩家的展柜信息 2022-06-05 16:42:49 +08:00
ec250a3cbb 修复若水和落霞的武器map 2022-06-05 16:30:04 +08:00
f7d62129cb 完善查询展柜信息的错误提示 2022-06-05 13:58:06 +08:00
d24a3109f0 更新xx能用啥命令的推荐表 & 备注 2022-06-04 21:57:43 +08:00
e2b52b0987 完善Map制作方式 2022-06-04 14:45:04 +08:00
8fb71cb0be fix 2022-06-03 19:19:17 +08:00
a974b7b1b7 去除UI线框,换用默认大图 2022-06-03 19:08:25 +08:00
a475fd8811 修复:命座数据问题 2022-06-02 11:37:07 +08:00
74e471380a 添加:夜兰 2022-06-02 09:50:10 +08:00
6f9d251fd1 添加:夜兰 2022-06-02 09:49:29 +08:00
8e87716175 Merge pull request #249 from lgc2333/nonebot2-beta1
fix
2022-06-02 01:41:51 +08:00
daffc0e39f Merge remote-tracking branch 'origin/nonebot2-beta1' into nonebot2-beta1 2022-06-02 01:40:05 +08:00
ac2346def6 ~~fuck~~ fix 2022-06-02 01:39:50 +08:00
e7c9071a2a Merge branch 'KimigaiiWuyi:nonebot2-beta1' into nonebot2-beta1 2022-06-02 01:19:02 +08:00
07ac6fc212 requirements 2022-06-02 01:18:00 +08:00
6bb12944b8 fix 2022-06-02 01:17:02 +08:00
46d94cebe3 Merge pull request #248 from lgc2333/nonebot2-beta1
fix & format
2022-06-02 00:12:12 +08:00
94838c0a0a fix 2022-06-01 23:52:37 +08:00
4e2f6d8ee0 fix 2022-06-01 23:40:26 +08:00
47bc645b68 format 2022-06-01 23:34:57 +08:00
60d1c59f2c matcher.**finsih** 2022-06-01 23:33:48 +08:00
96d4ba3211 Merge branch 'nonebot2-beta1' of https://github.com/lgc2333/GenshinUID into nonebot2-beta1 2022-06-01 23:16:33 +08:00
26fbb1b38c 补充文件 2022-06-01 23:13:59 +08:00
d201c33278 Merge branch 'nonebot2-beta1' of https://github.com/lgc2333/GenshinUID into nonebot2-beta1 2022-06-01 22:57:46 +08:00
97fee4c824 新增:查询展柜角色 2022-06-01 22:14:57 +08:00
12bd7ba921 chore(deps): pin nonebot2 to 2.0.0b2 2022-06-01 15:04:19 +08:00
29a98bab97 fix: import ActionFailed from nonebot.adapters.onebot.v11 2022-06-01 15:03:09 +08:00
e4c4e66e58 新增:查询收集 2022-06-01 00:02:24 +08:00
f74d04f53a Merge branch 'KimigaiiWuyi:nonebot2-beta1' into nonebot2-beta1 2022-05-31 01:52:42 +08:00
ead44f46f6 新增:gs关闭米游币推送 2022-05-28 21:41:34 +08:00
894da9c2a6 整理依赖 (#240) 2022-05-25 21:36:23 +08:00
ae25d5c6b1 修复:新api接口(-record) 2022-05-18 19:44:01 +08:00
4f605e8654 Merge #229 into nonebot2-beta1 (by @lgc2333) 2022-05-11 08:37:38 +08:00
ca8ecb677b Merge branch 'nonebot2-beta1' of https://github.com/lgc2333/GenshinUID into nonebot2-beta1 2022-05-11 02:25:26 +08:00
89db8d35ca reformat README 2022-05-11 02:21:54 +08:00
65c3496e37 Merge #222 into nonebot2-beta1 (by @lgc2333)
gen char_adv_list.json from xlsx that weapon_adv and char_adv use
2022-05-02 22:32:43 +08:00
eccfe329a3 rename 2022-05-02 22:30:20 +08:00
86e22f7374 modify regex match param 2022-05-02 22:27:12 +08:00
62fccbedef move 2022-05-02 22:23:48 +08:00
4ef0be08e8 fix 2022-05-02 22:19:11 +08:00
1fd5b6c564 gen char_adv_list.json from xlsx that weapon_adv and char_adv use 2022-05-02 22:11:58 +08:00
1a88b93efd 同步查询 -> uid & mys 2022-05-01 23:00:54 +08:00
1b3706a46b 颜色转换 2022-05-01 22:58:59 +08:00
ecad374c03 Merge #220 into nonebot2-beta1
fix: use depends
2022-04-30 21:57:42 +08:00
fa4ca0be51 fix: use depends(fix #207, fix #219) 2022-04-30 21:49:51 +08:00
240a01fb18 Merge pull request #216 from yen-qian/nonebot2-beta1
修复安装时httpx版本冲突问题
2022-04-28 17:49:19 +08:00
yen
7103e7d8ca Update requirements.txt 2022-04-28 17:46:24 +08:00
728ea9abc2 yapf 2022-04-27 23:44:56 +08:00
2f90e0ee3b 新增:参考面板(eg.参考面板火) 2022-04-27 23:11:12 +08:00
42d28f2fed 当ck数量大于9条时,[校验全部Cookies]命令输出精简 2022-04-26 22:12:05 +08:00
1893edf8a7 fix: send error message(fix #207, fix #208) 2022-04-25 21:29:15 +08:00
92b9e1737f fix:send error message 2022-04-20 09:23:57 +08:00
d4c5d515c8 fix #205 2022-04-18 22:27:07 +08:00
1198c71160 fix #205 2022-04-18 22:23:16 +08:00
6d4704da56 test: wiki 2022-04-18 17:08:56 +08:00
4234cc2d2e fix:audio error&style: use finish 2022-04-18 16:53:54 +08:00
c07e864aa0 Merge #204 into nonebot2-beta1 (by @shirokurakana)
减少重复代码
2022-04-17 22:52:37 +08:00
de97644fd0 fix: finish can't raise FinishedException 2022-04-17 22:50:02 +08:00
3b862cb54f 减少重复代码 2022-04-17 22:24:54 +08:00
192682ea2a Merge pull request #202 from shirokurakana/nonebot2-beta1
重做消息响应器&参数获取
2022-04-17 11:03:48 +08:00
3593c2d163 防止一律响应开头满足条件的消息 2022-04-16 15:03:11 +08:00
9ae88a11d5 使用更好的方式实现指令参数的获取 2022-04-16 15:01:41 +08:00
7efc532f3e 合并 #199
Revert 197 nonebot2-beta1
2022-04-15 20:23:13 +08:00
c2e62045fd feat: use one scheduler 2022-04-15 15:14:59 +08:00
5de79b499f Revert "小修复" 2022-04-15 14:56:00 +08:00
dffdbcc4c6 Merge pull request #197 from shirokurakana/nonebot2-beta1
小修复
2022-04-14 18:13:40 +08:00
90e5b9d3e7 scheduler只需要require一次 2022-04-14 16:20:54 +08:00
6b6d9ee479 修复未配置优先级时引发的问题 2022-04-14 16:19:11 +08:00
3ae3611d36 fix: the error message send error by record type 2022-04-11 20:51:14 +08:00
7c75145a50 fix: the error message send error by record type 2022-04-11 20:47:13 +08:00
ad88bc5011 fix: key-value error 2022-04-08 17:34:50 +08:00
18a16db8db 合并 #192 (closed #191)
补上一个空格 & 修复给谁用
2022-04-08 17:28:36 +08:00
bb385e3f9f fix: key and value error 2022-04-08 17:27:21 +08:00
d600d4ff9a fix 2022-04-08 17:23:06 +08:00
71620ce015 fix text 2022-04-08 17:16:09 +08:00
19d9781107 modify 2022-04-08 17:13:09 +08:00
f42788c008 修复给谁用 2022-04-08 16:04:28 +08:00
6c95472351 补上一个空格 2022-04-08 15:58:58 +08:00
1a92f35fcc 适应米游社数据 2022-04-08 00:17:11 +08:00
f800581446 修复:未探索地下造成的查询错误 & gs帮助错别字 2022-04-06 23:14:17 +08:00
b63c5b9ba3 修复:米游社新命名造成的查询错误 & 优化:更深的颜色遮罩 2022-04-06 21:06:52 +08:00
22204b115d 修改错误 2022-04-06 00:21:12 +08:00
35b884a2d3 新增:gs帮助 & xx推荐|攻略 2022-04-06 00:15:07 +08:00
7440ef2805 Merge pull request #179 from lgc2333/nonebot2-beta1
规范引号
2022-04-03 22:36:27 +08:00
c54facc919 规范引号 2022-04-03 21:40:47 +08:00
4390193184 向下兼容Python 3.8 2022-04-02 23:51:38 +08:00
23ec1dce8d 合并lgc2333/nonebot2-beta1(#176)
修复全部重签
2022-04-02 21:00:27 +08:00
d3853a6eb4 修复全部重签 2022-04-02 20:47:49 +08:00
dfe71c99f0 Merge pull request #166 from chenchenriver/nonebot2-beta1
Update get_mihoyo_bbs_data.py
2022-04-01 14:22:10 +08:00
6ef6005112 Update get_mihoyo_bbs_data.py 2022-04-01 14:18:00 +08:00
e39094f54a 更新:推荐表格信息 2022-04-01 00:33:17 +08:00
435e4a2d9a fix 2022-04-01 00:23:48 +08:00
746cb89bf3 新增:当前状态 & 当前信息添加参量质变仪信息 2022-04-01 00:22:04 +08:00
83a8c53449 Merge branch 'nonebot2-beta1' of github.com:KimigaiiWuyi/GenshinUID into nonebot2-beta1 2022-04-01 00:21:55 +08:00
0907e10271 新增:当前状态 & 当前信息添加参量质变仪信息 2022-04-01 00:21:24 +08:00
e07183beae 修复活动列表未进行正则提取的错误以及当前信息图片全部恢复的重合问题(fix #130) 2022-03-31 14:34:48 +08:00
8daec54d15 更新依赖 2022-03-31 13:44:23 +08:00
0fc4d899b6 修复:八角色UI重叠问题 2022-03-31 09:40:16 +08:00
53b9026d0a 新增:层岩巨渊的适配 2022-03-31 01:20:21 +08:00
0ec2685d37 同步:beta1 & main分支 2022-03-31 00:06:46 +08:00
656fbb4749 Merge pull request #156 from lgc2333/nonebot2-beta1
修复词云
2022-03-30 09:27:03 +08:00
2a4da7699d 删除测试代码 2022-03-29 23:49:06 +08:00
b5ff2b3613 尝试修复词云 2022-03-29 23:37:29 +08:00
c121c95a4c Merge branch 'KimigaiiWuyi:nonebot2-beta1' into nonebot2-beta1 2022-03-29 23:24:36 +08:00
cbcaa41640 修复:御神签偶发性输出空字符串 & 其他 2022-03-29 23:18:08 +08:00
2e37a0ff9a 修复:御神签偶发性输出空字符串 & 其他 2022-03-29 23:17:08 +08:00
4389d23bcc Merge remote-tracking branch 'origin/nonebot2-beta1' into nonebot2-beta1 2022-03-29 23:15:34 +08:00
a2b2f2f3d3 尝试修复词云 2022-03-29 23:14:44 +08:00
0ddad55580 尝试修复词云 2022-03-29 22:49:17 +08:00
1cc1d4e765 Merge pull request #153 from lgc2333/nonebot2-beta1
修复满树脂仍然显示剩余时间的问题 & Fix
2022-03-29 15:00:44 +08:00
72bd7be66e fix 2022-03-29 04:03:37 +08:00
b1ff73ef0d 修复满树脂仍然显示剩余时间的问题 2022-03-29 03:59:07 +08:00
72d9fa0828 尝试修复 2022-03-29 03:50:31 +08:00
82e33b153b 建议无疑早日使用jb 2022-03-29 03:42:19 +08:00
06c67c85f8 建议无疑早日使用jb 2022-03-29 03:38:41 +08:00
fdeafed874 修改:开启/关闭为gs开启/gs关闭 2022-03-29 00:32:47 +08:00
e3fb49c791 re: 2022-03-29 00:31:18 +08:00
71db7d8f0f 同步 2022-03-28 00:10:03 +08:00
223f519ee1 新增:开启自动米游币 & 当前信息(当前状态图片版)& 全部重获取;优化:新的查询样式 2022-03-26 18:58:26 +08:00
8d6b3c5c77 Merge pull request #143 from lgc2333/nonebot2-beta1
fixes
2022-03-18 09:35:42 +08:00
a60b64181c fix 2022-03-18 09:29:59 +08:00
5260abac14 fix 2022-03-18 09:04:50 +08:00
7838150f35 fix tip 2022-03-18 08:39:10 +08:00
cd0c38700c Merge pull request #142 from lgc2333/nonebot2-beta1
兼容
2022-03-17 23:29:03 +08:00
70c23164c5 修复失误 2022-03-17 22:15:56 +08:00
f3c5cb80a1 兼容 2022-03-17 21:33:19 +08:00
f28d7ae0a0 nb a16分支同步(pr #141 by @Igc2333)
与nb a16分支同步
2022-03-17 20:29:37 +08:00
017c561008 与nb a16分支同步 2022-03-17 20:18:08 +08:00
35dcd29d74 Update the setting of priority(Fix #137) 2022-03-13 20:19:00 +08:00
3c4c7a83c8 修复:全部重签 2022-03-11 10:13:55 +08:00
5f20fbd347 新增:开始获取米游币 & 添加Stokne;修复:活动列表 2022-03-10 23:58:39 +08:00
d0f334c9aa 米游币自动获取前提:Stoken获取指南 2022-03-09 00:24:09 +08:00
0333757b92 fix 2022-03-09 00:18:22 +08:00
89fe126579 准备:当前状态图片版 & 自动米游币获取 2022-03-09 00:01:16 +08:00
b9991ac7d2 修改结构 2022-03-06 23:36:19 +08:00
ef0913e6dd 补充:新增文件 2022-03-06 00:04:57 +08:00
564f3b2783 新增:xxx用什么|能用啥|怎么养&xxx能给谁|给谁用|要给谁|谁能用 2022-03-05 23:57:24 +08:00
d49c3297ed 优化:统一深渊生成图 & 统一返回 (添加大量冗余代码 2022-03-05 22:01:45 +08:00
3df56c1249 ReadMe 2022-02-22 23:58:50 +08:00
e43392253c 更新接口 2022-02-22 23:52:41 +08:00
2d1339f8c1 优化:天赋wiki的显示(合并转发) 2022-02-22 23:49:57 +08:00
9597a6d1ba Merge pull request #118 from shirokurakana/nonebot2-beta1
nonebot2-beta1 分支的一些修复工作
2022-02-16 19:20:40 +08:00
8f3bc1f9ee 修复发不出消息 2022-02-16 17:17:54 +08:00
b8279048c1 使用MessageSegment代替CQ码 2022-02-16 16:44:53 +08:00
d2a8c048a1 修复:深渊查询问题 2022-02-16 16:16:28 +08:00
b785adf105 修复:活动列表时间 2022-02-15 00:14:01 +08:00
414e384f1c Merge pull request #115 from MingxuanGame/nonebot2-beta1
Nonebot2 beta1
2022-02-12 19:04:04 +08:00
0ca23df74f 格式化提交(事件响应部分) 2022-02-12 18:49:19 +08:00
e6b629d9e1 格式化提交(数据部分) 2022-02-12 18:48:52 +08:00
c37e008261 Merge pull request #109 from MingxuanGame/nonebot2
nonebot2 2.0.0b1更新
2022-02-08 13:50:29 +08:00
f3eb0b0aa1 填无疑复制错的坑 2022-02-07 23:49:49 +08:00
563933f78f nonebot2 2.0.0b1更新 2022-02-07 23:40:35 +08:00
89a8883f07 requirements 2022-02-06 23:26:47 +08:00
adc0a86ce0 修复 2022-02-04 19:26:28 +08:00
0fb37e41ab 优化:报错 2022-02-04 19:23:18 +08:00
ce110cba99 Merge branch 'nonebot2' of github.com:KimigaiiWuyi/GenshinUID into nonebot2 2022-02-03 20:08:05 +08:00
bf51b8a2a6 Readme 2022-02-03 20:07:48 +08:00
a3e9a00568 Merge pull request #104 from lgc2333/patch-1
fix
2022-02-03 17:57:29 +08:00
5adf659ac5 fix 2022-02-03 17:49:28 +08:00
7500be4078 优化:定时任务log&活动列表图片发送 2022-02-03 00:05:39 +08:00
c933d5d9ef requirements.txt 2022-02-02 13:00:06 +08:00
157ad92eda 优化:校验全部Cookies现在会私聊已失效CK的QQ账号提醒ck过期 2022-02-02 10:59:00 +08:00
82d2fbcda1 README! 2022-02-01 19:07:04 +08:00
2afaa437b7 优化:八角色UI信息内容 2022-02-01 18:39:07 +08:00
b7c896e18a 补充代码 2022-02-01 00:16:20 +08:00
16dc1fe974 优化:自动签到报告&新增:开启简洁签到报告 2022-02-01 00:05:57 +08:00
586481062c 删除:无效代码 2022-01-27 00:02:27 +08:00
fd0e60796e 修复:同步新的WikiAPI接口;优化:错误提示. 2022-01-26 23:47:11 +08:00
e91564ac08 添加依赖 2022-01-25 14:15:51 +08:00
e9042d42fd 临时修改 2022-01-25 14:12:42 +08:00
b92ff01ddb Update getMes.py 2022-01-25 13:40:59 +08:00
5d736dbda1 修改获取Cookies 2022-01-25 13:39:36 +08:00
a5006183ae 优化:每日签到 2022-01-24 00:39:28 +08:00
3b919f54fb 同步语音重试:PR #81 2022-01-23 01:54:40 +08:00
9c3e260d1a 移除:数据库优化命令 2022-01-23 01:13:55 +08:00
0054148196 新增:食物/圣遗物命令,支持模糊查询;修复&优化:签到/添加Ck指令 2022-01-23 00:52:45 +08:00
0be58c1f43 Create LICENSE 2022-01-11 19:39:37 +08:00
02d4809d2c Merge pull request #86 from lgc2333/nonebot2
edit
2022-01-08 20:48:50 +08:00
cea56eb3ea edit 2022-01-08 20:47:39 +08:00
e53a1d2299 Merge pull request #85 from lgc2333/nonebot2
加入洞天宝钱大概积攒速度和全恢复时间
2022-01-08 20:47:24 +08:00
2f0f8ccbd6 add features 2022-01-08 20:13:45 +08:00
c120bf65a3 Merge pull request #82 from lgc2333/nonebot2
修正文本
2022-01-07 12:30:54 +08:00
dd0720a32c edit 2022-01-07 11:51:54 +08:00
ed8d169134 edit 2022-01-07 11:49:17 +08:00
e59d4ed1e5 edit 2022-01-07 11:09:50 +08:00
7955f52ba9 Update getImg.py 2022-01-07 10:46:02 +08:00
fc9e35ed05 edit 2022-01-07 10:40:50 +08:00
c7cc86ca2d Merge pull request #81 from lgc2333/nonebot2
fix
2022-01-06 10:28:12 +08:00
199c2f3a78 fix record 2022-01-06 04:17:44 +08:00
5c9960b5af Merge pull request #80 from lgc2333/nonebot2
fix
2022-01-06 03:01:08 +08:00
81d5e52528 fix 2022-01-06 02:47:21 +08:00
8f70742528 fix 2022-01-06 02:41:27 +08:00
d00b7bcbd9 Merge pull request #78 from lgc2333/nonebot2
optimize
2022-01-06 02:31:57 +08:00
c47d091c40 fix 2022-01-06 02:24:45 +08:00
7ff2609f2d optimize 2022-01-06 02:17:37 +08:00
1e2f605776 readme 2022-01-06 00:35:21 +08:00
05f53275f6 新增:语音命令;修复:渊下宫带来的查询错误问题;新增:当前状态命令查询洞天宝钱数量 2022-01-06 00:17:11 +08:00
5728d4ecad Merge pull request #77 from lgc2333/nonebot2
修复活动列表发图失败
2022-01-06 00:11:03 +08:00
91758947ac update event list when load plugin 2022-01-05 21:45:17 +08:00
a6e06dce57 fix send pic 2022-01-05 21:03:37 +08:00
bc49efa759 修复:角色命令可能出错的问题 2022-01-01 15:42:23 +08:00
ad88859ca6 新增:开启&关闭自动签到/推送服务,可由超级管理员操作 2021-12-30 23:03:35 +08:00
3dce0539c6 新增:命座查询的模糊匹配;优化:代码结构 2021-12-30 22:29:29 +08:00
fcc038abc1 新增:武器已支持查询某个固定等级属性 & 支持模糊查询;修复:角色查等级时元素精通数值不正确显示。 2021-12-30 00:38:21 +08:00
247709b06a 修复:角色命令现已支持模糊查询(修复之前直接输出Json) 2021-12-30 00:02:12 +08:00
a4fbaccee8 修复&优化:数据获取方式 & 推送树脂可能造成的Bug;新增:原魔、天赋指令。 2021-12-29 23:51:45 +08:00
0fce1cbe92 Merge branch 'nonebot2' of github.com:KimigaiiWuyi/GenshinUID into nonebot2 2021-12-26 22:18:38 +08:00
823e998114 修复:活动列表可能导致的bug 2021-12-26 22:18:06 +08:00
66e76c71ba Merge pull request #64 from lgc2333/nonebot2
fix
2021-12-25 16:15:42 +08:00
926b48a890 fix 2021-12-25 16:06:02 +08:00
22b7a53e58 Merge pull request #62 from wudifeixue/patch-2
修复米哈游更改api造成的插件损坏
2021-12-24 14:06:11 +08:00
f09547ba04 重新再次修复 2021-12-23 23:04:26 -07:00
6f54c0c99a 补充意外删除的debug信息 2021-12-23 22:53:03 -07:00
5bc89880fe 修复米哈游更改api造成的插件损坏
顺便更新了更好的后台错误反馈信息方便debug
2021-12-23 22:48:20 -07:00
aab3d148c4 修复:Readme 2021-12-20 01:04:50 +08:00
c23e577c45 新增:若干功能 2021-12-20 00:33:38 +08:00
69250a8700 Merge pull request #56 from ZhouYingSASA/nonebot2
Nonebot2:完善错误处理
2021-12-16 01:39:02 +08:00
5a9e63c54a fix: 完善错误处理 2021-12-16 01:27:56 +08:00
336c3f2aaf fix: 完善错误处理 2021-12-16 01:25:54 +08:00
9ba855fa17 修复:原神wiki相关功能 2021-12-11 00:28:47 +08:00
bd47c1dce8 fix 2021-12-10 00:51:34 +08:00
d04dd57aef !!fix!! 2021-12-04 19:17:37 +08:00
18a054ae66 !!fix!! 2021-12-04 19:13:08 +08:00
1b6dc2a194 !!fix!! 2021-12-04 19:03:19 +08:00
421291929d Merge pull request #35 from lgc2333/nonebot2
fix&feature
2021-11-26 10:09:32 +08:00
ecf9419186 fix 2021-11-26 04:30:46 +08:00
b5362fe575 feature 2021-11-26 04:03:23 +08:00
ac223d02b3 edit 2021-11-26 03:27:08 +08:00
babac2d270 fix 2021-11-26 02:51:42 +08:00
7ea57c069e fix 2021-11-25 22:09:07 +08:00
68a0fc6073 Merge branch 'nonebot2' of github.com:KimigaiiWuyi/GenshinUID into nonebot2 2021-11-25 22:03:27 +08:00
cedd47a453 fix 2021-11-25 22:02:56 +08:00
b72594f20e Merge pull request #31 from lgc2333/nonebot2
fixxxxxxxxxxxxxxxxxxx custom background of wordcloud
2021-11-21 03:08:25 +08:00
61cf1ce79e fixxxxxxxxxxxxxxxxxxx 2021-11-21 02:30:15 +08:00
997688fa67 Merge pull request #30 from lgc2333/nonebot2
fix wordcloud & add requirements
2021-11-21 02:16:04 +08:00
6aa62f2451 fix 2021-11-21 02:04:05 +08:00
96a2bf6a46 Update requirements.txt 2021-11-21 02:03:23 +08:00
53a58d458c Merge pull request #29 from lgc2333/nonebot2
紧急修复bug
2021-11-21 01:30:18 +08:00
4452e35f6a 紧急修复bug 2021-11-21 01:21:08 +08:00
608c505d7a 紧急修复bug 2021-11-21 01:13:40 +08:00
da36b1ae0d readme 2021-11-21 00:29:16 +08:00
d72bdf87ad fix and feat 2021-11-21 00:18:23 +08:00
dd19fc6bd2 Merge pull request #26 from lgc2333/nonebot2
尝试解决签到限制问题 添加通过.env.*配置文件设置消息处理优先级
2021-11-20 22:25:40 +08:00
a51d03c6ee 尝试解决签到限制问题 添加通过.env.*配置文件设置消息处理优先级 2021-11-20 03:55:21 +08:00
d73a6d57e4 尝试解决签到限制问题 添加通过.env.*配置文件设置消息处理优先级 2021-11-20 03:15:28 +08:00
84b46699ba Merge pull request #24 from lgc2333/nonebot2
改回readme 在requirements.txt添加nonebot-plugin-apscheduler>=0.1.2
2021-11-19 12:18:10 +08:00
9bdb8dfc3f Update README.md 2021-11-19 12:15:08 +08:00
286a74d004 Update requirements.txt 2021-11-19 12:14:16 +08:00
3cd332d8f5 Merge pull request #23 from lgc2333/patch-1
edit
2021-11-19 00:29:37 +08:00
2a3db3784f edit 2021-11-19 00:19:21 +08:00
1cea32424d fix 2021-11-18 00:43:11 +08:00
207c82dfab 合并Hoshino提交,修复Bug 2021-11-16 21:45:46 +08:00
dff8992adc fix 2021-11-15 00:51:16 +08:00
8a7fdb1709 fix 2021-11-15 00:14:43 +08:00
94682d43fe readme 2021-11-14 23:59:05 +08:00
2e34937700 NoneBot2 support 2021-11-14 23:48:04 +08:00
74 changed files with 4959 additions and 2417 deletions

16
.dockerignore Normal file
View File

@ -0,0 +1,16 @@
# .git
.vscode
.env
.venv
env
venv
.pytest_cache
*.pyc
*.pyo
*.pyd
.Python
tests
GenshinUID.egg-info
build
__pycache__
.pytest_cache

42
.github/workflows/unittest.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: Unittest
on:
push:
branches:
- nonebot2-beta1
pull_request:
jobs:
test:
name: Test
strategy:
matrix:
version: ["3.8", "3.9", "3.10", "3.11"]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
env:
OS: ${{ matrix.os }}
PYTHON_VERSION: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v3
- name: Install poetry
run: pipx install poetry
shell: bash
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.version }}
architecture: "x64"
cache: "poetry"
- name: Install dependencies
run: poetry install --with test --without dev
shell: bash
- name: Run Pytest
run: |
cd tests
poetry run pytest

7
.gitignore vendored
View File

@ -210,7 +210,7 @@ celerybeat.pid
*.sage.py *.sage.py
# Environments # Environments
.env .env/
.venv .venv
env/ env/
venv/ venv/
@ -668,5 +668,6 @@ result.txt
### GenshinUID ### ### GenshinUID ###
GenshinUID/genshinuid_help/help.png GenshinUID/genshinuid_help/help.png
GenshinUID/genshinuid_map/map_data GenshinUID/genshinuid_map/map_data
.vscode/settings.json
.vscode/settings.json ### Debug ###
testnb2/

View File

@ -1,15 +1,12 @@
ci: ci:
autofix_commit_msg: ":rotating_light: auto fix by pre-commit-ci" autofix_commit_msg: ":rotating_light: auto fix by pre-commit-ci"
skip:
- "poetry-lock"
autofix_prs: true autofix_prs: true
autoupdate_branch: master autoupdate_branch: master
autoupdate_schedule: monthly autoupdate_schedule: monthly
autoupdate_commit_msg: ":arrow_up: auto update by pre-commit-ci" autoupdate_commit_msg: ":arrow_up: auto update by pre-commit-ci"
repos: repos:
- repo: https://github.com/hadialqattan/pycln
rev: v2.1.2
hooks:
- id: pycln
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort
rev: 5.11.5 rev: 5.11.5
hooks: hooks:
@ -25,17 +22,16 @@ repos:
hooks: hooks:
- id: flake8 - id: flake8
- repo: https://github.com/hadialqattan/pycln
rev: v2.1.2
hooks:
- id: pycln
- repo: https://github.com/python-poetry/poetry - repo: https://github.com/python-poetry/poetry
rev: 1.3.1 rev: 1.3.1
hooks: hooks:
- id: poetry-check - id: poetry-check
- id: poetry-lock
- id: poetry-export - id: poetry-export
args: args: ["-f", "requirements.txt", "--without-hashes", "-o", "requirements.txt"]
[
"-f",
"requirements.txt",
"--without-hashes",
"-o",
"requirements.txt",
]
verbose: true verbose: true

View File

@ -1,6 +1,6 @@
{ {
"python.languageServer": "Pylance", "python.languageServer": "Pylance",
"python.analysis.typeCheckingMode": "off", "python.analysis.typeCheckingMode": "basic",
"cSpell.words": [ "cSpell.words": [
"audioid", "audioid",
"enka", "enka",

43
Dockerfile Normal file
View File

@ -0,0 +1,43 @@
FROM python:3.9
# 1. 环境设置
# 使用镜像源
RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple
RUN apt-get update && apt-get install -y tzdata
ENV TZ Asia/Shanghai
# 2. 安装 GenshinUID
WORKDIR /plugin
COPY ./pyproject.toml ./LICENSE ./README.md /plugin/
COPY ./GenshinUID /plugin/GenshinUID/
RUN pip install --editable "."
COPY ./.git /plugin/.git
# 3. 生成 nb2 项目
WORKDIR /nb2
RUN pip install tomlkit "cookiecutter>=2.1.1"
COPY ./deploy/cookiecutter.yml ./deploy/update_pyproject.py /nb2/
# RUN cookiecutter --config-file ./cookiecutter.yml https://github.com/nonebot/nb-cli.git --directory="nb_cli/project" --no-input
# 使用镜像源
RUN cookiecutter --config-file ./cookiecutter.yml https://ghproxy.com/https://github.com/nonebot/nb-cli.git --directory="nb_cli/project" --no-input
RUN python update_pyproject.py
COPY ./deploy/.env.dev /nb2/nb2/
WORKDIR /nb2/nb2
EXPOSE 8080
CMD python bot.py

View File

@ -0,0 +1,25 @@
from pathlib import Path
from pkgutil import iter_modules
from nonebot.log import logger
from nonebot import require, load_all_plugins, get_plugin_by_module_name
from .config import config as _config
require('nonebot_plugin_apscheduler')
if get_plugin_by_module_name("GenshinUID"):
logger.info("推荐直接加载 GenshinUID 仓库文件夹")
load_all_plugins(
[
f"GenshinUID.{module.name}"
for module in iter_modules([str(Path(__file__).parent)])
if module.ispkg
and (
(name := module.name[11:]) == "meta"
or name not in _config.disabled_plugins
)
# module.name[:11] == genshinuid_
],
[],
)

View File

@ -1,6 +0,0 @@
import hoshino
from hoshino import Service
sv = Service('genshinuid', bundle='genshin', help_='发送"原神帮助"查看详情')
hoshino_bot = hoshino.get_bot()
logger = sv.logger

15
GenshinUID/config.py Normal file
View File

@ -0,0 +1,15 @@
from typing import Set
from nonebot import get_driver
from pydantic import Field, BaseModel
class Config(BaseModel):
disabled_plugins: Set[str] = Field(
default_factory=set, alias="genshinuid_disabled_plugins"
)
priority: int = Field(2, alias="genshinuid_priority")
config = Config.parse_obj(get_driver().config)
priority = config.priority

View File

@ -1,59 +1,84 @@
import re from typing import Any, Tuple, Union
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_regex
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import Depends, RegexGroup
from nonebot.adapters.onebot.v11 import (
MessageSegment,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger from ..genshinuid_meta import register_menu
from .draw_abyss_card import draw_abyss_img from .draw_abyss_card import draw_abyss_img
from ..utils.message.error_reply import UID_HINT from ..utils.message.error_reply import UID_HINT
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
from ..utils.message.get_image_and_at import ImageAndAt
from ..utils.mhy_api.convert_mysid_to_uid import convert_mysid from ..utils.mhy_api.convert_mysid_to_uid import convert_mysid
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
get_abyss_info = on_regex(
@sv.on_rex(
r'^(\[CQ:at,qq=[0-9]+\])?( )?' r'^(\[CQ:at,qq=[0-9]+\])?( )?'
r'(uid|查询|mys)?([0-9]+)?(上期)?(深渊|sy)' r'(uid|查询|mys)?([0-9]+)?(上期)?(深渊|sy)'
r'(9|10|11|12|九|十|十一|十二)?(层)?' r'(9|10|11|12|九|十|十一|十二)?(层)?'
r'(\[CQ:at,qq=[0-9]+\])?( )?$', r'(\[CQ:at,qq=[0-9]+\])?( )?$',
block=True,
) )
async def send_abyss_info(bot: HoshinoBot, ev: CQEvent):
args = ev['match'].groups()
@get_abyss_info.handle()
@handle_exception('查询深渊信息')
@register_menu(
'查询深渊信息',
'查询(@某人)(上期)深渊(xx层)',
'查询你的或者指定人的深渊战绩',
detail_des=(
'介绍:\n'
'可以用来查看你的或者指定人的深渊战绩,可以指定层数,默认为最高层数\n'
'可以在命令文本后带一张图以自定义背景图\n'
' \n' # 如果想要空行,请在换行符前面打个空格,不然会忽略换行符
'指令:\n'
'- <ft color=(238,120,0)>{查询</ft>'
'<ft color=(125,125,125)>(@某人)</ft>'
'<ft color=(238,120,0)>|uid</ft><ft color=(0,148,200)>xx</ft>'
'<ft color=(238,120,0)>|mys</ft><ft color=(0,148,200)>xx</ft>'
'<ft color=(238,120,0)>}</ft>'
'<ft color=(125,125,125)>(上期)</ft>'
'<ft color=(238,120,0)>深渊</ft>'
'<ft color=(125,125,125)>(xx层)</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>查询深渊</ft>\n'
'- <ft color=(238,120,0)>uid123456789上期深渊</ft>\n'
'- <ft color=(238,120,0)>查询</ft><ft color=(0,123,67)>@无疑Wuyi</ft> '
'<ft color=(238,120,0)>上期深渊12层</ft>'
),
)
async def send_abyss_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Tuple[Any, ...] = RegexGroup(),
custom: ImageAndAt = Depends(),
):
logger.info('开始执行[查询深渊信息]') logger.info('开始执行[查询深渊信息]')
logger.info('[查询深渊信息]参数: {}'.format(args)) logger.info(f'[查询深渊信息]参数: {args}')
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) at = custom.get_first_at()
qid = at or event.user_id
if at: if args[2] == 'mys':
qid = int(at.group(1))
else:
if ev.sender:
qid = int(ev.sender['user_id'])
else:
return
# 判断uid
if args[2] != 'mys':
if args[3] is None:
uid = await select_db(qid, mode='uid')
uid = str(uid)
elif len(args[3]) != 9:
return
else:
uid = args[3]
else:
uid = await convert_mysid(args[3]) uid = await convert_mysid(args[3])
elif args[3] is None:
logger.info('[查询深渊信息]uid: {}'.format(uid)) uid = await select_db(qid, mode='uid')
uid = str(uid)
if '未找到绑定的UID' in uid: elif len(args[3]) != 9:
await bot.send(ev, UID_HINT) return
# 判断深渊期数
if args[4] is None:
schedule_type = '1'
else: else:
schedule_type = '2' uid = args[3]
logger.info('[查询深渊信息]深渊期数: {}'.format(schedule_type)) logger.info(f'[查询深渊信息]uid: {uid}')
if '未找到绑定的UID' in uid:
await matcher.finish(UID_HINT)
schedule_type = '1' if args[4] is None else '2'
logger.info(f'[查询深渊信息]深渊期数: {schedule_type}')
if args[6] in ['', '', '十一', '十二']: if args[6] in ['', '', '十一', '十二']:
floor = ( floor = (
args[6] args[6]
@ -62,17 +87,16 @@ async def send_abyss_info(bot: HoshinoBot, ev: CQEvent):
.replace('十二', '12') .replace('十二', '12')
.replace('', '10') .replace('', '10')
) )
else: else:
floor = args[6] floor = args[6]
if floor is not None: if floor is not None:
floor = int(floor) floor = int(floor)
logger.info('[查询深渊信息]深渊层数: {}'.format(floor)) logger.info(f'[查询深渊信息]深渊层数: {floor}')
im = await draw_abyss_img(uid, floor, schedule_type) im = await draw_abyss_img(uid, floor, schedule_type)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')

View File

@ -1,36 +1,34 @@
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import CommandArg
from nonebot.adapters.onebot.v11 import Message
from ..base import sv, logger from ..config import priority
from .get_achi_desc import get_achi, get_daily_achi from .get_achi_desc import get_achi, get_daily_achi
from ..utils.exception.handle_exception import handle_exception
get_task_info = on_command('查委托', aliases={'委托'}, priority=priority)
get_achi_info = on_command('查成就', aliases={'成就'}, priority=priority)
@sv.on_prefix('查委托') @get_task_info.handle()
async def send_task_info(bot: HoshinoBot, ev: CQEvent): @handle_exception('查委托')
if ev.message: async def send_task_info(matcher: Matcher, args: Message = CommandArg()):
message = ev.message.extract_plain_text().replace(' ', '') if not args:
else:
return return
name = str(args[0])
if message == '':
return
name = str(message)
logger.info(f'[查委托] 参数:{name}') logger.info(f'[查委托] 参数:{name}')
im = await get_daily_achi(name) im = await get_daily_achi(name)
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('查成就') @get_achi_info.handle()
async def send_achi_info(bot: HoshinoBot, ev: CQEvent): @handle_exception('查成就')
if ev.message: async def send_achi_info(matcher: Matcher, args: Message = CommandArg()):
message = ev.message.extract_plain_text().replace(' ', '') if not args:
else:
return return
name = str(args[0])
if message == '':
return
name = str(message)
logger.info(f'[查成就] 参数:{name}') logger.info(f'[查成就] 参数:{name}')
im = await get_achi(name) im = await get_achi(name)
await bot.send(ev, im) await matcher.finish(im)

View File

@ -1,19 +1,72 @@
from hoshino.typing import CQEvent, HoshinoBot from typing import Any, Tuple
from ..base import sv from nonebot import on_regex
from nonebot.matcher import Matcher
from nonebot.params import RegexGroup
from ..config import priority
from .get_adv import char_adv, weapon_adv from .get_adv import char_adv, weapon_adv
from ..genshinuid_meta import register_menu
from ..utils.alias.alias_to_char_name import alias_to_char_name from ..utils.alias.alias_to_char_name import alias_to_char_name
from ..utils.exception.handle_exception import handle_exception
get_char_adv = on_regex('([\u4e00-\u9fa5]+)(用什么|能用啥|怎么养)', priority=priority)
get_weapon_adv = on_regex(
'([\u4e00-\u9fa5]+)(能给谁|给谁用|要给谁|谁能用)', priority=priority
)
@sv.on_rex(r'([\u4e00-\u9fa5]+)(用什么|能用啥|怎么养)') @get_char_adv.handle()
async def send_char_adv(bot: HoshinoBot, ev: CQEvent): @handle_exception('建议')
name = await alias_to_char_name(str(ev['match'].group(1))) @register_menu(
'角色配置推荐',
'xx用什么',
'查询角色武器/圣遗物推荐配置',
detail_des=(
'介绍:\n'
'可以查询某角色的武器/圣遗物推荐配置\n'
'支持部分角色别名\n'
' \n'
'指令:\n'
'- <ft color=(0,148,200)>[角色名]</ft>'
'<ft color=(238,120,0)>{用什么|能用啥|怎么养}</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>钟离用什么</ft>\n'
'- <ft color=(238,120,0)>公子怎么养</ft>'
),
)
async def send_char_adv(
matcher: Matcher, args: Tuple[Any, ...] = RegexGroup()
):
name = await alias_to_char_name(str(args[0]))
im = await char_adv(name) im = await char_adv(name)
await bot.send(ev, im) await matcher.finish(im)
@sv.on_rex(r'([\u4e00-\u9fa5]+)(能给谁|给谁用|要给谁|谁能用)') @get_weapon_adv.handle()
async def send_weapon_adv(bot: HoshinoBot, ev: CQEvent): @handle_exception('建议')
name = await alias_to_char_name(str(ev['match'].group(1))) @register_menu(
'装备适用角色',
'xx能给谁',
'查询某武器/圣遗物能给谁用',
detail_des=(
'介绍:\n'
'可以通过武器/圣遗物名反查适用的角色\n'
'支持部分别名\n'
' \n'
'指令:\n'
'- <ft color=(0,148,200)>[武器名]</ft>'
'<ft color=(238,120,0)>{能给谁|给谁用|要给谁|谁能用}</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>四风原典能给谁</ft>\n'
'- <ft color=(238,120,0)>千岩给谁用</ft>'
),
)
async def send_weapon_adv(
matcher: Matcher, args: Tuple[Any, ...] = RegexGroup()
):
name = await alias_to_char_name(str(args[0]))
im = await weapon_adv(name) im = await weapon_adv(name)
await bot.send(ev, im) await matcher.finish(im)

View File

@ -1,133 +1,142 @@
import random import random
import asyncio import asyncio
from nonebot import get_bot from nonebot.log import logger
from hoshino import Service, priv from nonebot.matcher import Matcher
from nonebot.params import CommandArg
from ..base import logger from nonebot import get_bot, on_command
from .util import black_ids from nonebot.permission import SUPERUSER
from .main import ann, consume_remind from nonebot_plugin_apscheduler import scheduler
from ..utils.message.error_reply import UID_HINT from nonebot.adapters.onebot.v11 import (
from ..utils.db_operation.db_operation import select_db Message,
from ..genshinuid_config.default_config import string_config MessageEvent,
from ..utils.draw_image_tools.send_image_tool import convert_img MessageSegment,
from .ann_card import sub_ann, unsub_ann, ann_list_card, ann_detail_card GroupMessageEvent,
)
sv_help = '''
原神公告 from .util import black_ids
原神公告#ID from ..config import priority
'''.strip() from .main import ann, consume_remind
from ..utils.nonebot2.rule import FullCommand
sv = Service( from ..utils.message.error_reply import UID_HINT
name='原神公告', # 功能名 from ..utils.db_operation.db_operation import select_db
use_priv=priv.NORMAL, # 使用权限 from ..genshinuid_config.default_config import string_config
manage_priv=priv.ADMIN, # 管理权限 from ..utils.exception.handle_exception import handle_exception
visible=True, # 可见性 from .ann_card import sub_ann, unsub_ann, ann_list_card, ann_detail_card
enable_on_default=True, # 默认启用
# bundle = '娱乐', #分组归类 update_ann_scheduler = scheduler
help_=sv_help, # 帮助说明 get_ann_info = on_command('原神公告', priority=priority)
) reg_ann = on_command(
'订阅原神公告', priority=priority, rule=FullCommand(), permission=SUPERUSER
prefix = '原神' )
unreg_ann = on_command(
'取消订阅原神公告',
@sv.on_prefix((f'{prefix}公告#', f'{prefix}公告')) aliases={'取消原神公告', '退订原神公告'},
async def ann_(bot, ev): priority=priority,
ann_id = ev.message.extract_plain_text().strip() rule=FullCommand(),
if not ann_id: permission=SUPERUSER,
img = await ann_list_card() )
img = await convert_img(img) consume_ann = on_command('清除原神公告红点', priority=priority, rule=FullCommand())
await bot.send(ev, img, at_sender=True)
return
@get_ann_info.handle()
if not ann_id.isdigit(): @handle_exception('原神公告', '获取/发送原神公告失败')
raise Exception("公告ID不正确") async def send_ann_pic(
try: matcher: Matcher,
img = await ann_detail_card(int(ann_id)) args: Message = CommandArg(),
img = await convert_img(img) ):
await bot.send(ev, img, at_sender=True) ann_id = str(args).replace(' ', '').replace('#', '')
except Exception as e:
await bot.finish(ev, str(e)) if not ann_id:
img = await ann_list_card()
await matcher.finish(MessageSegment.image(img))
@sv.on_fullmatch(f'订阅{prefix}公告')
async def sub_ann_(bot, ev): if not ann_id.isdigit():
if not priv.check_priv(ev, priv.ADMIN): raise Exception("公告ID不正确")
raise Exception("你没有权限开启原神公告推送")
try: img = await ann_detail_card(int(ann_id))
await bot.send(ev, sub_ann(ev.group_id)) await matcher.finish(MessageSegment.image(img))
except Exception as e:
await bot.finish(ev, str(e))
@reg_ann.handle()
@handle_exception('设置原神公告', '设置原神公告失败')
@sv.on_fullmatch((f'取消订阅{prefix}公告', f'取消{prefix}公告', f'退订{prefix}公告')) async def send_reg_ann(
async def unsub_ann_(bot, ev): event: GroupMessageEvent,
if not priv.check_priv(ev, priv.ADMIN): matcher: Matcher,
raise Exception("你没有权限取消原神公告推送") ):
try: await matcher.finish(sub_ann(event.group_id))
await bot.send(ev, unsub_ann(ev.group_id))
except Exception as e:
await bot.finish(ev, str(e)) @unreg_ann.handle()
@handle_exception('取消原神公告', '取消设置原神公告失败')
async def send_unreg_ann(
@sv.on_fullmatch(f'取消{prefix}公告红点') event: GroupMessageEvent,
async def consume_remind_(bot, ev): matcher: Matcher,
try: ):
qid = int(ev.sender['user_id']) await matcher.finish(unsub_ann(event.group_id))
uid = await select_db(qid, mode='uid')
uid = str(uid)
if '未找到绑定的UID' in uid: @consume_ann.handle()
await bot.send(ev, UID_HINT) @handle_exception('取消原神公告红点', '取消红点失败')
return async def send_consume_ann(
await bot.send(ev, await consume_remind(uid), at_sender=True) event: MessageEvent,
except Exception as e: matcher: Matcher,
await bot.finish(ev, str(e)) ):
qid = event.user_id
uid = await select_db(qid, mode='uid')
@sv.scheduled_job('cron', minute=10) uid = str(uid)
async def check_ann(): if '未找到绑定的UID' in uid:
await check_ann_state() await matcher.finish(UID_HINT)
await matcher.finish(await consume_remind(uid))
async def check_ann_state():
logger.info('[原神公告] 定时任务: 原神公告查询..') @update_ann_scheduler.scheduled_job('cron', minute=10)
ids = string_config.get_config('Ann_Ids') async def check_ann():
sub_list = string_config.get_config('Ann_Groups') await check_ann_state()
if not sub_list:
logger.info('没有群订阅, 取消获取数据') async def check_ann_state():
return logger.info('[原神公告] 定时任务: 原神公告查询..')
ids = string_config.get_config('Ann_Ids')
if not ids: sub_list = string_config.get_config('Ann_Groups')
ids = await ann().get_ann_ids()
if not ids: if not sub_list:
raise Exception('获取原神公告ID列表错误,请检查接口') logger.info('没有群订阅, 取消获取数据')
string_config.set_config('Ann_Ids', ids) return
logger.info('初始成功, 将在下个轮询中更新.')
return if not ids:
ids = await ann().get_ann_ids()
new_ids = await ann().get_ann_ids() if not ids:
new_ann = set(ids) ^ set(new_ids) raise Exception('获取原神公告ID列表错误,请检查接口')
string_config.set_config('Ann_Ids', ids)
if not new_ann: logger.info('初始成功, 将在下个轮询中更新.')
logger.info('[原神公告] 没有最新公告') return
return
new_ids = await ann().get_ann_ids()
for ann_id in new_ann: new_ann = set(ids) ^ set(new_ids)
if ann_id in black_ids:
continue if not new_ann:
try: logger.info('[原神公告] 没有最新公告')
img = await ann_detail_card(ann_id) return
img = await convert_img(img)
bot = get_bot() for ann_id in new_ann:
for group in sub_list: if ann_id in black_ids:
try: continue
await bot.send_group_msg(group_id=group, message=img) try:
await asyncio.sleep(random.uniform(1, 3)) img = await ann_detail_card(ann_id) # 防止抛出异常报错
except Exception as e: bot = get_bot()
logger.exception(e) for group in sub_list:
except Exception as e: try:
logger.exception(str(e)) await bot.call_api(
api='send_group_msg',
logger.info('[原神公告] 推送完毕, 更新数据库') group_id=group,
string_config.set_config('Ann_Ids', new_ids) message=MessageSegment.image(img),
)
await asyncio.sleep(random.uniform(1, 3))
except Exception as e:
logger.exception(e)
except Exception as e:
logger.exception(str(e))
logger.info('[原神公告] 推送完毕, 更新数据库')
string_config.set_config('Ann_Ids', new_ids)

View File

@ -1,65 +1,65 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
import inspect import inspect
import datetime import datetime
import functools import functools
from typing import Dict, Optional, TypedDict from typing import Dict, Optional, TypedDict
import httpx import httpx
class _Dict(dict): class _Dict(dict):
__setattr__ = dict.__setitem__ # type: ignore __setattr__ = dict.__setitem__ # type: ignore
__getattr__ = dict.__getitem__ __getattr__ = dict.__getitem__
class _CacheData(TypedDict): class _CacheData(TypedDict):
time: Optional[datetime.datetime] time: Optional[datetime.datetime]
value: Optional[int] value: Optional[int]
def filter_list(plist, func): def filter_list(plist, func):
return list(filter(func, plist)) return list(filter(func, plist))
def cache(ttl=datetime.timedelta(hours=1), **kwargs): def cache(ttl=datetime.timedelta(hours=1), **kwargs):
def wrap(func): def wrap(func):
cache_data: Dict[str, _CacheData] = {} cache_data: Dict[str, _CacheData] = {}
@functools.wraps(func) @functools.wraps(func)
async def wrapped(*args, **kw): async def wrapped(*args, **kw):
nonlocal cache_data nonlocal cache_data
bound = inspect.signature(func).bind(*args, **kw) bound = inspect.signature(func).bind(*args, **kw)
bound.apply_defaults() bound.apply_defaults()
ins_key = '|'.join( ins_key = '|'.join(
['%s_%s' % (k, v) for k, v in bound.arguments.items()] ['%s_%s' % (k, v) for k, v in bound.arguments.items()]
) )
default_data: _CacheData = { default_data: _CacheData = {
'time': None, 'time': None,
'value': None, 'value': None,
} }
data = cache_data.get(ins_key, default_data) data = cache_data.get(ins_key, default_data)
now = datetime.datetime.now() now = datetime.datetime.now()
if not data['time'] or now - data['time'] > ttl: if not data['time'] or now - data['time'] > ttl:
try: try:
data['value'] = await func(*args, **kw) data['value'] = await func(*args, **kw)
data['time'] = now data['time'] = now
cache_data[ins_key] = data cache_data[ins_key] = data
except Exception as e: except Exception as e:
raise e raise e
return data['value'] return data['value']
return wrapped return wrapped
return wrap return wrap
@cache(ttl=datetime.timedelta(minutes=30), arg_key='url') @cache(ttl=datetime.timedelta(minutes=30), arg_key='url')
async def cache_request_json(url): async def cache_request_json(url):
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
res = await client.get(url, timeout=10) res = await client.get(url, timeout=10)
return res.json(object_hook=_Dict) return res.json(object_hook=_Dict)
black_ids = [762, 422, 423, 1263, 495, 1957, 2522, 2388, 2516, 2476] black_ids = [762, 422, 423, 1263, 495, 1957, 2522, 2388, 2516, 2476]

View File

@ -1,10 +1,23 @@
import random import random
import asyncio import asyncio
from typing import Union
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
from nonebot_plugin_apscheduler import scheduler
from nonebot.adapters.onebot.v11 import (
Bot,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger from ..config import priority
from .backup_data import data_backup from .backup_data import data_backup
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.exception.handle_exception import handle_exception
from ..utils.db_operation.db_cache_and_check import check_db, check_stoken_db from ..utils.db_operation.db_cache_and_check import check_db, check_stoken_db
from ..utils.db_operation.db_operation import delete_cookies, get_all_push_list from ..utils.db_operation.db_operation import delete_cookies, get_all_push_list
from ..utils.message.get_cqhttp_data import ( from ..utils.message.get_cqhttp_data import (
@ -12,35 +25,69 @@ from ..utils.message.get_cqhttp_data import (
get_group_member_list, get_group_member_list,
) )
backup = on_command('gs清除缓存', rule=FullCommand(), priority=priority)
check = on_command('校验全部Cookies', rule=FullCommand(), priority=priority)
check_stoken = on_command('校验全部Stoken', rule=FullCommand(), priority=priority)
remove_invalid_user = on_command(
'清除无效用户', rule=FullCommand(), priority=priority
)
@sv.scheduled_job('cron', hour=0) backup_scheduler = scheduler
@backup_scheduler.scheduled_job('cron', hour=0)
async def daily_refresh_charData(): async def daily_refresh_charData():
await data_backup() await data_backup()
@sv.on_fullmatch('gs清除缓存') @backup.handle()
@handle_exception('清除缓存', '清除缓存错误')
@register_menu(
'清除缓存',
'清除缓存',
'清除插件产生的缓存数据',
trigger_method='超级用户指令',
detail_des=(
'介绍:\n'
'备份一份插件数据库后清除插件产生的文件与数据库缓存\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>清除缓存</ft>'
),
)
async def send_backup_msg( async def send_backup_msg(
bot: HoshinoBot, bot: Bot,
ev: CQEvent, event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
): ):
if ev.sender: if not await SUPERUSER(bot, event):
qid = int(ev.sender['user_id'])
else:
return return
if qid not in bot.config.SUPERUSERS:
return
await data_backup() await data_backup()
await bot.send(ev, '操作成功完成!') await matcher.finish('操作成功完成!')
@sv.on_fullmatch('清除无效用户') @remove_invalid_user.handle()
async def send_remove_invalid_user_msg(bot: HoshinoBot, ev: CQEvent): @handle_exception('清除无效用户', '清除无效用户错误')
if ev.sender: @register_menu(
qid = int(ev.sender['user_id']) '清除无效用户',
else: '清除无效用户',
return '清除非好友或非推送群成员的数据',
if qid not in bot.config.SUPERUSERS: trigger_method='超级用户指令',
detail_des=(
'介绍:\n'
'从数据库中删除掉 开启了私聊推送但不是Bot好友的用户 '
'以及 开启了群聊推送但不在推送目标群的用户 的数据\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>清除无效用户</ft>'
),
)
async def send_remove_invalid_user_msg(
bot: Bot,
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
):
if not await SUPERUSER(bot, event):
return return
im_list = [] im_list = []
invalid_user = {} invalid_user = {}
@ -62,40 +109,78 @@ async def send_remove_invalid_user_msg(bot: HoshinoBot, ev: CQEvent):
for uid in invalid_uid_list: for uid in invalid_uid_list:
im_list.append(await delete_cookies(str(uid))) im_list.append(await delete_cookies(str(uid)))
logger.warning(f'无效UID已被删除: {uid}') logger.warning(f'无效UID已被删除: {uid}')
await bot.send(ev, f'已清理失效用户{len(im_list)}个!') await matcher.finish(f'已清理失效用户{len(im_list)}个!')
# 群聊内 校验Cookies 是否正常的功能,不正常自动删掉 # 群聊内 校验Cookies 是否正常的功能,不正常自动删掉
@sv.on_fullmatch('校验全部Cookies') @check.handle()
async def send_check_cookies(bot: HoshinoBot, ev: CQEvent): @handle_exception('Cookie校验', 'Cookie校验错误')
@register_menu(
'校验全部Cookies',
'校验全部Cookies',
'校验数据库内所有Cookies是否正常',
detail_des=(
'介绍:\n'
'校验数据库内所有Cookies是否正常不正常的会自动删除\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>校验全部Cookies</ft>\n'
'注意<ft color=(238,120,0)>Cookies</ft>的'
'<ft color=(238,120,0)>C</ft>为大写'
),
)
async def send_check_cookie(bot: Bot, matcher: Matcher):
raw_mes = await check_db() raw_mes = await check_db()
im = raw_mes[0] im = raw_mes[0]
await bot.send(ev, im) await matcher.send(im)
for i in raw_mes[1]: for i in raw_mes[1]:
await bot.send_private_msg( await bot.call_api(
user_id=i[0], api='send_private_msg',
message=( **{
'您绑定的Cookiesuid{})已失效,以下功能将会受到影响:\n' 'user_id': i[0],
'查看完整信息列表\n查看深渊配队\n自动签到/当前状态/每月统计\n' 'message': (
'请及时重新绑定Cookies并重新开关相应功能。' '绑定Cookiesuid{})已失效,以下功能将会受到影响:\n'
).format(i[1]), '查看完整信息列表\n查看深渊配队\n自动签到/当前状态/每月统计\n'
'请及时重新绑定Cookies并重新开关相应功能。'
).format(i[1]),
},
) )
await asyncio.sleep(3 + random.randint(1, 3)) await asyncio.sleep(3 + random.randint(1, 3))
await matcher.finish()
# 群聊内 校验Stoken 是否正常的功能,不正常自动删掉 # 群聊内 校验Stoken 是否正常的功能,不正常自动删掉
@sv.on_fullmatch('校验全部Stoken') @check_stoken.handle()
async def send_check_stoken(bot: HoshinoBot, ev: CQEvent): @handle_exception('Stoken校验', 'Stoken校验错误')
@register_menu(
'校验全部Stoken',
'校验全部Stoken',
'校验数据库内所有Stoken是否正常',
detail_des=(
'介绍:\n'
'校验数据库内所有Stoken是否正常不正常的会自动删除\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>校验全部Stoken</ft>\n'
'注意<ft color=(238,120,0)>Stoken</ft>的<ft color=(238,120,0)>S</ft>为大写'
),
)
async def send_check_stoken(bot: Bot, matcher: Matcher):
raw_mes = await check_stoken_db() raw_mes = await check_stoken_db()
im = raw_mes[0] im = raw_mes[0]
await bot.send(ev, im) await matcher.send(im)
for i in raw_mes[1]: for i in raw_mes[1]:
await bot.send_private_msg( await bot.call_api(
user_id=i[0], api='send_private_msg',
message=( **{
'您绑定的Stokenuid{})已失效,以下功能将会受到影响:\n' 'user_id': i[0],
'gs开启自动米游币开始获取米游币。\n' 'message': (
'重新添加后需要重新开启自动米游币。' '您绑定的Stokenuid{})已失效,以下功能将会受到影响:\n'
).format(i[1]), 'gs开启自动米游币开始获取米游币。\n'
'重新添加后需要重新开启自动米游币。'
).format(i[1]),
},
) )
await asyncio.sleep(3 + random.randint(1, 3)) await asyncio.sleep(3 + random.randint(1, 3))
await matcher.finish()

View File

@ -1,70 +1,112 @@
import re from typing import Union
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import Depends, CommandArg
from nonebot.adapters.onebot.v11 import (
Message,
MessageSegment,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger from ..genshinuid_meta import register_menu
from ..utils.data_convert.get_uid import get_uid from ..utils.data_convert.get_uid import get_uid
from ..utils.message.error_reply import UID_HINT from ..utils.message.error_reply import UID_HINT
from ..utils.message.error_reply import * # noqa: F403,F401 from ..utils.message.get_image_and_at import ImageAndAt
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
from .draw_collection_card import draw_explora_img, draw_collection_img from .draw_collection_card import draw_explora_img, draw_collection_img
get_collection_info = on_command('查询收集', aliases={'收集', 'sj'}, block=True)
get_explora_info = on_command('查询探索', aliases={'探索', 'ts'}, block=True)
@sv.on_prefix(('查询收集', '收集', 'sj'))
async def send_collection_info(bot: HoshinoBot, ev: CQEvent): @get_collection_info.handle()
raw_mes = ev.message.extract_plain_text().replace(' ', '') @handle_exception('查询收集信息')
@register_menu(
'查询收集信息',
'查询(@某人)收集',
'查询你的或者指定人的宝箱收集度',
detail_des=(
'介绍:\n'
'可以用来查看你的或者指定人的宝箱收集度\n'
'可以在命令文本后带一张图以自定义背景图\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>{查询</ft>'
'<ft color=(125,125,125)>(@某人)</ft>'
'<ft color=(238,120,0)>|uid</ft><ft color=(0,148,200)>xx</ft>'
'<ft color=(238,120,0)>|mys</ft><ft color=(0,148,200)>xx</ft>'
'<ft color=(238,120,0)>}</ft>'
'<ft color=(238,120,0)>{收集|宝箱|sj|bx}</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>查询收集</ft>\n'
'- <ft color=(238,120,0)>uid123456789宝箱</ft>\n'
'- <ft color=(238,120,0)>查询</ft><ft color=(0,123,67)>@无疑Wuyi'
'</ft> <ft color=(238,120,0)>bx</ft>'
),
)
async def send_collection_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Message = CommandArg(),
custom: ImageAndAt = Depends(),
):
logger.info('开始执行[查询收集信息]') logger.info('开始执行[查询收集信息]')
at = re.search(r'\[CQ:at,qq=(\d*)]', raw_mes) logger.info('[查询收集信息]参数: {}'.format(args))
raw_mes = args.extract_plain_text().strip()
at = custom.get_first_at()
if at: if at:
qid = int(at.group(1)) qid = at
else: else:
if ev.sender: qid = event.user_id
qid = int(ev.sender['user_id'])
else:
return
# 获取uid
uid = await get_uid(qid, raw_mes) uid = await get_uid(qid, raw_mes)
logger.info('[查询收集信息]uid: {}'.format(uid)) logger.info('[查询角色面板]uid: {}'.format(uid))
if '未找到绑定的UID' in uid: if '未找到绑定的UID' in uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
im = await draw_collection_img(qid, uid) im = await draw_collection_img(qid, uid)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
@sv.on_prefix(('查询探索', '探索', 'ts')) @get_explora_info.handle()
async def send_explora_info(bot: HoshinoBot, ev: CQEvent): @handle_exception('查询探索信息')
raw_mes = ev.message.extract_plain_text().replace(' ', '') async def send_explora_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Message = CommandArg(),
custom: ImageAndAt = Depends(),
):
logger.info('开始执行[查询探索信息]') logger.info('开始执行[查询探索信息]')
at = re.search(r'\[CQ:at,qq=(\d*)]', raw_mes) logger.info('[查询探索信息]参数: {}'.format(args))
raw_mes = args.extract_plain_text().strip()
at = custom.get_first_at()
if at: if at:
qid = int(at.group(1)) qid = at
else: else:
if ev.sender: qid = event.user_id
qid = int(ev.sender['user_id'])
else:
return
# 获取uid
uid = await get_uid(qid, raw_mes) uid = await get_uid(qid, raw_mes)
logger.info('[查询探索信息]uid: {}'.format(uid)) logger.info('[查询角色面板]uid: {}'.format(uid))
if '未找到绑定的UID' in uid: if '未找到绑定的UID' in uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
im = await draw_explora_img(qid, uid) im = await draw_explora_img(qid, uid)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')

View File

@ -1,98 +1,153 @@
import re from typing import Any, Tuple, Union
from hoshino.typing import CQEvent, HoshinoBot from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot import on_regex, on_command
from nonebot.permission import SUPERUSER
from nonebot.params import Depends, CommandArg, RegexGroup
from nonebot.adapters.onebot.v11 import (
Bot,
Message,
MessageSegment,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger from ..genshinuid_meta import register_menu
from .draw_config_card import draw_config_img from .draw_config_card import draw_config_img
from ..utils.message.error_reply import UID_HINT from ..utils.message.error_reply import UID_HINT
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
from ..utils.message.get_image_and_at import ImageAndAt
from .set_config import set_push_value, set_config_func from .set_config import set_push_value, set_config_func
from ..utils.message.error_reply import * # noqa: F403,F401 from ..utils.exception.handle_exception import handle_exception
from ..utils.draw_image_tools.send_image_tool import convert_img
open_and_close_switch = on_regex(
r'^(\[CQ:at,qq=[0-9]+\])?( )?'
r'(gs)(开启|关闭)(.*)'
r'(\[CQ:at,qq=[0-9]+\])?( )?$'
)
@sv.on_fullmatch('gs配置') push_config = on_regex(
async def send_config_card(bot: HoshinoBot, ev: CQEvent):
logger.info('开始执行[gs配置]')
im = await draw_config_img()
if isinstance(im, str):
await bot.send(ev, im)
elif isinstance(im, bytes):
im = await convert_img(im)
await bot.send(ev, im)
else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!')
@sv.on_rex(
r'^(\[CQ:at,qq=[0-9]+\])?( )?' r'^(\[CQ:at,qq=[0-9]+\])?( )?'
r'(gs)(设置)([\u4e00-\u9fffa-zA-Z]*)([0-9]*)' r'(gs)(设置)([\u4e00-\u9fffa-zA-Z]*)([0-9]*)'
r'(\[CQ:at,qq=[0-9]+\])?( )?$' r'(\[CQ:at,qq=[0-9]+\])?( )?$'
) )
async def send_config_msg(bot: HoshinoBot, ev: CQEvent):
args = ev['match'].groups() config_card = on_command('gs配置')
@config_card.handle()
@handle_exception('发送配置表')
@register_menu(
'发送配置表',
'gs配置',
'查看插件当前配置项开关情况',
detail_des=(
'介绍:\n'
'查看插件当前配置项开关情况\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>gs配置</ft>'
),
)
async def send_config_card(matcher: Matcher, args: Message = CommandArg()):
if args:
await matcher.finish()
logger.info('开始执行[gs配置]')
im = await draw_config_img()
if isinstance(im, str):
await matcher.finish(im)
elif isinstance(im, bytes):
await matcher.finish(MessageSegment.image(im))
else:
await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
@push_config.handle()
@handle_exception('设置推送服务')
@register_menu(
'设置推送阈值',
'gs设置xx(@某人)',
'设置自己或指定人的推送服务阈值',
detail_des=(
'介绍:\n'
'设置某人的推送服务阈值\n'
'超级用户可以设置他人的推送服务阈值\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>gs设置</ft>'
'<ft color=(0,148,200)>[服务名称][阈值]</ft>'
'<ft color=(125,125,125)>(@某人)</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>gs设置推送140</ft>'
),
)
async def send_config_msg(
bot: Bot,
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Tuple[Any, ...] = RegexGroup(),
custom: ImageAndAt = Depends(),
):
logger.info('开始执行[设置阈值信息]') logger.info('开始执行[设置阈值信息]')
logger.info('[设置阈值信息]参数: {}'.format(args)) logger.info('[设置阈值信息]参数: {}'.format(args))
qid = event.user_id
at = custom.get_first_at()
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) if at and await SUPERUSER(bot, event):
if at:
qid = int(at.group(1))
else:
if ev.sender:
qid = int(ev.sender['user_id'])
else:
return
if qid in bot.config.SUPERUSERS:
is_admin = True
else:
is_admin = False
if at and is_admin:
qid = at qid = at
elif at and at != qid: elif at and at != qid:
await bot.send(ev, '你没有权限操作别人的状态噢~', at_sender=True) await matcher.finish('你没有权限操作别人的状态噢~', at_sender=True)
logger.info('[设置阈值信息]qid: {}'.format(qid)) logger.info('[设置阈值信息]qid: {}'.format(qid))
try: try:
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
except TypeError: except TypeError:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
return
func = args[4].replace('阈值', '') func = args[4].replace('阈值', '')
if args[5]: if args[5]:
try: try:
value = int(args[5]) value = int(args[5])
except ValueError: except ValueError:
await bot.send(ev, '请输入数字哦~', at_sender=True) await matcher.finish('请输入数字哦~', at_sender=True)
return
else: else:
await bot.send(ev, '请输入正确的阈值数字!', at_sender=True) await matcher.finish('请输入正确的阈值数字!', at_sender=True)
return
logger.info('[设置阈值信息]func: {}, value: {}'.format(func, value)) logger.info('[设置阈值信息]func: {}, value: {}'.format(func, value))
im = await set_push_value(func, str(uid), value) im = await set_push_value(func, str(uid), value)
await bot.send(ev, im, at_sender=True) await matcher.finish(im, at_sender=True)
# 开启 自动签到 和 推送树脂提醒 功能 # 开启 自动签到 和 推送树脂提醒 功能
@sv.on_rex( @open_and_close_switch.handle()
r'^(\[CQ:at,qq=[0-9]+\])?( )?' @register_menu(
r'(gs)(开启|关闭)(.*)' '开关推送服务',
r'(\[CQ:at,qq=[0-9]+\])?( )?$' 'gs{开启|关闭}xx(@某人)',
'开关自己或指定人的推送服务状态',
detail_des=(
'介绍:\n'
'设置某人的推送服务开关状态\n'
'超级用户可以设置他人的推送服务状态\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>gs{开启|关闭}</ft>'
'<ft color=(0,148,200)>[服务名称]</ft>'
'<ft color=(125,125,125)>(@某人)</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>gs开启推送</ft>'
),
) )
async def open_switch_func(bot: HoshinoBot, ev: CQEvent): async def open_switch_func(
args = ev['match'].groups() bot: Bot,
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
if at: args: Tuple[Any, ...] = RegexGroup(),
qid = int(at.group(1)) at: ImageAndAt = Depends(),
else: ):
if ev.sender: qid = event.user_id
qid = int(ev.sender['user_id']) atqq = at.get_first_at() if at else None
else:
return
config_name = args[4] config_name = args[4]
@ -100,34 +155,31 @@ async def open_switch_func(bot: HoshinoBot, ev: CQEvent):
if args[3] == '开启': if args[3] == '开启':
query = 'OPEN' query = 'OPEN'
gid = str(ev.group_id) if ev.group_id else 'on' gid = (
event.get_session_id().split('_')[1]
if len(event.get_session_id().split('_')) == 3
else 'on'
)
else: else:
query = 'CLOSED' query = 'CLOSED'
gid = 'off' gid = 'off'
is_admin = await SUPERUSER(bot, event)
if atqq:
if is_admin:
qid = atqq
elif atqq != qid:
await matcher.finish('你没有权限操作别人的状态噢~', at_sender=True)
if qid in bot.config.SUPERUSERS: uid = await select_db(qid, mode='uid')
is_admin = True if uid is None or not isinstance(uid, str) or not uid.isdecimal():
else: await matcher.finish(UID_HINT)
is_admin = False
if at and is_admin:
qid = at
elif at and at != qid:
bot.send(ev, '你没有权限操作别人的状态噢~', at_sender=True)
return
try:
uid = await select_db(qid, mode='uid')
except TypeError:
await bot.send(ev, UID_HINT)
return
im = await set_config_func( im = await set_config_func(
config_name=config_name, config_name=config_name,
uid=uid, # type: ignore uid=uid,
qid=qid, # type: ignore qid=str(qid),
option=gid, option=gid,
query=query, query=query,
is_admin=is_admin, is_admin=is_admin,
) )
await bot.send(ev, im, at_sender=True) await matcher.finish(im, at_sender=True)

View File

@ -1,17 +1,15 @@
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
from ..base import sv
from .export_data import export_v3 from .export_data import export_v3
from ..utils.nonebot2.rule import FullCommand
export_v3_data = on_command('导出v3数据', permission=SUPERUSER, rule=FullCommand())
@sv.on_prefix(('导出v3数据')) @export_v3_data.handle()
async def send_export_msg(bot: HoshinoBot, ev: CQEvent): async def send_export_msg(matcher: Matcher):
if ev.sender: await matcher.send('开始导出数据..可能需要一定时间!')
qid = int(ev.sender['user_id'])
else:
return
if qid not in bot.config.SUPERUSERS:
return
await bot.send(ev, '开始导出数据..可能需要一定时间!')
await export_v3() await export_v3()
await bot.send(ev, '导出数据成功!') await matcher.send('导出数据成功!')

View File

@ -1,106 +1,196 @@
import re import re
import random import random
import asyncio import asyncio
from typing import Tuple from typing import Tuple, Union
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
from nonebot.params import Depends, CommandArg
from nonebot_plugin_apscheduler import scheduler
from nonebot.adapters.onebot.v11 import (
Bot,
Message,
MessageSegment,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger from ..config import priority
from .get_enka_img import draw_enka_img from .get_enka_img import draw_enka_img
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from .draw_char_rank import draw_cahrcard_list from .draw_char_rank import draw_cahrcard_list
from ..utils.message.error_reply import UID_HINT from ..utils.message.error_reply import UID_HINT
from ..utils.enka_api.get_enka_data import switch_api from ..utils.enka_api.get_enka_data import switch_api
from ..utils.enka_api.enka_to_card import enka_to_card from ..utils.enka_api.enka_to_card import enka_to_card
from ..utils.enka_api.enka_to_data import enka_to_data from ..utils.enka_api.enka_to_data import enka_to_data
from ..utils.message.get_image_and_at import ImageAndAt
from ..utils.download_resource.RESOURCE_PATH import TEMP_PATH from ..utils.download_resource.RESOURCE_PATH import TEMP_PATH
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
from ..utils.db_operation.db_operation import select_db, get_all_uid from ..utils.db_operation.db_operation import select_db, get_all_uid
refresh = on_command('强制刷新')
original_pic = on_command('原图', rule=FullCommand())
change_api = on_command('切换api')
get_charcard_list = on_command('毕业度统计')
get_char_info = on_command(
'查询',
priority=priority,
)
AUTO_REFRESH = False AUTO_REFRESH = False
refresh_scheduler = scheduler
@sv.on_fullmatch('切换api') @change_api.handle()
async def send_change_api_info(bot: HoshinoBot, ev: CQEvent): @handle_exception('切换api')
print(ev) @register_menu(
if ev.sender: '切换API',
qid = int(ev.sender['user_id']) '切换api',
else: '切换获取角色面板时使用的API',
return detail_des=(
'介绍:\n'
if qid not in bot.config.SUPERUSERS: '切换获取角色面板时使用的Enka Network API\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>切换api</ft>'
),
)
async def send_change_api_info(
bot: Bot,
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Message = CommandArg(),
):
if args or not await SUPERUSER(bot, event):
return return
im = await switch_api() im = await switch_api()
await bot.send(ev, im) await matcher.finish(im)
@sv.on_rex(r'^(\[CQ:reply,id=[0-9]+\])?( )?(\[CQ:at,qq=[0-9]+\])?( )?原图') @original_pic.handle()
async def send_original_pic(bot: HoshinoBot, ev: CQEvent): @handle_exception('原图')
for msg in ev.message: @register_menu(
if msg['type'] == 'reply': '查看面板原图',
msg_id = msg['data']['id'] '原图',
path = TEMP_PATH / f'{msg_id}.jpg' '查看角色面板中原随机图',
if path.exists(): trigger_method='回复+指令',
logger.info('[原图]访问图片: {}'.format(path)) detail_des=(
with open(path, 'rb') as f: '介绍:\n'
im = await convert_img(f.read()) '查看开启随机图功能时角色面板中角色位置的原图,需要回复要查看原图的面板图片消息\n'
await bot.send(ev, im) ' \n'
'指令:\n'
'- <ft color=(238,120,0)>原图</ft>'
@sv.on_rex( ),
r'^(\[CQ:at,qq=[0-9]+\])?( )?'
r'(uid|查询|mys)([0-9]+)?'
r'([\u4e00-\u9fa5]+)'
r'(\[CQ:at,qq=[0-9]+\])?( )?',
) )
async def send_char_info(bot: HoshinoBot, ev: CQEvent): async def send_original_pic(
args = ev['match'].groups() event: Union[GroupMessageEvent, PrivateMessageEvent],
if args[4] is None: matcher: Matcher,
return ):
# 获取角色名 if event.reply:
msg = ''.join(re.findall('[\u4e00-\u9fa5]', args[4])) msg_id = event.reply.message_id
logger.info('开始执行[查询角色面板]') path = TEMP_PATH / f'{msg_id}.jpg'
logger.info('[查询角色面板]参数: {}'.format(args)) if path.exists():
# 获取角色名 logger.info('[原图]访问图片: {}'.format(path))
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) with open(path, 'rb') as f:
image = re.search(r'\[CQ:image,file=(.*),url=(.*)]', str(ev.message)) await matcher.finish(MessageSegment.image(f.read()))
@get_char_info.handle()
@handle_exception('查询角色面板')
@register_menu(
'查询角色面板',
'查询(@某人)角色名',
'查询你的或者指定人的已缓存展柜角色的面板',
detail_des=(
'介绍:\n'
'可以用来查看你的或者指定人的已缓存展柜角色的面板\n'
'支持部分角色别名\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>{查询</ft>'
'<ft color=(125,125,125)>(@某人)</ft>'
'<ft color=(238,120,0)>|uid</ft><ft color=(0,148,200)>xx</ft>'
'<ft color=(238,120,0)>|mys</ft><ft color=(0,148,200)>xx</ft>'
'<ft color=(238,120,0)>}</ft>'
'<ft color=(0,148,200)>[角色名]</ft>\n'
'后面可以跟 '
'<ft color=(238,120,0)>换</ft>'
'<ft color=(125,125,125)>(精{一|二|三|四|五})</ft>'
'<ft color=(0,148,200)>[武器名]</ft> '
'来更换展示的武器\n'
'可以跟 '
'<ft color=(125,125,125)>(成长)</ft><ft color=(238,120,0)>曲线</ft> '
'来查询该角色成长曲线\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>查询宵宫</ft>\n'
'- <ft color=(238,120,0)>查询绫华换精五雾切</ft>\n'
'- <ft color=(238,120,0)>查询一斗成长曲线</ft>\n'
'- <ft color=(238,120,0)>查询</ft><ft color=(0,123,67)>@无疑Wuyi</ft>'
' <ft color=(238,120,0)>公子</ft>'
),
)
@register_menu(
'查询展柜角色',
'查询展柜角色',
'查询插件已缓存的展柜角色列表',
detail_des=(
'介绍:\n'
'查询插件当前已缓存的展柜角色列表\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>查询展柜角色</ft>'
),
)
async def send_char_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Message = CommandArg(),
custom: ImageAndAt = Depends(),
):
raw_mes = args.extract_plain_text().strip()
name = ''.join(re.findall('[\u4e00-\u9fa5]', raw_mes))
if not name:
return
logger.info('开始执行[查询角色面板]')
at = custom.get_first_at()
img = custom.get_first_image()
img = None
if image:
img = image.group(2)
if at: if at:
qid = int(at.group(1)) qid = at
else: else:
if ev.sender: qid = event.user_id
qid = int(ev.sender['user_id'])
else:
return
logger.info('[查询角色面板]QQ: {}'.format(qid)) logger.info('[查询角色面板]QQ: {}'.format(qid))
# 获取uid # 获取uid
if args[3] is None: uid = re.findall(r'\d+', raw_mes)
if uid:
uid = uid[0]
else:
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
uid = str(uid) uid = str(uid)
else:
uid = args[3]
logger.info('[查询角色面板]uid: {}'.format(uid)) logger.info('[查询角色面板]uid: {}'.format(uid))
if '未找到绑定的UID' in uid: if '未找到绑定的UID' in uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
im = await draw_enka_img(msg, uid, img) im = await draw_enka_img(raw_mes, uid, img)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, Tuple): elif isinstance(im, Tuple):
img = await convert_img(im[0]) req = await matcher.send(MessageSegment.image(im[0]))
req = await bot.send(ev, img)
msg_id = req['message_id'] msg_id = req['message_id']
if im[1]: if im[1]:
with open(TEMP_PATH / f'{msg_id}.jpg', 'wb') as f: with open(TEMP_PATH / f'{msg_id}.jpg', 'wb') as f:
f.write(im[1]) f.write(im[1])
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
async def refresh_char_data(): async def refresh_char_data():
@ -125,92 +215,115 @@ async def refresh_char_data():
return f'执行成功!共刷新{str(t)}个角色!' return f'执行成功!共刷新{str(t)}个角色!'
@sv.scheduled_job('cron', hour='4') @refresh_scheduler.scheduled_job('cron', hour='4')
async def daily_refresh_charData(): async def daily_refresh_charData():
global AUTO_REFRESH global AUTO_REFRESH
if AUTO_REFRESH: if AUTO_REFRESH:
await refresh_char_data() await refresh_char_data()
@sv.on_prefix('强制刷新') @refresh.handle()
async def send_card_info(bot: HoshinoBot, ev: CQEvent): @handle_exception('强制刷新')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '刷新展柜缓存',
else: '强制刷新',
return '强制刷新你的或者指定人缓存的角色展柜数据',
detail_des=(
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) '指令:'
'<ft color=(238,120,0)>强制刷新</ft>'
if at: '<ft color=(125,125,125)>(uid/全部数据)</ft>\n'
qid = int(at.group(1)) ' \n'
message = message.replace(str(at), '') '用于强制刷新你的或者指定人缓存的角色展柜数据\n'
else: '当刷新全部数据时需要机器人管理员权限\n'
if ev.sender: ' \n'
qid = int(ev.sender['user_id']) '示例:\n'
else: '<ft color=(238,120,0)>强制刷新</ft>\n'
return '<ft color=(238,120,0)>强制刷新123456789</ft>\n'
'<ft color=(238,120,0)>强制刷新全部数据</ft>'
),
)
async def send_card_info(
bot: Bot,
matcher: Matcher,
event: Union[GroupMessageEvent, PrivateMessageEvent],
args: Message = CommandArg(),
custom: ImageAndAt = Depends(),
):
message = args.extract_plain_text().strip().replace(' ', '')
uid = re.findall(r'\d+', message) # str uid = re.findall(r'\d+', message) # str
m = ''.join(re.findall('[\u4e00-\u9fa5]', message)) m = ''.join(re.findall('[\u4e00-\u9fa5]', message))
qid = event.user_id
at = custom.get_first_at()
if at:
qid = at
if len(uid) >= 1: if len(uid) >= 1:
uid = uid[0] uid = uid[0]
else: else:
if m == '全部数据': if m == '全部数据':
if qid in bot.config.SUPERUSERS: if await SUPERUSER(bot, event):
await bot.send(ev, '开始刷新全部数据,这可能需要相当长的一段时间!!') await matcher.send('开始刷新全部数据,这可能需要相当长的一段时间!!')
im = await refresh_char_data() im = await refresh_char_data()
await bot.send(ev, str(im)) await matcher.finish(str(im))
return
else: else:
return return
else: else:
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
uid = str(uid) uid = str(uid)
if '未找到绑定的UID' in uid: if not uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
return
im = await enka_to_card(uid) im = await enka_to_card(uid)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
@sv.on_prefix('毕业度统计') @get_charcard_list.handle()
async def send_charcard_list(bot: HoshinoBot, ev: CQEvent): @handle_exception('毕业度统计')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '毕业度统计',
else: '毕业度统计',
return '查看你或指定人已缓存的展柜角色毕业度',
detail_des=(
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) '指令:'
'<ft color=(238,120,0)>毕业度统计</ft>'
'<ft color=(125,125,125)>(@某人)</ft>\n'
' \n'
'可以查看你或指定人已缓存的所有展柜角色毕业度\n'
' \n'
'示例:\n'
'<ft color=(238,120,0)>毕业度统计</ft>\n'
'<ft color=(238,120,0)>毕业度统计</ft><ft color=(0,148,200)>@无疑Wuyi</ft>'
),
)
async def send_charcard_list(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Message = CommandArg(),
custom: ImageAndAt = Depends(),
):
raw_mes = args.extract_plain_text().strip()
qid = event.user_id
at = custom.get_first_at()
if at: if at:
qid = int(at.group(1)) qid = at
message = message.replace(str(at), '')
else:
if ev.sender:
qid = int(ev.sender['user_id'])
else:
return
# 获取uid # 获取uid
uid = re.findall(r'\d+', message) uid = re.findall(r'\d+', raw_mes)
if uid: if uid:
uid = uid[0] uid = uid[0]
else: else:
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
uid = str(uid)
im = await draw_cahrcard_list(str(uid), qid) im = await draw_cahrcard_list(str(uid), qid)
logger.info(f'UID{uid}获取角色数据成功!') logger.info(f'UID{uid}获取角色数据成功!')
if isinstance(im, bytes): if isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, str(im)) await matcher.finish(str(im))

View File

@ -501,7 +501,7 @@ class Character:
# 重新计算加成值 # 重新计算加成值
# base_effect_list = [ # base_effect_list = [
# [limit_list, effect_attr, effect_value,effect_base] # [limit_list, effect_attr, effect_value, effect_base]
# ] # ]
for effect in base_effect_list: for effect in base_effect_list:
prop = await self.get_buff_value(prop, *effect) prop = await self.get_buff_value(prop, *effect)
@ -614,8 +614,12 @@ class Character:
'type': '攻击力', 'type': '攻击力',
'plus': 1, 'plus': 1,
'value': [ 'value': [
f'''{int(i[:-1]) + f'''{
int(self.power_list["A霜华矢·霜华绽发伤害"]["value"][index][:-1]) int(i[:-1]) + int(
self.power_list[
"A霜华矢·霜华绽发伤害"
]["value"][index][:-1]
)
}%''' }%'''
for index, i in enumerate( for index, i in enumerate(
self.power_list['A霜华矢命中伤害']['value'] self.power_list['A霜华矢命中伤害']['value']

View File

@ -216,8 +216,8 @@ class Fight:
if '前台' in char.power_list[char.power_name]['name']: if '前台' in char.power_list[char.power_name]['name']:
if char.char_name == '纳西妲': if char.char_name == '纳西妲':
em = char.fight_prop[f'{char.attack_type}_elementalMastery'] em = char.fight_prop[f'{char.attack_type}_elementalMastery']
effect = f'''elementalMastery+ effect = f'''
{0.25 * em if 0.25 * em <= 250 else 250} elementalMastery+{0.25 * em if 0.25 * em <= 250 else 250}
'''.strip() '''.strip()
effect_list.append(effect) effect_list.append(effect)

View File

@ -1,42 +1,118 @@
from pathlib import Path from pathlib import Path
from typing import Any, Tuple
from hoshino.typing import CQEvent, HoshinoBot from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot import on_regex, on_command
from nonebot.params import CommandArg, RegexGroup
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from ..base import sv, logger
from ..version import Genshin_version from ..version import Genshin_version
from ..utils.draw_image_tools.send_image_tool import convert_img from ..genshinuid_meta import register_menu
from ..utils.exception.handle_exception import handle_exception
get_primogems_data = on_command('版本规划', aliases={'原石预估'})
get_img_data = on_regex(r'^(查询)?(伤害乘区|血量表|抗性表|血量排行)$')
PRIMOGEMS_DATA_PATH = Path(__file__).parent / 'primogems_data' PRIMOGEMS_DATA_PATH = Path(__file__).parent / 'primogems_data'
IMG_PATH = Path(__file__).parent / 'img_data' IMG_PATH = Path(__file__).parent / 'img_data'
@sv.on_rex(r'^(版本规划|原石预估)(\S+)?$') @get_primogems_data.handle()
async def send_primogems_data(bot: HoshinoBot, ev: CQEvent): @handle_exception('版本规划')
args = ev['match'].groups() @register_menu(
'版本原石规划',
'版本规划(版本号)',
'发送一张指定版本的原石规划图',
detail_des=(
'介绍:\n'
'发送一张指定版本的原石规划图\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>版本规划</ft><ft color=(125,125,125)>(版本号)</ft>\n'
'- <ft color=(238,120,0)>原石预估</ft><ft color=(125,125,125)>(版本号)</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>版本规划</ft>\n'
'- <ft color=(238,120,0)>版本规划3.0</ft>'
),
)
async def send_primogems_data(matcher: Matcher, args: Message = CommandArg()):
logger.info('开始执行[图片][版本规划]') logger.info('开始执行[图片][版本规划]')
logger.info('[图片][版本规划]参数: {}'.format(args)) logger.info('[图片][版本规划]参数: {}'.format(args))
if args[1]: if args:
path = PRIMOGEMS_DATA_PATH / f'{str(args[1])}.png' path = PRIMOGEMS_DATA_PATH / f'{str(args)}.png'
if path.exists(): if path.exists():
img = f'{str(args[1])}.png' img = f'{str(args)}.png'
else: else:
return await matcher.finish()
else: else:
img = f'{Genshin_version[:3]}.png' img = f'{Genshin_version[:3]}.png'
primogems_img = PRIMOGEMS_DATA_PATH / img primogems_img = PRIMOGEMS_DATA_PATH / img
logger.info('[图片][版本规划]访问图片: {}'.format(img)) if primogems_img.exists():
primogems_img = await convert_img(primogems_img) logger.info('[图片][版本规划]访问图片: {}'.format(img))
await bot.send(ev, primogems_img) with open(primogems_img, 'rb') as f:
await matcher.finish(MessageSegment.image(f.read()))
else:
await matcher.finish()
@sv.on_rex(r'^(查询)?(伤害乘区|血量表|抗性表|血量排行)$') @get_img_data.handle()
async def send_img_data(bot: HoshinoBot, ev: CQEvent): @handle_exception('杂图')
args = ev['match'].groups() @register_menu(
'伤害乘区图',
'(查询)伤害乘区',
'发送一张理论伤害计算公式图',
detail_des=(
'介绍:\n'
'发送一张理论伤害计算公式图\n'
' \n'
'指令:\n'
'- <ft color=(125,125,125)>(查询)</ft><ft color=(238,120,0)>伤害乘区</ft>'
),
)
@register_menu(
'怪物血量表',
'(查询)血量表',
'发送一张原神怪物血量表图',
detail_des=(
'介绍:\n'
'发送一张原神怪物血量表图\n'
' \n'
'指令:\n'
'- <ft color=(125,125,125)>(查询)</ft><ft color=(238,120,0)>血量表</ft>'
),
)
@register_menu(
'怪物抗性表',
'(查询)抗性表',
'发送一张原神怪物抗性表图',
detail_des=(
'介绍:\n'
'发送一张原神怪物抗性表图\n'
' \n'
'指令:\n'
'- <ft color=(125,125,125)>(查询)</ft><ft color=(238,120,0)>抗性表</ft>'
),
)
@register_menu(
'怪物血量排行',
'(查询)血量排行',
'发送一张原神怪物血量排行图',
detail_des=(
'介绍:\n'
'发送一张原神怪物血量排行图\n'
' \n'
'指令:\n'
'- <ft color=(125,125,125)>(查询)</ft><ft color=(238,120,0)>血量排行</ft>'
),
)
async def send_img_data(
matcher: Matcher, args: Tuple[Any, ...] = RegexGroup()
):
logger.info('开始执行[图片][杂图]') logger.info('开始执行[图片][杂图]')
logger.info('[图片][杂图]参数: {}'.format(args)) logger.info('[图片][杂图]参数: {}'.format(args))
img = IMG_PATH / f'{args[1]}.jpg' img = IMG_PATH / f'{args[1]}.jpg'
if img.exists(): if img.exists():
img = await convert_img(img) with open(img, 'rb') as f:
await bot.send(ev, img) await matcher.finish(MessageSegment.image(f.read()))
else:
return

View File

@ -1,24 +1,56 @@
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.matcher import Matcher
from nonebot_plugin_apscheduler import scheduler
from nonebot.adapters.onebot.v11 import MessageSegment
from ..base import sv from ..config import priority
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from .draw_event_img import get_event_img, get_all_event_img from .draw_event_img import get_event_img, get_all_event_img
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
get_event = on_command('活动列表', priority=priority, rule=FullCommand())
get_gacha = on_command('卡池列表', priority=priority, rule=FullCommand())
@sv.scheduled_job('cron', hour='2') @scheduler.scheduled_job('cron', hour='2')
async def draw_event(): async def draw_event():
await get_all_event_img() await get_all_event_img()
@sv.on_fullmatch('活动列表') @get_event.handle()
async def send_events(bot: HoshinoBot, ev: CQEvent): @handle_exception('活动')
@register_menu(
'活动列表',
'活动列表',
'查询当前版本活动日程表',
detail_des=(
'介绍:\n'
'查询当前版本活动日程表\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>活动列表</ft>'
),
)
async def send_events(matcher: Matcher):
img = await get_event_img('EVENT') img = await get_event_img('EVENT')
im = await convert_img(img) await matcher.finish(MessageSegment.image(img))
await bot.send(ev, im)
@sv.on_fullmatch('卡池列表') @get_gacha.handle()
async def send_gachas(bot: HoshinoBot, ev: CQEvent): @handle_exception('活动')
@register_menu(
'卡池列表',
'卡池列表',
'查询当前版本卡池列表',
detail_des=(
'介绍:\n'
'查询当前版本卡池列表\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>卡池列表</ft>'
),
)
async def send_gachas(matcher: Matcher):
img = await get_event_img('GACHA') img = await get_event_img('GACHA')
im = await convert_img(img) await matcher.finish(MessageSegment.image(img))
await bot.send(ev, im)

View File

@ -1,93 +1,161 @@
from nonebot import get_bot from typing import Union
from hoshino.typing import CQEvent, HoshinoBot, NoticeSession
from nonebot.log import logger
from ..base import sv, logger from nonebot.matcher import Matcher
from .get_gachalogs import save_gachalogs from nonebot import get_bot, on_notice, on_command
from .draw_gachalogs import draw_gachalogs_img from nonebot.adapters.onebot.v11 import (
from ..utils.message.error_reply import UID_HINT NoticeEvent,
from ..utils.db_operation.db_operation import select_db MessageSegment,
from ..utils.draw_image_tools.send_image_tool import convert_img GroupMessageEvent,
from .export_and_import import export_gachalogs, import_gachalogs PrivateMessageEvent,
)
@sv.on_notice() from .get_gachalogs import save_gachalogs
async def import_gacha_log_info(session: NoticeSession): from ..genshinuid_meta import register_menu
ev = session.event from ..utils.nonebot2.rule import FullCommand
if ev['notice_type'] != 'offline_file': from .draw_gachalogs import draw_gachalogs_img
return from ..utils.message.error_reply import UID_HINT
url = ev['file']['url'] from ..utils.db_operation.db_operation import select_db
name: str = ev['file']['name'] from ..utils.exception.handle_exception import handle_exception
if not name.endswith('.json'): from .export_and_import import export_gachalogs, import_gachalogs
return
qid = ev['user_id'] get_gacha_log = on_command('刷新抽卡记录', aliases={'强制刷新抽卡记录'}, rule=FullCommand())
uid = await select_db(qid, mode='uid') get_gacha_log_card = on_command('抽卡记录', rule=FullCommand())
if not isinstance(uid, str) or '未找到绑定的UID' in uid: import_gacha_log = on_notice()
await session.send(UID_HINT) export_gacha_log = on_command('导出抽卡记录', rule=FullCommand())
return
logger.info('开始执行[导入抽卡记录]')
im = await import_gachalogs(url, uid) @export_gacha_log.handle()
await session.send(im, at_sender=True) @handle_exception('导出抽卡记录')
@register_menu(
'导出抽卡记录',
@sv.on_fullmatch('导出抽卡记录') '导出抽卡记录',
async def export_gacha_log_info(bot: HoshinoBot, ev: CQEvent): '导出符合UIGF规范的抽卡记录',
logger.info('开始执行[导出抽卡记录]') trigger_method='群聊指令',
qid = int(ev.sender['user_id']) detail_des=(
gid = int(ev.group_id) '介绍:\n'
uid = await select_db(qid, mode='uid') '导出UIGF格式规范的json格式抽卡记录上传到群文件\n'
bot = get_bot() ' \n'
if not isinstance(uid, str) or '未找到绑定的UID' in uid: '指令:\n'
await bot.send(ev, UID_HINT) '- <ft color=(238,120,0)>导出抽卡记录</ft>'
return ),
raw_data = await export_gachalogs(uid) )
if raw_data['retcode'] == 'ok': async def export_gacha_log_info(
await bot.call_action( event: GroupMessageEvent,
action='upload_group_file', matcher: Matcher,
group_id=gid, ):
name=raw_data['name'], logger.info('开始执行[导出抽卡记录]')
file=raw_data['url'], qid = event.user_id
) gid = event.group_id
logger.info(f'[导出抽卡记录] UID{uid}成功!') uid = await select_db(qid, mode='uid')
await bot.send(ev, '上传成功!') bot = get_bot()
else: if not isinstance(uid, str) or '未找到绑定的UID' in uid:
logger.warning(f'[导出抽卡记录] UID{uid}失败!') await matcher.finish(UID_HINT)
await bot.send(ev, '导出抽卡记录失败!') raw_data = await export_gachalogs(uid)
if raw_data['retcode'] == 'ok':
await bot.call_api(
@sv.on_fullmatch('抽卡记录') 'upload_group_file',
async def send_gacha_log_card_info(bot: HoshinoBot, ev: CQEvent): group_id=gid,
logger.info('开始执行[抽卡记录]') name=raw_data['name'],
if ev.sender: file=raw_data['url'],
qid = int(ev.sender['user_id']) )
else: logger.info(f'[导出抽卡记录] UID{uid}成功!')
return await matcher.finish('上传成功!')
uid = await select_db(qid, mode='uid') else:
logger.warning(f'[导出抽卡记录] UID{uid}失败!')
if isinstance(uid, str): await matcher.finish('导出抽卡记录失败!')
im = await draw_gachalogs_img(uid, qid)
if isinstance(im, bytes):
im = await convert_img(im) @import_gacha_log.handle()
await bot.send(ev, im) @handle_exception('导入抽卡记录')
else: @register_menu(
await bot.send(ev, im) '导入抽卡记录',
else: 'json格式文件',
await bot.send(ev, UID_HINT) '导入符合UIGF规范的抽卡记录',
trigger_method='私聊离线文件',
detail_des=(
@sv.on_fullmatch(('刷新抽卡记录', '强制刷新抽卡记录')) '介绍:\n'
async def send_daily_info(bot: HoshinoBot, ev: CQEvent): '导入UIGF格式规范的json格式抽卡记录到插件本地缓存\n'
logger.info('开始执行[刷新抽卡记录]') ' \n'
if ev.sender: '触发方式:\n'
qid = int(ev.sender['user_id']) '- <ft color=(238,120,0)>私聊发送json格式的离线文件</ft>'
else: ),
return )
uid = await select_db(qid, mode='uid') async def import_gacha_log_info(event: NoticeEvent, matcher: Matcher):
if isinstance(uid, str): args = event.dict()
is_force = False if args['notice_type'] != 'offline_file':
if ev.raw_message and str(ev.raw_message).startswith('强制'): await matcher.finish()
logger.info('[WARNING]本次为强制刷新') url = args['file']['url']
is_force = True name: str = args['file']['name']
im = await save_gachalogs(uid, None, is_force) if not name.endswith('.json'):
await bot.send(ev, im) return
else: qid = args['user_id']
await bot.send(ev, UID_HINT) uid = await select_db(qid, mode='uid')
if not isinstance(uid, str) or '未找到绑定的UID' in uid:
await matcher.finish(UID_HINT)
logger.info('开始执行[导入抽卡记录]')
im = await import_gachalogs(url, uid)
await matcher.finish(im)
@get_gacha_log_card.handle()
@handle_exception('抽卡记录')
@register_menu(
'查询抽卡记录',
'抽卡记录',
'查询你的原神抽卡记录',
detail_des=(
'介绍:\n'
'查询你的原神抽卡记录\n'
'需要<ft color=(238,120,0)>绑定Stoken</ft>\n'
' \n'
'指令:\n'
'<ft color=(238,120,0)>抽卡记录</ft>'
),
)
async def send_gacha_log_card_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
):
logger.info('开始执行[抽卡记录]')
uid = await select_db(event.user_id, mode='uid')
if isinstance(uid, str):
im = await draw_gachalogs_img(uid, event.user_id)
if isinstance(im, bytes):
await matcher.finish(MessageSegment.image(im))
else:
await matcher.finish(im)
else:
await matcher.finish(UID_HINT)
@get_gacha_log.handle()
@handle_exception('刷新抽卡记录')
@register_menu(
'刷新抽卡记录',
'刷新抽卡记录',
'刷新你的原神抽卡记录本地缓存',
detail_des=(
'介绍:\n'
'刷新你的原神抽卡记录本地缓存\n'
'需要<ft color=(238,120,0)>绑定Stoken</ft>\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>刷新抽卡记录</ft>'
),
)
async def send_daily_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
):
logger.info('开始执行[刷新抽卡记录]')
uid = await select_db(event.user_id, mode='uid')
if isinstance(uid, str):
is_force = False
if event.raw_message.startswith('强制'):
is_force = True
im = await save_gachalogs(uid, None, is_force)
await matcher.finish(im)
else:
await matcher.finish(UID_HINT)

View File

@ -0,0 +1,43 @@
from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent
from .gacha_url import post_url
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.message.error_reply import UID_HINT
from ..utils.db_operation.db_operation import select_db
from ..utils.exception.handle_exception import handle_exception
get_gacha_url = on_command(
'获取抽卡记录链接', aliases={'抽卡链接', '抽卡记录链接'}, rule=FullCommand()
)
@get_gacha_url.handle()
@handle_exception('获取抽卡记录链接')
@register_menu(
'获取抽卡记录链接',
'获取抽卡记录链接',
'获取用户的抽卡记录链接',
trigger_method='群聊指令',
detail_des=(
'介绍:\n'
'导出抽卡记录的链接以用于原神小程序\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>抽卡链接</ft>'
),
)
async def _(
bot: Bot,
event: GroupMessageEvent,
matcher: Matcher,
):
await get_gacha_url.send("正在获取抽卡记录链接")
logger.info('开始执行[获取抽卡记录链接]')
uid = await select_db(event.user_id, mode='uid')
if not isinstance(uid, str) or '未找到绑定的UID' in uid:
await matcher.finish(UID_HINT)
await post_url(bot, uid, str(event.group_id), str(event.user_id))

View File

@ -0,0 +1,53 @@
import time
from urllib.parse import quote
from nonebot.adapters.onebot.v11 import Bot
from ..utils.message.error_reply import SK_HINT
from ..utils.message.send_msg import send_forward_msg
from ..utils.mhy_api.get_mhy_data import get_authkey_by_cookie
async def post_url(bot: Bot, uid: str, group_id: str, qid: str):
async def send_group_msg(msg: str):
await bot.call_api(
api='send_group_msg',
group_id=group_id,
message=msg,
)
return ''
authkey = await get_authkey_by_cookie(uid)
if authkey == {}:
return await send_group_msg(SK_HINT)
authkey = authkey['data']['authkey']
now = time.time()
region = ""
if uid[0] == "1" or uid[0] == "2":
region = 'cn_gf01'
elif uid[0] == "5":
region = "'cn_qd01'"
elif uid[0] == "6":
region = "'os_usa'"
elif uid[0] == "7":
region = "'os_euro'"
elif uid[0] == "8":
region = "'os_asia'"
elif uid[0] == "9":
region = "'os_cht'"
else:
region = 'cn_gf01'
msgs = []
msgs.append(f"uid{uid}的抽卡记录链接为:")
url = (
f"https://hk4e-api.mihoyo.com/event/gacha_info/api/getGachaLog?"
f"authkey_ver=1&sign_type=2&auth_appid=webview_gacha&init_type=301&"
f"gacha_id=fecafa7b6560db5f3182222395d88aaa6aaac1bc"
f"&timestamp={str(int(now))}"
f"&lang=zh-cn&device_type=mobile&plat_type=ios&region={region}"
f"&authkey={quote(authkey,'utf-8')}"
f"&game_biz=hk4e_cn&gacha_type=301&page=1&size=5&end_id=0"
)
msgs.append(url)
await send_forward_msg(bot, group_id, "抽卡链接", qid, msgs)
return "成功执行"

View File

@ -1,28 +1,41 @@
import re import re
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import Depends, CommandArg
from nonebot.adapters.onebot.v11 import Message, MessageEvent, MessageSegment
from ..base import sv, logger from ..config import priority
from .draw_gcginfo import draw_gcg_info from .draw_gcginfo import draw_gcg_info
from ..utils.message.error_reply import UID_HINT
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.message.get_image_and_at import ImageAndAt
from ..utils.message.error_reply import CK_HINT, UID_HINT
from ..utils.exception.handle_exception import handle_exception
get_gcg_info = on_command('七圣召唤', aliases={'七圣', '召唤'}, priority=priority)
@sv.on_prefix(('七圣召唤', '七圣', '召唤')) # 群聊内 每月统计 功能
async def send_gcg_pic(bot: HoshinoBot, ev: CQEvent): @get_gcg_info.handle()
if ev.message: @handle_exception('七圣召唤', '获取/发送七圣召唤失败', '@未找到绑定信息\n' + CK_HINT)
raw_mes = ev.message.extract_plain_text().replace(' ', '') async def send_gcg_pic(
else: event: MessageEvent,
matcher: Matcher,
args: Message = CommandArg(),
custom: ImageAndAt = Depends(),
):
raw_mes = args.extract_plain_text().strip().replace(' ', '')
name = ''.join(re.findall('[\u4e00-\u9fa5]', raw_mes))
if name:
return return
at = custom.get_first_at()
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message))
logger.info('开始执行[七圣召唤]') logger.info('开始执行[七圣召唤]')
if at: if at:
qid = int(at.group(1)) qid = at
else: else:
qid = int(ev.sender['user_id']) qid = event.user_id
logger.info('[七圣召唤]QQ: {}'.format(qid)) logger.info('[七圣召唤]QQ: {}'.format(qid))
# 获取uid # 获取uid
@ -32,18 +45,16 @@ async def send_gcg_pic(bot: HoshinoBot, ev: CQEvent):
else: else:
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
uid = str(uid) uid = str(uid)
logger.info('[七圣召唤]uid: {}'.format(uid)) logger.info('[七圣召唤]uid: {}'.format(uid))
if '未找到绑定的UID' in uid: if '未找到绑定的UID' in uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
im = await draw_gcg_info(uid) im = await draw_gcg_info(uid)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')

View File

@ -1,96 +1,132 @@
import asyncio import asyncio
import threading import threading
from typing import List
from pathlib import Path from pathlib import Path
from typing import Any, List, Tuple
from hoshino.typing import CQEvent, HoshinoBot from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot import on_regex, on_command
from nonebot.params import CommandArg, RegexGroup
from nonebot.adapters.onebot.v11 import (
Bot,
Message,
MessageSegment,
GroupMessageEvent,
)
from ..base import sv, logger
from .get_card import get_gs_card from .get_card import get_gs_card
from .get_guide import get_gs_guide from .get_guide import get_gs_guide
from ..version import Genshin_version from ..version import Genshin_version
from ..genshinuid_meta import register_menu
from .get_abyss_data import get_review, generate_data from .get_abyss_data import get_review, generate_data
from ..utils.alias.alias_to_char_name import alias_to_char_name from ..utils.alias.alias_to_char_name import alias_to_char_name
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
get_guide_pic = on_regex('([\u4e00-\u9fa5]+)(推荐|攻略)')
get_bluekun_pic = on_command('参考面板')
get_card = on_command('原牌')
get_abyss = on_command('版本深渊')
IMG_PATH = Path(__file__).parent / 'img' IMG_PATH = Path(__file__).parent / 'img'
@sv.on_rex('([\u4e00-\u9fa5]+)(推荐|攻略)') @get_guide_pic.handle()
async def send_guide_pic(bot: HoshinoBot, ev: CQEvent): @handle_exception('建议')
if ev.message: @register_menu(
name = name = str(ev['match'].group(1)) '角色攻略',
else: 'xx攻略',
'发送一张对应角色的西风驿站攻略图',
detail_des=(
'介绍:\n'
'发送一张对应角色的米游社西风驿站攻略图\n'
'支持部分角色别名\n'
' \n'
'指令:\n'
'- <ft color=(0,148,200)>[角色名]</ft>'
'<ft color=(238,120,0)>{推荐|攻略}</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>钟离推荐</ft>\n'
'- <ft color=(238,120,0)>公子攻略</ft>'
),
)
async def send_guide_pic(
matcher: Matcher, args: Tuple[Any, ...] = RegexGroup()
):
if not args:
return return
name = str(args[0])
if name == '':
return
im = await get_gs_guide(name) im = await get_gs_guide(name)
if im: if im:
logger.info('获得{}攻略成功!'.format(name)) logger.info('获得{}攻略成功!'.format(name))
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
logger.warning('未找到{}攻略图片'.format(name)) logger.warning('未找到{}攻略图片'.format(name))
@sv.on_prefix('参考面板') @get_bluekun_pic.handle()
async def send_bluekun_pic(bot: HoshinoBot, ev: CQEvent): @handle_exception('参考面板')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '参考面板',
'参考面板[角色名/元素名]',
'发送一张对应角色/元素的参考面板图',
detail_des=(
'介绍:\n'
'发送一张对应角色/元素的参考面板图\n'
'支持部分角色别名\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>参考面板</ft>'
'<ft color=(0,148,200)>[角色名/元素名]</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>参考面板火</ft>\n'
'- <ft color=(238,120,0)>参考面板公子</ft>'
),
)
async def send_bluekun_pic(matcher: Matcher, args: Message = CommandArg()):
if str(args[0]) in ['', '', '', '', '', '', '']:
name = str(args[0])
else: else:
return name = await alias_to_char_name(str(args[0]))
if message == '':
return
if str(message) in ['', '', '', '', '', '', '']:
name = str(message)
else:
name = await alias_to_char_name(str(message))
img = IMG_PATH / '{}.jpg'.format(name) img = IMG_PATH / '{}.jpg'.format(name)
if img.exists(): if img.exists():
img = await convert_img(img) with open(img, 'rb') as f:
im = MessageSegment.image(f.read())
logger.info('获得{}参考面板图片成功!'.format(name)) logger.info('获得{}参考面板图片成功!'.format(name))
await bot.send(ev, img) await matcher.finish(im)
else: else:
logger.warning('未找到{}参考面板图片'.format(name)) logger.warning('未找到{}参考面板图片'.format(name))
@sv.on_prefix('原牌') @get_card.handle()
async def send_gscard_pic(bot: HoshinoBot, ev: CQEvent): @handle_exception('原牌')
if ev.message: async def send_gscard_pic(matcher: Matcher, args: Message = CommandArg()):
name = ev.message.extract_plain_text().replace(' ', '') if not args:
else:
return return
name = str(args[0])
if name == '':
return
im = await get_gs_card(name) im = await get_gs_card(name)
if im: if im:
logger.info('获得{}原牌成功!'.format(name)) logger.info('获得{}原牌成功!'.format(name))
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
logger.warning('未找到{}原牌图片'.format(name)) logger.warning('未找到{}原牌图片'.format(name))
@sv.on_prefix('版本深渊') @get_abyss.handle()
async def send_abyss_review(bot: HoshinoBot, ev: CQEvent): @handle_exception('原牌')
if ev.message: async def send_abyss_review(
version = ev.message.extract_plain_text().replace(' ', '') bot: Bot,
else: event: GroupMessageEvent,
return matcher: Matcher,
args: Message = CommandArg(),
if version == '': ):
if not args:
version = Genshin_version[:-2] version = Genshin_version[:-2]
else:
version = str(args[0])
im = await get_review(version) im = await get_review(version)
if isinstance(im, List): if isinstance(im, List):
mes = [] mes = []
for msg in im: for msg in im:
@ -104,14 +140,16 @@ async def send_abyss_review(bot: HoshinoBot, ev: CQEvent):
}, },
} }
) )
await bot.send_group_forward_msg(group_id=ev.group_id, messages=mes) await bot.call_api(
'send_group_forward_msg', group_id=event.group_id, messages=mes
)
await matcher.finish()
elif isinstance(im, str): elif isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
threading.Thread( threading.Thread(

View File

@ -2,18 +2,37 @@ import asyncio
import threading import threading
from pathlib import Path from pathlib import Path
from ..base import sv, logger from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11 import MessageSegment
from .draw_help_card import draw_help_img from .draw_help_card import draw_help_img
from ..utils.draw_image_tools.send_image_tool import convert_img from ..genshinuid_meta import register_menu
from ..utils.exception.handle_exception import handle_exception
get_help = on_command('gs帮助')
HELP_IMG = Path(__file__).parent / 'help.png' HELP_IMG = Path(__file__).parent / 'help.png'
@sv.on_fullmatch(('gs帮助', 'genshin帮助', 'ys帮助', '原神帮助')) @get_help.handle()
async def send_guide_pic(bot, ev): @handle_exception('建议')
img = await convert_img(HELP_IMG) @register_menu(
'插件帮助',
'gs帮助',
'查看插件功能帮助图',
detail_des=(
'介绍:\n' '查看插件功能帮助图\n' ' \n' '指令:\n' '- <ft color=(238,120,0)>gs帮助</ft>'
),
)
async def send_guide_pic(matcher: Matcher):
logger.info('获得gs帮助图片成功') logger.info('获得gs帮助图片成功')
await bot.send(ev, img) if HELP_IMG.exists():
with open(HELP_IMG, 'rb') as f:
await matcher.finish(MessageSegment.image(f.read()))
else:
await matcher.finish('帮助图不存在!')
threading.Thread( threading.Thread(

View File

@ -1,8 +1,29 @@
from hoshino.typing import CQEvent, HoshinoBot from typing import Any, Dict, Union
from ..base import sv, logger from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import RegexDict
from nonebot import on_regex, on_command
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11 import (
Bot,
MessageSegment,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..config import priority
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from .draw_genshinmap_card import MAP_DATA, draw_genshin_map from .draw_genshinmap_card import MAP_DATA, draw_genshin_map
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
change_map = on_command('切换地图', block=True, rule=FullCommand())
find_map = on_regex(
r'^(?P<name>.*)(在哪里|在哪|哪里有|哪儿有|哪有|在哪儿)$', priority=priority
)
find_map2 = on_regex(r'^(哪里有|哪儿有|哪有)(?P<name>.*)$', priority=priority)
MAP_ID_LIST = [ MAP_ID_LIST = [
'2', # 提瓦特 '2', # 提瓦特
@ -18,13 +39,31 @@ MAP_CHN_NAME = {
} }
@sv.on_fullmatch('切换地图') @change_map.handle()
async def send_change_map_msg(bot: HoshinoBot, ev: CQEvent): @handle_exception('切换地图')
if ev.sender: @register_menu(
qid = int(ev.sender['user_id']) '切换地图',
else: '切换地图',
return '切换查找资源点功能所使用的地图',
if qid not in bot.config.SUPERUSERS: detail_des=(
'介绍:\n'
'切换查找资源点功能所使用的地图\n'
'指令按列表顺序轮流切换地图\n'
'目前可用地图:'
+ "".join(
[f"<ft color=(238,120,0)>{x}</ft>" for x in MAP_CHN_NAME.values()]
)
+ ' \n\n'
'指令:\n'
'- <ft color=(238,120,0)>切换地图</ft>'
),
)
async def send_change_map_msg(
bot: Bot,
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
):
if not await SUPERUSER(bot, event):
return return
logger.info('[切换地图]正在执行...') logger.info('[切换地图]正在执行...')
MAP_ID_LIST.append(MAP_ID_LIST[0]) MAP_ID_LIST.append(MAP_ID_LIST[0])
@ -32,44 +71,67 @@ async def send_change_map_msg(bot: HoshinoBot, ev: CQEvent):
current = MAP_ID_LIST[0] current = MAP_ID_LIST[0]
chn = MAP_CHN_NAME.get(current) chn = MAP_CHN_NAME.get(current)
logger.info(f'[切换地图]当前地图为{chn}') logger.info(f'[切换地图]当前地图为{chn}')
await bot.send(ev, f'切换到{chn}地图') await matcher.finish(f'切换到{chn}地图')
@sv.on_rex(r'^(?P<name>.*)(在哪里|在哪|哪里有|哪儿有|哪有|在哪儿)$') @find_map.handle()
@sv.on_rex(r'^(哪里有|哪儿有|哪有)(?P<name>.*)$') @find_map2.handle()
async def send_find_map_msg(bot: HoshinoBot, ev: CQEvent): @handle_exception('查找资源点')
@register_menu(
'查找资源点',
'xx在哪',
'查找指定资源在地图上的位置',
detail_des=(
'介绍:\n'
'在米游社大地图上查询某资源的位置\n'
'使用 <ft color=(238,120,0)>切换地图</ft> 指令来切换目标地图'
' \n'
'指令:\n'
'- <ft color=(0,148,200)>[资源名称]</ft>'
'<ft color=(238,120,0)>{在哪里|在哪|哪里有|哪儿有|哪有|在哪儿}</ft>\n'
'- <ft color=(238,120,0)>{哪里有|哪儿有|哪有}</ft>'
'<ft color=(0,148,200)>[资源名称]</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>甜甜花在哪</ft>\n'
'- <ft color=(238,120,0)>哪有清心</ft>'
),
)
async def send_find_map_msg(
matcher: Matcher, args: Dict[str, Any] = RegexDict()
):
map_id = MAP_ID_LIST[0] map_id = MAP_ID_LIST[0]
map_name = MAP_CHN_NAME[map_id] map_name = MAP_CHN_NAME[map_id]
args = ev['match'].groupdict().get('name')
logger.info(f'[查找资源点]正在执行...当前地图为{map_name}') logger.info(f'[查找资源点]正在执行...当前地图为{map_name}')
logger.info('[查找资源点]参数: {}'.format(args)) logger.info('[查找资源点]参数: {}'.format(args))
if not args: if not (args and (name := args.get('name'))):
return return
im = ''
if not MAP_DATA.exists(): if not MAP_DATA.exists():
MAP_DATA.mkdir() MAP_DATA.mkdir()
resource_temp_path = MAP_DATA / f'{map_name}_{args}.jpg' resource_temp_path = MAP_DATA / f'{map_name}_{name}.jpg'
if resource_temp_path.exists(): if resource_temp_path.exists():
logger.info(f'本地已有{map_name}_{args}的资源点,直接发送...') logger.info(f'本地已有{map_name}_{name}的资源点,直接发送...')
resource_temp = await convert_img(resource_temp_path) with open(resource_temp_path, 'rb') as f:
await bot.send(ev, resource_temp) await matcher.finish(MessageSegment.image(f.read()))
else: else:
# 放弃安慰剂回复 # 放弃安慰剂回复
''' '''
await bot.send( await matcher.send(
ev, (
f'正在查找{args},可能需要比较久的时间...\n当前地图:{map_name}', f'正在查找{name},可能需要比较久的时间...\n'
f'当前地图:{MAP_CHN_NAME.get(MAP_ID_LIST[0])}'
)
) )
''' '''
logger.info('本地未缓存,正在渲染...') logger.info('本地未缓存,正在渲染...')
im = await draw_genshin_map(args, map_id, map_name) im = await draw_genshin_map(name, map_id, map_name)
if isinstance(im, str): if isinstance(im, str):
return # 如果无结果,直接不返回
# await bot.send(ev, im) await matcher.finish()
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im) else:
await matcher.finish('查找失败!')

View File

@ -0,0 +1,54 @@
from typing import Optional
from nonebot.plugin import PluginMetadata
sub_menus = []
__plugin_meta__ = PluginMetadata(
name='GenshinUID',
description='基于NoneBot2的原神Uid查询/原神Wiki/米游社签到/树脂提醒插件',
usage=(
'发送 <ft color=(238,120,0)>gs帮助</ft> 可以获取帮助列表,也可以参考下面的表格\n'
'可以使用 <ft color=(238,120,0)>菜单 gsuid </ft>'
'<ft color=(0,148,200)>[序号]</ft> '
'指令获取某功能详细介绍\n'
' \n'
'菜单描述中的指令:\n'
'<ft color=(0,148,200)>[中括号及其中的内容]</ft>'
'或<ft color=(0,148,200)>用“xx”代表的内容</ft> '
'为<ft color=(238,120,0)>必选</ft>的参数,'
'请将它们替换为适当的值;\n'
'<ft color=(125,125,125)>(小括号及其中的内容)</ft> '
'为<ft color=(238,120,0)>可选</ft>参数,'
'可以省略;\n'
'<ft color=(238,120,0)>{大括号及其中的内容}</ft> '
'为<ft color=(238,120,0)>选择其一</ft>参数,'
'请将它们替换为用 <ft color=(238,120,0)>|</ft> 分割后括号中内容的其中一个值'
),
extra={'menu_data': sub_menus, 'menu_template': 'default'},
)
def register_menu_func(
func: str,
trigger_condition: str,
brief_des: str,
trigger_method: str = '指令',
detail_des: Optional[str] = None,
):
sub_menus.append(
{
'func': func,
'trigger_method': trigger_method,
'trigger_condition': trigger_condition,
'brief_des': brief_des,
'detail_des': detail_des or brief_des,
}
)
def register_menu(*args, **kwargs):
def decorator(f):
register_menu_func(*args, **kwargs)
return f
return decorator

View File

@ -1,35 +1,75 @@
import random import random
import asyncio import asyncio
from nonebot import get_bot from nonebot.log import logger
from hoshino.typing import CQEvent, HoshinoBot from nonebot.matcher import Matcher
from nonebot import get_bot, on_command
from nonebot.permission import SUPERUSER
from nonebot_plugin_apscheduler import scheduler
from nonebot.adapters.onebot.v11 import MessageEvent
from ..base import sv, logger from ..config import priority
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.nonebot2.utils import get_superusers
from ..utils.db_operation.db_operation import config_check from ..utils.db_operation.db_operation import config_check
from ..utils.exception.handle_exception import handle_exception
from .daily_mihoyo_bbs_coin import mihoyo_coin, all_daily_mihoyo_bbs_coin from .daily_mihoyo_bbs_coin import mihoyo_coin, all_daily_mihoyo_bbs_coin
bbscoin_scheduler = scheduler
get_mihoyo_coin = on_command('开始获取米游币', priority=priority, rule=FullCommand())
all_bbscoin_recheck = on_command(
'全部重获取', permission=SUPERUSER, priority=priority, rule=FullCommand()
)
# 获取米游币 # 获取米游币
@sv.on_fullmatch('开始获取米游币') @get_mihoyo_coin.handle()
async def send_mihoyo_coin(bot: HoshinoBot, ev: CQEvent): @handle_exception('获取米游币')
await bot.send(ev, '开始操作……', at_sender=True) @register_menu(
qid = int(ev.sender['user_id']) # type: ignore '手动获取米游币',
'开始获取米游币',
'手动触发米游社米游币任务',
detail_des=(
'介绍:\n'
'手动触发米游社获取米游币的任务\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>开始获取米游币</ft>'
),
)
async def send_mihoyo_coin(event: MessageEvent, matcher: Matcher):
await matcher.send('开始操作……', at_sender=True)
qid = event.user_id
im = await mihoyo_coin(qid) im = await mihoyo_coin(qid)
await bot.send(ev, im, at_sender=True) await matcher.finish(im, at_sender=True)
@sv.on_fullmatch('全部重获取') @all_bbscoin_recheck.handle()
async def bbs_recheck(bot: HoshinoBot, ev: CQEvent): @handle_exception('米游币全部重获取')
qid = int(ev.sender['user_id']) # type: ignore @register_menu(
if qid not in bot.config.SUPERUSERS: '重新获取米游币',
return '全部重获取',
await bot.send(ev, '已开始执行!可能需要较久时间!') '重新运行所有自动获取米游币的任务',
detail_des=(
'介绍:\n'
'重新运行所有自动获取米游币的任务\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>全部重获取</ft>'
),
)
async def bbs_recheck(
matcher: Matcher,
):
await matcher.send('已开始执行!可能需要较久时间!')
await send_daily_mihoyo_bbs_sign() await send_daily_mihoyo_bbs_sign()
await bot.send(ev, '执行完成!') await matcher.finish('执行完成!')
# 每日一点十六分进行米游币获取 # 每日一点十六分进行米游币获取
@sv.scheduled_job('cron', hour='1', minute='16') @bbscoin_scheduler.scheduled_job('cron', hour='1', minute='16')
async def sign_at_night(): async def sign_at_night():
if await config_check('SchedMhyBBSCoin'): if await config_check('SchedMhyBBSCoin'):
await send_daily_mihoyo_bbs_sign() await send_daily_mihoyo_bbs_sign()
@ -45,7 +85,7 @@ async def send_daily_mihoyo_bbs_sign():
) )
await asyncio.sleep(5 + random.randint(1, 3)) await asyncio.sleep(5 + random.randint(1, 3))
if await config_check('PrivateReport'): if await config_check('PrivateReport'):
for qid in bot.config.SUPERUSERS: for qid in get_superusers():
await bot.send_private_msg(user_id=qid, message=im) await bot.call_api(api='send_private_msg', user_id=qid, message=im)
await asyncio.sleep(5 + random.randint(1, 3)) await asyncio.sleep(5 + random.randint(1, 3))
logger.info('米游币获取已结束。') logger.info('米游币获取已结束。')

View File

@ -1,39 +1,104 @@
import asyncio import asyncio
from typing import Any, Tuple
from hoshino.typing import CQEvent, HoshinoBot from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import RegexGroup
from nonebot import on_regex, on_command
from nonebot.adapters.onebot.v11 import (
Bot,
MessageEvent,
MessageSegment,
GroupMessageEvent,
)
from ..base import sv, logger from ..config import priority
from .get_lots_data import get_lots_msg from .get_lots_data import get_lots_msg
from .get_meme_card import get_meme_img from .get_meme_card import get_meme_img
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from .get_mys_data import get_region_task, get_task_detail from .get_mys_data import get_region_task, get_task_detail
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
get_task_adv = on_regex(
r'^(原神任务|任务|任务详情|任务攻略)( )?([\u4e00-\u9fa5]+)( )?$', priority=priority
)
get_meme = on_command('抽表情', priority=priority, rule=FullCommand())
get_lots = on_command('御神签', priority=priority, rule=FullCommand())
@sv.on_rex(r'^(原神任务|任务|任务详情|任务攻略)( )?([\u4e00-\u9fa5]+)( )?$') @get_task_adv.handle()
async def send_task_adv(bot: HoshinoBot, ev: CQEvent): @handle_exception('任务攻略')
args = ev['match'].groups() @register_menu(
'任务攻略',
'任务xx',
'查询某任务的攻略',
detail_des=(
'介绍:\n'
'查询指定任务或指定地区的攻略\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>{原神任务|任务|任务详情|任务攻略}</ft>'
'<ft color=(238,120,0)>{</ft>'
'<ft color=(0,148,200)>[任务名]</ft>'
'<ft color=(238,120,0)>|须弥|层岩|海岛}</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>任务神樱大祓</ft>\n'
'- <ft color=(238,120,0)>任务须弥</ft>'
),
)
async def send_task_adv(
bot: Bot,
event: GroupMessageEvent,
matcher: Matcher,
args: Tuple[Any, ...] = RegexGroup(),
):
if str(args[2]) in ['须弥', '层岩', '海岛']: if str(args[2]) in ['须弥', '层岩', '海岛']:
im = await get_region_task(str(args[2])) im = await get_region_task(str(args[2]))
for i in im: for i in im:
await bot.send_group_forward_msg(group_id=ev.group_id, messages=i) await bot.call_api(
'send_group_forward_msg', group_id=event.group_id, messages=i
)
await asyncio.sleep(1) await asyncio.sleep(1)
return await matcher.finish()
else: else:
im = await get_task_detail(str(args[2])) im = await get_task_detail(str(args[2]))
await bot.send(ev, im) await matcher.finish(im)
@sv.on_fullmatch('抽表情') @get_meme.handle()
async def send_meme_card(bot: HoshinoBot, ev: CQEvent): @handle_exception('抽表情')
@register_menu(
'抽表情',
'抽表情',
'随机发送一张札记角色表情',
detail_des=(
'介绍:\n'
'随机发送一张札记角色表情\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>抽表情</ft>'
),
)
async def send_meme_card(matcher: Matcher):
logger.info('开始执行[抽表情]') logger.info('开始执行[抽表情]')
img = await get_meme_img() img = await get_meme_img()
img = await convert_img(img) await matcher.finish(MessageSegment.image(img))
await bot.send(ev, img)
@sv.on_fullmatch('御神签') @get_lots.handle()
async def send_lots_data(bot: HoshinoBot, ev: CQEvent): @handle_exception('御神签')
qid = int(ev.sender['user_id']) @register_menu(
'御神签',
'御神签',
'鸣神大社御神签',
detail_des=(
'介绍:\n' '抽一签鸣神大社御神签\n' ' \n' '指令:\n' '- <ft color=(238,120,0)>御神签</ft>'
),
)
async def send_lots_data(matcher: Matcher, event: MessageEvent):
qid = event.user_id
logger.info('开始执行[御神签]') logger.info('开始执行[御神签]')
im = await get_lots_msg(qid) im = await get_lots_msg(qid)
await bot.send(ev, im) await matcher.finish(im)

View File

@ -1,48 +1,82 @@
import re from nonebot import on_command
from nonebot.log import logger
from hoshino.typing import CQEvent, HoshinoBot from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11 import MessageEvent, MessageSegment
from .note_text import award from .note_text import award
from ..base import sv, logger from ..config import priority
from .draw_note_card import draw_note_img from .draw_note_card import draw_note_img
from ..utils.message.error_reply import UID_HINT from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.message.error_reply import CK_HINT, UID_HINT
from ..utils.exception.handle_exception import handle_exception
monthly_data = on_command('每月统计', priority=priority, rule=FullCommand())
get_genshin_info = on_command(
'当前信息', aliases={'zj', '札记', '原石札记'}, priority=priority, rule=FullCommand()
)
# 群聊内 每月统计 功能 # 群聊内 每月统计 功能
@sv.on_fullmatch('每月统计') @monthly_data.handle()
async def send_monthly_data(bot: HoshinoBot, ev: CQEvent): @handle_exception('每月统计', '获取/发送每月统计失败', '@未找到绑定信息\n' + CK_HINT)
qid = int(ev.sender['user_id']) # type: ignore @register_menu(
'文字札记',
'每月统计',
'文字形式米游社札记',
detail_des=(
'介绍:\n' '文字形式米游社札记\n' ' \n' '指令:\n' '- <ft color=(238,120,0)>每月统计</ft>'
),
)
async def send_monthly_data(
event: MessageEvent,
matcher: Matcher,
):
qid = event.user_id
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
if isinstance(uid, str): if isinstance(uid, str):
if '未找到绑定的UID' in uid: if '未找到绑定的UID' in uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
else: else:
await bot.send(ev, '发生未知错误...') await matcher.finish('发生未知错误...')
im = await award(uid) im = await award(uid)
await bot.send(ev, im, at_sender=True) await matcher.finish(im, at_sender=True)
@sv.on_fullmatch(('当前信息', 'zj', '原石札记', '札记')) # 群聊内 每月统计 功能
async def send_monthly_pic(bot: HoshinoBot, ev: CQEvent): @get_genshin_info.handle()
logger.info('开始执行[每日信息]') @handle_exception('每月统计', '获取/发送每月统计失败', '@未找到绑定信息\n' + CK_HINT)
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) @register_menu(
if at: '图片札记',
qid = int(at.group(1)) '当前信息',
else: '图片形式米游社札记',
if ev.sender: detail_des=(
qid = int(ev.sender['user_id']) '介绍:\n'
else: '图片形式米游社札记\n'
return ' \n'
logger.info('[每日信息]QQ号: {}'.format(qid)) '指令:\n'
'- <ft color=(238,120,0)>当前信息</ft>\n'
'- <ft color=(125,125,125)>(原石)</ft><ft color=(238,120,0)>札记</ft>\n'
'- <ft color=(238,120,0)>zj</ft>'
),
)
async def send_monthly_pic(
event: MessageEvent,
matcher: Matcher,
):
qid = event.user_id
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
logger.info('[每日信息]UID: {}'.format(uid)) if isinstance(uid, str):
im = await draw_note_img(str(uid)) if '未找到绑定的UID' in uid:
if isinstance(im, str): await matcher.finish(UID_HINT)
await bot.send(ev, im)
elif isinstance(im, bytes):
im = await convert_img(im)
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生未知错误,请联系管理员检查后台输出!') await matcher.finish('发生未知错误...')
logger.info(f'[原石札记] 开始绘制,UID: {uid}')
im = await draw_note_img(uid)
if isinstance(im, str):
await matcher.finish(im)
elif isinstance(im, bytes):
await matcher.finish(MessageSegment.image(im))
else:
await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')

View File

@ -1,118 +1,140 @@
import re
import asyncio import asyncio
from typing import Union
from nonebot import get_bot from nonebot.log import logger
from hoshino.typing import CQEvent, HoshinoBot from nonebot.params import Depends
from nonebot.matcher import Matcher
from nonebot import get_bot, on_command
from nonebot_plugin_apscheduler import scheduler
from nonebot.adapters.onebot.v11 import (
MessageSegment,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger
from .notice import get_notice_list from .notice import get_notice_list
from .resin_text import get_resin_text from .resin_text import get_resin_text
from .draw_resin_card import get_resin_img from .draw_resin_card import get_resin_img
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.message.error_reply import UID_HINT from ..utils.message.error_reply import UID_HINT
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.message.get_image_and_at import ImageAndAt
from ..utils.exception.handle_exception import handle_exception
notice_scheduler = scheduler
get_resin_info = on_command(
'每日',
aliases={'mr', '状态', '实时便笺', '便笺', '便签'},
block=True,
rule=FullCommand(),
)
get_daily_info = on_command('当前状态', rule=FullCommand())
@sv.on_fullmatch('当前状态') @get_daily_info.handle()
async def send_daily_info(bot: HoshinoBot, ev: CQEvent): @handle_exception('每日信息文字版')
@register_menu(
'文字实时便笺',
'当前信息',
'米游社实时便笺文字版',
detail_des=(
'介绍:\n'
'米游社实时便笺文字版\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>当前状态</ft>'
),
)
async def send_daily_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
custom: ImageAndAt = Depends(),
):
logger.info('开始执行[每日信息文字版]') logger.info('开始执行[每日信息文字版]')
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message))
if ev.sender:
qid = ev.sender['user_id']
else:
return
at = custom.get_first_at()
qid = event.user_id
if at: if at:
qid = at.group(1) qid = at
logger.info('[每日信息文字版]QQ号: {}'.format(qid)) logger.info('[每日信息文字版]QQ号: {}'.format(qid))
uid: str = await select_db(qid, mode='uid') # type: ignore uid: str = await select_db(qid, mode='uid') # type: ignore
logger.info('[每日信息文字版]UID: {}'.format(uid)) logger.info('[每日信息文字版]UID: {}'.format(uid))
if '未找到绑定的UID' in uid: if not uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
im = await get_resin_text(uid) im = await get_resin_text(uid)
await bot.send(ev, im) await matcher.finish(im)
@sv.scheduled_job('cron', minute='*/30') @notice_scheduler.scheduled_job('cron', minute='*/30')
async def notice_job(): async def notice_job():
bot = get_bot() bot = get_bot()
result = await get_notice_list() result = await get_notice_list()
logger.info('[推送检查]完成!等待消息推送中...') logger.info('[推送检查]完成!等待消息推送中...')
# 执行私聊推送 # 执行私聊推送
bot_ids = bot._wsr_api_clients.keys()
for qid in result[0]: for qid in result[0]:
send_success = False try:
for sid in bot_ids: await bot.call_api(
try: api='send_private_msg',
await bot.send_private_msg( user_id=qid,
self_id=sid, message=result[0][qid],
user_id=qid, )
message=result[0][qid], except Exception:
)
send_success = True
break
except Exception:
logger.info(f'[推送检查(轮推)] BOT {sid} 没有 {qid} 好友,已跳过')
if not send_success:
logger.warning(f'[推送检查] QQ {qid} 私聊推送失败!') logger.warning(f'[推送检查] QQ {qid} 私聊推送失败!')
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
logger.info('[推送检查] 私聊推送完成') logger.info('[推送检查]私聊推送完成')
# 执行群聊推送 # 执行群聊推送
for group_id in result[1]: for group_id in result[1]:
send_success = False try:
for sid in bot_ids: await bot.call_api(
try: api='send_group_msg',
await bot.send_group_msg( group_id=group_id,
self_id=sid, message=result[1][group_id],
group_id=group_id, )
message=result[1][group_id], except Exception:
) logger.warning(f'[推送检查] 群 {group_id} 群聊推送失败!')
send_success = True
break
except Exception:
logger.info(f'[推送检查(轮推)] BOT {sid} 没有 {group_id} 群,已跳过')
if not send_success:
logger.warning(f'[推送检查] 群 {group_id} 推送失败!')
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
logger.info('[推送检查] 群聊推送完成') logger.info('[推送检查]群聊推送完成')
@sv.on_fullmatch(('执行推送检查任务')) @get_resin_info.handle()
async def manual_notice_job(bot: HoshinoBot, ev: CQEvent): @handle_exception('每日信息')
if ev.sender: @register_menu(
qid = int(ev.sender['user_id']) '图片实时便笺',
else: '每日',
return '图片形式米游社实时便笺',
if qid not in bot.config.SUPERUSERS: detail_des=(
return '介绍:\n'
await notice_job() '图片形式米游社实时便笺\n'
await bot.send(ev, '推送检查任务已执行') ' \n'
'指令:\n'
'- <ft color=(238,120,0)>每日</ft>\n'
@sv.on_fullmatch(('每日', 'mr', '实时便笺', '便笺', '便签')) '- <ft color=(238,120,0)>mr</ft>\n'
async def send_daily_info_pic(bot: HoshinoBot, ev: CQEvent): '- <ft color=(238,120,0)>状态</ft>\n'
'- <ft color=(125,125,125)>(实时)</ft><ft color=(238,120,0)>便笺</ft>\n'
'- <ft color=(238,120,0)>便签</ft>'
),
)
async def send_uid_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
custom: ImageAndAt = Depends(),
):
logger.info('开始执行[每日信息]') logger.info('开始执行[每日信息]')
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message))
at = custom.get_first_at()
qid = event.user_id
if at: if at:
qid = int(at.group(1)) qid = at
else:
if ev.sender:
qid = int(ev.sender['user_id'])
else:
return
logger.info('[每日信息]QQ号: {}'.format(qid)) logger.info('[每日信息]QQ号: {}'.format(qid))
im = await get_resin_img(qid) im = await get_resin_img(qid)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')

View File

@ -1,25 +1,52 @@
import asyncio import asyncio
import threading import threading
from typing import Union
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11 import (
Bot,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.exception.handle_exception import handle_exception
from ..utils.download_resource.download_all_resource import ( from ..utils.download_resource.download_all_resource import (
download_all_resource, download_all_resource,
) )
download_resource = on_command('下载全部资源', rule=FullCommand())
@sv.on_fullmatch('下载全部资源')
async def send_download_resource_msg(bot: HoshinoBot, ev: CQEvent): @download_resource.handle()
if ev.sender: @handle_exception('下载全部资源', '资源下载错误')
qid = ev.sender['user_id'] @register_menu(
else: '下载全部资源',
'下载全部资源',
'手动下载插件运行所需的资源',
trigger_method='管理员指令',
detail_des=(
'介绍:\n'
'手动下载插件正常运行所需的资源(一般每次启动会自动检查并下载)\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>下载全部资源</ft>'
),
)
async def send_download_resource_msg(
bot: Bot,
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
):
if not await SUPERUSER(bot, event):
return return
if qid not in bot.config.SUPERUSERS: await matcher.send('正在开始下载~可能需要较久的时间!')
return
await bot.send(ev, '正在开始下载~可能需要较久的时间!')
im = await download_all_resource() im = await download_all_resource()
await bot.send(ev, im) await matcher.finish(im)
async def startup(): async def startup():

View File

@ -1,27 +1,107 @@
import re import re
from typing import Union
from hoshino.typing import CQEvent, HoshinoBot from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import Depends, CommandArg
from nonebot.adapters.onebot.v11 import (
Message,
MessageSegment,
GroupMessageEvent,
PrivateMessageEvent,
)
from ..base import sv, logger
from .get_regtime import calc_reg_time from .get_regtime import calc_reg_time
from .draw_roleinfo_card import draw_pic from .draw_roleinfo_card import draw_pic
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.message.error_reply import UID_HINT from ..utils.message.error_reply import UID_HINT
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
from ..utils.mhy_api.convert_mysid_to_uid import convert_mysid from ..utils.message.get_image_and_at import ImageAndAt
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
get_role_info = on_command('uid', aliases={'查询'})
get_reg_time = on_command(
'原神注册时间', aliases={'注册时间', '查询注册时间'}, rule=FullCommand()
)
@sv.on_prefix(('原神注册时间', '注册时间')) @get_role_info.handle()
async def regtime(bot, ev): @handle_exception('查询角色信息')
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message)) @register_menu(
'查询帐号信息',
'查询',
'帐号基础数据与角色信息总览',
detail_des=(
'介绍:\n'
'查询帐号探索度、声望、宝箱收集、角色总览等等基础数据\n'
'未绑定CK时最多只能查询8个角色信息\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>{查询|uid}</ft>'
'<ft color=(125,125,125)>({@某人|[UID]})</ft>\n'
'- <ft color=(238,120,0)>mys</ft>'
'<ft color=(125,125,125)>({@某人|[米游社ID]})</ft>\n'
'- <ft color=(238,120,0)>直接发送九位数UID</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>查询</ft>\n'
'- <ft color=(238,120,0)>查询</ft><ft color=(0,123,67)>@无疑Wuyi</ft>\n'
'- <ft color=(238,120,0)>uid123456789</ft>\n'
'- <ft color=(238,120,0)>123456789</ft>'
),
)
async def send_role_info(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
args: Message = CommandArg(),
custom: ImageAndAt = Depends(),
):
raw_mes = args.extract_plain_text().strip().replace(' ', '')
name = ''.join(re.findall('[\u4e00-\u9fa5]', raw_mes))
if name:
return
qid = event.user_id
at = custom.get_first_at()
if at: if at:
qid = int(at.group(1)) qid = at
# 获取uid
uid = re.findall(r'\d+', raw_mes)
if uid:
uid = uid[0]
else: else:
if ev.sender: uid = await select_db(qid, mode='uid')
qid = int(ev.sender['user_id']) uid = str(uid)
else:
return logger.info('开始执行[查询角色信息]')
logger.info('[查询角色信息]参数: {}'.format(args))
logger.info('[查询角色信息]uid: {}'.format(uid))
if '未找到绑定的UID' in uid:
await matcher.finish(UID_HINT)
im = await draw_pic(uid)
if isinstance(im, str):
await matcher.finish(im)
elif isinstance(im, bytes):
await matcher.finish(MessageSegment.image(im))
else:
await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
@get_reg_time.handle()
async def regtime(
event: Union[GroupMessageEvent, PrivateMessageEvent],
matcher: Matcher,
custom: ImageAndAt = Depends(),
):
qid = event.user_id
at = custom.get_first_at()
if at:
qid = at
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
uid = str(uid) uid = str(uid)
@ -30,57 +110,11 @@ async def regtime(bot, ev):
logger.info('[查询注册时间]uid: {}'.format(uid)) logger.info('[查询注册时间]uid: {}'.format(uid))
if '未找到绑定的UID' in uid: if '未找到绑定的UID' in uid:
await bot.send(ev, UID_HINT) await matcher.finish(UID_HINT)
im = await calc_reg_time(uid) im = await calc_reg_time(uid)
await bot.send(ev, im)
@sv.on_rex(r'^()?()?()?([1256][0-9]{8})()?()?$')
@sv.on_rex(
r'^(\[CQ:at,qq=[0-9]+\])?( )?'
r'(uid|查询|mys)([0-9]+)?'
r'(\[CQ:at,qq=[0-9]+\])?( )?$',
)
async def send_role_info(bot: HoshinoBot, ev: CQEvent):
args = ev['match'].groups()
at = re.search(r'\[CQ:at,qq=(\d*)]', str(ev.message))
if at:
qid = int(at.group(1))
else:
if ev.sender:
qid = int(ev.sender['user_id'])
else:
return
# 判断uid
if args[2] != 'mys':
if args[3] is None:
if args[2] is None:
return
uid = await select_db(qid, mode='uid')
uid = str(uid)
elif len(args[3]) != 9:
return
else:
uid = args[3]
else:
uid = await convert_mysid(args[3])
logger.info('开始执行[查询角色信息]')
logger.info('[查询角色信息]参数: {}'.format(args))
logger.info('[查询角色信息]uid: {}'.format(uid))
if '未找到绑定的UID' in uid:
await bot.send(ev, UID_HINT)
im = await draw_pic(uid)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes):
im = await convert_img(im)
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')

View File

@ -1,51 +1,88 @@
import random import random
import asyncio
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot import get_bot, on_command
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11 import MessageEvent
from ..config import priority
try: try:
from sign import sign_in, daily_sign from sign import sign_in, daily_sign
except ImportError: except ImportError:
from .sign import sign_in, daily_sign from .sign import sign_in, daily_sign
import asyncio from nonebot_plugin_apscheduler import scheduler
from nonebot import get_bot from ..genshinuid_meta import register_menu
from hoshino.typing import CQEvent, HoshinoBot from ..utils.nonebot2.rule import FullCommand
from ..utils.exception.handle_exception import handle_exception
from ..base import sv, logger
from ..utils.db_operation.db_operation import select_db, config_check from ..utils.db_operation.db_operation import select_db, config_check
sign_scheduler = scheduler
get_sign = on_command('签到', priority=priority, rule=FullCommand())
all_recheck = on_command(
'全部重签', permission=SUPERUSER, priority=priority, rule=FullCommand()
)
# 每日零点半执行米游社原神签到 # 每日零点半执行米游社原神签到
@sv.scheduled_job('cron', hour='0', minute='30') @sign_scheduler.scheduled_job('cron', hour='0', minute='30')
async def sign_at_night(): async def sign_at_night():
if await config_check('SchedSignin'): if await config_check('SchedSignin'):
await send_daily_sign() await send_daily_sign()
# 群聊内 签到 功能 # 群聊内 签到 功能
@sv.on_rex(r'^(gs|米游社)(签到)$') @get_sign.handle()
async def get_sign_func(bot: HoshinoBot, ev: CQEvent): @handle_exception('签到')
@register_menu(
'手动米游社原神签到',
'签到',
'手动触发米游社原神签到任务',
detail_des=(
'介绍:\n'
'手动触发米游社原神签到任务\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>签到</ft>'
),
)
async def get_sign_func(
event: MessageEvent,
matcher: Matcher,
):
logger.info('开始执行[签到]') logger.info('开始执行[签到]')
qid = int(ev.sender['user_id']) # type: ignore qid = event.user_id
logger.info('[签到]QQ号: {}'.format(qid)) logger.info('[签到]QQ号: {}'.format(qid))
uid = await select_db(qid, mode='uid') uid = await select_db(qid, mode='uid')
logger.info('[签到]UID: {}'.format(uid)) logger.info('[签到]UID: {}'.format(uid))
im = await sign_in(uid) im = await sign_in(uid)
await bot.send(ev, im, at_sender=True) await matcher.finish(im, at_sender=True)
@sv.on_fullmatch('全部重签') @all_recheck.handle()
async def recheck(bot: HoshinoBot, ev: CQEvent): @handle_exception('全部重签')
if ev.sender: @register_menu(
qid = int(ev.sender['user_id']) '米游社原神重签到',
else: '全部重签',
return '重新运行所有自动米游社原神签到任务',
if qid not in bot.config.SUPERUSERS: detail_des=(
return '介绍:\n'
'重新运行所有自动米游社原神签到任务\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>全部重签</ft>'
),
)
async def recheck(matcher: Matcher):
logger.info('开始执行[全部重签]') logger.info('开始执行[全部重签]')
await bot.send(ev, '已开始执行') await matcher.send('已开始执行')
await send_daily_sign() await send_daily_sign()
await bot.send(ev, '执行完成') await matcher.finish('执行完成')
async def send_daily_sign(): async def send_daily_sign():
@ -60,7 +97,8 @@ async def send_daily_sign():
# 执行私聊推送 # 执行私聊推送
for qid in private_msg_list: for qid in private_msg_list:
try: try:
await bot.send_private_msg( await bot.call_api(
api='send_private_msg',
user_id=qid, user_id=qid,
message=private_msg_list[qid], message=private_msg_list[qid],
) )
@ -87,7 +125,8 @@ async def send_daily_sign():
msg_title = group_msg_list[gid]['push_message'] msg_title = group_msg_list[gid]['push_message']
# 发送群消息 # 发送群消息
try: try:
await bot.send_group_msg( await bot.call_api(
api='send_group_msg',
group_id=gid, group_id=gid,
message=msg_title, message=msg_title,
) )

View File

@ -1,78 +1,131 @@
from nonebot import get_bot, on_startup from typing import Any, Tuple
from hoshino.typing import CQEvent, HoshinoBot
from ..base import sv, logger from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.params import RegexGroup
from nonebot.permission import SUPERUSER
from nonebot import get_bot, on_regex, get_driver, on_command
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, MessageSegment
from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from .draw_update_log import draw_update_log_img from .draw_update_log import draw_update_log_img
from .restart import restart_message, restart_genshinuid from .restart import restart_message, restart_genshinuid
from ..utils.draw_image_tools.send_image_tool import convert_img
gs_restart = on_command('gs重启', rule=FullCommand())
get_update_log = on_command('更新记录', rule=FullCommand())
gs_update = on_regex(
r'^(gs)(强行)?(强制)?(更新)$',
block=True,
)
@on_startup driver = get_driver()
async def check_msg():
try:
logger.info('检查遗留信息...')
update_log = await restart_message()
if update_log == {}:
return
bot = get_bot()
if update_log['send_type'] == 'group':
await bot.send_group_msg(
group_id=update_log['send_to'],
message=update_log['msg'],
)
else:
await bot.send_private_msg(
user_id=update_log['send_to'],
message=update_log['msg'],
)
logger.info('遗留信息检查完毕!')
except Exception:
logger.warning('遗留信息检查失败!')
@sv.on_fullmatch('gs重启') @driver.on_bot_connect
async def send_restart_msg(bot: HoshinoBot, ev: CQEvent): async def _():
if ev.sender: logger.info('检查遗留信息...')
qid = int(ev.sender['user_id']) bot = get_bot()
else: update_log = await restart_message()
if update_log == {}:
return return
if qid not in bot.config.SUPERUSERS: if update_log['send_type'] == 'group':
await bot.call_api(
api='send_group_msg',
group_id=update_log['send_to'],
message=update_log['msg'],
)
else:
await bot.call_api(
api='send_private_msg',
user_id=update_log['send_to'],
message=update_log['msg'],
)
logger.info('遗留信息检查完毕!')
@get_update_log.handle()
@register_menu(
'更新记录',
'更新记录',
'查看插件最近的更新记录',
detail_des=(
'介绍:\n'
'查看插件最近的有效Git更新记录\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>更新记录</ft>'
),
)
async def send_updatelog_msg(
matcher: Matcher,
):
im = await draw_update_log_img(is_update=False)
logger.info('正在执行[更新记录]...')
if isinstance(im, str):
await matcher.finish(im)
elif isinstance(im, bytes):
await matcher.finish(MessageSegment.image(im))
else:
await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
@gs_restart.handle()
@register_menu(
'重启Bot',
'gs重启',
'重启Bot框架',
trigger_method='超级用户指令',
detail_des=(
'介绍:\n' '重启Bot框架\n' ' \n' '指令:\n' '- <ft color=(238,120,0)>gs重启</ft>'
),
)
async def send_restart_msg(
bot: Bot,
event: MessageEvent,
matcher: Matcher,
):
if not await SUPERUSER(bot, event):
return return
logger.warning('开始执行[重启]') logger.warning('开始执行[重启]')
qid = event.user_id
if ev.group_id: if len(event.get_session_id().split('_')) == 3:
send_id = str(ev.group_id) send_id = event.get_session_id().split('_')[1]
send_type = 'group' send_type = 'group'
else: else:
send_id = qid send_id = qid
send_type = 'private' send_type = 'private'
await bot.send(ev, '正在执行[gs重启]...') await matcher.send('正在执行[gs重启]...')
await restart_genshinuid(send_type, str(send_id)) await restart_genshinuid(send_type, str(send_id))
@sv.on_fullmatch('更新记录') @gs_update.handle()
async def send_updatelog_msg(bot: HoshinoBot, ev: CQEvent): @register_menu(
im = await draw_update_log_img(is_update=False) '更新插件',
logger.info('正在执行[更新记录]...') 'gs更新',
if isinstance(im, str): '手动更新插件',
await bot.send(ev, im) detail_des=(
elif isinstance(im, bytes): '介绍:\n'
im = await convert_img(im) '手动更新插件(执行 git pull\n'
await bot.send(ev, im) '每加上一个可选参数执行等级加1\n'
else: '当执行等级≥1时会还原上次更改等级≥2时会清空暂存\n'
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') ' \n'
'指令:\n'
'- <ft color=(238,120,0)>gs</ft>'
@sv.on_rex(r'^(gs)(强行)?(强制)?(更新)$') '<ft color=(125,125,125)>(强行)(强制)</ft>'
async def send_update_msg(bot: HoshinoBot, ev: CQEvent): '<ft color=(238,120,0)>更新</ft>'
if ev.sender: ),
qid = int(ev.sender['user_id']) )
else: async def send_update_msg(
return bot: Bot,
if qid not in bot.config.SUPERUSERS: event: MessageEvent,
matcher: Matcher,
args: Tuple[Any, ...] = RegexGroup(),
):
if not await SUPERUSER(bot, event):
return return
args = ev['match'].groups()
logger.info('[gs更新] 正在执行 ...') logger.info('[gs更新] 正在执行 ...')
level = 2 level = 2
if args[1] is None: if args[1] is None:
@ -80,12 +133,11 @@ async def send_update_msg(bot: HoshinoBot, ev: CQEvent):
if args[2] is None: if args[2] is None:
level -= 1 level -= 1
logger.info(f'[gs更新] 更新等级为{level}') logger.info(f'[gs更新] 更新等级为{level}')
await bot.send(ev, f'开始执行[gs更新], 执行等级为{level}') await matcher.send(f'开始执行[gs更新], 执行等级为{level}')
im = await draw_update_log_img(level) im = await draw_update_log_img(level)
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
elif isinstance(im, bytes): elif isinstance(im, bytes):
im = await convert_img(im) await matcher.finish(MessageSegment.image(im))
await bot.send(ev, im)
else: else:
await bot.send(ev, '发生了未知错误,请联系管理员检查后台输出!') await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')

View File

@ -8,7 +8,7 @@ from pathlib import Path
from ..utils.db_operation.db_operation import config_check from ..utils.db_operation.db_operation import config_check
bot_start = Path().cwd() / 'run.py' bot_start = Path().cwd() / 'bot.py'
restart_sh_path = Path().cwd() / 'gs_restart.sh' restart_sh_path = Path().cwd() / 'gs_restart.sh'
update_log_path = Path(__file__).parent / 'update_log.json' update_log_path = Path(__file__).parent / 'update_log.json'
@ -23,17 +23,17 @@ async def get_restart_sh(extra: str) -> str:
async def restart_genshinuid(send_type: str, send_id: str) -> None: async def restart_genshinuid(send_type: str, send_id: str) -> None:
pid = os.getpid()
extra = '' extra = ''
if await config_check('UsePoetry'): if await config_check('UsePoetry'):
extra = 'poetry run ' extra = 'poetry run '
extra += sys.executable extra += sys.executable
restart_sh = await get_restart_sh(extra) restart_sh = await get_restart_sh(extra)
with open(restart_sh_path, "w", encoding="utf8") as f: if not restart_sh_path.exists():
f.write(restart_sh) with open(restart_sh_path, "w", encoding="utf8") as f:
if platform.system() == 'Linux': f.write(restart_sh)
os.system(f'chmod +x {str(restart_sh_path)}') if platform.system() == 'Linux':
os.system(f'chmod +x {str(bot_start)}') os.system(f'chmod +x {str(restart_sh_path)}')
os.system(f'chmod +x {str(bot_start)}')
now_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) now_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
update_log = { update_log = {
'type': 'restart', 'type': 'restart',
@ -45,11 +45,9 @@ async def restart_genshinuid(send_type: str, send_id: str) -> None:
with open(str(update_log_path), 'w', encoding='utf-8') as f: with open(str(update_log_path), 'w', encoding='utf-8') as f:
json.dump(update_log, f) json.dump(update_log, f)
if platform.system() == 'Linux': if platform.system() == 'Linux':
subprocess.Popen( os.execl(str(restart_sh_path), ' ')
f'kill -9 {pid} & {extra} {bot_start}',
shell=True,
)
else: else:
pid = os.getpid()
subprocess.Popen( subprocess.Popen(
f'taskkill /F /PID {pid} & {extra} {bot_start}', f'taskkill /F /PID {pid} & {extra} {bot_start}',
shell=True, shell=True,

View File

@ -1,103 +1,229 @@
import hoshino from typing import Any, Tuple
from hoshino.typing import CQEvent, HoshinoBot
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot import on_regex, on_command
from nonebot.permission import SUPERUSER
from nonebot.params import CommandArg, RegexGroup
from nonebot.adapters.onebot.v11 import (
PRIVATE_FRIEND,
Bot,
Message,
MessageEvent,
MessageSegment,
GroupMessageEvent,
)
from .topup import topup_ from .topup import topup_
from ..base import sv, logger from ..config import priority
from .qrlogin import qrcode_login from .qrlogin import qrcode_login
from .get_ck_help_msg import get_ck_help from .get_ck_help_msg import get_ck_help
from .draw_user_card import get_user_card from .draw_user_card import get_user_card
from ..utils.draw_image_tools.send_image_tool import convert_img from ..genshinuid_meta import register_menu
from ..utils.nonebot2.rule import FullCommand
from ..utils.exception.handle_exception import handle_exception
from .add_ck import deal_ck, get_ck_by_stoken, get_ck_by_all_stoken from .add_ck import deal_ck, get_ck_by_stoken, get_ck_by_all_stoken
from ..utils.db_operation.db_operation import bind_db, delete_db, switch_db from ..utils.db_operation.db_operation import bind_db, delete_db, switch_db
hoshino_bot = hoshino.get_bot() add_cookie = on_command('添加', permission=PRIVATE_FRIEND)
get_ck_msg = on_command(
'绑定ck说明',
aliases={'ck帮助', '绑定ck'},
block=True,
rule=FullCommand(),
)
bind_info = on_command(
'绑定信息', priority=priority, block=True, rule=FullCommand()
)
refresh_ck = on_command(
'刷新CK',
aliases={'刷新ck', '刷新Ck', '刷新Cookies'},
priority=priority,
block=True,
rule=FullCommand(),
)
refresh_all_ck = on_command(
'刷新全部CK',
aliases={'刷新全部ck', '刷新全部Ck', '刷新全部Cookies'},
priority=priority,
block=True,
rule=FullCommand(),
permission=SUPERUSER,
)
bind = on_regex(
r'^(绑定|切换|解绑|删除)(uid|UID|mys|MYS)([0-9]+)?$', priority=priority
)
get_qrcode_login = on_command(
'扫码登录',
aliases={'扫码登陆', '扫码登入'},
rule=FullCommand(),
)
get_topup = on_command('gsrc', priority=priority, block=True, aliases={'原神充值'})
@sv.on_fullmatch(('刷新全部CK', '刷新全部ck', '刷新全部Ck', '刷新全部Cookies')) @get_topup.handle()
async def send_refresh_allck_msg(bot: HoshinoBot, ev: CQEvent): async def send_topup(bot: Bot, event: GroupMessageEvent):
if ev.sender: qid = event.user_id
qid = int(ev.sender['user_id']) goods_id = event.raw_message.replace('原神充值', '').replace('gsrc', '')
if goods_id == "":
goods_id = 0
else: else:
return goods_id = int(goods_id)
if qid not in bot.config.SUPERUSERS: group_id = event.group_id
return await topup_(bot, qid, group_id, goods_id)
logger.info('开始执行[刷新全部ck]')
@refresh_all_ck.handle()
async def send_refresh_all_ck_msg(
matcher: Matcher,
):
logger.info('开始执行[刷新全部CK]')
im = await get_ck_by_all_stoken() im = await get_ck_by_all_stoken()
if isinstance(im, bytes): if isinstance(im, str):
im = await convert_img(im) await matcher.finish(im)
await bot.send(ev, im) await matcher.finish(MessageSegment.image(im))
@sv.on_fullmatch(('刷新CK', '刷新ck', '刷新Ck', '刷新Cookies')) @refresh_ck.handle()
async def send_refresh_ck_msg(bot: HoshinoBot, ev: CQEvent): async def send_refresh_ck_msg(
logger.info('开始执行[刷新ck]') event: MessageEvent,
if ev.sender: matcher: Matcher,
qid = ev.sender['user_id'] ):
else: logger.info('开始执行[刷新CK]')
return qid = event.user_id
im = await get_ck_by_stoken(qid) im = await get_ck_by_stoken(qid)
if isinstance(im, bytes): if isinstance(im, str):
im = await convert_img(im) await matcher.finish(im)
await bot.send(ev, im) await matcher.finish(MessageSegment.image(im))
@sv.on_fullmatch('绑定信息') @get_qrcode_login.handle()
async def send_bind_card(bot: HoshinoBot, ev: CQEvent): async def send_qrcode_login(
logger.info('开始执行[查询用户绑定状态]') bot: Bot,
if ev.sender: event: GroupMessageEvent,
qid = ev.sender['user_id'] matcher: Matcher,
else: ):
return logger.info('开始执行[扫码登陆]')
im = await get_user_card(qid) qid = event.user_id
im = await convert_img(im) groupid = event.group_id
logger.info('[查询用户绑定状态]完成!等待图片发送中...') im = await qrcode_login(bot, groupid, qid)
await bot.send(ev, im)
@sv.on_fullmatch(('扫码登陆', '扫码登录', '扫码登入'))
async def send_qr_card(bot: HoshinoBot, ev: CQEvent):
im = await qrcode_login(hoshino_bot, ev.group_id, ev.user_id)
if not im: if not im:
return return
im = await deal_ck(im, ev.user_id) # type: ignore im = await deal_ck(im, qid)
if isinstance(im, bytes): await matcher.finish(MessageSegment.image(im))
im = await convert_img(im)
await bot.send(ev, im)
@hoshino_bot.on_message('private') # type: ignore @bind_info.handle()
async def send_add_ck_msg(ctx): @register_menu(
message = ctx['raw_message'] '绑定状态',
sid = int(ctx['self_id']) '绑定信息',
userid = int(ctx['sender']['user_id']) '查询你绑定UID的绑定和推送状态',
gid = 0 detail_des=(
if message.startswith('添加'): '介绍:\n'
message = message.replace('添加', '').replace(' ', '') '查询你绑定的UID列表以及它们的CK、SK绑定状态和推送设置\n'
im = await deal_ck(message, userid) # type: ignore ' \n'
else: '指令:\n'
return '- <ft color=(238,120,0)>绑定信息</ft>'
if isinstance(im, bytes): ),
im = await convert_img(im) )
await hoshino_bot.send_msg( async def send_bind_card(
self_id=sid, user_id=userid, group_id=gid, message=im event: MessageEvent,
) matcher: Matcher,
):
logger.info('开始执行[查询用户绑定状态]')
qid = event.user_id
im = await get_user_card(qid)
logger.info('[查询用户绑定状态]完成!等待图片发送中...')
await matcher.finish(MessageSegment.image(im))
@add_cookie.handle()
@handle_exception('Cookie', '校验失败请输入正确的Cookies')
@register_menu(
'绑定CK、SK',
'添加[CK或SK]',
'绑定你的Cookies以及Stoken',
trigger_method='好友私聊指令',
detail_des=(
'介绍:\n'
'绑定你的Cookies以及Stoken\n'
'Cookies (CK)米游社CookiesStoken (SK)米哈游通行证Cookies\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>添加</ft><ft color=(0,148,200)>[CK或SK]</ft>'
),
)
async def send_add_ck_msg(
event: MessageEvent, matcher: Matcher, args: Message = CommandArg()
):
mes = args.extract_plain_text().strip().replace(' ', '')
qid = event.user_id
im = await deal_ck(mes, qid)
if isinstance(im, str):
await matcher.finish(im)
await matcher.finish(MessageSegment.image(im))
# 群聊内 绑定uid或者mysid 的命令会绑定至当前qq号上 # 群聊内 绑定uid或者mysid 的命令会绑定至当前qq号上
@sv.on_rex(r'^(绑定|切换|解绑|删除)(uid|UID|mys|MYS)([0-9]+)?$') @bind.handle()
async def send_link_uid_msg(bot: HoshinoBot, ev: CQEvent): @handle_exception('绑定ID', '绑定ID异常')
args = ev['match'].groups() @register_menu(
'绑定UID',
'绑定xx',
'绑定原神UID或米游社UID',
detail_des=(
'介绍:\n'
'绑定原神UID或米游社UID\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>绑定'
'{uid</ft><ft color=(0,148,200)>[原神UID]</ft>'
'<ft color=(238,120,0)>|mys</ft><ft color=(0,148,200)>[米游社UID]</ft>'
'<ft color=(238,120,0)>}</ft>'
),
)
@register_menu(
'解绑UID',
'解绑xx',
'解绑原神UID或米游社UID',
detail_des=(
'介绍:\n'
'解绑原神UID或米游社UID\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>{解绑|删除}'
'{uid</ft><ft color=(0,148,200)>[原神UID]</ft>'
'<ft color=(238,120,0)>|mys</ft><ft color=(0,148,200)>[米游社UID]</ft>'
'<ft color=(238,120,0)>}</ft>'
),
)
@register_menu(
'切换UID',
'切换xx',
'切换当前原神UID或米游社UID',
detail_des=(
'介绍:\n'
'切换当前原神UID或米游社UID\n'
'绑定一个UID的情况下无法切换\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>切换'
'{uid</ft><ft color=(0,148,200)>[原神UID]</ft>'
'<ft color=(238,120,0)>|mys</ft><ft color=(0,148,200)>[米游社UID]</ft>'
'<ft color=(238,120,0)>}</ft>'
),
)
async def send_link_uid_msg(
event: MessageEvent, matcher: Matcher, args: Tuple[Any, ...] = RegexGroup()
):
logger.info('开始执行[绑定/解绑用户信息]') logger.info('开始执行[绑定/解绑用户信息]')
logger.info('[绑定/解绑]参数: {}'.format(str(args))) logger.info('[绑定/解绑]参数: {}'.format(args))
if ev.sender: qid = event.user_id
qid = ev.sender['user_id']
else:
return
logger.info('[绑定/解绑]UserID: {}'.format(qid)) logger.info('[绑定/解绑]UserID: {}'.format(qid))
if args[0] in ('绑定'): if args[0] in ('绑定'):
if args[2] is None: if args[2] is None:
await bot.send(ev, '请输入正确的uid或者mysid') await matcher.finish('请输入正确的uid或者mysid')
if args[1] in ('uid', 'UID'): if args[1] in ('uid', 'UID'):
im = await bind_db(qid, args[2]) im = await bind_db(qid, args[2])
@ -110,11 +236,11 @@ async def send_link_uid_msg(bot: HoshinoBot, ev: CQEvent):
im = await delete_db(qid, {'UID': args[2]}) im = await delete_db(qid, {'UID': args[2]})
else: else:
im = await delete_db(qid, {'MYSID': args[2]}) im = await delete_db(qid, {'MYSID': args[2]})
await bot.send(ev, im, at_sender=True) await matcher.finish(im, at_sender=True)
@sv.on_fullmatch(('绑定ck说明', 'ck帮助', '绑定ck')) @get_ck_msg.handle()
async def send_ck_msg(bot: HoshinoBot, ev: CQEvent): async def send_ck_help(bot: Bot, event: GroupMessageEvent):
msg_list = await get_ck_help() msg_list = await get_ck_help()
forward_msg = [] forward_msg = []
for msg in msg_list: for msg in msg_list:
@ -124,18 +250,6 @@ async def send_ck_msg(bot: HoshinoBot, ev: CQEvent):
"data": {"name": "小冰", "uin": "2854196306", "content": msg}, "data": {"name": "小冰", "uin": "2854196306", "content": msg},
} }
) )
await bot.send_group_forward_msg( await bot.call_api(
group_id=ev.group_id, messages=forward_msg 'send_group_forward_msg', group_id=event.group_id, messages=forward_msg
) )
@sv.on_prefix(("gsrc", "原神充值"))
async def topup(bot: HoshinoBot, ev: CQEvent):
qid = ev.user_id
goods_id = ev.message.extract_plain_text()
if goods_id == "":
goods_id = 0
else:
goods_id = int(goods_id)
group_id = ev.group_id
await topup_(bot, qid, group_id, goods_id)

View File

@ -7,6 +7,7 @@ from typing import Any, Tuple, Union, Literal
import qrcode import qrcode
from nonebot.log import logger from nonebot.log import logger
from qrcode.constants import ERROR_CORRECT_L
from ..utils.message.send_msg import send_forward_msg from ..utils.message.send_msg import send_forward_msg
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
@ -30,15 +31,15 @@ disnote = '''免责声明:您将通过扫码完成获取米游社sk以及ck。
def get_qrcode_base64(url): def get_qrcode_base64(url):
qr = qrcode.QRCode( qr = qrcode.QRCode(
version=1, version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L, error_correction=ERROR_CORRECT_L,
box_size=10, box_size=10,
border=4, border=4,
) )
qr.add_data(url) qr.add_data(url)
qr.make(fit=True) qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white") img = qr.make_image(fill_color='black', back_color='white')
img_byte = io.BytesIO() img_byte = io.BytesIO()
img.save(img_byte, format="PNG") img.save(img_byte, format='PNG') # type: ignore
img_byte = img_byte.getvalue() img_byte = img_byte.getvalue()
return base64.b64encode(img_byte).decode() return base64.b64encode(img_byte).decode()
@ -50,50 +51,57 @@ async def refresh(
while True: while True:
await asyncio.sleep(2) await asyncio.sleep(2)
status_data = await check_qrcode( status_data = await check_qrcode(
code_data["app_id"], code_data["ticket"], code_data["device"] code_data['app_id'], code_data['ticket'], code_data['device']
) )
if status_data["retcode"] != 0: if status_data['retcode'] != 0:
logger.warn("二维码已过期") logger.warning('二维码已过期')
return False, None return False, None
if status_data["data"]["stat"] == "Scanned": if status_data['data']['stat'] == 'Scanned':
if not scanned: if not scanned:
logger.info("二维码已扫描") logger.info('二维码已扫描')
scanned = True scanned = True
continue continue
if status_data["data"]["stat"] == "Confirmed": if status_data['data']['stat'] == 'Confirmed':
logger.info("二维码已确认") logger.info('二维码已确认')
# print(status_data["data"]["payload"]["raw"]) # print(status_data['data']['payload']['raw'])
break break
return True, json.loads(status_data["data"]["payload"]["raw"]) return True, json.loads(status_data['data']['payload']['raw'])
async def qrcode_login(bot, group_id, user_id) -> str: async def qrcode_login(bot, group_id, user_id) -> str:
async def send_group_msg(msg: str): async def send_group_msg(msg: str):
await bot.call_action( await bot.call_api(
action='send_group_msg', api='send_group_msg',
group_id=group_id, group_id=group_id,
message=msg, message=msg,
) )
return "" return ''
code_data = await create_qrcode_url() code_data = await create_qrcode_url()
try: try:
im = [] im = []
qrc = f'[CQ:image,file=base64://{get_qrcode_base64(code_data["url"])}]'
im.append('请使用米游社扫描下方二维码登录:') im.append('请使用米游社扫描下方二维码登录:')
im.append(qrc) im.append(
im.append(disnote) f'[CQ:image,file=base64://{get_qrcode_base64(code_data["url"])}]'
)
im.append(
'免责声明:您将通过扫码完成获取米游社sk以及ck。\n'
'本Bot将不会保存您的登录状态。\n'
'我方仅提供米游社查询及相关游戏内容服务,\n'
'若您的账号封禁、被盗等处罚与我方无关。\n'
'害怕风险请勿扫码~'
)
await send_forward_msg(bot, group_id, "扫码小助手", str(user_id), im) await send_forward_msg(bot, group_id, "扫码小助手", str(user_id), im)
except Exception: except Exception:
logger.warn(f"[扫码登录] {group_id} 图片发送失败") logger.warning(f'[扫码登录] {user_id} 图片发送失败')
status, game_token_data = await refresh(code_data) status, game_token_data = await refresh(code_data)
if status: if status:
assert game_token_data is not None # 骗过 pyright assert game_token_data is not None # 骗过 pyright
logger.info("game_token获取成功") logger.info('game_token获取成功')
cookie_token = await get_cookie_token(**game_token_data) cookie_token = await get_cookie_token(**game_token_data)
stoken_data = await get_stoken_by_game_token( stoken_data = await get_stoken_by_game_token(
account_id=int(game_token_data["uid"]), account_id=int(game_token_data['uid']),
game_token=game_token_data["token"], game_token=game_token_data['token'],
) )
account_id = game_token_data['uid'] account_id = game_token_data['uid']
stoken = stoken_data['data']['token']['token'] stoken = stoken_data['data']['token']['token']
@ -116,6 +124,7 @@ async def qrcode_login(bot, group_id, user_id) -> str:
else: else:
im = '请求失败, 请稍后再试...' im = '请求失败, 请稍后再试...'
return await send_group_msg(im) return await send_group_msg(im)
uid_bind = await select_db(user_id, mode='uid') uid_bind = await select_db(user_id, mode='uid')
# 没有在gsuid绑定uid的情况 # 没有在gsuid绑定uid的情况
if uid_bind == "未找到绑定的UID~": if uid_bind == "未找到绑定的UID~":

View File

@ -5,6 +5,7 @@ import traceback
import qrcode import qrcode
from nonebot.log import logger from nonebot.log import logger
from qrcode.constants import ERROR_CORRECT_L
from ..utils.message.send_msg import send_forward_msg from ..utils.message.send_msg import send_forward_msg
from ..utils.db_operation.db_operation import select_db from ..utils.db_operation.db_operation import select_db
@ -19,7 +20,7 @@ disnote = '''免责声明:
def get_qrcode_base64(url): def get_qrcode_base64(url):
qr = qrcode.QRCode( qr = qrcode.QRCode(
version=1, version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L, error_correction=ERROR_CORRECT_L,
box_size=10, box_size=10,
border=4, border=4,
) )
@ -27,7 +28,7 @@ def get_qrcode_base64(url):
qr.make(fit=True) qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white") img = qr.make_image(fill_color="black", back_color="white")
img_byte = io.BytesIO() img_byte = io.BytesIO()
img.save(img_byte, format="PNG") img.save(img_byte, format="PNG") # type: ignore
img_byte = img_byte.getvalue() img_byte = img_byte.getvalue()
return base64.b64encode(img_byte).decode() return base64.b64encode(img_byte).decode()
@ -48,12 +49,12 @@ async def refresh(order, uid):
async def topup_(bot, qid, group_id, goods_id): async def topup_(bot, qid, group_id, goods_id):
async def send_group_msg(msg: str): async def send_group_msg(msg: str):
await bot.call_action( await bot.call_api(
action='send_group_msg', api='send_group_msg',
group_id=group_id, group_id=group_id,
message=msg, message=msg,
) )
return "" return ''
uid = await select_db(qid, mode="uid") uid = await select_db(qid, mode="uid")
if uid is None: if uid is None:
@ -69,7 +70,7 @@ async def topup_(bot, qid, group_id, goods_id):
order = await topup(uid, goods_data) order = await topup(uid, goods_data)
except Exception: except Exception:
await send_group_msg("出错了,可能是cookie过期或接口出错") await send_group_msg("出错了,可能是cookie过期或接口出错")
logger.warn(f"[充值] {group_id} {qid}") logger.warning(f"[充值] {group_id} {qid}")
return return
try: try:
im = [] im = []
@ -88,5 +89,5 @@ async def topup_(bot, qid, group_id, goods_id):
await send_forward_msg(bot, group_id, "小助手", str(qid), im) await send_forward_msg(bot, group_id, "小助手", str(qid), im)
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
logger.warn(f"[充值] {group_id} 图片发送失败") logger.warning(f"[充值] {group_id} 图片发送失败")
await send_group_msg(await refresh(order, uid)) await send_group_msg(await refresh(order, uid))

View File

@ -1,10 +1,11 @@
from sqlmodel import SQLModel from sqlmodel import SQLModel
from nonebot import get_driver
from nonebot.log import logger from nonebot.log import logger
from nonebot import get_bot, on_startup
from ..utils.db_operation.db_operation import config_check from ..utils.db_operation.db_operation import config_check
config = get_bot().config driver = get_driver()
config = driver.config
async def run_webconsole(): async def run_webconsole():
@ -16,22 +17,28 @@ async def run_webconsole():
user_auth_i18n.set_language('zh_CN') user_auth_i18n.set_language('zh_CN')
# 导入app # 导入app
from .mount_app import auth, site try:
from .mount_app import auth, site
except RuntimeError:
logger.warning("当前 Driver 非 ReverseDriverWebConsole 已禁用")
return
logger.info('尝试挂载WebConsole') logger.info('尝试挂载WebConsole')
await site.db.async_run_sync( await site.db.async_run_sync(
SQLModel.metadata.create_all, is_session=False # type: ignore SQLModel.metadata.create_all, is_session=False # type: ignore
) )
# 创建默认测试用户, 请及时修改密码!!! # 创建默认测试用户, 请及时修改密码!!!
await auth.create_role_user() await auth.create_role_user()
logger.info( logger.opt(colors=True).info(
('WebConsole挂载成功' f'http://{config.HOST}:{config.PORT}/genshinuid') (
'WebConsole挂载成功'
f'<blue>http://{config.host}:{config.port}/genshinuid</blue>'
)
) )
@on_startup @driver.on_startup
async def start_check(): async def start_check():
if await config_check('OpenWeb'): if await config_check('OpenWeb'):
await run_webconsole() await run_webconsole()

View File

@ -1,146 +1,146 @@
import fastapi_amis_admin import fastapi_amis_admin
from fastapi import Request from fastapi import Request
from fastapi_user_auth import admin as user_auth_admin from nonebot.typing import overrides
from fastapi_amis_admin.admin import admin as amis_admin from fastapi_user_auth import admin as user_auth_admin
from fastapi_amis_admin.utils.translation import i18n as _ from fastapi_amis_admin.admin import admin as amis_admin
from fastapi_amis_admin.amis.constants import LevelEnum, DisplayModeEnum from fastapi_amis_admin.utils.translation import i18n as _
from fastapi_amis_admin.amis.components import ( from fastapi_amis_admin.amis.constants import LevelEnum, DisplayModeEnum
App, from fastapi_amis_admin.amis.components import (
Tpl, App,
Form, Tpl,
Grid, Form,
Html, Grid,
Page, Html,
Action, Page,
ActionType, Action,
Horizontal, ActionType,
ButtonToolbar, Horizontal,
) ButtonToolbar,
)
from .nb2 import overrides
from ..version import GenshinUID_version from ..version import GenshinUID_version
login_html = ''' login_html = '''
<p align='center'> <p align='center'>
<a href='https://github.com/KimigaiiWuyi/GenshinUID/'> <a href='https://github.com/KimigaiiWuyi/GenshinUID/'>
<img src='https://s2.loli.net/2022/01/31/kwCIl3cF1Z2GxnR.png' <img src='https://s2.loli.net/2022/01/31/kwCIl3cF1Z2GxnR.png'
width='256' height='256' alt='GenshinUID'> width='256' height='256' alt='GenshinUID'>
</a> </a>
</p> </p>
<h1 align='center'>GenshinUID 3.1 WebConsole</h1> <h1 align='center'>GenshinUID 3.1 WebConsole</h1>
<h4 align='center'> <h4 align='center'>
✨基于 ✨基于
<a href='https://github.com/Ice-Cirno/HoshinoBot' target='_blank'> <a href='https://github.com/Ice-Cirno/HoshinoBot' target='_blank'>
HoshinoBot HoshinoBot
</a> </a>
/ /
<a href='https://github.com/nonebot/nonebot2' target='_blank'>NoneBot2</a> <a href='https://github.com/nonebot/nonebot2' target='_blank'>NoneBot2</a>
/ /
<a href='https://bot.q.qq.com/wiki/#' target='_blank'>QQ官方频道Bot</a> <a href='https://bot.q.qq.com/wiki/#' target='_blank'>QQ官方频道Bot</a>
的原神多功能插件✨ 的原神多功能插件✨
</h4> </h4>
<div align='center'> <div align='center'>
<a href='https://github.com/KimigaiiWuyi/GenshinUID/wiki' target='_blank'> <a href='https://github.com/KimigaiiWuyi/GenshinUID/wiki' target='_blank'>
安装文档</a> &nbsp; · &nbsp; 安装文档</a> &nbsp; · &nbsp;
<a href='https://github.com/KimigaiiWuyi/GenshinUID/wiki/File5-「指令列表」' <a href='https://github.com/KimigaiiWuyi/GenshinUID/wiki/File5-「指令列表」'
target='_blank'>指令列表</a> &nbsp; · &nbsp; target='_blank'>指令列表</a> &nbsp; · &nbsp;
<a href='https://github.com/KimigaiiWuyi/GenshinUID/issues/226'>常见问题</a> <a href='https://github.com/KimigaiiWuyi/GenshinUID/issues/226'>常见问题</a>
</div> </div>
''' '''
footer_html = f''' footer_html = f'''
<p align='right'> <p align='right'>
<div class='p-2 text-center bg-light'>Copyright © 2021 - 2022 <div class='p-2 text-center bg-light'>Copyright © 2021 - 2022
<a href='https://github.com/KimigaiiWuyi/GenshinUID' target='_blank' <a href='https://github.com/KimigaiiWuyi/GenshinUID' target='_blank'
class='link-secondary'>GenshinUID {GenshinUID_version} class='link-secondary'>GenshinUID {GenshinUID_version}
</a> </a>
X X
<a target='_blank' <a target='_blank'
href='https://github.com/amisadmin/fastapi_amis_admin/' href='https://github.com/amisadmin/fastapi_amis_admin/'
class='link-secondary' rel='noopener'> class='link-secondary' rel='noopener'>
fastapi_amis_admin {fastapi_amis_admin.__version__} fastapi_amis_admin {fastapi_amis_admin.__version__}
</a> </a>
</div> </div>
</p> </p>
''' '''
# 还原高版本的注册按钮丢失 # 还原高版本的注册按钮丢失
@overrides(user_auth_admin.UserLoginFormAdmin) @overrides(user_auth_admin.UserLoginFormAdmin)
async def get_form(self, request: Request) -> Form: async def get_form(self, request: Request) -> Form:
form = await super(user_auth_admin.UserLoginFormAdmin, self).get_form( form = await super(user_auth_admin.UserLoginFormAdmin, self).get_form(
request request
) )
form.body.sort( form.body.sort(
key=lambda form_item: form_item.type, reverse=True # type: ignore key=lambda form_item: form_item.type, reverse=True # type: ignore
) )
form.update_from_kwargs( form.update_from_kwargs(
title='', title='',
mode=DisplayModeEnum.horizontal, mode=DisplayModeEnum.horizontal,
submitText=_('Sign in'), submitText=_('Sign in'),
actionsClassName='no-border m-none p-none', actionsClassName='no-border m-none p-none',
panelClassName='', panelClassName='',
wrapWithPanel=True, wrapWithPanel=True,
horizontal=Horizontal(left=3, right=9), horizontal=Horizontal(left=3, right=9),
actions=[ actions=[
ButtonToolbar( ButtonToolbar(
buttons=[ buttons=[
ActionType.Link( ActionType.Link(
actionType='link', actionType='link',
link=f'{self.router_path}/reg', link=f'{self.router_path}/reg',
label=_('Sign up'), label=_('Sign up'),
), ),
Action( Action(
actionType='submit', actionType='submit',
label=_('Sign in'), label=_('Sign in'),
level=LevelEnum.primary, level=LevelEnum.primary,
), ),
] ]
) )
], ],
) )
form.redirect = request.query_params.get('redirect') or '/genshinuid' form.redirect = request.query_params.get('redirect') or '/genshinuid'
return form return form
@overrides(user_auth_admin) @overrides(user_auth_admin)
def attach_page_head(page: Page) -> Page: def attach_page_head(page: Page) -> Page:
page.body = [ page.body = [
Html(html=login_html), Html(html=login_html),
Grid( Grid(
columns=[ columns=[
{'body': [page.body], 'lg': 2, 'md': 4, 'valign': 'middle'} {'body': [page.body], 'lg': 3, 'md': 4, 'valign': 'middle'}
], ],
align='center', align='center',
valign='middle', valign='middle',
), ),
] ]
return page return page
@overrides(amis_admin.AdminApp) @overrides(amis_admin.AdminApp)
async def _get_page_as_app(self, request: Request) -> App: async def _get_page_as_app(self, request: Request) -> App:
app = App() app = App()
app.brandName = self.site.settings.site_title app.brandName = self.site.settings.site_title
app.header = Tpl( app.header = Tpl(
className='w-full', className='w-full',
tpl=''' tpl='''
<div class='flex justify-between'> <div class='flex justify-between'>
<div> <div>
<a href='https://github.com/KimigaiiWuyi/GenshinUID' <a href='https://github.com/KimigaiiWuyi/GenshinUID'
target='_blank' title='Copyright'> target='_blank' title='Copyright'>
<i class='fa fa-github fa-2x'></i> <i class='fa fa-github fa-2x'></i>
</a> </a>
</div> </div>
</div> </div>
''', ''',
) # type: ignore ) # type: ignore
app.footer = footer_html app.footer = footer_html
children = await self.get_page_schema_children(request) children = await self.get_page_schema_children(request)
app.pages = [{'children': children}] if children else [] # type: ignore app.pages = [{'children': children}] if children else [] # type: ignore
return app return app
amis_admin.AdminApp._get_page_as_app = _get_page_as_app amis_admin.AdminApp._get_page_as_app = _get_page_as_app
user_auth_admin.attach_page_head = attach_page_head user_auth_admin.attach_page_head = attach_page_head
user_auth_admin.UserLoginFormAdmin.get_form = get_form user_auth_admin.UserLoginFormAdmin.get_form = get_form

View File

@ -1,15 +1,24 @@
# flake8: noqa # flake8: noqa
import platform import platform
import contextlib
from pathlib import Path from pathlib import Path
from typing import Any, Set, Dict, List, Callable from typing import (
TYPE_CHECKING,
Any,
Set,
List,
Union,
Callable,
Optional,
cast,
)
from quart import Quart import fastapi_amis_admin
from nonebot import get_bot
from pydantic import BaseModel from pydantic import BaseModel
from sqlmodel import Relationship from sqlmodel import Relationship
from sqlalchemy.orm import backref from sqlalchemy.orm import backref
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
import fastapi_amis_admin # noqa: F401 from nonebot import get_app, get_driver
from fastapi_amis_admin import amis, admin from fastapi_amis_admin import amis, admin
from fastapi_amis_admin.crud import BaseApiOut from fastapi_amis_admin.crud import BaseApiOut
from sqlalchemy.ext.asyncio import AsyncEngine from sqlalchemy.ext.asyncio import AsyncEngine
@ -40,8 +49,8 @@ from fastapi_amis_admin.amis.components import (
from ..version import GenshinUID_version from ..version import GenshinUID_version
from ..genshinuid_user.add_ck import _deal_ck from ..genshinuid_user.add_ck import _deal_ck
from .login_page import amis_admin, user_auth_admin # noqa
from ..utils.db_operation.database.db_config import DATABASE_URL from ..utils.db_operation.database.db_config import DATABASE_URL
from .login_page import amis_admin, user_auth_admin # noqa # 不要删
from ..utils.db_operation.database.models import ( from ..utils.db_operation.database.models import (
Config, Config,
UidData, UidData,
@ -50,21 +59,32 @@ from ..utils.db_operation.database.models import (
NewCookiesTable, NewCookiesTable,
) )
if TYPE_CHECKING:
from quart import Quart
from asgiref.typing import Scope, HTTPScope, WebSocketScope
AppType = Union[FastAPI, 'Quart']
class FastApiMiddleware: class FastApiMiddleware:
def __init__(self, app: Quart, fastapi: FastAPI, routes: Set[str]) -> None: def __init__(
self, app: 'Quart', fastapi: FastAPI, routes: Set[str]
) -> None:
self.fastapi = fastapi self.fastapi = fastapi
self.app = app.asgi_app self.app = app.asgi_app
self.routes = routes self.routes = routes
async def __call__( async def __call__(
self, scope: Dict[str, Any], receive: Callable, send: Callable self, scope: 'Scope', receive: Callable, send: Callable
) -> None: ) -> None:
if scope['type'] in ('http', 'websocket'): if scope['type'] in ('http', 'websocket'):
scope = cast(Union['HTTPScope', 'WebSocketScope'], scope)
for path in self.routes: for path in self.routes:
if scope['path'].startswith(path): if scope['path'].startswith(path):
return await self.fastapi(scope, receive, send) return await self.fastapi(
return await self.app(scope, receive, send) scope, receive, send # type: ignore
)
return await self.app(scope, receive, send) # type: ignore
# 自定义后台管理站点 # 自定义后台管理站点
@ -89,8 +109,28 @@ class GenshinUIDAdminSite(AuthAdminSite):
return app return app
# 创建FastAPI应用 def get_asgi() -> Optional[AppType]:
app = FastAPI() try:
return get_app()
except AssertionError:
return None
# 从 nb 获取 FastAPI
app = get_asgi()
if app is None:
raise RuntimeError('App is not ReverseDriver')
with contextlib.suppress(ImportError):
from quart import Quart # noqa: F811
if isinstance(app, Quart):
fastapi = FastAPI()
app.asgi_app = FastApiMiddleware(app, fastapi, {'/genshinuid'}) # type: ignore
app = fastapi
app = cast(FastAPI, app)
settings = Settings( settings = Settings(
database_url_async=DATABASE_URL, database_url_async=DATABASE_URL,
database_url='', database_url='',
@ -99,8 +139,6 @@ settings = Settings(
site_title='GenshinUID网页控制台', site_title='GenshinUID网页控制台',
language='zh_CN', language='zh_CN',
) )
quart = get_bot().server_app
quart.asgi_app = FastApiMiddleware(quart, app, {'/genshinuid'}) # type: ignore
# 显示主键 # 显示主键
@ -152,16 +190,13 @@ admin.BaseModelAdmin.get_create_form = patched_get_create_form
# 创建AdminSite实例 # 创建AdminSite实例
site = GenshinUIDAdminSite(settings) site = GenshinUIDAdminSite(settings)
auth = site.auth auth = site.auth
config = get_bot().config
if float(fastapi_amis_admin.__version__[:3]) >= 0.3: if float(fastapi_amis_admin.__version__[:3]) >= 0.3:
class MyUser(User, table=True): class MyUser(User, table=True):
point: float = Field(default=0, title=_('Point')) # type: ignore point: float = Field(default=0, title=_('Point')) # type: ignore
phone: str = Field(None, title=_('Tel'), max_length=15) # type: ignore phone: str = Field(None, title=_('Tel'), max_length=15) # type: ignore
parent_id: int = Field( parent_id: int = Field(None, title=_('Parent'), foreign_key='auth_user.id') # type: ignore
None, title=_('Parent'), foreign_key='auth_user.id' # type: ignore
)
children: List['User'] = Relationship( children: List['User'] = Relationship(
sa_relationship_kwargs=dict( sa_relationship_kwargs=dict(
backref=backref('parent', remote_side='User.id'), backref=backref('parent', remote_side='User.id'),
@ -170,9 +205,10 @@ if float(fastapi_amis_admin.__version__[:3]) >= 0.3:
auth.user_model = MyUser auth.user_model = MyUser
config = get_driver().config
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=[f'http://{config.HOST}:{config.PORT}/genshinuid'], allow_origins=[f'http://{config.host}:{config.port}'],
allow_credentials=True, allow_credentials=True,
allow_methods=['*'], allow_methods=['*'],
allow_headers=['*'], allow_headers=['*'],
@ -180,12 +216,17 @@ app.add_middleware(
gsuid_webconsole_help = ''' gsuid_webconsole_help = '''
## 初次使用 ## 初次使用
欢迎进入网页控制台! 欢迎进入网页控制台!
Admin账户可以通过左侧的选项进入不同的数据库直接修改,**首次登陆的Admin账户别忘了修改你的密码!** Admin账户可以通过左侧的选项进入不同的数据库直接修改,**首次登陆的Admin账户别忘了修改你的密码!**
普通账户可以通过左侧的选项进行绑定CK或者SK 普通账户可以通过左侧的选项进行绑定CK或者SK
未来还会加入更多功能! 未来还会加入更多功能!
## 丨我该如何获取Cookies[#92](https://github.com/KimigaiiWuyi/GenshinUID/issues/92)[@RemKeeper](https://github.com/RemKeeper) ## 丨我该如何获取Cookies[#92](https://github.com/KimigaiiWuyi/GenshinUID/issues/92)[@RemKeeper](https://github.com/RemKeeper)
```js ```js
var cookie = document.cookie; var cookie = document.cookie;
var Str_Num = cookie.indexOf('_MHYUUID='); var Str_Num = cookie.indexOf('_MHYUUID=');
@ -198,12 +239,16 @@ if (ask == true) {
msg = 'Cancel' msg = 'Cancel'
} }
``` ```
1. 复制上面全部代码,然后打开[米游社BBS](https://bbs.mihoyo.com/ys/) 1. 复制上面全部代码,然后打开[米游社BBS](https://bbs.mihoyo.com/ys/)
2. 在页面上右键检查或者Ctrl+Shift+i 2. 在页面上右键检查或者Ctrl+Shift+i
3. 选择控制台Console粘贴回车在弹出的窗口点确认点完自动复制 3. 选择控制台Console粘贴回车在弹出的窗口点确认点完自动复制
4. 然后在和机器人的私聊窗口,粘贴发送即可 4. 然后在和机器人的私聊窗口,粘贴发送即可
**警告Cookies属于个人隐私其效用相当于账号密码请勿随意公开** **警告Cookies属于个人隐私其效用相当于账号密码请勿随意公开**
## 丨获取米游社Stoken([AutoMihoyoBBS](https://github.com/Womsxd/AutoMihoyoBBS#%E8%8E%B7%E5%8F%96%E7%B1%B3%E6%B8%B8%E7%A4%BECookie)) ## 丨获取米游社Stoken([AutoMihoyoBBS](https://github.com/Womsxd/AutoMihoyoBBS#%E8%8E%B7%E5%8F%96%E7%B1%B3%E6%B8%B8%E7%A4%BECookie))
```js ```js
var cookie = document.cookie; var cookie = document.cookie;
var ask = confirm('Cookie:' + cookie + '按确认然后粘贴至Cookies或者Login_ticket选框内'); var ask = confirm('Cookie:' + cookie + '按确认然后粘贴至Cookies或者Login_ticket选框内');
@ -214,10 +259,12 @@ if (ask == true) {
msg = 'Cancel' msg = 'Cancel'
} }
``` ```
1. 复制上面全部代码,然后打开[米游社账户登录界面](http://user.mihoyo.com/) 1. 复制上面全部代码,然后打开[米游社账户登录界面](http://user.mihoyo.com/)
2. 在页面上右键检查或者Ctrl+Shift+i 2. 在页面上右键检查或者Ctrl+Shift+i
3. 选择控制台Console粘贴回车在弹出的窗口点确认点完自动复制 3. 选择控制台Console粘贴回车在弹出的窗口点确认点完自动复制
4. 然后在和机器人的私聊窗口,粘贴发送即可 4. 然后在和机器人的私聊窗口,粘贴发送即可
**警告Cookies属于个人隐私其效用相当于账号密码请勿随意公开** **警告Cookies属于个人隐私其效用相当于账号密码请勿随意公开**
## 获取CK通则 ## 获取CK通则

View File

@ -1,15 +0,0 @@
from typing import TypeVar, Callable
T_Wrapped = TypeVar("T_Wrapped", bound=Callable)
def overrides(InterfaceClass: object) -> Callable[[T_Wrapped], T_Wrapped]:
"""标记一个方法为父类 interface 的 implement"""
def overrider(func: T_Wrapped) -> T_Wrapped:
assert func.__name__ in dir(
InterfaceClass
), f"Error method: {func.__name__}"
return func
return overrider

View File

@ -1,9 +1,18 @@
import re import re
from nonebot import MessageSegment from nonebot import on_command
from hoshino.typing import CQEvent, HoshinoBot from nonebot.matcher import Matcher
from nonebot.params import CommandArg
from nonebot.adapters.onebot.v11 import (
Bot,
Message,
MessageSegment,
GroupMessageEvent,
)
from ..base import sv from ..config import priority
from ..genshinuid_meta import register_menu
from ..utils.exception.handle_exception import handle_exception
from .get_wiki_text import ( from .get_wiki_text import (
char_wiki, char_wiki,
audio_wiki, audio_wiki,
@ -13,149 +22,251 @@ from .get_wiki_text import (
artifacts_wiki, artifacts_wiki,
) )
get_weapon = on_command('武器', priority=priority)
get_char = on_command('角色', priority=priority)
get_cost = on_command('材料', priority=priority)
get_polar = on_command('命座', priority=priority)
get_talents = on_command('天赋', priority=priority)
get_enemies = on_command('原魔', priority=priority)
get_audio = on_command('语音', priority=priority)
get_artifacts = on_command('圣遗物', priority=priority)
get_food = on_command('食物', priority=priority)
@sv.on_prefix('语音')
async def send_audio(bot: HoshinoBot, ev: CQEvent):
if ev.message:
message = ev.message.extract_plain_text().replace(' ', '')
else:
return
if message == '':
return
@get_audio.handle()
@handle_exception('语音', '语音发送失败可能是FFmpeg环境未配置。')
@register_menu(
'角色语音',
'语音[ID]',
'获取角色语音',
detail_des=(
'介绍:\n'
'获取角色语音\n'
'获取语言ID列表请使用指令 <ft color=(238,120,0)>语音列表</ft>\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>语音{列表|</ft>'
'<ft color=(0,148,200)>[语音ID]</ft>'
'<ft color=(238,120,0)>}</ft>'
),
)
async def send_audio(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
name = ''.join(re.findall('[\u4e00-\u9fa5]', message)) name = ''.join(re.findall('[\u4e00-\u9fa5]', message))
im = await audio_wiki(name, message) im = await audio_wiki(name, message)
if name == '列表': if name == '列表':
await bot.send(ev, MessageSegment.image(im)) await matcher.finish(MessageSegment.image(im))
else: else:
if isinstance(im, str): if isinstance(im, str):
await bot.send(ev, im) await matcher.finish(im)
else: else:
await bot.send(ev, MessageSegment.record(im)) await matcher.finish(MessageSegment.record(im))
@sv.on_prefix('原魔') @get_enemies.handle()
async def send_enemies(bot: HoshinoBot, ev: CQEvent): @handle_exception('怪物')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '怪物图鉴',
else: '怪物xx',
return '获取怪物Wiki',
if message == '': detail_des=(
return '介绍:\n'
'获取怪物Wiki\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>怪物</ft><ft color=(0,148,200)>[怪物名称]</ft>'
),
)
async def send_enemies(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
im = await enemies_wiki(message) im = await enemies_wiki(message)
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('食物') @get_food.handle()
async def send_food(bot: HoshinoBot, ev: CQEvent): @handle_exception('食物')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '食物图鉴',
else: '食物xx',
return '获取食物Wiki',
if message == '': detail_des=(
return '介绍:\n'
'获取食物Wiki\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>食物</ft><ft color=(0,148,200)>[食物名称]</ft>'
),
)
async def send_food(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
im = await foods_wiki(message) im = await foods_wiki(message)
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('圣遗物') @get_artifacts.handle()
async def send_artifacts(bot: HoshinoBot, ev: CQEvent): @handle_exception('圣遗物')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '圣遗物图鉴',
else: '圣遗物xx',
return '获取怪物Wiki',
if message == '': detail_des=(
return '介绍:\n'
'获取圣遗物Wiki\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>圣遗物</ft><ft color=(0,148,200)>[圣遗物名称]</ft>'
),
)
async def send_artifacts(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
im = await artifacts_wiki(message) im = await artifacts_wiki(message)
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('武器') @get_weapon.handle()
async def send_weapon(bot: HoshinoBot, ev: CQEvent): @handle_exception('武器')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '武器图鉴',
else: '武器xx',
return '获取武器Wiki',
if message == '': detail_des=(
return '介绍:\n'
'获取武器Wiki\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>武器</ft><ft color=(0,148,200)>[武器名称]</ft>'
'<ft color=(125,125,125)>(级数)</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>武器雾切</ft>\n'
'- <ft color=(238,120,0)>武器无工之剑90</ft>'
),
)
async def send_weapon(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
name = ''.join(re.findall('[\u4e00-\u9fa5]', message)) name = ''.join(re.findall('[\u4e00-\u9fa5]', message))
level = re.findall(r'\d+', message) level = re.findall(r'\d+', message)
if len(level) == 1: if len(level) == 1:
im = await weapon_wiki(name, level=level[0]) im = await weapon_wiki(name, level=level[0])
else: else:
im = await weapon_wiki(name) im = await weapon_wiki(name)
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('天赋') @get_talents.handle()
async def send_talents(bot: HoshinoBot, ev: CQEvent): @handle_exception('天赋')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '天赋效果',
else: '天赋[角色][天赋序号]',
return '查询角色天赋技能效果',
if message == '': detail_des=(
return '介绍:\n'
'查询角色天赋技能效果\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>天赋</ft>'
'<ft color=(0,148,200)>[角色名称][天赋序号]</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>天赋绫华2</ft>'
),
)
async def send_talents(
bot: Bot,
event: GroupMessageEvent,
matcher: Matcher,
args: Message = CommandArg(),
):
message = args.extract_plain_text().strip().replace(' ', '')
name = ''.join(re.findall('[\u4e00-\u9fa5]', message)) name = ''.join(re.findall('[\u4e00-\u9fa5]', message))
num = re.findall(r'\d+', message) num = re.findall(r'\d+', message)
if len(num) == 1: if len(num) == 1:
im = await char_wiki(name, 'talents', num[0]) im = await char_wiki(name, 'talents', num[0])
if isinstance(im, list): if isinstance(im, list):
await bot.send_group_forward_msg(group_id=ev.group_id, messages=im) await bot.call_api(
'send_group_forward_msg', group_id=event.group_id, messages=im
)
await matcher.finish()
return return
else: else:
im = '参数不正确。' im = '参数不正确。'
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('角色') @get_char.handle()
async def send_char(bot: HoshinoBot, ev: CQEvent): @handle_exception('角色')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '角色图鉴',
else: '角色xx',
return '获取角色Wiki',
if message == '': detail_des=(
return '介绍:\n'
'获取角色Wiki\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>角色</ft><ft color=(0,148,200)>[角色名称]</ft>'
'<ft color=(125,125,125)>(等级)</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>角色可莉</ft>\n'
'- <ft color=(238,120,0)>角色可莉90</ft>'
),
)
async def send_char(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
name = ''.join(re.findall('[\u4e00-\u9fa5]', message)) name = ''.join(re.findall('[\u4e00-\u9fa5]', message))
level = re.findall(r'\d+', message) level = re.findall(r'\d+', message)
if len(level) == 1: if len(level) == 1:
im = await char_wiki(name, 'char', level=level[0]) im = await char_wiki(name, 'char', level=level[0])
else: else:
im = await char_wiki(name) im = await char_wiki(name)
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('材料') @get_cost.handle()
async def send_cost(bot: HoshinoBot, ev: CQEvent): @handle_exception('材料')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '材料图鉴',
else: '材料xx',
return '获取材料Wiki',
if message == '': detail_des=(
return '介绍:\n'
'获取材料Wiki\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>材料</ft><ft color=(0,148,200)>[材料名称]</ft>'
),
)
async def send_cost(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
im = await char_wiki(message, 'costs') im = await char_wiki(message, 'costs')
await bot.send(ev, im) await matcher.finish(im)
@sv.on_prefix('命座') @get_polar.handle()
async def send_polar(bot: HoshinoBot, ev: CQEvent): @handle_exception('命座')
if ev.message: @register_menu(
message = ev.message.extract_plain_text().replace(' ', '') '角色命座图鉴',
else: '命座[角色][等级]',
return '获取角色命座Wiki',
if message == '': detail_des=(
return '介绍:\n'
'获取角色命座Wiki\n'
' \n'
'指令:\n'
'- <ft color=(238,120,0)>命座</ft>'
'<ft color=(0,148,200)>[角色名称][命座等级]</ft>\n'
' \n'
'示例:\n'
'- <ft color=(238,120,0)>命座胡桃1</ft>'
),
)
async def send_polar(matcher: Matcher, args: Message = CommandArg()):
message = args.extract_plain_text().strip().replace(' ', '')
num = int(re.findall(r'\d+', message)[0]) # str num = int(re.findall(r'\d+', message)[0]) # str
m = ''.join(re.findall('[\u4e00-\u9fa5]', message)) m = ''.join(re.findall('[\u4e00-\u9fa5]', message))
if num <= 0 or num > 6: if num <= 0 or num > 6:
await bot.send(ev, '你家{}{}命?'.format(m, num)) await get_polar.finish('你家{}{}命?'.format(m, num))
return return
im = await char_wiki(m, 'constellations', num) im = await char_wiki(m, 'constellations', num)
await bot.send(ev, im) await matcher.finish(im)

View File

@ -2,22 +2,34 @@ import random
import asyncio import asyncio
import threading import threading
from ..base import sv, logger from nonebot import on_command
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot_plugin_apscheduler import scheduler
from nonebot.adapters.onebot.v11 import MessageSegment
from .draw_abyss_total import TOTAL_IMG, draw_xk_abyss_img from .draw_abyss_total import TOTAL_IMG, draw_xk_abyss_img
from ..utils.draw_image_tools.send_image_tool import convert_img from ..utils.exception.handle_exception import handle_exception
draw_total_scheduler = scheduler
get_abyss_total = on_command('深渊概览', aliases={'深渊统计', '深渊使用率'})
@sv.scheduled_job('interval', hours=3) @draw_total_scheduler.scheduled_job('interval', hours=3)
async def scheduled_draw_abyss(): async def scheduled_draw_abyss():
await asyncio.sleep(random.randint(0, 60)) await asyncio.sleep(random.randint(0, 60))
await draw_xk_abyss_img() await draw_xk_abyss_img()
@sv.on_fullmatch(('深渊概览', '深渊统计', '深渊使用率')) @get_abyss_total.handle()
async def send_abyss_pic(bot, ev): @handle_exception('深渊概览')
img = await convert_img(TOTAL_IMG) async def send_guide_pic(matcher: Matcher):
logger.info('获得gs帮助图片成功') if TOTAL_IMG.exists():
await bot.send(ev, img) logger.info('获得深渊概览成功!')
with open(TOTAL_IMG, 'rb') as f:
await matcher.finish(MessageSegment.image(f.read()))
else:
await matcher.finish('深渊概览图不存在!')
threading.Thread( threading.Thread(

View File

@ -27,7 +27,9 @@ async def check_db():
try: try:
if int(str(row[0])[0]) < 6: if int(str(row[0])[0]) < 6:
aid = re.search(r'account_id=(\d*)', row[1]) aid = re.search(r'account_id=(\d*)', row[1])
mihoyo_id_data = aid.group(0).split('=') # type: ignore if not aid:
raise Exception('cannot match account_id')
mihoyo_id_data = aid.group(0).split('=')
mihoyo_id = mihoyo_id_data[1] mihoyo_id = mihoyo_id_data[1]
mys_data = await get_mihoyo_bbs_info(mihoyo_id, row[1]) mys_data = await get_mihoyo_bbs_info(mihoyo_id, row[1])
for i in mys_data['data']['list']: for i in mys_data['data']['list']:

View File

@ -1,9 +1,7 @@
import sys import sys
from pathlib import Path from pathlib import Path
import hoshino MAIN_PATH = Path() / 'data' / 'GenshinUID'
MAIN_PATH = Path(hoshino.config.RES_DIR) / 'GenshinUID'
sys.path.append(str(MAIN_PATH)) sys.path.append(str(MAIN_PATH))
CONFIG_PATH = MAIN_PATH / 'config.json' CONFIG_PATH = MAIN_PATH / 'config.json'
RESOURCE_PATH = MAIN_PATH / 'resource' RESOURCE_PATH = MAIN_PATH / 'resource'

View File

@ -1,53 +1,63 @@
# flake8: noqa from functools import wraps
# from nonebot.log import logger from typing import Optional
# from aiocqhttp.exceptions import ActionFailed
# from hoshino.typing import List, CQEvent, Iterable
# FIXME: - 在 Hoshino 中可用 from nonebot.log import logger
# def handle_exception(name: str, log_msg: str = None, fail_msg: str = None): # type: ignore from nonebot.matcher import Matcher
# """ from nonebot.exception import FinishedException
# :说明: from nonebot.adapters.onebot.v11 import ActionFailed
# 捕获命令执行过程中发生的异常并回报。
# :参数:
# * ``name: str``: 项目的名称。
# * ``log_msg: str = None``: 自定义捕获异常后在日志中留存的信息。留空则使用默认信息。
# * ``fail_msg: str = None``: 自定义捕获异常后向用户回报的信息,仅在提供自定义日志信息时有效。开头带@则艾特用户。留空则与日志信息相同。
# """
# def wrapper(func):
# @wraps(func)
# async def inner(
# log_msg: str = log_msg, fail_msg: str = fail_msg, **kwargs
# ):
# print(kwargs)
# matcher: CQEvent = kwargs['matcher']
# try:
# await func(**kwargs)
# except ActionFailed as e:
# # 此为bot本身由于风控或网络问题发不出消息并非代码本身出问题
# await matcher.send(f'发送消息失败{e.result["wording"]}')
# logger.exception(f'发送{name}消息失败')
# except Exception as e:
# # 如果e内包含敏感信息应在此处进行处理
# if 'SQL' in str(e):
# e = '数据库操作失败!可能正在[校验全部Cookies]\n敏感信息已抹去...请等待一段时间后重试!'
# # 代码本身出问题
# if log_msg:
# if not fail_msg:
# fail_msg = log_msg
# if fail_msg[0] == '@':
# await matcher.send(
# f'{fail_msg[1:]}\n错误信息为{e}', at_sender=True
# )
# else:
# await matcher.send(f'{fail_msg}\n错误信息为{e}')
# if log_msg[0] == '@':
# log_msg = log_msg[1:]
# logger.exception(log_msg)
# else:
# await matcher.send(f'发生错误 {e},请检查后台输出。')
# logger.exception(f'获取{name}信息错误')
# return inner def handle_exception(
name: str, log_msg: Optional[str] = None, fail_msg: Optional[str] = None
):
"""
:说明:
捕获命令执行过程中发生的异常并回报。
:参数:
* ``name: str``: 项目的名称。
* ``log_msg: str = None``: 自定义捕获异常后在日志中留存的信息。留空则使用默认信息。
* ``fail_msg: str = None``: 自定义捕获异常后向用户回报的信息,仅在提供自定义日志信息时有效。
开头带@则艾特用户。留空则与日志信息相同。
"""
# return wrapper def wrapper(func):
@wraps(func)
async def inner(
log_msg: Optional[str] = log_msg,
fail_msg: Optional[str] = fail_msg,
**kwargs,
):
matcher: Matcher = kwargs['matcher']
try:
await func(**kwargs)
except ActionFailed as e:
# 此为bot本身由于风控或网络问题发不出消息并非代码本身出问题
await matcher.send(f'发送消息失败{e.info["wording"]}')
logger.exception(f'发送{name}消息失败')
except FinishedException:
# `finish` 会抛出此异常,应予以抛出而不处理
raise
except Exception as e:
# 如果e内包含敏感信息应在此处进行处理
if 'SQL' in str(e):
e = '数据库操作失败!可能正在[校验全部Cookies]\n敏感信息已抹去...请等待一段时间后重试!'
# 代码本身出问题
if log_msg:
if not fail_msg:
fail_msg = log_msg
if fail_msg[0] == '@':
await matcher.send(
f'{fail_msg[1:]}\n错误信息为{e}', at_sender=True
)
else:
await matcher.send(f'{fail_msg}\n错误信息为{e}')
if log_msg[0] == '@':
log_msg = log_msg[1:]
logger.exception(log_msg)
else:
await matcher.send(f'发生错误 {e},请检查后台输出。')
logger.exception(f'获取{name}信息错误')
return inner
return wrapper

View File

@ -1,18 +1,20 @@
from typing import List from typing import List
from nonebot.adapters.onebot.v11 import Bot
async def get_all_friend_list(bot) -> List[int]:
async def get_all_friend_list(bot: Bot) -> List[int]:
friend_list = [] friend_list = []
friend_dict_list = await bot.call_action(action='get_friend_list') friend_dict_list = await bot.call_api('get_friend_list')
for friend in friend_dict_list: for friend in friend_dict_list:
friend_list.append(friend['user_id']) friend_list.append(friend['user_id'])
return friend_list return friend_list
async def get_group_member_list(bot, group_id: int) -> List[int]: async def get_group_member_list(bot: Bot, group_id: int) -> List[int]:
member_list = [] member_list = []
group_member_list = await bot.call_api( group_member_list = await bot.call_api(
action='get_group_member_list', group_id=group_id 'get_group_member_list', group_id=group_id
) )
for group_member in group_member_list: for group_member in group_member_list:
member_list.append(group_member['user_id']) member_list.append(group_member['user_id'])

View File

@ -1,9 +1,11 @@
from typing import Union from typing import Union
from nonebot.adapters.onebot.v11 import MessageEvent
# https://v2.nonebot.dev/docs/advanced/di/dependency-injection#class-%E4%BD%9C%E4%B8%BA%E4%BE%9D%E8%B5%96 # https://v2.nonebot.dev/docs/advanced/di/dependency-injection#class-%E4%BD%9C%E4%B8%BA%E4%BE%9D%E8%B5%96
class ImageAndAt: class ImageAndAt:
def __init__(self, event): def __init__(self, event: MessageEvent):
self.images = [] self.images = []
self.at = [] self.at = []
for i in event.message: for i in event.message:

View File

@ -1,12 +1,12 @@
from typing import List from typing import List
from ...base import hoshino_bot from nonebot.adapters.onebot.v11 import Bot
# 发送聊天记录 # 发送聊天记录
async def send_forward_msg( async def send_forward_msg(
bot: hoshino_bot, bot: Bot,
group_id: int, groupid: int,
name: str, name: str,
uin: str, uin: str,
msgs: List[str], msgs: List[str],
@ -18,6 +18,6 @@ async def send_forward_msg(
} }
messages = [to_json(msg) for msg in msgs] messages = [to_json(msg) for msg in msgs]
await bot.call_action( await bot.call_api(
action='send_group_forward_msg', group_id=group_id, messages=messages "send_group_forward_msg", group_id=groupid, messages=messages
) )

View File

@ -0,0 +1,15 @@
from nonebot.rule import Rule
from nonebot.params import Depends, CommandArg
from nonebot.adapters.onebot.v11 import Message
async def full_command(arg: Message = CommandArg()) -> bool:
return not bool(str(arg))
def FullCommand() -> Rule:
return Rule(full_command)
def FullCommandDepend():
return Depends(full_command)

View File

@ -0,0 +1,15 @@
from typing import List
from nonebot import get_driver
def get_superusers() -> List[int]:
config = get_driver().config
superusers: List[int] = []
for su in config.superusers:
if "onebot:" in su:
# su[7:] == onebot:
su = su[7:]
if su.isdigit():
superusers.append(int(su))
return superusers

View File

@ -3,11 +3,11 @@ import shutil
from typing import List from typing import List
from pathlib import Path from pathlib import Path
import hoshino
from nonebot.log import logger from nonebot.log import logger
from nonebot import load_plugins from nonebot import require, load_plugins
dir_ = Path(__file__).parent dir_ = Path(__file__).parent
require('nonebot_plugin_apscheduler')
def copy_and_delete_files(): def copy_and_delete_files():
@ -27,7 +27,7 @@ def copy_and_delete_files():
elif path.name in {"resource", "player"}: elif path.name in {"resource", "player"}:
dst = Path().joinpath( dst = Path().joinpath(
( (
hoshino.config.RES_DIR + "/GenshinUID/" "data/GenshinUID/"
f"{'players' if path.name == 'player' else path.name}" f"{'players' if path.name == 'player' else path.name}"
) )
) )
@ -37,7 +37,7 @@ def copy_and_delete_files():
dst, dst,
dirs_exist_ok=True, dirs_exist_ok=True,
) )
logger.info(f"复制文件夹 {path} -> {dst} 成功") logger.success(f"复制文件夹 {path} -> {dst} 成功")
except shutil.Error as e: except shutil.Error as e:
failed_src: List[Path] = [] failed_src: List[Path] = []
exc: str exc: str
@ -56,10 +56,10 @@ def copy_and_delete_files():
else: else:
try: try:
shutil.rmtree(path) shutil.rmtree(path)
logger.info(f"删除文件夹 {path} 成功") logger.success(f"删除文件夹 {path} 成功")
except OSError as e: except OSError as e:
logger.warning(f"删除文件夹 {path} 失败:{e.strerror}") logger.warning(f"删除文件夹 {path} 失败:{e.strerror}")
copy_and_delete_files() copy_and_delete_files()
load_plugins(str(dir_ / 'GenshinUID'), 'hoshino.modules.GenshinUID.GenshinUID') load_plugins(str(dir_ / "GenshinUID"))

14
deploy/.env.dev Normal file
View File

@ -0,0 +1,14 @@
# 配置 NoneBot2 监听的 IP/主机名(不建议修改)
HOST=0.0.0.0
# 配置 NoneBot2 监听的端口(不建议修改)
PORT=8080
# 配置 NoneBot 超级用户例如你的QQ号
SUPERUSERS=["123456789"]
# 配置命令起始字符
COMMAND_START=["/", ""]
# 建议别删下面这行
FASTAPI_RELOAD=false
# 建议别删上面这行
更多配置参见https://v2.nonebot.dev/docs/tutorial/configuration

14
deploy/cookiecutter.yml Normal file
View File

@ -0,0 +1,14 @@
default_context:
py: py
project_name: nb2
use_src: true
adapters:
- builtin:
- module_name: "nonebot.adapters.onebot.v11"
project_link: "nonebot-adapter-onebot"
name: "OneBot V11"
desc: "OneBot V11 协议"
author: "yanyongyu"
homepage: "https://onebot.adapters.nonebot.dev/"
tags: []
is_official: true

View File

@ -0,0 +1,21 @@
from typing import List
import tomlkit
def main():
with open("./nb2/pyproject.toml", "r", encoding="utf-8") as f:
data = tomlkit.load(f)
plugins: List[str] = data["tool"]["nonebot"]["plugins"] # type: ignore
if "GenshinUID" in plugins:
return
plugins.append("GenshinUID")
with open("./nb2/pyproject.toml", "w", encoding="utf-8") as f:
tomlkit.dump(data, f)
print("Update pyproject.toml done.")
if __name__ == "__main__":
main()

1824
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,3 @@
[tool.poetry]
name = "GenshinUID"
version = "0.1.0"
description = "基于HoshinoBot/NoneBot2/QQ官方频道Bot(PythonSDK)的原神Uid查询/原神Wiki/米社签到/树脂提醒插件"
authors = ["KimigaiiWuyi <444835641@qq.com>"]
license = "GPL-3.0-or-later"
[tool.poetry.dependencies]
python = "^3.8"
httpx = "^0.23.0"
beautifulsoup4 = "^4.11.1"
lxml = "^4.9.1"
openpyxl = "^3.0.10"
aiohttp = "^3.8.1"
SQLAlchemy = "^1.4.39"
Pillow = "^9.2.0"
aiosqlite = "^0.17.0"
sqlmodel = "^0.0.8"
GitPython = "^3.1.27"
fastapi_amis_admin = "^0.2.1"
fastapi_user_auth = "^0.2.1"
pydantic = "^1.10.2"
aiofiles = "^22.1.0"
qrcode = {extras = ["pil"], version = "^7.3.1"}
[tool.poetry.dev-dependencies]
flake8 = "^4.0.1"
black = "^22.6.0"
isort = "^5.11.5"
pre-commit = "^2.20.0"
[tool.black] [tool.black]
line-length = 79 line-length = 79
target-version = ["py38", "py39", "py310"] target-version = ["py38", "py39", "py310"]
@ -45,10 +14,65 @@ skip_gitignore = true
force_sort_within_sections = true force_sort_within_sections = true
extra_standard_library = ["typing_extensions"] extra_standard_library = ["typing_extensions"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.2.0"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "GenshinUID"
version = "3.1.0"
description = "基于HoshinoBot/NoneBot2/QQ官方频道/微信Bot的原神面板查询/原神Wiki/米社签到/树脂提醒插件"
authors = ["KimigaiiWuyi <444835641@qq.com>"]
license = "GPL-3.0-or-later"
readme = "README.md"
homepage = "https://github.com/KimigaiiWuyi/GenshinUID/tree/nonebot2-beta1"
repository = "https://github.com/KimigaiiWuyi/GenshinUID"
documentation = "https://github.com/KimigaiiWuyi/GenshinUID/wiki"
packages = [
{ include = "GenshinUID" }
]
exclude = ["tests", "deploy"]
[tool.poetry.urls]
"Bug Tracker" = "https://github.com/KimigaiiWuyi/GenshinUID/issues"
[tool.poetry.dependencies]
python = "^3.8.1"
nonebot2 = ">=2.0.0b4"
nonebot-adapter-onebot = ">=2.1.1"
httpx = ">=0.23.0"
beautifulsoup4 = ">=4.11.1"
lxml = ">=4.9.2"
openpyxl = ">=3.0.10"
aiohttp = ">=3.8.1"
sqlalchemy = ">=1.4.39"
pillow = ">=9.2.0"
aiosqlite = ">=0.17.0"
nonebot-plugin-apscheduler = ">=0.1.4"
aiofiles = ">=0.8.0"
sqlmodel = ">=0.0.8"
gitpython = ">=3.1.27"
fastapi-amis-admin = ">=0.2.1"
fastapi-user-auth = ">=0.2.1"
qrcode = {extras = ["pil"], version = "^7.3.1"}
[[tool.poetry.source]] [[tool.poetry.source]]
name = 'aliyun.mirrors' name = "USTC"
url = "http://mirrors.aliyun.com/pypi/simple/" url = "https://pypi.mirrors.ustc.edu.cn/simple"
default = false
secondary = true
[tool.poetry.group.dev.dependencies]
flake8 = "^6.0.0"
black = "^22.12.0"
isort = "^5.11.5"
pre-commit = "^2.21.0"
pycln = "^2.1.2"
[tool.poetry.group.test.dependencies]
nonebug = "^0.3.0"
pytest = "^7.2.0"
pytest-asyncio = "^0.20.3"

View File

@ -1,50 +1,65 @@
--trusted-host mirrors.aliyun.com aiofiles==23.1.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
--extra-index-url http://mirrors.aliyun.com/pypi/simple aiohttp==3.8.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
aiosignal==1.3.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
aiofiles==22.1.0 ; python_version >= "3.8" and python_version < "4.0" aiosqlite==0.18.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
aiohttp==3.8.3 ; python_version >= "3.8" and python_version < "4.0" anyio==3.6.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
aiosignal==1.3.1 ; python_version >= "3.8" and python_version < "4.0" apscheduler==3.10.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
aiosqlite==0.17.0 ; python_version >= "3.8" and python_version < "4.0" async-timeout==4.0.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
anyio==3.6.2 ; python_version >= "3.8" and python_version < "4.0" attrs==22.2.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
async-timeout==4.0.2 ; python_version >= "3.8" and python_version < "4.0" backports-zoneinfo==0.2.1 ; python_full_version >= "3.8.1" and python_version < "3.9"
attrs==22.2.0 ; python_version >= "3.8" and python_version < "4.0" bcrypt==4.0.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
bcrypt==4.0.1 ; python_version >= "3.8" and python_version < "4.0" beautifulsoup4==4.11.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
beautifulsoup4==4.11.1 ; python_version >= "3.8" and python_version < "4.0" certifi==2022.12.7 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
certifi==2022.12.7 ; python_version >= "3.8" and python_version < "4.0" charset-normalizer==3.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
charset-normalizer==2.1.1 ; python_version >= "3.8" and python_version < "4.0" colorama==0.4.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" and platform_system == "Windows" or python_full_version >= "3.8.1" and python_version < "4.0" and sys_platform == "win32"
colorama==0.4.6 ; python_version >= "3.8" and python_version < "4.0" and platform_system == "Windows" dnspython==2.3.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
dnspython==2.2.1 ; python_version >= "3.8" and python_version < "4.0" email-validator==1.3.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
email-validator==1.3.0 ; python_version >= "3.8" and python_version < "4.0" et-xmlfile==1.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
et-xmlfile==1.1.0 ; python_version >= "3.8" and python_version < "4.0" fastapi-amis-admin==0.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-amis-admin==0.2.5 ; python_version >= "3.8" and python_version < "4.0" fastapi-user-auth==0.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-user-auth==0.2.4 ; python_version >= "3.8" and python_version < "4.0" fastapi==0.93.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi==0.88.0 ; python_version >= "3.8" and python_version < "4.0" frozenlist==1.3.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
frozenlist==1.3.3 ; python_version >= "3.8" and python_version < "4.0" gitdb==4.0.10 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
gitdb==4.0.10 ; python_version >= "3.8" and python_version < "4.0" gitpython==3.1.31 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
gitpython==3.1.30 ; python_version >= "3.8" and python_version < "4.0" greenlet==2.0.2 ; python_full_version >= "3.8.1" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_full_version < "4.0.0"
greenlet==2.0.1 ; python_version >= "3.8" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_version < "4.0" h11==0.14.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
h11==0.14.0 ; python_version >= "3.8" and python_version < "4.0" httpcore==0.16.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
httpcore==0.16.3 ; python_version >= "3.8" and python_version < "4.0" httpx==0.23.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
httpx==0.23.1 ; python_version >= "3.8" and python_version < "4.0" idna==3.4 ; python_full_version >= "3.8.1" and python_version < "4.0"
idna==3.4 ; python_version >= "3.8" and python_version < "4.0" loguru==0.6.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
lxml==4.9.2 ; python_version >= "3.8" and python_version < "4.0" lxml==4.9.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
multidict==6.0.4 ; python_version >= "3.8" and python_version < "4.0" msgpack==1.0.5 ; python_full_version >= "3.8.1" and python_version < "4.0"
openpyxl==3.0.10 ; python_version >= "3.8" and python_version < "4.0" multidict==6.0.4 ; python_full_version >= "3.8.1" and python_version < "4.0"
passlib==1.7.4 ; python_version >= "3.8" and python_version < "4.0" nonebot-adapter-onebot==2.2.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
pillow==9.3.0 ; python_version >= "3.8" and python_version < "4.0" nonebot-plugin-apscheduler==0.2.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
pydantic==1.10.4 ; python_version >= "3.8" and python_version < "4.0" nonebot2==2.0.0rc3 ; python_full_version >= "3.8.1" and python_version < "4.0"
python-multipart==0.0.5 ; python_version >= "3.8" and python_version < "4.0" openpyxl==3.1.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
qrcode[pil]==7.3.1 ; python_version >= "3.8" and python_version < "4.0" passlib==1.7.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
rfc3986[idna2008]==1.5.0 ; python_version >= "3.8" and python_version < "4.0" pillow==9.4.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
six==1.16.0 ; python_version >= "3.8" and python_version < "4.0" pydantic==1.10.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
smmap==5.0.0 ; python_version >= "3.8" and python_version < "4.0" pydantic[dotenv]==1.10.6 ; python_full_version >= "3.8.1" and python_version < "4.0"
sniffio==1.3.0 ; python_version >= "3.8" and python_version < "4.0" pygtrie==2.5.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
soupsieve==2.3.2.post1 ; python_version >= "3.8" and python_version < "4.0" pypng==0.20220715.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy-database==0.0.11 ; python_version >= "3.8" and python_version < "4.0" python-dotenv==1.0.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
sqlalchemy2-stubs==0.0.2a31 ; python_version >= "3.8" and python_version < "4.0" python-multipart==0.0.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy==1.4.41 ; python_version >= "3.8" and python_version < "4.0" pytz-deprecation-shim==0.1.0.post0 ; python_full_version >= "3.8.1" and python_version < "4.0"
sqlmodel==0.0.8 ; python_version >= "3.8" and python_version < "4.0" pytz==2022.7.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
sqlmodelx==0.0.4 ; python_version >= "3.8" and python_version < "4.0" qrcode[pil]==7.4.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
starlette==0.22.0 ; python_version >= "3.8" and python_version < "4.0" rfc3986[idna2008]==1.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
typing-extensions==4.4.0 ; python_version >= "3.8" and python_version < "4.0" setuptools==67.6.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
yarl==1.8.2 ; python_version >= "3.8" and python_version < "4.0" six==1.16.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
smmap==5.0.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sniffio==1.3.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
soupsieve==2.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy-database==0.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy2-stubs==0.0.2a32 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy==1.4.41 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlmodel==0.0.8 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlmodelx==0.0.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
starlette==0.25.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
tomlkit==0.11.6 ; python_full_version >= "3.8.1" and python_version < "4.0"
typing-extensions==4.5.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
tzdata==2022.7 ; python_full_version >= "3.8.1" and python_version < "4.0"
tzlocal==4.2 ; python_full_version >= "3.8.1" and python_version < "4.0"
win32-setctime==1.1.0 ; python_full_version >= "3.8.1" and python_version < "4.0" and sys_platform == "win32"
yarl==1.8.2 ; python_full_version >= "3.8.1" and python_version < "4.0"

1
tests/.env Normal file
View File

@ -0,0 +1 @@
ENVIRONMENT=test

5
tests/.env.test Normal file
View File

@ -0,0 +1,5 @@
LOG_LEVEL=TRACE
NICKNAME=["test"]
SUPERUSERS=["onebot:10000","10001","other:10002","abcdef"]
COMMAND_START=["", "/"]
DRIVER="~none"

23
tests/conftest.py Normal file
View File

@ -0,0 +1,23 @@
import pytest
import nonebot
from nonebug import NONEBOT_INIT_KWARGS
from nonebot.adapters.onebot.v11 import Adapter
PLUGINS = ["meta", "adv", "etcimg", "guide"]
@pytest.fixture(scope="session", autouse=True)
def load_bot():
driver = nonebot.get_driver()
driver.register_adapter(Adapter)
nonebot.load_all_plugins(
[f"GenshinUID.genshinuid_{name}" for name in PLUGINS], []
)
def pytest_configure(config: pytest.Config):
config.stash[NONEBOT_INIT_KWARGS] = {
"genshinuid_disabled_plugins": {"xkdata", "abyss", "adv"},
"genshinuid_priority": 5,
}

31
tests/test_adv.py Normal file
View File

@ -0,0 +1,31 @@
import pytest
from nonebug import App
MESSAGE = """「安柏」
-=-=-=-=-=-=-=-=-=-
推荐5★武器阿莫斯之弓、天空之翼、终末嗟叹之诗
推荐4★武器绝弦
推荐圣遗物搭配:
[昔日宗室之仪]四件套
-=-=-=-=-=-=-=-=-=-
备注:
原神御三家之一,必胜客联动看板角色之一;
身份西风骑士团侦查骑士,蒙德飞行冠军,柏菈图的拼图(误);
人送外号解谜点火真君/打火姬
通常情况下,安柏的大世界解谜意义大于其深渊实战意义,建议根据实际需求选择投入资源培养"""
@pytest.mark.asyncio
@pytest.mark.parametrize(argnames="alias", argvalues=["安柏用什么", "安柏怎么养"])
async def test_adv_char_chat(app: App, alias):
from utils import make_event
from nonebot.adapters.onebot.v11 import Bot, Message
from GenshinUID.genshinuid_adv import get_char_adv
async with app.test_matcher(get_char_adv) as ctx:
bot = ctx.create_bot(base=Bot)
event = make_event(message=Message(alias))
ctx.receive_event(bot, event)
ctx.should_call_send(event, MESSAGE, True)
ctx.should_finished()

8
tests/test_base.py Normal file
View File

@ -0,0 +1,8 @@
from nonebug import App
def test_config(app: App):
from GenshinUID import config
assert config.config.disabled_plugins == {"xkdata", "abyss", "adv"}
assert config.priority == 5

121
tests/test_etc.py Normal file
View File

@ -0,0 +1,121 @@
from pathlib import Path
import pytest
from nonebug import App
@pytest.mark.asyncio
@pytest.mark.parametrize(argnames="alias", argvalues=["版本规划", "原石预估"])
async def test_get_primogems_data(app: App, alias):
from utils import make_event
from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
from GenshinUID.version import Genshin_version
from GenshinUID.genshinuid_etcimg import get_primogems_data
with open(
Path(
(
"../GenshinUID/genshinuid_etcimg"
f"/primogems_data/{Genshin_version[:3]}.png"
)
),
"rb",
) as f:
data = f.read()
async with app.test_matcher(get_primogems_data) as ctx:
bot = ctx.create_bot(base=Bot)
event = make_event(message=Message(alias))
ctx.receive_event(bot, event)
ctx.should_call_send(
event,
MessageSegment.image(data),
True,
)
ctx.should_finished()
@pytest.mark.asyncio
async def test_primogems_version(app: App):
from utils import make_event
from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
from GenshinUID.version import Genshin_version
from GenshinUID.genshinuid_etcimg import get_primogems_data
with open(
Path(
(
"../GenshinUID/genshinuid_etcimg"
f"/primogems_data/{Genshin_version[:3]}.png"
)
),
"rb",
) as f:
data = f.read()
async with app.test_matcher(get_primogems_data) as ctx:
bot = ctx.create_bot(base=Bot)
event = make_event(message=Message(f"版本规划{Genshin_version[:3]}"))
ctx.receive_event(bot, event)
ctx.should_call_send(
event,
MessageSegment.image(data),
True,
)
ctx.should_finished()
@pytest.mark.asyncio
async def test_primogems_failed(app: App):
from utils import make_event
from nonebot.adapters.onebot.v11 import Bot, Message
from GenshinUID.genshinuid_etcimg import get_primogems_data
# primogems_img.exists() is False
async with app.test_matcher(get_primogems_data) as ctx:
bot = ctx.create_bot(base=Bot)
event = make_event(message=Message("版本规划1.0"))
ctx.receive_event(bot, event)
ctx.should_finished()
# str(args) in version is False
async with app.test_matcher(get_primogems_data) as ctx:
event = make_event(message=Message("版本规划abc"))
ctx.receive_event(bot, event)
ctx.should_finished()
@pytest.mark.asyncio
@pytest.mark.parametrize(
argnames="alias",
argvalues=[
"伤害乘区",
"血量表",
"抗性表",
"血量排行",
"伤害乘区",
],
)
async def test_get_img_data(app: App, alias):
from utils import make_event
from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
from GenshinUID.genshinuid_etcimg import get_img_data
with open(
Path(f"../GenshinUID/genshinuid_etcimg/img_data/{alias}.jpg"),
"rb",
) as f:
data = f.read()
async with app.test_matcher(get_img_data) as ctx:
bot = ctx.create_bot(base=Bot)
event = make_event(message=Message(f"查询{alias}"))
ctx.receive_event(bot, event)
ctx.should_call_send(event, MessageSegment.image(data), True)
ctx.should_finished()

123
tests/test_guide.py Normal file
View File

@ -0,0 +1,123 @@
from pathlib import Path
import pytest
from nonebug import App
# TODO: update guide tests
# @pytest.mark.asyncio
# @pytest.mark.parametrize(
# argnames="alias",
# argvalues=[
# "钟离推荐",
# "钟离攻略",
# "岩王爷攻略", # alias
# ],
# )
# async def test_get_guide_pic(app: App, alias ):
# from utils import make_event
# from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
# from GenshinUID.genshinuid_guide import get_guide_pic
# async with app.test_matcher(get_guide_pic) as ctx:
# bot = ctx.create_bot(base=Bot)
# event = make_event(message=Message(alias))
# ctx.receive_event(bot, event)
# ctx.should_call_send(
# event,
# MessageSegment.image(
# "https://file.microgg.cn/MiniGG/guide/钟离.jpg"
# ),
# True,
# )
# ctx.should_finished()
# @pytest.mark.asyncio
# async def test_get_guide_pic_traveler(app: App ):
# from utils import make_event
# from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
# from GenshinUID.genshinuid_guide import get_guide_pic
# async with app.test_matcher(get_guide_pic) as ctx:
# bot = ctx.create_bot(base=Bot)
# event = make_event(message=Message("旅行者风推荐"))
# ctx.receive_event(bot, event)
# ctx.should_call_send(
# event,
# MessageSegment.image(
# "https://file.microgg.cn/MiniGG/guide/旅行者-风.jpg"
# ),
# True,
# )
# ctx.should_finished()
# @pytest.mark.asyncio
# async def test_get_guide_pic_failed(app: App ):
# from utils import make_event
# from nonebot.adapters.onebot.v11 import Bot, Message
# from GenshinUID.genshinuid_guide import get_guide_pic
# async with app.test_matcher(get_guide_pic) as ctx:
# bot = ctx.create_bot(base=Bot)
# event = make_event(message=Message("蔡徐坤攻略"))
# ctx.receive_event(bot, event)
# ctx.should_finished()
@pytest.mark.asyncio
@pytest.mark.parametrize(
argnames="alias",
argvalues=[
"参考面板钟离",
"参考面板岩王爷", # alias
],
)
async def test_get_bluekun_pic(app: App, alias):
from utils import make_event
from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
from GenshinUID.genshinuid_guide import get_bluekun_pic
with open(Path("../GenshinUID/genshinuid_guide/img/钟离.jpg"), "rb") as f:
data = f.read()
async with app.test_matcher(get_bluekun_pic) as ctx:
bot = ctx.create_bot(base=Bot)
event = make_event(message=Message(alias))
ctx.receive_event(bot, event)
ctx.should_call_send(event, MessageSegment.image(data), True)
ctx.should_finished()
@pytest.mark.asyncio
@pytest.mark.parametrize(
argnames="alias",
argvalues=[
"",
"",
],
)
async def test_get_bluekun_pic_element(app: App, alias):
from utils import make_event
from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
from GenshinUID.genshinuid_guide import get_bluekun_pic
with open(
Path(f"../GenshinUID/genshinuid_guide/img/{alias}.jpg"), "rb"
) as f:
data = f.read()
async with app.test_matcher(get_bluekun_pic) as ctx:
bot = ctx.create_bot(base=Bot)
event = make_event(message=Message(f"参考面板{alias}"))
ctx.receive_event(bot, event)
ctx.should_call_send(event, MessageSegment.image(data), True)
ctx.should_finished()

36
tests/test_metadata.py Normal file
View File

@ -0,0 +1,36 @@
import pytest
from nonebug import App
@pytest.mark.asyncio
async def test_metadata(app: App):
from GenshinUID.genshinuid_meta import __plugin_meta__
assert __plugin_meta__.name == 'GenshinUID'
assert (
__plugin_meta__.description == '基于NoneBot2的原神Uid查询/原神Wiki/米游社签到/树脂提醒插件'
)
@pytest.mark.asyncio
async def test_register_menu(app: App):
from GenshinUID.genshinuid_meta import sub_menus, register_menu
@register_menu(
'test',
'trigger',
'test register_menu',
trigger_method='114514',
detail_des='test register_menu',
)
async def _example() -> None:
pass
menu = {
"func": "test",
"trigger_condition": "trigger",
"trigger_method": "114514",
"brief_des": "test register_menu",
"detail_des": "test register_menu",
}
assert menu in sub_menus

View File

@ -0,0 +1,9 @@
from nonebug import App
def test_get_superusers(app: App):
from GenshinUID.utils.nonebot2.utils import get_superusers
superusers = get_superusers()
assert len(superusers) == 2
assert set(superusers) == {10000, 10001}

108
tests/utils.py Normal file
View File

@ -0,0 +1,108 @@
# https://gist.github.com/38e4df0f6f7879d9324b15ac910229ac
from typing import Any, Dict, Optional, cast
from nonebot.adapters.onebot.v11 import Adapter, Message
from nonebot.adapters.onebot.v11.event import Event, Sender
def make_sender(
user_id: int = 10001,
nickname: str = "test",
sex: str = "unknown",
age: int = 1,
card: str = "test",
area: str = "北京",
level: str = "1",
role: str = "owner",
title: str = "test",
):
"""
:说明:
生成发送人信息类型。
https://github.com/botuniverse/onebot-11/blob/master/event/message.md
:参数:
* ``user_id: int = 10001``: 发送者 QQ 号。
* ``nickname: str = "test"``: 昵称。
* ``sex: str = "unknown"``: 性别,`male` 或 `female` 或 `unknown`。
* ``age: int = 1``: 年龄。
* ``card: str = "test"``: 群名片/备注。
* ``area: str = "北京"``: 地区。
* ``level: str = "1"``: 成员等级。
* ``role: str = "owner"``: 角色,`owner` 或 `admin` 或 `member`。
* ``title: str = "test"``: 专属头衔。
"""
return Sender(
user_id=user_id,
nickname=nickname,
sex=sex,
age=age,
card=card,
area=area,
level=level,
role=role,
title=title,
)
def make_event(
sender: Sender = make_sender(),
message: Optional[Message] = None,
time: int = 0,
self_id: int = 10000,
post_type: str = "message",
message_type: str = "private",
sub_type: str = "friend",
group_id: int = 10002,
anonymous: Optional[Dict[str, Any]] = None,
message_id: int = 1,
user_id: int = 10001,
font: int = 0,
**kwargs,
) -> Event:
"""
:说明:
根据消息类型自动生成事件。
https://github.com/botuniverse/onebot-11/blob/master/event/message.md
:参数:
* ``time: int = 0``: 事件发生的时间戳。
* ``self_id: int = 10000``: 收到事件的机器人 QQ 号。
* ``post_type: str = "message"``: 上报类型。
* ``message_type: str = "private"``: 消息类型,`friend` 是私聊消息,`group是群消息`。
* ``sub_type: str = "friend"``: 消息子类型:
* 私聊消息:如果是好友则是 `friend`,如果是群临时会话则是 `group`。
* 群消息:正常消息是 normal匿名消息是 anonymous系统提示如「管理员已禁止群内匿名聊天」是 notice
* ``message_id: int = 1``: 消息 ID。
* ``user_id: int = 10001``: 发送者 QQ 号。
* ``message: Message = None``: 消息内容。
* ``font: int = 0``: 字体。
* ``sender: Sender = None``: 发送人信息。
"""
raw_message = message.extract_plain_text() if message else ''
return cast(
Event,
Adapter.json_to_event(
{
"time": time,
"self_id": self_id,
"post_type": post_type,
"message_type": message_type,
"sub_type": sub_type,
"message_id": message_id,
"user_id": user_id,
"message": message,
"raw_message": raw_message,
"font": font,
"sender": sender,
"group_id": group_id,
"anonymous": anonymous,
**kwargs,
},
),
)