Compare commits

..

194 Commits

Author SHA1 Message Date
fumiama
37d27e07e9 ✏️ 小修正 2021-11-25 22:39:25 +08:00
fumiama
01853768db ✏️ 小修正 2021-11-23 23:25:04 +08:00
fumiama
9d3787dfc2 ✏️ 小修正 2021-11-23 23:05:59 +08:00
fumiama
e9f145056d ✏️ 小修正 2021-11-23 22:51:18 +08:00
fumiama
ea17943bff ✏️ 新增 wtf 2021-11-23 22:40:49 +08:00
fumiama
180c32ef50 ✏️ 优化 moyu 格式 2021-11-23 21:35:42 +08:00
fumiama
17bb844360 ✏️ vtb drop unsafe 2021-11-23 13:05:16 +08:00
fumiama
3d0a161176 ✏️ 修正 badge 2021-11-23 12:46:05 +08:00
fumiama
1148867d3c Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-11-23 12:33:33 +08:00
fumiama
c83d01e977 ✏️ 修复摸鱼 cron 2021-11-23 12:33:24 +08:00
ByronLeeeee
7c42d6f857 修复代理域名,解决PC端无法看图问题 (#80)
1.代理域名从.cat替换成.re;
2.Large尺寸图无法在PC QQ看见,已更改成Medium尺寸
2021-11-23 12:30:40 +08:00
fumiama
ac1c6bc74b ✏️ 在 main 添加摸鱼 2021-11-22 22:40:01 +08:00
fumiama
12f96bb95c ✏️ 修复 vtb panic 判断失误 2021-11-22 22:33:29 +08:00
fumiama
fa063a05f7 ✏️ 修复 vtb 自动下载数据库失败 2021-11-22 22:29:07 +08:00
fumiama
51d10d3234 升级加密算法 2021-11-22 22:22:13 +08:00
fumiama
2d2db15813 新增 moyu 说明 2021-11-22 22:06:22 +08:00
fumiama
006c782819 b14 增加口令加解密 2021-11-22 22:04:31 +08:00
fumiama
37e36fb886 ✏️ 修复 sql 加载失败 2021-11-22 21:48:22 +08:00
fumiama
0e026a8b3b ✏️ 修复 webgui 监听端口问题 2021-11-22 19:12:29 +08:00
fumiama
f37daa5ca6 ✏️ 优化 vtbquotation 2021-11-22 18:56:52 +08:00
fumiama
dafcf7049b ✏️ 修正 moyu 逻辑 2021-11-22 17:53:10 +08:00
fumiama
207da3fcd9 ✏️ 修正 moyu 逻辑 2021-11-22 17:49:37 +08:00
fumiama
a3fbe5d747 ✏️ 优化 moyu,升级依赖 2021-11-22 13:41:55 +08:00
散无友纪
c1717c71bd 摸鱼提醒 (#79)
* Add files via upload

* Update run.go

* Update run.go

* Update run.go
2021-11-22 13:07:04 +08:00
himawari
bcd111f585 小小的修改一下cron表达式 (#77)
* fix:小修一下表达式

* fix:小修一下表达式
2021-11-22 13:01:17 +08:00
github-actions[bot]
d6f1113201 🎨 改进代码样式 2021-11-20 05:35:43 +00:00
himawari
e812d2a074 添加vtb语音包 (#74)
* fix:给msg进行url编码,解决青云客接口返回错误

* feat:增加一个vtbkeyboard.moe接口

* fix:id添加映射

* feat:优化逻辑

* feat:优化逻辑

* feat:优化逻辑

* feat:优化逻辑

* feat:增加一个随机vtb

* feat:增加一个随机vtb

* refactor:更改代码逻辑

* feat:更新数据库

* feat:更新数据库

* feat:更新数据库

* feat:更新数据库

* feat:更新数据库驱动

* feat:增加定时更新数据脚本

* feat:更换驱动

* fix:更新zerobot

* fix:修改全局变量

* fix:微调位置

* fix:解决modernc.org/sqlite版本冲突

* fix:解决go.sum冲突,更换cron库
2021-11-20 13:34:37 +08:00
huoxue1
a537306307 webui功能添加 (#75)
* feat: webui添加功能

为webui添加处理request的请求
包括好友添加请求,群邀请请求,群申请加入请求

* feat: webui添加功能

为webui添加手动处理request的请求的功能
包括好友添加请求,群邀请请求,群申请加入请求

* fix: 修改request对象为指针存储
2021-11-12 18:12:31 +08:00
fumiama
206889bdc5 更新 zb 到 v1.4.1 2021-11-11 20:39:49 +08:00
fumiama
58c7b5c818 ✏️ 修复 lolicon 无法下载 2021-11-09 13:19:33 +08:00
fumiama
eace561f73 ✏️ 修复 fortune 无法下载 2021-11-09 13:09:11 +08:00
fumiama
e2032cdc74 ✏️ 修复 webgui 无法启动 2021-11-09 13:01:01 +08:00
源文雨
34bc8e3a3c Update tl.go 2021-11-09 12:41:41 +08:00
源文雨
1304611ab7 Update http.go 2021-11-09 12:41:08 +08:00
himawari
7a0ce4b5d6 fix:给msg进行url编码,解决青云客接口返回错误 (#73) 2021-11-06 18:55:34 +08:00
github-actions[bot]
835df33e11 🎨 改进代码样式 2021-11-03 05:37:24 +00:00
fumiama
fb80c3606b 新增 搜番 插件 2021-11-03 13:36:46 +08:00
fumiama
f0c80693bb 新增 搜番 插件 2021-11-03 13:34:54 +08:00
fumiama
6997c2f2b9 ✏️ 优化 main 2021-11-02 17:18:55 +08:00
fumiama
cb1057cd5e ⬆️ 更新 zb 到 v1.4.0 2021-11-02 17:18:21 +08:00
fumiama
eb1e2de917 ✏️ 优化 win 下 log 格式 2021-11-01 22:12:56 +08:00
fumiama
4b9b66e7d0 ✏️ 调整 acgimage 限速器 2021-10-31 22:53:11 +08:00
fumiama
c1e87ace78 atri 插件 引入 control 2021-10-31 19:28:31 +08:00
fumiama
ba9eb9c023 acgimage 增加限速器 2021-10-31 19:19:13 +08:00
fumiama
3084d4ad54 atri 插件 引入 control 2021-10-31 19:13:20 +08:00
fumiama
fcb13c19a1 群管自闭增加匹配项 2021-10-31 19:01:01 +08:00
fumiama
d6b81d0363 ✏️ v1.1.8 -> v1.2.0 2021-10-29 13:15:50 +08:00
fumiama
fdd1135a66 ✏️ 修正 timer 2021-10-29 12:54:11 +08:00
fumiama
f9ce439e56 ✏️ 修正正则与cd认证 2021-10-29 12:48:56 +08:00
fumiama
9608d1e736 ✏️ 小修正 2021-10-28 21:24:01 +08:00
fumiama
776d7fbbd9 ✏️ 小修正 2021-10-28 21:06:39 +08:00
fumiama
7c69c24362 ✏️ 在 main.go 引入 b14 2021-10-28 21:04:48 +08:00
fumiama
d205d48166 新增 插件冲突检测、b14 加解密 添加随机等待 1~2s 工具函数 2021-10-28 21:03:09 +08:00
fumiama
dd32aec462 新增插件翻译 by @sky-rainy 2021-10-28 17:05:59 +08:00
fumiama
c0327fe733 manager cron 完善 2021-10-28 11:40:30 +08:00
fumiama
6f4c40f450 差异化 pb 2021-10-27 23:55:54 +08:00
fumiama
022ee6cd95 manager 增加 cron 2021-10-27 23:50:46 +08:00
Kanri
085e04c9ba 🎨 改进结构 2021-10-27 22:28:19 +08:00
fumiama
19f58acb79 改用增强版 cron 2021-10-27 20:45:08 +08:00
fumiama
90dd60b942 升级依赖 & hs drop req 2021-10-27 19:35:57 +08:00
fumiama
755bfeaa5b fortune 增加下载锁;优化 gui 插件控制 2021-10-27 12:42:34 +08:00
fumiama
82ee2f6b0a 更改版本号到 v1.1.8 2021-10-27 10:34:18 +08:00
fumiama
500d03f293 ✏️ 优化打印 2021-10-27 00:19:17 +08:00
fumiama
ee99abe6ff 修复 timer 计时错误 2021-10-27 00:10:33 +08:00
fumiama
0563006c55 修复 timer 计时错误 2021-10-26 22:24:28 +08:00
fumiama
31db6fa4fb 修复 timer 计时错误 2021-10-26 22:09:01 +08:00
fumiama
043b543cfa 修复 timer 计时错误 2021-10-26 16:05:28 +08:00
fumiama
7b52599da7 修复 timer 计时错误 2021-10-26 15:22:00 +08:00
fumiama
4dc8e5619c 优化 timer 资源消耗 2021-10-26 15:05:32 +08:00
fumiama
21ff752322 ✏️ 离散化加载时间 2021-10-26 13:18:48 +08:00
fumiama
0f687d6e95 🔙 合并 timer 2021-10-26 13:11:45 +08:00
fumiama
22e23efbdc ✏️ 修复 sql 查询异常 2021-10-26 00:48:13 +08:00
fumiama
38935937ae control 增加还原;调整禁用优先级 2021-10-26 00:05:45 +08:00
fumiama
a3685e2e83 ✏️ 尝试解决win下路径异常 2021-10-24 18:13:12 +08:00
fumiama
3a5e391191 修正代码问题 2021-10-23 11:51:32 +08:00
fumiama
09a9dd53fd 修正代码问题 2021-10-23 01:09:15 +08:00
github-actions[bot]
5e064249be 🎨 改进代码样式 2021-10-22 16:55:19 +00:00
fumiama
67555512e7 搜图下载使用animeapi,将文件判存移至utils 2021-10-23 00:54:38 +08:00
fumiama
591df6439c 更新 goreleaser 2021-10-22 11:37:40 +08:00
fumiama
7dfb7dfe24 更新 goreleaser 2021-10-22 11:20:01 +08:00
Kanri
8e56f137b6 ⬆️ 更新依赖 2021-10-22 09:36:11 +08:00
源文雨
3b61c73c17 Update README.md 2021-10-20 22:56:31 +08:00
fumiama
44dac98b37 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-10-18 15:25:06 +08:00
fumiama
1a7f98379a ✏️ 修正 acgimage 发图 2021-10-18 15:24:56 +08:00
Kanri
4109ef0612 Update main.go 2021-10-17 23:56:34 +08:00
fumiama
93a9bf6c5b 更新 ZeroBot 到 v1.3.2 2021-10-16 19:07:41 +08:00
fumiama
0b7b35cdcc control 支持全局禁用&个人用户 2021-10-16 14:02:44 +08:00
fumiama
350ef86dd6 ✏️ control 减少 defer 开销 2021-10-16 13:33:12 +08:00
fumiama
2d69ae2e42 ✏️ driver 使用 api 写法 2021-10-16 13:25:13 +08:00
Kanri
e95367f4b2 Merge pull request #70 from Yiwen-Chan/master
⬆️ 更新依赖
2021-10-16 11:11:59 +08:00
Kanri
3101911aa2 ⬆️ 更新依赖 2021-10-16 11:09:26 +08:00
Kanri
ac73087f93 Merge pull request #69 from Yiwen-Chan/master
🎨 ctx.Send -> ctx.SendChain
2021-10-15 22:05:02 +08:00
Kanri
d375a3bbbb 🎨 小修改 2021-10-15 22:02:14 +08:00
Kanri
c46ca1d4c2 🎨 ctx.Send -> ctx.SendChain 2021-10-15 21:43:47 +08:00
fumiama
2a1cca8ebb ✏️ 防止文件名重复 2021-10-15 16:28:31 +08:00
fumiama
d1fdc989b6 ✏️ 防止文件名重复 2021-10-15 16:21:01 +08:00
fumiama
672215f753 ✏️ windows取消arm系 2021-10-15 16:10:58 +08:00
fumiama
4160175fcf ✏️ 修改编译逻辑 2021-10-15 16:02:11 +08:00
fumiama
8f8ba55fc9 ✏️ 改用 gocq 同款 release 2021-10-15 16:00:54 +08:00
fumiama
1dbb4aa837 ✏️ 改用 gocq 同款 release 2021-10-15 15:57:42 +08:00
fumiama
c183c4f17d ✏️ 修正zip缓存位置 2021-10-15 15:27:19 +08:00
fumiama
fa6d14d89a ✏️ 修正zip缓存位置 2021-10-15 15:10:09 +08:00
fumiama
65b92b9da3 更新 README 2021-10-15 14:43:31 +08:00
fumiama
a7056c4601 更新 README 2021-10-14 23:38:52 +08:00
fumiama
1dce0f7859 更新 README 2021-10-14 23:32:49 +08:00
fumiama
bdffbfab67 ✏️ 分离 data 2021-10-14 23:07:13 +08:00
fumiama
98b21d0fdf ✏️ str byte 转换改用 zb 的工具 2021-10-14 19:51:24 +08:00
fumiama
cccea70db1 ✏️ 分离 dyloader 2021-10-14 16:26:01 +08:00
fumiama
d2bcd0bc9f Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-10-14 13:46:44 +08:00
fumiama
08653fd3b6 🚮 删除多余文件 2021-10-14 13:46:30 +08:00
fumiama
75d0671d9b dyloader 缩小插件体积 2021-10-14 13:45:14 +08:00
fumiama
51ec3c32a9 dyloader 缩小插件体积 2021-10-14 13:44:16 +08:00
fumiama
ec0032c5ab dyloader 移除 win,增加加载插件 2021-10-14 00:06:13 +08:00
fumiama
2723f3662c ✏️ 禁用 dyloader 2021-10-13 18:40:40 +08:00
fumiama
539b050b97 ✏️ 完成插件卸载 2021-10-13 18:39:54 +08:00
fumiama
a0b9623a9f dyloader 增加 win,优化 register 2021-10-13 11:07:34 +08:00
fumiama
6b263418a0 升级 zb 到 v1.3.0 2021-10-13 00:34:43 +08:00
fumiama
92989ce9fd control 增加 Delete 2021-10-12 19:16:01 +08:00
fumiama
173925b57a 增加动态加载,添加默认禁用 2021-10-11 21:44:46 +08:00
fumiama
43735722bf ✏️ 收集 max / min 到 data 包 2021-10-11 14:24:22 +08:00
fumiama
d89e7aebec 增加-u参数说明 2021-10-11 13:35:03 +08:00
fumiama
4677d789f2 增加-u参数 2021-10-11 13:32:23 +08:00
fumiama
2fb445746e Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-10-11 13:18:15 +08:00
fumiama
505dfef48c 增加-h参数说明 2021-10-11 13:18:06 +08:00
fumiama
19a9a8ef83 增加-h参数说明 2021-10-11 13:16:30 +08:00
fumiama
119730bada 增加-h参数,优化参数处理 2021-10-11 13:15:38 +08:00
fumiama
c46748524a 增加-w参数 2021-10-10 12:00:23 +08:00
fumiama
29f833db41 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-10-10 11:52:26 +08:00
fumiama
1232856b21 beautify 2021-10-10 11:52:18 +08:00
github-actions[bot]
770ae6ebd0 🎨 改进代码样式 2021-10-10 03:51:49 +00:00
fumiama
8c9ced0bda ✏️ 解耦 web gui 2021-10-10 11:51:09 +08:00
fumiama
3b3dd3df99 fortune 个人用户也可设置底图 2021-10-10 11:37:41 +08:00
fumiama
0817e6233d 更新时间 2021-10-09 12:51:05 +08:00
fumiama
aa4f428194 更新依赖 2021-10-09 12:50:06 +08:00
fumiama
73717dec73 更新帮助 2021-10-09 12:48:58 +08:00
github-actions[bot]
57e2ef3bab 🎨 改进代码样式 2021-10-09 04:36:26 +00:00
fumiama
a5d0b8db8e fortune 增加设置底图并加速base64 和下载 2021-10-09 12:30:59 +08:00
fumiama
3faec79371 ✏️ 解决hs cache问题 2021-10-07 12:23:59 +08:00
散无友纪
c3e0520aec 修改了搜索结果样式 (#68)
* Update run.go

* Update run.go

* Update run.go

* Update run.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2021-10-07 12:21:39 +08:00
源文雨
76db0b6fb4 Update keyword.go 2021-10-07 12:21:20 +08:00
Kanri
40a8473ce0 Merge pull request #67 from Yiwen-Chan/master
改进 fortune 插件
2021-10-06 13:15:04 +08:00
Kanri
21c1d104b8 Merge branch 'master' of github.com:Yiwen-Chan/ZeroBot-Plugin 2021-10-06 10:35:36 +08:00
Kanri
0dda861863 🎨 改进 fortune 2021-10-06 10:33:22 +08:00
Kanri
b21f2f7166 Merge pull request #66 from Yiwen-Chan/master
 增加运势图片插件
2021-10-05 12:17:44 +08:00
Kanri
e533170160 🎨 make lint happy 2021-10-05 12:16:36 +08:00
Kanri
8236874779 🎨 make lint happy 2021-10-05 12:10:45 +08:00
Kanri
4cc1dc2d1b 增加 fortune 插件 2021-10-05 12:03:31 +08:00
Kanri
18424bea7c 🙈 增加 fortune 素材文件忽略 2021-10-05 12:02:49 +08:00
Kanri
0cc6251c0d 增加 gg 绘图库直接依赖 2021-10-05 12:02:22 +08:00
Kanri
63d87be789 增加运势图片插件 2021-10-05 00:57:22 +08:00
Kanri
7e3b898383 Merge pull request #65 from starim00/forup
搜图增加浏览器标头
2021-09-30 14:47:05 +08:00
hutiance
217fa62004 用结果数组的长度作为随机数最大值、防止越界 2021-09-30 14:42:09 +08:00
hutiance
e667fb8708 搜图增加浏览器标头 2021-09-30 14:24:56 +08:00
fumiama
2fef6f51b5 ✏️ fix plugin gif 2021-09-27 22:38:24 +08:00
fumiama
81bba8595a Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-09-27 22:10:55 +08:00
fumiama
96aefc3938 ✏️ 调整 log 格式 2021-09-27 22:10:47 +08:00
github-actions[bot]
5bb0493f02 🎨 改进代码样式 2021-09-27 14:10:29 +00:00
fumiama
e8fa6b8b07 ✏️ 增加命令行参数说明 2021-09-27 22:09:51 +08:00
fumiama
ec15178ba7 ✏️ 修正命令行参数 2021-09-27 22:06:46 +08:00
fumiama
1d469a40d5 aifalse 增加 清理缓存 2021-09-27 21:51:05 +08:00
fumiama
4df30a56a3 ✏️ 修复 panic 2021-09-27 21:37:55 +08:00
fumiama
6bc1e407d5 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-09-27 21:31:54 +08:00
fumiama
48442330c1 ✏️ 美化 log & 更新 banner 2021-09-27 21:31:38 +08:00
fumiama
3623a88b16 ✏️ 调整 log 格式 2021-09-27 21:27:30 +08:00
github-actions[bot]
ffca19edab 🎨 改进代码样式 2021-09-27 13:20:16 +00:00
fumiama
52a8a9de6f 增加插件 reborn 2021-09-27 21:19:37 +08:00
fumiama
b9e303196f ✏️ gif插件增加缓存 2021-09-27 20:23:15 +08:00
fumiama
da3a7e12bd update ZeroBot-Plugin-Gif to v0.1.6 2021-09-26 10:39:43 +08:00
huoxue1
21013bde98 feat: 添加webui的初步支持 (#63)
* feat: 添加webui的初步支持

使用gin监听server,前端使用vuecli
目前已支持:
   前端发送信息
   前端获取信息
   获取插件列表
预计实现功能:

改变插件状态
  获取日志
  获取配置信息
  改变配置信息
  获取好友请求列表以及群请求列表
  手动同意申请列表

* feat: 继续实现webui功能

改变插件状态
  获取日志
  获取配置信息
  前端仓库位置更改

* fix: 修复golangLint的提示信息

* 🎨 改进代码样式

* Update gui.go

* fix: 修复golangLint的提示信息

* fix: 修复golangLint的提示信息

* feat: 支持通过命令行参数禁用gui

* fix: 设置gin在非debug模式下禁用日志

* Update gui.go

* Update gui.go

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2021-09-26 10:35:07 +08:00
fumiama
ae6d83c675 mlh 2021-09-26 10:26:23 +08:00
fumiama
f932e24573 mlh 2021-09-26 10:25:26 +08:00
fumiama
a588ec9d18 mlh 2021-09-26 10:24:46 +08:00
fumiama
bc23211f23 make lint happy 2021-09-26 10:23:52 +08:00
源文雨
78ebf39624 Update choose.go 2021-09-26 10:21:41 +08:00
源文雨
bbc2ab5f17 Update register.go 2021-09-26 10:20:57 +08:00
源文雨
2ffe1e9112 Update rule.go 2021-09-26 10:20:40 +08:00
源文雨
1036733fcb Update register.go 2021-09-26 10:19:10 +08:00
源文雨
ebd5555955 Update text.go 2021-09-26 10:18:21 +08:00
源文雨
83199cf3aa Update nbnhhsh.go 2021-09-26 10:15:22 +08:00
源文雨
c724be743d Update sqlite.go 2021-09-26 10:09:04 +08:00
源文雨
42ba65e21b Update nbnhhsh.go 2021-09-26 10:07:57 +08:00
Kanri
3405c1c45a 翻牌改为抽取最近发言的人 2021-09-25 18:11:53 +08:00
Kanri
5cb6608e17 🗃️🍱 更新数据库 2021-09-25 18:03:11 +08:00
fumiama
aa891ad3fa ✏️ 修复某些 gif 制作失败 2021-09-19 19:44:45 +08:00
fumiama
158bda52a8 ✏️ 升级gif 2021-09-19 19:10:49 +08:00
fumiama
57e5ea87d8 ✏️ 修正制图小错误 2021-09-19 18:07:08 +08:00
fumiama
74486f65cf ✏️ 简化&美化日志输出 2021-09-19 17:06:24 +08:00
fumiama
27fcb63601 ✏️ 制图增加 control 2021-09-19 16:48:41 +08:00
github-actions[bot]
8d83d6be2f 🎨 改进代码样式 2021-09-12 10:43:19 +00:00
Kanri
d31e67e598 Merge pull request #61 from DiheChen/master
Introduce new feature: choose
2021-09-12 18:42:53 +08:00
Chendihe4975
629d3c1fa8 帮助选择困难症 2021-09-12 17:52:30 +08:00
Kanri
193d6efa67 Merge pull request #60 from DiheChen/master
Introduce new feature: 拼音首字母缩写释义工具
2021-09-12 15:44:30 +08:00
Chendihe4975
c70dbd219c Update README 2021-09-12 15:37:54 +08:00
Chendihe4975
da289073e2 拼音首字母缩写释义工具 2021-09-12 15:34:38 +08:00
79 changed files with 8255 additions and 605 deletions

View File

@@ -1,55 +0,0 @@
name: 测试版
on:
push:
tags:
- p*
env:
GITHUB_TOKEN: ${{ github.token }}
jobs:
my-job:
name: Build ZeroBot-Plugin on Push Tag 🚀
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Cache Go
id: cache
uses: actions/cache@v2
with:
# A list of files, directories, and wildcard patterns to cache and restore
path: ~/go/pkg/mod
key: ${{ runner.os }}-build-${{ hashFiles('**/go.sum') }}
- name: Tidy Go modules
run: go mod tidy
- name: Build linux-x64
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x64
- name: Build linux-x86
run: CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x86
- name: Build windows-x64
run: CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x64.exe
- name: Build windows-x86
run: CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x86.exe
- name: Build arm64
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=7 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-arm64
- name: Build armv6
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-armv6
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/zerobot-plugin-*
tag: ${{ github.ref }}
overwrite: true
file_glob: true

View File

@@ -1,55 +1,27 @@
name: 稳定版
name: compile
on:
push:
tags:
- v*
env:
GITHUB_TOKEN: ${{ github.token }}
- 'v*'
jobs:
my-job:
name: Build ZeroBot-Plugin on Push Tag 🚀
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: '1.17'
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Cache Go
id: cache
uses: actions/cache@v2
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
# A list of files, directories, and wildcard patterns to cache and restore
path: ~/go/pkg/mod
key: ${{ runner.os }}-build-${{ hashFiles('**/go.sum') }}
- name: Tidy Go modules
run: go mod tidy
- name: Build linux-x64
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x64
- name: Build linux-x86
run: CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x86
- name: Build windows-x64
run: CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x64.exe
- name: Build windows-x86
run: CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x86.exe
- name: Build arm64
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=7 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-arm64
- name: Build armv6
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-armv6
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/zerobot-plugin-*
tag: ${{ github.ref }}
overwrite: true
file_glob: true
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

5
.gitignore vendored
View File

@@ -3,9 +3,14 @@ data/control
data/SetuTime/search
data/manager
data/acgimage
data/saucenao
data/fortune
data/hs
plugins/*.so
plugins/*.dll
.idea/
.DS_Store
.vscode
go-zero*
nohup.out
zerobot

79
.goreleaser.yml Normal file
View File

@@ -0,0 +1,79 @@
project_name: zbp
env:
- GO111MODULE=on
before:
hooks:
- go mod tidy
builds:
- id: nowin
env:
- CGO_ENABLED=0
- GO111MODULE=on
goos:
- linux
- darwin
goarch:
- 386
- amd64
- arm
- arm64
goarm:
- 6
- 7
ignore:
- goos: darwin
goarch: arm
- goos: darwin
goarch: 386
mod_timestamp: "{{ .CommitTimestamp }}"
flags:
- -trimpath
ldflags:
- -s -w
- id: win
env:
- CGO_ENABLED=0
- GO111MODULE=on
goos:
- windows
goarch:
- 386
- amd64
mod_timestamp: "{{ .CommitTimestamp }}"
flags:
- -trimpath
ldflags:
- -s -w
checksum:
name_template: "zbp_checksums.txt"
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- fix typo
- Merge pull request
- Merge branch
- Merge remote-tracking
- go mod tidy
archives:
- id: nowin
builds:
- nowin
- win
name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
format_overrides:
- goos: windows
format: zip
nfpms:
- license: GPL 3.0
homepage: https://github.com/FloatTech/ZeroBot-Plugin
file_name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
formats:
- deb
- rpm
maintainer: FloatTech

View File

@@ -10,20 +10,42 @@
[![OICQ](https://img.shields.io/badge/OneBot-OICQ-green.svg?style=social&logo=appveyor)](https://github.com/takayama-lily/node-onebot)
[![MIRAI](https://img.shields.io/badge/OneBot-Mirai-green.svg?style=social&logo=appveyor)](https://github.com/yyuueexxiinngg/onebot-kotlin)
[![Go Report Card](https://goreportcard.com/badge/github.com/Yiwen-Chan/ZeroBot-Plugin?style=flat-square&logo=go)](https://goreportcard.com/report/github.com/github.com/Yiwen-Chan/ZeroBot-Plugin)
[![Go Report Card](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin?style=flat-square&logo=go)](https://goreportcard.com/report/github.com/github.com/FloatTech/ZeroBot-Plugin)
[![Badge](https://img.shields.io/badge/onebot-v11-black?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==)](https://github.com/howmanybots/onebot)
[![Badge](https://img.shields.io/badge/zerobot-v1.2.3-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![License](https://img.shields.io/github/license/Yiwen-Chan/OneBot-YaYa.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
[![Badge](https://img.shields.io/badge/zerobot-v1.4.1-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![License](https://img.shields.io/github/license/FloatTech/ZeroBot-Plugin.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
[![qq group](https://img.shields.io/badge/group-1048452984-red?style=flat-square&logo=tencent-qq)](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
</div>
## 命令行参数
```bash
zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
```
- **-h**: 显示帮助
- **-t token**: 设置`AccessToken`,默认为空
- **-u url**: 设置`Url`,默认为`ws://127.0.0.1:6700`
- **-d|w**: 开启 debug | warning 级别及以上日志输出
- **-g 监听地址:端口**: 在 http://监听地址:端口 上开启 [webgui](https://github.com/FloatTech/bot-manager)
- **qqs**: superusers 的 qq 号
## 功能
> 在编译时,以下功能除插件控制外,均可通过注释`main.go`中的相应`import`而物理禁用,减小插件体积。
> 通过插件控制,还可动态管理某个功能在某个群的打开/关闭。
- **web管理** `import _ "github.com/FloatTech/ZeroBot-Plugin/control/web"`
- 开启后可执行文件大约增加 5M ,默认注释不开启。如需开启请自行编辑`main.go`取消注释
- 需要配合 [webgui](https://github.com/FloatTech/bot-manager) 使用
- **动态加载插件** `import _ github.com/FloatTech/ZeroBot-Plugin-Dynamic/dyloader`
- 本功能需要`cgo`,故已分离出主线。详见[ZeroBot-Plugin-Dynamic](https://github.com/FloatTech/ZeroBot-Plugin-Dynamic)
- **插件控制**
- [x] /启用 xxx
- [x] /禁用 xxx
- [x] /启用 xxx (在发送的群/用户启用xxx)
- [x] /禁用 xxx (在发送的群/用户禁用xxx)
- [x] /全局启用 xxx
- [x] /全局禁用 xxx
- [x] /还原 xxx (在发送的群/用户还原xxx的开启状态到初始状态)
- [x] /用法 xxx
- [x] /服务列表
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat"`
- [x] [BOT名字]
- [x] [戳一戳BOT]
@@ -37,7 +59,7 @@
- **群管** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager"`
- [x] 禁言[@xxx][分钟]
- [x] 解除禁言[@xxx]
- [x] 我要自闭 [分钟]
- [x] 我要自闭|禅定 x [分钟|小时|天]
- [x] 开启全员禁言
- [x] 解除全员禁言
- [x] 升为管理[@xxx]
@@ -54,6 +76,8 @@
- [x] 在[MM]月[每周|周几]的[hh]点[mm]分时(用[url])提醒大家[xxx]
- [x] 取消在[MM]月[dd]日的[hh]点[mm]分的提醒
- [x] 取消在[MM]月[每周|周几]的[hh]点[mm]分的提醒
- [x] 在"cron"时(用[url])提醒大家[xxx]
- [x] 取消在"cron"的提醒
- [x] 列出所有提醒
- [x] 翻牌
- [x] [开启|关闭]入群验证
@@ -85,6 +109,14 @@
- [x] 摸[@xxx]
- [x] 搓[@xxx]
- 注:更多指令见项目 --> https://github.com/tdf1939/ZeroBot-Plugin-Gif
- **base16384加解密** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_b14"`
- [x] 加密xxx
- [x] 解密xxx
- [x] 用yyy加密xxx
- [x] 用yyy解密xxx
- **摸鱼** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_moyu"`
- [x] 添加摸鱼提醒
- [x] 删除摸鱼提醒
- **涩图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_setutime"`
- [x] 来份[涩图/二次元/风景/车万]
- [x] 添加[涩图/二次元/风景/车万][P站图片ID]
@@ -95,14 +127,19 @@
- **搜图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao"`
- [x] 以图搜图|搜索图片|以图识图[图片]
- [x] 搜图[P站图片ID]
- **搜番** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_tracemoe"`
- [x] 搜番|搜索番剧[图片]
- **随机图片与AI点评** `github.com/FloatTech/ZeroBot-Plugin/plugin_acgimage`
- [x] 随机图片(评级大于6的图将私发)
- [x] 直接随机(无r18检测务必小心仅管理可用)
- [x] 设置随机图片网址[url]
- [x] 太涩了(撤回最近发的图)
- [x] 评价图片(发送一张图片让bot评分)
- **浅草寺求签** `github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji`
- [x] 求签|运势|占卜
- **每日运势** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_fortune`
- [x] 运势|抽签
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师]
- **浅草寺求签** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji`
- [x] 求签|占卜
- **bilibili** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili"`
- [x] >vup info [名字|uid]
- [x] >user info [名字|uid]
@@ -112,8 +149,12 @@
- [x] 发大病
- [x] 教你一篇小作文[作文]
- [x] [回复]查重
- **鬼东西** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf"`
- [x] 鬼东西列表
- [x] 查询鬼东西[序号][@xxx]
- **AIfalse** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false"`
- [x] 查询计算机当前活跃度 [身体检查]
- [x] 清理缓存
- [ ] 简易语音
- [ ] 爬图合成 [@xxx]
- **minecraft** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft"`
@@ -129,6 +170,18 @@
- [x] @Bot 任意文本(任意一句话回复)
- **关键字搜图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder"`
- [x] 来张 [xxx]
- **拼音首字母释义工具** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh"`
- [x] ?? [缩写]
- **选择困难症帮手** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose"`
- [x] 选择[选择项1]还是[选项2]还是[更多选项]
- **投胎** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn"`
- [x] reborn
- 注:本插件来源于[tgbot](https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py)
- **翻译** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation"`
- [x] >TL 你好
- **vtb语录** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation"`
- [x] vtb语录
- [x] 随机vtb
- **TODO...**
## 使用方法
@@ -148,7 +201,7 @@
### 本地运行
1. 下载安装 [Go](https://studygolang.com/dl) 环境
2. 下载本项目[压缩包](https://github.com/Yiwen-Chan/ZeroBot-Plugin/archive/master.zip),本地解压
2. 下载本项目[压缩包](https://github.com/FloatTech/ZeroBot-Plugin/archive/master.zip),本地解压
3. 编辑 main.go 文件,内容按需修改
4. 双击 build.bat 文件 或 直接双击 run.bat 文件
5. 运行 OneBot 框架,并同时运行本插件
@@ -160,7 +213,7 @@
1. 点击右上角 Fork 本项目,并转跳到自己 Fork 的仓库
2. 点击仓库上方的 Actions 按钮,确认使用 Actions
3. 编辑 main.go 文件,内容按需修改
4. 前往 Release 页面发布一个 Release`tag`形如`vx.y.z`,以触发稳定版编译流程
4. 前往 Release 页面发布一个 Release`tag`形如`v1.2.3`,以触发稳定版编译流程
5. 点击 Actions 按钮,等待编译完成,回到 Release 页面下载编译好的文件
6. 运行 OneBot 框架,并同时运行本插件
7. 啾咪~
@@ -200,4 +253,4 @@ GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags "-s -w"
## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FYiwen-Chan%2FZeroBot-Plugin.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FYiwen-Chan%2FZeroBot-Plugin?ref=badge_large)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FFloatTech%2FZeroBot-Plugin.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FFloatTech%2FZeroBot-Plugin?ref=badge_large)

93
control/cd.go Normal file
View File

@@ -0,0 +1,93 @@
package control
import (
"encoding/binary"
"strings"
"time"
b14 "github.com/fumiama/go-base16384"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
var startTime int64
func init() {
// 插件冲突检测 会在本群发送一条消息并在约 1s 后撤回
zero.OnFullMatch("插件冲突检测", zero.OnlyGroup, zero.AdminPermission, zero.OnlyToMe).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
tok, err := genToken()
if err != nil {
return
}
t := message.Text("●cd" + tok)
startTime = time.Now().Unix()
id := ctx.SendChain(t)
process.SleepAbout1sTo2s()
ctx.DeleteMessage(id)
})
zero.OnRegex("^●cd([\u4e00-\u8e00]{4})$", zero.OnlyGroup).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if isValidToken(ctx.State["regex_matched"].([]string)[1]) {
msg := ""
gid := ctx.Event.GroupID
ForEach(func(key string, manager *Control) bool {
if manager.IsEnabledIn(gid) {
msg += "\xfe\xff" + key
}
return true
})
if len(msg) > 2 {
my, err := b14.UTF16be2utf8(b14.EncodeString(msg[2:]))
mys := "●cd●" + helper.BytesToString(my)
if err == nil {
id := ctx.SendChain(message.Text(mys))
process.SleepAbout1sTo2s()
ctx.DeleteMessage(id)
}
}
}
})
zero.OnRegex("^●cd●(([\u4e00-\u8e00]*[\u3d01-\u3d06]?))", zero.OnlyGroup).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if time.Now().Unix()-startTime < 10 {
msg, err := b14.UTF82utf16be(helper.StringToBytes(ctx.State["regex_matched"].([]string)[1]))
if err == nil {
gid := ctx.Event.GroupID
for _, s := range strings.Split(b14.DecodeString(msg), "\xfe\xff") {
mu.RLock()
c, ok := managers[s]
mu.RUnlock()
if ok && c.IsEnabledIn(gid) {
c.Disable(gid)
}
}
}
}
})
}
func genToken() (tok string, err error) {
timebytes := make([]byte, 8)
binary.BigEndian.PutUint64(timebytes, uint64(time.Now().Unix()))
timebytes, err = b14.UTF16be2utf8(b14.Encode(timebytes[1:]))
if err == nil {
tok = helper.BytesToString(timebytes)
}
return
}
func isValidToken(tok string) (yes bool) {
s, err := b14.UTF82utf16be(helper.StringToBytes(tok))
if err == nil {
timebytes := make([]byte, 1, 8)
timebytes = append(timebytes, b14.Decode(s)...)
yes = time.Now().Unix()-int64(binary.BigEndian.Uint64(timebytes)) < 10
}
return
}

19
control/cd_test.go Normal file
View File

@@ -0,0 +1,19 @@
package control
import "testing"
func TestGenToken(t *testing.T) {
tok, err := genToken()
if err == nil {
t.Log(tok)
t.Log(isValidToken(tok))
t.Fail()
} else {
t.Fatal(err)
}
}
func TestMaru(t *testing.T) {
t.Log(len("\xff"))
t.Fail()
}

View File

@@ -4,8 +4,28 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
)
var enmap = make(map[string]*zero.Engine)
// Register 注册插件控制器
func Register(service string, o *Options) *zero.Engine {
engine := zero.New()
engine.UsePreHandler(new(service, o).Handler())
engine.UsePreHandler(newctrl(service, o).Handler())
enmap[service] = engine
return engine
}
// Delete 删除插件控制器,不会删除数据
func Delete(service string) {
engine, ok := enmap[service]
if ok {
engine.Delete()
mu.RLock()
_, ok = managers[service]
mu.RUnlock()
if ok {
mu.Lock()
delete(managers, service)
mu.Unlock()
}
}
}

View File

@@ -4,6 +4,7 @@ package control
import (
"os"
"strconv"
"strings"
"sync"
"github.com/sirupsen/logrus"
@@ -11,11 +12,11 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension"
"github.com/wdvxdr1123/ZeroBot/message"
. "github.com/FloatTech/ZeroBot-Plugin/data"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
var (
db = &Sqlite{DBPath: "data/control/plugins.db"}
db = &sql.Sqlite{DBPath: "data/control/plugins.db"}
// managers 每个插件对应的管理
managers = map[string]*Control{}
mu = sync.RWMutex{}
@@ -29,8 +30,8 @@ type Control struct {
options Options
}
// new returns Manager with settings.
func new(service string, o *Options) *Control {
// newctrl returns Manager with settings.
func newctrl(service string, o *Options) *Control {
m := &Control{service: service,
options: func() Options {
if o == nil {
@@ -40,8 +41,8 @@ func new(service string, o *Options) *Control {
}(),
}
mu.Lock()
defer mu.Unlock()
managers[service] = m
mu.Unlock()
err := db.Create(service, &grpcfg{})
if err != nil {
panic(err)
@@ -49,42 +50,62 @@ func new(service string, o *Options) *Control {
return m
}
// enable enables a group to pass the Manager.
func (m *Control) enable(groupID int64) {
// Enable enables a group to pass the Manager.
// groupID == 0 (ALL) will operate on all grps.
func (m *Control) Enable(groupID int64) {
m.Lock()
err := db.Insert(m.service, &grpcfg{groupID, 0})
m.Unlock()
if err != nil {
logrus.Errorf("[control] %v", err)
}
m.Unlock()
}
// disable disables a group to pass the Manager.
func (m *Control) disable(groupID int64) {
// Disable disables a group to pass the Manager.
// groupID == 0 (ALL) will operate on all grps.
func (m *Control) Disable(groupID int64) {
m.Lock()
err := db.Insert(m.service, &grpcfg{groupID, 1})
m.Unlock()
if err != nil {
logrus.Errorf("[control] %v", err)
}
m.Unlock()
}
func (m *Control) isEnabledIn(gid int64) bool {
m.RLock()
var c grpcfg
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10))
if err == nil {
m.RUnlock()
logrus.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable)
return c.Disable == 0
} else {
logrus.Errorf("[control] %v", err)
// Reset resets the default config of a group.
// groupID == 0 (ALL) is not allowed.
func (m *Control) Reset(groupID int64) {
if groupID != 0 {
m.Lock()
err := db.Del(m.service, "WHERE gid = "+strconv.FormatInt(groupID, 10))
m.Unlock()
if err != nil {
logrus.Errorf("[control] %v", err)
}
}
}
// IsEnabledIn 开启群
func (m *Control) IsEnabledIn(gid int64) bool {
var c grpcfg
var err error
logrus.Debugln("[control] IsEnabledIn recv gid =", gid)
if gid != 0 {
m.RLock()
err = db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10))
m.RUnlock()
logrus.Debugln("[control] db find gid =", c.GroupID)
if err == nil && gid == c.GroupID {
logrus.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable)
return c.Disable == 0
}
}
m.RLock()
err = db.Find(m.service, &c, "WHERE gid = 0")
m.RUnlock()
if m.options.DisableOnDefault {
m.disable(gid)
} else {
m.enable(gid)
if err == nil {
logrus.Debugf("[control] plugin %s of all : %d", m.service, c.Disable)
return c.Disable == 0
}
return !m.options.DisableOnDefault
}
@@ -93,21 +114,27 @@ func (m *Control) isEnabledIn(gid int64) bool {
func (m *Control) Handler() zero.Rule {
return func(ctx *zero.Ctx) bool {
ctx.State["manager"] = m
return m.isEnabledIn(ctx.Event.GroupID)
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
grp = -ctx.Event.UserID
}
logrus.Debugln("[control] handler get gid =", grp)
return m.IsEnabledIn(grp)
}
}
// lookup returns a Manager by the service name, if
// Lookup returns a Manager by the service name, if
// not exist, it will returns nil.
func lookup(service string) (*Control, bool) {
func Lookup(service string) (*Control, bool) {
mu.RLock()
defer mu.RUnlock()
m, ok := managers[service]
mu.RUnlock()
return m, ok
}
// forEach iterates through managers.
func forEach(iterator func(key string, manager *Control) bool) {
// ForEach iterates through managers.
func ForEach(iterator func(key string, manager *Control) bool) {
mu.RLock()
m := copyMap(managers)
mu.RUnlock()
@@ -126,6 +153,13 @@ func copyMap(m map[string]*Control) map[string]*Control {
return ret
}
func userOrGrpAdmin(ctx *zero.Ctx) bool {
if zero.OnlyGroup(ctx) {
return zero.AdminPermission(ctx)
}
return zero.OnlyToMe(ctx)
}
func init() {
if !hasinit {
mu.Lock()
@@ -135,60 +169,80 @@ func init() {
panic(err)
} else {
hasinit = true
zero.OnCommandGroup([]string{"启用", "enable"}, zero.AdminPermission, zero.OnlyGroup).
Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := lookup(model.Args)
if !ok {
ctx.Send("没有找到指定服务!")
}
service.enable(ctx.Event.GroupID)
ctx.Send(message.Text("已启用服务: " + model.Args))
})
zero.OnCommandGroup([]string{
"启用", "enable", "禁用", "disable",
"全局启用", "enableall", "全局禁用", "disableall",
}, userOrGrpAdmin).Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := Lookup(model.Args)
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
}
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
grp = -ctx.Event.UserID
}
if strings.Contains(model.Command, "全局") || strings.Contains(model.Command, "all") {
grp = 0
}
if strings.Contains(model.Command, "启用") || strings.Contains(model.Command, "enable") {
service.Enable(grp)
ctx.SendChain(message.Text("已启用服务: " + model.Args))
} else {
service.Disable(grp)
ctx.SendChain(message.Text("已禁用服务: " + model.Args))
}
})
zero.OnCommandGroup([]string{"禁用", "disable"}, zero.AdminPermission, zero.OnlyGroup).
Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := lookup(model.Args)
if !ok {
ctx.Send("没有找到指定服务!")
}
service.disable(ctx.Event.GroupID)
ctx.Send(message.Text("已关闭服务: " + model.Args))
})
zero.OnCommandGroup([]string{"还原", "reset"}, userOrGrpAdmin).Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := Lookup(model.Args)
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
}
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
grp = -ctx.Event.UserID
}
service.Reset(grp)
ctx.SendChain(message.Text("已还原服务的默认启用状态: " + model.Args))
})
zero.OnCommandGroup([]string{"用法", "usage"}, zero.AdminPermission, zero.OnlyGroup).
zero.OnCommandGroup([]string{"用法", "usage"}, userOrGrpAdmin).
Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := lookup(model.Args)
service, ok := Lookup(model.Args)
if !ok {
ctx.Send("没有找到指定服务!")
ctx.SendChain(message.Text("没有找到指定服务!"))
}
if service.options.Help != "" {
ctx.Send(service.options.Help)
ctx.SendChain(message.Text(service.options.Help))
} else {
ctx.Send("该服务无帮助!")
ctx.SendChain(message.Text("该服务无帮助!"))
}
})
zero.OnCommandGroup([]string{"服务列表", "service_list"}, zero.AdminPermission, zero.OnlyGroup).
zero.OnCommandGroup([]string{"服务列表", "service_list"}, userOrGrpAdmin).
Handle(func(ctx *zero.Ctx) {
msg := `---服务列表---`
i := 0
forEach(func(key string, manager *Control) bool {
gid := ctx.Event.GroupID
ForEach(func(key string, manager *Control) bool {
i++
msg += "\n" + strconv.Itoa(i) + `: `
if manager.isEnabledIn(ctx.Event.GroupID) {
if manager.IsEnabledIn(gid) {
msg += "●" + key
} else {
msg += "○" + key
}
return true
})
ctx.Send(message.Text(msg))
ctx.SendChain(message.Text(msg))
})
}
}

564
control/web/gui.go Normal file
View File

@@ -0,0 +1,564 @@
// Package webctrl
/*
* 一个用户webui的包里面包含了webui所需的所有内容
*/
package webctrl
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strconv"
"sync"
manager "github.com/FloatTech/bot-manager"
// 依赖gin监听server
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
// 前端静态文件
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/ZeroBot-Plugin/control"
)
var (
// 向前端推送消息的ws链接
conn *websocket.Conn
// 向前端推送日志的ws链接
logConn *websocket.Conn
l logWriter
// 存储请求事件flag作为键一个request对象作为值
requestData sync.Map
)
// logWriter
// @Description:
//
type logWriter struct {
}
// request
// @Description: 一个请求事件的结构体
//
type request struct {
RequestType string `json:"request_type"`
SubType string `json:"sub_type"`
Type string `json:"type"`
Comment string `json:"comment"`
GroupID int64 `json:"group_id"`
UserID int64 `json:"user_id"`
Flag string `json:"flag"`
SelfID int64 `json:"self_id"`
}
// InitGui 初始化gui
func InitGui(addr string) {
// 将日志重定向到前端hook
writer := io.MultiWriter(l, os.Stderr)
log.SetOutput(writer)
// 监听后端
go controller(addr)
// 注册消息handle
messageHandle()
}
// websocket的协议升级
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func controller(addr string) {
defer func() {
err := recover()
if err != nil {
log.Errorln("[gui]" + "bot-manager出现不可恢复的错误")
log.Errorln("[gui]", err)
}
}()
engine := gin.New()
// 支持跨域
engine.Use(cors())
// 注册静态文件
engine.StaticFS("/dist", http.FS(manager.Dist))
engine.POST("/get_bots", getBots)
engine.POST("/get_group_list", getGroupList)
engine.POST("/get_friend_list", getFriendList)
// 注册主路径路由,使其跳转到主页面
engine.GET("/", func(context *gin.Context) {
context.Redirect(http.StatusMovedPermanently, "/dist/dist/default.html")
})
// 更改某个插件状态
engine.POST("/update_plugin_status", updatePluginStatus)
// 更改某一个插件在所有群的状态
engine.POST("/update_plugin_all_group_status", updatePluginAllGroupStatus)
// 更改所有插件状态
engine.POST("/update_all_plugin_status", updateAllPluginStatus)
// 获取所有插件状态
engine.POST("/get_plugins_status", getPluginsStatus)
// 获取一个插件状态
engine.POST("/get_plugin_status", getPluginStatus)
// 获取插件列表
engine.POST("/get_plugins", func(context *gin.Context) {
var datas []map[string]interface{}
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
datas = append(datas, map[string]interface{}{"id": 1, "handle_type": "", "name": key, "enable": manager.IsEnabledIn(0)})
return true
})
context.JSON(200, datas)
})
// 获取所有请求
engine.POST("/get_requests", getRequests)
// 执行一个请求事件
engine.POST("handle_request", handelRequest)
// 链接日志
engine.GET("/get_log", getLogs)
// 获取前端标签
engine.GET("/get_label", func(context *gin.Context) {
context.JSON(200, "ZeroBot-Plugin")
})
// 发送信息
engine.POST("/send_msg", sendMsg)
engine.GET("/data", upgrade)
log.Infoln("[gui] the webui is running on", addr)
log.Infoln("[gui] ", "you input the `ZeroBot-Plugin.exe -g` can disable the gui")
if err := engine.Run(addr); err != nil {
log.Debugln("[gui] ", err.Error())
}
}
// handelRequest
/**
* @Description: 处理一个请求
* @param context
*/
func handelRequest(context *gin.Context) {
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
context.JSON(404, nil)
return
}
r, ok := requestData.LoadAndDelete(data["flag"].(string))
if !ok {
context.JSON(404, "flag not found")
}
r2 := r.(*request)
r2.handle(data["approve"].(bool), data["reason"].(string))
context.JSON(200, "操作成功")
}
// getRequests
/**
* @Description: 获取所有的请求
* @param context
*/
func getRequests(context *gin.Context) {
var data []interface{}
requestData.Range(func(key, value interface{}) bool {
data = append(data, value)
return true
})
context.JSON(200, data)
}
// updateAllPluginStatus
/**
* @Description: 改变所有插件的状态
* @param context
* example
*/
func updateAllPluginStatus(context *gin.Context) {
enable, err := strconv.ParseBool(context.PostForm("enable"))
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui] " + err.Error())
return
}
enable = parse["enable"].(bool)
}
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
if enable {
manager.Enable(0)
} else {
manager.Disable(0)
}
return true
})
context.JSON(200, nil)
}
// updatePluginAllGroupStatus
/**
* @Description: 改变插件在所有群的状态
* @param context
* example
*/
func updatePluginAllGroupStatus(context *gin.Context) {
name := context.PostForm("name")
enable, err := strconv.ParseBool(context.PostForm("enable"))
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
name = parse["name"].(string)
enable = parse["enable"].(bool)
}
control, b := ctrl.Lookup(name)
if !b {
context.JSON(404, nil)
return
}
if enable {
control.Enable(0)
} else {
control.Disable(0)
}
context.JSON(200, nil)
}
// updatePluginStatus
/**
* @Description: 更改某一个插件状态
* @param context
* example
*/
func updatePluginStatus(context *gin.Context) {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui] ", err)
return
}
groupID := int64(parse["group_id"].(float64))
name := parse["name"].(string)
enable := parse["enable"].(bool)
fmt.Println(name)
control, b := ctrl.Lookup(name)
if !b {
context.JSON(404, "服务不存在")
return
}
if enable {
control.Enable(groupID)
} else {
control.Disable(groupID)
}
context.JSON(200, nil)
}
// getPluginStatus
/**
* @Description: 获取一个插件的状态
* @param context
* example
*/
func getPluginStatus(context *gin.Context) {
groupID, err := strconv.ParseInt(context.PostForm("group_id"), 10, 64)
name := context.PostForm("name")
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
groupID = int64(parse["group_id"].(float64))
name = parse["name"].(string)
}
control, b := ctrl.Lookup(name)
if !b {
context.JSON(404, "服务不存在")
return
}
context.JSON(200, gin.H{"enable": control.IsEnabledIn(groupID)})
}
// getPluginsStatus
/**
* @Description: 获取所有插件的状态
* @param context
* example
*/
func getPluginsStatus(context *gin.Context) {
groupID, err := strconv.ParseInt(context.PostForm("group_id"), 10, 64)
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
groupID = int64(parse["group_id"].(float64))
}
var datas []map[string]interface{}
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
enable := manager.IsEnabledIn(groupID)
datas = append(datas, map[string]interface{}{"name": key, "enable": enable})
return true
})
context.JSON(200, datas)
}
// getLogs
/**
* @Description: 连接日志
* @param context
* example
*/
func getLogs(context *gin.Context) {
con1, err := upGrader.Upgrade(context.Writer, context.Request, nil)
if err != nil {
return
}
logConn = con1
}
// getFriendList
/**
* @Description: 获取好友列表
* @param context
* example
*/
func getFriendList(context *gin.Context) {
selfID, err := strconv.Atoi(context.PostForm("self_id"))
if err != nil {
log.Errorln("[gui]" + err.Error())
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
log.Errorln("[gui]" + err.Error())
log.Errorln("[gui]" + "绑定错误")
return
}
selfID = int(data["self_id"].(float64))
}
bot := zero.GetBot(int64(selfID))
var resp []interface{}
list := bot.GetFriendList().String()
err = json.Unmarshal([]byte(list), &resp)
if err != nil {
log.Errorln("[gui]" + err.Error())
log.Errorln("[gui]" + "解析json错误")
}
context.JSON(200, resp)
}
// getGroupList
/**
* @Description: 获取群列表
* @param context
* example
*/
func getGroupList(context *gin.Context) {
selfID, err := strconv.Atoi(context.PostForm("self_id"))
if err != nil {
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
selfID = int(data["self_id"].(float64))
}
bot := zero.GetBot(int64(selfID))
var resp []interface{}
list := bot.GetGroupList().String()
err = json.Unmarshal([]byte(list), &resp)
if err != nil {
log.Errorln("[gui]" + err.Error())
}
context.JSON(200, resp)
}
// getBots
/**
* @Description: 获取机器人qq号
* @param context
* example
*/
func getBots(context *gin.Context) {
var bots []int64
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
bots = append(bots, id)
return true
})
context.JSON(200, bots)
}
// MessageHandle
/**
* @Description: 定义一个向前端发送信息的handle
* example
*/
func messageHandle() {
defer func() {
err := recover()
if err != nil {
log.Errorln("[gui]" + "bot-manager出现不可恢复的错误")
log.Errorln("[gui] ", err)
}
}()
matcher := zero.OnMessage().SetBlock(false).SetPriority(1)
matcher.Handle(func(ctx *zero.Ctx) {
if conn != nil {
err := conn.WriteJSON(ctx.Event)
if err != nil {
log.Debugln("[gui] " + "向发送错误")
return
}
}
})
// 直接注册一个request请求监听器优先级设置为最高设置不阻断事件传播
zero.OnRequest(func(ctx *zero.Ctx) bool {
if ctx.Event.RequestType == "friend" {
ctx.State["type_name"] = "好友添加"
} else {
if ctx.Event.SubType == "add" {
ctx.State["type_name"] = "加群请求"
} else {
ctx.State["type_name"] = "群邀请"
}
}
return true
}).SetBlock(false).FirstPriority().Handle(func(ctx *zero.Ctx) {
r := &request{
RequestType: ctx.Event.RequestType,
SubType: ctx.Event.SubType,
Type: ctx.State["type_name"].(string),
GroupID: ctx.Event.GroupID,
UserID: ctx.Event.UserID,
Flag: ctx.Event.Flag,
Comment: ctx.Event.Comment,
SelfID: ctx.Event.SelfID,
}
requestData.Store(ctx.Event.Flag, r)
})
}
// upgrade
/**
* @Description: 连接ws向前端推送message
* @param context
* example
*/
func upgrade(context *gin.Context) {
con, err := upGrader.Upgrade(context.Writer, context.Request, nil)
if err != nil {
return
}
conn = con
}
// sendMsg
/**
* @Description: 前端调用发送信息
* @param context
* example
*/
func sendMsg(context *gin.Context) {
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
context.JSON(404, nil)
return
}
selfID := int64(data["self_id"].(float64))
id := int64(data["id"].(float64))
message1 := data["message"].(string)
messageType := data["message_type"].(string)
bot := zero.GetBot(selfID)
var msgID int64
if messageType == "group" {
msgID = bot.SendGroupMessage(id, message.ParseMessageFromString(message1))
} else {
msgID = bot.SendPrivateMessage(id, message.ParseMessageFromString(message1))
}
context.JSON(200, msgID)
}
// cors
/**
* @Description: 支持跨域访问
* @return gin.HandlerFunc
* example
*/
func cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
origin := c.Request.Header.Get("Origin") // 请求头部
if origin != "" {
// 接收客户端发送的origin (重要!)
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
// 服务器支持的所有跨域请求的方法
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
// 允许跨域设置可以返回其他子段,可以自定义字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session, Content-Type")
// 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
// 设置缓存时间
c.Header("Access-Control-Max-Age", "172800")
// 允许客户端传递校验信息比如 cookie (重要)
c.Header("Access-Control-Allow-Credentials", "true")
}
// 允许类型校验
if method == "OPTIONS" {
c.JSON(http.StatusOK, "ok!")
}
defer func() {
if err := recover(); err != nil {
log.Printf("Panic info is: %v", err)
}
}()
c.Next()
}
}
// handle
/**
* @Description: 提交一个请求
* @receiver r
* @param approve 是否通过
* @param reason 拒绝的理由
*/
func (r *request) handle(approve bool, reason string) {
bot := zero.GetBot(r.SelfID)
if r.RequestType == "friend" {
bot.SetFriendAddRequest(r.Flag, approve, "")
} else {
bot.SetGroupAddRequest(r.Flag, r.SubType, approve, reason)
}
log.Debugln("[gui] ", "已处理", r.UserID, "的"+r.Type)
}
func (l logWriter) Write(p []byte) (n int, err error) {
if logConn != nil {
err := logConn.WriteMessage(websocket.TextMessage, p)
if err != nil {
return len(p), nil
}
}
return len(p), nil
}

906
data/Reborn/rate.json Normal file
View File

@@ -0,0 +1,906 @@
[
{
"name": "印度",
"weight": 0.179369185
},
{
"weight": 0.116660088,
"name": "中华人民共和国"
},
{
"name": "尼日利亚",
"weight": 0.052104876
},
{
"weight": 0.04490831,
"name": "巴基斯坦"
},
{
"weight": 0.029767875,
"name": "印尼"
},
{
"weight": 0.02917347,
"name": "美国"
},
{
"name": "刚果民主共和国",
"weight": 0.026980482
},
{
"weight": 0.02653533,
"name": "埃塞俄比亚"
},
{
"name": "孟加拉国",
"weight": 0.022001723
},
{
"name": "巴西",
"weight": 0.020641351
},
{
"name": "埃及",
"weight": 0.019722924
},
{
"name": "菲律宾",
"weight": 0.017944256
},
{
"name": "墨西哥",
"weight": 0.015798468
},
{
"weight": 0.015156998,
"name": "坦桑尼亚"
},
{
"weight": 0.013686862,
"name": "乌干达"
},
{
"weight": 0.010405389,
"name": "俄罗斯"
},
{
"weight": 0.010217107,
"name": "苏丹"
},
{
"weight": 0.010079201,
"name": "越南"
},
{
"name": "阿富汗",
"weight": 0.009796745
},
{
"name": "伊朗",
"weight": 0.009789926
},
{
"name": "肯尼亚",
"weight": 0.009216044
},
{
"weight": 0.008870993,
"name": "安哥拉"
},
{
"name": "土耳其",
"weight": 0.008815318
},
{
"weight": 0.008267509,
"name": "莫桑比克"
},
{
"name": "南非",
"weight": 0.007826801
},
{
"weight": 0.00755071,
"name": "尼日尔"
},
{
"name": "伊拉克",
"weight": 0.007350484
},
{
"name": "喀麦隆",
"weight": 0.006786572
},
{
"weight": 0.006782117,
"name": "缅甸"
},
{
"name": "日本",
"weight": 0.006518972
},
{
"weight": 0.006384764,
"name": "加纳"
},
{
"weight": 0.006183538,
"name": "阿尔及利亚"
},
{
"weight": 0.006075416,
"name": "马里"
},
{
"name": "法国",
"weight": 0.00571344
},
{
"name": "英国",
"weight": 0.005662409
},
{
"name": "马达加斯加",
"weight": 0.00559132
},
{
"weight": 0.005562893,
"name": "也门"
},
{
"name": "哥伦比亚",
"weight": 0.005525953
},
{
"name": "布基纳法索",
"weight": 0.005378297
},
{
"name": "科特迪瓦",
"weight": 0.005352997
},
{
"name": "阿根廷",
"weight": 0.005171935
},
{
"name": "赞比亚",
"weight": 0.005147159
},
{
"name": "德国",
"weight": 0.005096501
},
{
"weight": 0.005067552,
"name": "泰国"
},
{
"name": "马拉维",
"weight": 0.005017242
},
{
"name": "乍得",
"weight": 0.004825619
},
{
"name": "摩洛哥",
"weight": 0.004571552
},
{
"weight": 0.004266592,
"name": "马来西亚"
},
{
"weight": 0.004130712,
"name": "南苏丹"
},
{
"name": "委内瑞拉",
"weight": 0.00410843
},
{
"weight": 0.003903682,
"name": "乌兹别克斯坦"
},
{
"weight": 0.003891083,
"name": "秘鲁"
},
{
"weight": 0.003854943,
"name": "尼泊尔"
},
{
"name": "沙特阿拉伯",
"weight": 0.003683713
},
{
"name": "塞内加尔",
"weight": 0.003671814
},
{
"name": "津巴布韦",
"weight": 0.003628572
},
{
"name": "意大利",
"weight": 0.003591173
},
{
"weight": 0.003564036,
"name": "贝宁"
},
{
"weight": 0.003318383,
"name": "索马里"
},
{
"name": "几内亚",
"weight": 0.003229938
},
{
"name": "韩国",
"weight": 0.00302709
},
{
"name": "危地马拉",
"weight": 0.002989448
},
{
"weight": 0.002933277,
"name": "西班牙"
},
{
"name": "布隆迪",
"weight": 0.002916273
},
{
"name": "乌克兰",
"weight": 0.002865519
},
{
"name": "叙利亚",
"weight": 0.002803866
},
{
"name": "加拿大",
"weight": 0.002769376
},
{
"name": "朝鲜",
"weight": 0.002663995
},
{
"name": "柬埔寨",
"weight": 0.002507218
},
{
"weight": 0.002459301,
"name": "卢旺达"
},
{
"weight": 0.002433661,
"name": "波兰"
},
{
"weight": 0.002264484,
"name": "澳大利亚"
},
{
"name": "斯里兰卡",
"weight": 0.002205474
},
{
"weight": 0.00217928,
"name": "哈萨克斯坦"
},
{
"name": "厄瓜多尔",
"weight": 0.002114416
},
{
"name": "塞拉利昂",
"weight": 0.002042686
},
{
"name": "海地",
"weight": 0.001815248
},
{
"name": "智利",
"weight": 0.001761297
},
{
"name": "多哥",
"weight": 0.001756614
},
{
"name": "约旦",
"weight": 0.001738363
},
{
"weight": 0.001716995,
"name": "玻利维亚"
},
{
"weight": 0.001432103,
"name": "巴布亚新几内亚"
},
{
"weight": 0.001424043,
"name": "塔吉克斯坦"
},
{
"name": "多米尼加",
"weight": 0.001376899
},
{
"name": "荷兰",
"weight": 0.001365722
},
{
"name": "罗马尼亚",
"weight": 0.001342703
},
{
"weight": 0.001340039,
"name": "台湾"
},
{
"name": "突尼斯",
"weight": 0.001327688
},
{
"name": "中非",
"weight": 0.001269639
},
{
"name": "洪都拉斯",
"weight": 0.001219191
},
{
"name": "刚果共和国",
"weight": 0.001209073
},
{
"weight": 0.001189154,
"name": "利比里亚"
},
{
"weight": 0.001150376,
"name": "以色列"
},
{
"weight": 0.001149654,
"name": "厄立特里亚"
},
{
"weight": 0.001119049,
"name": "老挝"
},
{
"name": "阿塞拜疆",
"weight": 0.001039837
},
{
"name": "利比亚",
"weight": 0.001029222
},
{
"name": "巴勒斯坦",
"weight": 0.000992651
},
{
"name": "吉尔吉斯斯坦",
"weight": 0.000957294
},
{
"weight": 0.000907425,
"name": "比利时"
},
{
"name": "瑞典",
"weight": 0.000890654
},
{
"name": "巴拉圭",
"weight": 0.00085764
},
{
"name": "毛里塔尼亚",
"weight": 0.000842302
},
{
"weight": 0.000830493,
"name": "古巴"
},
{
"name": "萨尔瓦多",
"weight": 0.000822881
},
{
"name": "尼加拉瓜",
"weight": 0.000782782
},
{
"weight": 0.000764766,
"name": "阿曼"
},
{
"name": "黎巴嫩",
"weight": 0.000751395
},
{
"name": "土库曼斯坦",
"weight": 0.000743841
},
{
"weight": 0.000680867,
"name": "阿联酋"
},
{
"weight": 0.000677997,
"name": "捷克"
},
{
"weight": 0.000643037,
"name": "白俄罗斯"
},
{
"weight": 0.000642255,
"name": "瑞士"
},
{
"name": "匈牙利",
"weight": 0.000612393
},
{
"name": "奥地利",
"weight": 0.000602473
},
{
"name": "希腊",
"weight": 0.000595922
},
{
"weight": 0.000592992,
"name": "葡萄牙"
},
{
"weight": 0.000566764,
"name": "科威特"
},
{
"weight": 0.000538867,
"name": "哥斯达黎加"
},
{
"name": "巴拿马",
"weight": 0.000513904
},
{
"name": "挪威",
"weight": 0.000466485
},
{
"name": "丹麦",
"weight": 0.000460789
},
{
"name": "爱尔兰",
"weight": 0.000455762
},
{
"name": "新西兰",
"weight": 0.000451486
},
{
"name": "纳米比亚",
"weight": 0.000450165
},
{
"name": "香港",
"weight": 0.000448826
},
{
"weight": 0.000441931,
"name": "冈比亚"
},
{
"weight": 0.000436542,
"name": "塞尔维亚"
},
{
"name": "芬兰",
"weight": 0.000417327
},
{
"weight": 0.00041658,
"name": "几内亚比绍"
},
{
"weight": 0.000410456,
"name": "保加利亚"
},
{
"weight": 0.000382945,
"name": "蒙古"
},
{
"name": "莱索托",
"weight": 0.00037228
},
{
"weight": 0.000361607,
"name": "新加坡"
},
{
"name": "斯洛伐克",
"weight": 0.000361482
},
{
"weight": 0.00035722,
"name": "加蓬"
},
{
"name": "博茨瓦纳",
"weight": 0.000348221
},
{
"weight": 0.000323338,
"name": "乌拉圭"
},
{
"name": "赤道几内亚",
"weight": 0.000318155
},
{
"name": "东帝汶",
"weight": 0.000316195
},
{
"name": "牙买加",
"weight": 0.000312724
},
{
"name": "格鲁吉亚",
"weight": 0.000307685
},
{
"weight": 0.000265076,
"name": "阿尔巴尼亚"
},
{
"weight": 0.000252622,
"name": "克罗地亚"
},
{
"weight": 0.000250708,
"name": "亚美尼亚"
},
{
"name": "波黑",
"weight": 0.000232069
},
{
"name": "摩尔多瓦",
"weight": 0.000204405
},
{
"name": "科索沃",
"weight": 0.000196993
},
{
"weight": 0.000189047,
"name": "立陶宛"
},
{
"weight": 0.000182006,
"name": "卡塔尔"
},
{
"name": "波多黎各",
"weight": 0.000182004
},
{
"name": "吉布提",
"weight": 0.000174383
},
{
"name": "北马其顿",
"weight": 0.000158321
},
{
"weight": 0.000146886,
"name": "科摩罗"
},
{
"weight": 0.000144027,
"name": "巴林"
},
{
"weight": 0.000129782,
"name": "斯洛文尼亚"
},
{
"weight": 0.000126232,
"name": "西撒哈拉"
},
{
"name": "拉脱维亚",
"weight": 0.000124966
},
{
"name": "所罗门群岛",
"weight": 0.000120169
},
{
"name": "斐济",
"weight": 0.000110985
},
{
"weight": 0.000110769,
"name": "特立尼达和多巴哥"
},
{
"weight": 0.000109656,
"name": "毛里求斯"
},
{
"weight": 8.8e-5,
"name": "爱沙尼亚"
},
{
"weight": 8.61e-5,
"name": "圭亚那"
},
{
"name": "不丹",
"weight": 8.61e-5
},
{
"weight": 7.49e-5,
"name": "佛得角"
},
{
"name": "塞浦路斯",
"weight": 6.8e-5
},
{
"name": "伯利兹",
"weight": 6.4e-5
},
{
"weight": 6.01e-5,
"name": "苏里南"
},
{
"name": "文莱",
"weight": 5.2e-5
},
{
"weight": 5.1e-5,
"name": "黑山"
},
{
"name": "瓦努阿图",
"weight": 5.1e-5
},
{
"name": "卢森堡",
"weight": 5.07e-5
},
{
"name": "马尔代夫",
"weight": 4.27e-5
},
{
"name": "巴哈马",
"weight": 4.06e-5
},
{
"weight": 3.82e-5,
"name": "澳门"
},
{
"weight": 3.48e-5,
"name": "马耳他"
},
{
"name": "冰岛",
"weight": 3.45e-5
},
{
"weight": 3.03e-5,
"name": "新喀里多尼亚"
},
{
"name": "萨摩亚",
"weight": 2.83e-5
},
{
"weight": 2.8e-5,
"name": "法属波利尼西亚"
},
{
"name": "关岛",
"weight": 2.36e-5
},
{
"weight": 2.32e-5,
"name": "巴巴多斯"
},
{
"name": "基里巴斯",
"weight": 1.83e-5
},
{
"weight": 1.71e-5,
"name": "圣卢西亚"
},
{
"name": "库拉索",
"weight": 1.51e-5
},
{
"weight": 1.5e-5,
"name": "汤加"
},
{
"weight": 1.42e-5,
"name": "密克罗尼西亚联邦"
},
{
"weight": 1.13e-5,
"name": "格林纳达"
},
{
"name": "安提瓜和巴布达",
"weight": 1.05e-5
},
{
"weight": 9.93e-6,
"name": "圣文森特和格林纳丁斯"
},
{
"name": "泽西",
"weight": 9.66e-6
},
{
"weight": 9.64e-6,
"name": "阿鲁巴"
},
{
"weight": 9.15e-6,
"name": "美属维尔京群岛"
},
{
"weight": 9.08e-6,
"name": "马绍尔群岛"
},
{
"weight": 8.9e-6,
"name": "塞舌尔"
},
{
"name": "美属萨摩亚",
"weight": 7.97e-6
},
{
"name": "多米尼克",
"weight": 7.57e-6
},
{
"weight": 6.41e-6,
"name": "马恩岛"
},
{
"weight": 6.09e-6,
"name": "北马里亚纳群岛"
},
{
"name": "开曼群岛",
"weight": 5.77e-6
},
{
"name": "格陵兰",
"weight": 5.63e-6
},
{
"weight": 5.54e-6,
"name": "法罗群岛"
},
{
"weight": 5.17e-6,
"name": "圣基茨和尼维斯"
},
{
"weight": 5.11e-6,
"name": "百慕大"
},
{
"weight": 4.38e-6,
"name": "根西"
},
{
"weight": 4.31e-6,
"name": "特克斯和凯科斯群岛"
},
{
"name": "荷属圣马丁",
"weight": 4.14e-6
},
{
"weight": 3.87e-6,
"name": "安道尔"
},
{
"name": "法国(法属圣马丁)",
"weight": 3.6e-6
},
{
"name": "直布罗陀",
"weight": 3.2e-6
},
{
"weight": 2.87e-6,
"name": "列支敦士登"
},
{
"name": "英属维尔京群岛",
"weight": 2.57e-6
},
{
"weight": 2.1e-6,
"name": "圣马力诺"
},
{
"weight": 1.75e-6,
"name": "瑙鲁"
},
{
"name": "摩纳哥",
"weight": 1.75e-6
},
{
"name": "图瓦卢",
"weight": 1.72e-6
},
{
"name": "库克群岛",
"weight": 1.44e-6
},
{
"name": "帕劳",
"weight": 1.44e-6
},
{
"weight": 1.41e-6,
"name": "安圭拉"
},
{
"weight": 1.05e-6,
"name": "法国(瓦利斯和富图纳)"
},
{
"weight": 6.6e-7,
"name": "法国(圣巴泰勒米)"
},
{
"name": "蒙特塞拉特",
"weight": 4.35e-7
},
{
"weight": 3.77e-7,
"name": "圣赫勒拿、阿森松和特里斯坦-达库尼亚"
},
{
"name": "法国(圣皮埃尔和密克隆)",
"weight": 2.86e-7
},
{
"name": "福克兰群岛",
"weight": 2.48e-7
}
]

Binary file not shown.

BIN
data/VtbQuotation/vtb.db Normal file

Binary file not shown.

27
go.mod
View File

@@ -3,18 +3,23 @@ module github.com/FloatTech/ZeroBot-Plugin
go 1.16
require (
github.com/FloatTech/AnimeAPI v1.1.9
github.com/FloatTech/ZeroBot-Plugin-Timer v1.4.3
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/FloatTech/AnimeAPI v1.1.10
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed
github.com/fogleman/gg v1.3.0
github.com/fumiama/cron v1.3.0
github.com/fumiama/go-base16384 v1.2.1
github.com/fumiama/gofastTEA v0.0.5
github.com/fumiama/gotracemoe v0.0.3
github.com/gin-gonic/gin v1.7.5
github.com/golang/protobuf v1.5.2
github.com/imroc/req v0.3.0
github.com/robfig/cron v1.2.0
github.com/shirou/gopsutil v3.21.8+incompatible
github.com/gorilla/websocket v1.4.2
github.com/jinzhu/gorm v1.9.16
github.com/logoove/sqlite v1.13.0
github.com/mroth/weightedrand v0.4.1
github.com/shirou/gopsutil v3.21.10+incompatible
github.com/sirupsen/logrus v1.8.1
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
github.com/tdf1939/ZeroBot-Plugin-Gif v0.0.0-20210828060956-389b1dc33652
github.com/tidwall/gjson v1.9.0
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/wdvxdr1123/ZeroBot v1.2.3
modernc.org/sqlite v1.13.0
github.com/tidwall/gjson v1.11.0
github.com/wdvxdr1123/ZeroBot v1.4.1
)

117
go.sum
View File

@@ -1,9 +1,20 @@
github.com/FloatTech/AnimeAPI v1.1.9 h1:H1hZmgwZPNHdx39K9JvY3awT8TTsCl9kKA1uVMyCjRg=
github.com/FloatTech/AnimeAPI v1.1.9/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/ZeroBot-Plugin-Timer v1.4.3 h1:jn/dH+OwPSRozkmeCeQQPrAGJRBudcm3OK5tXhGItRk=
github.com/FloatTech/AnimeAPI v1.1.10 h1:fYkv65P1HBukHi3GpzYulGx/xLshEL9635QXALDryf0=
github.com/FloatTech/AnimeAPI v1.1.10/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/ZeroBot-Plugin v1.1.5/go.mod h1:kWuUARvU7gs4xLggi8Sy37ja2GRL6k0X6kewe5TiZRs=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4 h1:WW0BmmLLqAg+m6qGkrKbsfSIm91fkj3/udt3R7Myodo=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4/go.mod h1:W7ag6hml1pZTNzRXKU74OMr6rS8awQKSU+o2g7Gj4O0=
github.com/FloatTech/ZeroBot-Plugin-Timer v1.4.3/go.mod h1:MVOQQ4e6AVGFm993blXXU4Sd6bAsLY2+Zb+/HMrEeEc=
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed h1:GEOgDVbvaxXqZxgWE/y5JOlbMXrmq7n0M+m9g3md2To=
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
github.com/FloatTech/imgfactory v0.1.1 h1:ooL2+fV8yrMhv1ShGGKsN0Rm/flWoKnvqXaUD+dC3DQ=
github.com/FloatTech/imgfactory v0.1.1/go.mod h1:ThDALab8aOuU6KVYESVWFqmjcqtm03e0SvGlTw6s+aw=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb h1:Rkj28fqIwGx/EgBzRYtpmJRfH6wqVn7cNdc7aJ0QE4M=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqeit+C/eaWGb4MKQ3z3gN6pRpBU5RMtp5so=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz6M=
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
github.com/antchfx/xpath v1.1.6 h1:6sVh6hB5T6phw1pFpHRQ+C4bd8sNI+O58flqtg7h0R0=
@@ -11,22 +22,55 @@ github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNY
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
github.com/fumiama/go-base16384 v1.2.1 h1:6OGprW8g/95m2ocmryHi8mipZ7bx9StFMZDKEqLvMiA=
github.com/fumiama/go-base16384 v1.2.1/go.mod h1:1HTC0QFL7BjS0DuO5Qm+fBYKQkHqmAapLbRpCxrhPXQ=
github.com/fumiama/gofastTEA v0.0.3 h1:JKcNktWArLkJe88Y+zGmsQGhqlh8IzYqUnWy2ipylh0=
github.com/fumiama/gofastTEA v0.0.3/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
github.com/fumiama/gofastTEA v0.0.4 h1:SOWEIXBkFekhaxZoLEFk/L3rOh2X1G5PeM2TLAZycaQ=
github.com/fumiama/gofastTEA v0.0.4/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
github.com/fumiama/gofastTEA v0.0.5 h1:Pd/2eSfLl2V0CqZL8pnu1CIU8Fy4HYpLutpliXU70Ds=
github.com/fumiama/gofastTEA v0.0.5/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.5 h1:GOccErVuE4RiwM9DCzVIBfwZjLeFv3d1eHcbqVlrVvU=
github.com/gin-gonic/gin v1.7.5/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
@@ -38,15 +82,29 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imroc/req v0.3.0 h1:3EioagmlSG+z+KySToa+Ylo3pTFZs+jh3Brl7ngU12U=
github.com/imroc/req v0.3.0/go.mod h1:F+NZ+2EFSo6EFXdeIbpfE9hcC233id70kf0byW97Caw=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/logoove/sqlite v1.13.0 h1:XM7QKK9R3tm8o7bI75R3zmwYBFQ5S3Jqg+XCaqsAMQQ=
github.com/logoove/sqlite v1.13.0/go.mod h1:MRpE/o3qQhT7AgfIdnBue5c63+//xT+KXV0gHeVAUAg=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
@@ -54,17 +112,21 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b h1:6Xjqolv/0DDdUqlpnsTomXQvjvvkz7Ux7TcMALvozEw=
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU=
github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.10+incompatible h1:AL2kpVykjkqeN+MFe1WcwSBVUjGjvdU8/ubvCuXAjrU=
github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@@ -72,47 +134,64 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
github.com/tdf1939/ZeroBot-Plugin-Gif v0.0.0-20210828060956-389b1dc33652 h1:ZMZGgo6hboOetoExFZBecloH1zmQYJlWQWuhCeR0FiY=
github.com/tdf1939/ZeroBot-Plugin-Gif v0.0.0-20210828060956-389b1dc33652/go.mod h1:bkxKi7un9gCDvUUZAiIJF6k90pyj8rmxiXLJkiHcsMY=
github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3 h1:DUQxv4Ua1sb0/zOkExNJ/MSJcSnbZ7WT9thXCPWTh5U=
github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3/go.mod h1:FgTEOcosTWrkOr7++gbtPSj1rX5loRWrf/AL+hm3Cnw=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.9.0 h1:+Od7AE26jAaMgVC31cQV/Ope5iKXulNMflrlB7k+F9E=
github.com/tidwall/gjson v1.9.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/gjson v1.11.0 h1:C16pk7tQNiH6VlCrtIXL1w8GaOsi1X3W8KDkE1BuYd4=
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/wdvxdr1123/ZeroBot v1.2.2/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
github.com/wdvxdr1123/ZeroBot v1.2.3 h1:Fu6aHr+91NRN48G9szJwyR0MhnTjG5lNMS0Wy0QX1Uo=
github.com/wdvxdr1123/ZeroBot v1.2.3/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
github.com/wdvxdr1123/ZeroBot v1.2.4/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
github.com/wdvxdr1123/ZeroBot v1.3.2/go.mod h1:i2DIqQjtjE+3gvVi9r9sc+QpNaUuyTXx/HNXXayIpwI=
github.com/wdvxdr1123/ZeroBot v1.4.1 h1:fk/8RH2D1gB3YeC1eI/SZi/kG31Rh7Z8lAiDc60VZFM=
github.com/wdvxdr1123/ZeroBot v1.4.1/go.mod h1:7t9m4vDZPwWAmzKlhP6IvUoisOIiqNdm/3AJgiY3+ew=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -122,11 +201,15 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b h1:S7hKs0Flbq0bbc9xgYt4stIEG1zNDFqyrPwAX2Wj/sE=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -140,12 +223,17 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
@@ -161,7 +249,6 @@ modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBM
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
modernc.org/ccgo/v3 v3.11.2 h1:gqa8PQ2v7SjrhHCgxUO5dzoAJWSLAveJqZTNkPCN0kc=
modernc.org/ccgo/v3 v3.11.2/go.mod h1:6kii3AptTDI+nUrM9RFBoIEUEisSWCbdczD9ZwQH2FE=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
@@ -183,9 +270,7 @@ modernc.org/sqlite v1.13.0 h1:cwhUj0jTBgPjk/demWheV+T6xi6ifTfsGIFKFq0g3Ck=
modernc.org/sqlite v1.13.0/go.mod h1:2qO/6jZJrcQaxFUHxOwa6Q6WfiGSsiVj6GXX0Ker+Jg=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.5.9 h1:DZMfR+RDJRhcrmMEMTJgVIX+Wf5qhfVX0llI0rsc20w=
modernc.org/tcl v1.5.9/go.mod h1:bcwjvBJ2u0exY6K35eAmxXBBij5kXb1dHlAWmfhqThE=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.1.2 h1:IjjzDsIFbl0wuF2KfwvdyUAJVwxD4iwZ6akLNiDoClM=
modernc.org/z v1.1.2/go.mod h1:sj9T1AGBG0dm6SCVzldPOHWrif6XBpooJtbttMn1+Js=

121
main.go
View File

@@ -1,97 +1,134 @@
package main
import (
"flag"
"fmt"
"os"
"strings"
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
// 插件控制
// webctrl "github.com/FloatTech/ZeroBot-Plugin/control/web" // web 后端控制
// 词库类
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri" // ATRI词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat" // 基础词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_qingyunke" //青云客
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_qingyunke" // 青云客
// 实用类
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager" // 群管
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_runcode" // 在线运行代码
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_b14" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager" // 群管
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh" // 拼音首字母缩写释义工具
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_runcode" // 在线运行代码
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation" // 翻译
// 娱乐类
_ "github.com/tdf1939/ZeroBot-Plugin-Gif/plugin_gif" // 制图
_ "github.com/FloatTech/ZeroBot-Plugin-Gif" // 制图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft" // MCSManager
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_moyu" // 摸鱼
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_music" // 点歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf" // 鬼东西
// b站相关
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili" // 查询b站用户信息
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_diana" // 嘉心糖发病
// 二次元图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_acgimage" // 随机图片与AI点评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder" // 关键字搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_lolicon" // lolicon 随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao" // 以图搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_setutime" // 来份涩图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_acgimage" // 随机图片与AI点评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder" // 关键字搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_lolicon" // lolicon 随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao" // 以图搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_setutime" // 来份涩图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_tracemoe" // 搜番
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation" // vtb语录
// 以下为内置依赖,勿动
log "github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/driver"
"github.com/wdvxdr1123/ZeroBot/message"
)
var (
contents = []string{
"* OneBot + ZeroBot + Golang",
"* Version 1.1.5 - 2021-09-09 20:52:33 +0800 CST",
"* Copyright © 2020 - 2021 Kanri, DawnNights, Fumiama, Suika",
"* Version 1.2.0 - 2021-10-29 13:08:45 +0800 CST",
"* Copyright © 2020 - 2021 FloatTech. All Rights Reserved.",
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
}
banner = strings.Join(contents, "\n")
token *string
url *string
)
func init() {
log.SetFormatter(&easy.Formatter{
TimestampFormat: "2006-01-02 15:04:05",
LogFormat: "[zero][%time%][%lvl%]: %msg% \n",
})
log.SetLevel(log.DebugLevel)
// 解析命令行参数
d := flag.Bool("d", false, "Enable debug level log and higher.")
w := flag.Bool("w", false, "Enable warning level log and higher.")
h := flag.Bool("h", false, "Display this help.")
// 解析命令行参数,输入 `-g 监听地址:端口` 即可启用 gui
// g := flag.String("g", "127.0.0.1:3000", "Enable web gui.")
// 直接写死 AccessToken 时,请更改下面第二个参数
token = flag.String("t", "", "Set AccessToken of WSClient.")
// 直接写死 URL 时,请更改下面第二个参数
url = flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
flag.Parse()
if *h {
printBanner()
fmt.Println("Usage:")
flag.PrintDefaults()
os.Exit(0)
} else {
if *d && !*w {
logrus.SetLevel(logrus.DebugLevel)
}
if *w {
logrus.SetLevel(logrus.WarnLevel)
}
}
// 解析命令行参数,输入 `-g` 即可启用 gui
// if *g {
// webctrl.InitGui(*g)
// }
}
func main() {
func printBanner() {
fmt.Print(
"\n======================[ZeroBot-Plugin]======================",
"\n", banner, "\n",
"============================================================\n",
) // 启动打印
zero.Run(zero.Config{
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
CommandPrefix: "/",
// SuperUsers 某些功能需要主人权限,可通过以下两种方式修改
// []string{}:通过代码写死的方式添加主人账号
// os.Args[1:]:通过命令行参数的方式添加主人账号
SuperUsers: append([]string{"12345678", "87654321"}, os.Args[1:]...),
Driver: []zero.Driver{
&driver.WSClient{
// OneBot 正向WS 默认使用 6700 端口
Url: "ws://127.0.0.1:6700",
AccessToken: "",
},
},
})
)
}
func main() {
printBanner()
// 帮助
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
ctx.Send(banner)
ctx.SendChain(message.Text(banner))
})
select {}
zero.RunAndBlock(
zero.Config{
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
CommandPrefix: "/",
// SuperUsers 某些功能需要主人权限,可通过以下两种方式修改
// "12345678", "87654321":通过代码写死的方式添加主人账号
// flag.Args():通过命令行参数的方式添加主人账号,无需修改下方任何代码
SuperUsers: append([]string{"12345678", "87654321"}, flag.Args()...),
Driver: []zero.Driver{driver.NewWebSocketClient(*url, *token)},
},
)
}

15
main_win.go Normal file
View File

@@ -0,0 +1,15 @@
//go:build windows
// +build windows
package main
import (
"github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
)
func init() {
logrus.SetFormatter(&easy.Formatter{
LogFormat: "[%lvl%] %msg%\n",
})
}

View File

@@ -3,16 +3,18 @@ package acgimage
import (
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/FloatTech/AnimeAPI/classify"
"github.com/FloatTech/AnimeAPI/picture"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
)
const (
@@ -21,13 +23,13 @@ const (
)
var (
botpath, _ = os.Getwd()
datapath = botpath + "/data/acgimage/"
cacheuri = "file:///" + datapath + "cache"
datapath = file.BOT_PATH + "/data/acgimage/"
cacheuri = "file:///" + datapath + "cache"
// r18有一定保护一般不会发出图片
randapi = "&loli=true&r18=true"
msgof = make(map[int64]int64)
block = false
limit = rate.NewManager(time.Minute, 5)
)
func init() { // 插件主体
@@ -46,29 +48,29 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
url := ctx.State["regex_matched"].([]string)[1]
if !strings.HasPrefix(url, "http") {
ctx.Send("URL非法!")
ctx.SendChain(message.Text("URL非法!"))
} else {
randapi = url
ctx.Send("设置好啦")
ctx.SendChain(message.Text("设置好啦"))
}
})
// 有保护的随机图片
engine.OnFullMatch("随机图片", zero.OnlyGroup).SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
if classify.CanVisit(5) {
if classify.CanVisit(5) && limit.Load(ctx.Event.UserID).Acquire() {
go func() {
class, lastvisit, dhash, comment := classify.Classify(randapi, false)
replyClass(ctx, dhash, class, false, lastvisit, comment)
}()
} else {
ctx.Send("你太快啦!")
ctx.SendChain(message.Text("你太快啦!"))
}
})
// 直接随机图片无r18保护后果自负。如果出r18图可尽快通过发送"太涩了"撤回
engine.OnFullMatch("直接随机", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
if block {
ctx.Send("请稍后再试哦")
ctx.SendChain(message.Text("请稍后再试哦"))
} else if randapi != "" {
block = true
var url string
@@ -77,7 +79,7 @@ func init() { // 插件主体
} else {
url = randapi
}
setLastMsg(ctx.Event.GroupID, ctx.Send(message.Image(url).Add("cache", "0")))
setLastMsg(ctx.Event.GroupID, ctx.SendChain(message.Image(url).Add("cache", "0")))
block = false
}
})
@@ -89,7 +91,7 @@ func init() { // 插件主体
// 上传一张图进行评价
engine.OnKeywordGroup([]string{"评价图片"}, zero.OnlyGroup, picture.CmdMatch, picture.MustGiven).SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
ctx.Send("少女祈祷中...")
ctx.SendChain(message.Text("少女祈祷中..."))
for _, url := range ctx.State["image_url"].([]string) {
go func(target string) {
class, lastvisit, dhash, comment := classify.Classify(target, true)
@@ -101,7 +103,7 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
dhash := ctx.State["regex_matched"].([]string)[1]
if len(dhash) == 5*3 {
ctx.Send(message.Image(apihead + dhash))
ctx.SendChain(message.Image(apihead + dhash))
}
})
}
@@ -124,19 +126,18 @@ func replyClass(ctx *zero.Ctx, dhash string, class int, noimg bool, lv int64, co
if dhash != "" && !noimg {
b14, err3 := url.QueryUnescape(dhash)
if err3 == nil {
ctx.Send(comment + "\n给你点提示哦" + b14)
ctx.SendChain(message.Text(comment + "\n给你点提示哦" + b14))
ctx.Event.GroupID = 0
ctx.Send(img)
ctx.SendChain(img)
}
} else {
ctx.Send(comment)
ctx.SendChain(message.Text(comment))
}
} else {
comment := message.Text(comment)
if !noimg {
ctx.SendChain(img, comment)
ctx.SendChain(img, message.Text(comment))
} else {
ctx.SendChain(message.Reply(ctx.Event.MessageID), comment)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(comment))
}
}
}

View File

@@ -3,6 +3,7 @@ package aifalse
import (
"math"
"os"
"time"
"github.com/shirou/gopsutil/cpu"
@@ -30,6 +31,15 @@ func init() { // 插件主体
),
)
})
engine.OnFullMatch("清理缓存", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := os.RemoveAll("data/cache/*")
if err != nil {
ctx.SendChain(message.Text("错误: ", err.Error()))
} else {
ctx.SendChain(message.Text("成功!"))
}
})
}
func cpuPercent() float64 {

View File

@@ -11,33 +11,43 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
var (
const (
// 服务名
servicename = "atri"
// ATRI 所有命令的优先级
prio = 2
// ATRI 表情的 codechina 镜像
res = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/plugin_atri/"
// ATRI 的总开关
enable = true
)
func init() { // 插件主体
engine := control.Register(servicename, &control.Options{})
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
enable = true
time.Sleep(time.Second * 1)
ctx.SendChain(randText("嗯呜呜……夏生先生……?"))
c, ok := control.Lookup(servicename)
if ok && !c.IsEnabledIn(ctx.Event.GroupID) {
c.Enable(ctx.Event.GroupID)
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
}
})
zero.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).SetPriority(prio).
engine.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
enable = false
time.Sleep(time.Second * 1)
ctx.SendChain(randText("Zzz……Zzz……"))
c, ok := control.Lookup(servicename)
if ok && c.IsEnabledIn(ctx.Event.GroupID) {
c.Disable(ctx.Event.GroupID)
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("Zzz……Zzz……"))
}
})
zero.OnFullMatch("萝卜子", atriSwitch(), atriSleep()).SetBlock(true).SetPriority(prio).
engine.OnFullMatch("萝卜子", atriSleep).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
switch rand.Intn(2) {
case 0:
ctx.SendChain(randText("萝卜子是对机器人的蔑称!", "是亚托莉......萝卜子可是对机器人的蔑称"))
@@ -45,20 +55,20 @@ func init() { // 插件主体
ctx.SendChain(randRecord("RocketPunch.amr"))
}
})
zero.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, atriSwitch(), atriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(prio).
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
})
zero.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, atriSwitch(), atriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(prio - 1).
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio - 1).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
})
zero.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早"}, atriSwitch()).SetBlock(true).SetPriority(prio).
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早"}).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
switch {
case now < 6: // 凌晨
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
@@ -95,11 +105,11 @@ func init() { // 插件主体
))
}
})
zero.OnFullMatchGroup([]string{"中午好", "午安", "午好"}, atriSwitch()).SetBlock(true).SetPriority(prio).
engine.OnFullMatchGroup([]string{"中午好", "午安", "午好"}).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
if now > 11 && now < 15 { // 中午
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
"午安w",
"午觉要好好睡哦ATRI会陪伴在你身旁的w",
@@ -108,10 +118,10 @@ func init() { // 插件主体
))
}
})
zero.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい", "晚好", "晚上好"}, atriSwitch()).SetBlock(true).SetPriority(prio).
engine.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい", "晚好", "晚上好"}).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
switch {
case now < 6: // 凌晨
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
@@ -151,9 +161,9 @@ func init() { // 插件主体
))
}
})
zero.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, atriSwitch(), atriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(prio).
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
ctx.SendChain(randText(
"当然,我是高性能的嘛~",
"小事一桩,我是高性能的嘛",
@@ -172,9 +182,9 @@ func init() { // 插件主体
"呣......我的高性能,毫无遗憾地施展出来了......",
))
})
zero.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, atriSwitch(), atriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(prio).
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
ctx.SendChain(randText(
"当然,我是高性能的嘛~",
"没事没事,因为我是高性能的嘛!嗯哼!",
@@ -187,28 +197,28 @@ func init() { // 插件主体
))
})
zero.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, atriSwitch(), atriSleep()).SetBlock(true).SetPriority(prio).
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, atriSleep).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
if rand.Intn(2) == 0 {
ctx.SendChain(randImage("YES.png", "NO.jpg"))
}
})
zero.OnKeywordGroup([]string{"啊这"}, atriSwitch(), atriSleep()).SetBlock(true).SetPriority(prio).
engine.OnKeywordGroup([]string{"啊这"}, atriSleep).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
if rand.Intn(2) == 0 {
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
}
})
zero.OnKeywordGroup([]string{"我好了"}, atriSwitch(), atriSleep()).SetBlock(true).SetPriority(prio).
engine.OnKeywordGroup([]string{"我好了"}, atriSleep).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText("不许好!", "憋回去!"))
})
zero.OnFullMatchGroup([]string{"", "?", "¿"}, atriSwitch(), atriSleep()).SetBlock(true).SetPriority(prio).
engine.OnFullMatchGroup([]string{"", "?", "¿"}, atriSleep).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
switch rand.Intn(5) {
case 0:
ctx.SendChain(randText("?", "", "嗯?", "(。´・ω・)ん?", "ん?"))
@@ -216,7 +226,7 @@ func init() { // 插件主体
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
}
})
zero.OnKeyword("离谱", atriSwitch(), atriSleep()).SetBlock(true).SetPriority(prio).
engine.OnKeyword("离谱", atriSleep).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
switch rand.Intn(5) {
case 0:
@@ -225,41 +235,29 @@ func init() { // 插件主体
ctx.SendChain(randImage("WH.jpg"))
}
})
zero.OnKeyword("答应我", atriSwitch(), atriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(prio).
engine.OnKeyword("答应我", atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
time.Sleep(time.Second * 1)
process.SleepAbout1sTo2s()
ctx.SendChain(randText("我无法回应你的请求"))
})
}
func randText(text ...string) message.MessageSegment {
length := len(text)
return message.Text(text[rand.Intn(length)])
return message.Text(text[rand.Intn(len(text))])
}
func randImage(file ...string) message.MessageSegment {
length := len(file)
return message.Image(res + file[rand.Intn(length)])
return message.Image(res + file[rand.Intn(len(file))])
}
func randRecord(file ...string) message.MessageSegment {
length := len(file)
return message.Record(res + file[rand.Intn(length)])
}
// atriSwitch 控制 ATRI 的开关
func atriSwitch() zero.Rule {
return func(ctx *zero.Ctx) bool {
return enable
}
return message.Record(res + file[rand.Intn(len(file))])
}
// atriSleep 凌晨0点到6点ATRI 在睡觉,不回应任何请求
func atriSleep() zero.Rule {
return func(ctx *zero.Ctx) bool {
if now := time.Now().Hour(); now >= 1 && now < 6 {
return false
}
return true
func atriSleep(ctx *zero.Ctx) bool {
if now := time.Now().Hour(); now >= 1 && now < 6 {
return false
}
return true
}

90
plugin_b14/main.go Normal file
View File

@@ -0,0 +1,90 @@
package b14coder
import (
"unsafe"
base14 "github.com/fumiama/go-base16384"
tea "github.com/fumiama/gofastTEA"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() {
en := control.Register("base16384", &control.Options{
DisableOnDefault: false,
Help: "base16384加解密\n" +
"- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
})
en.OnRegex(`^加密(.*)`).SetBlock(true).ThirdPriority().
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es, err := base14.UTF16be2utf8(base14.EncodeString(str))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(es)))
} else {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex("^解密([\u4e00-\u8e00]*[\u3d01-\u3d06]?)$").SetBlock(true).ThirdPriority().
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es, err := base14.UTF82utf16be(helper.StringToBytes(str))
if err == nil {
ctx.SendChain(message.Text(base14.DecodeString(es)))
} else {
ctx.SendChain(message.Text("解密失败!"))
}
})
en.OnRegex(`^用(.*)加密(.*)`).SetBlock(true).ThirdPriority().
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)
es, err := base14.UTF16be2utf8(base14.Encode(t.Encrypt(helper.StringToBytes(str))))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(es)))
} else {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex("^用(.*)解密([\u4e00-\u8e00]*[\u3d01-\u3d06]?)$").SetBlock(true).ThirdPriority().
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)
es, err := base14.UTF82utf16be(helper.StringToBytes(str))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(t.Decrypt(base14.Decode(es)))))
} else {
ctx.SendChain(message.Text("解密失败!"))
}
})
}
// Slice is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
//
// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
// data it references will not be garbage collected.
type slice struct {
Data unsafe.Pointer
Len int
Cap int
}
func getea(key string) tea.TEA {
kr := []rune(key)
if len(kr) > 4 {
kr = kr[:4]
} else {
for len(kr) < 4 {
kr = append(kr, rune(4-len(kr)))
}
}
skr := *(*slice)(unsafe.Pointer(&kr))
skr.Len *= 4
skr.Cap *= 4
return tea.NewTeaCipher(*(*[]byte)(unsafe.Pointer(&skr)))
}

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
"github.com/robfig/cron"
"github.com/fumiama/cron"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
@@ -32,12 +32,15 @@ func init() {
// 定时任务每天晚上最后2分钟执行一次
func fansDaily(groupID int64) {
c := cron.New()
_ = c.AddFunc("0 58 23 * * ?", func() { fansData(groupID) })
c.Start()
_, err := c.AddFunc("58 23 * * *", func() { fansData(groupID) })
if err == nil {
c.Start()
}
}
// 获取数据拼接消息链并发送
func fansData(groupID int64) {
// TODO: 更改为 GetBot
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
var (
diana = fansapi("672328094")

View File

@@ -12,17 +12,16 @@ import (
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var engine *zero.Engine
var engine = control.Register("bilibili", &control.Options{
DisableOnDefault: false,
Help: "bilibili\n" +
"- >vup info [名字|uid]\n" +
"- >user info [名字|uid]\n" +
"- /开启粉丝日报",
})
// 查成分的
func init() {
engine = control.Register("bilibili", &control.Options{
DisableOnDefault: false,
Help: "bilibili\n" +
"- >vup info [名字|uid]\n" +
"- >user info [名字|uid]\n" +
"- /开启粉丝日报",
})
engine.OnRegex(`^>user info\s(.{1,25})$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]

37
plugin_choose/choose.go Normal file
View File

@@ -0,0 +1,37 @@
// Package choose 选择困难症帮手
package choose
import (
"math/rand"
"strconv"
"strings"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() {
engine := control.Register("choose", &control.Options{
DisableOnDefault: false,
Help: "choose\n" +
"- 选择可口可乐还是百事可乐\n" +
"- 选择肯德基还是麦当劳还是必胜客\n",
})
engine.OnPrefix("选择").SetBlock(true).FirstPriority().Handle(handle)
}
func handle(ctx *zero.Ctx) {
rawOptions := strings.Split(ctx.State["args"].(string), "还是")
var options = make([]string, 0)
for count, option := range rawOptions {
options = append(options, strconv.Itoa(count+1)+", "+option)
}
result := rawOptions[rand.Intn(len(rawOptions))]
name := ctx.Event.Sender.NickName
ctx.SendChain(message.Text("> ", name, "\n",
"你的选项有:", "\n",
strings.Join(options, "\n"), "\n",
"你最终会选: ", result,
))
}

View File

@@ -2,11 +2,11 @@
package diana
import (
fmt "fmt"
"math/rand"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_diana/data"
@@ -28,22 +28,22 @@ func init() {
Handle(func(ctx *zero.Ctx) {
rand.Seed(time.Now().UnixNano())
// 绕过第一行发病
ctx.Send((*data.Array)[rand.Intn(len(*data.Array)-1)+1])
ctx.SendChain(message.Text((*data.Array)[rand.Intn(len(*data.Array)-1)+1]))
})
// 逆天
engine.OnFullMatch("发大病").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 第一行是发病
ctx.Send((*data.Array)[0])
ctx.SendChain(message.Text((*data.Array)[0]))
})
// 增加小作文
engine.OnRegex(`^教你一篇小作文(.*)$`, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := data.AddText(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
ctx.SendChain(message.Text("ERROR: ", err))
} else {
ctx.Send("记住啦!")
ctx.SendChain(message.Text("记住啦!"))
}
})
}

View File

@@ -3,20 +3,23 @@ package data
import (
"crypto/md5"
"errors"
"io"
"net/http"
"os"
"sync"
"time"
"unsafe"
log "github.com/sirupsen/logrus"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
const (
datapath = "data/Diana"
pbfile = datapath + "/text.pb"
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/data/Diana/text.pb"
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + pbfile
)
var (
@@ -26,12 +29,12 @@ var (
// m 小作文保存锁
m sync.Mutex
// md5s 验证重复
md5s [][16]byte
md5s []*[16]byte
)
func init() {
go func() {
time.Sleep(time.Second)
process.SleepAbout1sTo2s()
err := os.MkdirAll(datapath, 0755)
if err != nil {
panic(err)
@@ -40,9 +43,10 @@ func init() {
if err1 == nil {
arrl := len(*Array)
log.Printf("[Diana]读取%d条小作文", arrl)
md5s = make([][16]byte, arrl)
md5s = make([]*[16]byte, arrl)
for i, t := range *Array {
md5s[i] = md5.Sum(str2bytes(t))
m := md5.Sum(helper.StringToBytes(t))
md5s[i] = &m
}
} else {
log.Printf("[Diana]读取小作文错误:%v", err1)
@@ -52,7 +56,7 @@ func init() {
// LoadText 加载小作文
func LoadText() error {
if _, err := os.Stat(pbfile); err == nil || os.IsExist(err) {
if file.IsExist(pbfile) {
f, err := os.Open(pbfile)
if err == nil {
defer f.Close()
@@ -91,20 +95,20 @@ func LoadText() error {
// AddText 添加小作文
func AddText(txt string) error {
sum := md5.Sum(str2bytes(txt))
if txt != "" && !isin(sum) {
sum := md5.Sum(helper.StringToBytes(txt))
if txt != "" && !isin(&sum) {
m.Lock()
defer m.Unlock()
compo.Array = append(compo.Array, txt)
md5s = append(md5s, sum)
md5s = append(md5s, &sum)
return savecompo()
}
return nil
}
func isin(sum [16]byte) bool {
func isin(sum *[16]byte) bool {
for _, t := range md5s {
if t == sum {
if *t == *sum {
return true
}
}
@@ -115,7 +119,7 @@ func isin(sum [16]byte) bool {
func savecompo() error {
data, err := compo.Marshal()
if err == nil {
if _, err := os.Stat(datapath); err == nil || os.IsExist(err) {
if file.IsExist(datapath) {
f, err1 := os.OpenFile(pbfile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 == nil {
_, err2 := f.Write(data)
@@ -124,13 +128,7 @@ func savecompo() error {
}
return err1
}
return errors.New("datapath is not exist")
}
return err
}
// str2bytes Fast convert
func str2bytes(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}

View File

@@ -1,3 +1,4 @@
// Package diana 嘉然相关
package diana
import (
@@ -37,12 +38,12 @@ func init() {
zhiwangjson := zhiwangapi(msg)
if zhiwangjson == nil || zhiwangjson.Code != 0 {
ctx.Send("api返回错误")
ctx.SendChain(message.Text("api返回错误"))
return
}
if len(zhiwangjson.Data.Related) == 0 {
ctx.Send("枝网没搜到查重率为0%,我的评价是:一眼真")
ctx.SendChain(message.Text("枝网没搜到查重率为0%,我的评价是:一眼真"))
return
}

405
plugin_fortune/cfg.pb.go Normal file
View File

@@ -0,0 +1,405 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cfg.proto
package fortune
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Conf struct {
Kind map[int64]uint32 `protobuf:"bytes,1,rep,name=kind,proto3" json:"kind,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Conf) Reset() { *m = Conf{} }
func (m *Conf) String() string { return proto.CompactTextString(m) }
func (*Conf) ProtoMessage() {}
func (*Conf) Descriptor() ([]byte, []int) {
return fileDescriptor_f81ba022997f8a9d, []int{0}
}
func (m *Conf) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Conf) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Conf.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Conf) XXX_Merge(src proto.Message) {
xxx_messageInfo_Conf.Merge(m, src)
}
func (m *Conf) XXX_Size() int {
return m.Size()
}
func (m *Conf) XXX_DiscardUnknown() {
xxx_messageInfo_Conf.DiscardUnknown(m)
}
var xxx_messageInfo_Conf proto.InternalMessageInfo
func (m *Conf) GetKind() map[int64]uint32 {
if m != nil {
return m.Kind
}
return nil
}
func init() {
proto.RegisterType((*Conf)(nil), "fortune.conf")
proto.RegisterMapType((map[int64]uint32)(nil), "fortune.conf.KindEntry")
}
func init() { proto.RegisterFile("cfg.proto", fileDescriptor_f81ba022997f8a9d) }
var fileDescriptor_f81ba022997f8a9d = []byte{
// 154 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x4e, 0x4b, 0xd7,
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4f, 0xcb, 0x2f, 0x2a, 0x29, 0xcd, 0x4b, 0x55, 0xca,
0xe1, 0x62, 0x49, 0xce, 0xcf, 0x4b, 0x13, 0xd2, 0xe6, 0x62, 0xc9, 0xce, 0xcc, 0x4b, 0x91, 0x60,
0x54, 0x60, 0xd6, 0xe0, 0x36, 0x12, 0xd7, 0x83, 0xca, 0xeb, 0x81, 0x24, 0xf5, 0xbc, 0x33, 0xf3,
0x52, 0x5c, 0xf3, 0x4a, 0x8a, 0x2a, 0x83, 0xc0, 0x8a, 0xa4, 0xcc, 0xb9, 0x38, 0xe1, 0x42, 0x42,
0x02, 0x5c, 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x20, 0xa6, 0x90,
0x08, 0x17, 0x6b, 0x59, 0x62, 0x4e, 0x69, 0xaa, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6f, 0x10, 0x84,
0x63, 0xc5, 0x64, 0xc1, 0xe8, 0x24, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f,
0x1e, 0xc9, 0x31, 0xce, 0x78, 0x2c, 0xc7, 0x90, 0xc4, 0x06, 0x76, 0x8f, 0x31, 0x20, 0x00, 0x00,
0xff, 0xff, 0x8a, 0xa2, 0xbe, 0x9e, 0x9c, 0x00, 0x00, 0x00,
}
func (m *Conf) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Conf) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Conf) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Kind) > 0 {
for k := range m.Kind {
v := m.Kind[k]
baseI := i
i = encodeVarintCfg(dAtA, i, uint64(v))
i--
dAtA[i] = 0x10
i = encodeVarintCfg(dAtA, i, uint64(k))
i--
dAtA[i] = 0x8
i = encodeVarintCfg(dAtA, i, uint64(baseI-i))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintCfg(dAtA []byte, offset int, v uint64) int {
offset -= sovCfg(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Conf) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Kind) > 0 {
for k, v := range m.Kind {
_ = k
_ = v
mapEntrySize := 1 + sovCfg(uint64(k)) + 1 + sovCfg(uint64(v))
n += mapEntrySize + 1 + sovCfg(uint64(mapEntrySize))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovCfg(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozCfg(x uint64) (n int) {
return sovCfg(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Conf) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: conf: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: conf: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthCfg
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthCfg
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Kind == nil {
m.Kind = make(map[int64]uint32)
}
var mapkey int64
var mapvalue uint32
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapkey |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
} else if fieldNum == 2 {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapvalue |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
} else {
iNdEx = entryPreIndex
skippy, err := skipCfg(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthCfg
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
m.Kind[mapkey] = mapvalue
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipCfg(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthCfg
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipCfg(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowCfg
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowCfg
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowCfg
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthCfg
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupCfg
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthCfg
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthCfg = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowCfg = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupCfg = fmt.Errorf("proto: unexpected end of group")
)

6
plugin_fortune/cfg.proto Normal file
View File

@@ -0,0 +1,6 @@
syntax = "proto3";
package fortune;
message conf {
map<int64, uint32> kind = 1;
}

55
plugin_fortune/data.go Normal file
View File

@@ -0,0 +1,55 @@
package fortune
import (
"errors"
io "io"
"os"
"sync"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
)
var (
conf Conf
mu sync.Mutex
)
func loadcfg(name string) error {
name = base + name
if file.IsExist(name) {
f, err := os.Open(name)
if err == nil {
defer f.Close()
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
return conf.Unmarshal(data)
}
}
return err1
}
} else { // 如果没有 cfg则使用空 map
conf.Kind = make(map[int64]uint32)
}
return nil
}
func savecfg(name string) error {
name = base + name
data, err := conf.Marshal()
if err == nil {
if file.IsExist(base) {
f, err1 := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 == nil {
mu.Lock()
_, err2 := f.Write(data)
f.Close()
mu.Unlock()
return err2
}
return err1
}
return errors.New("base dir is not exist")
}
return err
}

321
plugin_fortune/fortune.go Normal file
View File

@@ -0,0 +1,321 @@
// Package fortune 每日运势
package fortune
import (
"archive/zip"
"bytes"
"encoding/base64"
"encoding/json"
"image/jpeg"
"io"
"io/ioutil"
"math/rand"
"os"
"strconv"
"sync"
"time"
"github.com/fogleman/gg"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
)
var (
// 底图缓存位置
base = "data/fortune/"
// 素材下载网站
site = "https://pan.dihe.moe/fortune/"
// 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师"}
// 映射底图与 index
index = make(map[string]uint32)
// 下载锁
dlmu sync.Mutex
)
func init() {
err := loadcfg("cfg.pb")
if err != nil {
panic(err)
}
for i, s := range table {
index[s] = uint32(i)
}
err = os.MkdirAll(base, 0755)
if err != nil {
panic(err)
}
// 插件主体
en := control.Register("fortune", &control.Options{
DisableOnDefault: false,
Help: "每日运势: \n" +
"- 运势|抽签\n" +
"- 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师]",
})
en.OnRegex(`^设置底图(.*)`).SetBlock(true).SecondPriority().
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
if gid <= 0 {
// 个人用户设为负数
gid = -ctx.Event.UserID
}
i, ok := index[ctx.State["regex_matched"].([]string)[1]]
if ok {
conf.Kind[gid] = i
savecfg("cfg.pb")
ctx.SendChain(message.Text("设置成功~"))
} else {
ctx.SendChain(message.Text("没有这个底图哦~"))
}
})
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).SecondPriority().
Handle(func(ctx *zero.Ctx) {
// 检查签文文件是否存在
mikuji := base + "运势签文.json"
if file.IsNotExist(mikuji) {
dlmu.Lock()
if file.IsNotExist(mikuji) {
ctx.SendChain(message.Text("正在下载签文文件,请稍后..."))
err := file.DownloadTo(site+"运势签文.json", mikuji, false)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("下载签文文件完毕"))
}
dlmu.Unlock()
}
// 检查字体文件是否存在
ttf := base + "sakura.ttf"
if file.IsNotExist(ttf) {
dlmu.Lock()
if file.IsNotExist(ttf) {
ctx.SendChain(message.Text("正在下载字体文件,请稍后..."))
err := file.DownloadTo(site+"sakura.ttf", ttf, false)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("下载字体文件完毕"))
}
dlmu.Unlock()
}
// 获取该群背景类型,默认车万
kind := "车万"
gid := ctx.Event.GroupID
if gid <= 0 {
// 个人用户设为负数
gid = -ctx.Event.UserID
}
logrus.Debugln("[fortune]gid:", ctx.Event.GroupID, "uid:", ctx.Event.UserID)
if v, ok := conf.Kind[gid]; ok {
kind = table[v]
}
// 检查背景图片是否存在
folder := base + kind
if file.IsNotExist(folder) {
dlmu.Lock()
if file.IsNotExist(folder) {
ctx.SendChain(message.Text("正在下载背景图片,请稍后..."))
zipfile := kind + ".zip"
zipcache := base + zipfile
err := file.DownloadTo(site+zipfile, zipcache, false)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("下载背景图片完毕"))
err = unpack(zipcache, folder+"/")
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("解压背景图片完毕"))
// 释放空间
os.Remove(zipcache)
}
dlmu.Unlock()
}
// 生成种子
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
seed := ctx.Event.UserID + t
// 随机获取背景
background, err := randimage(folder+"/", seed)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 随机获取签文
title, text, err := randtext(mikuji, seed)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 绘制背景
d, err := draw(background, title, text)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 发送图片
ctx.SendChain(message.Image("base64://" + helper.BytesToString(d)))
})
}
// @function unpack 解压资源包
// @param tgt 压缩文件位置
// @param dest 解压位置
// @return 错误信息
func unpack(tgt, dest string) error {
// 路径目录不存在则创建目录
if file.IsNotExist(dest) {
if err := os.MkdirAll(dest, 0755); err != nil {
panic(err)
}
}
reader, err := zip.OpenReader(tgt)
if err != nil {
return err
}
defer reader.Close()
// 遍历解压到文件
for _, file := range reader.File {
// 打开解压文件
rc, err := file.Open()
if err != nil {
return err
}
// 打开目标文件
w, err := os.OpenFile(dest+file.Name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
rc.Close()
return err
}
// 复制到文件
_, err = io.Copy(w, rc)
rc.Close()
w.Close()
if err != nil {
return err
}
}
return nil
}
// @function randimage 随机选取文件夹下的文件
// @param path 文件夹路径
// @param seed 随机数种子
// @return 文件路径 & 错误信息
func randimage(path string, seed int64) (string, error) {
rd, err := ioutil.ReadDir(path)
if err != nil {
return "", err
}
rand.Seed(seed)
return path + rd[rand.Intn(len(rd))].Name(), nil
}
// @function randtext 随机选取签文
// @param file 文件路径
// @param seed 随机数种子
// @return 签名 & 签文 & 错误信息
func randtext(file string, seed int64) (string, string, error) {
data, err := ioutil.ReadFile(file)
if err != nil {
return "", "", err
}
temp := []map[string]string{}
if err := json.Unmarshal(data, &temp); err != nil {
return "", "", err
}
rand.Seed(seed)
r := rand.Intn(len(temp))
return temp[r]["title"], temp[r]["content"], nil
}
// @function draw 绘制运势图
// @param background 背景图片路径
// @param seed 随机数种子
// @param title 签名
// @param text 签文
// @return 错误信息
func draw(background, title, text string) ([]byte, error) {
// 加载背景
back, err := gg.LoadImage(background)
if err != nil {
return nil, err
}
canvas := gg.NewContext(back.Bounds().Size().Y, back.Bounds().Size().X)
canvas.DrawImage(back, 0, 0)
// 写标题
canvas.SetRGB(1, 1, 1)
if err := canvas.LoadFontFace(base+"sakura.ttf", 45); err != nil {
return nil, err
}
sw, _ := canvas.MeasureString(title)
canvas.DrawString(title, 140-sw/2, 112)
// 写正文
canvas.SetRGB(0, 0, 0)
if err := canvas.LoadFontFace(base+"sakura.ttf", 23); err != nil {
return nil, err
}
tw, th := canvas.MeasureString("测")
tw, th = tw+10, th+10
r := []rune(text)
xsum := rowsnum(len(r), 9)
switch xsum {
default:
for i, o := range r {
xnow := rowsnum(i+1, 9)
ysum := math.Min(len(r)-(xnow-1)*9, 9)
ynow := i%9 + 1
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(ysum, ynow, th)+320.0)
}
case 2:
div := rowsnum(len(r), 2)
for i, o := range r {
xnow := rowsnum(i+1, div)
ysum := math.Min(len(r)-(xnow-1)*div, div)
ynow := i%div + 1
switch xnow {
case 1:
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow, th)+320.0)
case 2:
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow+(9-ysum), th)+320.0)
}
}
}
// 转成 base64
buffer := new(bytes.Buffer)
encoder := base64.NewEncoder(base64.StdEncoding, buffer)
var opt jpeg.Options
opt.Quality = 70
err = jpeg.Encode(encoder, canvas.Image(), &opt)
if err != nil {
return nil, err
}
encoder.Close()
return buffer.Bytes(), nil
}
func offest(total, now int, distance float64) float64 {
if total%2 == 0 {
return (float64(now-total/2) - 1) * distance
}
return (float64(now-total/2) - 1.5) * distance
}
func rowsnum(total, div int) int {
temp := total / div
if total%div != 0 {
temp++
}
return temp
}

View File

@@ -6,22 +6,41 @@ import (
"os"
"strconv"
"strings"
"time"
"github.com/imroc/req"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
)
const cachedir = "data/hs/"
var (
cachedir = file.BOT_PATH + "/data/hs/"
reqconf = [...]string{"GET", "https://hs.fbigame.com",
"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}
)
var header = req.Header{
"user-agent": `Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36`,
"referer": `https://hs.fbigame.com`,
}
const (
hs = `https://hs.fbigame.com/ajax.php?`
para = "mod=get_cards_list&" +
"mode=-1&" +
"extend=-1&" +
"mutil_extend=&" +
"hero=-1&" +
"rarity=-1&" +
"cost=-1&" +
"mutil_cost=&" +
"techlevel=-1&" +
"type=-1&" +
"collectible=-1&" +
"isbacon=-1&" +
"page=1&" +
"search_type=1&" +
"deckmode=normal"
)
func init() {
os.RemoveAll(cachedir)
@@ -41,40 +60,41 @@ func init() {
SetBlock(true).SetPriority(20).Handle(func(ctx *zero.Ctx) {
List := ctx.State["regex_matched"].([]string)[1]
g := sh(List)
im, _ := req.Get(`https://res.fbigame.com/hs/v13/`+
gjson.Get(g, `list.0.CardID`).String()+
`.png?auth_key=`+
gjson.Get(g, `list.0.auth_key`).String(), header)
cachefile := cachedir + strconv.Itoa(int(time.Now().Unix()))
err := im.ToFile(cachefile)
if err == nil {
file, err := os.Open(cachefile)
if err == nil {
defer file.Close()
sg, _ := req.Post("https://pic.sogou.com/pic/upload_pic.jsp", req.FileUpload{
File: file,
FieldName: "image", // FieldName 是表单字段名
FileName: "avatar.png", // Filename 是要上传的文件的名称我们使用它来猜测mimetype并将其上传到服务器上
})
var tx string
t := int(gjson.Get(g, `list.#`).Int())
if t == 0 {
ctx.Send("查询为空!")
return
}
for i := 0; i < t && i < 10; i++ {
tx += strconv.Itoa(i+1) + ". 法力:" +
gjson.Get(g, `list.`+strconv.Itoa(i)+`.COST`).String() +
" " +
gjson.Get(g, `list.`+strconv.Itoa(i)+`.CARDNAME`).String() +
"\n"
}
ctx.SendChain(
message.Image(sg.String()),
message.Text(tx),
)
}
t := int(gjson.Get(g, `list.#`).Int())
if t == 0 {
ctx.SendChain(message.Text("查询为空!"))
return
}
var sk message.Message
for i := 0; i < t && i < 5; i++ {
cid := gjson.Get(g, `list.`+strconv.Itoa(i)+`.CardID`).String()
cachefile := cachedir + cid
imgcq := `[CQ:image,file=` + "file:///" + cachefile + `]`
if file.IsNotExist(cachefile) {
data, err := web.ReqWith(
`https://res.fbigame.com/hs/v13/`+cid+`.png?auth_key=`+
gjson.Get(g, `list.`+strconv.Itoa(i)+`.auth_key`).String(),
reqconf[0], reqconf[1], reqconf[2])
if err == nil {
err = os.WriteFile(cachefile, data, 0644)
}
if err != nil {
imgcq = err.Error()
}
}
sk = append(
sk,
message.CustomNode(
ctx.Event.Sender.NickName,
ctx.Event.UserID,
imgcq, // 图片
),
)
}
ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
sk,
)
})
// 卡组
engine.OnRegex(`^[\s\S]*?(AAE[a-zA-Z0-9/\+=]{70,})[\s\S]*$`).
@@ -88,39 +108,25 @@ func init() {
}
func sh(s string) string {
var hs = `https://hs.fbigame.com/ajax.php`
h, _ := req.Get("https://hs.fbigame.com", header)
var param = req.Param{
"mod": `get_cards_list`,
"mode": `-1`,
"extend": `-1`,
"mutil_extend": ``,
"hero": `-1`,
"rarity": `-1`,
"cost": `-1`,
"mutil_cost": ``,
"techlevel": `-1`,
"type": `-1`,
"collectible": `-1`,
"isbacon": `-1`,
"page": `1`,
"search_type": `1`,
"deckmode": "normal",
"hash": strings.SplitN(strings.SplitN(h.String(), `var hash = "`, 2)[1], `"`, 2)[0],
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
if err == nil {
url := hs + para + "&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
r, err := web.ReqWith(url, reqconf[0], reqconf[1], reqconf[2])
if err == nil {
return helper.BytesToString(r)
}
}
r, _ := req.Get(hs, header, param, req.Param{"search": s})
return r.String()
return ""
}
func kz(s string) string {
h, _ := req.Get("https://hs.fbigame.com")
param := req.Param{
"mod": `general_deck_image`,
"deck_code": s,
"deck_text": ``,
"hash": strings.SplitN(strings.SplitN(h.String(), `var hash = "`, 2)[1], `"`, 2)[0],
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
if err == nil {
url := hs + para + "mod=general_deck_image&deck_code=" + s + "&deck_text=&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
r, err := web.ReqWith(url, reqconf[0], reqconf[1], reqconf[2])
if err == nil {
return "base64://" + gjson.Get(helper.BytesToString(r), "img").String()
}
}
r, _ := req.Get(`https://hs.fbigame.com/ajax.php`, param, h.Request().Header)
im := gjson.Get(r.String(), "img").String()
return `base64://` + im
return ""
}

View File

@@ -69,9 +69,9 @@ func init() {
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
soutujson := soutuapi(keyword)
pom1 := "https://i.pixiv.cat"
rannum := randint()
pom2 := soutujson.Illusts[rannum].ImageUrls.Large[19:]
pom1 := "https://i.pixiv.re"
rannum := randintn(len(soutujson.Illusts))
pom2 := soutujson.Illusts[rannum].ImageUrls.Medium[19:]
ctx.SendChain(message.Image(pom1 + pom2))
})
}
@@ -88,7 +88,7 @@ func soutuapi(keyword string) *resultjson {
fmt.Println(err)
}
req.Header.Add("accept", "application/json, text/plain, */*")
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
@@ -102,8 +102,8 @@ func soutuapi(keyword string) *resultjson {
return result
}
// randint 从json里的30条数据中随机获取一条返回
func randint() int {
// randintn 从json里的30条数据中随机获取一条返回
func randintn(len int) int {
rand.Seed(time.Now().UnixNano())
return rand.Intn(30)
return rand.Intn(len)
}

View File

@@ -4,6 +4,7 @@ package lolicon
import (
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/tidwall/gjson"
@@ -11,6 +12,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
)
const (
@@ -30,7 +32,7 @@ func init() {
}).OnFullMatch("来份萝莉").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
go func() {
for i := 0; i < min(cap(queue)-len(queue), 2); i++ {
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
resp, err := http.Get(api)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
@@ -48,7 +50,7 @@ func init() {
continue
}
url := json.Get("data.0.urls.original").Str
ctx.SendGroupMessage(0, message.Image(url))
ctx.SendGroupMessage(0, message.Image(strings.ReplaceAll(url, "i.pixiv.cat", "i.pixiv.re")))
queue <- url
}
}()
@@ -60,10 +62,3 @@ func init() {
}
})
}
func min(a, b int) int {
if a < b {
return a
}
return b
}

View File

@@ -6,20 +6,26 @@ import (
"io"
"math/rand"
"os"
"sort"
"strconv"
"strings"
"time"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
timer "github.com/FloatTech/ZeroBot-Plugin-Timer"
"github.com/FloatTech/ZeroBot-Plugin/plugin_manager/timer"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
)
const (
datapath = "data/manager/"
confile = datapath + "config.pb"
hint = "====群管====\n" +
datapath = "data/manager/"
confile = datapath + "config.pb"
timerfile = datapath + "timers.pb"
hint = "====群管====\n" +
"- 禁言@QQ 1分钟\n" +
"- 解除禁言 @QQ\n" +
"- 我要自闭 1分钟\n" +
@@ -38,6 +44,8 @@ const (
"- 在MM月[每周|周几]的hh点mm分时(用http://url)提醒大家XXX\n" +
"- 取消在MM月dd日的hh点mm分的提醒\n" +
"- 取消在MM月[每周|周几]的hh点mm分的提醒\n" +
"- [x] 在\"cron\"时(用[url])提醒大家[xxx]\n" +
"- [x] 取消在\"cron\"的提醒\n" +
"- 列出所有提醒\n" +
"- 翻牌\n" +
"- 设置欢迎语XXX\n" +
@@ -46,14 +54,20 @@ const (
var (
config Config
limit = rate.NewManager(time.Minute*5, 2)
clock timer.Clock
)
func init() { // 插件主体
loadConfig()
go func() {
time.Sleep(time.Second + time.Millisecond*time.Duration(rand.Intn(1000)))
clock = timer.NewClock(timerfile)
}()
// 菜单
zero.OnFullMatch("群管系统", zero.AdminPermission).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
ctx.Send(hint)
ctx.SendChain(message.Text(hint))
})
// 升为管理
zero.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
@@ -161,18 +175,18 @@ func init() { // 插件主体
ctx.SendChain(message.Text("小黑屋释放成功~"))
})
// 自闭禁言
zero.OnRegex(`^我要自闭.*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
zero.OnRegex(`^(我要自闭|禅定).*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
duration := strToInt(ctx.State["regex_matched"].([]string)[1])
switch ctx.State["regex_matched"].([]string)[2] {
case "分钟":
//
case "小时":
duration := strToInt(ctx.State["regex_matched"].([]string)[2])
switch ctx.State["regex_matched"].([]string)[3] {
case "分钟", "min", "mins", "m":
break
case "小时", "hour", "hours", "h":
duration *= 60
case "天":
case "天", "day", "days", "d":
duration *= 60 * 24
default:
//
break
}
if duration >= 43200 {
duration = 43199 // qq禁言最大时长为一个月
@@ -241,59 +255,108 @@ func init() { // 插件主体
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
})
// 定时提醒
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.AdminPermission).SetBlock(true).SetPriority(40).
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimeStamp(dateStrs, false)
ts.Grpid = uint64(ctx.Event.GroupID)
if ts.Enable {
go timer.RegisterTimer(ts, true)
ctx.Send("记住了~")
} else {
ctx.Send("参数非法!")
}
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, false)
if ts.En() {
go clock.RegisterTimer(ts, ctx.Event.GroupID, true)
ctx.SendChain(message.Text("记住了~"))
} else {
ctx.SendChain(message.Text("参数非法:" + ts.Alert))
}
})
// 定时 cron 提醒
zero.OnRegex(`^在"(.*)"时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
var url, alert string
switch len(dateStrs) {
case 4:
url = dateStrs[2]
alert = dateStrs[3]
case 3:
alert = dateStrs[2]
default:
ctx.SendChain(message.Text("参数非法!"))
return
}
logrus.Debugln("[manager] cron:", dateStrs[1])
ts := timer.GetFilledCronTimer(dateStrs[1], alert, url, ctx.Event.SelfID)
if clock.RegisterTimer(ts, ctx.Event.GroupID, true) {
ctx.SendChain(message.Text("记住了~"))
} else {
ctx.SendChain(message.Text("参数非法:" + ts.Alert))
}
})
// 取消定时
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.AdminPermission).SetBlock(true).SetPriority(40).
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimeStamp(dateStrs, true)
ts.Grpid = uint64(ctx.Event.GroupID)
ti := timer.GetTimerInfo(ts)
t, ok := (*timer.Timers)[ti]
if ok {
t.Enable = false
delete(*timer.Timers, ti) // 避免重复取消
_ = timer.SaveTimers()
ctx.Send("取消成功~")
} else {
ctx.Send("没有这个定时器哦~")
}
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, true)
ti := ts.GetTimerInfo(ctx.Event.GroupID)
ok := clock.CancelTimer(ti)
if ok {
ctx.SendChain(message.Text("取消成功~"))
} else {
ctx.SendChain(message.Text("没有这个定时器哦~"))
}
})
// 取消 cron 定时
zero.OnRegex(`^取消在"(.*)"的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.Timer{Cron: dateStrs[1]}
ti := ts.GetTimerInfo(ctx.Event.GroupID)
ok := clock.CancelTimer(ti)
if ok {
ctx.SendChain(message.Text("取消成功~"))
} else {
ctx.SendChain(message.Text("没有这个定时器哦~"))
}
})
// 列出本群所有定时
zero.OnFullMatch("列出所有提醒", zero.AdminPermission).SetBlock(true).SetPriority(40).
zero.OnFullMatch("列出所有提醒", zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
ctx.Send(fmt.Sprint(timer.ListTimers(uint64(ctx.Event.GroupID))))
}
ctx.SendChain(message.Text(clock.ListTimers(uint64(ctx.Event.GroupID))))
})
// 随机点名
zero.OnFullMatchGroup([]string{"翻牌"}).SetBlock(true).SetPriority(40).
zero.OnFullMatchGroup([]string{"翻牌"}, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
list := ctx.GetGroupMemberList(ctx.Event.GroupID)
rand.Seed(time.Now().UnixNano())
randIndex := fmt.Sprint(rand.Intn(int(list.Get("#").Int())))
randCard := list.Get(randIndex + ".card").String()
if randCard == "" {
randCard = list.Get(randIndex + ".nickname").String()
}
ctx.Send(randCard + ",就是你啦!")
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.SendChain(message.Text("少女祈祷中......"))
return
}
// 无缓存获取群员列表
list := ctx.CallAction("get_group_member_list", zero.Params{
"group_id": ctx.Event.GroupID,
"no_cache": true,
}).Data
temp := list.Array()
sort.SliceStable(temp, func(i, j int) bool {
return temp[i].Get("last_sent_time").Int() < temp[j].Get("last_sent_time").Int()
})
temp = temp[math.Max(0, len(temp)-10):]
rand.Seed(time.Now().UnixNano())
who := temp[rand.Intn(len(temp))]
if who.Get("user_id").Int() == ctx.Event.SelfID {
ctx.SendChain(message.Text("幸运儿居然是我自己"))
return
}
if who.Get("user_id").Int() == ctx.Event.UserID {
ctx.SendChain(message.Text("哎呀,就是你自己了"))
return
}
nick := who.Get("card").Str
if nick == "" {
nick = who.Get("nickname").Str
}
ctx.SendChain(
message.Text(
nick,
" 就是你啦!",
),
)
})
// 入群欢迎
zero.OnNotice().SetBlock(false).FirstPriority().
@@ -301,9 +364,9 @@ func init() { // 插件主体
if ctx.Event.NoticeType == "group_increase" {
word, ok := config.Welcome[uint64(ctx.Event.GroupID)]
if ok {
ctx.Send(word)
ctx.SendChain(message.Text(word))
} else {
ctx.Send("欢迎~")
ctx.SendChain(message.Text("欢迎~"))
}
enable, ok1 := config.Checkin[uint64(ctx.Event.GroupID)]
if ok1 && enable {
@@ -320,7 +383,7 @@ func init() { // 插件主体
ans, err := strconv.Atoi(text)
if err == nil {
if ans != r {
ctx.Send("答案不对哦,再想想吧~")
ctx.SendChain(message.Text("答案不对哦,再想想吧~"))
return false
}
return true
@@ -333,12 +396,12 @@ func init() { // 插件主体
recv, cancel := next.Repeat()
select {
case <-time.After(time.Minute):
ctx.Send("拜拜啦~")
ctx.SendChain(message.Text("拜拜啦~"))
ctx.SetGroupKick(ctx.Event.GroupID, uid, false)
cancel()
case <-recv:
cancel()
ctx.Send("答对啦~")
ctx.SendChain(message.Text("答对啦~"))
}
}
}
@@ -355,9 +418,9 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
config.Welcome[uint64(ctx.Event.GroupID)] = ctx.State["regex_matched"].([]string)[1]
if saveConfig() == nil {
ctx.Send("记住啦!")
ctx.SendChain(message.Text("记住啦!"))
} else {
ctx.Send("出错啦!")
ctx.SendChain(message.Text("出错啦!"))
}
})
// 入群验证开关
@@ -373,9 +436,9 @@ func init() { // 插件主体
return
}
if saveConfig() == nil {
ctx.Send("已" + option)
ctx.SendChain(message.Text("已", option))
} else {
ctx.Send("出错啦!")
ctx.SendChain(message.Text("出错啦!"))
}
})
// 运行 CQ 码
@@ -384,6 +447,7 @@ func init() { // 插件主体
var cmd = ctx.State["regex_matched"].([]string)[1]
cmd = strings.ReplaceAll(cmd, "&#91;", "[")
cmd = strings.ReplaceAll(cmd, "&#93;", "]")
// 可注入,权限为主人
ctx.Send(cmd)
})
}
@@ -397,7 +461,7 @@ func strToInt(str string) int64 {
func loadConfig() {
mkdirerr := os.MkdirAll(datapath, 0755)
if mkdirerr == nil {
if _, err := os.Stat(confile); err == nil || os.IsExist(err) {
if file.IsExist(confile) {
f, err := os.Open(confile)
if err == nil {
data, err1 := io.ReadAll(f)
@@ -422,7 +486,7 @@ func saveConfig() error {
data, err := config.Marshal()
if err != nil {
return err
} else if _, err := os.Stat(datapath); err == nil || os.IsExist(err) {
} else if file.IsExist(datapath) {
f, err1 := os.OpenFile(confile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 != nil {
return err1

View File

@@ -0,0 +1,71 @@
package main
import (
"fmt"
io "io"
"os"
"time"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
)
var timersmap TimersMapOld
var timersmapnew TimersMap
func loadTimers(pbfile string) bool {
if file.IsExist(pbfile) {
f, err := os.Open(pbfile)
if err == nil {
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
err1 = timersmap.Unmarshal(data)
if err1 == nil {
return true
}
}
}
}
}
return false
}
// saveTimers 保存当前计时器
func saveTimers(pbfile string) error {
data, err := timersmapnew.Marshal()
if err == nil {
f, err1 := os.OpenFile(pbfile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 != nil {
return err1
} else {
_, err2 := f.Write(data)
f.Close()
return err2
}
}
return err
}
func main() {
if len(os.Args) == 3 {
if loadTimers(os.Args[1]) {
timersmapnew.Timers = make(map[string]*Timer)
for s, t := range timersmap.Timers {
tm := &Timer{
Alert: t.Alert,
Url: t.Url,
}
tm.SetMonth(time.Month(t.Month))
tm.SetDay(int(t.Day))
tm.SetHour(int(t.Hour))
tm.SetMinute(int(t.Minute))
tm.SetWeek(time.Weekday(t.Week))
tm.SetEn(t.Enable)
timersmapnew.Timers[s] = tm
}
saveTimers(os.Args[2])
}
} else {
fmt.Println("用法:旧文件路径 新文件路径")
}
}

View File

@@ -0,0 +1,946 @@
package main
import (
fmt "fmt"
io "io"
math "math"
math_bits "math/bits"
proto "github.com/golang/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type TimerOld struct {
Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"`
Alert string `protobuf:"bytes,2,opt,name=alert,proto3" json:"alert,omitempty"`
Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"`
Month int32 `protobuf:"zigzag32,4,opt,name=month,proto3" json:"month,omitempty"`
Day int32 `protobuf:"zigzag32,5,opt,name=day,proto3" json:"day,omitempty"`
Week int32 `protobuf:"zigzag32,6,opt,name=week,proto3" json:"week,omitempty"`
Hour int32 `protobuf:"zigzag32,7,opt,name=hour,proto3" json:"hour,omitempty"`
Minute int32 `protobuf:"zigzag32,8,opt,name=minute,proto3" json:"minute,omitempty"`
Grpid uint64 `protobuf:"varint,9,opt,name=grpid,proto3" json:"grpid,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TimerOld) Reset() { *m = TimerOld{} }
func (m *TimerOld) String() string { return proto.CompactTextString(m) }
func (*TimerOld) ProtoMessage() {}
func (*TimerOld) Descriptor() ([]byte, []int) {
return fileDescriptor_old, []int{0}
}
func (m *TimerOld) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *TimerOld) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Timer.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *TimerOld) XXX_Merge(src proto.Message) {
xxx_messageInfo_Timer.Merge(m, src)
}
func (m *TimerOld) XXX_Size() int {
return m.Size()
}
func (m *TimerOld) XXX_DiscardUnknown() {
xxx_messageInfo_Timer.DiscardUnknown(m)
}
func (m *TimerOld) GetEnable() bool {
if m != nil {
return m.Enable
}
return false
}
func (m *TimerOld) GetAlert() string {
if m != nil {
return m.Alert
}
return ""
}
func (m *TimerOld) GetUrl() string {
if m != nil {
return m.Url
}
return ""
}
func (m *TimerOld) GetMonth() int32 {
if m != nil {
return m.Month
}
return 0
}
func (m *TimerOld) GetDay() int32 {
if m != nil {
return m.Day
}
return 0
}
func (m *TimerOld) GetWeek() int32 {
if m != nil {
return m.Week
}
return 0
}
func (m *TimerOld) GetHour() int32 {
if m != nil {
return m.Hour
}
return 0
}
func (m *TimerOld) GetMinute() int32 {
if m != nil {
return m.Minute
}
return 0
}
func (m *TimerOld) GetGrpid() uint64 {
if m != nil {
return m.Grpid
}
return 0
}
type TimersMapOld struct {
Timers map[string]*TimerOld `protobuf:"bytes,1,rep,name=timers,proto3" json:"timers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TimersMapOld) Reset() { *m = TimersMapOld{} }
func (m *TimersMapOld) String() string { return proto.CompactTextString(m) }
func (*TimersMapOld) ProtoMessage() {}
func (*TimersMapOld) Descriptor() ([]byte, []int) {
return fileDescriptor_old, []int{1}
}
func (m *TimersMapOld) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *TimersMapOld) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_TimersMap.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *TimersMapOld) XXX_Merge(src proto.Message) {
xxx_messageInfo_TimersMap.Merge(m, src)
}
func (m *TimersMapOld) XXX_Size() int {
return m.Size()
}
func (m *TimersMapOld) XXX_DiscardUnknown() {
xxx_messageInfo_TimersMap.DiscardUnknown(m)
}
func (m *TimersMapOld) GetTimers() map[string]*TimerOld {
if m != nil {
return m.Timers
}
return nil
}
func init() {
proto.RegisterType((*TimerOld)(nil), "timer.Timer")
proto.RegisterType((*TimersMapOld)(nil), "timer.TimersMap")
proto.RegisterMapType((map[string]*TimerOld)(nil), "timer.TimersMap.TimersEntry")
}
func init() { proto.RegisterFile("timer.proto", fileDescriptor_old) }
var fileDescriptor_old = []byte{
// 278 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xcd, 0x4a, 0xc3, 0x40,
0x10, 0xc7, 0x9d, 0xe6, 0xc3, 0x66, 0xe3, 0xa1, 0x2e, 0x22, 0x83, 0x48, 0x08, 0x39, 0xe5, 0xd4,
0x43, 0xf5, 0x20, 0x1e, 0x05, 0xf1, 0xe4, 0x65, 0xf1, 0x05, 0x52, 0xba, 0xd8, 0xd0, 0x7c, 0xb1,
0xdd, 0x28, 0x79, 0x05, 0x9f, 0xc0, 0x17, 0x12, 0x3c, 0xfa, 0x08, 0x12, 0x5f, 0x44, 0x66, 0x36,
0x94, 0xde, 0x7e, 0xff, 0x5f, 0xfe, 0x64, 0x67, 0x46, 0xc4, 0xb6, 0xac, 0xb5, 0x59, 0x76, 0xa6,
0xb5, 0xad, 0x0c, 0x38, 0x64, 0x5f, 0x20, 0x82, 0x17, 0x22, 0x79, 0x29, 0x42, 0xdd, 0x14, 0xeb,
0x4a, 0x23, 0xa4, 0x90, 0xcf, 0xd5, 0x94, 0xe4, 0x85, 0x08, 0x8a, 0x4a, 0x1b, 0x8b, 0xb3, 0x14,
0xf2, 0x48, 0xb9, 0x20, 0x17, 0xc2, 0xeb, 0x4d, 0x85, 0x1e, 0x3b, 0x42, 0xea, 0xd5, 0x6d, 0x63,
0xb7, 0xe8, 0xa7, 0x90, 0x9f, 0x2b, 0x17, 0xa8, 0xb7, 0x29, 0x06, 0x0c, 0xd8, 0x11, 0x4a, 0x29,
0xfc, 0x77, 0xad, 0x77, 0x18, 0xb2, 0x62, 0x26, 0xb7, 0x6d, 0x7b, 0x83, 0xa7, 0xce, 0x11, 0xd3,
0x3c, 0x75, 0xd9, 0xf4, 0x56, 0xe3, 0x9c, 0xed, 0x94, 0xe8, 0x9d, 0x57, 0xd3, 0x95, 0x1b, 0x8c,
0x52, 0xc8, 0x7d, 0xe5, 0x42, 0xf6, 0x01, 0x22, 0xe2, 0x3d, 0xf6, 0xcf, 0x45, 0x27, 0x6f, 0x45,
0xc8, 0xeb, 0xed, 0x11, 0x52, 0x2f, 0x8f, 0x57, 0xd7, 0x4b, 0xb7, 0xfa, 0xa1, 0x31, 0xd1, 0x63,
0x63, 0xcd, 0xa0, 0xa6, 0xee, 0xd5, 0x93, 0x88, 0x8f, 0x34, 0x8d, 0xbe, 0xd3, 0x03, 0x5f, 0x23,
0x52, 0x84, 0x32, 0x13, 0xc1, 0x5b, 0x51, 0xf5, 0x9a, 0x4f, 0x11, 0xaf, 0xce, 0x8e, 0xff, 0xaa,
0xdc, 0xa7, 0xfb, 0xd9, 0x1d, 0x3c, 0x2c, 0xbe, 0xc7, 0x04, 0x7e, 0xc6, 0x04, 0x7e, 0xc7, 0x04,
0x3e, 0xff, 0x92, 0x93, 0x75, 0xc8, 0x47, 0xbf, 0xf9, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xe0, 0xc7,
0xad, 0xf8, 0x83, 0x01, 0x00, 0x00,
}
func (m *TimerOld) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *TimerOld) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *TimerOld) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if m.Grpid != 0 {
i = encodeVarintTimerOld(dAtA, i, uint64(m.Grpid))
i--
dAtA[i] = 0x48
}
if m.Minute != 0 {
i = encodeVarintTimerOld(dAtA, i, uint64((uint32(m.Minute)<<1)^uint32((m.Minute>>31))))
i--
dAtA[i] = 0x40
}
if m.Hour != 0 {
i = encodeVarintTimerOld(dAtA, i, uint64((uint32(m.Hour)<<1)^uint32((m.Hour>>31))))
i--
dAtA[i] = 0x38
}
if m.Week != 0 {
i = encodeVarintTimerOld(dAtA, i, uint64((uint32(m.Week)<<1)^uint32((m.Week>>31))))
i--
dAtA[i] = 0x30
}
if m.Day != 0 {
i = encodeVarintTimerOld(dAtA, i, uint64((uint32(m.Day)<<1)^uint32((m.Day>>31))))
i--
dAtA[i] = 0x28
}
if m.Month != 0 {
i = encodeVarintTimerOld(dAtA, i, uint64((uint32(m.Month)<<1)^uint32((m.Month>>31))))
i--
dAtA[i] = 0x20
}
if len(m.Url) > 0 {
i -= len(m.Url)
copy(dAtA[i:], m.Url)
i = encodeVarintTimerOld(dAtA, i, uint64(len(m.Url)))
i--
dAtA[i] = 0x1a
}
if len(m.Alert) > 0 {
i -= len(m.Alert)
copy(dAtA[i:], m.Alert)
i = encodeVarintTimerOld(dAtA, i, uint64(len(m.Alert)))
i--
dAtA[i] = 0x12
}
if m.Enable {
i--
if m.Enable {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func (m *TimersMapOld) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *TimersMapOld) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *TimersMapOld) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Timers) > 0 {
for k := range m.Timers {
v := m.Timers[k]
baseI := i
if v != nil {
{
size, err := v.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTimerOld(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
i -= len(k)
copy(dAtA[i:], k)
i = encodeVarintTimerOld(dAtA, i, uint64(len(k)))
i--
dAtA[i] = 0xa
i = encodeVarintTimerOld(dAtA, i, uint64(baseI-i))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintTimerOld(dAtA []byte, offset int, v uint64) int {
offset -= sovTimerOld(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *TimerOld) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Enable {
n += 2
}
l = len(m.Alert)
if l > 0 {
n += 1 + l + sovTimerOld(uint64(l))
}
l = len(m.Url)
if l > 0 {
n += 1 + l + sovTimerOld(uint64(l))
}
if m.Month != 0 {
n += 1 + sozTimerOld(uint64(m.Month))
}
if m.Day != 0 {
n += 1 + sozTimerOld(uint64(m.Day))
}
if m.Week != 0 {
n += 1 + sozTimerOld(uint64(m.Week))
}
if m.Hour != 0 {
n += 1 + sozTimerOld(uint64(m.Hour))
}
if m.Minute != 0 {
n += 1 + sozTimerOld(uint64(m.Minute))
}
if m.Grpid != 0 {
n += 1 + sovTimerOld(uint64(m.Grpid))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *TimersMapOld) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Timers) > 0 {
for k, v := range m.Timers {
_ = k
_ = v
l = 0
if v != nil {
l = v.Size()
l += 1 + sovTimerOld(uint64(l))
}
mapEntrySize := 1 + len(k) + sovTimerOld(uint64(len(k))) + l
n += mapEntrySize + 1 + sovTimerOld(uint64(mapEntrySize))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovTimerOld(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozTimerOld(x uint64) (n int) {
return sovTimerOld(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *TimerOld) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Timer: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Timer: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Enable", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Enable = bool(v != 0)
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Alert", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimerOld
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimerOld
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Alert = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Url", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimerOld
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimerOld
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Url = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Month", wireType)
}
var v int32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))
m.Month = v
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Day", wireType)
}
var v int32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))
m.Day = v
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Week", wireType)
}
var v int32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))
m.Week = v
case 7:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Hour", wireType)
}
var v int32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))
m.Hour = v
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Minute", wireType)
}
var v int32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))
m.Minute = v
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Grpid", wireType)
}
m.Grpid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Grpid |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipTimerOld(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimerOld
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *TimersMapOld) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TimersMap: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TimersMap: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Timers", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTimerOld
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTimerOld
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Timers == nil {
m.Timers = make(map[string]*TimerOld)
}
var mapkey string
var mapvalue *TimerOld
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthTimerOld
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey < 0 {
return ErrInvalidLengthTimerOld
}
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
} else if fieldNum == 2 {
var mapmsglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimerOld
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapmsglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if mapmsglen < 0 {
return ErrInvalidLengthTimerOld
}
postmsgIndex := iNdEx + mapmsglen
if postmsgIndex < 0 {
return ErrInvalidLengthTimerOld
}
if postmsgIndex > l {
return io.ErrUnexpectedEOF
}
mapvalue = &TimerOld{}
if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
return err
}
iNdEx = postmsgIndex
} else {
iNdEx = entryPreIndex
skippy, err := skipTimerOld(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimerOld
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
m.Timers[mapkey] = mapvalue
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTimerOld(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimerOld
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTimerOld(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimerOld
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimerOld
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimerOld
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthTimerOld
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupTimerOld
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthTimerOld
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthTimerOld = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowTimerOld = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupTimerOld = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -0,0 +1,810 @@
package main
import (
fmt "fmt"
io "io"
math "math"
math_bits "math/bits"
proto "github.com/golang/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Timer struct {
Alert string `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"`
Cron string `protobuf:"bytes,2,opt,name=cron,proto3" json:"cron,omitempty"`
En1Month4Day5Week3Hour5Min6 int32 `protobuf:"varint,4,opt,name=en1month4day5week3hour5min6,proto3" json:"en1month4day5week3hour5min6,omitempty"`
Selfid int64 `protobuf:"varint,8,opt,name=selfid,proto3" json:"selfid,omitempty"`
Url string `protobuf:"bytes,16,opt,name=url,proto3" json:"url,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Timer) Reset() { *m = Timer{} }
func (m *Timer) String() string { return proto.CompactTextString(m) }
func (*Timer) ProtoMessage() {}
func (*Timer) Descriptor() ([]byte, []int) {
return fileDescriptor_ad0307ee16b652d2, []int{0}
}
func (m *Timer) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Timer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Timer.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Timer) XXX_Merge(src proto.Message) {
xxx_messageInfo_Timer.Merge(m, src)
}
func (m *Timer) XXX_Size() int {
return m.Size()
}
func (m *Timer) XXX_DiscardUnknown() {
xxx_messageInfo_Timer.DiscardUnknown(m)
}
var xxx_messageInfo_Timer proto.InternalMessageInfo
func (m *Timer) GetAlert() string {
if m != nil {
return m.Alert
}
return ""
}
func (m *Timer) GetCron() string {
if m != nil {
return m.Cron
}
return ""
}
func (m *Timer) GetEn1Month4Day5Week3Hour5Min6() int32 {
if m != nil {
return m.En1Month4Day5Week3Hour5Min6
}
return 0
}
func (m *Timer) GetSelfid() int64 {
if m != nil {
return m.Selfid
}
return 0
}
func (m *Timer) GetUrl() string {
if m != nil {
return m.Url
}
return ""
}
type TimersMap struct {
Timers map[string]*Timer `protobuf:"bytes,1,rep,name=timers,proto3" json:"timers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TimersMap) Reset() { *m = TimersMap{} }
func (m *TimersMap) String() string { return proto.CompactTextString(m) }
func (*TimersMap) ProtoMessage() {}
func (*TimersMap) Descriptor() ([]byte, []int) {
return fileDescriptor_ad0307ee16b652d2, []int{1}
}
func (m *TimersMap) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *TimersMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_TimersMap.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *TimersMap) XXX_Merge(src proto.Message) {
xxx_messageInfo_TimersMap.Merge(m, src)
}
func (m *TimersMap) XXX_Size() int {
return m.Size()
}
func (m *TimersMap) XXX_DiscardUnknown() {
xxx_messageInfo_TimersMap.DiscardUnknown(m)
}
var xxx_messageInfo_TimersMap proto.InternalMessageInfo
func (m *TimersMap) GetTimers() map[string]*Timer {
if m != nil {
return m.Timers
}
return nil
}
func init() {
proto.RegisterType((*Timer)(nil), "timer.Timer")
proto.RegisterType((*TimersMap)(nil), "timer.TimersMap")
proto.RegisterMapType((map[string]*Timer)(nil), "timer.TimersMap.TimersEntry")
}
func init() { proto.RegisterFile("timer.proto", fileDescriptor_ad0307ee16b652d2) }
var fileDescriptor_ad0307ee16b652d2 = []byte{
// 256 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0xc9, 0xcc, 0x4d,
0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x73, 0x94, 0xe6, 0x32, 0x72, 0xb1,
0x86, 0x80, 0x58, 0x42, 0x22, 0x5c, 0xac, 0x89, 0x39, 0xa9, 0x45, 0x25, 0x12, 0x8c, 0x0a, 0x8c,
0x1a, 0x9c, 0x41, 0x10, 0x8e, 0x90, 0x10, 0x17, 0x4b, 0x72, 0x51, 0x7e, 0x9e, 0x04, 0x13, 0x58,
0x10, 0xcc, 0x16, 0x72, 0xe0, 0x92, 0x4e, 0xcd, 0x33, 0xcc, 0xcd, 0xcf, 0x2b, 0xc9, 0x30, 0x49,
0x49, 0xac, 0x34, 0x2d, 0x4f, 0x4d, 0xcd, 0x36, 0xce, 0xc8, 0x2f, 0x2d, 0x32, 0xcd, 0xcd, 0xcc,
0x33, 0x93, 0x60, 0x51, 0x60, 0xd4, 0x60, 0x0d, 0xc2, 0xa7, 0x44, 0x48, 0x8c, 0x8b, 0xad, 0x38,
0x35, 0x27, 0x2d, 0x33, 0x45, 0x82, 0x43, 0x81, 0x51, 0x83, 0x39, 0x08, 0xca, 0x13, 0x12, 0xe0,
0x62, 0x2e, 0x2d, 0xca, 0x91, 0x10, 0x00, 0x5b, 0x06, 0x62, 0x2a, 0x75, 0x31, 0x72, 0x71, 0x82,
0xdd, 0x57, 0xec, 0x9b, 0x58, 0x20, 0x64, 0xc2, 0xc5, 0x06, 0x76, 0x76, 0xb1, 0x04, 0xa3, 0x02,
0xb3, 0x06, 0xb7, 0x91, 0x8c, 0x1e, 0xc4, 0x4b, 0x70, 0x15, 0x50, 0x96, 0x6b, 0x5e, 0x49, 0x51,
0x65, 0x10, 0x54, 0xad, 0x94, 0x3b, 0x17, 0x37, 0x92, 0x30, 0xc8, 0x92, 0xec, 0xd4, 0x4a, 0xa8,
0x37, 0x41, 0x4c, 0x21, 0x25, 0x2e, 0xd6, 0xb2, 0xc4, 0x9c, 0xd2, 0x54, 0xb0, 0x2f, 0xb9, 0x8d,
0x78, 0x90, 0x4d, 0x0d, 0x82, 0x48, 0x59, 0x31, 0x59, 0x30, 0x3a, 0x09, 0x9c, 0x78, 0x24, 0xc7,
0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x33, 0x1e, 0xcb, 0x31, 0x24, 0xb1, 0x81,
0x03, 0xd3, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xf5, 0xc1, 0x9e, 0x44, 0x5b, 0x01, 0x00, 0x00,
}
func (m *Timer) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Timer) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Timer) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Url) > 0 {
i -= len(m.Url)
copy(dAtA[i:], m.Url)
i = encodeVarintTimer(dAtA, i, uint64(len(m.Url)))
i--
dAtA[i] = 0x1
i--
dAtA[i] = 0x82
}
if m.Selfid != 0 {
i = encodeVarintTimer(dAtA, i, uint64(m.Selfid))
i--
dAtA[i] = 0x40
}
if m.En1Month4Day5Week3Hour5Min6 != 0 {
i = encodeVarintTimer(dAtA, i, uint64(m.En1Month4Day5Week3Hour5Min6))
i--
dAtA[i] = 0x20
}
if len(m.Cron) > 0 {
i -= len(m.Cron)
copy(dAtA[i:], m.Cron)
i = encodeVarintTimer(dAtA, i, uint64(len(m.Cron)))
i--
dAtA[i] = 0x12
}
if len(m.Alert) > 0 {
i -= len(m.Alert)
copy(dAtA[i:], m.Alert)
i = encodeVarintTimer(dAtA, i, uint64(len(m.Alert)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *TimersMap) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *TimersMap) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *TimersMap) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Timers) > 0 {
for k := range m.Timers {
v := m.Timers[k]
baseI := i
if v != nil {
{
size, err := v.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTimer(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
i -= len(k)
copy(dAtA[i:], k)
i = encodeVarintTimer(dAtA, i, uint64(len(k)))
i--
dAtA[i] = 0xa
i = encodeVarintTimer(dAtA, i, uint64(baseI-i))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintTimer(dAtA []byte, offset int, v uint64) int {
offset -= sovTimer(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Timer) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Alert)
if l > 0 {
n += 1 + l + sovTimer(uint64(l))
}
l = len(m.Cron)
if l > 0 {
n += 1 + l + sovTimer(uint64(l))
}
if m.En1Month4Day5Week3Hour5Min6 != 0 {
n += 1 + sovTimer(uint64(m.En1Month4Day5Week3Hour5Min6))
}
if m.Selfid != 0 {
n += 1 + sovTimer(uint64(m.Selfid))
}
l = len(m.Url)
if l > 0 {
n += 2 + l + sovTimer(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *TimersMap) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Timers) > 0 {
for k, v := range m.Timers {
_ = k
_ = v
l = 0
if v != nil {
l = v.Size()
l += 1 + sovTimer(uint64(l))
}
mapEntrySize := 1 + len(k) + sovTimer(uint64(len(k))) + l
n += mapEntrySize + 1 + sovTimer(uint64(mapEntrySize))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovTimer(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozTimer(x uint64) (n int) {
return sovTimer(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Timer) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Timer: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Timer: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Alert", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Alert = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Cron", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Cron = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field En1Month4Day5Week3Hour5Min6", wireType)
}
m.En1Month4Day5Week3Hour5Min6 = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.En1Month4Day5Week3Hour5Min6 |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Selfid", wireType)
}
m.Selfid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Selfid |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 16:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Url", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Url = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTimer(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimer
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *TimersMap) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TimersMap: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TimersMap: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Timers", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Timers == nil {
m.Timers = make(map[string]*Timer)
}
var mapkey string
var mapvalue *Timer
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthTimer
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey < 0 {
return ErrInvalidLengthTimer
}
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
} else if fieldNum == 2 {
var mapmsglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapmsglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if mapmsglen < 0 {
return ErrInvalidLengthTimer
}
postmsgIndex := iNdEx + mapmsglen
if postmsgIndex < 0 {
return ErrInvalidLengthTimer
}
if postmsgIndex > l {
return io.ErrUnexpectedEOF
}
mapvalue = &Timer{}
if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
return err
}
iNdEx = postmsgIndex
} else {
iNdEx = entryPreIndex
skippy, err := skipTimer(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimer
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
m.Timers[mapkey] = mapvalue
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTimer(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimer
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTimer(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthTimer
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupTimer
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthTimer
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthTimer = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowTimer = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupTimer = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -0,0 +1,75 @@
package main
import "time"
func (m *Timer) En() (en bool) {
return m.En1Month4Day5Week3Hour5Min6&0x800000 != 0
}
func (m *Timer) Month() (mon time.Month) {
mon = time.Month((m.En1Month4Day5Week3Hour5Min6 & 0x780000) >> 19)
if mon == 0b1111 {
mon = -1
}
return
}
func (m *Timer) Day() (d int) {
d = int((m.En1Month4Day5Week3Hour5Min6 & 0x07c000) >> 14)
if d == 0b11111 {
d = -1
}
return
}
func (m *Timer) Week() (w time.Weekday) {
w = time.Weekday((m.En1Month4Day5Week3Hour5Min6 & 0x003800) >> 11)
if w == 0b111 {
w = -1
}
return
}
func (m *Timer) Hour() (h int) {
h = int((m.En1Month4Day5Week3Hour5Min6 & 0x0007c0) >> 6)
if h == 0b11111 {
h = -1
}
return
}
func (m *Timer) Minute() (min int) {
min = int(m.En1Month4Day5Week3Hour5Min6 & 0x00003f)
if min == 0b111111 {
min = -1
}
return
}
func (m *Timer) SetEn(en bool) {
if en {
m.En1Month4Day5Week3Hour5Min6 |= 0x800000
} else {
m.En1Month4Day5Week3Hour5Min6 &= 0x7fffff
}
}
func (m *Timer) SetMonth(mon time.Month) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(mon) << 19) & 0x780000) | (m.En1Month4Day5Week3Hour5Min6 & 0x87ffff)
}
func (m *Timer) SetDay(d int) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(d) << 14) & 0x07c000) | (m.En1Month4Day5Week3Hour5Min6 & 0xf83fff)
}
func (m *Timer) SetWeek(w time.Weekday) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(w) << 11) & 0x003800) | (m.En1Month4Day5Week3Hour5Min6 & 0xffc7ff)
}
func (m *Timer) SetHour(h int) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(h) << 6) & 0x0007c0) | (m.En1Month4Day5Week3Hour5Min6 & 0xfff83f)
}
func (m *Timer) SetMinute(min int) {
m.En1Month4Day5Week3Hour5Min6 = (int32(min) & 0x00003f) | (m.En1Month4Day5Week3Hour5Min6 & 0xffffc0)
}

View File

@@ -0,0 +1,16 @@
package timer
import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func (ts *Timer) sendmsg(grp int64, ctx *zero.Ctx) {
ctx.Event = new(zero.Event)
ctx.Event.GroupID = grp
if ts.Url == "" {
ctx.SendChain(atall, message.Text(ts.Alert))
} else {
ctx.SendChain(atall, message.Text(ts.Alert), message.Image(ts.Url).Add("cache", "0"))
}
}

View File

@@ -0,0 +1,153 @@
package timer
import (
"fmt"
"strconv"
"strings"
"time"
"unicode"
"github.com/sirupsen/logrus"
)
// GetTimerInfo 获得标准化定时字符串
func (ts *Timer) GetTimerInfo(grp int64) string {
if ts.Cron != "" {
return fmt.Sprintf("[%d]%s", grp, ts.Cron)
}
return fmt.Sprintf("[%d]%d月%d日%d周%d:%d", grp, ts.Month(), ts.Day(), ts.Week(), ts.Hour(), ts.Minute())
}
// GetFilledCronTimer 获得以cron填充好的ts
func GetFilledCronTimer(croncmd string, alert string, img string, botqq int64) *Timer {
var ts Timer
ts.Alert = alert
ts.Cron = croncmd
ts.Url = img
ts.Selfid = botqq
return &ts
}
// GetFilledTimer 获得填充好的ts
func GetFilledTimer(dateStrs []string, botqq int64, matchDateOnly bool) *Timer {
monthStr := []rune(dateStrs[1])
dayWeekStr := []rune(dateStrs[2])
hourStr := []rune(dateStrs[3])
minuteStr := []rune(dateStrs[4])
var ts Timer
mon := time.Month(chineseNum2Int(monthStr))
if (mon != -1 && mon <= 0) || mon > 12 { // 月份非法
ts.Alert = "月份非法!"
return &ts
}
ts.SetMonth(mon)
lenOfDW := len(dayWeekStr)
if lenOfDW == 4 { // 包括末尾的"日"
dayWeekStr = []rune{dayWeekStr[0], dayWeekStr[2]} // 去除中间的十
d := chineseNum2Int(dayWeekStr)
if (d != -1 && d <= 0) || d > 31 { // 日期非法
ts.Alert = "日期非法1"
return &ts
}
ts.SetDay(d)
} else if dayWeekStr[lenOfDW-1] == rune('日') { // xx日
dayWeekStr = dayWeekStr[:lenOfDW-1]
d := chineseNum2Int(dayWeekStr)
if (d != -1 && d <= 0) || d > 31 { // 日期非法
ts.Alert = "日期非法2"
return &ts
}
ts.SetDay(d)
} else if dayWeekStr[0] == rune('每') { // 每周
ts.SetWeek(-1)
} else { // 周x
w := chineseNum2Int(dayWeekStr[1:])
if w == 7 { // 周天是0
w = 0
}
if w < 0 || w > 6 { // 星期非法
ts.Alert = "星期非法!"
return &ts
}
ts.SetWeek(time.Weekday(w))
}
if len(hourStr) == 3 {
hourStr = []rune{hourStr[0], hourStr[2]} // 去除中间的十
}
h := chineseNum2Int(hourStr)
if h < -1 || h > 23 { // 小时非法
ts.Alert = "小时非法!"
return &ts
}
ts.SetHour(h)
if len(minuteStr) == 3 {
minuteStr = []rune{minuteStr[0], minuteStr[2]} // 去除中间的十
}
min := chineseNum2Int(minuteStr)
if min < -1 || min > 59 { // 分钟非法
ts.Alert = "分钟非法!"
return &ts
}
ts.SetMinute(min)
if !matchDateOnly {
urlStr := dateStrs[5]
if urlStr != "" { // 是图片url
ts.Url = urlStr[3:] // utf-8下用为3字节
logrus.Println("[群管]" + ts.Url)
if !strings.HasPrefix(ts.Url, "http") {
ts.Url = "illegal"
logrus.Println("[群管]url非法")
return &ts
}
}
ts.Alert = dateStrs[6]
ts.SetEn(true)
}
ts.Selfid = botqq
return &ts
}
// chineseNum2Int 汉字数字转int仅支持-1099最多两位数其中"每"解释为-1"每二"为-2以此类推
func chineseNum2Int(rs []rune) int {
r := -1
l := len(rs)
mai := rune('每')
if unicode.IsDigit(rs[0]) { // 默认可能存在的第二位也为int
r, _ = strconv.Atoi(string(rs))
} else {
if rs[0] == mai {
if l == 2 {
r = -chineseChar2Int(rs[1])
}
} else if l == 1 {
r = chineseChar2Int(rs[0])
} else {
ten := chineseChar2Int(rs[0])
if ten != 10 {
ten *= 10
}
ge := chineseChar2Int(rs[1])
if ge == 10 {
ge = 0
}
r = ten + ge
}
}
return r
}
// chineseChar2Int 处理单个字符的映射0~10
func chineseChar2Int(c rune) int {
if c == rune('日') || c == rune('天') { // 周日/周天
return 7
} else {
match := []rune("零一二三四五六七八九十")
for i, m := range match {
if c == m {
return i
}
}
return 0
}
}

View File

@@ -0,0 +1,164 @@
package timer
import (
"time"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
)
func firstWeek(date *time.Time, week time.Weekday) (d time.Time) {
d = date.AddDate(0, 0, 1-date.Day())
for d.Weekday() != week {
d = d.AddDate(0, 0, 1)
}
return
}
func (ts *Timer) nextWakeTime() (date time.Time) {
date = time.Now()
m := ts.Month()
d := ts.Day()
h := ts.Hour()
mn := ts.Minute()
w := ts.Week()
var unit time.Duration
logrus.Debugln("[timer] unit init:", unit)
if mn >= 0 {
switch {
case h < 0:
if unit <= time.Second {
unit = time.Hour
}
case d < 0 || w < 0:
if unit <= time.Second {
unit = time.Hour * 24
}
case d == 0 && w >= 0:
delta := time.Hour * 24 * time.Duration(int(w)-int(date.Weekday()))
if delta < 0 {
delta = time.Hour * 24 * 7
}
unit += delta
case m < 0:
unit = -1
}
} else {
unit = time.Minute
}
logrus.Debugln("[timer] unit:", unit)
stable := 0
if mn < 0 {
mn = date.Minute()
}
if h < 0 {
h = date.Hour()
} else {
stable |= 0x8
}
if d < 0 {
d = date.Day()
} else if d > 0 {
stable |= 0x4
} else {
d = date.Day()
if w >= 0 {
stable |= 0x2
}
}
if m < 0 {
m = date.Month()
} else {
stable |= 0x1
}
switch stable {
case 0b0101:
if ts.Day() != time.Now().Day() || ts.Month() != time.Now().Month() {
h = 0
}
case 0b1001:
if ts.Month() != time.Now().Month() {
d = 0
}
case 0b0001:
if ts.Month() != time.Now().Month() {
d = 0
h = 0
}
}
logrus.Debugln("[timer] stable:", stable)
logrus.Debugln("[timer] m:", m, "d:", d, "h:", h, "mn:", mn, "w:", w)
date = time.Date(date.Year(), time.Month(m), int(d), int(h), int(mn), date.Second(), date.Nanosecond(), date.Location())
logrus.Debugln("[timer] date original:", date)
if unit > 0 {
date = date.Add(unit)
}
logrus.Debugln("[timer] date after add:", date)
if time.Until(date) <= 0 {
if ts.Month() < 0 {
if ts.Day() > 0 || (ts.Day() == 0 && ts.Week() >= 0) {
date = date.AddDate(0, 1, 0)
} else if ts.Day() < 0 || ts.Week() < 0 {
if ts.Hour() > 0 {
date = date.AddDate(0, 0, 1)
} else if ts.Minute() > 0 {
date = date.Add(time.Hour)
}
}
} else {
date = date.AddDate(1, 0, 0)
}
}
logrus.Debugln("[timer] date after fix:", date)
if stable&0x8 != 0 && date.Hour() != int(h) {
switch {
case stable&0x4 == 0:
date = date.AddDate(0, 0, 1).Add(-time.Hour)
case stable&0x2 == 0:
date = date.AddDate(0, 0, 7).Add(-time.Hour)
case stable*0x1 == 0:
date = date.AddDate(0, 1, 0).Add(-time.Hour)
default:
date = date.AddDate(1, 0, 0).Add(-time.Hour)
}
}
logrus.Debugln("[timer] date after s8:", date)
if stable&0x4 != 0 && date.Day() != int(d) {
switch {
case stable*0x1 == 0:
date = date.AddDate(0, 1, -1)
default:
date = date.AddDate(1, 0, -1)
}
}
logrus.Debugln("[timer] date after s4:", date)
if stable&0x2 != 0 && date.Weekday() != w {
switch {
case stable*0x1 == 0:
date = date.AddDate(0, 1, 0)
default:
date = date.AddDate(1, 0, 0)
}
date = firstWeek(&date, time.Weekday(w))
}
logrus.Debugln("[timer] date after s2:", date)
if time.Until(date) <= 0 {
date = time.Now().Add(time.Minute)
}
return date
}
func (ts *Timer) judgeHM(grp int64) {
if ts.Hour() < 0 || ts.Hour() == time.Now().Hour() {
if ts.Minute() < 0 || ts.Minute() == time.Now().Minute() {
if ts.Selfid != 0 {
ts.sendmsg(grp, zero.GetBot(ts.Selfid))
} else {
zero.RangeBot(func(id int64, ctx *zero.Ctx) (_ bool) {
ts.sendmsg(grp, ctx)
return
})
}
}
}
}

View File

@@ -0,0 +1,209 @@
// Package timer 群管定时器
package timer
import (
"io"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/fumiama/cron"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
)
type Clock struct {
// 记录每个定时器以便取消
timersmap TimersMap
// 定时器map
timers *(map[string]*Timer)
timersmu sync.RWMutex
// 定时器存储位置
pbfile *string
// cron 定时器
cron *cron.Cron
// entries key <-> cron
entries map[string]cron.EntryID
entmu sync.Mutex
}
var (
// @全体成员
atall = message.MessageSegment{
Type: "at",
Data: map[string]string{
"qq": "all",
},
}
)
func NewClock(pbfile string) (c Clock) {
c.loadTimers(pbfile)
c.timers = &c.timersmap.Timers
c.pbfile = &pbfile
c.cron = cron.New()
c.entries = make(map[string]cron.EntryID)
c.cron.Start()
return
}
// RegisterTimer 注册计时器
func (c *Clock) RegisterTimer(ts *Timer, grp int64, save bool) bool {
key := ts.GetTimerInfo(grp)
t, ok := c.GetTimer(key)
if t != ts && ok { // 避免重复注册定时器
t.SetEn(false)
}
c.timersmu.Lock()
(*c.timers)[key] = ts
c.timersmu.Unlock()
logrus.Println("[群管]注册计时器", key)
if ts.Cron != "" {
var ctx *zero.Ctx
if ts.Selfid != 0 {
ctx = zero.GetBot(ts.Selfid)
} else {
zero.RangeBot(func(id int64, c *zero.Ctx) bool {
ctx = c
ts.Selfid = id
return false
})
}
eid, err := c.cron.AddFunc(ts.Cron, func() { ts.sendmsg(grp, ctx) })
if err == nil {
c.entmu.Lock()
c.entries[key] = eid
c.entmu.Unlock()
if save {
c.SaveTimers()
}
return true
}
ts.Alert = err.Error()
} else {
if save {
c.SaveTimers()
}
for ts.En() {
nextdate := ts.nextWakeTime()
sleepsec := time.Until(nextdate)
logrus.Printf("[群管]计时器%s将睡眠%ds", key, sleepsec/time.Second)
time.Sleep(sleepsec)
if ts.En() {
if ts.Month() < 0 || ts.Month() == time.Now().Month() {
if ts.Day() < 0 || ts.Day() == time.Now().Day() {
ts.judgeHM(grp)
} else if ts.Day() == 0 {
if ts.Week() < 0 || ts.Week() == time.Now().Weekday() {
ts.judgeHM(grp)
}
}
}
}
}
}
return false
}
// CancelTimer 取消计时器
func (c *Clock) CancelTimer(key string) bool {
t, ok := (*c.timers)[key]
if ok {
if t.Cron != "" {
c.entmu.Lock()
e := c.entries[key]
c.cron.Remove(e)
delete(c.entries, key)
c.entmu.Unlock()
} else {
t.SetEn(false)
}
c.timersmu.Lock()
delete(*c.timers, key) // 避免重复取消
c.timersmu.Unlock()
_ = c.SaveTimers()
}
return ok
}
// SaveTimers 保存当前计时器
func (c *Clock) SaveTimers() error {
c.timersmu.RLock()
data, err := c.timersmap.Marshal()
c.timersmu.RUnlock()
if err == nil {
c.timersmu.Lock()
defer c.timersmu.Unlock()
f, err1 := os.OpenFile(*c.pbfile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 != nil {
return err1
} else {
_, err2 := f.Write(data)
f.Close()
return err2
}
}
return err
}
// ListTimers 列出本群所有计时器
func (c *Clock) ListTimers(grpID uint64) []string {
// 数组默认长度为map长度,后面append时,不需要重新申请内存和拷贝,效率很高
if c.timers != nil {
g := strconv.FormatUint(grpID, 10)
c.timersmu.RLock()
keys := make([]string, 0, len(*c.timers))
for k := range *c.timers {
if strings.Contains(k, g) {
start := strings.Index(k, "]")
msg := strings.ReplaceAll(k[start+1:]+"\n", "-1", "每")
msg = strings.ReplaceAll(msg, "月0日0周", "月周天")
msg = strings.ReplaceAll(msg, "月0日", "月")
msg = strings.ReplaceAll(msg, "日0周", "日")
keys = append(keys, msg)
}
}
c.timersmu.RUnlock()
return keys
} else {
return nil
}
}
func (c *Clock) GetTimer(key string) (t *Timer, ok bool) {
c.timersmu.RLock()
t, ok = (*c.timers)[key]
c.timersmu.RUnlock()
return
}
func (c *Clock) loadTimers(pbfile string) {
if file.IsExist(pbfile) {
f, err := os.Open(pbfile)
if err == nil {
data, err := io.ReadAll(f)
if err == nil {
if len(data) > 0 {
err = c.timersmap.Unmarshal(data)
if err == nil {
for str, t := range c.timersmap.Timers {
grp, err := strconv.ParseInt(str[1:strings.Index(str, "]")], 10, 64)
if err == nil {
go c.RegisterTimer(t, grp, false)
}
}
return
}
logrus.Errorln("[群管]读取定时器文件失败将在下一次保存时覆盖原文件。err:", err)
logrus.Errorln("[群管]如不希望被覆盖请运行源码plugin_manager/timers/migrate下的程序将timers.pb刷新为新版")
}
}
}
}
c.timersmap.Timers = make(map[string]*Timer)
}

View File

@@ -0,0 +1,812 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: timer.proto
package timer
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Timer struct {
Alert string `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"`
Cron string `protobuf:"bytes,2,opt,name=cron,proto3" json:"cron,omitempty"`
En1Month4Day5Week3Hour5Min6 int32 `protobuf:"varint,4,opt,name=en1month4day5week3hour5min6,proto3" json:"en1month4day5week3hour5min6,omitempty"`
Selfid int64 `protobuf:"varint,8,opt,name=selfid,proto3" json:"selfid,omitempty"`
Url string `protobuf:"bytes,16,opt,name=url,proto3" json:"url,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Timer) Reset() { *m = Timer{} }
func (m *Timer) String() string { return proto.CompactTextString(m) }
func (*Timer) ProtoMessage() {}
func (*Timer) Descriptor() ([]byte, []int) {
return fileDescriptor_ad0307ee16b652d2, []int{0}
}
func (m *Timer) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Timer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Timer.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Timer) XXX_Merge(src proto.Message) {
xxx_messageInfo_Timer.Merge(m, src)
}
func (m *Timer) XXX_Size() int {
return m.Size()
}
func (m *Timer) XXX_DiscardUnknown() {
xxx_messageInfo_Timer.DiscardUnknown(m)
}
var xxx_messageInfo_Timer proto.InternalMessageInfo
func (m *Timer) GetAlert() string {
if m != nil {
return m.Alert
}
return ""
}
func (m *Timer) GetCron() string {
if m != nil {
return m.Cron
}
return ""
}
func (m *Timer) GetEn1Month4Day5Week3Hour5Min6() int32 {
if m != nil {
return m.En1Month4Day5Week3Hour5Min6
}
return 0
}
func (m *Timer) GetSelfid() int64 {
if m != nil {
return m.Selfid
}
return 0
}
func (m *Timer) GetUrl() string {
if m != nil {
return m.Url
}
return ""
}
type TimersMap struct {
Timers map[string]*Timer `protobuf:"bytes,1,rep,name=timers,proto3" json:"timers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TimersMap) Reset() { *m = TimersMap{} }
func (m *TimersMap) String() string { return proto.CompactTextString(m) }
func (*TimersMap) ProtoMessage() {}
func (*TimersMap) Descriptor() ([]byte, []int) {
return fileDescriptor_ad0307ee16b652d2, []int{1}
}
func (m *TimersMap) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *TimersMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_TimersMap.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *TimersMap) XXX_Merge(src proto.Message) {
xxx_messageInfo_TimersMap.Merge(m, src)
}
func (m *TimersMap) XXX_Size() int {
return m.Size()
}
func (m *TimersMap) XXX_DiscardUnknown() {
xxx_messageInfo_TimersMap.DiscardUnknown(m)
}
var xxx_messageInfo_TimersMap proto.InternalMessageInfo
func (m *TimersMap) GetTimers() map[string]*Timer {
if m != nil {
return m.Timers
}
return nil
}
func init() {
proto.RegisterType((*Timer)(nil), "timer.Timer")
proto.RegisterType((*TimersMap)(nil), "timer.TimersMap")
proto.RegisterMapType((map[string]*Timer)(nil), "timer.TimersMap.TimersEntry")
}
func init() { proto.RegisterFile("timer.proto", fileDescriptor_ad0307ee16b652d2) }
var fileDescriptor_ad0307ee16b652d2 = []byte{
// 256 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0xc9, 0xcc, 0x4d,
0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x73, 0x94, 0xe6, 0x32, 0x72, 0xb1,
0x86, 0x80, 0x58, 0x42, 0x22, 0x5c, 0xac, 0x89, 0x39, 0xa9, 0x45, 0x25, 0x12, 0x8c, 0x0a, 0x8c,
0x1a, 0x9c, 0x41, 0x10, 0x8e, 0x90, 0x10, 0x17, 0x4b, 0x72, 0x51, 0x7e, 0x9e, 0x04, 0x13, 0x58,
0x10, 0xcc, 0x16, 0x72, 0xe0, 0x92, 0x4e, 0xcd, 0x33, 0xcc, 0xcd, 0xcf, 0x2b, 0xc9, 0x30, 0x49,
0x49, 0xac, 0x34, 0x2d, 0x4f, 0x4d, 0xcd, 0x36, 0xce, 0xc8, 0x2f, 0x2d, 0x32, 0xcd, 0xcd, 0xcc,
0x33, 0x93, 0x60, 0x51, 0x60, 0xd4, 0x60, 0x0d, 0xc2, 0xa7, 0x44, 0x48, 0x8c, 0x8b, 0xad, 0x38,
0x35, 0x27, 0x2d, 0x33, 0x45, 0x82, 0x43, 0x81, 0x51, 0x83, 0x39, 0x08, 0xca, 0x13, 0x12, 0xe0,
0x62, 0x2e, 0x2d, 0xca, 0x91, 0x10, 0x00, 0x5b, 0x06, 0x62, 0x2a, 0x75, 0x31, 0x72, 0x71, 0x82,
0xdd, 0x57, 0xec, 0x9b, 0x58, 0x20, 0x64, 0xc2, 0xc5, 0x06, 0x76, 0x76, 0xb1, 0x04, 0xa3, 0x02,
0xb3, 0x06, 0xb7, 0x91, 0x8c, 0x1e, 0xc4, 0x4b, 0x70, 0x15, 0x50, 0x96, 0x6b, 0x5e, 0x49, 0x51,
0x65, 0x10, 0x54, 0xad, 0x94, 0x3b, 0x17, 0x37, 0x92, 0x30, 0xc8, 0x92, 0xec, 0xd4, 0x4a, 0xa8,
0x37, 0x41, 0x4c, 0x21, 0x25, 0x2e, 0xd6, 0xb2, 0xc4, 0x9c, 0xd2, 0x54, 0xb0, 0x2f, 0xb9, 0x8d,
0x78, 0x90, 0x4d, 0x0d, 0x82, 0x48, 0x59, 0x31, 0x59, 0x30, 0x3a, 0x09, 0x9c, 0x78, 0x24, 0xc7,
0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x33, 0x1e, 0xcb, 0x31, 0x24, 0xb1, 0x81,
0x03, 0xd3, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xf5, 0xc1, 0x9e, 0x44, 0x5b, 0x01, 0x00, 0x00,
}
func (m *Timer) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Timer) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Timer) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Url) > 0 {
i -= len(m.Url)
copy(dAtA[i:], m.Url)
i = encodeVarintTimer(dAtA, i, uint64(len(m.Url)))
i--
dAtA[i] = 0x1
i--
dAtA[i] = 0x82
}
if m.Selfid != 0 {
i = encodeVarintTimer(dAtA, i, uint64(m.Selfid))
i--
dAtA[i] = 0x40
}
if m.En1Month4Day5Week3Hour5Min6 != 0 {
i = encodeVarintTimer(dAtA, i, uint64(m.En1Month4Day5Week3Hour5Min6))
i--
dAtA[i] = 0x20
}
if len(m.Cron) > 0 {
i -= len(m.Cron)
copy(dAtA[i:], m.Cron)
i = encodeVarintTimer(dAtA, i, uint64(len(m.Cron)))
i--
dAtA[i] = 0x12
}
if len(m.Alert) > 0 {
i -= len(m.Alert)
copy(dAtA[i:], m.Alert)
i = encodeVarintTimer(dAtA, i, uint64(len(m.Alert)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *TimersMap) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *TimersMap) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *TimersMap) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Timers) > 0 {
for k := range m.Timers {
v := m.Timers[k]
baseI := i
if v != nil {
{
size, err := v.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTimer(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
i -= len(k)
copy(dAtA[i:], k)
i = encodeVarintTimer(dAtA, i, uint64(len(k)))
i--
dAtA[i] = 0xa
i = encodeVarintTimer(dAtA, i, uint64(baseI-i))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintTimer(dAtA []byte, offset int, v uint64) int {
offset -= sovTimer(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Timer) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Alert)
if l > 0 {
n += 1 + l + sovTimer(uint64(l))
}
l = len(m.Cron)
if l > 0 {
n += 1 + l + sovTimer(uint64(l))
}
if m.En1Month4Day5Week3Hour5Min6 != 0 {
n += 1 + sovTimer(uint64(m.En1Month4Day5Week3Hour5Min6))
}
if m.Selfid != 0 {
n += 1 + sovTimer(uint64(m.Selfid))
}
l = len(m.Url)
if l > 0 {
n += 2 + l + sovTimer(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *TimersMap) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Timers) > 0 {
for k, v := range m.Timers {
_ = k
_ = v
l = 0
if v != nil {
l = v.Size()
l += 1 + sovTimer(uint64(l))
}
mapEntrySize := 1 + len(k) + sovTimer(uint64(len(k))) + l
n += mapEntrySize + 1 + sovTimer(uint64(mapEntrySize))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovTimer(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozTimer(x uint64) (n int) {
return sovTimer(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Timer) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Timer: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Timer: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Alert", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Alert = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Cron", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Cron = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field En1Month4Day5Week3Hour5Min6", wireType)
}
m.En1Month4Day5Week3Hour5Min6 = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.En1Month4Day5Week3Hour5Min6 |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Selfid", wireType)
}
m.Selfid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Selfid |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 16:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Url", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Url = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTimer(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimer
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *TimersMap) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TimersMap: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TimersMap: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Timers", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTimer
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTimer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Timers == nil {
m.Timers = make(map[string]*Timer)
}
var mapkey string
var mapvalue *Timer
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthTimer
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey < 0 {
return ErrInvalidLengthTimer
}
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
} else if fieldNum == 2 {
var mapmsglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapmsglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if mapmsglen < 0 {
return ErrInvalidLengthTimer
}
postmsgIndex := iNdEx + mapmsglen
if postmsgIndex < 0 {
return ErrInvalidLengthTimer
}
if postmsgIndex > l {
return io.ErrUnexpectedEOF
}
mapvalue = &Timer{}
if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
return err
}
iNdEx = postmsgIndex
} else {
iNdEx = entryPreIndex
skippy, err := skipTimer(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimer
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
m.Timers[mapkey] = mapvalue
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTimer(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTimer
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTimer(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTimer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthTimer
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupTimer
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthTimer
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthTimer = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowTimer = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupTimer = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -0,0 +1,14 @@
syntax = "proto3";
package timer;
message Timer {
string alert = 1;
string cron = 2;
int32 en1month4day5week3hour5min6 = 4;
int64 selfid = 8;
string url = 16;
}
message TimersMap {
map<string, Timer> timers = 1;
}

View File

@@ -0,0 +1,24 @@
package timer
import (
"testing"
"time"
"github.com/sirupsen/logrus"
)
func TestNextWakeTime(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
ts := &Timer{}
ts.SetMonth(-1)
ts.SetWeek(6)
ts.SetHour(16)
ts.SetMinute(30)
t1 := time.Until(ts.nextWakeTime())
if t1 < 0 {
t.Log(t1)
t.Fail()
}
t.Log(t1)
t.Fail()
}

View File

@@ -0,0 +1,75 @@
package timer
import "time"
func (m *Timer) En() (en bool) {
return m.En1Month4Day5Week3Hour5Min6&0x800000 != 0
}
func (m *Timer) Month() (mon time.Month) {
mon = time.Month((m.En1Month4Day5Week3Hour5Min6 & 0x780000) >> 19)
if mon == 0b1111 {
mon = -1
}
return
}
func (m *Timer) Day() (d int) {
d = int((m.En1Month4Day5Week3Hour5Min6 & 0x07c000) >> 14)
if d == 0b11111 {
d = -1
}
return
}
func (m *Timer) Week() (w time.Weekday) {
w = time.Weekday((m.En1Month4Day5Week3Hour5Min6 & 0x003800) >> 11)
if w == 0b111 {
w = -1
}
return
}
func (m *Timer) Hour() (h int) {
h = int((m.En1Month4Day5Week3Hour5Min6 & 0x0007c0) >> 6)
if h == 0b11111 {
h = -1
}
return
}
func (m *Timer) Minute() (min int) {
min = int(m.En1Month4Day5Week3Hour5Min6 & 0x00003f)
if min == 0b111111 {
min = -1
}
return
}
func (m *Timer) SetEn(en bool) {
if en {
m.En1Month4Day5Week3Hour5Min6 |= 0x800000
} else {
m.En1Month4Day5Week3Hour5Min6 &= 0x7fffff
}
}
func (m *Timer) SetMonth(mon time.Month) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(mon) << 19) & 0x780000) | (m.En1Month4Day5Week3Hour5Min6 & 0x87ffff)
}
func (m *Timer) SetDay(d int) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(d) << 14) & 0x07c000) | (m.En1Month4Day5Week3Hour5Min6 & 0xf83fff)
}
func (m *Timer) SetWeek(w time.Weekday) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(w) << 11) & 0x003800) | (m.En1Month4Day5Week3Hour5Min6 & 0xffc7ff)
}
func (m *Timer) SetHour(h int) {
m.En1Month4Day5Week3Hour5Min6 = ((int32(h) << 6) & 0x0007c0) | (m.En1Month4Day5Week3Hour5Min6 & 0xfff83f)
}
func (m *Timer) SetMinute(min int) {
m.En1Month4Day5Week3Hour5Min6 = (int32(min) & 0x00003f) | (m.En1Month4Day5Week3Hour5Min6 & 0xffffc0)
}

View File

@@ -19,24 +19,23 @@ import (
const api = "http://your.addr:23333/api/start_server/%s/?apikey=apikey"
var engine *zero.Engine
var engine = control.Register("minecraft", &control.Options{
DisableOnDefault: false,
Help: "minecraft\n" +
"- /mcstart xxx\n" +
"- /mcstop xxx\n" +
"- /mclist servername\n" +
"- https://github.com/Suwings/MCSManager",
})
func init() {
engine = control.Register("minecraft", &control.Options{
DisableOnDefault: false,
Help: "minecraft\n" +
"- /mcstart xxx\n" +
"- /mcstop xxx\n" +
"- /mclist servername\n" +
"- https://github.com/Suwings/MCSManager",
})
engine.OnCommand("mcstart").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
ctx.SendChain(message.Text("开启服务器: ", model.Args, "....."))
result := start(model.Args)
ctx.Send(result)
ctx.SendChain(message.Text(result))
})
engine.OnCommand("mcstop").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
@@ -44,7 +43,7 @@ func init() {
_ = ctx.Parse(&model)
ctx.SendChain(message.Text("开启服务器: ", model.Args, "....."))
result := stop(model.Args)
ctx.Send(result)
ctx.SendChain(message.Text(result))
})
}

40
plugin_moyu/nowork.go Normal file
View File

@@ -0,0 +1,40 @@
package moyu
import (
"fmt"
"strconv"
"time"
)
type holiday struct {
name string
date time.Time
dur time.Duration
}
// NewHoliday 节日名 天数 年 月 日
func NewHoliday(name string, dur, year int, month time.Month, day int) *holiday {
return &holiday{name: name, date: time.Date(year, month, day, 0, 0, 0, 0, time.Local), dur: time.Duration(dur) * time.Hour * 24}
}
// 获取两个时间相差
func (h *holiday) String() string {
d := time.Until(h.date)
if d >= 0 {
return "距离" + h.name + "还有: " + strconv.FormatFloat(d.Hours()/24.0, 'f', 2, 64) + "天!"
} else if d+h.dur >= 0 {
return "好好享受 " + h.name + " 假期吧!"
} else {
return "今年 " + h.name + " 假期已过"
}
}
func weekend() string {
t := time.Now().Weekday()
switch t {
case time.Sunday, time.Saturday:
return "好好享受周末吧!"
default:
return fmt.Sprintf("距离周末还有:%d天", 5-t)
}
}

93
plugin_moyu/run.go Normal file
View File

@@ -0,0 +1,93 @@
package moyu
import (
"time"
"github.com/fumiama/cron"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() { // 插件主体
// 定时任务每天10点执行一次
c := cron.New()
_, err := c.AddFunc("0 10 * * *", func() { sendNotice() })
if err == nil {
c.Start()
}
control.Register("moyu", &control.Options{
DisableOnDefault: true,
Help: "moyu\n" +
"- 添加摸鱼提醒\n" +
"- 删除摸鱼提醒\n",
}).OnFullMatch("删除摸鱼提醒", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
m, ok := control.Lookup("moyu")
if ok {
if m.IsEnabledIn(ctx.Event.GroupID) {
m.Disable(ctx.Event.GroupID)
ctx.Send(message.Text("删除成功!"))
} else {
ctx.Send(message.Text("未启用!"))
}
} else {
ctx.Send(message.Text("找不到该服务!"))
}
})
zero.OnFullMatch("添加摸鱼提醒", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
m, ok := control.Lookup("moyu")
if ok {
if m.IsEnabledIn(ctx.Event.GroupID) {
ctx.Send(message.Text("已启用!"))
} else {
m.Enable(ctx.Event.GroupID)
ctx.Send(message.Text("添加成功!"))
}
} else {
ctx.Send(message.Text("找不到该服务!"))
}
})
}
// 获取数据拼接消息链并发送
func sendNotice() {
m, ok := control.Lookup("moyu")
if ok {
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
for _, g := range ctx.GetGroupList().Array() {
grp := g.Get("group_id").Int()
if m.IsEnabledIn(grp) {
ctx.SendGroupMessage(grp,
[]message.MessageSegment{
message.Text(time.Now().Format("2006-01-02")),
message.Text("上午好,摸鱼人!\n工作再累一定不要忘记摸鱼哦有事没事起身去茶水间去厕所去廊道走走别老在工位上坐着钱是老板的,但命是自己的。\n"),
message.Text(weekend()),
message.Text("\n"),
message.Text(NewHoliday("元旦", 1, 2022, 1, 1)),
message.Text("\n"),
message.Text(NewHoliday("春节", 7, 2022, 1, 31)),
message.Text("\n"),
message.Text(NewHoliday("清明节", 1, 2022, 4, 3)),
message.Text("\n"),
message.Text(NewHoliday("劳动节", 1, 2022, 4, 30)),
message.Text("\n"),
message.Text(NewHoliday("端午节", 1, 2022, 6, 3)),
message.Text("\n"),
message.Text(NewHoliday("中秋节", 1, 2022, 9, 10)),
message.Text("\n"),
message.Text(NewHoliday("国庆节", 7, 2022, 10, 1)),
message.Text("\n"),
message.Text("上班是帮老板赚钱,摸鱼是赚老板的钱!最后,祝愿天下所有摸鱼人,都能愉快的渡过每一天…"),
},
)
}
}
return true
})
}
}

View File

@@ -32,7 +32,7 @@ func init() {
}).OnRegex("^(.{0,2})点歌(.{1,25})$").SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.Send("请稍后重试0x0...")
ctx.SendChain(message.Text("请稍后重试0x0..."))
return
}
// switch 平台

47
plugin_nbnhhsh/nbnhhsh.go Normal file
View File

@@ -0,0 +1,47 @@
// Package nbnhhsh 能不能好好说话
package nbnhhsh
import (
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
zero.OnRegex(`^[?]{1,2} ?([a-z0-9]+)$`).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
ctx.SendChain(message.Text(keyword + ": " + strings.Join(getValue(keyword), ", ")))
})
}
func getValue(text string) []string {
urlValues := url.Values{}
urlValues.Add("text", text)
resp, err := http.PostForm("https://lab.magiconch.com/api/nbnhhsh/guess", urlValues)
if err == nil {
body, err := ioutil.ReadAll(resp.Body)
if err == nil {
resp.Body.Close()
json := gjson.ParseBytes(body)
res := make([]string, 0)
var jsonPath string
if json.Get("0.trans").Exists() {
jsonPath = "0.trans"
} else {
jsonPath = "0.inputting"
}
for _, value := range json.Get(jsonPath).Array() {
res = append(res, value.String())
}
return res
}
return []string{err.Error()}
}
return []string{err.Error()}
}

View File

@@ -17,14 +17,12 @@ const (
)
func init() { // 插件主体
// TODO: 1.17 特性暂不增加
// rand.Seed(time.Now().UnixMicro())
rand.Seed(time.Now().UnixNano())
control.Register("omikuji", &control.Options{
DisableOnDefault: false,
Help: "浅草寺求签\n" +
"- 求签|运势|占卜",
}).OnFullMatchGroup([]string{"求签", "运势", "占卜"}).SetPriority(10).SetBlock(true).
"- 求签|占卜",
}).OnFullMatchGroup([]string{"求签", "占卜"}).SetPriority(10).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
miku := rand.Intn(100) + 1
ctx.SendChain(

View File

@@ -1,6 +1,7 @@
// TODO: 待优化
package qingyunke
// TODO: 待优化
/*
import (
"fmt"

View File

@@ -1,6 +1,4 @@
/*
基于青云客接口的聊天对话功能
*/
// Package qingyunke 基于青云客接口的聊天对话功能
package qingyunke
import (
@@ -9,6 +7,7 @@ import (
"io/ioutil"
"math/rand"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
@@ -100,13 +99,13 @@ type dataQYK struct {
// 青云客取消息
func getMessage(msg string) (string, error) {
url := "http://api.qingyunke.com/api.php"
qykUrl := "http://api.qingyunke.com/api.php"
key := "free"
appid := "0"
url = fmt.Sprintf(url+"?key=%s&appid=%s&msg=%s", key, appid, msg)
qykUrl = fmt.Sprintf(qykUrl+"?key=%s&appid=%s&msg=%s", key, appid, url.QueryEscape(msg))
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
req, err := http.NewRequest("GET", qykUrl, nil)
if err != nil {
return "", err
}

View File

@@ -1,6 +1,7 @@
// TODO: 移动到 manager 搭配自动验证使用
package qingyunke
// TODO: 移动到 manager 搭配自动验证使用
/*
import (
zero "github.com/wdvxdr1123/ZeroBot"

21
plugin_reborn/born.go Normal file
View File

@@ -0,0 +1,21 @@
package reborn
import (
wr "github.com/mroth/weightedrand"
)
var (
gender, _ = wr.NewChooser(
wr.Choice{Item: "男孩子", Weight: 50707},
wr.Choice{Item: "女孩子", Weight: 48292},
wr.Choice{Item: "雌雄同体", Weight: 1001},
)
)
func randcoun() string {
return areac.Pick().(string)
}
func randgen() string {
return gender.Pick().(string)
}

93
plugin_reborn/load.go Normal file
View File

@@ -0,0 +1,93 @@
package reborn
import (
"encoding/json"
"io"
"net/http"
"os"
wr "github.com/mroth/weightedrand"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
const (
datapath = "data/Reborn"
jsonfile = datapath + "/rate.json"
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + jsonfile
)
type rate []struct {
Name string `json:"name"`
Weight float64 `json:"weight"`
}
var (
areac *wr.Chooser
)
func init() {
go func() {
process.SleepAbout1sTo2s()
err := os.MkdirAll(datapath, 0755)
if err != nil {
panic(err)
}
area := make(rate, 226)
err = load(&area)
if err != nil {
panic(err)
}
choices := make([]wr.Choice, len(area))
for i, a := range area {
choices[i].Item = a.Name
choices[i].Weight = uint(a.Weight * 1e9)
}
areac, err = wr.NewChooser(choices...)
if err != nil {
panic(err)
}
log.Printf("[Reborn]读取%d个国家/地区", len(area))
}()
}
// load 加载rate数据
func load(area *rate) error {
if file.IsExist(jsonfile) {
f, err := os.Open(jsonfile)
if err == nil {
defer f.Close()
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
return json.Unmarshal(data, area)
}
}
return err1
}
} else { // 如果没有小作文,则从 url 下载
f, err := os.Create(jsonfile)
if err != nil {
return err
}
defer f.Close()
resp, err := http.Get(pburl)
if err == nil {
defer resp.Body.Close()
if resp.ContentLength > 0 {
log.Printf("[Reborn]从镜像下载国家和地区%d字节...", resp.ContentLength)
data, err := io.ReadAll(resp.Body)
if err == nil && len(data) > 0 {
_, _ = f.Write(data)
return json.Unmarshal(data, area)
}
return err
}
return nil
}
return err
}
return nil
}

28
plugin_reborn/main.go Normal file
View File

@@ -0,0 +1,28 @@
// Package reborn 投胎 来自 https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py
package reborn
import (
"fmt"
"math/rand"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() {
rand.Seed(time.Now().UnixNano())
control.Register("reborn", &control.Options{
DisableOnDefault: false,
Help: "投胎\n- reborn",
}).OnFullMatch("reborn").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if rand.Int31() > 1<<27 {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("投胎成功!\n您出生在 %s, 是 %s。", randcoun(), randgen())))
} else {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("投胎失败!\n您没能活到出生祝您下次好运"))
}
})
}

View File

@@ -107,7 +107,7 @@ func init() {
}).OnRegex(`^>runcode\s(.+?)\s([\s\S]+)$`).SetBlock(true).SecondPriority().
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.Send("请稍后重试0x0...")
ctx.SendChain(message.Text("请稍后重试0x0..."))
} else {
language := ctx.State["regex_matched"].([]string)[1]
language = strings.ToLower(language)

View File

@@ -3,21 +3,31 @@ package saucenao
import (
"fmt"
"os"
"strconv"
"strings"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/ascii2d"
"github.com/FloatTech/AnimeAPI/picture"
"github.com/FloatTech/AnimeAPI/pixiv"
"github.com/FloatTech/AnimeAPI/saucenao"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
)
var (
datapath = file.BOT_PATH + "/data/saucenao/"
)
func init() { // 插件主体
_ = os.RemoveAll(datapath)
err := os.MkdirAll(datapath, 0755)
if err != nil {
panic(err)
}
engine := control.Register("saucenao", &control.Options{
DisableOnDefault: false,
Help: "搜图\n" +
@@ -28,7 +38,7 @@ func init() { // 插件主体
engine.OnRegex(`^搜图(\d+)$`).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
id, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
ctx.Send("少女祈祷中......")
ctx.SendChain(message.Text("少女祈祷中......"))
// 获取P站插图信息
illust, err := pixiv.Works(id)
if err != nil {
@@ -36,30 +46,48 @@ func init() { // 插件主体
return
}
if illust.Pid > 0 {
// 改用 i.pixiv.cat 镜像站
link := illust.ImageUrls
link = strings.ReplaceAll(link, "i.pximg.net", "i.pixiv.cat")
// 发送搜索结果
ctx.SendChain(
message.Image(link),
message.Text(
"\n",
"标题:", illust.Title, "\n",
"插画ID", illust.Pid, "\n",
"画师:", illust.UserName, "\n",
"画师ID", illust.UserId, "\n",
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
),
name := strconv.FormatInt(illust.Pid, 10)
filepath := datapath + name
switch {
case file.IsExist(filepath + ".jpg"):
filepath = "file:///" + filepath + ".jpg"
case file.IsExist(filepath + ".png"):
filepath = "file:///" + filepath + ".png"
case file.IsExist(filepath + ".gif"):
filepath = "file:///" + filepath + ".gif"
default:
filepath = ""
}
if filepath == "" {
logrus.Debug("[sausenao]开始下载", name)
filepath, err = pixiv.Download(illust.ImageUrls, datapath, name)
if err == nil {
filepath = "file:///" + filepath
}
}
txt := message.Text(
"标题:", illust.Title, "\n",
"插画ID", illust.Pid, "\n",
"画师:", illust.UserName, "\n",
"画师ID", illust.UserId, "\n",
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
)
if filepath != "" {
// 发送搜索结果
ctx.SendChain(message.Image(filepath), message.Text("\n"), txt)
} else {
// 图片下载失败,仅发送文字结果
ctx.SendChain(txt)
}
} else {
ctx.Send("图片不存在!")
ctx.SendChain(message.Text("图片不存在!"))
}
})
// 以图搜图
engine.OnKeywordGroup([]string{"以图搜图", "搜索图片", "以图识图"}, picture.CmdMatch, picture.MustGiven).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
// 开始搜索图片
ctx.Send("少女祈祷中......")
ctx.SendChain(message.Text("少女祈祷中......"))
for _, pic := range ctx.State["image_url"].([]string) {
fmt.Println(pic)
if result, err := saucenao.SauceNAO(pic); err != nil {

View File

@@ -18,13 +18,15 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
. "github.com/FloatTech/ZeroBot-Plugin/data"
fileutil "github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
// Pools 图片缓冲池
type imgpool struct {
Lock sync.Mutex
DB *Sqlite
DB *sql.Sqlite
Path string
Group int64
List []string
@@ -40,7 +42,7 @@ const (
// NewPoolsCache 返回一个缓冲池对象
func newPools() *imgpool {
cache := &imgpool{
DB: &Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
DB: &sql.Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
Path: "data/SetuTime/cache/",
Group: 0,
List: []string{"涩图", "二次元", "风景", "车万"}, // 可以自己加类别,得自己加图片进数据库
@@ -48,29 +50,44 @@ func newPools() *imgpool {
Pool: map[string][]*pixiv.Illust{},
Form: 0,
}
// 每次启动清理缓存
os.RemoveAll(cache.Path)
err := os.MkdirAll(cache.Path, 0755)
if err != nil {
panic(err)
}
// 如果数据库不存在则下载
if _, err := os.Stat(cache.DB.DBPath); err != nil || os.IsNotExist(err) {
f, err := os.Create(cache.DB.DBPath)
if err == nil {
down := func() (err error) {
// 下载
resp, err := http.Get(dburl)
if err == nil {
defer resp.Body.Close()
if resp.ContentLength > 0 {
logrus.Printf("[Setu]从镜像下载数据库%d字节...", resp.ContentLength)
data, err := io.ReadAll(resp.Body)
if err == nil && len(data) > 0 {
_, err = f.Write(data)
if err != nil {
logrus.Errorf("[Setu]写入数据库失败: %v", err)
}
}
}
if err != nil {
return
}
f.Close()
defer resp.Body.Close()
if resp.ContentLength > 0 {
return
}
logrus.Printf("[Setu]从镜像下载数据库%d字节...", resp.ContentLength)
// 生成文件
f, err := os.Create(cache.DB.DBPath)
if err != nil {
return
}
defer f.Close()
// 读取数据
data, err := io.ReadAll(resp.Body)
if err != nil || len(data) > 0 {
return
}
// 写入数据
if _, err = f.Write(data); err != nil {
return
}
return nil
}
if err := down(); err != nil {
logrus.Printf("[Setu]下载数据库失败%v", err)
}
}
for i := range cache.List {
@@ -104,7 +121,7 @@ func init() { // 插件主体
var imgtype = ctx.State["regex_matched"].([]string)[1]
// 补充池子
go func() {
times := min(pool.Max-pool.size(imgtype), 2)
times := math.Min(pool.Max-pool.size(imgtype), 2)
for i := 0; i < times; i++ {
illust := &pixiv.Illust{}
// 查询出一张图片
@@ -120,7 +137,6 @@ func init() { // 插件主体
ctx.SendGroupMessage(pool.Group, []message.MessageSegment{message.Image(file(illust))})
// 向缓冲池添加一张图片
pool.push(imgtype, illust)
time.Sleep(time.Second * 1)
}
}()
@@ -167,7 +183,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send("添加成功")
ctx.SendChain(message.Text("添加成功"))
})
engine.OnRegex(`^删除(.*?)(\d+)$`, firstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
@@ -178,10 +194,10 @@ func init() { // 插件主体
)
// 查询数据库
if err := pool.DB.Del(imgtype, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send("删除成功")
ctx.SendChain(message.Text("删除成功"))
})
// 查询数据库涩图数量
@@ -198,7 +214,7 @@ func init() { // 插件主体
state = append(state, ": ")
state = append(state, fmt.Sprintf("%d", num))
}
ctx.Send(strings.Join(state, ""))
ctx.SendChain(message.Text(state))
})
}
@@ -215,18 +231,6 @@ func firstValueInList(list []string) zero.Rule {
}
}
// min 返回两数最小值
func min(a, b int) int {
switch {
default:
return a
case a > b:
return b
case a < b:
return a
}
}
// size 返回缓冲池指定类型的现有大小
func (p *imgpool) size(imgtype string) int {
return len(p.Pool[imgtype])
@@ -259,8 +263,7 @@ func (p *imgpool) pop(imgtype string) (illust *pixiv.Illust) {
func file(i *pixiv.Illust) string {
filename := fmt.Sprint(i.Pid)
pwd, _ := os.Getwd()
filepath := pwd + `/` + pool.Path + filename
filepath := fileutil.BOT_PATH + `/` + pool.Path + filename
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
return `file:///` + filepath + ".jpg"
}

View File

@@ -1,3 +1,10 @@
/*
* @Author: Kanri
* @Date: 2021-10-15 21:23:14
* @LastEditors: Kanri
* @LastEditTime: 2021-10-15 21:42:51
* @Description:
*/
// Package shindan 基于 https://shindanmaker.com 的测定小功能
package shindan
@@ -52,6 +59,7 @@ func handle(ctx *zero.Ctx) {
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
// TODO: 可注入
ctx.Send(text)
}

55
plugin_tracemoe/moe.go Normal file
View File

@@ -0,0 +1,55 @@
package tracemoe
import (
"fmt"
"github.com/FloatTech/AnimeAPI/picture"
trmoe "github.com/fumiama/gotracemoe"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var (
moe = trmoe.NewMoe("")
)
func init() { // 插件主体
engine := control.Register("tracemoe", &control.Options{
DisableOnDefault: false,
Help: "tracemoe\n- 搜番|搜索番剧[图片]",
})
// 以图搜图
engine.OnKeywordGroup([]string{"搜番", "搜索番剧"}, picture.CmdMatch, picture.MustGiven).SetBlock(true).ThirdPriority().
Handle(func(ctx *zero.Ctx) {
// 开始搜索图片
ctx.SendChain(message.Text("少女祈祷中......"))
for _, pic := range ctx.State["image_url"].([]string) {
fmt.Println(pic)
if result, err := moe.Search(pic, true, true); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
} else if len(result.Result) > 0 {
r := result.Result[0]
hint := "我有把握是这个!"
if r.Similarity < 0.8 {
hint = "大概是这个?"
}
mf := int(r.From / 60)
mt := int(r.To / 60)
sf := r.From - float32(mf*60)
st := r.To - float32(mt*60)
ctx.SendChain(
message.Text(hint),
message.Image(r.Image),
message.Text(
"\n",
"番剧名:", r.Anilist.Title.Native, "\n",
"话数:", r.Episode, "\n",
"时间:", mf, ":", sf, "-", mt, ":", st,
),
)
}
}
})
}

65
plugin_translation/tl.go Normal file
View File

@@ -0,0 +1,65 @@
// Package translation 翻译
package translation
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
var (
prio = 100
bucket = rate.NewManager(time.Minute, 20) // 接口回复
)
func tl(d string) ([]byte, error) {
url := "https://api.cloolc.club/fanyi?data=" + d
resp, err := http.Get(url)
if err != nil {
fmt.Println(err)
}
data, err := ioutil.ReadAll(resp.Body)
_ = resp.Body.Close()
if err != nil {
return nil, err
}
if code := resp.StatusCode; code != 200 {
// 如果返回不是200则立刻抛出错误
errmsg := fmt.Sprintf("code %d", code)
return nil, errors.New(errmsg)
}
return data, err
}
func init() {
control.Register("translation", &control.Options{
DisableOnDefault: false,
Help: "翻译\n" +
">TL 你好",
}).OnRegex(`^>TL\s(-.{1,10}? )?(.*)$`).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
if !bucket.Load(ctx.Event.UserID).Acquire() {
// 频繁触发,不回复
return
}
msg := []string{ctx.State["regex_matched"].([]string)[2]}
rely, err := tl(msg[0])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
info := gjson.ParseBytes(rely)
repo := info.Get("data.0")
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text(repo.Get("value.0")))
})
}

View File

@@ -0,0 +1,41 @@
package vtbquotation
import (
"github.com/fumiama/cron"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation/model"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
func init() {
go func() {
process.SleepAbout1sTo2s()
log.Println("[vtb/cron] 开启vtb数据库日常更新")
vtbDaily()
}()
}
func vtbDaily() {
c := cron.New()
_, err := c.AddFunc("0 4 * * *", func() { vtbData() })
if err != nil {
log.Errorln("定时任务有错误:", err)
} else {
log.Println("开启vtb数据库定时任务")
c.Start()
}
}
func vtbData() {
db := model.Initialize(dbfile)
if db != nil {
for _, v := range db.GetVtbList() {
db.StoreVtb(v)
}
err := db.Close()
if err != nil {
log.Errorln("[vtb/cron]", err)
}
}
}

View File

@@ -0,0 +1,42 @@
package vtbquotation
import (
"io"
"log"
"net/http"
"os"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
const pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + dbfile
// 加载数据库
func init() {
go func() {
process.SleepAbout1sTo2s()
_ = os.MkdirAll(dbpath, 0755)
if !file.IsExist(dbfile) { // 如果没有数据库,则从 url 下载
f, err := os.Create(dbfile)
if err != nil {
panic(err)
}
defer f.Close()
resp, err := http.Get(pburl)
if err == nil {
defer resp.Body.Close()
if resp.ContentLength > 0 {
log.Printf("[vtb]从镜像下载数据库%d字节...", resp.ContentLength)
data, err := io.ReadAll(resp.Body)
if err == nil && len(data) > 0 {
_, _ = f.Write(data)
return
}
panic(err)
}
}
panic(err)
}
}()
}

View File

@@ -0,0 +1,361 @@
package model
import (
"io/ioutil"
"math/rand"
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/jinzhu/gorm"
_ "github.com/logoove/sqlite"
"github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
)
type VtbDB gorm.DB
func Initialize(dbpath string) *VtbDB {
var err error
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
panic(err)
}
gdb.AutoMigrate(FirstCategory{}).AutoMigrate(SecondCategory{}).AutoMigrate(ThirdCategory{})
return (*VtbDB)(gdb)
}
func Open(dbpath string) (*VtbDB, error) {
db, err := gorm.Open("sqlite3", dbpath)
if err != nil {
return nil, err
} else {
return (*VtbDB)(db), nil
}
}
// FirstCategory 第一品类
type FirstCategory struct {
gorm.Model
FirstCategoryIndex int64 `gorm:"column:first_category_index"`
FirstCategoryName string `gorm:"column:first_category_name"`
FirstCategoryUid string `gorm:"column:first_category_uid"`
FirstCategoryDescription string `gorm:"column:first_category_description;type:varchar(1024)"`
FirstCategoryIconPath string `gorm:"column:first_category_icon_path"`
}
func (FirstCategory) TableName() string {
return "first_category"
}
// SecondCategory 第二品类
type SecondCategory struct {
gorm.Model
SecondCategoryIndex int64 `gorm:"column:second_category_index"`
FirstCategoryUid string `gorm:"column:first_category_uid;association_foreignkey:first_category_uid"`
SecondCategoryName string `gorm:"column:second_category_name"`
SecondCategoryAuthor string `gorm:"column:second_category_author"`
SecondCategoryDescription string `gorm:"column:second_category_description"`
}
func (SecondCategory) TableName() string {
return "second_category"
}
// ThirdCategory 第三品类
type ThirdCategory struct {
gorm.Model
ThirdCategoryIndex int64 `gorm:"column:third_category_index"`
SecondCategoryIndex int64 `gorm:"column:second_category_index"`
FirstCategoryUid string `gorm:"column:first_category_uid"`
ThirdCategoryName string `gorm:"column:third_category_name"`
ThirdCategoryPath string `gorm:"column:third_category_path"`
ThirdCategoryAuthor string `gorm:"column:third_category_author"`
ThirdCategoryDescription string `gorm:"column:third_category_description"`
}
func (ThirdCategory) TableName() string {
return "third_category"
}
// GetAllFirstCategoryMessage 取出所有vtb
func (vdb *VtbDB) GetAllFirstCategoryMessage() string {
db := (*gorm.DB)(vdb)
firstStepMessage := "请选择一个vtb并发送序号:\n"
var fc FirstCategory
rows, err := db.Model(&FirstCategory{}).Rows()
if err != nil {
logrus.Errorln("[vtb/model]数据库读取错误", err)
}
if rows == nil {
return ""
}
for rows.Next() {
db.ScanRows(rows, &fc)
// logrus.Println(fc)
firstStepMessage = firstStepMessage + strconv.FormatInt(fc.FirstCategoryIndex, 10) + ". " + fc.FirstCategoryName + "\n"
}
return firstStepMessage
}
// GetAllSecondCategoryMessageByFirstIndex 取得同一个vtb所有语录类别
func (vdb *VtbDB) GetAllSecondCategoryMessageByFirstIndex(firstIndex int) string {
db := (*gorm.DB)(vdb)
SecondStepMessage := "请选择一个语录类别并发送序号:\n"
var sc SecondCategory
var count int
var fc FirstCategory
db.Model(FirstCategory{}).Where("first_category_index = ?", firstIndex).First(&fc)
db.Model(&SecondCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUid).Count(&count)
if count == 0 {
return ""
}
rows, err := db.Model(&SecondCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUid).Rows()
if err != nil {
logrus.Errorln("[vtb/model]数据库读取错误", err)
}
for rows.Next() {
db.ScanRows(rows, &sc)
// logrus.Println(sc)
SecondStepMessage = SecondStepMessage + strconv.FormatInt(sc.SecondCategoryIndex, 10) + ". " + sc.SecondCategoryName + "\n"
}
return SecondStepMessage
}
// GetAllThirdCategoryMessageByFirstIndexAndSecondIndex 取得同一个vtb同个类别的所有语录
func (vdb *VtbDB) GetAllThirdCategoryMessageByFirstIndexAndSecondIndex(firstIndex, secondIndex int) string {
db := (*gorm.DB)(vdb)
ThirdStepMessage := "请选择一个语录并发送序号:\n"
var fc FirstCategory
db.Model(FirstCategory{}).Where("first_category_index = ?", firstIndex).First(&fc)
var count int
db.Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ?", fc.FirstCategoryUid, secondIndex).Count(&count)
if count == 0 {
return ""
}
var tc ThirdCategory
rows, err := db.Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ?", fc.FirstCategoryUid, secondIndex).Rows()
if err != nil {
logrus.Errorln("[vtb/model]数据库读取错误", err)
}
for rows.Next() {
db.ScanRows(rows, &tc)
// logrus.Println(tc)
ThirdStepMessage = ThirdStepMessage + strconv.FormatInt(tc.ThirdCategoryIndex, 10) + ". " + tc.ThirdCategoryName + "\n"
}
return ThirdStepMessage
}
// GetThirdCategory
func (vdb *VtbDB) GetThirdCategory(firstIndex, secondIndex, thirdIndex int) ThirdCategory {
db := (*gorm.DB)(vdb)
var fc FirstCategory
db.Model(FirstCategory{}).Where("first_category_index = ?", firstIndex).First(&fc)
var tc ThirdCategory
db.Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?", fc.FirstCategoryUid, secondIndex, thirdIndex).Take(&tc)
return tc
}
func (vdb *VtbDB) RandomVtb() ThirdCategory {
db := (*gorm.DB)(vdb)
rand.Seed(time.Now().UnixNano())
var count int
db.Model(&ThirdCategory{}).Count(&count)
// logrus.Info("一共有", count, "个")
var tc ThirdCategory
db.Model(&ThirdCategory{}).Offset(rand.Intn(count)).Take(&tc)
// logrus.Info(tc)
return tc
}
func (vdb *VtbDB) GetFirstCategoryByFirstUid(firstUid string) FirstCategory {
db := (*gorm.DB)(vdb)
var fc FirstCategory
db.Model(FirstCategory{}).Where("first_category_uid = ?", firstUid).Take(&fc)
// logrus.Info(fc)
return fc
}
func (vdb *VtbDB) Close() error {
db := (*gorm.DB)(vdb)
return db.Close()
}
const vtbUrl = "https://vtbkeyboard.moe/api/get_vtb_list"
func (vdb *VtbDB) GetVtbList() []string {
db := (*gorm.DB)(vdb)
client := &http.Client{}
req, err := http.NewRequest("GET", vtbUrl, nil)
if err != nil {
logrus.Errorln(err)
}
// 自定义Header
req.Header.Set("User-Agent", randua())
resp, err := client.Do(req)
if err != nil {
logrus.Errorln(err)
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
logrus.Errorln(err)
}
// logrus.Println(string(bytes))
vtbListStr, err := strconv.Unquote(strings.Replace(strconv.Quote(string(bytes)), `\\u`, `\u`, -1))
if err != nil {
logrus.Errorln(err)
}
// logrus.Println(vtbListStr)
uidList := make([]string, 0)
count := gjson.Get(vtbListStr, "#").Int()
for i := int64(0); i < count; i++ {
item := gjson.Get(vtbListStr, strconv.FormatInt(i, 10))
logrus.Println(item)
fc := FirstCategory{
FirstCategoryIndex: i,
FirstCategoryName: item.Get("name").String(),
FirstCategoryDescription: item.Get("description").String(),
FirstCategoryIconPath: item.Get("icon_path").String(),
FirstCategoryUid: item.Get("uid").String(),
}
logrus.Println(fc)
//db.Model(FirstCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUid).FirstOrCreate(&fc)
if err := db.Debug().Model(&FirstCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUid).First(&fc).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&FirstCategory{}).Create(&fc) // newUser not user
}
} else {
db.Debug().Model(&FirstCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUid).Update(
map[string]interface{}{
"first_category_index": i,
"first_category_name": item.Get("name").String(),
"first_category_description": item.Get("description").String(),
"first_category_icon_path": item.Get("icon_path").String(),
})
}
uidList = append(uidList, fc.FirstCategoryUid)
}
// logrus.Println(uidList)
return uidList
}
func (vdb *VtbDB) StoreVtb(uid string) {
db := (*gorm.DB)(vdb)
vtbUrl := "https://vtbkeyboard.moe/api/get_vtb_page?uid=" + uid
client := &http.Client{}
req, err := http.NewRequest("GET", vtbUrl, nil)
if err != nil {
logrus.Errorln(err)
}
// 自定义Header
req.Header.Set("User-Agent", randua())
resp, err := client.Do(req)
if err != nil {
logrus.Errorln(err)
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
logrus.Errorln(err)
}
//logrus.Println(string(bytes))
vtbStr, err := strconv.Unquote(strings.Replace(strconv.Quote(string(bytes)), `\\u`, `\u`, -1))
if err != nil {
logrus.Errorln(err)
}
// logrus.Println(vtbListStr)
secondCount := gjson.Get(vtbStr, "data.voices.#").Int()
logrus.Println("二级品类一共有", secondCount)
for secondIndex := int64(0); secondIndex < secondCount; secondIndex++ {
secondItem := gjson.Get(vtbStr, "data.voices."+strconv.FormatInt(secondIndex, 10))
logrus.Println(secondItem)
sc := SecondCategory{
SecondCategoryName: secondItem.Get("categoryName").String(),
SecondCategoryIndex: secondIndex,
SecondCategoryAuthor: secondItem.Get("author").String(),
SecondCategoryDescription: secondItem.Get("categoryDescription.zh-CN").String(),
FirstCategoryUid: uid,
}
// logrus.Println(sc)
// db.Model(SecondCategory{}).Where("first_category_uid = ? and second_category_index = ?", uid, secondIndex).FirstOrCreate(&sc)
if err := db.Debug().Model(&SecondCategory{}).Where("first_category_uid = ? and second_category_index = ?", uid, secondIndex).First(&sc).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&SecondCategory{}).Create(&sc) // newUser not user
}
} else {
db.Debug().Model(&SecondCategory{}).Where("first_category_uid = ? and second_category_index = ?", uid, secondIndex).Update(
map[string]interface{}{
"second_category_name": secondItem.Get("categoryName").String(),
"second_category_author": secondItem.Get("author").String(),
"second_category_description": secondItem.Get("categoryDescription.zh-CN").String(),
})
}
thirdCount := secondItem.Get("voiceList.#").Int()
logrus.Println("三级品类一共有", thirdCount)
for thirdIndex := int64(0); thirdIndex < thirdCount; thirdIndex++ {
thirdItem := secondItem.Get("voiceList." + strconv.FormatInt(thirdIndex, 10))
logrus.Println(thirdItem)
tc := ThirdCategory{
ThirdCategoryName: thirdItem.Get("name").String(),
ThirdCategoryIndex: thirdIndex,
ThirdCategoryDescription: thirdItem.Get("description.zh-CN").String(),
FirstCategoryUid: uid,
SecondCategoryIndex: secondIndex,
ThirdCategoryPath: thirdItem.Get("path").String(),
ThirdCategoryAuthor: thirdItem.Get("author").String(),
}
logrus.Println(tc)
//db.Model(ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?",
// uid, secondIndex, thirdIndex).FirstOrCreate(&tc)
if err := db.Debug().Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?",
uid, secondIndex, thirdIndex).First(&tc).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&ThirdCategory{}).Create(&tc) // newUser not user
}
} else {
db.Debug().Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?",
uid, secondIndex, thirdIndex).Update(
map[string]interface{}{
"third_category_name": thirdItem.Get("name").String(),
"third_category_description": thirdItem.Get("description.zh-CN").String(),
"third_category_path": thirdItem.Get("path").String(),
"third_category_author": thirdItem.Get("author").String(),
})
}
}
}
}
var agent = [...]string{
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
"User-Agent,Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"User-Agent, Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
"User-Agent,Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
}
func randua() string {
return agent[rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(agent))]
}

View File

@@ -0,0 +1,159 @@
package vtbquotation
import (
"net/url"
"regexp"
"strconv"
"strings"
"time"
_ "github.com/logoove/sqlite"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation/model"
)
const regStr = ".*/(.*)"
const dbpath = "data/VtbQuotation/"
const dbfile = dbpath + "vtb.db"
var engine = control.Register("vtbquotation", &control.Options{
DisableOnDefault: false,
Help: "vtbquotation\n- vtb语录\n- 随机vtb\n",
})
func init() {
engine.OnFullMatch("vtb语录").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var firstIndex int
var secondIndex int
var thirdIndex int
echo, cancel := ctx.FutureEvent("message",
ctx.CheckSession()). // 只复读开启复读模式的人的消息
Repeat() // 不断监听复读
db, err := model.Open(dbfile)
if err != nil {
logrus.Errorln(err)
return
}
defer db.Close()
defer cancel()
firstStepMessage := db.GetAllFirstCategoryMessage()
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(firstStepMessage))
// 步骤012依次选择3个类别
step := 0
// 错误次数
errorCount := 0
for {
select {
case e := <-echo: // 接收到需要复读的消息
// 错误次数达到3次结束命令
if errorCount >= 3 {
ctx.SendChain(message.Reply(e.MessageID), message.Text("输入错误太多,请重新发指令"))
return
}
switch step {
case 0:
firstIndex, err = strconv.Atoi(e.RawMessage)
// log.Println(fmt.Sprintf("当前在第%d步", step))
// log.Println(fmt.Sprintf("firstIndex:%d,secondIndex:%d,thirdIndex:%d", firstIndex, secondIndex, thirdIndex))
if err != nil {
ctx.SendChain(message.Reply(e.MessageID), message.Text("请输入正确的序号,三次输入错误,指令可退出重输"))
errorCount++
} else {
SecondStepMessage := db.GetAllSecondCategoryMessageByFirstIndex(firstIndex)
// log.Println(SecondStepMessage)
if SecondStepMessage == "" {
ctx.SendChain(message.Reply(e.MessageID), message.Text("你选择的序号没有内容,请重新选择,三次输入错误,指令可退出重输"))
ctx.SendChain(message.Reply(e.MessageID), message.Text(db.GetAllFirstCategoryMessage()))
errorCount++
} else {
ctx.SendChain(message.Reply(e.MessageID), message.Text(SecondStepMessage))
step++
}
}
case 1:
secondIndex, err = strconv.Atoi(e.RawMessage)
// log.Println(fmt.Sprintf("当前在第%d步", step))
// log.Println(fmt.Sprintf("firstIndex:%d,secondIndex:%d,thirdIndex:%d", firstIndex, secondIndex, thirdIndex))
if err != nil {
ctx.SendChain(message.Reply(e.MessageID), message.Text("请输入正确的序号,三次输入错误,指令可退出重输"))
errorCount++
} else {
ThirdStepMessage := db.GetAllThirdCategoryMessageByFirstIndexAndSecondIndex(firstIndex, secondIndex)
// log.Println(ThirdStepMessage)
if ThirdStepMessage == "" {
ctx.SendChain(message.Reply(e.MessageID), message.Text("你选择的序号没有内容,请重新选择,三次输入错误,指令可退出重输"))
ctx.SendChain(message.Reply(e.MessageID), message.Text(db.GetAllSecondCategoryMessageByFirstIndex(firstIndex)))
errorCount++
} else {
ctx.SendChain(message.Reply(e.MessageID), message.Text(ThirdStepMessage))
step++
}
}
case 2:
thirdIndex, err = strconv.Atoi(e.RawMessage)
// log.Println(fmt.Sprintf("当前在第%d步", step))
// log.Println(fmt.Sprintf("firstIndex:%d,secondIndex:%d,thirdIndex:%d", firstIndex, secondIndex, thirdIndex))
if err != nil {
ctx.SendChain(message.Reply(e.MessageID), message.Text("请输入正确的序号,三次输入错误,指令可退出重输"))
errorCount++
} else {
tc := db.GetThirdCategory(firstIndex, secondIndex, thirdIndex)
reg := regexp.MustCompile(regStr)
recordUrl := tc.ThirdCategoryPath
if recordUrl == "" {
ctx.SendChain(message.Reply(e.MessageID), message.Text("没有内容请重新选择,三次输入错误,指令可退出重输"))
ctx.SendChain(message.Reply(e.MessageID), message.Text(db.GetAllFirstCategoryMessage()))
errorCount++
step = 1
} else {
if reg.MatchString(recordUrl) {
// log.Println(reg.FindStringSubmatch(recordUrl)[1])
// log.Println(url.QueryEscape(reg.FindStringSubmatch(recordUrl)[1]))
recordUrl = strings.Replace(recordUrl, reg.FindStringSubmatch(recordUrl)[1], url.QueryEscape(reg.FindStringSubmatch(recordUrl)[1]), -1)
recordUrl = strings.Replace(recordUrl, "+", "%20", -1)
// log.Println(recordUrl)
}
ctx.SendChain(message.Reply(e.MessageID), message.Text("请欣赏《"+tc.ThirdCategoryName+"》"))
ctx.SendChain(message.Record(recordUrl))
return
}
}
default:
return
}
case <-time.After(time.Second * 60):
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("vtb语录指令过期"))
return
}
}
})
engine.OnFullMatch("随机vtb").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
db, err := model.Open(dbfile)
if err != nil {
logrus.Errorln(err)
return
}
tc := db.RandomVtb()
fc := db.GetFirstCategoryByFirstUid(tc.FirstCategoryUid)
if (tc != model.ThirdCategory{}) && (fc != model.FirstCategory{}) {
reg := regexp.MustCompile(regStr)
recordUrl := tc.ThirdCategoryPath
if reg.MatchString(recordUrl) {
// log.Println(reg.FindStringSubmatch(recordUrl)[1])
// log.Println(url.QueryEscape(reg.FindStringSubmatch(recordUrl)[1]))
recordUrl = strings.Replace(recordUrl, reg.FindStringSubmatch(recordUrl)[1], url.QueryEscape(reg.FindStringSubmatch(recordUrl)[1]), -1)
recordUrl = strings.Replace(recordUrl, "+", "%20", -1)
// log.Println(recordUrl)
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("请欣赏"+fc.FirstCategoryName+"的《"+tc.ThirdCategoryName+"》"))
ctx.SendChain(message.Record(recordUrl))
}
db.Close()
})
}

72
plugin_wtf/main.go Normal file
View File

@@ -0,0 +1,72 @@
package wtf
import (
"fmt"
"strconv"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var (
// 限制调用频率
limit = rate.NewManager(time.Minute*5, 5)
)
func init() {
en := control.Register("wtf", &control.Options{
DisableOnDefault: false,
Help: "鬼东西\n- 鬼东西列表\n- 查询鬼东西[序号][@xxx]",
})
en.OnFullMatch("鬼东西列表").SetBlock(true).SetPriority(30).
Handle(func(ctx *zero.Ctx) {
s := ""
for i, w := range table {
s += fmt.Sprintf("%02d. %s\n", i, w.name)
i++
}
ctx.SendChain(message.Text(s))
})
en.OnRegex(`^查询鬼东西(\d*)`).SetBlock(true).SetPriority(30).
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.SendChain(message.Text("请稍后重试0x0..."))
return
}
// 调用接口
i, err := strconv.Atoi(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
w := NewWtf(i)
if w == nil {
ctx.SendChain(message.Text("没有这项内容!"))
return
}
// 获取名字
var name string
var secondname string
if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
qq, _ := strconv.ParseInt(ctx.Event.Message[1].Data["qq"], 10, 64)
secondname = ctx.GetGroupMemberInfo(ctx.Event.GroupID, qq, false).Get("nickname").Str
}
name = ctx.Event.Sender.NickName
var text string
if secondname != "" {
text, err = w.Predict(name, secondname)
} else {
text, err = w.Predict(name)
}
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// TODO: 可注入
ctx.Send(text)
})
}

155
plugin_wtf/model.go Normal file
View File

@@ -0,0 +1,155 @@
package wtf
import (
"encoding/json"
"errors"
"io"
"net/http"
"net/url"
)
/* JS path getter for https://wtf.hiigara.net/ranking
a = document.getElementById("testList").getElementsByTagName("a")
s = ""
for(i=0; i<a.length; i++) {
s += "\"" + a[i].innerText + "\":\"" + a[i].href + "\",\n";
}
*/
const apiprefix = "https://wtf.hiigara.net/api/run/"
type Wtf struct {
name string
path string
}
var table = [...]*Wtf{
{"你的意义是什么?", "mRIFuS"},
{"【ABO】性別和信息素", "KXyy9"},
{"测测cp", "ZoGXQd"},
{"xxx和xxx的關係是", "L4HfA"},
{"在JOJO世界你的替身会是什么", "lj0a8o"},
{"稱號產生器", "titlegen"},
{"成分报告", "2PCeo1"},
{"測驗你跟你的朋友是攻/受", "LkQXO3"},
{"测试两人的关系?", "uwjQQt"},
{"【Fate系列】當你成為了從者 2.0", "LHStH2"},
{"想不到自己未來要做什麼工作嗎?", "D1agGa"},
{"(σ゚∀゚)σ名字產生器", "LNxXq7"},
{"人設生產器", "LBtPu5"},
{"測驗你在ABO世界的訊息素", "SwmdU"},
{"爱是什么", "llpBEY"},
{"測測你和哪位名人相似?", "RHQeXu"},
{"S/M测试", "Ga47oZ"},
{"测测你是谁", "aV1AEi"},
{"取個綽號吧", "LTkyUy"},
{"什麼都不是", "vyrSCb"},
{"今天中午吃什麼", "LdS4K6"},
{"測試你的中二稱號", "LwUmQ6"},
{"神奇海螺", "Lon1h7"},
{"ABO測試", "H1Tgd"},
{"女主角姓名產生器", "MsQBTd"},
{"您是什么人", "49PwSd"},
{"如果你成为了干员", "ok5e7n"},
{"abo人设生成~", "Di8enA"},
{"✡你的命運✡塔羅占卜🔮", "ohCzID"},
{"小說大綱生產器", "Lnstjz"},
{"他会喜欢你吗?", "pezX3a"},
{"抽签!你明年的今天会干什么", "IF31kS"},
{"如果你是受,會是哪種受呢?", "Dr6zpF"},
{"cp文梗", "vEO2KD"},
{"您是什么人?", "TQ5qyl"},
{"你成為......的機率", "g0uoBL"},
{"ABO性別與信息素", "KFPju"},
{"異國名稱產生器(國家、人名、星球...)", "OBpu4"},
{"對方到底喜不喜歡你", "JSLoZC"},
{"【脑叶公司】测一测你在脑叶公司的经历", "uPBhjC"},
{"当你成为魔法少女", "7ZiGcJ"},
{"你是yyds吗?", "SpBnCa"},
{"○○喜歡你嗎?", "S6Uceo"},
{"测测你的sm属性", "dOtcO5"},
{"你/妳究竟是攻還是受呢?", "RXALH"},
{"神秘藏书阁", "tDRyET"},
{"中午吃什么?", "L0Wsis"},
{"十年后你cp的结局是", "VUwnXQ"},
{"高维宇宙与常数的你", "6Zql97"},
{"色色的東東", "o2eg74"},
{"文章標題產生器", "Ky25WO"},
{"你的成績怎麼樣", "6kZv69"},
{"智能SM偵測器ヾ(*ΦωΦ)ツ", "9pY6HQ"},
{"你的使用注意事項", "La4Gir"},
{"戀愛指數", "Jsgz0"},
{"测试你今晚拉的屎", "N8dbcL"},
{"成為情侶的機率ᶫᵒᵛᵉᵧₒᵤ♥", "eDURch"},
{"他對你...", "CJxHMf"},
{"你的明日方舟人际关系", "u5z4Mw"},
{"日本姓氏產生器", "JJ5Ctb"},
{"當你轉生到了異世界,你將成為...", "FTpwK"},
{"魔幻世界大穿越2.0", "wUATOq"},
{"未來男朋友", "F3dSV"},
{"ABO與信息素", "KFOGA"},
{"你必將就這樣一事無成啊アホ", "RWw9oX"},
{"用習慣舉手的方式測試你的戀愛運!<3", "wv5bzA"},
{"攻受", "RaKmY"},
{"你和你喜歡的人的微h寵溺段子XD", "LdQqGz"},
{"我的藝名", "LBaTx"},
{"你是什麼神?", "LqZORE"},
{"你的起源是什麼?", "HXWwC"},
{"測你喜歡什麼", "Sue5g2"},
{"看看朋友的秘密", "PgKb8r"},
{"你在動漫裡的名字", "Lz82V7"},
{"小說男角名字產生器", "LyGDRr"},
{"測試短文", "S48yA"},
{"我們兩人在一起的機率......", "LBZbgE"},
{"創造小故事", "Kjy3AS"},
{"你的另外一個名字", "LuyYQA"},
{"與你最匹配的攻君屬性 ", "I7pxy"},
{"英文全名生產器(女)", "HcYbq"},
{"BL文章生產器", "LBZMO"},
{"輕小說書名產生器", "NFucA"},
{"長相評分", "2cQSDP"},
{"日本名字產生器(女孩子)", "JRiKv"},
{"中二技能名產生器", "Ky1BA"},
{"抽籤", "XqxfuH"},
{"你的蘿莉控程度全國排名", "IIWh9k"},
}
func NewWtf(index int) *Wtf {
if index >= 0 && index < len(table) {
return table[index]
}
return nil
}
type result struct {
Text string `json:"text"`
// Path string `json:"path"`
Ok bool `json:"ok"`
Msg string `json:"msg"`
}
func (w *Wtf) Predict(names ...string) (string, error) {
name := ""
for _, n := range names {
name += "/" + url.QueryEscape(n)
}
u := apiprefix + w.path + name
resp, err := http.Get(u)
if err != nil {
return "", err
}
r, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return "", err
}
re := new(result)
err = json.Unmarshal(r, re)
if err != nil {
return "", err
}
if re.Ok {
return "> " + w.name + "\n" + re.Text, nil
}
return "", errors.New(re.Msg)
}

11
utils/file/dir_nowin.go Normal file
View File

@@ -0,0 +1,11 @@
//go:build !windows
// +build !windows
package file
import "os"
func Pwd() (path string) {
path, _ = os.Getwd()
return
}

14
utils/file/dir_win.go Normal file
View File

@@ -0,0 +1,14 @@
//go:build windows
// +build windows
package file
import (
"os"
"strings"
)
func Pwd() string {
path, _ := os.Getwd()
return strings.ReplaceAll(path, "\\", "/")
}

37
utils/file/dl.go Normal file
View File

@@ -0,0 +1,37 @@
// Package file 文件实用工具
package file
import (
"crypto/tls"
"io"
"net/http"
"os"
)
var (
tr = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
nochkcrtcli = &http.Client{Transport: tr}
)
// DownloadTo 下载到路径
func DownloadTo(url, file string, chkcrt bool) error {
var resp *http.Response
var err error
if chkcrt {
resp, err = http.Get(url)
} else {
resp, err = nochkcrtcli.Get(url)
}
if err == nil {
var f *os.File
f, err = os.Create(file)
if err == nil {
_, err = io.Copy(f, resp.Body)
resp.Body.Close()
f.Close()
}
}
return err
}

17
utils/file/f.go Normal file
View File

@@ -0,0 +1,17 @@
package file
import "os"
var BOT_PATH = Pwd()
// IsExist 文件/路径存在
func IsExist(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}
// IsExist 文件/路径不存在
func IsNotExist(path string) bool {
_, err := os.Stat(path)
return err != nil && os.IsNotExist(err)
}

18
utils/math/math.go Normal file
View File

@@ -0,0 +1,18 @@
// Package math 计算实用工具
package math
// Max 返回两数最大值,该函数将被内联
func Max(a, b int) int {
if a > b {
return a
}
return b
}
// Min 返回两数最小值,该函数将被内联
func Min(a, b int) int {
if a > b {
return b
}
return a
}

10
utils/process/sleep.go Normal file
View File

@@ -0,0 +1,10 @@
package process
import (
"math/rand"
"time"
)
func SleepAbout1sTo2s() {
time.Sleep(time.Second + time.Millisecond*time.Duration(rand.Intn(1000)))
}

View File

@@ -1,11 +1,12 @@
package data
// Package sql 数据库/数据处理相关工具
package sql
import (
"database/sql"
"reflect"
"strings"
_ "modernc.org/sqlite" // 引入sqlite
_ "github.com/logoove/sqlite" // 引入sqlite
)
// Sqlite 数据库对象
@@ -19,7 +20,7 @@ type Sqlite struct {
// 返回错误
func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
if db.DB == nil {
database, err := sql.Open("sqlite", db.DBPath)
database, err := sql.Open("sqlite3", db.DBPath)
if err != nil {
return err
}
@@ -47,17 +48,15 @@ func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
cmd = append(cmd, "NULL);")
}
}
if _, err := db.DB.Exec(strings.Join(cmd, " ")); err != nil {
return err
}
return nil
_, err = db.DB.Exec(strings.Join(cmd, " ") + ";")
return
}
// Insert 插入数据集
// 默认结构体的第一个元素为主键
// 返回错误
func (db *Sqlite) Insert(table string, objptr interface{}) (err error) {
rows, err := db.DB.Query("SELECT * FROM " + table)
func (db *Sqlite) Insert(table string, objptr interface{}) error {
rows, err := db.DB.Query("SELECT * FROM " + table + ";")
if err != nil {
return err
}
@@ -101,7 +100,7 @@ func (db *Sqlite) Insert(table string, objptr interface{}) (err error) {
cmd = append(cmd, ")")
}
}
stmt, err := db.DB.Prepare(strings.Join(cmd, " "))
stmt, err := db.DB.Prepare(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
@@ -109,19 +108,19 @@ func (db *Sqlite) Insert(table string, objptr interface{}) (err error) {
if err != nil {
return err
}
return nil
return stmt.Close()
}
// Find 查询数据库
// condition 可为"WHERE id = 0"
// 默认字段与结构体元素顺序一致
// 返回错误
func (db *Sqlite) Find(table string, objptr interface{}, condition string) (err error) {
func (db *Sqlite) Find(table string, objptr interface{}, condition string) error {
var cmd = []string{}
cmd = append(cmd, "SELECT * FROM ")
cmd = append(cmd, table)
cmd = append(cmd, condition)
rows, err := db.DB.Query(strings.Join(cmd, " "))
rows, err := db.DB.Query(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
@@ -170,12 +169,12 @@ func (db *Sqlite) ListTables() (s []string, err error) {
// Del 删除数据库
// condition 可为"WHERE id = 0"
// 返回错误
func (db *Sqlite) Del(table string, condition string) (err error) {
func (db *Sqlite) Del(table string, condition string) error {
var cmd = []string{}
cmd = append(cmd, "DELETE FROM")
cmd = append(cmd, table)
cmd = append(cmd, condition)
stmt, err := db.DB.Prepare(strings.Join(cmd, " "))
stmt, err := db.DB.Prepare(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
@@ -183,7 +182,7 @@ func (db *Sqlite) Del(table string, condition string) (err error) {
if err != nil {
return err
}
return nil
return stmt.Close()
}
// Count 查询数据库行数
@@ -192,17 +191,17 @@ func (db *Sqlite) Count(table string) (num int, err error) {
var cmd = []string{}
cmd = append(cmd, "SELECT * FROM")
cmd = append(cmd, table)
rows, err := db.DB.Query(strings.Join(cmd, " "))
rows, err := db.DB.Query(strings.Join(cmd, " ") + ";")
if err != nil {
return num, err
}
if rows.Err() != nil {
return num, rows.Err()
}
defer rows.Close()
for rows.Next() {
num++
}
rows.Close()
return num, nil
}

25
utils/web/http.go Normal file
View File

@@ -0,0 +1,25 @@
package web
import (
"io"
"net/http"
)
func ReqWith(url string, method string, referer string, ua string) (data []byte, err error) {
client := &http.Client{}
// 提交请求
var reqest *http.Request
reqest, err = http.NewRequest(method, url, nil)
if err == nil {
// 增加header选项
reqest.Header.Add("Referer", referer)
reqest.Header.Add("User-Agent", ua)
var response *http.Response
response, err = client.Do(reqest)
if err == nil {
data, err = io.ReadAll(response.Body)
response.Body.Close()
}
}
return
}