mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-06 15:20:22 +00:00
Compare commits
293 Commits
v1.2.2-bet
...
v1.3.1-fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebca124c86 | ||
|
|
3b7803a81b | ||
|
|
b7b9d92148 | ||
|
|
44575fb19e | ||
|
|
f181a4b9cd | ||
|
|
77e5d8b0c2 | ||
|
|
edd9feb8f8 | ||
|
|
81d6a06dbe | ||
|
|
8afbc67bf7 | ||
|
|
a27132f907 | ||
|
|
183be05d82 | ||
|
|
bccf789714 | ||
|
|
55944dddb3 | ||
|
|
f67932cc56 | ||
|
|
6d633fac6a | ||
|
|
86fc5c51c8 | ||
|
|
156e9f07ad | ||
|
|
1ba4722fc7 | ||
|
|
54c9857219 | ||
|
|
ea56c7d0d2 | ||
|
|
0cbe43df97 | ||
|
|
1f941d883a | ||
|
|
f5b3e423fb | ||
|
|
6c7f81ca55 | ||
|
|
3911b5ed82 | ||
|
|
f38f3ab69c | ||
|
|
846db6f063 | ||
|
|
ff068a05b0 | ||
|
|
051b7dd182 | ||
|
|
11870aeed6 | ||
|
|
9bcff82d9c | ||
|
|
309efe8cd8 | ||
|
|
bf54789f0f | ||
|
|
01e527abdb | ||
|
|
db6b558c75 | ||
|
|
9a792eb144 | ||
|
|
44e99664a3 | ||
|
|
9f3dd37bf0 | ||
|
|
f5936d9cb7 | ||
|
|
27e69ef022 | ||
|
|
6262aab6bd | ||
|
|
4781bc8eb7 | ||
|
|
b233c4b638 | ||
|
|
0a0cc807dc | ||
|
|
feeeb63e52 | ||
|
|
5c620d6268 | ||
|
|
a469000d7a | ||
|
|
0e15ac78b2 | ||
|
|
d9e195ccd0 | ||
|
|
cf52997279 | ||
|
|
88318a7151 | ||
|
|
91f522b666 | ||
|
|
1895f8815e | ||
|
|
7be5f52be4 | ||
|
|
0cfb2e4e06 | ||
|
|
5ccf753af3 | ||
|
|
bfcf3cac91 | ||
|
|
bc3d7bc278 | ||
|
|
7cf767f344 | ||
|
|
7aed9a2c89 | ||
|
|
454196a462 | ||
|
|
1597ba7128 | ||
|
|
480523ff27 | ||
|
|
7ec7ab8682 | ||
|
|
ba2d011d48 | ||
|
|
504e6cd1cc | ||
|
|
b8f3700fe4 | ||
|
|
b2cff862bb | ||
|
|
dc348f8500 | ||
|
|
8c40293fed | ||
|
|
48deaf3aca | ||
|
|
6932643788 | ||
|
|
7f972e3d68 | ||
|
|
edb0880999 | ||
|
|
45f0f5cd6c | ||
|
|
e468ac1933 | ||
|
|
55b6b40acf | ||
|
|
5f1190f72e | ||
|
|
b0fbd6507d | ||
|
|
598a664d30 | ||
|
|
211f0a667d | ||
|
|
28fb788778 | ||
|
|
628830fbf5 | ||
|
|
7d235d0077 | ||
|
|
861b0b6cef | ||
|
|
9986c57727 | ||
|
|
f1c9e2331c | ||
|
|
7c1ddc6ab1 | ||
|
|
44ad78761b | ||
|
|
bd6925f2f1 | ||
|
|
3838d74cb8 | ||
|
|
eaad8beb7b | ||
|
|
14acdfdbc3 | ||
|
|
a5fe7a5b40 | ||
|
|
61df3c55b5 | ||
|
|
eb0059c1a3 | ||
|
|
4ca5038ae9 | ||
|
|
121403231a | ||
|
|
b945338a8d | ||
|
|
ae5ea542a0 | ||
|
|
fe95dc8201 | ||
|
|
1eefb4e610 | ||
|
|
8660d8d990 | ||
|
|
37033fe48d | ||
|
|
30665ad8c6 | ||
|
|
f9e4b8db76 | ||
|
|
c486a210e4 | ||
|
|
0cd01959a0 | ||
|
|
d5ac9f7920 | ||
|
|
6b2dd112a6 | ||
|
|
01abfab133 | ||
|
|
e2a56872dc | ||
|
|
6f22a9c4bc | ||
|
|
a2426de70c | ||
|
|
ed7bbf54a7 | ||
|
|
69394377d0 | ||
|
|
8f20487a15 | ||
|
|
fae24db2df | ||
|
|
f8fb791d8f | ||
|
|
f320d9e1e5 | ||
|
|
18bd34fad2 | ||
|
|
cf72d0b36a | ||
|
|
c3722b0a6c | ||
|
|
3af701e803 | ||
|
|
bc4b2e89db | ||
|
|
3cbb589d2c | ||
|
|
63ef93a9f9 | ||
|
|
8c943d2c01 | ||
|
|
806b77acce | ||
|
|
3df0414621 | ||
|
|
04f70b0499 | ||
|
|
0b20087e61 | ||
|
|
5c82600972 | ||
|
|
45edd86cb8 | ||
|
|
8f6b3fa00d | ||
|
|
a16bcda7da | ||
|
|
259b29f6e3 | ||
|
|
477868c601 | ||
|
|
92de963c0c | ||
|
|
a7c56d9e77 | ||
|
|
4fe64eeb44 | ||
|
|
fc0d020a04 | ||
|
|
617e2c9885 | ||
|
|
bb1130490b | ||
|
|
ca18a323e3 | ||
|
|
0770c6e4a1 | ||
|
|
e1dbfe8f6a | ||
|
|
a2854069ac | ||
|
|
9f0efc2bda | ||
|
|
ec5798f264 | ||
|
|
ded20441fa | ||
|
|
47064dbcec | ||
|
|
2cda7ecb04 | ||
|
|
b372892a20 | ||
|
|
fabf62059e | ||
|
|
c524c68809 | ||
|
|
876fd425e4 | ||
|
|
72ed1293f6 | ||
|
|
fa973a9231 | ||
|
|
e245a8f124 | ||
|
|
aa71fa7cb8 | ||
|
|
da5aab3ee6 | ||
|
|
e0317d1fe1 | ||
|
|
3557a0ebc1 | ||
|
|
ddd0cc4538 | ||
|
|
0212ec51cc | ||
|
|
7109e30d93 | ||
|
|
6990819d5c | ||
|
|
b4ff754934 | ||
|
|
6ece644a7b | ||
|
|
f826b4d0bc | ||
|
|
aa1f82d46f | ||
|
|
f7c6d67428 | ||
|
|
cd30d6df31 | ||
|
|
7463792de7 | ||
|
|
80f49c47c6 | ||
|
|
4baead3490 | ||
|
|
2d0c69344a | ||
|
|
a94ea2b332 | ||
|
|
4ee50a6582 | ||
|
|
b21021bd6b | ||
|
|
7238fe0b6b | ||
|
|
e1b5c176c3 | ||
|
|
3aabc089d8 | ||
|
|
db5177027f | ||
|
|
0e2da1b983 | ||
|
|
1583006018 | ||
|
|
6b49c2842c | ||
|
|
9c4a5dc818 | ||
|
|
8256658ac2 | ||
|
|
4b11ff495d | ||
|
|
461dc925af | ||
|
|
1233b1d11c | ||
|
|
6dbc0b3891 | ||
|
|
db3cef9bb6 | ||
|
|
3de009727e | ||
|
|
8d35515497 | ||
|
|
4519dd5eb8 | ||
|
|
925e6847f3 | ||
|
|
9462cbc7e0 | ||
|
|
8ec4271419 | ||
|
|
173fd250cb | ||
|
|
89bdc1e496 | ||
|
|
48736d3f4a | ||
|
|
f8df60f06b | ||
|
|
9bd0ed03a5 | ||
|
|
cb1e4bcdb7 | ||
|
|
af8e6a63b9 | ||
|
|
8c8cd709b5 | ||
|
|
18ae566d34 | ||
|
|
9cfa44d434 | ||
|
|
23393d9157 | ||
|
|
b676e00f0b | ||
|
|
790200e519 | ||
|
|
ccde99e695 | ||
|
|
a80f8082cc | ||
|
|
4b194627bb | ||
|
|
d983c66597 | ||
|
|
30f6b57941 | ||
|
|
107979c459 | ||
|
|
f05f09d741 | ||
|
|
bc989f2fb0 | ||
|
|
9b4494a24f | ||
|
|
d3fafa7b9a | ||
|
|
ce1e85e0a3 | ||
|
|
560df5cade | ||
|
|
9f6e361e6e | ||
|
|
00be4a856f | ||
|
|
606aec4ec1 | ||
|
|
7f0f211333 | ||
|
|
42f761d44d | ||
|
|
577b5b108f | ||
|
|
4d39b32cf6 | ||
|
|
8279ed31d1 | ||
|
|
0185d0c730 | ||
|
|
4ac1674cc0 | ||
|
|
1c222a36ee | ||
|
|
16e05e0320 | ||
|
|
8ea64e7aba | ||
|
|
c22140103f | ||
|
|
8bd6e40ac8 | ||
|
|
2ed25c6991 | ||
|
|
d8991ec016 | ||
|
|
dc9ca1e63f | ||
|
|
7bb3203dfb | ||
|
|
8ebe9548f7 | ||
|
|
f90f20d3a8 | ||
|
|
1437e3b323 | ||
|
|
d44171de61 | ||
|
|
62a9e413fb | ||
|
|
c12c48dea6 | ||
|
|
7dd81525e4 | ||
|
|
ca36038bbd | ||
|
|
ca2f674696 | ||
|
|
8acf9b817f | ||
|
|
2dc1fbde96 | ||
|
|
919651a2b3 | ||
|
|
19b55a574f | ||
|
|
a6ab7de475 | ||
|
|
2ff229e9d9 | ||
|
|
18def7c624 | ||
|
|
59a731df88 | ||
|
|
6186356496 | ||
|
|
045ee091a7 | ||
|
|
a69d985139 | ||
|
|
c13641dd1d | ||
|
|
f0fc5d6598 | ||
|
|
2348039c16 | ||
|
|
7f8d34e8a0 | ||
|
|
205036b658 | ||
|
|
9519896d04 | ||
|
|
aa83b63617 | ||
|
|
3e89a372b3 | ||
|
|
d464695b66 | ||
|
|
657532f7e5 | ||
|
|
3f69308603 | ||
|
|
486160fc57 | ||
|
|
3939e0760f | ||
|
|
16624a9596 | ||
|
|
58e075e6ff | ||
|
|
ef081714d7 | ||
|
|
96802efa45 | ||
|
|
0a95f3198b | ||
|
|
cb44758036 | ||
|
|
1682c321d3 | ||
|
|
eeba8a5de7 | ||
|
|
2ea0f58e03 | ||
|
|
05235473c1 | ||
|
|
f0c083f4e6 | ||
|
|
6997c9a5c0 | ||
|
|
eebfa23509 | ||
|
|
59fe8a021f | ||
|
|
16672d9b89 |
6
.github/workflows/nightly.yml
vendored
6
.github/workflows/nightly.yml
vendored
@@ -15,13 +15,9 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
# build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/amd64, darwin/arm64
|
||||
goos: [linux, windows, darwin]
|
||||
goos: [linux, windows]
|
||||
goarch: ["386", amd64, arm, arm64]
|
||||
exclude:
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: "386"
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
- goos: windows
|
||||
|
||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,14 +1,3 @@
|
||||
data/SetuTime/cache
|
||||
data/control
|
||||
data/SetuTime/search
|
||||
data/manager
|
||||
data/acgimage
|
||||
data/saucenao
|
||||
data/fortune
|
||||
data/hs
|
||||
data/nsetu
|
||||
data/nwife
|
||||
data/sleep
|
||||
plugins/*.so
|
||||
plugins/*.dll
|
||||
.idea/
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "data"]
|
||||
path = data
|
||||
url = https://github.com/FloatTech/zbpdata
|
||||
@@ -1,6 +1,6 @@
|
||||
linters-settings:
|
||||
errcheck:
|
||||
ignore: fmt:.*,io/ioutil:^Read.*
|
||||
ignore: fmt:.*
|
||||
ignoretests: true
|
||||
|
||||
goimports:
|
||||
@@ -64,6 +64,8 @@ run:
|
||||
deadline: 5m
|
||||
issues-exit-code: 1
|
||||
tests: false
|
||||
skip-dirs:
|
||||
- order
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
|
||||
@@ -11,7 +11,6 @@ builds:
|
||||
- GO111MODULE=on
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
@@ -20,11 +19,6 @@ builds:
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
flags:
|
||||
- -trimpath
|
||||
|
||||
254
README.md
254
README.md
@@ -28,20 +28,25 @@
|
||||
> 如果您不知道什么是 [OneBot](https://github.com/howmanybots/onebot) 或不希望运行多个程序,还可以直接前往 [gocqzbp](https://github.com/FloatTech/gocqzbp) 的 [Release](https://github.com/FloatTech/gocqzbp/releases) 页面下载单一可执行文件或前往 [Packages](https://github.com/FloatTech/gocqzbp/pkgs/container/gocqzbp) 页面使用`docker`,运行后按提示登录即可。
|
||||
|
||||
## 命令行参数
|
||||
> `[]`代表是可选参数
|
||||
```bash
|
||||
zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
|
||||
zerobot [-h] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [-g 监听地址:端口] [qq1 qq2 qq3 ...] [&]
|
||||
```
|
||||
- **-h**: 显示帮助
|
||||
- **-t token**: 设置`AccessToken`,默认为空
|
||||
- **-u url**: 设置`Url`,默认为`ws://127.0.0.1:6700`
|
||||
- **-n nickname**: 设置默认昵称,默认为`椛椛`
|
||||
- **-p prefix**: 设置命令前缀,默认为`/`
|
||||
- **-d|w**: 开启 debug | warning 级别及以上日志输出
|
||||
- **-g 监听地址:端口**: 在 http://监听地址:端口 上开启 [webgui](https://github.com/FloatTech/bot-manager)
|
||||
- **qqs**: superusers 的 qq 号
|
||||
- **&**: 驻留在后台,必须放在最后,仅`Linux`下有效
|
||||
|
||||
## 功能
|
||||
> 在编译时,以下功能除插件控制外,均可通过注释`main.go`中的相应`import`而物理禁用,减小插件体积。
|
||||
> 通过插件控制,还可动态管理某个功能在某个群的打开/关闭。
|
||||
- **web管理** `import _ "github.com/FloatTech/ZeroBot-Plugin/control/web"`
|
||||
> 插件的优先级为`import`的先后顺序
|
||||
- **web管理** `import _ "github.com/FloatTech/zbputils/control/web"`
|
||||
- 开启后可执行文件大约增加 5M ,默认注释不开启。如需开启请自行编辑`main.go`取消注释
|
||||
- 需要配合 [webgui](https://github.com/FloatTech/bot-manager) 使用
|
||||
- **动态加载插件** `import _ github.com/FloatTech/ZeroBot-Plugin-Dynamic/dyloader`
|
||||
@@ -52,27 +57,83 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
|
||||
- [x] /全局启用 xxx
|
||||
- [x] /全局禁用 xxx
|
||||
- [x] /还原 xxx (在发送的群/用户还原xxx的开启状态到初始状态)
|
||||
- 注:当全局未配置或与默认相同时,状态取决于单独配置,后备为默认配置;当全局与默认不同时,状态取决于全局配置,单独配置失效。
|
||||
- [x] /禁止 service qq1 qq2... (禁止 qqs 使用服务 service)
|
||||
- [x] /允许 service qq1 qq2... (重新允许 qqs 使用服务 service)
|
||||
- [x] /封禁 qq1 qq2... (禁止 qqs 使用全部服务)
|
||||
- [x] /解封 qq1 qq2... (允许 qqs 使用全部服务)
|
||||
- [x] /用法 xxx
|
||||
- [x] /服务列表
|
||||
- [x] /服务详情
|
||||
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
|
||||
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat"`
|
||||
- **定时指令触发器** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/job"`
|
||||
- [x] 记录以"完全匹配关键词"触发的(代表我执行的)指令
|
||||
- [x] 取消以"完全匹配关键词"触发的(代表我执行的)指令
|
||||
- [x] 记录在"cron"触发的指令
|
||||
- [x] 取消在"cron"触发的指令
|
||||
- [x] 查看所有触发指令
|
||||
- [x] 查看在"cron"触发的指令
|
||||
- [x] 查看以"完全匹配关键词"触发的(代表我执行的)指令
|
||||
- [x] 注入指令结果:任意指令
|
||||
- [x] 执行指令:任意指令
|
||||
- 注:任意指令可以使用形如`?::参数1提示语::1!`,`?::参数2提示语::2!`,`?::?可选参数3提示语,不回答将填入空值::3!`,`!::从url获取的参数::4!`,`!::?可选的从url获取的参数,出错将填入空值::5!`的未定参数,在注入时一一匹配
|
||||
- 一些示例
|
||||
> 每日9:30推送摸鱼人日历
|
||||
```
|
||||
记录在"30 9 * * *"触发的指令
|
||||
run[CQ:image,file=https://api.vvhan.com/api/moyu]
|
||||
```
|
||||
> 每日12:00以1/2概率执行coser指令
|
||||
```python
|
||||
记录在"0 12 * * *"触发的指令
|
||||
注入指令结果:>runcoderaw py
|
||||
from random import random
|
||||
if random() > 0.5: print('coser')
|
||||
else: print('今天没有coser哦~')
|
||||
```
|
||||
> 每日15:00询问设置定时者否想看coser
|
||||
```python
|
||||
记录在"0 15 * * *"触发的指令
|
||||
注入指令结果:>runcoderaw py
|
||||
if '?::想看coser吗?::1!' == '想': print('coser')
|
||||
else: print('好吧')
|
||||
```
|
||||
> 自行编写简易的选择困难症助手小插件
|
||||
```python
|
||||
记录以"简易的选择困难症助手"触发的指令
|
||||
执行指令:>runcoderaw py
|
||||
from random import random
|
||||
if random() > 0.5: print('您最终会选?::请输入您的选择1::1!')
|
||||
else: print('您最终会选?::请输入您的选择2::2!')
|
||||
简易的选择困难症助手
|
||||
```
|
||||
> 自行编写随机b站404页趣图插件
|
||||
```python
|
||||
记录以"随机b站404页趣图"触发的代表我执行的指令
|
||||
注入指令结果:>runcoderaw py
|
||||
import json
|
||||
j = json.loads(r'''!::https://api.iyk0.com/bili_chart::1!''')
|
||||
print("run[CQ:image,file="+j["img"]+"]")
|
||||
随机b站404页趣图
|
||||
```
|
||||

|
||||
|
||||
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat"`
|
||||
- [x] [BOT名字]
|
||||
- [x] [戳一戳BOT]
|
||||
- [x] 空调开
|
||||
- [x] 空调关
|
||||
- [x] 群温度
|
||||
- [x] 设置温度[正整数]
|
||||
- [x] @Bot mua|啾咪|摸|上你|傻|裸|贴|老婆|抱|亲|一下|咬|操|123|进去|调教|搓|让|捏|挤|略|呐|原味|胖次|内裤|内衣|衣服|ghs|批|憨批|kkp|咕|骚|喜欢|suki|好き|看|不能|砸了|透|口我|草我|自慰|onani|オナニー|炸了|色图|涩图|告白|对不起|回来|吻|软|壁咚|掰开|女友|是|喵|嗷呜|叫|拜|佬|awsl|臭|香|腿|张开|脚|脸|头发|手|pr|舔|小穴|腰|诶嘿嘿|可爱|扭蛋|鼻|眼|色气|推|床|举|手冲|饿|变|敲|爬|怕|冲|射|不穿|迫害|猫粮|揪尾巴|薄荷|早|晚安|揉|榨|掐|胸|奶子|欧派|嫩|蹭|牵手|握手|拍照|w|睡不着|欧尼酱|哥|爱你|过来|自闭|打不过|么么哒|很懂|膝枕|累了|安慰|洗澡|一起睡觉|一起|多大|姐姐|糖|嗦|牛子|🐂子|🐮子|嫌弃|紧|baka|笨蛋|插|插进来|屁股|翘|翘起来|抬|抬起|爸|傲娇|rua|咕噜咕噜|咕噜|上床|做爱|吃掉|吃|揪|种草莓|种草|掀|妹|病娇|嘻
|
||||
- **ATRI** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri"`
|
||||
- **词典匹配回复** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
|
||||
- [x] @Bot 关键词
|
||||
- **ATRI** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri"`
|
||||
- [x] 具体指令看 /用法 atri
|
||||
- 注:本插件基于 [ATRI](https://github.com/Kyomotoi/ATRI) ,为 Golang 移植版
|
||||
- **群管** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager"`
|
||||
- **群管** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager"`
|
||||
- [x] 禁言[@xxx][分钟]
|
||||
- [x] 解除禁言[@xxx]
|
||||
- [x] 我要自闭|禅定 x [分钟|小时|天]
|
||||
- [x] 我要自闭 | 禅定 x [分钟 | 小时 | 天]
|
||||
- [x] 开启全员禁言
|
||||
- [x] 解除全员禁言
|
||||
- [x] 升为管理[@xxx]
|
||||
@@ -86,151 +147,206 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
|
||||
- [x] *退群通知
|
||||
- [x] 设置欢迎语[欢迎~]
|
||||
- [x] 在[MM]月[dd]日的[hh]点[mm]分时(用[url])提醒大家[xxx]
|
||||
- [x] 在[MM]月[每周|周几]的[hh]点[mm]分时(用[url])提醒大家[xxx]
|
||||
- [x] 在[MM]月[每周 | 周几]的[hh]点[mm]分时(用[url])提醒大家[xxx]
|
||||
- [x] 取消在[MM]月[dd]日的[hh]点[mm]分的提醒
|
||||
- [x] 取消在[MM]月[每周|周几]的[hh]点[mm]分的提醒
|
||||
- [x] 取消在[MM]月[每周 | 周几]的[hh]点[mm]分的提醒
|
||||
- [x] 在"cron"时(用[url])提醒大家[xxx]
|
||||
- [x] 取消在"cron"的提醒
|
||||
- [x] 列出所有提醒
|
||||
- [x] 翻牌
|
||||
- [x] [开启|关闭]入群验证
|
||||
- [x] [开启|关闭]gist加群自动审批
|
||||
- [x] [开启 | 关闭]入群验证
|
||||
- [x] [开启 | 关闭]gist加群自动审批
|
||||
- [ ] 同意好友请求
|
||||
- [ ] 撤回[@xxx] [xxx]
|
||||
- [ ] 警告[@xxx]
|
||||
- [x] run[xxx]
|
||||
- 注:使用gist加群自动审批,请在群介绍添加以下说明,同时开启`需要回答问题并由管理员审核`:加群请在github新建一个gist,其文件名为本群群号的字符串的md5(小写),内容为一行,是当前unix时间戳(10分钟内有效)。然后请将您的用户名和gist哈希(小写)按照username/gisthash的格式填写到回答即可。
|
||||
- **GitHub仓库搜索** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_github"`
|
||||
- **GitHub仓库搜索** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/github"`
|
||||
- [x] >github [xxx]
|
||||
- [x] >github -p [xxx]
|
||||
- **在线代码运行** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_runcode"`
|
||||
- **在线代码运行** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode"`
|
||||
- [x] > runcode [language] help
|
||||
- [x] > runcode [language] [code block]
|
||||
- **点歌** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_music"`
|
||||
- [x] > runcoderaw [language] [code block]
|
||||
- **点歌** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/music"`
|
||||
- [x] 点歌[xxx]
|
||||
- [x] 网易点歌[xxx]
|
||||
- [x] 酷我点歌[xxx]
|
||||
- [x] 酷狗点歌[xxx]
|
||||
- **shindan** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan"`
|
||||
- **shindan** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/shindan"`
|
||||
- [x] 今天是什么少女[@xxx]
|
||||
- [x] 异世界转生[@xxx]
|
||||
- [x] 卖萌[@xxx]
|
||||
- [x] 抽老婆[@xxx]
|
||||
- **AIWife** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_aiwife"`
|
||||
- [x] waifu|随机waifu(从[100000个AI生成的waifu](https://www.thiswaifudoesnotexist.net/)中随机一位)
|
||||
- **gif** `import _ "github.com/tdf1939/ZeroBot-Plugin-Gif/plugin_gif"`
|
||||
- **AIWife** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife"`
|
||||
- [x] waifu | 随机waifu(从[100000个AI生成的waifu](https://www.thiswaifudoesnotexist.net/)中随机一位)
|
||||
- **gif** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif"`
|
||||
- [x] 爬[@xxx]
|
||||
- [x] 摸[@xxx]
|
||||
- [x] 搓[@xxx]
|
||||
- 注:更多指令见项目 --> https://github.com/FloatTech/ZeroBot-Plugin-Gif
|
||||
- **base16384加解密** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_b14"`
|
||||
- **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"`
|
||||
- **摸鱼** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu"`
|
||||
- [x] /启用 moyu
|
||||
- [x] /禁用 moyu
|
||||
- **摸鱼人日历** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu_calendar"`
|
||||
- [x] /启用 moyucalendar
|
||||
- [x] /禁用 moyucalendar
|
||||
- **涩图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/setutime"`
|
||||
- [x] 来份[涩图/二次元/风景/车万]
|
||||
- [x] 添加[涩图/二次元/风景/车万][P站图片ID]
|
||||
- [x] 删除[涩图/二次元/风景/车万][P站图片ID]
|
||||
- [x] > setu status
|
||||
- **本地涩图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativesetu"`
|
||||
- **本地涩图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativesetu"`
|
||||
- [x] 本地[xxx]
|
||||
- [x] 刷新本地[xxx]
|
||||
- [x] 设置本地setu绝对路径[xxx]
|
||||
- [x] 刷新所有本地setu
|
||||
- [x] 所有本地setu分类
|
||||
- 注:刷新文件夹较慢,请耐心等待刷新完成,会提示“成功”。
|
||||
- **lolicon** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_lolicon"`
|
||||
- **nsfw图片识别** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw"`
|
||||
- [x] nsfw打分[图片]
|
||||
- [x] 当图片属于非 neutral 类别时自动发送评价(默认禁用,启用输入 /启用 nsfwauto)
|
||||
- **lolicon** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon"`
|
||||
- [x] 来份萝莉
|
||||
- **搜图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao"`
|
||||
- [x] 以图搜图|搜索图片|以图识图[图片]
|
||||
- **搜图** `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`
|
||||
- **搜番** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe"`
|
||||
- [x] 搜番 | 搜索番剧[图片]
|
||||
- **百度一下** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu"`
|
||||
- [x] 百度下[xxx]
|
||||
- **随机图片与AI点评** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/acgimage`
|
||||
- [x] 随机图片(评级大于6的图将私发)
|
||||
- [x] 直接随机(无r18检测,务必小心,仅管理可用)
|
||||
- [x] 设置随机图片网址[url]
|
||||
- [x] 太涩了(撤回最近发的图)
|
||||
- [x] 评价图片(发送一张图片让bot评分)
|
||||
- **每日运势** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_fortune`
|
||||
- [x] 运势|抽签
|
||||
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师]
|
||||
- **睡眠管理** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage`
|
||||
- [x] 早安|晚安
|
||||
- **浅草寺求签** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji`
|
||||
- [x] 求签|占卜
|
||||
- **DeepDanbooru二次元图标签识别** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru`
|
||||
- [x] 鉴赏图片[图片]
|
||||
- **叔叔的AI二次元图片放大** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale"`
|
||||
- [x] 放大图片[图片]
|
||||
- **每日运势** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/fortune`
|
||||
- [x] 运势 | 抽签
|
||||
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘 东方归言录]
|
||||
- **睡眠管理** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage`
|
||||
- [x] 早安 | 晚安
|
||||
- **浅草寺求签** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji`
|
||||
- [x] 求签 | 占卜
|
||||
- [x] 解签
|
||||
- **bilibili** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili"`
|
||||
- [x] >vup info [名字|uid]
|
||||
- [x] >user info [名字|uid]
|
||||
- [x] /开启粉丝日报
|
||||
- **嘉然** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_diana"`
|
||||
- **漂流瓶** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle"`
|
||||
- [x] (在群xxx)丢漂流瓶(到频道xxx) [消息]
|
||||
- [x] (从频道xxx)捡漂流瓶
|
||||
- [x] @BOT 创建频道 xxx
|
||||
- [x] 跳入(频道)海中
|
||||
- [x] 注:不显式限制时,私聊发送可在所有群抽到,群聊发送仅可在本群抽到,默认频道为 global
|
||||
- **猜单词** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle"`
|
||||
- [x] 个人猜单词
|
||||
- [x] 团队猜单词
|
||||
- **bilibili** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili"`
|
||||
- [x] >vup info [名字 | uid]
|
||||
- [x] >user info [名字 | uid]
|
||||
- **嘉然** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana"`
|
||||
- [x] 小作文
|
||||
- [x] 发大病
|
||||
- [x] 教你一篇小作文[作文]
|
||||
- [x] [回复]查重
|
||||
- **鬼东西** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf"`
|
||||
- **鬼东西** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf"`
|
||||
- [x] 鬼东西列表
|
||||
- [x] 查询鬼东西[序号][@xxx]
|
||||
- 注:由于需要科学,默认注释。
|
||||
- **AIfalse** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false"`
|
||||
- [x] 查询计算机当前活跃度: [检查身体|自检|启动自检|系统状态]
|
||||
- **AIfalse** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false"`
|
||||
- [x] 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]
|
||||
- [x] 清理缓存 (仅适用于 gocq 且需要 bot 的运行目录和 gocq 相同)
|
||||
- [ ] 简易语音
|
||||
- [ ] 爬图合成 [@xxx]
|
||||
- **抽wife** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativewife"`
|
||||
- **抽wife** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativewife"`
|
||||
- [x] 抽wife[@xxx]
|
||||
- [x] 添加wife[名字][图片]
|
||||
- [x] 删除wife[名字]
|
||||
- [x] [让|不让]所有人均可添加wife
|
||||
- [x] [让 | 不让]所有人均可添加wife
|
||||
- 注:不同群添加后不会重叠
|
||||
- **minecraft** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft"`
|
||||
- [x] /mcstart xxx
|
||||
- [x] /mcstop xxx
|
||||
- [x] /mclist servername
|
||||
- 注:此功能实现依赖[MCSManager](https://github.com/Suwings/MCSManager)项目对服务器的管理api,mc服务器如果没有在该管理平台部署此功能无效
|
||||
- **炉石** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_hs"`
|
||||
- **炉石** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs"`
|
||||
- [x] 搜卡[xxxx]
|
||||
- [x] [卡组代码xxx]
|
||||
- 注:更多搜卡指令参数:https://hs.fbigame.com/misc/searchhelp
|
||||
- **青云客** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_qingyunke"`
|
||||
- **人工智能回复** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply"`
|
||||
- [x] @Bot 任意文本(任意一句话回复)
|
||||
- **关键字搜图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder"`
|
||||
- [x] 设置回复模式[青云客 | 小爱]
|
||||
- **关键字搜图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder"`
|
||||
- [x] 来张 [xxx]
|
||||
- **拼音首字母释义工具** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh"`
|
||||
- **拼音首字母释义工具** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nbnhhsh"`
|
||||
- [x] ?? [缩写]
|
||||
- **选择困难症帮手** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose"`
|
||||
- **选择困难症帮手** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose"`
|
||||
- [x] 选择[选择项1]还是[选项2]还是[更多选项]
|
||||
- **投胎** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn"`
|
||||
- **投胎** `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"`
|
||||
- **翻译** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation"`
|
||||
- [x] >TL 你好
|
||||
- **vtb语录** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation"`
|
||||
- **vtb语录** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation"`
|
||||
- [x] vtb语录
|
||||
- [x] 随机vtb
|
||||
- **书评** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review"`
|
||||
- [x] 更新vtb
|
||||
- **书评** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/book_review"`
|
||||
- [x] 书评[xxx]
|
||||
- [x] 随机书评
|
||||
- **coser** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_coser" `
|
||||
- **coser** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" `
|
||||
- [x] coser
|
||||
- **小说** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_novel" `
|
||||
- **小说** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/novel" `
|
||||
- [x] 小说[xxx]
|
||||
- **沙雕app插件** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_shadiao"`
|
||||
- [x] 骂他[@xxx]|骂他[qq号] (停用)
|
||||
- [x] 骂我 (停用)
|
||||
- **沙雕app插件** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao"`
|
||||
- [x] 哄我
|
||||
- [x] 渣我
|
||||
- [x] 来碗绿茶
|
||||
- [x] 发个朋友圈
|
||||
- [x] 来碗毒鸡汤
|
||||
- [x] 讲个段子
|
||||
- **笑话** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_funny"`
|
||||
- [x] 讲个笑话[@xxx]|讲个笑话[qq号]
|
||||
- **笑话** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/funny"`
|
||||
- [x] 讲个笑话[@xxx] | 讲个笑话[qq号]
|
||||
- **抽象话** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chouxianghua"`
|
||||
- [x] 抽象翻译[xxx]
|
||||
- **合成emoji** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix"`
|
||||
- [x] [emoji][emoji]
|
||||
- **绝绝子** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi"`
|
||||
- [x] 喝奶茶绝绝子 | 绝绝子吃饭
|
||||
- **藏头诗** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi"`
|
||||
- [x] 藏头诗[xxx]
|
||||
- [x] 藏尾诗[xxx]
|
||||
- **cp短打** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory"`
|
||||
- [x] 组cp[@xxx][@xxx]
|
||||
- [x] 磕cp大老师 雪乃
|
||||
- **签到得分** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/score"`
|
||||
- [x] 签到
|
||||
- [x] 获得签到背景[@xxx] | 获得签到背景
|
||||
- **骂人** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse"`
|
||||
- [x] 骂我
|
||||
- [x] 大力骂我
|
||||
- **b站推送** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_push"`
|
||||
- [x] 添加订阅[uid]
|
||||
- [x] 取消订阅[uid]
|
||||
- [x] 取消动态订阅[uid]
|
||||
- [x] 取消直播订阅[uid]
|
||||
- [x] 推送列表
|
||||
- **网易云音乐热评** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun"`
|
||||
- [x] 来份网易云热评
|
||||
- **b站视频链接解析** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_parse"`
|
||||
- [x] https://www.bilibili.com/video/BV1xx411c7BF | https://www.bilibili.com/video/av1605 | https://b23.tv/I8uzWCA | https://www.bilibili.com/video/bv1xx411c7BF
|
||||
- **煎蛋网无聊图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan"`
|
||||
- [x] 来份屌图
|
||||
- [x] 更新屌图
|
||||
- **月幕galgame图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal"`
|
||||
- [x] 随机galCG
|
||||
- [x] 随机gal表情包
|
||||
- [x] galCG[xxx]
|
||||
- [x] gal表情包[xxx]
|
||||
- [x] 更新gal
|
||||
- **城市疫情查询** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/epidemic"`
|
||||
- [x] xxx疫情
|
||||
- **TODO...**
|
||||
|
||||
## 使用方法
|
||||
@@ -285,7 +401,7 @@ GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o zerobot -trimpath
|
||||
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o zerobot.exe -trimpath
|
||||
# armv6 Linux 平台 如树莓派 zero W
|
||||
GOOS=linux GOARCH=arm GOARM=6 CGO_ENABLED=0 go build -ldflags "-s -w" -o zerobot -trimpath
|
||||
# (由于引入了github.com/logoove/sqlite,本项不再可用)mips Linux 平台 如 路由器 wndr4300
|
||||
# (由于引入了github.com/fumiama/sqlite3,本项不再可用)mips Linux 平台 如 路由器 wndr4300
|
||||
GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags "-s -w" -o zerobot -trimpath
|
||||
```
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
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()
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package control
|
||||
|
||||
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(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()
|
||||
}
|
||||
}
|
||||
}
|
||||
473
control/rule.go
473
control/rule.go
@@ -1,473 +0,0 @@
|
||||
// Package control 控制插件的启用与优先级等
|
||||
package control
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
)
|
||||
|
||||
var (
|
||||
db = &sql.Sqlite{DBPath: "data/control/plugins.db"}
|
||||
// managers 每个插件对应的管理
|
||||
managers = map[string]*Control{}
|
||||
mu = sync.RWMutex{}
|
||||
hasinit bool
|
||||
)
|
||||
|
||||
// Control is to control the plugins.
|
||||
type Control struct {
|
||||
sync.RWMutex
|
||||
service string
|
||||
options Options
|
||||
}
|
||||
|
||||
// newctrl returns Manager with settings.
|
||||
func newctrl(service string, o *Options) *Control {
|
||||
m := &Control{service: service,
|
||||
options: func() Options {
|
||||
if o == nil {
|
||||
return Options{}
|
||||
}
|
||||
return *o
|
||||
}(),
|
||||
}
|
||||
mu.Lock()
|
||||
managers[service] = m
|
||||
mu.Unlock()
|
||||
err := db.Create(service, &grpcfg{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = db.Create(service+"ban", &ban{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Enable enables a group to pass the Manager.
|
||||
// groupID == 0 (ALL) will operate on all grps.
|
||||
func (m *Control) Enable(groupID int64) {
|
||||
var c grpcfg
|
||||
m.RLock()
|
||||
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(groupID, 10))
|
||||
m.RUnlock()
|
||||
if err != nil {
|
||||
c.GroupID = groupID
|
||||
}
|
||||
c.Disable = int64(uint64(c.Disable) & 0xffffffff_fffffffe)
|
||||
m.Lock()
|
||||
err = db.Insert(m.service, &c)
|
||||
m.Unlock()
|
||||
if err != nil {
|
||||
logrus.Errorf("[control] %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Disable disables a group to pass the Manager.
|
||||
// groupID == 0 (ALL) will operate on all grps.
|
||||
func (m *Control) Disable(groupID int64) {
|
||||
var c grpcfg
|
||||
m.RLock()
|
||||
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(groupID, 10))
|
||||
m.RUnlock()
|
||||
if err != nil {
|
||||
c.GroupID = groupID
|
||||
}
|
||||
c.Disable |= 1
|
||||
m.Lock()
|
||||
err = db.Insert(m.service, &c)
|
||||
m.Unlock()
|
||||
if err != nil {
|
||||
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()
|
||||
if err == nil && gid == c.GroupID {
|
||||
logrus.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable&1)
|
||||
return c.Disable&1 == 0
|
||||
}
|
||||
}
|
||||
m.RLock()
|
||||
err = db.Find(m.service, &c, "WHERE gid = 0")
|
||||
m.RUnlock()
|
||||
if err == nil && c.GroupID == 0 {
|
||||
logrus.Debugf("[control] plugin %s of all : %d", m.service, c.Disable&1)
|
||||
return c.Disable&1 == 0
|
||||
}
|
||||
return !m.options.DisableOnDefault
|
||||
}
|
||||
|
||||
// Ban 禁止某人在某群使用本插件
|
||||
func (m *Control) Ban(uid, gid int64) {
|
||||
var err error
|
||||
var digest [16]byte
|
||||
logrus.Debugln("[control] Ban recv gid =", gid, "uid =", uid)
|
||||
if gid != 0 { // 特定群
|
||||
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
|
||||
m.RLock()
|
||||
err = db.Insert(m.service+"ban", &ban{ID: int64(binary.LittleEndian.Uint64(digest[:8])), UserID: uid, GroupID: gid})
|
||||
m.RUnlock()
|
||||
if err == nil {
|
||||
logrus.Debugf("[control] plugin %s is banned in grp %d for usr %d.", m.service, gid, uid)
|
||||
return
|
||||
}
|
||||
}
|
||||
// 所有群
|
||||
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
|
||||
m.RLock()
|
||||
err = db.Insert(m.service+"ban", &ban{ID: int64(binary.LittleEndian.Uint64(digest[:8])), UserID: uid, GroupID: 0})
|
||||
m.RUnlock()
|
||||
if err == nil {
|
||||
logrus.Debugf("[control] plugin %s is banned in all grp for usr %d.", m.service, uid)
|
||||
}
|
||||
}
|
||||
|
||||
// Permit 允许某人在某群使用本插件
|
||||
func (m *Control) Permit(uid, gid int64) {
|
||||
var digest [16]byte
|
||||
logrus.Debugln("[control] Permit recv gid =", gid, "uid =", uid)
|
||||
if gid != 0 { // 特定群
|
||||
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
|
||||
m.RLock()
|
||||
_ = db.Del(m.service+"ban", "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
|
||||
m.RUnlock()
|
||||
logrus.Debugf("[control] plugin %s is permitted in grp %d for usr %d.", m.service, gid, uid)
|
||||
return
|
||||
}
|
||||
// 所有群
|
||||
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
|
||||
m.RLock()
|
||||
_ = db.Del(m.service+"ban", "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
|
||||
m.RUnlock()
|
||||
logrus.Debugf("[control] plugin %s is permitted in all grp for usr %d.", m.service, uid)
|
||||
}
|
||||
|
||||
// IsBannedIn 某人是否在某群被 ban
|
||||
func (m *Control) IsBannedIn(uid, gid int64) bool {
|
||||
var b ban
|
||||
var err error
|
||||
var digest [16]byte
|
||||
logrus.Debugln("[control] IsBannedIn recv gid =", gid, "uid =", uid)
|
||||
if gid != 0 {
|
||||
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
|
||||
m.RLock()
|
||||
err = db.Find(m.service+"ban", &b, "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
|
||||
m.RUnlock()
|
||||
if err == nil && gid == b.GroupID && uid == b.UserID {
|
||||
logrus.Debugf("[control] plugin %s is banned in grp %d for usr %d.", m.service, b.GroupID, b.UserID)
|
||||
return true
|
||||
}
|
||||
}
|
||||
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
|
||||
m.RLock()
|
||||
err = db.Find(m.service+"ban", &b, "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
|
||||
m.RUnlock()
|
||||
if err == nil && b.GroupID == 0 && uid == b.UserID {
|
||||
logrus.Debugf("[control] plugin %s is banned in all grp for usr %d.", m.service, b.UserID)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetData 获取某个群的 63 字节配置信息
|
||||
func (m *Control) GetData(gid int64) int64 {
|
||||
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()
|
||||
if err == nil && gid == c.GroupID {
|
||||
logrus.Debugf("[control] plugin %s of grp %d : %x", m.service, c.GroupID, c.Disable>>1)
|
||||
return c.Disable >> 1
|
||||
}
|
||||
}
|
||||
m.RLock()
|
||||
err = db.Find(m.service, &c, "WHERE gid = 0")
|
||||
m.RUnlock()
|
||||
if err == nil && c.GroupID == 0 {
|
||||
logrus.Debugf("[control] plugin %s of all : %x", m.service, c.Disable>>1)
|
||||
return c.Disable >> 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// SetData 为某个群设置低 63 位配置数据
|
||||
func (m *Control) SetData(groupID int64, data int64) error {
|
||||
var c grpcfg
|
||||
m.RLock()
|
||||
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(groupID, 10))
|
||||
m.RUnlock()
|
||||
if err != nil {
|
||||
c.GroupID = groupID
|
||||
if m.options.DisableOnDefault {
|
||||
c.Disable = 1
|
||||
}
|
||||
}
|
||||
c.Disable |= data << 1
|
||||
logrus.Debugf("[control] set plugin %s of all : %x", m.service, data)
|
||||
m.Lock()
|
||||
err = db.Insert(m.service, &c)
|
||||
m.Unlock()
|
||||
if err != nil {
|
||||
logrus.Errorf("[control] %v", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Handler 返回 预处理器
|
||||
func (m *Control) Handler(ctx *zero.Ctx) bool {
|
||||
ctx.State["manager"] = m
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
// 个人用户
|
||||
return m.IsEnabledIn(-ctx.Event.UserID)
|
||||
}
|
||||
logrus.Debugln("[control] handler get gid =", grp)
|
||||
return m.IsEnabledIn(grp) && !m.IsBannedIn(ctx.Event.UserID, grp)
|
||||
}
|
||||
|
||||
// Lookup returns a Manager by the service name, if
|
||||
// not exist, it will return nil.
|
||||
func Lookup(service string) (*Control, bool) {
|
||||
mu.RLock()
|
||||
m, ok := managers[service]
|
||||
mu.RUnlock()
|
||||
return m, ok
|
||||
}
|
||||
|
||||
// ForEach iterates through managers.
|
||||
func ForEach(iterator func(key string, manager *Control) bool) {
|
||||
mu.RLock()
|
||||
m := copyMap(managers)
|
||||
mu.RUnlock()
|
||||
for k, v := range m {
|
||||
if !iterator(k, v) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func copyMap(m map[string]*Control) map[string]*Control {
|
||||
ret := make(map[string]*Control, len(m))
|
||||
for k, v := range m {
|
||||
ret[k] = v
|
||||
}
|
||||
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()
|
||||
if !hasinit {
|
||||
err := os.MkdirAll("data/control", 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
hasinit = true
|
||||
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("没有找到指定服务!"))
|
||||
return
|
||||
}
|
||||
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{"还原", "reset"}, userOrGrpAdmin).Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
return
|
||||
}
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
// 个人用户
|
||||
grp = -ctx.Event.UserID
|
||||
}
|
||||
service.Reset(grp)
|
||||
ctx.SendChain(message.Text("已还原服务的默认启用状态: " + model.Args))
|
||||
})
|
||||
|
||||
zero.OnCommandGroup([]string{
|
||||
"禁止", "ban", "允许", "permit",
|
||||
"全局禁止", "banall", "全局允许", "permitall",
|
||||
}, zero.OnlyGroup, zero.AdminPermission).Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
args := strings.Split(model.Args, " ")
|
||||
if len(args) >= 2 {
|
||||
service, ok := Lookup(args[0])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
return
|
||||
}
|
||||
grp := ctx.Event.GroupID
|
||||
if strings.Contains(model.Command, "全局") || strings.Contains(model.Command, "all") {
|
||||
grp = 0
|
||||
}
|
||||
msg := "**" + args[0] + "报告**"
|
||||
if strings.Contains(model.Command, "允许") || strings.Contains(model.Command, "permit") {
|
||||
for _, usr := range args[1:] {
|
||||
uid, err := strconv.ParseInt(usr, 10, 64)
|
||||
if err == nil {
|
||||
service.Permit(uid, grp)
|
||||
msg += "\n+ 已允许" + usr
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, usr := range args[1:] {
|
||||
uid, err := strconv.ParseInt(usr, 10, 64)
|
||||
if err == nil {
|
||||
service.Ban(uid, grp)
|
||||
msg += "\n- 已禁止" + usr
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.SendChain(message.Text(msg))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("参数错误!"))
|
||||
})
|
||||
|
||||
zero.OnCommandGroup([]string{"用法", "usage"}, userOrGrpAdmin).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
return
|
||||
}
|
||||
if service.options.Help != "" {
|
||||
ctx.SendChain(message.Text(service.options.Help))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("该服务无帮助!"))
|
||||
}
|
||||
})
|
||||
|
||||
zero.OnCommandGroup([]string{"服务列表", "service_list"}, userOrGrpAdmin).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := "--------服务列表--------\n发送\"/用法 name\"查看详情"
|
||||
i := 0
|
||||
gid := ctx.Event.GroupID
|
||||
ForEach(func(key string, manager *Control) bool {
|
||||
i++
|
||||
msg += "\n" + strconv.Itoa(i) + `: `
|
||||
if manager.IsEnabledIn(gid) {
|
||||
msg += "●" + key
|
||||
} else {
|
||||
msg += "○" + key
|
||||
}
|
||||
return true
|
||||
})
|
||||
ctx.SendChain(message.Text(msg))
|
||||
})
|
||||
|
||||
zero.OnCommandGroup([]string{"服务详情", "service_detail"}, userOrGrpAdmin, zero.OnlyGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var m message.Message
|
||||
m = append(m,
|
||||
message.CustomNode(
|
||||
zero.BotConfig.NickName[0],
|
||||
ctx.Event.SelfID,
|
||||
"---服务详情---",
|
||||
))
|
||||
i := 0
|
||||
ForEach(func(key string, manager *Control) bool {
|
||||
service, _ := Lookup(key)
|
||||
help := service.options.Help
|
||||
i++
|
||||
msg := strconv.Itoa(i) + `: `
|
||||
if manager.IsEnabledIn(ctx.Event.GroupID) {
|
||||
msg += "●" + key
|
||||
} else {
|
||||
msg += "○" + key
|
||||
}
|
||||
msg += "\n" + help
|
||||
m = append(m,
|
||||
message.CustomNode(
|
||||
zero.BotConfig.NickName[0],
|
||||
ctx.Event.SelfID,
|
||||
msg,
|
||||
))
|
||||
return true
|
||||
})
|
||||
|
||||
if id := ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
m,
|
||||
).Get("message_id").Int(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
mu.Unlock()
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package control
|
||||
|
||||
// grpcfg holds the group config for the Manager.
|
||||
type grpcfg struct {
|
||||
GroupID int64 `db:"gid"` // GroupID 群号
|
||||
Disable int64 `db:"disable"` // Disable 默认启用该插件
|
||||
}
|
||||
|
||||
type ban struct {
|
||||
ID int64 `db:"id"`
|
||||
UserID int64 `db:"uid"`
|
||||
GroupID int64 `db:"gid"`
|
||||
}
|
||||
|
||||
// Options holds the optional parameters for the Manager.
|
||||
type Options struct {
|
||||
DisableOnDefault bool
|
||||
Help string // 帮助文本信息
|
||||
}
|
||||
@@ -1,561 +0,0 @@
|
||||
// Package webctrl 包含 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.Stdout)
|
||||
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
|
||||
}
|
||||
1
data
Submodule
1
data
Submodule
Submodule data added at e084d72e9d
Binary file not shown.
1607
data/Chat/kimoi.json
1607
data/Chat/kimoi.json
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,906 +0,0 @@
|
||||
[
|
||||
{
|
||||
"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.
Binary file not shown.
60
go.mod
60
go.mod
@@ -1,29 +1,55 @@
|
||||
module github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
go 1.16
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/FloatTech/AnimeAPI v1.1.11
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4
|
||||
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed
|
||||
github.com/antchfx/htmlquery v1.2.3
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220311024222-ed58ddf6834e
|
||||
github.com/FloatTech/sqlite v0.2.1
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220311032316-df8ab8b3c180
|
||||
github.com/antchfx/htmlquery v1.2.4
|
||||
github.com/corona10/goimagehash v1.0.3
|
||||
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/go-registry v0.0.2
|
||||
github.com/fumiama/gofastTEA v0.0.6
|
||||
github.com/fumiama/go-base16384 v1.3.0
|
||||
github.com/fumiama/go-registry v0.1.1
|
||||
github.com/fumiama/gofastTEA v0.0.9
|
||||
github.com/fumiama/gotracemoe v0.0.3
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/fumiama/sqlite3 v1.14.6
|
||||
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 v3.21.11
|
||||
github.com/pkumza/numcn v1.0.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
|
||||
github.com/tidwall/gjson v1.12.1
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.1
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
golang.org/x/text v0.3.6
|
||||
github.com/tidwall/gjson v1.14.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220307142419-a1b34e6da007
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
|
||||
github.com/antchfx/xpath v1.2.0 // indirect
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.12 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
modernc.org/libc v1.14.6 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.0.5 // indirect
|
||||
)
|
||||
|
||||
293
go.sum
293
go.sum
@@ -1,25 +1,22 @@
|
||||
github.com/FloatTech/AnimeAPI v1.1.9/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
|
||||
github.com/FloatTech/AnimeAPI v1.1.11 h1:uuV4v5qweh0mI0E2KMiG5XGt0pKboV/EFAlIfSJxIi8=
|
||||
github.com/FloatTech/AnimeAPI v1.1.11/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/FloatTech/AnimeAPI v1.3.1-0.20220311024222-ed58ddf6834e h1:PKm/g1M7rYu6YMOV5k8xCOkgXTKF2Tk9v2exeYyCe+0=
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220311024222-ed58ddf6834e/go.mod h1:JNF2O/RdbrsDIccSQ29a4g1pQRrZsN0Jh3ggFZYzZuY=
|
||||
github.com/FloatTech/bot-manager v1.0.0/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
|
||||
github.com/FloatTech/sqlite v0.2.1 h1:9t6Me48XJJCIoPy4nLRvcdhcVKfT0c2lilp7SEKROG8=
|
||||
github.com/FloatTech/sqlite v0.2.1/go.mod h1:6NfHRzqOo9RWeMJEoAQVuo51Omd5LFNxCNQhMF02/9U=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220307143543-1139754cacdf/go.mod h1:u+PiX1khNvtAgfRVTVP4hkA2oUnn5q5dTZSk1Cgp0Gw=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220311032316-df8ab8b3c180 h1:8tE9DYu0+YMk3oKeO0ffl80818ZrPM9afbRgb2ag0tQ=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220311032316-df8ab8b3c180/go.mod h1:u+PiX1khNvtAgfRVTVP4hkA2oUnn5q5dTZSk1Cgp0Gw=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc/go.mod h1:OMmITAib6POA37xCichWM0aRnoVpSMZO1rB/G01wrr0=
|
||||
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=
|
||||
github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||
github.com/antchfx/htmlquery v1.2.4 h1:qLteofCMe/KGovBI6SQgmou2QNyedFUW+pE+BpeZ494=
|
||||
github.com/antchfx/htmlquery v1.2.4/go.mod h1:2xO6iu3EVWs7R2JYqBbp8YzG50gj/ofqs5/0VZoDZLc=
|
||||
github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
|
||||
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
|
||||
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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=
|
||||
@@ -27,7 +24,6 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6RO
|
||||
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=
|
||||
@@ -38,52 +34,50 @@ github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzP
|
||||
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/go-registry v0.0.2 h1:2EoZwZpqI7YhkQ1FnuAPvALYPpvUtbsCqk879+r7ehs=
|
||||
github.com/fumiama/go-registry v0.0.2/go.mod h1:QkcmmHuw1y6y/w7/HiH1c9yjBw5Zt+6EER6YJKl9xh8=
|
||||
github.com/fumiama/gofastTEA v0.0.6 h1:Yni3MXDbJVa/c4CecgdZDgCJK+fLdvGph+OBqY2mtiI=
|
||||
github.com/fumiama/gofastTEA v0.0.6/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
|
||||
github.com/fumiama/go-base16384 v1.3.0 h1:J5Xtwh/3alGJt/z/0IFralo5UQA89iFWQqbxj5ZQZi8=
|
||||
github.com/fumiama/go-base16384 v1.3.0/go.mod h1:RGA715p34BiLoZvPRtaxuo2q25Kq9jFsgUsJb8dwy14=
|
||||
github.com/fumiama/go-registry v0.1.1 h1:cmCRizjXHFW2ApwUHCXi8wKLJ6Gtt4GrShJlamGPbVI=
|
||||
github.com/fumiama/go-registry v0.1.1/go.mod h1:iJT3DVgH7KXpJZs6waXEjnWtJPUBBGhF+ByJIMRfngk=
|
||||
github.com/fumiama/gofastTEA v0.0.9 h1:adaWz+014vMShnLUNWIHLBs0Yv6JNUohcaXZNtct5J0=
|
||||
github.com/fumiama/gofastTEA v0.0.9/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
|
||||
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/fumiama/sqlite3 v1.14.6 h1:+e+iygyiDXQJVi7xeXIviBvR7hAc5y20WA9hRwfKn10=
|
||||
github.com/fumiama/sqlite3 v1.14.6/go.mod h1:Xx9a2/OtHuy9pBjow0N+bE/RhNeZ7zZz5xh25vqbA5A=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/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/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
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/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
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/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/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=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
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=
|
||||
@@ -91,30 +85,31 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
|
||||
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/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
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/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
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-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
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=
|
||||
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
|
||||
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
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/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
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/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
@@ -122,19 +117,20 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
|
||||
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/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkumza/numcn v1.0.0 h1:ZT5cf9IJkUZgRgEtCiNNykk0RwsrKXSTsvDHOwUTzgE=
|
||||
github.com/pkumza/numcn v1.0.0/go.mod h1:QSeH+al9dWCd8di5HZM/ZqHqhZmUKfph572e9Ev/ETc=
|
||||
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
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/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 v3.21.11 h1:d5tOAP5+bmJ8Hf2+4bxOSkQ/64+sjEbjU9nSW9nJgG0=
|
||||
github.com/shirou/gopsutil/v3 v3.21.11/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
|
||||
github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
|
||||
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=
|
||||
@@ -143,38 +139,30 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/go.mod h1:bkxKi7un9gCDvUUZAiIJF6k90pyj8rmxiXLJkiHcsMY=
|
||||
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/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
|
||||
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w=
|
||||
github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
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 v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||
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/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/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220307142419-a1b34e6da007 h1:yHCJCj8u3Y0JDgTlrUqPHxIO6KU0WK9+voECZ2im5lo=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220307142419-a1b34e6da007/go.mod h1:NwXIp7PgjV+kUALMXJ4v4/3QcsRSOodtjhLekuPXFog=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
@@ -182,13 +170,13 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
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/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867 h1:TcHcE0vrmgzNH1v3ppjcMGbhG5+9fMuvOmUYwNEF4q4=
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
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=
|
||||
@@ -198,12 +186,13 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
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/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/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
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=
|
||||
@@ -217,19 +206,28 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c h1:taxlMj0D/1sOAuv/CbSD+MMDof2vbyPTqz5FNYKpXt8=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
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=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -238,38 +236,124 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N
|
||||
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/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/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
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.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
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=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.34.0 h1:dFhZc/HKR3qp92sYQxKRRaDMz+sr1bwcFD+m7LSCrAs=
|
||||
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
|
||||
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
|
||||
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
|
||||
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/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
|
||||
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
|
||||
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
|
||||
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
|
||||
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
|
||||
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
|
||||
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
|
||||
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
|
||||
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
|
||||
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
|
||||
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
|
||||
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
|
||||
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
|
||||
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
|
||||
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
|
||||
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
|
||||
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
|
||||
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
|
||||
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
|
||||
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
|
||||
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
|
||||
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
|
||||
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
|
||||
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
|
||||
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
|
||||
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
|
||||
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
|
||||
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
|
||||
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
|
||||
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
|
||||
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
|
||||
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
|
||||
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
|
||||
modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4=
|
||||
modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
|
||||
modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8=
|
||||
modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I=
|
||||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
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=
|
||||
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
|
||||
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
|
||||
modernc.org/libc v1.11.3 h1:q//spBhqp23lC/if8/o8hlyET57P8mCZqrqftzT2WmY=
|
||||
modernc.org/libc v1.11.3/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
|
||||
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
|
||||
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
|
||||
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
|
||||
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
|
||||
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
|
||||
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
|
||||
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
|
||||
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
|
||||
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
|
||||
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
|
||||
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
|
||||
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
|
||||
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
|
||||
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
|
||||
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
|
||||
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
|
||||
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
|
||||
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
|
||||
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
|
||||
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
|
||||
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
|
||||
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
|
||||
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
|
||||
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
|
||||
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
|
||||
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
|
||||
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
|
||||
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
|
||||
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
|
||||
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
|
||||
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
|
||||
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
|
||||
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
|
||||
modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
|
||||
modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
|
||||
modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34=
|
||||
modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
|
||||
modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
|
||||
modernc.org/libc v1.14.6 h1:SSiZiE5199iYsGM9gtkDj90xqcXVwubWG8CtoYE+Mnk=
|
||||
modernc.org/libc v1.14.6/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
|
||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
@@ -278,13 +362,6 @@ modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6
|
||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
|
||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
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/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/go.mod h1:sj9T1AGBG0dm6SCVzldPOHWrif6XBpooJtbttMn1+Js=
|
||||
|
||||
45
kanban/banner.go
Normal file
45
kanban/banner.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package kanban
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fumiama/go-registry"
|
||||
)
|
||||
|
||||
var (
|
||||
info = [...]string{
|
||||
"* OneBot + ZeroBot + Golang",
|
||||
"* Version 1.3.1 - 2022-03-07 13:40:58 +0800 CST",
|
||||
"* Copyright © 2020 - 2022 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
// Banner ...
|
||||
Banner = strings.Join(info[:], "\n")
|
||||
reg = registry.NewRegReader("reilia.westeurope.cloudapp.azure.com:32664", "fumiama")
|
||||
)
|
||||
|
||||
// PrintBanner ...
|
||||
func PrintBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
"\n", Banner, "\n",
|
||||
"----------------------[ZeroBot-公告栏]----------------------",
|
||||
"\n", Kanban(), "\n",
|
||||
"============================================================\n\n",
|
||||
)
|
||||
}
|
||||
|
||||
// Kanban ...
|
||||
func Kanban() string {
|
||||
err := reg.Connect()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
defer reg.Close()
|
||||
text, err := reg.Get("ZeroBot-Plugin/kanban")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return text
|
||||
}
|
||||
6
kanban/init.go
Normal file
6
kanban/init.go
Normal file
@@ -0,0 +1,6 @@
|
||||
// Package kanban 打印版本信息
|
||||
package kanban
|
||||
|
||||
func init() {
|
||||
PrintBanner()
|
||||
}
|
||||
247
main.go
247
main.go
@@ -3,83 +3,160 @@ package main
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
|
||||
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 在最前打印 banner
|
||||
|
||||
// 插件控制
|
||||
// webctrl "github.com/FloatTech/ZeroBot-Plugin/control/web" // web 后端控制
|
||||
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
|
||||
// ----------------------插件优先级按顺序从高到低---------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------高优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv高优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv高优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv高优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
// 词库类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri" // ATRI词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat" // 基础词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_qingyunke" // 青云客
|
||||
// webctrl "github.com/FloatTech/zbputils/control/web" // web 后端控制
|
||||
|
||||
// 实用类
|
||||
_ "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_sleep_manage" // 统计睡眠时间
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation" // 翻译
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
|
||||
|
||||
// 娱乐类
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf" // 鬼东西
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin-Gif" // 制图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review" // 哀伤雪刃吧推书记录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_coser" // 三次元小姐姐
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_funny" // 笑话
|
||||
_ "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_novel" // 铅笔小说网搜索
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shadiao" // 沙雕app
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage" // 统计睡眠时间
|
||||
|
||||
// b站相关
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili" // 查询b站用户信息
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_diana" // 嘉心糖发病
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
|
||||
|
||||
// 二次元图片
|
||||
_ "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_nativesetu" // 本地涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativewife" // 本地老婆
|
||||
_ "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语录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager" // 群管
|
||||
|
||||
// 以下为内置依赖,勿动
|
||||
"github.com/fumiama/go-registry"
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^高优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^高优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^高优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------高优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------中优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv中优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv中优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv中优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/acgimage" // 随机图片与AI点评
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // 查询b站用户信息
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_parse" // b站视频链接解析
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/book_review" // 哀伤雪刃吧推书记录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi" // 藏头诗
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chouxianghua" // 说抽象话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle" // 漂流瓶
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/epidemic" // 城市疫情查询
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/fortune" // 运势
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/funny" // 笑话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif" // 制图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/job" // 定时指令触发器
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu" // 摸鱼
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu_calendar" // 摸鱼人日历
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/music" // 点歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativesetu" // 本地涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativewife" // 本地老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nbnhhsh" // 拼音首字母缩写释义工具
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/novel" // 铅笔小说网搜索
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale" // 叔叔的AI二次元图片放大
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/setutime" // 来份涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao" // 沙雕app
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe" // 搜番
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation" // 翻译
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
||||
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_push" // b站推送
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^中优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^中优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^中优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------中优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------低优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv低优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv低优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv低优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse" // 骂人
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^低优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^低优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^低优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------低优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// -----------------------以下为内置依赖,勿动------------------------ //
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"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.2.2 - 2021-12-13 21:22:45 +0800 CST",
|
||||
"* Copyright © 2020 - 2021 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
banner = strings.Join(contents, "\n")
|
||||
nicks = []string{"ATRI", "atri", "亚托莉", "アトリ"}
|
||||
token *string
|
||||
url *string
|
||||
reg = registry.NewRegReader("reilia.eastasia.azurecontainer.io:32664", "fumiama")
|
||||
adana *string
|
||||
prefix *string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -94,10 +171,13 @@ func init() {
|
||||
token = flag.String("t", "", "Set AccessToken of WSClient.")
|
||||
// 直接写死 URL 时,请更改下面第二个参数
|
||||
url = flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
|
||||
// 默认昵称
|
||||
adana = flag.String("n", "椛椛", "Set default nickname.")
|
||||
prefix = flag.String("p", "/", "Set command prefix.")
|
||||
|
||||
flag.Parse()
|
||||
if *h {
|
||||
printBanner()
|
||||
kanban.PrintBanner()
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
@@ -109,53 +189,32 @@ func init() {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
}
|
||||
|
||||
// 启用 gui
|
||||
// webctrl.InitGui(*g)
|
||||
}
|
||||
|
||||
func printBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
"\n", banner, "\n",
|
||||
"----------------------[ZeroBot-公告栏]----------------------",
|
||||
"\n", getKanban(), "\n",
|
||||
"============================================================\n",
|
||||
)
|
||||
}
|
||||
|
||||
func getKanban() string {
|
||||
err := reg.Connect()
|
||||
defer reg.Close()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
text, err := reg.Get("ZeroBot-Plugin/kanban")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
func main() {
|
||||
printBanner()
|
||||
rand.Seed(time.Now().UnixNano()) // 全局 seed,其他插件无需再 seed
|
||||
// 帮助
|
||||
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).FirstPriority().
|
||||
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(banner, "\n可发送\"/服务列表\"查看 bot 功能"))
|
||||
ctx.SendChain(message.Text(kanban.Banner, "\n可发送\"/服务列表\"查看 bot 功能"))
|
||||
})
|
||||
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).FirstPriority().
|
||||
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(getKanban()))
|
||||
ctx.SendChain(message.Text(kanban.Kanban()))
|
||||
})
|
||||
zero.RunAndBlock(
|
||||
zero.Run(
|
||||
zero.Config{
|
||||
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
|
||||
CommandPrefix: "/",
|
||||
NickName: append([]string{*adana}, nicks...),
|
||||
CommandPrefix: *prefix,
|
||||
// SuperUsers 某些功能需要主人权限,可通过以下两种方式修改
|
||||
// "12345678", "87654321":通过代码写死的方式添加主人账号
|
||||
// flag.Args():通过命令行参数的方式添加主人账号,无需修改下方任何代码
|
||||
SuperUsers: append([]string{"12345678", "87654321"}, flag.Args()...),
|
||||
// SuperUsers: []string{"12345678", "87654321"}, // 通过代码写死的方式添加主人账号
|
||||
SuperUsers: flag.Args(), // 通过命令行参数的方式添加主人账号
|
||||
Driver: []zero.Driver{driver.NewWebSocketClient(*url, *token)},
|
||||
},
|
||||
)
|
||||
process.GlobalInitMutex.Unlock()
|
||||
select {}
|
||||
}
|
||||
|
||||
64
main_win.go
64
main_win.go
@@ -4,13 +4,67 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// windows 不支持带颜色的 log,故自定义格式
|
||||
logrus.SetFormatter(&easy.Formatter{
|
||||
LogFormat: "[%lvl%] %msg%\n",
|
||||
})
|
||||
// windows 带颜色 log 自定义格式
|
||||
logrus.SetFormatter(&LogFormat{})
|
||||
}
|
||||
|
||||
const (
|
||||
colorCodePanic = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeFatal = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeError = "\x1b[31m" // color.Style{color.Red}.String()
|
||||
colorCodeWarn = "\x1b[33m" // color.Style{color.Yellow}.String()
|
||||
colorCodeInfo = "\x1b[37m" // color.Style{color.White}.String()
|
||||
colorCodeDebug = "\x1b[32m" // color.Style{color.Green}.String()
|
||||
colorCodeTrace = "\x1b[36m" // color.Style{color.Cyan}.String()
|
||||
colorReset = "\x1b[0m"
|
||||
)
|
||||
|
||||
// LogFormat specialize for zbp
|
||||
type LogFormat struct{}
|
||||
|
||||
// Format implements logrus.Formatter
|
||||
func (f LogFormat) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
buf.WriteString(getLogLevelColorCode(entry.Level))
|
||||
|
||||
buf.WriteByte('[')
|
||||
buf.WriteString(strings.ToUpper(entry.Level.String()))
|
||||
buf.WriteString("] ")
|
||||
buf.WriteString(entry.Message)
|
||||
buf.WriteString(" \n")
|
||||
|
||||
buf.WriteString(colorReset)
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// getLogLevelColorCode 获取日志等级对应色彩code
|
||||
func getLogLevelColorCode(level logrus.Level) string {
|
||||
switch level {
|
||||
case logrus.PanicLevel:
|
||||
return colorCodePanic
|
||||
case logrus.FatalLevel:
|
||||
return colorCodeFatal
|
||||
case logrus.ErrorLevel:
|
||||
return colorCodeError
|
||||
case logrus.WarnLevel:
|
||||
return colorCodeWarn
|
||||
case logrus.InfoLevel:
|
||||
return colorCodeInfo
|
||||
case logrus.DebugLevel:
|
||||
return colorCodeDebug
|
||||
case logrus.TraceLevel:
|
||||
return colorCodeTrace
|
||||
|
||||
default:
|
||||
return colorCodeInfo
|
||||
}
|
||||
}
|
||||
|
||||
173
plugin/acgimage/classify.go
Normal file
173
plugin/acgimage/classify.go
Normal file
@@ -0,0 +1,173 @@
|
||||
// Package acgimage 随机图片与AI点评
|
||||
package acgimage
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/classify"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
const (
|
||||
lolipxy = "https://sayuri.fumiama.top/dice?class=0&loli=true&r18=true"
|
||||
apihead = "https://sayuri.fumiama.top/img?path="
|
||||
apiheadv6 = "http://aikae.v6.army:62002/img?arg=get&name="
|
||||
)
|
||||
|
||||
var (
|
||||
// r18有一定保护,一般不会发出图片
|
||||
randapi = "&loli=true&r18=true"
|
||||
msgof = make(map[int64]message.MessageID)
|
||||
block = false
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("acgimage", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "随机图片与AI点评\n" +
|
||||
"- 随机图片(评级大于6的图将私发)\n" +
|
||||
"- 直接随机(无r18检测,务必小心,仅管理可用)\n" +
|
||||
"- 设置随机图片网址[url]\n" +
|
||||
"- 太涩了(撤回最近发的图)\n" +
|
||||
"- 评价图片(发送一张图片让bot评分)",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
engine.OnRegex(`^设置随机图片网址(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["regex_matched"].([]string)[1]
|
||||
if !strings.HasPrefix(url, "http") {
|
||||
ctx.SendChain(message.Text("URL非法!"))
|
||||
} else {
|
||||
randapi = url
|
||||
ctx.SendChain(message.Text("设置好啦"))
|
||||
}
|
||||
})
|
||||
// 有保护的随机图片
|
||||
engine.OnFullMatch("随机图片", zero.OnlyGroup).Limit(ctxext.LimitByUser).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
class, dhash, _, err := classify.Classify(randapi, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
err = reply(ctx, class, dhash, classify.Comments[class])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
// 直接随机图片,无r18保护,后果自负。如果出r18图可尽快通过发送"太涩了"撤回
|
||||
engine.OnFullMatch("直接随机", ctxext.UserOrGrpAdmin).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if block {
|
||||
ctx.SendChain(message.Text("请稍后再试哦"))
|
||||
} else if randapi != "" {
|
||||
block = true
|
||||
var url string
|
||||
if randapi[0] == '&' {
|
||||
url = lolipxy
|
||||
} else {
|
||||
url = randapi
|
||||
}
|
||||
setLastMsg(ctx.Event.GroupID, message.NewMessageID(
|
||||
ctx.SendGroupForwardMessage(ctx.Event.GroupID,
|
||||
message.Message{
|
||||
ctxext.FakeSenderForwardNode(ctx,
|
||||
message.Image(url).Add("cache", "0"),
|
||||
),
|
||||
}).Get("message_id").String()))
|
||||
block = false
|
||||
}
|
||||
})
|
||||
// 撤回最后的直接随机图片
|
||||
engine.OnFullMatch("太涩了", zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg, ok := msgof[ctx.Event.GroupID]
|
||||
if ok {
|
||||
ctx.DeleteMessage(msg)
|
||||
delete(msgof, ctx.Event.GroupID)
|
||||
}
|
||||
})
|
||||
// 上传一张图进行评价
|
||||
engine.OnKeywordGroup([]string{"评价图片"}, zero.OnlyGroup, ctxext.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
url := ctx.State["image_url"].([]string)[0]
|
||||
class, _, _, err := classify.Classify(url, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(classify.Comments[class]))
|
||||
})
|
||||
engine.OnRegex(`^给你点提示哦:(.*)$`, zero.OnlyPrivate).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dhash := ctx.State["regex_matched"].([]string)[1]
|
||||
if len(dhash) == 5*3 {
|
||||
var u string
|
||||
if web.IsSupportIPv6 {
|
||||
u = apiheadv6 + dhash + ".webp"
|
||||
} else {
|
||||
u = apihead + dhash
|
||||
}
|
||||
|
||||
err := pool.SendRemoteImageFromPool(dhash, u, ctxext.Send(ctx), ctxext.GetMessage(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func setLastMsg(id int64, msg message.MessageID) {
|
||||
msgof[id] = msg
|
||||
}
|
||||
|
||||
func reply(ctx *zero.Ctx, class int, dhash string, comment string) error {
|
||||
b14, err := url.QueryUnescape(dhash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var u string
|
||||
if web.IsSupportIPv6 {
|
||||
u = apiheadv6 + dhash + ".webp"
|
||||
} else {
|
||||
u = apihead + dhash
|
||||
}
|
||||
|
||||
var send ctxext.NoCtxSendMsg
|
||||
if class > 5 {
|
||||
send = ctxext.SendTo(ctx, ctx.Event.UserID)
|
||||
if dhash != "" {
|
||||
ctx.SendChain(message.Text(comment + "\n给你点提示哦:" + b14))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(comment))
|
||||
}
|
||||
} else {
|
||||
send = func(msg interface{}) int64 {
|
||||
return ctx.SendGroupForwardMessage(ctx.Event.GroupID, message.Message{
|
||||
ctxext.FakeSenderForwardNode(ctx, append(
|
||||
msg.(message.Message),
|
||||
message.Text(comment))...,
|
||||
),
|
||||
}).Get("message_id").Int()
|
||||
}
|
||||
}
|
||||
|
||||
return pool.SendRemoteImageFromPool(b14, u, send, func(i int64) zero.Message {
|
||||
if class > 5 {
|
||||
return ctxext.GetMessage(ctx)(i)
|
||||
}
|
||||
return ctxext.GetFirstMessageInForward(ctx)(i)
|
||||
})
|
||||
}
|
||||
@@ -7,21 +7,22 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("aifalse", &control.Options{
|
||||
engine := control.Register("aifalse", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIfalse\n" +
|
||||
"- 查询计算机当前活跃度: [检查身体|自检|启动自检|系统状态]",
|
||||
"- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]",
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
@@ -44,20 +45,33 @@ func init() { // 插件主体
|
||||
}
|
||||
|
||||
func cpuPercent() float64 {
|
||||
percent, _ := cpu.Percent(time.Second, false)
|
||||
percent, err := cpu.Percent(time.Second, false)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return math.Round(percent[0])
|
||||
}
|
||||
|
||||
func memPercent() float64 {
|
||||
memInfo, _ := mem.VirtualMemory()
|
||||
memInfo, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return math.Round(memInfo.UsedPercent)
|
||||
}
|
||||
|
||||
func diskPercent() string {
|
||||
parts, _ := disk.Partitions(true)
|
||||
parts, err := disk.Partitions(true)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
msg := ""
|
||||
for _, p := range parts {
|
||||
diskInfo, _ := disk.Usage(p.Mountpoint)
|
||||
diskInfo, err := disk.Usage(p.Mountpoint)
|
||||
if err != nil {
|
||||
msg += "\n - " + err.Error()
|
||||
continue
|
||||
}
|
||||
pc := uint(math.Round(diskInfo.UsedPercent))
|
||||
if pc > 0 {
|
||||
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, pc)
|
||||
156
plugin/ai_reply/ai_tts.go
Normal file
156
plugin/ai_reply/ai_tts.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/pkumza/numcn"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
"github.com/FloatTech/AnimeAPI/tts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/baidutts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/mockingbird"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const ttsServiceName = "tts"
|
||||
|
||||
var (
|
||||
t = &ttsInstances{
|
||||
m: map[string]tts.TTS{
|
||||
"百度女声": baidutts.NewBaiduTTS(0),
|
||||
"百度男声": baidutts.NewBaiduTTS(1),
|
||||
"百度度逍遥": baidutts.NewBaiduTTS(3),
|
||||
"百度度丫丫": baidutts.NewBaiduTTS(4),
|
||||
"拟声鸟阿梓": mockingbird.NewMockingBirdTTS(0),
|
||||
"拟声鸟药水哥": mockingbird.NewMockingBirdTTS(1),
|
||||
},
|
||||
l: []string{"拟声鸟阿梓", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"},
|
||||
}
|
||||
re = regexp.MustCompile(`(\-|\+)?\d+(\.\d+)?`)
|
||||
)
|
||||
|
||||
type ttsInstances struct {
|
||||
sync.RWMutex
|
||||
m map[string]tts.TTS
|
||||
l []string
|
||||
}
|
||||
|
||||
func (t *ttsInstances) List() []string {
|
||||
t.RLock()
|
||||
cl := make([]string, len(t.l))
|
||||
_ = copy(cl, t.l)
|
||||
t.RUnlock()
|
||||
return cl
|
||||
}
|
||||
|
||||
func init() {
|
||||
engine := control.Register(ttsServiceName, order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: true,
|
||||
Help: "语音回复(包括拟声鸟和百度)\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n" +
|
||||
"- 设置语音模式[拟声鸟阿梓 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n" +
|
||||
"- 设置默认语音模式[拟声鸟阿梓 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n",
|
||||
})
|
||||
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := ctx.ExtractPlainText()
|
||||
r := aireply.NewAIReply(getReplyMode(ctx))
|
||||
tts := t.new(t.getSoundMode(ctx))
|
||||
ctx.SendChain(message.Record(tts.Speak(ctx.Event.UserID, func() string {
|
||||
reply := r.TalkPlain(msg, zero.BotConfig.NickName[0])
|
||||
reply = re.ReplaceAllStringFunc(reply, func(s string) string {
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
log.Errorln("[tts]:", err)
|
||||
return s
|
||||
}
|
||||
return numcn.EncodeFromFloat64(f)
|
||||
})
|
||||
log.Println("[tts]:", reply)
|
||||
return reply
|
||||
})))
|
||||
})
|
||||
engine.OnRegex(`^设置语音模式(.*)$`, ctxext.FirstValueInList(t)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
err := t.setSoundMode(ctx, param)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前模式为", param))
|
||||
})
|
||||
engine.OnRegex(`^设置默认语音模式(.*)$`, ctxext.FirstValueInList(t)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
t.setDefaultSoundMode(param)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,默认模式为", param))
|
||||
})
|
||||
}
|
||||
|
||||
// new 语音简单工厂
|
||||
func (t *ttsInstances) new(name string) tts.TTS {
|
||||
return t.m[name]
|
||||
}
|
||||
|
||||
func (t *ttsInstances) setSoundMode(ctx *zero.Ctx, name string) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
var index int64
|
||||
t.RLock()
|
||||
for i, s := range t.l {
|
||||
if s == name {
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
t.RUnlock()
|
||||
m, ok := control.Lookup(ttsServiceName)
|
||||
if !ok {
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
return m.SetData(gid, index)
|
||||
}
|
||||
|
||||
func (t *ttsInstances) getSoundMode(ctx *zero.Ctx) (name string) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := control.Lookup(ttsServiceName)
|
||||
if ok {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
index := m.GetData(gid)
|
||||
if int(index) < len(t.l) {
|
||||
return t.l[index]
|
||||
}
|
||||
}
|
||||
return "拟声鸟阿梓"
|
||||
}
|
||||
|
||||
func (t *ttsInstances) setDefaultSoundMode(name string) {
|
||||
var index int
|
||||
t.RLock()
|
||||
for _, s := range t.l {
|
||||
if s == name {
|
||||
break
|
||||
}
|
||||
index++
|
||||
}
|
||||
t.RUnlock()
|
||||
t.Lock()
|
||||
t.l[0], t.l[index] = t.l[index], t.l[0]
|
||||
t.Unlock()
|
||||
}
|
||||
92
plugin/ai_reply/main.go
Normal file
92
plugin/ai_reply/main.go
Normal file
@@ -0,0 +1,92 @@
|
||||
// Package aireply AI 回复
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
replyServiceName = "aireply"
|
||||
)
|
||||
|
||||
var replyModes = [...]string{"青云客", "小爱"}
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register(replyServiceName, order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "人工智能回复\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客 | 小爱]\n- ",
|
||||
})
|
||||
// 回复 @和包括名字
|
||||
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
aireply := aireply.NewAIReply(getReplyMode(ctx))
|
||||
reply := message.ParseMessageFromString(aireply.Talk(ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
|
||||
// 回复
|
||||
time.Sleep(time.Second * 1)
|
||||
if zero.OnlyPublic(ctx) {
|
||||
reply = append(reply, message.Reply(ctx.Event.MessageID))
|
||||
ctx.Send(reply)
|
||||
return
|
||||
}
|
||||
ctx.Send(reply)
|
||||
})
|
||||
engine.OnPrefix(`设置回复模式`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["args"].(string)
|
||||
err := setReplyMode(ctx, param)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功"))
|
||||
})
|
||||
}
|
||||
|
||||
func setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
var ok bool
|
||||
var index int64
|
||||
for i, s := range replyModes {
|
||||
if s == name {
|
||||
ok = true
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return errors.New("no such mode")
|
||||
}
|
||||
m, ok := control.Lookup(replyServiceName)
|
||||
if !ok {
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
return m.SetData(gid, index)
|
||||
}
|
||||
|
||||
func getReplyMode(ctx *zero.Ctx) (name string) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := control.Lookup(replyServiceName)
|
||||
if ok {
|
||||
index := m.GetData(gid)
|
||||
if int(index) < len(replyModes) {
|
||||
return replyModes[index]
|
||||
}
|
||||
}
|
||||
return "青云客"
|
||||
}
|
||||
@@ -4,12 +4,13 @@ package aiwife
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -17,14 +18,11 @@ const (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// TODO: 1.17 特性暂不增加
|
||||
// rand.Seed(time.Now().UnixMicro())
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
control.Register("aiwife", &control.Options{
|
||||
control.Register("aiwife", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIWife\n" +
|
||||
"- waifu|随机waifu",
|
||||
}).OnFullMatchGroup([]string{"waifu", "随机waifu"}).SetPriority(10).SetBlock(true).
|
||||
"- waifu | 随机waifu",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatchGroup([]string{"waifu", "随机waifu"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
miku := rand.Intn(100000) + 1
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Image(fmt.Sprintf(bed, miku)))
|
||||
@@ -12,30 +12,30 @@ import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
// 服务名
|
||||
servicename = "atri"
|
||||
// ATRI 所有命令的优先级
|
||||
prio = 15
|
||||
// ATRI 表情的 codechina 镜像
|
||||
res = "https://gitcode.net/u011570312/ZeroBot-Plugin/-/raw/master/plugin_atri/"
|
||||
res = "https://gitcode.net/u011570312/zbpdata/-/raw/main/Atri/"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register(servicename, &control.Options{
|
||||
engine := control.Register(servicename, order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
|
||||
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢|爱你|爱|suki|daisuki|すき|好き|贴贴|老婆|亲一个|mua\n" +
|
||||
"- 草你妈|操你妈|脑瘫|废柴|fw|废物|战斗|爬|爪巴|sb|SB|傻B\n- 早安|早哇|早上好|ohayo|哦哈哟|お早う|早好|早|早早早\n" +
|
||||
"- 中午好|午安|午好\n- 晚安|oyasuminasai|おやすみなさい|晚好|晚上好\n- 高性能|太棒了|すごい|sugoi|斯国一|よかった\n" +
|
||||
"- 没事|没关系|大丈夫|还好|不要紧|没出大问题|没伤到哪\n- 好吗|是吗|行不行|能不能|可不可以\n- 啊这\n- 我好了\n- ?|?|¿\n" +
|
||||
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢 | 爱你 | 爱 | suki | daisuki | すき | 好き | 贴贴 | 老婆 | 亲一个 | mua\n" +
|
||||
"- 草你妈 | 操你妈 | 脑瘫 | 废柴 | fw | 废物 | 战斗 | 爬 | 爪巴 | sb | SB | 傻B\n- 早安 | 早哇 | 早上好 | ohayo | 哦哈哟 | お早う | 早好 | 早 | 早早早\n" +
|
||||
"- 中午好 | 午安 | 午好\n- 晚安 | oyasuminasai | おやすみなさい | 晚好 | 晚上好\n- 高性能 | 太棒了 | すごい | sugoi | 斯国一 | よかった\n" +
|
||||
"- 没事 | 没关系 | 大丈夫 | 还好 | 不要紧 | 没出大问题 | 没伤到哪\n- 好吗 | 是吗 | 行不行 | 能不能 | 可不可以\n- 啊这\n- 我好了\n- ? | ? | ¿\n" +
|
||||
"- 离谱\n- 答应我",
|
||||
})
|
||||
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).SetPriority(prio).
|
||||
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := control.Lookup(servicename)
|
||||
if ok && !c.IsEnabledIn(ctx.Event.GroupID) {
|
||||
@@ -44,7 +44,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := control.Lookup(servicename)
|
||||
if ok && c.IsEnabledIn(ctx.Event.GroupID) {
|
||||
@@ -53,7 +53,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("Zzz……Zzz……"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("萝卜子", atriSleep).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatch("萝卜子", atriSleep).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(2) {
|
||||
@@ -63,17 +63,17 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randRecord("RocketPunch.amr"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio - 1).
|
||||
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
process.SleepAbout1sTo2s()
|
||||
@@ -113,7 +113,7 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"中午好", "午安", "午好"}).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatchGroup([]string{"中午好", "午安", "午好"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
if now > 11 && now < 15 { // 中午
|
||||
@@ -126,7 +126,7 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい", "晚好", "晚上好"}).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい", "晚好", "晚上好"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
process.SleepAbout1sTo2s()
|
||||
@@ -169,7 +169,7 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
|
||||
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
@@ -190,7 +190,7 @@ func init() { // 插件主体
|
||||
"呣......我的高性能,毫无遗憾地施展出来了......",
|
||||
))
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
|
||||
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
@@ -205,26 +205,26 @@ func init() { // 插件主体
|
||||
))
|
||||
})
|
||||
|
||||
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, atriSleep).SetBlock(true).SetPriority(prio).
|
||||
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, atriSleep).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("YES.png", "NO.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"啊这"}, atriSleep).SetBlock(true).SetPriority(prio).
|
||||
engine.OnKeywordGroup([]string{"啊这"}, atriSleep).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"我好了"}, atriSleep).SetBlock(true).SetPriority(prio).
|
||||
engine.OnKeywordGroup([]string{"我好了"}, atriSleep).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText("不许好!", "憋回去!"))
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"?", "?", "¿"}, atriSleep).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatchGroup([]string{"?", "?", "¿"}, atriSleep).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(5) {
|
||||
@@ -234,7 +234,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeyword("离谱", atriSleep).SetBlock(true).SetPriority(prio).
|
||||
engine.OnKeyword("离谱", atriSleep).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
@@ -243,7 +243,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randImage("WH.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeyword("答应我", atriSleep, zero.OnlyToMe).SetBlock(true).SetPriority(prio).
|
||||
engine.OnKeyword("答应我", atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText("我无法回应你的请求"))
|
||||
@@ -4,22 +4,23 @@ package b14coder
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
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"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("base16384", &control.Options{
|
||||
en := control.Register("base16384", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "base16384加解密\n" +
|
||||
"- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
|
||||
})
|
||||
en.OnRegex(`^加密(.*)`).SetBlock(true).ThirdPriority().
|
||||
en.OnRegex(`^加密\s?(.*)`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es, err := base14.UTF16be2utf8(base14.EncodeString(str))
|
||||
@@ -29,7 +30,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("加密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex("^解密([\u4e00-\u8e00]*[\u3d01-\u3d06]?)$").SetBlock(true).ThirdPriority().
|
||||
en.OnRegex(`^解密\s?([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es, err := base14.UTF82utf16be(helper.StringToBytes(str))
|
||||
@@ -39,7 +40,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("解密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^用(.*)加密(.*)`).SetBlock(true).ThirdPriority().
|
||||
en.OnRegex(`^用(.*)加密\s?(.*)`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
|
||||
t := getea(key)
|
||||
@@ -50,7 +51,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("加密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex("^用(.*)解密([\u4e00-\u8e00]*[\u3d01-\u3d06]?)$").SetBlock(true).ThirdPriority().
|
||||
en.OnRegex(`^用(.*)解密\s?([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
|
||||
t := getea(key)
|
||||
27
plugin/baidu/search.go
Normal file
27
plugin/baidu/search.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Package baidu 百度一下
|
||||
package baidu
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("baidu", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "baidu\n" +
|
||||
"- 百度下[xxx]",
|
||||
}).OnPrefix("百度下").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
txt := ctx.State["args"].(string)
|
||||
if txt != "" {
|
||||
ctx.SendChain(message.Text("https://buhuibaidu.me/?s=" + url.QueryEscape(txt)))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -2,26 +2,27 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
var engine = control.Register("bilibili", &control.Options{
|
||||
var engine = control.Register("bilibili", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibili\n" +
|
||||
"- >vup info [名字|uid]\n" +
|
||||
"- >user info [名字|uid]",
|
||||
"- >vup info [名字 | uid]\n" +
|
||||
"- >user info [名字 | uid]",
|
||||
})
|
||||
|
||||
// 查成分的
|
||||
func init() {
|
||||
engine.OnRegex(`^>user info\s(.{1,25})$`).SetBlock(true).
|
||||
engine.OnRegex(`^>(?:user|vup)\s?info\s?(.{1,25})$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
rest, err := uid(keyword)
|
||||
@@ -46,7 +47,7 @@ func init() {
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
85
plugin/bilibili/live_info.go
Normal file
85
plugin/bilibili/live_info.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
// 查vup粉丝数据
|
||||
func init() {
|
||||
engine.OnRegex(`^>vup info\s?(.{1,25})$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
res, err := uid(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
id := res.Get("data.result.0.mid").String()
|
||||
// 获取详情
|
||||
fo, err := fansapi(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(
|
||||
"uid: ", fo.Mid, "\n",
|
||||
"名字: ", fo.Uname, "\n",
|
||||
"当前粉丝数: ", fo.Follower, "\n",
|
||||
"24h涨粉数: ", fo.Rise, "\n",
|
||||
"视频投稿数: ", fo.Video, "\n",
|
||||
"直播间id: ", fo.Roomid, "\n",
|
||||
"舰队: ", fo.GuardNum, "\n",
|
||||
"直播总排名: ", fo.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", fo.Mid, "\n",
|
||||
"数据获取时间: ", time.Now().Format("2006-01-02 15:04:05"),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
// 搜索api:通过把触发指令传入的昵称找出uid返回
|
||||
func uid(keyword string) (*gjson.Result, error) {
|
||||
api := "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&&user_type=1&keyword=" + keyword
|
||||
data, err := web.GetData(api)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
json := gjson.ParseBytes(data)
|
||||
if json.Get("data.numResults").Int() == 0 {
|
||||
return nil, errors.New("查无此人")
|
||||
}
|
||||
return &json, nil
|
||||
}
|
||||
|
||||
type follower struct {
|
||||
Mid int `json:"mid"`
|
||||
Uname string `json:"uname"`
|
||||
Video int `json:"video"`
|
||||
Roomid int `json:"roomid"`
|
||||
Rise int `json:"rise"`
|
||||
Follower int `json:"follower"`
|
||||
GuardNum int `json:"guardNum"`
|
||||
AreaRank int `json:"areaRank"`
|
||||
}
|
||||
|
||||
// 请求api
|
||||
func fansapi(uid string) (*follower, error) {
|
||||
url := "https://api.vtbs.moe/v1/detail/" + uid
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
result := &follower{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
72
plugin/bilibili_parse/bilibili_parse.go
Normal file
72
plugin/bilibili_parse/bilibili_parse.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Package bilibiliparse b站视频链接解析
|
||||
package bilibiliparse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/antchfx/htmlquery"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
bilibiliRe = "https://www.bilibili.com/video/av[0-9]+|https://www.bilibili.com/video/BV[0-9a-zA-Z]+|https://b23.tv/[0-9a-zA-Z]+|https://www.bilibili.com/video/bv[0-9a-zA-Z]+"
|
||||
validRe = "https://www.bilibili.com/video/(BV[0-9a-zA-Z]+)"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("bilibiliparse", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "b站视频链接解析\n" +
|
||||
"- https://www.bilibili.com/video/BV1xx411c7BF | https://www.bilibili.com/video/av1605 | https://b23.tv/I8uzWCA | https://www.bilibili.com/video/bv1xx411c7BF",
|
||||
})
|
||||
|
||||
engine.OnRegex(bilibiliRe).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
bilibiliURL := ctx.State["regex_matched"].([]string)[0]
|
||||
m := parseURL(bilibiliURL)
|
||||
if len(m) != 0 {
|
||||
ctx.Send(m)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func parseURL(bilibiliURL string) (m message.Message) {
|
||||
doc, err := htmlquery.LoadURL(bilibiliURL)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibiliparse]:访问的链接为", bilibiliURL, ",错误为", err)
|
||||
}
|
||||
videoURL := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='url']").Attr[2].Val
|
||||
re := regexp.MustCompile(validRe)
|
||||
if !re.MatchString(videoURL) {
|
||||
return
|
||||
}
|
||||
bv := re.FindStringSubmatch(videoURL)[1]
|
||||
title := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/h1/span/text()").Data
|
||||
m = append(m, message.Text(title+"\n"))
|
||||
upName := strings.TrimSpace(htmlquery.FindOne(doc, "//*[@id='v_upinfo']/div[2]/div[1]/a[1]/text()").Data)
|
||||
fmt.Println(upName)
|
||||
fanNumber := htmlquery.InnerText(htmlquery.FindOne(doc, "//i[@class='van-icon-general_addto_s']").NextSibling.NextSibling)
|
||||
fmt.Println(fanNumber)
|
||||
m = append(m, message.Text("up:"+upName+",粉丝:"+fanNumber+"\n"))
|
||||
view := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='view']/text()").Data
|
||||
dm := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='dm']/text()").Data
|
||||
m = append(m, message.Text(view+dm+"\n"))
|
||||
t := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[3]/text()").Data
|
||||
m = append(m, message.Text(t))
|
||||
image := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='image']").Attr[2].Val
|
||||
m = append(m, message.Image(image))
|
||||
like := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='like']/text()").Data
|
||||
coin := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='coin']/text()").Data
|
||||
m = append(m, message.Text("\n点赞:", strings.TrimSpace(like)+",投币:", strings.TrimSpace(coin)+"\n"))
|
||||
collect := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='collect']/text()").Data
|
||||
share := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='share']/text()").Data
|
||||
m = append(m, message.Text("收藏:", strings.TrimSpace(collect)+",分享:", strings.TrimSpace(share)+"\n"))
|
||||
m = append(m, message.Text(bv))
|
||||
return
|
||||
}
|
||||
563
plugin/bilibili_push/bilibili_push.go
Normal file
563
plugin/bilibili_push/bilibili_push.go
Normal file
@@ -0,0 +1,563 @@
|
||||
// Package bilibilipush b站推送
|
||||
package bilibilipush
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
const (
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
|
||||
referer = "https://www.bilibili.com/"
|
||||
infoURL = "https://api.bilibili.com/x/space/acc/info?mid=%d"
|
||||
userDynamicURL = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history?host_uid=%d&offset_dynamic_id=0&need_top=0"
|
||||
liveListURL = "https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids"
|
||||
tURL = "https://t.bilibili.com/"
|
||||
liveURL = "https://live.bilibili.com/"
|
||||
serviceName = "bilibilipush"
|
||||
)
|
||||
|
||||
// bdb bilibili推送数据库
|
||||
var bdb *bilibilipushdb
|
||||
|
||||
var (
|
||||
lastTime = map[int64]int64{}
|
||||
typeMsg = map[int64]string{
|
||||
1: "转发了一条动态",
|
||||
2: "有图营业",
|
||||
4: "无图营业",
|
||||
8: "发布了新投稿",
|
||||
16: "发布了短视频",
|
||||
64: "发布了新专栏",
|
||||
256: "发布了新音频",
|
||||
}
|
||||
liveStatus = map[int64]int{}
|
||||
uidErrorMsg = map[int]string{
|
||||
0: "输入的uid有效",
|
||||
-400: "uid不存在,注意uid不是房间号",
|
||||
-402: "uid不存在,注意uid不是房间号",
|
||||
-412: "操作过于频繁IP暂时被风控,请半小时后再尝试",
|
||||
}
|
||||
upMap = map[int64]string{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
go bilibiliPushDaily()
|
||||
en := control.Register(serviceName, order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibilipush\n" +
|
||||
"- 添加订阅[uid]\n" +
|
||||
"- 取消订阅[uid]\n" +
|
||||
"- 取消动态订阅[uid]\n" +
|
||||
"- 取消直播订阅[uid]\n" +
|
||||
"- 推送列表",
|
||||
PrivateDataFolder: serviceName,
|
||||
})
|
||||
|
||||
// 加载数据库
|
||||
go func() {
|
||||
dbpath := en.DataFolder()
|
||||
dbfile := dbpath + "push.db"
|
||||
bdb = initialize(dbfile)
|
||||
log.Println("[bilibilipush]加载bilibilipush数据库")
|
||||
}()
|
||||
|
||||
en.OnRegex(`^添加订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
var name string
|
||||
var ok bool
|
||||
if name, ok = upMap[buid]; !ok {
|
||||
var status int
|
||||
status, name = checkBuid(buid)
|
||||
if status != 0 {
|
||||
msg, ok := uidErrorMsg[status]
|
||||
if !ok {
|
||||
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
|
||||
}
|
||||
ctx.SendChain(message.Text(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
if err := subscribe(buid, gid); err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
} else {
|
||||
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^取消订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
var name string
|
||||
var ok bool
|
||||
if name, ok = upMap[buid]; !ok {
|
||||
var status int
|
||||
status, name = checkBuid(buid)
|
||||
if status != 0 {
|
||||
msg, ok := uidErrorMsg[status]
|
||||
if !ok {
|
||||
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
|
||||
}
|
||||
ctx.SendChain(message.Text(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
if err := unsubscribe(buid, gid); err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
} else {
|
||||
ctx.SendChain(message.Text("已取消" + name + "的订阅"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^取消动态订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
var name string
|
||||
var ok bool
|
||||
if name, ok = upMap[buid]; !ok {
|
||||
var status int
|
||||
status, name = checkBuid(buid)
|
||||
if status != 0 {
|
||||
msg, ok := uidErrorMsg[status]
|
||||
if !ok {
|
||||
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
|
||||
}
|
||||
ctx.SendChain(message.Text(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
if err := unsubscribeDynamic(buid, gid); err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
} else {
|
||||
ctx.SendChain(message.Text("已取消" + name + "的动态订阅"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^取消直播订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
var name string
|
||||
var ok bool
|
||||
if name, ok = upMap[buid]; !ok {
|
||||
var status int
|
||||
status, name = checkBuid(buid)
|
||||
if status != 0 {
|
||||
msg, ok := uidErrorMsg[status]
|
||||
if !ok {
|
||||
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
|
||||
}
|
||||
ctx.SendChain(message.Text(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
if err := unsubscribeLive(buid, gid); err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
} else {
|
||||
ctx.SendChain(message.Text("已取消" + name + "的直播订阅"))
|
||||
}
|
||||
})
|
||||
en.OnFullMatch("推送列表", ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
bpl := bdb.getAllPushByGroup(gid)
|
||||
fmt.Println(bpl)
|
||||
msg := "--------推送列表--------"
|
||||
for _, v := range bpl {
|
||||
if _, ok := upMap[v.BilibiliUID]; !ok {
|
||||
bdb.updateAllUp()
|
||||
fmt.Println(upMap)
|
||||
}
|
||||
msg += fmt.Sprintf("\nuid:%-12d 动态:", v.BilibiliUID)
|
||||
if v.DynamicDisable == 0 {
|
||||
msg += "●"
|
||||
} else {
|
||||
msg += "○"
|
||||
}
|
||||
msg += " 直播:"
|
||||
if v.LiveDisable == 0 {
|
||||
msg += "●"
|
||||
} else {
|
||||
msg += "○"
|
||||
}
|
||||
msg += " up主:" + upMap[v.BilibiliUID]
|
||||
}
|
||||
data, err := text.RenderToBase64(msg, text.FontFile, 600, 20)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func bilibiliPushDaily() {
|
||||
t := time.NewTicker(time.Second * 10)
|
||||
defer t.Stop()
|
||||
for range t.C {
|
||||
log.Println("-----bilibilipush拉取推送信息-----")
|
||||
sendDynamic()
|
||||
sendLive()
|
||||
}
|
||||
}
|
||||
|
||||
func checkBuid(buid int64) (status int, name string) {
|
||||
data, err := web.GetDataWith(web.NewDefaultClient(), fmt.Sprintf(infoURL, buid), "GET", referer, ua)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
}
|
||||
status = int(gjson.Get(binary.BytesToString(data), "code").Int())
|
||||
name = gjson.Get(binary.BytesToString(data), "data.name").String()
|
||||
if status == 0 {
|
||||
bdb.insertBilibiliUp(buid, name)
|
||||
upMap[buid] = name
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// subscribe 订阅
|
||||
func subscribe(buid, groupid int64) (err error) {
|
||||
bpMap := map[string]interface{}{
|
||||
"bilibili_uid": buid,
|
||||
"group_id": groupid,
|
||||
"live_disable": 0,
|
||||
"dynamic_disable": 0,
|
||||
}
|
||||
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
|
||||
return
|
||||
}
|
||||
|
||||
// unsubscribe 取消订阅
|
||||
func unsubscribe(buid, groupid int64) (err error) {
|
||||
bpMap := map[string]interface{}{
|
||||
"bilibili_uid": buid,
|
||||
"group_id": groupid,
|
||||
"live_disable": 1,
|
||||
"dynamic_disable": 1,
|
||||
}
|
||||
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
|
||||
return
|
||||
}
|
||||
|
||||
func unsubscribeDynamic(buid, groupid int64) (err error) {
|
||||
bpMap := map[string]interface{}{
|
||||
"bilibili_uid": buid,
|
||||
"group_id": groupid,
|
||||
"dynamic_disable": 1,
|
||||
}
|
||||
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
|
||||
return
|
||||
}
|
||||
|
||||
func unsubscribeLive(buid, groupid int64) (err error) {
|
||||
bpMap := map[string]interface{}{
|
||||
"bilibili_uid": buid,
|
||||
"group_id": groupid,
|
||||
"live_disable": 1,
|
||||
}
|
||||
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
|
||||
return
|
||||
}
|
||||
|
||||
func getUserDynamicCard(buid int64) (cardList []gjson.Result) {
|
||||
data, err := web.GetDataWith(web.NewDefaultClient(), fmt.Sprintf(userDynamicURL, buid), "GET", referer, ua)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
}
|
||||
cardList = gjson.Get(binary.BytesToString(data), "data.cards").Array()
|
||||
return
|
||||
}
|
||||
|
||||
func getLiveList(uids ...int64) string {
|
||||
m := make(map[string]interface{})
|
||||
m["uids"] = uids
|
||||
b, _ := json.Marshal(m)
|
||||
client := &http.Client{}
|
||||
// 提交请求
|
||||
request, err := http.NewRequest("POST", liveListURL, bytes.NewBuffer(b))
|
||||
if err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
}
|
||||
request.Header.Add("Referer", referer)
|
||||
request.Header.Add("User-Agent", ua)
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
data, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibilipush]:", err)
|
||||
}
|
||||
return binary.BytesToString(data)
|
||||
}
|
||||
|
||||
func sendDynamic() {
|
||||
uids := bdb.getAllBuidByDynamic()
|
||||
for _, buid := range uids {
|
||||
cardList := getUserDynamicCard(buid)
|
||||
if len(cardList) == 0 {
|
||||
return
|
||||
}
|
||||
t, ok := lastTime[buid]
|
||||
if !ok {
|
||||
lastTime[buid] = cardList[0].Get("desc.timestamp").Int()
|
||||
return
|
||||
}
|
||||
for i := len(cardList) - 1; i >= 0; i-- {
|
||||
ct := cardList[i].Get("desc.timestamp").Int()
|
||||
if ct > t && ct > time.Now().Unix()-600 {
|
||||
lastTime[buid] = ct
|
||||
m, ok := control.Lookup(serviceName)
|
||||
if ok {
|
||||
groupList := bdb.getAllGroupByBuidAndDynamic(buid)
|
||||
var msg []message.MessageSegment
|
||||
cType := cardList[i].Get("desc.type").Int()
|
||||
cardStr := cardList[i].Get("card").String()
|
||||
switch cType {
|
||||
case 0:
|
||||
cName := cardList[i].Get("desc.user_profile.info.uname").String()
|
||||
cTime := time.Unix(cardList[i].Get("desc.timestamp").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cTime+typeMsg[cType]+"\n"))
|
||||
case 1:
|
||||
cName := gjson.Get(cardStr, "user.uname").String()
|
||||
msg = append(msg, message.Text(cName+typeMsg[cType]+"\n"))
|
||||
cContent := gjson.Get(cardStr, "item.content").String()
|
||||
msg = append(msg, message.Text(cContent+"\n"))
|
||||
msg = append(msg, message.Text("转发的内容:\n"))
|
||||
cOrigType := gjson.Get(cardStr, "item.orig_type").Int()
|
||||
cOrigin := gjson.Get(cardStr, "origin").String()
|
||||
switch cOrigType {
|
||||
case 1:
|
||||
cName := gjson.Get(cOrigin, "user.uname").String()
|
||||
msg = append(msg, message.Text(cName+typeMsg[cOrigType]+"\n"))
|
||||
case 2:
|
||||
cName := gjson.Get(cOrigin, "user.name").String()
|
||||
cUploadTime := time.Unix(gjson.Get(cOrigin, "item.upload_time").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cOrigType]+"\n"))
|
||||
cDescription := gjson.Get(cOrigin, "item.description")
|
||||
msg = append(msg, message.Text(cDescription))
|
||||
if gjson.Get(cOrigin, "item.pictures.#").Int() != 0 {
|
||||
gjson.Get(cOrigin, "item.pictures").ForEach(func(_, v gjson.Result) bool {
|
||||
msg = append(msg, message.Image(v.Get("img_src").String()))
|
||||
return true
|
||||
})
|
||||
}
|
||||
case 4:
|
||||
cName := gjson.Get(cOrigin, "user.uname").String()
|
||||
cTimestamp := time.Unix(gjson.Get(cOrigin, "item.timestamp").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cTimestamp+typeMsg[cOrigType]+"\n"))
|
||||
cContent := gjson.Get(cOrigin, "item.content").String()
|
||||
msg = append(msg, message.Text(cContent+"\n"))
|
||||
case 8:
|
||||
cName := gjson.Get(cOrigin, "owner.name").String()
|
||||
cTime := time.Unix(gjson.Get(cOrigin, "pubdate").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cTime+typeMsg[cOrigType]+"\n"))
|
||||
cTitle := gjson.Get(cOrigin, "title").String()
|
||||
msg = append(msg, message.Text(cTitle))
|
||||
cPic := gjson.Get(cOrigin, "pic").String()
|
||||
msg = append(msg, message.Image(cPic))
|
||||
cDesc := gjson.Get(cOrigin, "desc").String()
|
||||
msg = append(msg, message.Text(cDesc+"\n"))
|
||||
cShareSubtitle := gjson.Get(cOrigin, "share_subtitle").String()
|
||||
msg = append(msg, message.Text(cShareSubtitle+"\n"))
|
||||
cShortLink := gjson.Get(cOrigin, "short_link").String()
|
||||
msg = append(msg, message.Text("视频链接:"+cShortLink+"\n"))
|
||||
case 16:
|
||||
cName := gjson.Get(cOrigin, "user.name").String()
|
||||
cUploadTime := gjson.Get(cOrigin, "item.upload_time").String()
|
||||
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cOrigType]+"\n"))
|
||||
cDescription := gjson.Get(cOrigin, "item.description")
|
||||
msg = append(msg, message.Text(cDescription))
|
||||
cCover := gjson.Get(cOrigin, "item.cover.default").String()
|
||||
msg = append(msg, message.Image(cCover))
|
||||
case 64:
|
||||
cName := gjson.Get(cOrigin, "author.name").String()
|
||||
cPublishTime := time.Unix(gjson.Get(cOrigin, "publish_time").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cPublishTime+typeMsg[cOrigType]+"\n"))
|
||||
cTitle := gjson.Get(cOrigin, "title").String()
|
||||
msg = append(msg, message.Text(cTitle+"\n"))
|
||||
cSummary := gjson.Get(cOrigin, "summary").String()
|
||||
msg = append(msg, message.Text(cSummary))
|
||||
cBannerURL := gjson.Get(cOrigin, "banner_url").String()
|
||||
msg = append(msg, message.Image(cBannerURL))
|
||||
case 256:
|
||||
cUpper := gjson.Get(cOrigin, "upper").String()
|
||||
cTime := time.UnixMilli(gjson.Get(cOrigin, "ctime").Int()).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cUpper+"在"+cTime+typeMsg[cOrigType]+"\n"))
|
||||
cTitle := gjson.Get(cOrigin, "title").String()
|
||||
msg = append(msg, message.Text(cTitle))
|
||||
cCover := gjson.Get(cOrigin, "cover").String()
|
||||
msg = append(msg, message.Image(cCover))
|
||||
default:
|
||||
msg = append(msg, message.Text("未知动态类型"+strconv.FormatInt(cOrigType, 10)+"\n"))
|
||||
}
|
||||
case 2:
|
||||
cName := gjson.Get(cardStr, "user.name").String()
|
||||
cUploadTime := time.Unix(gjson.Get(cardStr, "item.upload_time").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cType]+"\n"))
|
||||
cDescription := gjson.Get(cardStr, "item.description")
|
||||
msg = append(msg, message.Text(cDescription))
|
||||
if gjson.Get(cardStr, "item.pictures.#").Int() != 0 {
|
||||
gjson.Get(cardStr, "item.pictures").ForEach(func(_, v gjson.Result) bool {
|
||||
msg = append(msg, message.Image(v.Get("img_src").String()))
|
||||
return true
|
||||
})
|
||||
}
|
||||
case 4:
|
||||
cName := gjson.Get(cardStr, "user.uname").String()
|
||||
cTimestamp := time.Unix(gjson.Get(cardStr, "item.timestamp").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cTimestamp+typeMsg[cType]+"\n"))
|
||||
cContent := gjson.Get(cardStr, "item.content").String()
|
||||
msg = append(msg, message.Text(cContent+"\n"))
|
||||
case 8:
|
||||
cName := gjson.Get(cardStr, "owner.name").String()
|
||||
cTime := time.Unix(gjson.Get(cardStr, "ctime").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cTime+typeMsg[cType]+"\n"))
|
||||
cTitle := gjson.Get(cardStr, "title").String()
|
||||
msg = append(msg, message.Text(cTitle))
|
||||
cPic := gjson.Get(cardStr, "pic").String()
|
||||
msg = append(msg, message.Image(cPic))
|
||||
cDesc := gjson.Get(cardStr, "desc").String()
|
||||
msg = append(msg, message.Text(cDesc+"\n"))
|
||||
cShareSubtitle := gjson.Get(cardStr, "share_subtitle").String()
|
||||
msg = append(msg, message.Text(cShareSubtitle+"\n"))
|
||||
cShortLink := gjson.Get(cardStr, "short_link").String()
|
||||
msg = append(msg, message.Text("视频链接:"+cShortLink+"\n"))
|
||||
case 16:
|
||||
cName := gjson.Get(cardStr, "user.name").String()
|
||||
cUploadTime := gjson.Get(cardStr, "item.upload_time").String()
|
||||
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cType]+"\n"))
|
||||
cDescription := gjson.Get(cardStr, "item.description")
|
||||
msg = append(msg, message.Text(cDescription))
|
||||
cCover := gjson.Get(cardStr, "item.cover.default").String()
|
||||
msg = append(msg, message.Image(cCover))
|
||||
case 64:
|
||||
cName := gjson.Get(cardStr, "author.name").String()
|
||||
cPublishTime := time.Unix(gjson.Get(cardStr, "publish_time").Int(), 0).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cName+"在"+cPublishTime+typeMsg[cType]+"\n"))
|
||||
cTitle := gjson.Get(cardStr, "title").String()
|
||||
msg = append(msg, message.Text(cTitle+"\n"))
|
||||
cSummary := gjson.Get(cardStr, "summary").String()
|
||||
msg = append(msg, message.Text(cSummary))
|
||||
cBannerURL := gjson.Get(cardStr, "banner_url").String()
|
||||
msg = append(msg, message.Image(cBannerURL))
|
||||
case 256:
|
||||
cUpper := gjson.Get(cardStr, "upper").String()
|
||||
cTime := time.UnixMilli(gjson.Get(cardStr, "ctime").Int()).Format("2006-01-02 15:04:05")
|
||||
msg = append(msg, message.Text(cUpper+"在"+cTime+typeMsg[cType]+"\n"))
|
||||
cTitle := gjson.Get(cardStr, "title").String()
|
||||
msg = append(msg, message.Text(cTitle))
|
||||
cCover := gjson.Get(cardStr, "cover").String()
|
||||
msg = append(msg, message.Image(cCover))
|
||||
default:
|
||||
msg = append(msg, message.Text("未知动态类型"+strconv.FormatInt(cType, 10)+"\n"))
|
||||
}
|
||||
cID := cardList[i].Get("desc.dynamic_id").String()
|
||||
msg = append(msg, message.Text("动态链接:", tURL+cID))
|
||||
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
|
||||
for _, gid := range groupList {
|
||||
if m.IsEnabledIn(gid) {
|
||||
switch {
|
||||
case gid > 0:
|
||||
ctx.SendGroupMessage(gid, msg)
|
||||
case gid < 0:
|
||||
ctx.SendPrivateMessage(-gid, msg)
|
||||
default:
|
||||
log.Errorln("[bilibilipush]:gid为0")
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sendLive() {
|
||||
uids := bdb.getAllBuidByLive()
|
||||
gjson.Get(getLiveList(uids...), "data").ForEach(func(key, value gjson.Result) bool {
|
||||
newStatus := int(value.Get("live_status").Int())
|
||||
if newStatus == 2 {
|
||||
newStatus = 0
|
||||
}
|
||||
if _, ok := liveStatus[key.Int()]; !ok {
|
||||
liveStatus[key.Int()] = newStatus
|
||||
return true
|
||||
}
|
||||
oldStatus := liveStatus[key.Int()]
|
||||
if newStatus != oldStatus && newStatus == 1 {
|
||||
liveStatus[key.Int()] = newStatus
|
||||
m, ok := control.Lookup(serviceName)
|
||||
if ok {
|
||||
groupList := bdb.getAllGroupByBuidAndLive(key.Int())
|
||||
roomID := value.Get("short_id").Int()
|
||||
if roomID == 0 {
|
||||
roomID = value.Get("room_id").Int()
|
||||
}
|
||||
lURL := liveURL + strconv.FormatInt(roomID, 10)
|
||||
lName := value.Get("uname").String()
|
||||
lTitle := value.Get("title").String()
|
||||
lCover := value.Get("cover_from_user").String()
|
||||
if lCover == "" {
|
||||
lCover = value.Get("keyframe").String()
|
||||
}
|
||||
var msg []message.MessageSegment
|
||||
msg = append(msg, message.Text(lName+" 正在直播:\n"))
|
||||
msg = append(msg, message.Text(lTitle))
|
||||
msg = append(msg, message.Image(lCover))
|
||||
msg = append(msg, message.Text("直播链接:", lURL))
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
|
||||
for _, gid := range groupList {
|
||||
if m.IsEnabledIn(gid) {
|
||||
switch {
|
||||
case gid > 0:
|
||||
ctx.SendGroupMessage(gid, msg)
|
||||
case gid < 0:
|
||||
ctx.SendPrivateMessage(-gid, msg)
|
||||
default:
|
||||
log.Errorln("[bilibilipush]:gid为0")
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
} else if newStatus != oldStatus {
|
||||
liveStatus[key.Int()] = newStatus
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
144
plugin/bilibili_push/model.go
Normal file
144
plugin/bilibili_push/model.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package bilibilipush
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
_ "github.com/fumiama/sqlite3" // import sql
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// bilibilipushdb bili推送数据库
|
||||
type bilibilipushdb gorm.DB
|
||||
|
||||
type bilibilipush struct {
|
||||
ID int64 `gorm:"column:id;primary_key" json:"id"`
|
||||
BilibiliUID int64 `gorm:"column:bilibili_uid;index:idx_buid_gid" json:"bilibili_uid"`
|
||||
GroupID int64 `gorm:"column:group_id;index:idx_buid_gid" json:"group_id"`
|
||||
LiveDisable int64 `gorm:"column:live_disable;default:0" json:"live_disable"`
|
||||
DynamicDisable int64 `gorm:"column:dynamic_disable;default:0" json:"dynamic_disable"`
|
||||
}
|
||||
|
||||
// TableName ...
|
||||
func (bilibilipush) TableName() string {
|
||||
return "bilibili_push"
|
||||
}
|
||||
|
||||
type bilibiliup struct {
|
||||
BilibiliUID int64 `gorm:"column:bilibili_uid;primary_key"`
|
||||
Name string `gorm:"column:name"`
|
||||
}
|
||||
|
||||
// TableName ...
|
||||
func (bilibiliup) TableName() string {
|
||||
return "bilibili_up"
|
||||
}
|
||||
|
||||
// initialize 初始化ScoreDB数据库
|
||||
func initialize(dbpath string) *bilibilipushdb {
|
||||
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(&bilibilipush{}).AutoMigrate(&bilibiliup{})
|
||||
return (*bilibilipushdb)(gdb)
|
||||
}
|
||||
|
||||
// insertOrUpdateLiveAndDynamic 插入或更新数据库
|
||||
func (bdb *bilibilipushdb) insertOrUpdateLiveAndDynamic(bpMap map[string]interface{}) (err error) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
bp := bilibilipush{}
|
||||
data, _ := json.Marshal(&bpMap)
|
||||
_ = json.Unmarshal(data, &bp)
|
||||
if err = db.Debug().Model(&bilibilipush{}).First(&bp, "bilibili_uid = ? and group_id = ?", bp.BilibiliUID, bp.GroupID).Error; err != nil {
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
err = db.Debug().Model(&bilibilipush{}).Create(&bp).Error
|
||||
}
|
||||
} else {
|
||||
err = db.Debug().Model(&bilibilipush{}).Where("bilibili_uid = ? and group_id = ?", bp.BilibiliUID, bp.GroupID).Update(bpMap).Error
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) getAllBuidByLive() (buidList []int64) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
var bpl []bilibilipush
|
||||
db.Debug().Model(&bilibilipush{}).Find(&bpl, "live_disable = 0")
|
||||
temp := make(map[int64]bool)
|
||||
for _, v := range bpl {
|
||||
_, ok := temp[v.BilibiliUID]
|
||||
if !ok {
|
||||
buidList = append(buidList, v.BilibiliUID)
|
||||
temp[v.BilibiliUID] = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) getAllBuidByDynamic() (buidList []int64) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
var bpl []bilibilipush
|
||||
db.Debug().Model(&bilibilipush{}).Find(&bpl, "dynamic_disable = 0")
|
||||
temp := make(map[int64]bool)
|
||||
for _, v := range bpl {
|
||||
_, ok := temp[v.BilibiliUID]
|
||||
if !ok {
|
||||
buidList = append(buidList, v.BilibiliUID)
|
||||
temp[v.BilibiliUID] = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) getAllGroupByBuidAndLive(buid int64) (groupList []int64) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
var bpl []bilibilipush
|
||||
db.Debug().Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and live_disable = 0", buid)
|
||||
for _, v := range bpl {
|
||||
groupList = append(groupList, v.GroupID)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) getAllGroupByBuidAndDynamic(buid int64) (groupList []int64) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
var bpl []bilibilipush
|
||||
db.Debug().Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and dynamic_disable = 0", buid)
|
||||
for _, v := range bpl {
|
||||
groupList = append(groupList, v.GroupID)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) getAllPushByGroup(groupID int64) (bpl []bilibilipush) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
db.Debug().Model(&bilibilipush{}).Find(&bpl, "group_id = ? and (live_disable = 0 or dynamic_disable = 0)", groupID)
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) insertBilibiliUp(buid int64, name string) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
bu := bilibiliup{
|
||||
BilibiliUID: buid,
|
||||
Name: name,
|
||||
}
|
||||
db.Debug().Model(&bilibiliup{}).Create(bu)
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) updateAllUp() {
|
||||
db := (*gorm.DB)(bdb)
|
||||
var bul []bilibiliup
|
||||
db.Debug().Model(&bilibiliup{}).Find(&bul)
|
||||
for _, v := range bul {
|
||||
upMap[v.BilibiliUID] = v.Name
|
||||
}
|
||||
}
|
||||
63
plugin/book_review/book_review.go
Normal file
63
plugin/book_review/book_review.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// Package bookreview 书评
|
||||
package bookreview
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("bookreview", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "哀伤雪刃推书记录\n- 书评[xxx]\n- 随机书评",
|
||||
PublicDataFolder: "BookReview",
|
||||
})
|
||||
|
||||
go func() {
|
||||
dbpath := engine.DataFolder()
|
||||
db.DBPath = dbpath + "bookreview.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = file.GetLazyData(db.DBPath, false, true)
|
||||
err := db.Create("bookreview", &book{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n, err := db.Count("bookreview")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Printf("[bookreview]读取%d条书评", n)
|
||||
}()
|
||||
|
||||
// 中文、英文、数字但不包括下划线等符号
|
||||
engine.OnRegex("^书评([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
b := getBookReviewByKeyword(ctx.State["regex_matched"].([]string)[1])
|
||||
data, err := text.RenderToBase64(b.BookReview, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
log.Println("err:", err)
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnFullMatch("随机书评").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
br := getRandomBookReview()
|
||||
data, err := text.RenderToBase64(br.BookReview, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
log.Println("err:", err)
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
}
|
||||
21
plugin/book_review/model.go
Normal file
21
plugin/book_review/model.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package bookreview
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type book struct {
|
||||
ID uint64 `db:"id"`
|
||||
BookReview string `db:"bookreview"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
// 暂时随机选择一个书评
|
||||
func getBookReviewByKeyword(keyword string) (b book) {
|
||||
_ = db.Find("bookreview", &b, "where bookreview LIKE '%"+keyword+"%'")
|
||||
return
|
||||
}
|
||||
|
||||
func getRandomBookReview() (b book) {
|
||||
_ = db.Pick("bookreview", &b)
|
||||
return
|
||||
}
|
||||
123
plugin/cangtoushi/cangtoushi.go
Normal file
123
plugin/cangtoushi/cangtoushi.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Package cangtoushi 藏头诗
|
||||
package cangtoushi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/antchfx/htmlquery"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
loginURL = "https://www.shicimingju.com/cangtoushi/"
|
||||
searchURL = "https://www.shicimingju.com/cangtoushi/index.html"
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
|
||||
referer = "https://www.shicimingju.com/cangtoushi/index.html"
|
||||
)
|
||||
|
||||
var (
|
||||
gCurCookieJar *cookiejar.Jar
|
||||
csrf string
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cangtoushi", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "藏头诗\n" +
|
||||
"- 藏头诗[xxx]\n- 藏尾诗[xxx]",
|
||||
})
|
||||
engine.OnRegex(`藏头诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
kw := ctx.State["regex_matched"].([]string)[1]
|
||||
login()
|
||||
data, err := search(kw, "7", "0")
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
text := dealHTML(helper.BytesToString(data))
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnRegex(`藏尾诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
kw := ctx.State["regex_matched"].([]string)[1]
|
||||
login()
|
||||
data, err := search(kw, "7", "2")
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
text := dealHTML(helper.BytesToString(data))
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
}
|
||||
|
||||
func login() {
|
||||
gCurCookieJar, _ = cookiejar.New(nil)
|
||||
client := &http.Client{
|
||||
Jar: gCurCookieJar,
|
||||
}
|
||||
request, err := http.NewRequest("GET", loginURL, nil)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
request.Header.Add("User-Agent", ua)
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
data, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
response.Body.Close()
|
||||
doc, err := htmlquery.Parse(strings.NewReader(helper.BytesToString(data)))
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
csrf = htmlquery.SelectAttr(htmlquery.FindOne(doc, "//input[@name='_csrf']"), "value")
|
||||
}
|
||||
|
||||
func search(kw, zishu, position string) (data []byte, err error) {
|
||||
postStr := fmt.Sprintf("_csrf=%s&kw=%s&zishu=%s&position=%s", url.QueryEscape(csrf), url.QueryEscape(kw), zishu, position)
|
||||
log.Println("postStr:", postStr)
|
||||
client := &http.Client{
|
||||
Jar: gCurCookieJar,
|
||||
}
|
||||
request, err := http.NewRequest("POST", searchURL, strings.NewReader(postStr))
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
request.Header.Add("Referer", referer)
|
||||
request.Header.Add("User-Agent", ua)
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
data, err = io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
response.Body.Close()
|
||||
return
|
||||
}
|
||||
|
||||
func dealHTML(data string) (text string) {
|
||||
doc, err := htmlquery.Parse(strings.NewReader(data))
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
}
|
||||
text = htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@class='card']/div[@class='card']"))
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.Replace(text, "\n", "", 1)
|
||||
return text
|
||||
}
|
||||
@@ -6,32 +6,25 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
)
|
||||
|
||||
const (
|
||||
dbpath = "data/Chat/"
|
||||
dbfile = dbpath + "kimoi.json"
|
||||
prio = 10
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
var (
|
||||
poke = rate.NewManager(time.Minute*5, 8) // 戳一戳
|
||||
engine = control.Register("chat", &control.Options{
|
||||
engine = control.Register("chat", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]\n- mua|啾咪|摸|上你|傻|裸|贴|老婆|抱|亲|一下|咬|操|123|进去|调教|搓|让|捏|挤|略|呐|原味|胖次|内裤|内衣|衣服|ghs|批|憨批|kkp|咕|骚|喜欢|suki|好き|看|不能|砸了|透|口我|草我|自慰|onani|オナニー|炸了|色图|涩图|告白|对不起|回来|吻|软|壁咚|掰开|女友|是|喵|嗷呜|叫|拜|佬|awsl|臭|香|腿|张开|脚|脸|头发|手|pr|舔|小穴|腰|诶嘿嘿|可爱|扭蛋|鼻|眼|色气|推|床|举|手冲|饿|变|敲|爬|怕|冲|射|不穿|迫害|猫粮|揪尾巴|薄荷|早|晚安|揉|榨|掐|胸|奶子|欧派|嫩|蹭|牵手|握手|拍照|w|睡不着|欧尼酱|哥|爱你|过来|自闭|打不过|么么哒|很懂|膝枕|累了|安慰|洗澡|一起睡觉|一起|多大|姐姐|糖|嗦|牛子|🐂子|🐮子|嫌弃|紧|baka|笨蛋|插|插进来|屁股|翘|翘起来|抬|抬起|爸|傲娇|rua|咕噜咕噜|咕噜|上床|做爱|吃掉|吃|揪|种草莓|种草|掀|妹|病娇|嘻",
|
||||
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
|
||||
})
|
||||
kimomap = make(kimo, 256)
|
||||
chatList = make([]string, 0, 256)
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// 被喊名字
|
||||
engine.OnFullMatch("", zero.OnlyToMe).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatch("", zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var nickname = zero.BotConfig.NickName[0]
|
||||
time.Sleep(time.Second * 1)
|
||||
@@ -45,7 +38,7 @@ func init() { // 插件主体
|
||||
))
|
||||
})
|
||||
// 戳一戳
|
||||
engine.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).SetPriority(prio).
|
||||
engine.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var nickname = zero.BotConfig.NickName[0]
|
||||
switch {
|
||||
@@ -64,18 +57,18 @@ func init() { // 插件主体
|
||||
// 群空调
|
||||
var AirConditTemp = map[int64]int{}
|
||||
var AirConditSwitch = map[int64]bool{}
|
||||
engine.OnFullMatch("空调开").SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatch("空调开").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
AirConditSwitch[ctx.Event.GroupID] = true
|
||||
ctx.SendChain(message.Text("❄️哔~"))
|
||||
})
|
||||
engine.OnFullMatch("空调关").SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatch("空调关").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
AirConditSwitch[ctx.Event.GroupID] = false
|
||||
delete(AirConditTemp, ctx.Event.GroupID)
|
||||
ctx.SendChain(message.Text("💤哔~"))
|
||||
})
|
||||
engine.OnRegex(`设置温度(\d+)`).SetBlock(true).SetPriority(prio).
|
||||
engine.OnRegex(`设置温度(\d+)`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
|
||||
AirConditTemp[ctx.Event.GroupID] = 26
|
||||
@@ -94,7 +87,7 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch(`群温度`).SetBlock(true).SetPriority(prio).
|
||||
engine.OnFullMatch(`群温度`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
|
||||
AirConditTemp[ctx.Event.GroupID] = 26
|
||||
@@ -111,13 +104,4 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
initChatList(func() {
|
||||
engine.OnFullMatchGroup(chatList, zero.OnlyToMe).SetBlock(true).SetPriority(prio).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
key := ctx.MessageString()
|
||||
val := *kimomap[key]
|
||||
text := val[rand.Intn(len(val))]
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -6,20 +6,21 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("choose", &control.Options{
|
||||
engine := control.Register("choose", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "choose\n" +
|
||||
"- 选择可口可乐还是百事可乐\n" +
|
||||
"- 选择肯德基还是麦当劳还是必胜客",
|
||||
})
|
||||
engine.OnPrefix("选择").SetBlock(true).FirstPriority().Handle(handle)
|
||||
engine.OnPrefix("选择").SetBlock(true).Handle(handle)
|
||||
}
|
||||
func handle(ctx *zero.Ctx) {
|
||||
rawOptions := strings.Split(ctx.State["args"].(string), "还是")
|
||||
63
plugin/chouxianghua/chouxianghua.go
Normal file
63
plugin/chouxianghua/chouxianghua.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// Package chouxianghua 抽象话转化
|
||||
package chouxianghua
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("chouxianghua", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "抽象话\n- 抽象翻译xxx",
|
||||
PublicDataFolder: "ChouXiangHua",
|
||||
})
|
||||
|
||||
go func() {
|
||||
dbpath := en.DataFolder()
|
||||
db.DBPath = dbpath + "cxh.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = file.GetLazyData(db.DBPath, false, true)
|
||||
err := db.Create("pinyin", &pinyin{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n, err := db.Count("pinyin")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Printf("[chouxianghua]读取%d条拼音", n)
|
||||
}()
|
||||
|
||||
en.OnRegex("^抽象翻译((\\s|[\\r\\n]|[\\p{Han}\\p{P}A-Za-z0-9])+)$").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
r := cx(ctx.State["regex_matched"].([]string)[1])
|
||||
ctx.SendChain(message.Text(r))
|
||||
})
|
||||
}
|
||||
|
||||
func cx(s string) (r string) {
|
||||
h := []rune(s)
|
||||
for i := 0; i < len(h); i++ {
|
||||
if i < len(h)-1 {
|
||||
e := getEmojiByPronun(getPronunByDWord(h[i], h[i+1]))
|
||||
if e != "" {
|
||||
r += e
|
||||
i++
|
||||
continue
|
||||
}
|
||||
}
|
||||
e := getEmojiByPronun(getPinyinByWord(string(h[i])))
|
||||
if e != "" {
|
||||
r += e
|
||||
continue
|
||||
}
|
||||
r += string(h[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
30
plugin/chouxianghua/model.go
Normal file
30
plugin/chouxianghua/model.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package chouxianghua
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type pinyin struct {
|
||||
Word string `db:"word"`
|
||||
Pronun string `db:"pronunciation"`
|
||||
}
|
||||
type emoji struct {
|
||||
Pronun string `db:"pronunciation"`
|
||||
Emoji string `db:"emoji"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getPinyinByWord(word string) string {
|
||||
var p pinyin
|
||||
_ = db.Find("pinyin", &p, "where word = '"+word+"'")
|
||||
return p.Pronun
|
||||
}
|
||||
|
||||
func getPronunByDWord(w0, w1 rune) string {
|
||||
return getPinyinByWord(string(w0)) + getPinyinByWord(string(w1))
|
||||
}
|
||||
|
||||
func getEmojiByPronun(pronun string) string {
|
||||
var e emoji
|
||||
_ = db.Find("emoji", &e, "where pronunciation = '"+pronun+"'")
|
||||
return e.Emoji
|
||||
}
|
||||
@@ -2,59 +2,41 @@
|
||||
package coser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
var (
|
||||
engine = control.Register("coser", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "三次元小姐姐\n- coser\n",
|
||||
})
|
||||
prio = 20
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36"
|
||||
coserURL = "http://ovooa.com/API/cosplay/api.php"
|
||||
limit = rate.NewManager(time.Minute, 5)
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnFullMatch("coser", zero.OnlyGroup).SetBlock(true).SetPriority(prio).
|
||||
control.Register("coser", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "三次元小姐姐\n- coser",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.GroupID).Acquire() {
|
||||
ctx.SendChain(message.Text("请稍后重试0x0..."))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
data, err := web.ReqWith(coserURL, "GET", "", ua)
|
||||
data, err := web.GetDataWith(web.NewDefaultClient(), coserURL, "GET", "", ua)
|
||||
if err != nil {
|
||||
log.Println("err为:", err)
|
||||
}
|
||||
var m message.Message
|
||||
|
||||
text := gjson.Get(helper.BytesToString(data), "data.Title").String()
|
||||
m = append(m,
|
||||
message.CustomNode(
|
||||
ctx.Event.Sender.NickName,
|
||||
ctx.Event.UserID,
|
||||
text,
|
||||
))
|
||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(text))}
|
||||
gjson.Get(helper.BytesToString(data), "data.data").ForEach(func(_, value gjson.Result) bool {
|
||||
imgcq := `[CQ:image,file=` + value.String() + `]`
|
||||
m = append(m,
|
||||
message.CustomNode(
|
||||
ctx.Event.Sender.NickName,
|
||||
ctx.Event.UserID,
|
||||
imgcq),
|
||||
)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(value.String())))
|
||||
return true
|
||||
})
|
||||
|
||||
67
plugin/cpstory/cpstory.go
Normal file
67
plugin/cpstory/cpstory.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Package cpstory cp短打
|
||||
package cpstory
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cpstory", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "cp短打\n- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
|
||||
PublicDataFolder: "CpStory",
|
||||
})
|
||||
|
||||
go func() {
|
||||
dbpath := engine.DataFolder()
|
||||
db.DBPath = dbpath + "cp.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = file.GetLazyData(db.DBPath, false, true)
|
||||
err := db.Create("cp_story", &cpstory{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n, err := db.Count("cp_story")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Printf("[cpstory]读取%d条故事", n)
|
||||
}()
|
||||
|
||||
engine.OnRegex("^组cp.*?(\\d+).*?(\\d+)", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cs := getRandomCpStory()
|
||||
gong := ctxext.CardOrNickName(ctx, math.Str2Int64(ctx.State["regex_matched"].([]string)[1]))
|
||||
shou := ctxext.CardOrNickName(ctx, math.Str2Int64(ctx.State["regex_matched"].([]string)[2]))
|
||||
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
|
||||
text = strings.ReplaceAll(text, "<受>", shou)
|
||||
text = strings.ReplaceAll(text, cs.Gong, gong)
|
||||
text = strings.ReplaceAll(text, cs.Shou, gong)
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
engine.OnPrefix("磕cp").SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cs := getRandomCpStory()
|
||||
params := strings.Split(ctx.State["args"].(string), " ")
|
||||
if len(params) < 2 {
|
||||
ctx.SendChain(message.Text(ctx.Event.MessageID), message.Text("请用空格分开两个人名"))
|
||||
} else {
|
||||
gong := params[0]
|
||||
shou := params[1]
|
||||
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
|
||||
text = strings.ReplaceAll(text, "<受>", shou)
|
||||
text = strings.ReplaceAll(text, cs.Gong, gong)
|
||||
text = strings.ReplaceAll(text, cs.Shou, gong)
|
||||
ctx.SendChain(message.Text(text))
|
||||
}
|
||||
})
|
||||
}
|
||||
17
plugin/cpstory/model.go
Normal file
17
plugin/cpstory/model.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package cpstory
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type cpstory struct {
|
||||
ID int64 `db:"id"`
|
||||
Gong string `db:"gong"`
|
||||
Shou string `db:"shou"`
|
||||
Story string `db:"story"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getRandomCpStory() (cs cpstory) {
|
||||
_ = db.Pick("cp_story", &cs)
|
||||
return
|
||||
}
|
||||
61
plugin/curse/curse.go
Normal file
61
plugin/curse/curse.go
Normal file
@@ -0,0 +1,61 @@
|
||||
// Package curse 骂人插件(求骂,自卫)
|
||||
package curse
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
minLevel = "min"
|
||||
maxLevel = "max"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("curse", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: true,
|
||||
Help: "骂人(求骂,自卫)\n- 骂我\n- 大力骂我",
|
||||
PublicDataFolder: "Curse",
|
||||
})
|
||||
|
||||
go func() {
|
||||
dbpath := engine.DataFolder()
|
||||
db.DBPath = dbpath + "curse.db"
|
||||
_, err := file.GetLazyData(db.DBPath, false, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = db.Create("curse", &curse{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c, _ := db.Count("curse")
|
||||
logrus.Infoln("[curse]加载", c, "条骂人语录")
|
||||
}()
|
||||
|
||||
engine.OnFullMatch("骂我").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
text := getRandomCurseByLevel(minLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnFullMatch("大力骂我").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
text := getRandomCurseByLevel(maxLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnKeywordGroup([]string{"他妈", "公交车", "你妈", "操", "屎", "去死", "快死", "我日", "逼", "尼玛", "艾滋", "癌症", "有病", "烦你", "你爹", "屮", "cnm"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
text := getRandomCurseByLevel(maxLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
}
|
||||
16
plugin/curse/model.go
Normal file
16
plugin/curse/model.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package curse
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type curse struct {
|
||||
ID uint32 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
Level string `db:"level"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getRandomCurseByLevel(level string) (c curse) {
|
||||
_ = db.Find("curse", &c, "where level = '"+level+"' ORDER BY RANDOM() limit 1")
|
||||
return
|
||||
}
|
||||
56
plugin/danbooru/main.go
Normal file
56
plugin/danbooru/main.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Package deepdanbooru 二次元图片标签识别
|
||||
package deepdanbooru
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/danbooru"
|
||||
"github.com/FloatTech/AnimeAPI/saucenao"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("danbooru", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "二次元图片标签识别\n" +
|
||||
"- 鉴赏图片[图片]",
|
||||
PrivateDataFolder: "danbooru",
|
||||
})
|
||||
|
||||
cachefolder := engine.DataFolder()
|
||||
|
||||
// 上传一张图进行评价
|
||||
engine.OnKeywordGroup([]string{"鉴赏图片"}, zero.OnlyGroup, ctxext.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
for _, url := range ctx.State["image_url"].([]string) {
|
||||
name := ""
|
||||
r, err := saucenao.SauceNAO(url)
|
||||
if err != nil {
|
||||
name = "未知图片"
|
||||
} else {
|
||||
name = r[0].Title
|
||||
}
|
||||
t, err := danbooru.TagURL(name, url)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
digest := md5.Sum(helper.StringToBytes(url))
|
||||
f := cachefolder + hex.EncodeToString(digest[:])
|
||||
if file.IsNotExist(f) {
|
||||
_ = writer.SavePNG2Path(f, t)
|
||||
}
|
||||
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + f))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -2,31 +2,36 @@
|
||||
package diana
|
||||
|
||||
import (
|
||||
"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"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/diana/data"
|
||||
)
|
||||
|
||||
var engine *zero.Engine
|
||||
var engine = control.Register("diana", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "嘉然\n" +
|
||||
"- 小作文\n" +
|
||||
"- 发大病\n" +
|
||||
"- 教你一篇小作文[作文]\n" +
|
||||
"- [回复]查重",
|
||||
PublicDataFolder: "Diana",
|
||||
})
|
||||
|
||||
func init() {
|
||||
engine = control.Register("diana", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "嘉然\n" +
|
||||
"- 小作文\n" +
|
||||
"- 发大病\n" +
|
||||
"- 教你一篇小作文[作文]\n" +
|
||||
"- [回复]查重",
|
||||
})
|
||||
go func() {
|
||||
datapath := engine.DataFolder()
|
||||
dbfile := datapath + "text.db"
|
||||
data.LoadText(dbfile)
|
||||
}()
|
||||
|
||||
// 随机发送一篇上面的小作文
|
||||
engine.OnFullMatch("小作文").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
// 绕过第一行发病
|
||||
ctx.SendChain(message.Text(data.RandText()))
|
||||
})
|
||||
61
plugin/diana/data/text.go
Normal file
61
plugin/diana/data/text.go
Normal file
@@ -0,0 +1,61 @@
|
||||
// Package data 加载位于 datapath 的小作文
|
||||
package data
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
binutils "github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var db = sql.Sqlite{}
|
||||
|
||||
type text struct {
|
||||
ID int64 `db:"id"`
|
||||
Data string `db:"data"`
|
||||
}
|
||||
|
||||
// LoadText 加载小作文
|
||||
func LoadText(dbfile string) {
|
||||
_, err := file.GetLazyData(dbfile, false, false)
|
||||
db.DBPath = dbfile
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = db.Create("text", &text{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c, _ := db.Count("text")
|
||||
logrus.Printf("[Diana]读取%d条小作文", c)
|
||||
}
|
||||
|
||||
// AddText 添加小作文
|
||||
func AddText(txt string) error {
|
||||
s := md5.Sum(binutils.StringToBytes(txt))
|
||||
i := binary.LittleEndian.Uint64(s[:8])
|
||||
return db.Insert("text", &text{ID: int64(i), Data: txt})
|
||||
}
|
||||
|
||||
// RandText 随机小作文
|
||||
func RandText() string {
|
||||
var t text
|
||||
err := db.Pick("text", &t)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return t.Data
|
||||
}
|
||||
|
||||
// HentaiText 发大病
|
||||
func HentaiText() string {
|
||||
var t text
|
||||
err := db.Find("text", &t, "where id = -3802576048116006195")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return t.Data
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
@@ -33,8 +32,7 @@ func init() {
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := ctx.Event.Message
|
||||
if msg[0].Type == "reply" {
|
||||
id, _ := strconv.Atoi(msg[0].Data["id"])
|
||||
msg := ctx.GetMessage(int64(id)).Elements[0].Data["text"]
|
||||
msg := ctx.GetMessage(message.NewMessageID(msg[0].Data["id"])).Elements[0].Data["text"]
|
||||
zhiwangjson := zhiwangapi(msg)
|
||||
|
||||
if zhiwangjson == nil || zhiwangjson.Code != 0 {
|
||||
53
plugin/drift_bottle/data.go
Normal file
53
plugin/drift_bottle/data.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package driftbottle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc64"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
)
|
||||
|
||||
type bottle struct {
|
||||
ID int64 `db:"id"` // ID qq_grp_name_msg 的 crc64
|
||||
QQ int64 `db:"qq"` // QQ 发送者 qq
|
||||
Grp int64 `db:"grp"` // Grp 限制抽出的群 / 人(负数)
|
||||
Name string `db:"name"` // Name 发送者 昵称
|
||||
Msg string `db:"msg"` // Msg 消息,纯文本
|
||||
}
|
||||
|
||||
var sea = &sql.Sqlite{}
|
||||
var seamu sync.RWMutex
|
||||
|
||||
func newBottle(qq, grp int64, name, msg string) *bottle {
|
||||
id := int64(crc64.Checksum(binary.StringToBytes(fmt.Sprintf("%d_%d_%s_%s", qq, grp, name, msg)), crc64.MakeTable(crc64.ISO)))
|
||||
return &bottle{ID: id, QQ: qq, Grp: grp, Name: name, Msg: msg}
|
||||
}
|
||||
|
||||
func (b *bottle) throw(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Insert(channel, b)
|
||||
}
|
||||
|
||||
func (b *bottle) destroy(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Del(channel, "WHERE id="+strconv.FormatInt(b.ID, 10))
|
||||
}
|
||||
|
||||
// fetchBottle grp != 0
|
||||
func fetchBottle(db *sql.Sqlite, channel string, grp int64) (*bottle, error) {
|
||||
seamu.RLock()
|
||||
defer seamu.RUnlock()
|
||||
b := new(bottle)
|
||||
return b, db.Find(channel, b, "WHERE grp=0 or grp="+strconv.FormatInt(grp, 10)+" ORDER BY RANDOM() limit 1")
|
||||
}
|
||||
|
||||
func createChannel(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Create(channel, &bottle{})
|
||||
}
|
||||
133
plugin/drift_bottle/main.go
Normal file
133
plugin/drift_bottle/main.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// Package driftbottle 漂流瓶
|
||||
package driftbottle
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("driftbottle", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "漂流瓶\n- (在群xxx)丢漂流瓶(到频道xxx) [消息]\n- (从频道xxx)捡漂流瓶\n- @BOT 创建频道 xxx\n- 跳入(频道)海中\n- 注:不显式限制时,私聊发送可在所有群抽到,群聊发送仅可在本群抽到,默认频道为 global",
|
||||
PrivateDataFolder: "driftbottle",
|
||||
})
|
||||
sea.DBPath = en.DataFolder() + "sea.db"
|
||||
err := sea.Open()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = createChannel(sea, "global")
|
||||
en.OnRegex(`^(在群\d+)?丢漂流瓶(到频道\w+)?\s+(.*)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
grp := ctx.Event.GroupID
|
||||
channel := "global"
|
||||
msg := msgs[3]
|
||||
var err error
|
||||
if msgs[1] != "" {
|
||||
grp, err = strconv.ParseInt(msgs[1][6:], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("群号非法!"))
|
||||
return
|
||||
}
|
||||
}
|
||||
if msgs[2] != "" {
|
||||
channel = msgs[2][9:]
|
||||
}
|
||||
if msg == "" {
|
||||
ctx.SendChain(message.Text("消息为空!"))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[driftbottle]", grp, channel, msg)
|
||||
err = newBottle(
|
||||
ctx.Event.UserID,
|
||||
grp,
|
||||
ctxext.CardOrNickName(ctx, ctx.Event.UserID),
|
||||
msg,
|
||||
).throw(sea, channel)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你将它扔进大海,希望有人捞到吧~")))
|
||||
})
|
||||
en.OnRegex(`^(从频道\w+)?捡漂流瓶$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
grp = -ctx.Event.UserID
|
||||
}
|
||||
if grp == 0 {
|
||||
ctx.SendChain(message.Text("找不到对象!"))
|
||||
return
|
||||
}
|
||||
channel := "global"
|
||||
if msgs[1] != "" {
|
||||
channel = msgs[1][9:]
|
||||
}
|
||||
logrus.Debugln("[driftbottle]", grp, channel)
|
||||
b, err := fetchBottle(sea, channel, grp)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err = b.destroy(sea, channel)
|
||||
wg.Done()
|
||||
}()
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(
|
||||
ctx.Event.MessageID,
|
||||
message.Text("你在海边捡到了一个来自 ", b.Name, " 的漂流瓶,打开瓶子,里面有一张纸条,写着:"),
|
||||
message.Text(b.Msg),
|
||||
),
|
||||
)
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
en.OnPrefix("创建频道", zero.SuperUserPermission, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
channel := strings.TrimRight(ctx.State["args"].(string), " ")
|
||||
if channel == "" {
|
||||
ctx.SendChain(message.Text("频道名为空!"))
|
||||
return
|
||||
}
|
||||
err := createChannel(sea, channel)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("成功~")))
|
||||
})
|
||||
en.OnRegex(`^跳入(\w+)?海中$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
channel := "global"
|
||||
if msgs[1] != "" {
|
||||
channel = msgs[1]
|
||||
}
|
||||
seamu.RLock()
|
||||
c, err := sea.Count(channel)
|
||||
seamu.RUnlock()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你缓缓走入大海,感受着海浪轻柔地拍打着你的小腿,膝盖……\n波浪卷着你的腰腹,你感觉有些把握不住平衡了……\n……\n你沉入海中,", c, " 个物体与你一同沉浮。\n不知何处涌来一股暗流,你失去了意识。")))
|
||||
})
|
||||
}
|
||||
249
plugin/emojimix/emoji.go
Normal file
249
plugin/emojimix/emoji.go
Normal file
@@ -0,0 +1,249 @@
|
||||
// Package emojimix 合成emoji
|
||||
package emojimix
|
||||
|
||||
var emojis = map[rune]int64{
|
||||
128516: 20201001, // 😄 grinning face with smiling eyes
|
||||
128512: 20201001, // 😀 grinning face
|
||||
128578: 20201001, // 🙂 slightly smiling face
|
||||
128579: 20201001, // 🙃 upside-down face
|
||||
128521: 20201001, // 😉 winking face
|
||||
128522: 20201001, // 😊 smiling face with smiling eyes
|
||||
128518: 20201001, // 😆 grinning squinting face
|
||||
128515: 20201001, // 😃 grinning face with big eyes
|
||||
128513: 20201001, // 😁 beaming face with smiling eyes
|
||||
129315: 20201001, // 🤣 rolling on the floor laughing
|
||||
128517: 20201001, // 😅 grinning face with sweat
|
||||
128514: 20201001, // 😂 face with tears of joy
|
||||
128519: 20201001, // 😇 smiling face with halo
|
||||
129392: 20201001, // 🥰 smiling face with hearts
|
||||
128525: 20201001, // 😍 smiling face with heart-eyes
|
||||
128536: 20201001, // 😘 face blowing a kiss
|
||||
129321: 20201001, // 🤩 star-struck
|
||||
128535: 20201001, // 😗 kissing face
|
||||
128538: 20201001, // 😚 kissing face with closed eyes
|
||||
128537: 20201001, // 😙 kissing face with smiling eyes
|
||||
128539: 20201001, // 😛 face with tongue
|
||||
128541: 20201001, // 😝 squinting face with tongue
|
||||
128523: 20201001, // 😋 face savoring food
|
||||
129394: 20201001, // 🥲 smiling face with tear
|
||||
129297: 20201001, // 🤑 money-mouth face
|
||||
128540: 20201001, // 😜 winking face with tongue
|
||||
129303: 20201001, // 🤗 smiling face with open hands hugs
|
||||
129323: 20201001, // 🤫 shushing face quiet whisper
|
||||
129300: 20201001, // 🤔 thinking face question hmmm
|
||||
129325: 20201001, // 🤭 face with hand over mouth embarrassed
|
||||
129320: 20201001, // 🤨 face with raised eyebrow question
|
||||
129296: 20201001, // 🤐 zipper-mouth face
|
||||
128528: 20201001, // 😐 neutral face
|
||||
128529: 20201001, // 😑 expressionless face
|
||||
128566: 20201001, // 😶 face without mouth
|
||||
129322: 20201001, // 🤪 zany face
|
||||
128527: 20201001, // 😏 smirking face suspicious
|
||||
128530: 20201001, // 😒 unamused face
|
||||
128580: 20201001, // 🙄 face with rolling eyes
|
||||
128556: 20201001, // 😬 grimacing face
|
||||
128558: 20210218, // 😮 face exhaling
|
||||
129317: 20201001, // 🤥 lying face
|
||||
128524: 20201001, // 😌 relieved face
|
||||
128532: 20201001, // 😔 pensive face
|
||||
128554: 20201001, // 😪 sleepy face
|
||||
129316: 20201001, // 🤤 drooling face
|
||||
128564: 20201001, // 😴 sleeping face
|
||||
128567: 20201001, // 😷 face with medical mask
|
||||
129298: 20201001, // 🤒 face with thermometer
|
||||
129301: 20201001, // 🤕 face with head-bandage
|
||||
129314: 20201001, // 🤢 nauseated face
|
||||
129326: 20201001, // 🤮 face vomiting throw
|
||||
129319: 20201001, // 🤧 sneezing face
|
||||
129397: 20201001, // 🥵 hot face warm
|
||||
129398: 20201001, // 🥶 cold face freezing ice
|
||||
128565: 20201001, // 😵 face with crossed-out eyes
|
||||
129396: 20201001, // 🥴 woozy face drunk tipsy drug high
|
||||
129327: 20201001, // 🤯 exploding head mindblow
|
||||
129312: 20201001, // 🤠 cowboy hat face
|
||||
129395: 20201001, // 🥳 partying face
|
||||
129400: 20201001, // 🥸 disguised face
|
||||
129488: 20201001, // 🧐 face with monocle glasses
|
||||
128526: 20201001, // 😎 smiling face with sunglasses
|
||||
128533: 20201001, // 😕 confused face
|
||||
128543: 20201001, // 😟 worried face
|
||||
128577: 20201001, // 🙁 slightly frowning face
|
||||
128559: 20201001, // 😯 hushed face
|
||||
128562: 20201001, // 😲 astonished face
|
||||
129299: 20201001, // 🤓 nerd face glasses
|
||||
128563: 20201001, // 😳 flushed face
|
||||
129402: 20201001, // 🥺 pleading face
|
||||
128551: 20201001, // 😧 anguished face
|
||||
128552: 20201001, // 😨 fearful face
|
||||
128550: 20201001, // 😦 frowning face with open mouth
|
||||
128560: 20201001, // 😰 anxious face with sweat
|
||||
128549: 20201001, // 😥 sad but relieved face
|
||||
128557: 20201001, // 😭 loudly crying face
|
||||
128553: 20201001, // 😩 weary face
|
||||
128546: 20201001, // 😢 crying face
|
||||
128547: 20201001, // 😣 persevering face
|
||||
128544: 20201001, // 😠 angry face
|
||||
128531: 20201001, // 😓 downcast face with sweat
|
||||
128534: 20201001, // 😖 confounded face
|
||||
129324: 20201001, // 🤬 face with symbols on mouth
|
||||
128542: 20201001, // 😞 disappointed face
|
||||
128555: 20201001, // 😫 tired face
|
||||
128548: 20201001, // 😤 face with steam from nose
|
||||
129393: 20201001, // 🥱 yawning face
|
||||
128169: 20201001, // 💩 pile of poo
|
||||
128545: 20201001, // 😡 pouting face
|
||||
128561: 20201001, // 😱 face screaming in fear
|
||||
128127: 20201001, // 👿 angry face with horns
|
||||
128128: 20201001, // 💀 skull
|
||||
128125: 20201001, // 👽 alien
|
||||
128520: 20201001, // 😈 smiling face with horns devil
|
||||
129313: 20201001, // 🤡 clown face
|
||||
128123: 20201001, // 👻 ghost
|
||||
129302: 20201001, // 🤖 robot
|
||||
128175: 20201001, // 💯 hundred points percent
|
||||
128064: 20201001, // 👀 eyes
|
||||
127801: 20201001, // 🌹 rose flower
|
||||
127804: 20201001, // 🌼 blossom flower
|
||||
127799: 20201001, // 🌷 tulip flower
|
||||
127797: 20201001, // 🌵 cactus
|
||||
127821: 20201001, // 🍍 pineapple
|
||||
127874: 20201001, // 🎂 birthday cake
|
||||
127751: 20210831, // 🌇 sunset
|
||||
129473: 20201001, // 🧁 cupcake muffin
|
||||
127911: 20210521, // 🎧 headphone earphone
|
||||
127800: 20210218, // 🌸 cherry blossom flower
|
||||
129440: 20201001, // 🦠 microbe germ bacteria virus covid corona
|
||||
128144: 20201001, // 💐 bouquet flowers
|
||||
127789: 20201001, // 🌭 hot dog food
|
||||
128139: 20201001, // 💋 kiss mark lips
|
||||
127875: 20201001, // 🎃 jack-o-lantern pumpkin
|
||||
129472: 20201001, // 🧀 cheese wedge
|
||||
9749: 20201001, // ☕ hot beverage coffee cup tea
|
||||
127882: 20201001, // 🎊 confetti ball
|
||||
127880: 20201001, // 🎈 balloon
|
||||
9924: 20201001, // ⛄ snowman without snow
|
||||
128142: 20201001, // 💎 gem stone crystal diamond
|
||||
127794: 20201001, // 🌲 evergreen tree
|
||||
129410: 20210218, // 🦂 scorpion
|
||||
128584: 20201001, // 🙈 see-no-evil monkey
|
||||
128148: 20201001, // 💔 broken heart
|
||||
128140: 20201001, // 💌 love letter heart
|
||||
128152: 20201001, // 💘 heart with arrow
|
||||
128159: 20201001, // 💟 heart decoration
|
||||
128158: 20201001, // 💞 revolving hearts
|
||||
128147: 20201001, // 💓 beating heart
|
||||
128149: 20201001, // 💕 two hearts
|
||||
128151: 20201001, // 💗 growing heart
|
||||
129505: 20201001, // 🧡 orange heart
|
||||
128155: 20201001, // 💛 yellow heart
|
||||
10084: 20210218, // ❤ mending heart
|
||||
128156: 20201001, // 💜 purple heart
|
||||
128154: 20201001, // 💚 green heart
|
||||
128153: 20201001, // 💙 blue heart
|
||||
129294: 20201001, // 🤎 brown heart
|
||||
129293: 20201001, // 🤍 white heart
|
||||
128420: 20201001, // 🖤 black heart
|
||||
128150: 20201001, // 💖 sparkling heart
|
||||
128157: 20201001, // 💝 heart with ribbon
|
||||
127873: 20211115, // 🎁 wrapped-gift
|
||||
129717: 20211115, // 🪵 wood
|
||||
127942: 20211115, // 🏆 trophy
|
||||
127838: 20210831, // 🍞 bread
|
||||
128240: 20201001, // 📰 newspaper
|
||||
128302: 20201001, // 🔮 crystal ball
|
||||
128081: 20201001, // 👑 crown
|
||||
128055: 20201001, // 🐷 pig face
|
||||
129412: 20210831, // 🦄 unicorn
|
||||
127771: 20201001, // 🌛 first quarter moon face
|
||||
129420: 20201001, // 🦌 deer
|
||||
129668: 20210521, // 🪄 magic wand
|
||||
128171: 20201001, // 💫 dizzy
|
||||
128049: 20201001, // 🐱 meow cat face
|
||||
129409: 20201001, // 🦁 lion
|
||||
128293: 20201001, // 🔥 fire
|
||||
128038: 20210831, // 🐦 bird
|
||||
129415: 20201001, // 🦇 bat
|
||||
129417: 20210831, // 🦉 owl
|
||||
127752: 20201001, // 🌈 rainbow
|
||||
128053: 20201001, // 🐵 monkey face
|
||||
128029: 20201001, // 🐝 honeybee bumblebee wasp
|
||||
128034: 20201001, // 🐢 turtle
|
||||
128025: 20201001, // 🐙 octopus
|
||||
129433: 20201001, // 🦙 llama alpaca
|
||||
128016: 20210831, // 🐐 goat
|
||||
128060: 20201001, // 🐼 panda
|
||||
128040: 20201001, // 🐨 koala
|
||||
129445: 20201001, // 🦥 sloth
|
||||
128059: 20210831, // 🐻 bear
|
||||
128048: 20201001, // 🐰 rabbit face
|
||||
129428: 20201001, // 🦔 hedgehog
|
||||
128054: 20211115, // 🐶 dog puppy
|
||||
128041: 20211115, // 🐩 poodle dog
|
||||
129437: 20211115, // 🦝 raccoon
|
||||
128039: 20211115, // 🐧 penguin
|
||||
128012: 20210218, // 🐌 snail
|
||||
128045: 20201001, // 🐭 mouse face rat
|
||||
128031: 20210831, // 🐟 fish
|
||||
127757: 20201001, // 🌍 globe showing Europe-Africa
|
||||
127774: 20201001, // 🌞 sun with face
|
||||
127775: 20201001, // 🌟 glowing star
|
||||
11088: 20201001, // ⭐ star
|
||||
127772: 20201001, // 🌜 last quarter moon face
|
||||
129361: 20201001, // 🥑 avocado
|
||||
127820: 20211115, // 🍌 banana
|
||||
127827: 20210831, // 🍓 strawberry
|
||||
127819: 20210521, // 🍋 lemon
|
||||
127818: 20211115, // 🍊 tangerine orange
|
||||
}
|
||||
|
||||
var qqface = map[int]rune{
|
||||
0: 128558, // 😮 face exhaling
|
||||
1: 128556, // 😬 grimacing face
|
||||
2: 128525, // 😍 smiling face with heart-eyes
|
||||
4: 128526, // 😎 smiling face with sunglasses
|
||||
5: 128557, // 😭 loudly crying face
|
||||
6: 129402, // 🥺 pleading face
|
||||
7: 129296, // 🤐 zipper-mouth face
|
||||
8: 128554, // 😪 sleepy face
|
||||
11: 128545, // 😡 pouting face
|
||||
12: 128539, // 😛 face with tongue
|
||||
13: 128513, // 😁 beaming face with smiling eyes
|
||||
14: 128578, // 🙂 slightly smiling face
|
||||
15: 128577, // 🙁 slightly frowning face
|
||||
16: 128526, // 😎 smiling face with sunglasses
|
||||
19: 129326, // 🤮 face vomiting throw
|
||||
20: 129325, // 🤭 face with hand over mouth embarrassed
|
||||
21: 128522, // 😊 smiling face with smiling eyes
|
||||
23: 128533, // 😕 confused face
|
||||
24: 128523, // 😋 face savoring food
|
||||
27: 128531, // 😓 downcast face with sweat
|
||||
28: 128516, // 😄 grinning face with smiling eyes
|
||||
31: 129324, // 🤬 face with symbols on mouth
|
||||
32: 129300, // 🤔 thinking face question hmmm
|
||||
33: 129323, // 🤫 shushing face quiet whisper
|
||||
34: 128565, // 😵 face with crossed-out eyes
|
||||
35: 128547, // 😣 persevering face
|
||||
37: 128128, // 💀 skull
|
||||
46: 128055, // 🐷 pig face
|
||||
53: 127874, // 🎂 birthday cake
|
||||
59: 128169, // 💩 pile of poo
|
||||
60: 9749, // ☕ hot beverage coffee cup tea
|
||||
63: 127801, // 🌹 rose flower
|
||||
66: 10084, // ❤ mending heart
|
||||
67: 128148, // 💔 broken heart
|
||||
69: 127873, // 🎁 wrapped-gift
|
||||
74: 127774, // 🌞 sun with face
|
||||
75: 127772, // 🌜 last quarter moon face
|
||||
96: 128517, // 😅 grinning face with sweat
|
||||
104: 129393, // 🥱 yawning face
|
||||
109: 128535, // 😗 kissing face
|
||||
110: 128562, // 😲 astonished face
|
||||
111: 129402, // 🥺 pleading face
|
||||
172: 128539, // 😛 face with tongue
|
||||
182: 128514, // 😂 face with tears of joy
|
||||
187: 128123, // 👻 ghost
|
||||
247: 128567, // 😷 face with medical mask
|
||||
272: 128579, // 🙃 upside-down face
|
||||
320: 129395, // 🥳 partying face
|
||||
325: 128561, // 😱 face screaming in fear
|
||||
}
|
||||
101
plugin/emojimix/mix.go
Normal file
101
plugin/emojimix/mix.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Package emojimix 合成emoji
|
||||
package emojimix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%x.png"
|
||||
|
||||
func init() {
|
||||
control.Register("emojimix", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "合成emoji\n" +
|
||||
"- [emoji][emoji]",
|
||||
}).OnMessage(match).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
r := ctx.State["emojimix"].([]rune)
|
||||
logrus.Debugln("[emojimix] match:", r)
|
||||
r1, r2 := r[0], r[1]
|
||||
u1 := fmt.Sprintf(bed, emojis[r1], r1, r1, r2)
|
||||
u2 := fmt.Sprintf(bed, emojis[r2], r2, r2, r1)
|
||||
logrus.Debugln("[emojimix] u1:", u1)
|
||||
logrus.Debugln("[emojimix] u2:", u2)
|
||||
resp1, err := http.Head(u1)
|
||||
if err == nil {
|
||||
resp1.Body.Close()
|
||||
if resp1.StatusCode == http.StatusOK {
|
||||
ctx.SendChain(message.Image(u1))
|
||||
return
|
||||
}
|
||||
}
|
||||
resp2, err := http.Head(u2)
|
||||
if err == nil {
|
||||
resp2.Body.Close()
|
||||
if resp2.StatusCode == http.StatusOK {
|
||||
ctx.SendChain(message.Image(u2))
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func match(ctx *zero.Ctx) bool {
|
||||
logrus.Debugln("[emojimix] msg:", ctx.Event.Message)
|
||||
if len(ctx.Event.Message) == 2 {
|
||||
r1 := face2emoji(ctx.Event.Message[0])
|
||||
if _, ok := emojis[r1]; !ok {
|
||||
return false
|
||||
}
|
||||
r2 := face2emoji(ctx.Event.Message[1])
|
||||
if _, ok := emojis[r2]; !ok {
|
||||
return false
|
||||
}
|
||||
ctx.State["emojimix"] = []rune{r1, r2}
|
||||
return true
|
||||
}
|
||||
|
||||
r := []rune(ctx.Event.RawMessage)
|
||||
logrus.Debugln("[emojimix] raw msg:", ctx.Event.RawMessage)
|
||||
if len(r) == 2 {
|
||||
if _, ok := emojis[r[0]]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := emojis[r[1]]; !ok {
|
||||
return false
|
||||
}
|
||||
ctx.State["emojimix"] = r
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func face2emoji(face message.MessageSegment) rune {
|
||||
if face.Type == "text" {
|
||||
r := []rune(face.Data["text"])
|
||||
if len(r) != 1 {
|
||||
return 0
|
||||
}
|
||||
return r[0]
|
||||
}
|
||||
if face.Type != "face" {
|
||||
return 0
|
||||
}
|
||||
id, err := strconv.Atoi(face.Data["id"])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if r, ok := qqface[id]; ok {
|
||||
return r
|
||||
}
|
||||
return 0
|
||||
}
|
||||
123
plugin/epidemic/epidemic.go
Normal file
123
plugin/epidemic/epidemic.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Package epidemic 城市疫情查询
|
||||
package epidemic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
const (
|
||||
servicename = "epidemic"
|
||||
txurl = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5"
|
||||
)
|
||||
|
||||
// result 疫情查询结果
|
||||
type result struct {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
// epidemic 疫情数据
|
||||
type epidemic struct {
|
||||
LastUpdateTime string `json:"lastUpdateTime"`
|
||||
AreaTree []*area `json:"areaTree"`
|
||||
}
|
||||
|
||||
// area 城市疫情数据
|
||||
type area struct {
|
||||
Name string `json:"name"`
|
||||
Today struct {
|
||||
Confirm int `json:"confirm"`
|
||||
} `json:"today"`
|
||||
Total struct {
|
||||
NowConfirm int `json:"nowConfirm"`
|
||||
Confirm int `json:"confirm"`
|
||||
Dead int `json:"dead"`
|
||||
Heal int `json:"heal"`
|
||||
Grade string `json:"grade"`
|
||||
} `json:"total"`
|
||||
Children []*area `json:"children"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
engine := control.Register(servicename, order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "城市疫情查询\n" +
|
||||
"- xxx疫情\n",
|
||||
})
|
||||
engine.OnSuffix("疫情").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
city := ctx.State["args"].(string)
|
||||
if city == "" {
|
||||
ctx.SendChain(message.Text("你还没有输入城市名字呢!"))
|
||||
return
|
||||
}
|
||||
data, time, err := queryEpidemic(city)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if data == nil {
|
||||
ctx.SendChain(message.Text("没有找到【", city, "】城市的疫情数据."))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
"【", data.Name, "】疫情数据\n",
|
||||
"新增:", data.Today.Confirm, " ,",
|
||||
"现有确诊:", data.Total.NowConfirm, " ,",
|
||||
"治愈:", data.Total.Heal, " ,",
|
||||
"死亡:", data.Total.Dead, " ", data.Total.Grade, "\n",
|
||||
"更新时间:", time, "\n",
|
||||
"温馨提示:请大家做好防疫工作,出门带好口罩!",
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// rcity 查找城市
|
||||
func rcity(a *area, cityName string) *area {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
if a.Name == cityName {
|
||||
return a
|
||||
}
|
||||
for _, v := range a.Children {
|
||||
if v.Name == cityName {
|
||||
return v
|
||||
}
|
||||
c := rcity(v, cityName)
|
||||
if c != nil {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryEpidemic 查询城市疫情
|
||||
func queryEpidemic(findCityName string) (citydata *area, times string, err error) {
|
||||
data, err := web.GetData(txurl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var r result
|
||||
err = json.Unmarshal(data, &r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var e epidemic
|
||||
err = json.Unmarshal(binary.StringToBytes(r.Data), &e)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
citydata = rcity(e.AreaTree[0], findCityName)
|
||||
return citydata, e.LastUpdateTime, nil
|
||||
}
|
||||
261
plugin/fortune/fortune.go
Normal file
261
plugin/fortune/fortune.go
Normal file
@@ -0,0 +1,261 @@
|
||||
// Package fortune 每日运势
|
||||
package fortune
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"image"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fogleman/gg" // 注册了 jpg png gif
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
// 底图缓存位置
|
||||
images = "data/Fortune/"
|
||||
// 基础文件位置
|
||||
omikujson = "data/Fortune/text.json"
|
||||
// 字体文件位置
|
||||
font = "data/Font/sakura.ttf"
|
||||
// 生成图缓存位置
|
||||
cache = images + "cache/"
|
||||
)
|
||||
|
||||
var (
|
||||
// 底图类型列表
|
||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录"}
|
||||
// 映射底图与 index
|
||||
index = make(map[string]uint8)
|
||||
// 签文
|
||||
omikujis []map[string]string
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 插件主体
|
||||
en := control.Register("fortune", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "每日运势: \n" +
|
||||
"- 运势 | 抽签\n" +
|
||||
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录]",
|
||||
PublicDataFolder: "Fortune",
|
||||
})
|
||||
go func() {
|
||||
for i, s := range table {
|
||||
index[s] = uint8(i)
|
||||
}
|
||||
_ = os.RemoveAll(cache)
|
||||
err := os.MkdirAll(cache, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data, err := file.GetLazyData(omikujson, true, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = json.Unmarshal(data, &omikujis)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = file.GetLazyData(font, false, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
en.OnRegex(`^设置底图\s?(.*)`).SetBlock(true).
|
||||
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 {
|
||||
c, ok := control.Lookup("fortune")
|
||||
if ok {
|
||||
err := c.SetData(gid, int64(i)&0xff)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("设置失败:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置成功~"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置失败: 找不到插件"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("没有这个底图哦~"))
|
||||
})
|
||||
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 获取该群背景类型,默认车万
|
||||
kind := "车万"
|
||||
gid := ctx.Event.GroupID
|
||||
if gid <= 0 {
|
||||
// 个人用户设为负数
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
logrus.Debugln("[fortune]gid:", ctx.Event.GroupID, "uid:", ctx.Event.UserID)
|
||||
c, ok := control.Lookup("fortune")
|
||||
if ok {
|
||||
v := uint8(c.GetData(gid) & 0xff)
|
||||
if int(v) < len(table) {
|
||||
kind = table[v]
|
||||
}
|
||||
}
|
||||
// 检查背景图片是否存在
|
||||
zipfile := images + kind + ".zip"
|
||||
_, err := file.GetLazyData(zipfile, false, false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
|
||||
// 生成种子
|
||||
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
|
||||
seed := ctx.Event.UserID + t
|
||||
|
||||
// 随机获取背景
|
||||
background, index, err := randimage(zipfile, seed)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
|
||||
// 随机获取签文
|
||||
title, text := randtext(seed)
|
||||
digest := md5.Sum(helper.StringToBytes(zipfile + strconv.Itoa(index) + title + text))
|
||||
cachefile := cache + hex.EncodeToString(digest[:])
|
||||
|
||||
err = pool.SendImageFromPool(cachefile, cachefile, func() error {
|
||||
f, err := os.Create(cachefile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = draw(background, title, text, f)
|
||||
_ = f.Close()
|
||||
return err
|
||||
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// @function randimage 随机选取zip内的文件
|
||||
// @param path zip路径
|
||||
// @param seed 随机数种子
|
||||
// @return 文件路径 & 错误信息
|
||||
func randimage(path string, seed int64) (im image.Image, index int, err error) {
|
||||
reader, err := zip.OpenReader(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
index = r.Intn(len(reader.File))
|
||||
file := reader.File[index]
|
||||
f, err := file.Open()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
im, _, err = image.Decode(f)
|
||||
return
|
||||
}
|
||||
|
||||
// @function randtext 随机选取签文
|
||||
// @param file 文件路径
|
||||
// @param seed 随机数种子
|
||||
// @return 签名 & 签文 & 错误信息
|
||||
func randtext(seed int64) (string, string) {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
i := r.Intn(len(omikujis))
|
||||
return omikujis[i]["title"], omikujis[i]["content"]
|
||||
}
|
||||
|
||||
// @function draw 绘制运势图
|
||||
// @param background 背景图片路径
|
||||
// @param seed 随机数种子
|
||||
// @param title 签名
|
||||
// @param text 签文
|
||||
// @return 错误信息
|
||||
func draw(back image.Image, title, txt string, f io.Writer) (int64, error) {
|
||||
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(font, 45); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
sw, _ := canvas.MeasureString(title)
|
||||
canvas.DrawString(title, 140-sw/2, 112)
|
||||
// 写正文
|
||||
canvas.SetRGB(0, 0, 0)
|
||||
if err := canvas.LoadFontFace(font, 23); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
tw, th := canvas.MeasureString("测")
|
||||
tw, th = tw+10, th+10
|
||||
r := []rune(txt)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
return writer.WriteTo(canvas.Image(), f)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
60
plugin/funny/laugh.go
Normal file
60
plugin/funny/laugh.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// Package funny 冷笑话
|
||||
package funny
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
type joke struct {
|
||||
ID uint32 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func init() {
|
||||
en := control.Register("funny", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "讲个笑话\n" +
|
||||
"- 讲个笑话[@xxx] | 讲个笑话[qq号]",
|
||||
PublicDataFolder: "Funny",
|
||||
})
|
||||
|
||||
go func() {
|
||||
dbpath := en.DataFolder()
|
||||
db.DBPath = dbpath + "jokes.db"
|
||||
_, err := file.GetLazyData(db.DBPath, false, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = db.Create("jokes", &joke{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c, _ := db.Count("jokes")
|
||||
logrus.Infoln("[funny]加载", c, "个笑话")
|
||||
}()
|
||||
|
||||
en.OnPrefix("讲个笑话").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
// 获取名字
|
||||
name := ctxext.NickName(ctx)
|
||||
var j joke
|
||||
err := db.Pick("jokes", &j)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(strings.ReplaceAll(j.Text, "%name", name)))
|
||||
})
|
||||
}
|
||||
31
plugin/gif/README.md
Normal file
31
plugin/gif/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# ZeroBot-Plugin-Gif
|
||||
[ZeroBot QQ机器人](https://github.com/wdvxdr1123/ZeroBot)插件,可以制作各种沙雕gif图
|
||||
> 素材包地址: https://codechina.csdn.net/u011570312/imagematerials
|
||||
|
||||
## 触发方式
|
||||
1. [指令词]+[qq号] 如:爬123456
|
||||
2. [指令词]+[图片] 如:爬[图片]
|
||||
3. [指令词]+[艾特] 如:爬@小H
|
||||
|
||||
## 指令列表
|
||||
- [x] 爬
|
||||
- [x] 冲
|
||||
- [x] 摸
|
||||
- [x] 搓
|
||||
- [x] 拍
|
||||
- [x] 丢
|
||||
- [x] 敲
|
||||
- [x] 吃
|
||||
- [x] 啃
|
||||
- [x] 撕
|
||||
- [x] 蹭
|
||||
- [x] 灰度
|
||||
- [x] 上翻
|
||||
- [x] 下翻
|
||||
- [x] 左翻
|
||||
- [x] 右翻
|
||||
- [x] 反色
|
||||
- [x] 倒放
|
||||
- [x] 浮雕
|
||||
- [x] 打码
|
||||
- [x] 负片
|
||||
85
plugin/gif/context.go
Normal file
85
plugin/gif/context.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type context struct {
|
||||
usrdir string
|
||||
headimgsdir []string
|
||||
}
|
||||
|
||||
func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
|
||||
defer wg.Done()
|
||||
target := datapath + `materials/` + name
|
||||
var err error
|
||||
if file.IsNotExist(target) {
|
||||
err = file.DownloadTo(`https://codechina.csdn.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
|
||||
} else {
|
||||
logrus.Debugln("[gif] dl", name, "exists at", target)
|
||||
}
|
||||
*s = target
|
||||
}
|
||||
|
||||
func dlblock(name string) (string, error) {
|
||||
target := datapath + `materials/` + name
|
||||
if file.IsNotExist(target) {
|
||||
err := file.DownloadTo(`https://codechina.csdn.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
|
||||
} else {
|
||||
logrus.Debugln("[gif] dl", name, "exists at", target)
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func dlrange(prefix string, end int, wg *sync.WaitGroup, exit func(error)) []string {
|
||||
if file.IsNotExist(datapath + `materials/` + prefix) {
|
||||
err := os.MkdirAll(datapath+`materials/`+prefix, 0755)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
c := make([]string, end)
|
||||
for i := range c {
|
||||
wg.Add(1)
|
||||
go dlchan(prefix+"/"+strconv.Itoa(i)+".png", &c[i], wg, exit)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// 新的上下文
|
||||
func newContext(user int64) *context {
|
||||
c := new(context)
|
||||
c.usrdir = datapath + "users/" + strconv.FormatInt(user, 10) + `/`
|
||||
_ = os.MkdirAll(c.usrdir, 0755)
|
||||
c.headimgsdir = make([]string, 2)
|
||||
c.headimgsdir[0] = c.usrdir + "0.gif"
|
||||
c.headimgsdir[1] = c.usrdir + "1.gif"
|
||||
return c
|
||||
}
|
||||
|
||||
func loadFirstFrames(paths []string, size int) (imgs []*img.ImgFactory, err error) {
|
||||
imgs = make([]*img.ImgFactory, size)
|
||||
for i := range imgs {
|
||||
imgs[i], err = img.LoadFirstFrame(paths[i], 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return imgs, nil
|
||||
}
|
||||
345
plugin/gif/gif.go
Normal file
345
plugin/gif/gif.go
Normal file
@@ -0,0 +1,345 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"image"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
)
|
||||
|
||||
// A摸
|
||||
func (cc *context) A摸() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "摸.gif"
|
||||
c := dlrange("mo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 5)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
mo := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 80, 80, 32, 32).Im,
|
||||
imgs[1].InsertBottom(tou, 70, 90, 42, 22).Im,
|
||||
imgs[2].InsertBottom(tou, 75, 85, 37, 27).Im,
|
||||
imgs[3].InsertBottom(tou, 85, 75, 27, 37).Im,
|
||||
imgs[4].InsertBottom(tou, 90, 70, 22, 42).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, mo))
|
||||
}
|
||||
|
||||
// A搓
|
||||
func (cc *context) A搓() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "搓.gif"
|
||||
c := dlrange("cuo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(110, 110)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
m1 := img.Rotate(tou, 72, 0, 0)
|
||||
m2 := img.Rotate(tou, 144, 0, 0)
|
||||
m3 := img.Rotate(tou, 216, 0, 0)
|
||||
m4 := img.Rotate(tou, 288, 0, 0)
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 5)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cuo := []*image.NRGBA{
|
||||
imgs[0].InsertBottomC(tou, 0, 0, 75, 130).Im,
|
||||
imgs[1].InsertBottomC(m1.Im, 0, 0, 75, 130).Im,
|
||||
imgs[2].InsertBottomC(m2.Im, 0, 0, 75, 130).Im,
|
||||
imgs[3].InsertBottomC(m3.Im, 0, 0, 75, 130).Im,
|
||||
imgs[4].InsertBottomC(m4.Im, 0, 0, 75, 130).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(5, cuo))
|
||||
}
|
||||
|
||||
// A敲
|
||||
func (cc *context) A敲() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "敲.gif"
|
||||
c := dlrange("qiao", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(40, 40)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
qiao := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 40, 33, 57, 52).Im,
|
||||
imgs[1].InsertUp(tou, 38, 36, 58, 50).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, qiao))
|
||||
}
|
||||
|
||||
// A吃
|
||||
func (cc *context) A吃() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "吃.gif"
|
||||
c := dlrange("chi", 3, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(32, 32)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 3)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
chi := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
imgs[1].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
imgs[2].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chi))
|
||||
}
|
||||
|
||||
// A蹭
|
||||
func (cc *context) A蹭() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "蹭.gif"
|
||||
c := dlrange("ceng", 6, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou2, err := cc.getLogo2(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ceng := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 75, 77, 40, 88).InsertUp(tou2, 77, 103, 102, 81).Im,
|
||||
imgs[1].InsertUp(tou, 75, 77, 46, 100).InsertUp(img.Rotate(tou2, 10, 62, 127).Im, 0, 0, 92, 40).Im,
|
||||
imgs[2].InsertUp(tou, 75, 77, 67, 99).InsertUp(tou2, 76, 117, 90, 8).Im,
|
||||
imgs[3].InsertUp(tou, 75, 77, 52, 83).InsertUp(img.Rotate(tou2, -40, 94, 94).Im, 0, 0, 53, -20).Im,
|
||||
imgs[4].InsertUp(tou, 75, 77, 56, 110).InsertUp(img.Rotate(tou2, -66, 132, 80).Im, 0, 0, 78, 40).Im,
|
||||
imgs[5].InsertUp(tou, 75, 77, 62, 102).InsertUp(tou2, 71, 100, 110, 94).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(8, ceng))
|
||||
}
|
||||
|
||||
// A啃
|
||||
func (cc *context) A啃() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "啃.gif"
|
||||
c := dlrange("ken", 16, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 16)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ken := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 90, 90, 105, 150).Im,
|
||||
imgs[1].InsertBottom(tou, 90, 83, 96, 172).Im,
|
||||
imgs[2].InsertBottom(tou, 90, 90, 106, 148).Im,
|
||||
imgs[3].InsertBottom(tou, 88, 88, 97, 167).Im,
|
||||
imgs[4].InsertBottom(tou, 90, 85, 89, 179).Im,
|
||||
imgs[5].InsertBottom(tou, 90, 90, 106, 151).Im,
|
||||
imgs[6].Im,
|
||||
imgs[7].Im,
|
||||
imgs[8].Im,
|
||||
imgs[9].Im,
|
||||
imgs[10].Im,
|
||||
imgs[11].Im,
|
||||
imgs[12].Im,
|
||||
imgs[13].Im,
|
||||
imgs[14].Im,
|
||||
imgs[15].Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, ken))
|
||||
}
|
||||
|
||||
// A拍
|
||||
func (cc *context) A拍() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "拍.gif"
|
||||
c := dlrange("pai", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(30, 30)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pai := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 0, 0, 1, 47).Im,
|
||||
imgs[1].InsertUp(tou, 0, 0, 1, 67).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, pai))
|
||||
}
|
||||
|
||||
// A冲
|
||||
func (cc *context) A冲() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "冲.gif"
|
||||
c := dlrange("xqe", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
chong := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 30, 30, 15, 53).Im,
|
||||
imgs[1].InsertUp(tou, 30, 30, 40, 53).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chong))
|
||||
}
|
||||
|
||||
// A丢
|
||||
func (cc *context) A丢() (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "丢.gif"
|
||||
c := dlrange("diu", 8, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 8)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
diu := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 32, 32, 108, 36).Im,
|
||||
imgs[1].InsertUp(tou, 32, 32, 122, 36).Im,
|
||||
imgs[2].Im,
|
||||
imgs[3].InsertUp(tou, 123, 123, 19, 129).Im,
|
||||
imgs[4].InsertUp(tou, 185, 185, -50, 200).InsertUp(tou, 33, 33, 289, 70).Im,
|
||||
imgs[5].InsertUp(tou, 32, 32, 280, 73).Im,
|
||||
imgs[6].InsertUp(tou, 35, 35, 259, 31).Im,
|
||||
imgs[7].InsertUp(tou, 175, 175, -50, 220).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, diu))
|
||||
}
|
||||
41
plugin/gif/logo.go
Normal file
41
plugin/gif/logo.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"image"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
)
|
||||
|
||||
func (cc *context) prepareLogos(s ...string) error {
|
||||
for i, v := range s {
|
||||
_, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
} else {
|
||||
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[0], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo2(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[1], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
}
|
||||
108
plugin/gif/png.go
Normal file
108
plugin/gif/png.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
)
|
||||
|
||||
// A爬
|
||||
func (cc *context) A爬() (string, error) {
|
||||
name := cc.usrdir + `爬.png`
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 随机爬图序号
|
||||
rand := rand.Intn(60) + 1
|
||||
if file.IsNotExist(datapath + "materials/pa") {
|
||||
err = os.MkdirAll(datapath+"materials/pa", 0755)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
f, err := dlblock(`pa/` + strconv.Itoa(rand) + `.png`)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgf, err := img.LoadFirstFrame(f, 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertBottom(tou, 100, 100, 0, 400).Im)
|
||||
}
|
||||
|
||||
// A撕
|
||||
func (cc *context) A撕() (string, error) {
|
||||
name := cc.usrdir + `撕.png`
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
im1 := img.Rotate(tou, 20, 380, 380)
|
||||
im2 := img.Rotate(tou, -12, 380, 380)
|
||||
if file.IsNotExist(datapath + "materials/si") {
|
||||
err = os.MkdirAll(datapath+"materials/si", 0755)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
f, err := dlblock(`si/0.png`)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgf, err := img.LoadFirstFrame(f, 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertBottom(im1.Im, im1.W, im1.H, -3, 370).InsertBottom(im2.Im, im2.W, im2.H, 653, 310).Im)
|
||||
}
|
||||
|
||||
// 简单
|
||||
func (cc *context) other(value ...string) (string, error) {
|
||||
name := cc.usrdir + value[0] + `.png`
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var imgnrgba *image.NRGBA
|
||||
switch value[0] {
|
||||
case "上翻", "下翻":
|
||||
imgnrgba = im.FlipV().Im
|
||||
case "左翻", "右翻":
|
||||
imgnrgba = im.FlipH().Im
|
||||
case "反色":
|
||||
imgnrgba = im.Invert().Im
|
||||
case "灰度":
|
||||
imgnrgba = im.Grayscale().Im
|
||||
case "负片":
|
||||
imgnrgba = im.Invert().Grayscale().Im
|
||||
case "浮雕":
|
||||
imgnrgba = im.Convolve3x3().Im
|
||||
case "打码":
|
||||
imgnrgba = im.Blur(10).Im
|
||||
case "旋转":
|
||||
r, _ := strconv.ParseFloat(value[1], 64)
|
||||
imgnrgba = img.Rotate(im.Im, r, 0, 0).Im
|
||||
case "变形":
|
||||
w, err := strconv.Atoi(value[1])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
h, err := strconv.Atoi(value[2])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba = img.Size(im.Im, w, h).Im
|
||||
default:
|
||||
return "", errors.New("no such method")
|
||||
}
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
56
plugin/gif/run.go
Normal file
56
plugin/gif/run.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Package gif 制图
|
||||
package gif
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
var (
|
||||
cmds = []string{"搓", "冲", "摸", "拍", "丢", "吃", "敲", "啃", "蹭", "爬", "撕",
|
||||
"灰度", "上翻", "下翻", "左翻", "右翻", "反色", "浮雕", "打码", "负片"}
|
||||
datapath string
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
en := control.Register("gif", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "制图\n- " + strings.Join(cmds, "\n- "),
|
||||
PrivateDataFolder: "gif",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
datapath = file.BOTPATH + "/" + en.DataFolder()
|
||||
en.OnRegex(`^(` + strings.Join(cmds, "|") + `)\D*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := newContext(ctx.Event.UserID)
|
||||
list := ctx.State["regex_matched"].([]string)
|
||||
err := c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
var picurl string
|
||||
if len([]rune(list[1])) == 1 {
|
||||
r := reflect.ValueOf(c).MethodByName("A" + list[1]).Call(nil)
|
||||
picurl = r[0].String()
|
||||
if !r[1].IsNil() {
|
||||
err = r[1].Interface().(error)
|
||||
}
|
||||
} else {
|
||||
picurl, err = c.other(list[1]) // "灰度", "上翻", "下翻", "左翻", "右翻", "反色", "倒放", "浮雕", "打码", "负片"
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(picurl))
|
||||
})
|
||||
}
|
||||
@@ -4,26 +4,27 @@ package github
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("github", &control.Options{
|
||||
control.Register("github", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "GitHub仓库搜索\n" +
|
||||
"- >github [xxx]\n" +
|
||||
"- >github -p [xxx]",
|
||||
}).OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).FirstPriority().
|
||||
}).OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 发送请求
|
||||
header := http.Header{
|
||||
@@ -96,6 +97,7 @@ func init() { // 插件主体
|
||||
}
|
||||
|
||||
// notnull 如果传入文本为空,则返回默认值
|
||||
//nolint: unparam
|
||||
func notnull(text, defstr string) string {
|
||||
if text == "" {
|
||||
return defstr
|
||||
@@ -117,7 +119,7 @@ func netGet(dest string, header http.Header) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -12,16 +12,16 @@ import (
|
||||
"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"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
var (
|
||||
cachedir = file.BOTPATH + "/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 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"}
|
||||
|
||||
const (
|
||||
hs = `https://hs.fbigame.com/ajax.php?`
|
||||
@@ -43,21 +43,17 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
os.RemoveAll(cachedir)
|
||||
err := os.MkdirAll(cachedir, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
engine := control.Register("hs", &control.Options{
|
||||
engine := control.Register("hs", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "炉石\n" +
|
||||
"- 搜卡[xxxx]\n" +
|
||||
"- [卡组代码xxx]\n" +
|
||||
"- 更多搜卡指令参数:https://hs.fbigame.com/misc/searchhelp",
|
||||
})
|
||||
PrivateDataFolder: "hs",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
cachedir := file.BOTPATH + "/" + engine.DataFolder()
|
||||
engine.OnRegex(`^搜卡(.+)$`).
|
||||
SetBlock(true).SetPriority(20).Handle(func(ctx *zero.Ctx) {
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
List := ctx.State["regex_matched"].([]string)[1]
|
||||
g := sh(List)
|
||||
t := int(gjson.Get(g, `list.#`).Int())
|
||||
@@ -69,9 +65,8 @@ func init() {
|
||||
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(
|
||||
data, err := web.GetDataWith(web.NewDefaultClient(),
|
||||
`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])
|
||||
@@ -79,17 +74,10 @@ func init() {
|
||||
err = os.WriteFile(cachefile, data, 0644)
|
||||
}
|
||||
if err != nil {
|
||||
imgcq = err.Error()
|
||||
continue
|
||||
}
|
||||
}
|
||||
sk = append(
|
||||
sk,
|
||||
message.CustomNode(
|
||||
zero.BotConfig.NickName[0],
|
||||
ctx.Event.SelfID,
|
||||
imgcq, // 图片
|
||||
),
|
||||
)
|
||||
sk = append(sk, ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+cachefile)))
|
||||
}
|
||||
if id := ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
@@ -100,7 +88,7 @@ func init() {
|
||||
})
|
||||
// 卡组
|
||||
engine.OnRegex(`^[\s\S]*?(AAE[a-zA-Z0-9/\+=]{70,})[\s\S]*$`).
|
||||
SetBlock(true).SetPriority(20).Handle(func(ctx *zero.Ctx) {
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
fmt.Print("成功")
|
||||
List := ctx.State["regex_matched"].([]string)[1]
|
||||
ctx.SendChain(
|
||||
@@ -110,10 +98,10 @@ func init() {
|
||||
}
|
||||
|
||||
func sh(s string) string {
|
||||
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
data, err := web.GetDataWith(web.NewDefaultClient(), "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])
|
||||
r, err := web.GetDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
return helper.BytesToString(r)
|
||||
}
|
||||
@@ -122,10 +110,10 @@ func sh(s string) string {
|
||||
}
|
||||
|
||||
func kz(s string) string {
|
||||
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
data, err := web.GetDataWith(web.NewDefaultClient(), "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])
|
||||
r, err := web.GetDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
return "base64://" + gjson.Get(helper.BytesToString(r), "img").String()
|
||||
}
|
||||
82
plugin/image_finder/keyword.go
Normal file
82
plugin/image_finder/keyword.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Package imagefinder 关键字搜图
|
||||
package imagefinder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
type resultjson struct {
|
||||
Data struct {
|
||||
Illusts []struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
AltTitle string `json:"altTitle"`
|
||||
Description string `json:"description"`
|
||||
Sanity int `json:"sanity"`
|
||||
} `json:"illusts"`
|
||||
} `json:"data"`
|
||||
Error bool `json:"error"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
control.Register("imgfinder", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "关键字搜图\n" +
|
||||
"- 来张 [xxx]",
|
||||
}).OnRegex(`^来张\s?(.*)$`, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
soutujson, err := soutuapi(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
rannum := rand.Intn(len(soutujson.Data.Illusts))
|
||||
illust, err := pixiv.Works(soutujson.Data.Illusts[rannum].ID)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
u := illust.ImageUrls[0]
|
||||
n := u[strings.LastIndex(u, "/")+1 : len(u)-4]
|
||||
f := illust.Path(0)
|
||||
|
||||
err = pool.SendImageFromPool(n, f, func() error {
|
||||
// 下载图片
|
||||
return illust.DownloadToCache(0)
|
||||
}, ctxext.SendFakeForwardToGroup(ctx), ctxext.GetFirstMessageInForward(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// soutuapi 请求api
|
||||
func soutuapi(keyword string) (r resultjson, err error) {
|
||||
data, err := web.GetData("https://copymanga.azurewebsites.net/api/pixivel?" + url.QueryEscape(keyword) + "?page=0")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &r)
|
||||
if err == nil && r.Error {
|
||||
err = errors.New(r.Message)
|
||||
}
|
||||
return
|
||||
}
|
||||
23
plugin/inject/main.go
Normal file
23
plugin/inject/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Package inject 注入指令
|
||||
package inject
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("inject", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "注入指令\n" +
|
||||
"- run[CQ码]",
|
||||
})
|
||||
// 运行 CQ 码
|
||||
en.OnPrefix("run", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(message.UnescapeCQCodeText(ctx.State["args"].(string)))
|
||||
})
|
||||
}
|
||||
24
plugin/jandan/data.go
Normal file
24
plugin/jandan/data.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package jandan
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
)
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
var mu sync.RWMutex
|
||||
|
||||
type picture struct {
|
||||
ID uint64 `db:"id"`
|
||||
URL string `db:"url"`
|
||||
}
|
||||
|
||||
func getRandomPicture() (u string, err error) {
|
||||
var p picture
|
||||
mu.RLock()
|
||||
err = db.Pick("picture", &p)
|
||||
mu.RUnlock()
|
||||
u = p.URL
|
||||
return
|
||||
}
|
||||
108
plugin/jandan/jandan.go
Normal file
108
plugin/jandan/jandan.go
Normal file
@@ -0,0 +1,108 @@
|
||||
// Package jandan 煎蛋网无聊图
|
||||
package jandan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc64"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/antchfx/htmlquery"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
api = "http://jandan.net/pic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("jandan", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "煎蛋网无聊图\n- 来份屌图\n- 更新屌图\n",
|
||||
PublicDataFolder: "Jandan",
|
||||
})
|
||||
|
||||
go func() {
|
||||
dbpath := engine.DataFolder()
|
||||
db.DBPath = dbpath + "pics.db"
|
||||
_, _ = file.GetLazyData(db.DBPath, false, false)
|
||||
err := db.Create("picture", &picture{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n, err := db.Count("picture")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Printf("[jandan]读取%d张图片", n)
|
||||
}()
|
||||
|
||||
engine.OnFullMatch("来份屌图").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
u, err := getRandomPicture()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(u))
|
||||
})
|
||||
|
||||
engine.OnFullMatch("更新屌图", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send("少女更新中...")
|
||||
webpageURL := api
|
||||
doc, err := htmlquery.LoadURL(webpageURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
re := regexp.MustCompile(`\d+`)
|
||||
pageTotal, err := strconv.Atoi(re.FindString(htmlquery.FindOne(doc, "//*[@id='comments']/div[2]/div/span[@class='current-comment-page']/text()").Data))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
LOOP:
|
||||
for i := 0; i < pageTotal; i++ {
|
||||
logrus.Infoln("[jandan]", fmt.Sprintf("处理第%d/%d页...", i, pageTotal))
|
||||
doc, err = htmlquery.LoadURL(webpageURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
picList, err := htmlquery.QueryAll(doc, "//*[@class='view_img_link']")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if len(picList) != 0 {
|
||||
for _, v := range picList {
|
||||
u := "https:" + v.Attr[0].Val
|
||||
i := crc64.Checksum(binary.StringToBytes(u), crc64.MakeTable(crc64.ISO))
|
||||
mu.RLock()
|
||||
ok := db.CanFind("picture", "where id="+strconv.FormatUint(i, 10))
|
||||
mu.RUnlock()
|
||||
if !ok {
|
||||
mu.Lock()
|
||||
_ = db.Insert("picture", &picture{ID: i, URL: u})
|
||||
mu.Unlock()
|
||||
} else {
|
||||
// 开始重复,说明之后都是重复
|
||||
break LOOP
|
||||
}
|
||||
}
|
||||
}
|
||||
if i != pageTotal-1 {
|
||||
webpageURL = "https:" + htmlquery.FindOne(doc, "//*[@id='comments']/div[@class='comments']/div[@class='cp-pagenavi']/a[@class='previous-comment-page']").Attr[1].Val
|
||||
}
|
||||
}
|
||||
ctx.Send("更新完成!")
|
||||
})
|
||||
}
|
||||
541
plugin/job/main.go
Normal file
541
plugin/job/main.go
Normal file
@@ -0,0 +1,541 @@
|
||||
// Package job 定时指令触发器
|
||||
package job
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"hash/crc64"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/FloatTech/zbputils/vevent"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/fumiama/cron"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
lo map[int64]vevent.Loop
|
||||
entries = map[int64]cron.EntryID{} // id entryid
|
||||
matchers = map[int64]*zero.Matcher{}
|
||||
mu sync.Mutex
|
||||
limit = rate.NewLimiter(time.Second*2, 1)
|
||||
en = control.Register("job", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "定时指令触发器\n- 记录以\"完全匹配关键词\"触发的指令\n- 取消以\"完全匹配关键词\"触发的指令\n- 记录在\"cron\"触发的指令\n- 取消在\"cron\"触发的指令\n- 查看所有触发指令\n- 查看在\"cron\"触发的指令\n- 查看以\"完全匹配关键词\"触发的指令\n- 注入指令结果:任意指令\n- 执行指令:任意指令",
|
||||
PrivateDataFolder: "job",
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
db.DBPath = en.DataFolder() + "job.db"
|
||||
err := db.Open()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go func() {
|
||||
process.GlobalInitMutex.Lock()
|
||||
process.SleepAbout1sTo2s()
|
||||
lo = make(map[int64]vevent.Loop, len(zero.BotConfig.Driver))
|
||||
for _, drv := range zero.BotConfig.Driver {
|
||||
id := drv.SelfID()
|
||||
ids := strconv.FormatInt(id, 36)
|
||||
c := &cmd{}
|
||||
lo[id] = vevent.NewLoop(id)
|
||||
err := db.Create(ids, c)
|
||||
logrus.Infoln("[job]创建表", ids)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = db.FindFor(ids, c, "", func() error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if strings.HasPrefix(c.Cron, "fm:") {
|
||||
m := en.OnFullMatch(c.Cron[3:] /* skip fm: */).SetBlock(true)
|
||||
m.Handle(generalhandler(c))
|
||||
matchers[c.ID] = getmatcher(m)
|
||||
return nil
|
||||
}
|
||||
if strings.HasPrefix(c.Cron, "sm:") {
|
||||
m := en.OnFullMatch(c.Cron[3:] /* skip fm: */).SetBlock(true)
|
||||
m.Handle(superuserhandler(c))
|
||||
matchers[c.ID] = getmatcher(m)
|
||||
return nil
|
||||
}
|
||||
eid, err := process.CronTab.AddFunc(c.Cron, inject(id, []byte(c.Cmd)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
entries[c.ID] = eid
|
||||
return nil
|
||||
})
|
||||
}
|
||||
logrus.Infoln("[job]本地环回初始化完成")
|
||||
process.GlobalInitMutex.Unlock()
|
||||
}()
|
||||
en.OnRegex(`^记录在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil, isfirstregmatchnotnil, logevent).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := ctx.State["regex_matched"].([]string)[1]
|
||||
command := ctx.State["job_raw_event"].(string)
|
||||
c := &cmd{
|
||||
ID: idof(cron, command),
|
||||
Cron: cron,
|
||||
Cmd: command,
|
||||
}
|
||||
err := addcmd(ctx.Event.SelfID, c)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^记录以"(.*)"触发的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil, logevent).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := "fm:" + ctx.State["regex_matched"].([]string)[1]
|
||||
command := ctx.State["job_new_event"].(gjson.Result).Get("message").Raw
|
||||
logrus.Debugln("[job] get cmd:", command)
|
||||
c := &cmd{
|
||||
ID: idof(cron, command),
|
||||
Cron: cron,
|
||||
Cmd: command,
|
||||
}
|
||||
err := registercmd(ctx.Event.SelfID, c)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^记录以"(.*)"触发的代表我执行的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil, logevent).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := "sm:" + ctx.State["regex_matched"].([]string)[1]
|
||||
command := ctx.State["job_raw_event"].(string)
|
||||
logrus.Debugln("[job] get cmd:", command)
|
||||
c := &cmd{
|
||||
ID: idof(cron, command),
|
||||
Cron: cron,
|
||||
Cmd: command,
|
||||
}
|
||||
err := registercmd(ctx.Event.SelfID, c)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^取消在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := ctx.State["regex_matched"].([]string)[1]
|
||||
err := rmcmd(ctx.Event.SelfID, ctx.Event.UserID, cron)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^取消以"(.*)"触发的(代表我执行的)?指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
issu := ctx.State["regex_matched"].([]string)[2] != ""
|
||||
cron := ""
|
||||
if issu {
|
||||
cron = "sm:"
|
||||
} else {
|
||||
cron = "fm:"
|
||||
}
|
||||
cron += ctx.State["regex_matched"].([]string)[1]
|
||||
err := delcmd(ctx.Event.SelfID, cron)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnFullMatch("查看所有触发指令", zero.SuperUserPermission, islonotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := &cmd{}
|
||||
ids := strconv.FormatInt(ctx.Event.SelfID, 36)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
n, err := db.Count(ids)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
lst := make([]string, 0, n)
|
||||
err = db.FindFor(ids, c, "GROUP BY cron", func() error {
|
||||
lst = append(lst, c.Cron+"\n")
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(lst))
|
||||
})
|
||||
en.OnRegex(`^查看在"(.*)"触发的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := &cmd{}
|
||||
ids := strconv.FormatInt(ctx.Event.SelfID, 36)
|
||||
cron := ctx.State["regex_matched"].([]string)[1]
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
n, err := db.Count(ids)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
lst := make([]string, 0, n)
|
||||
err = db.FindFor(ids, c, "WHERE cron='"+cron+"'", func() error {
|
||||
lst = append(lst, c.Cmd+"\n")
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(lst))
|
||||
})
|
||||
en.OnRegex(`^查看以"(.*)"触发的(代表我执行的)?指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := &cmd{}
|
||||
ids := strconv.FormatInt(ctx.Event.SelfID, 36)
|
||||
issu := ctx.State["regex_matched"].([]string)[2] != ""
|
||||
cron := ""
|
||||
if issu {
|
||||
cron = "sm:"
|
||||
} else {
|
||||
cron = "fm:"
|
||||
}
|
||||
cron += ctx.State["regex_matched"].([]string)[1]
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
n, err := db.Count(ids)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
lst := make([]string, 0, n)
|
||||
err = db.FindFor(ids, c, "WHERE cron='"+cron+"'", func() error {
|
||||
lst = append(lst, c.Cmd+"\n")
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(lst))
|
||||
})
|
||||
en.OnPrefix("执行指令:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
||||
return ctx.State["args"].(string) != ""
|
||||
}, parseArgs).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ev := strings.ReplaceAll(ctx.Event.RawEvent.Raw, "执行指令:", "")
|
||||
logrus.Debugln("[job] inject:", ev)
|
||||
inject(ctx.Event.SelfID, binary.StringToBytes(ev))()
|
||||
})
|
||||
en.OnPrefix("注入指令结果:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
||||
return ctx.State["args"].(string) != ""
|
||||
}, parseArgs).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
vevent.NewLoopOf(vevent.NewAPICallerHook(ctx, func(rsp zero.APIResponse, err error) {
|
||||
if err == nil {
|
||||
logrus.Debugln("[job] CallerHook returned")
|
||||
id := message.NewMessageID(rsp.Data.Get("message_id").String())
|
||||
if id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:未获取到返回结果"))
|
||||
return
|
||||
}
|
||||
msg := ctx.GetMessage(id)
|
||||
ctx.Event.NativeMessage = json.RawMessage("\"" + msg.Elements.String() + "\"")
|
||||
ctx.Event.RawMessageID = json.RawMessage(msg.MessageId.String())
|
||||
ctx.Event.RawMessage = msg.Elements.String()
|
||||
time.Sleep(time.Second * 5) // 防止风控
|
||||
ctx.Event.Time = time.Now().Unix()
|
||||
ctx.DeleteMessage(id)
|
||||
vev, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
err = json.NewEncoder(w).Encode(ctx.Event)
|
||||
})
|
||||
if err != nil {
|
||||
cl()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[job] inject:", binary.BytesToString(vev))
|
||||
inject(ctx.Event.SelfID, vev)()
|
||||
cl()
|
||||
}
|
||||
})).Echo(binary.StringToBytes(strings.ReplaceAll(ctx.Event.RawEvent.Raw, "注入指令结果:", "")))
|
||||
})
|
||||
}
|
||||
|
||||
func islonotnil(ctx *zero.Ctx) bool {
|
||||
return len(lo) > 0
|
||||
}
|
||||
|
||||
func isfirstregmatchnotnil(ctx *zero.Ctx) bool {
|
||||
return ctx.State["regex_matched"].([]string)[1] != ""
|
||||
}
|
||||
|
||||
func inject(bot int64, response []byte) func() {
|
||||
return func() {
|
||||
if limit.Acquire() {
|
||||
lo[bot].Echo(response)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func idof(cron, cmd string) int64 {
|
||||
return int64(crc64.Checksum(binary.StringToBytes(cron+cmd), crc64.MakeTable(crc64.ISO)))
|
||||
}
|
||||
|
||||
func addcmd(bot int64, c *cmd) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
eid, err := process.CronTab.AddFunc(c.Cron, inject(bot, []byte(c.Cmd)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
entries[c.ID] = eid
|
||||
return db.Insert(strconv.FormatInt(bot, 36), c)
|
||||
}
|
||||
|
||||
func registercmd(bot int64, c *cmd) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
m := en.OnFullMatch(c.Cron[3:] /* skip fm: or sm: */).SetBlock(true)
|
||||
if strings.HasPrefix(c.Cron, "sm:") {
|
||||
m.Handle(superuserhandler(c))
|
||||
} else {
|
||||
m.Handle(generalhandler(c))
|
||||
}
|
||||
matchers[c.ID] = getmatcher(m)
|
||||
return db.Insert(strconv.FormatInt(bot, 36), c)
|
||||
}
|
||||
|
||||
func generalhandler(c *cmd) zero.Handler {
|
||||
return func(ctx *zero.Ctx) {
|
||||
ctx.Event.NativeMessage = json.RawMessage(c.Cmd) // c.Cmd only have message
|
||||
ctx.Event.Time = time.Now().Unix()
|
||||
var err error
|
||||
vev, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
err = json.NewEncoder(w).Encode(ctx.Event)
|
||||
})
|
||||
if err != nil {
|
||||
cl()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[job] inject:", binary.BytesToString(vev))
|
||||
inject(ctx.Event.SelfID, vev)()
|
||||
cl()
|
||||
}
|
||||
}
|
||||
|
||||
func superuserhandler(c *cmd) zero.Handler {
|
||||
e := &zero.Event{Sender: new(zero.User)}
|
||||
err := json.Unmarshal(binary.StringToBytes(c.Cmd), e)
|
||||
return func(ctx *zero.Ctx) {
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Event.UserID = e.UserID
|
||||
ctx.Event.RawMessage = e.RawMessage
|
||||
ctx.Event.Sender = e.Sender
|
||||
ctx.Event.NativeMessage = e.NativeMessage
|
||||
vev, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
err = json.NewEncoder(w).Encode(ctx.Event)
|
||||
})
|
||||
if err != nil {
|
||||
cl()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[job] inject:", binary.BytesToString(vev))
|
||||
inject(ctx.Event.SelfID, vev)()
|
||||
cl()
|
||||
}
|
||||
}
|
||||
|
||||
func rmcmd(bot, caller int64, cron string) error {
|
||||
c := &cmd{}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
bots := strconv.FormatInt(bot, 36)
|
||||
e := new(zero.Event)
|
||||
var delcmd []string
|
||||
err := db.FindFor(bots, c, "WHERE cron='"+cron+"'", func() error {
|
||||
err := json.Unmarshal(binary.StringToBytes(c.Cmd), e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if e.UserID != caller {
|
||||
return nil
|
||||
}
|
||||
eid, ok := entries[c.ID]
|
||||
if ok {
|
||||
process.CronTab.Remove(eid)
|
||||
delete(entries, c.ID)
|
||||
delcmd = append(delcmd, "id="+strconv.FormatInt(c.ID, 10))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(delcmd) > 0 {
|
||||
return db.Del(bots, "WHERE "+strings.Join(delcmd, " or "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func delcmd(bot int64, cron string) error {
|
||||
c := &cmd{}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
bots := strconv.FormatInt(bot, 36)
|
||||
var delcmd []string
|
||||
err := db.FindFor(bots, c, "WHERE cron='"+cron+"'", func() error {
|
||||
m, ok := matchers[c.ID]
|
||||
if ok {
|
||||
m.Delete()
|
||||
delete(matchers, c.ID)
|
||||
delcmd = append(delcmd, "id="+strconv.FormatInt(c.ID, 10))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(delcmd) > 0 {
|
||||
return db.Del(bots, "WHERE "+strings.Join(delcmd, " or "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseArgs(ctx *zero.Ctx) bool {
|
||||
cmds := ctx.State["args"].(string)
|
||||
if !strings.Contains(cmds, "?::") && !strings.Contains(cmds, "!::") {
|
||||
return true
|
||||
}
|
||||
args := make(map[int]string)
|
||||
for strings.Contains(ctx.Event.RawEvent.Raw, "?::") {
|
||||
start := strings.Index(ctx.Event.RawEvent.Raw, "?::")
|
||||
msgend := strings.Index(ctx.Event.RawEvent.Raw[start+3:], "::")
|
||||
if msgend < 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的::"))
|
||||
return false
|
||||
}
|
||||
msgend += start + 3
|
||||
numend := strings.Index(ctx.Event.RawEvent.Raw[msgend+2:], "!")
|
||||
if numend <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的!"))
|
||||
return false
|
||||
}
|
||||
numend += msgend + 2
|
||||
logrus.Debugln("[job]", start, msgend, numend)
|
||||
msg := ctx.Event.RawEvent.Raw[start+3 : msgend]
|
||||
arg, err := strconv.Atoi(ctx.Event.RawEvent.Raw[msgend+2 : numend])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
arr, ok := args[arg]
|
||||
if !ok {
|
||||
var id message.MessageID
|
||||
if msg == "" {
|
||||
id = ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入参数", arg))
|
||||
} else {
|
||||
id = ctx.SendChain(message.At(ctx.Event.UserID), message.Text("[", arg, "] ", msg))
|
||||
}
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("参数读取超时")))
|
||||
if msg[0] != '?' {
|
||||
return false
|
||||
}
|
||||
case e := <-zero.NewFutureEvent("message", 0, true, zero.CheckUser(ctx.Event.UserID)).Next():
|
||||
args[arg] = e.Message.String()
|
||||
arr = args[arg]
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(e.MessageID), message.Text("已记录"))
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
}
|
||||
ctx.Event.RawEvent.Raw = ctx.Event.RawEvent.Raw[:start] + arr + ctx.Event.RawEvent.Raw[numend+1:]
|
||||
}
|
||||
args = make(map[int]string)
|
||||
for strings.Contains(ctx.Event.RawEvent.Raw, "!::") {
|
||||
start := strings.Index(ctx.Event.RawEvent.Raw, "!::")
|
||||
msgend := strings.Index(ctx.Event.RawEvent.Raw[start+3:], "::")
|
||||
if msgend < 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的::"))
|
||||
return false
|
||||
}
|
||||
msgend += start + 3
|
||||
numend := strings.Index(ctx.Event.RawEvent.Raw[msgend+2:], "!")
|
||||
if numend <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的!"))
|
||||
return false
|
||||
}
|
||||
numend += msgend + 2
|
||||
logrus.Debugln("[job]", start, msgend, numend)
|
||||
u := ctx.Event.RawEvent.Raw[start+3 : msgend]
|
||||
if u == "" {
|
||||
return false
|
||||
}
|
||||
arg, err := strconv.Atoi(ctx.Event.RawEvent.Raw[msgend+2 : numend])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
arr, ok := args[arg]
|
||||
if !ok {
|
||||
isnilable := u[0] == '?'
|
||||
if isnilable {
|
||||
u = u[1:]
|
||||
if u == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
b, err := web.GetData(u)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
if !isnilable {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if len(b) > 0 {
|
||||
type fakejson struct {
|
||||
Arg string `json:"arg"`
|
||||
}
|
||||
f := fakejson{Arg: binary.BytesToString(b)}
|
||||
w := binary.SelectWriter()
|
||||
defer binary.PutWriter(w)
|
||||
_ = json.NewEncoder(w).Encode(&f)
|
||||
arr = w.String()[8 : w.Len()-3]
|
||||
args[arg] = arr
|
||||
}
|
||||
}
|
||||
w := binary.SelectWriter()
|
||||
w.WriteString(ctx.Event.RawEvent.Raw[:start])
|
||||
w.WriteString(arr)
|
||||
w.WriteString(ctx.Event.RawEvent.Raw[numend+1:])
|
||||
ctx.Event.RawEvent.Raw = string(w.Bytes())
|
||||
binary.PutWriter(w)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func logevent(ctx *zero.Ctx) bool {
|
||||
ctx.SendChain(message.Text("您的下一条指令将被记录,在", ctx.State["regex_matched"].([]string)[1], "时触发"))
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.SendChain(message.Text("指令记录超时"))
|
||||
return false
|
||||
case e := <-zero.NewFutureEvent("message", 0, true, zero.CheckUser(ctx.Event.UserID)).Next():
|
||||
ctx.State["job_raw_event"] = e.RawEvent.Raw
|
||||
ctx.State["job_new_event"] = e.RawEvent
|
||||
return true
|
||||
}
|
||||
}
|
||||
16
plugin/job/matcher.go
Normal file
16
plugin/job/matcher.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
)
|
||||
|
||||
type matcherinstance struct {
|
||||
m *zero.Matcher
|
||||
}
|
||||
|
||||
func getmatcher(m control.Matcher) *zero.Matcher {
|
||||
return (*matcherinstance)(unsafe.Pointer(&m)).m
|
||||
}
|
||||
11
plugin/job/model.go
Normal file
11
plugin/job/model.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package job
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type cmd struct {
|
||||
ID int64 `db:"id"`
|
||||
Cron string `db:"cron"`
|
||||
Cmd string `db:"cmd"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
71
plugin/juejuezi/juejuezi.go
Normal file
71
plugin/juejuezi/juejuezi.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Package juejuezi 绝绝子
|
||||
package juejuezi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
juejueziURL = "https://www.offjuan.com/api/juejuezi/text"
|
||||
referer = "https://juejuezi.offjuan.com/"
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("juejuezi", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "绝绝子生成器\n" +
|
||||
"- 喝奶茶绝绝子 | 绝绝子吃饭",
|
||||
}).OnRegex("[\u4E00-\u9FA5]{0,10}绝绝子[\u4E00-\u9FA5]{0,10}").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
toDealStr := []rune(strings.ReplaceAll(ctx.ExtractPlainText(), "绝绝子", ""))
|
||||
switch len(toDealStr) {
|
||||
case 0, 1:
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("不要只输入绝绝子"))
|
||||
case 2:
|
||||
data, err := juejuezi(string(toDealStr[0]), string(toDealStr[1]))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
|
||||
default:
|
||||
params := ctx.GetWordSlices(string(toDealStr)).Get("slices").Array()
|
||||
data, err := juejuezi(params[0].String(), params[1].String())
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func juejuezi(verb, noun string) (data []byte, err error) {
|
||||
juejueziStr := fmt.Sprintf("{\"verb\":\"%s\",\"noun\":\"%s\"}", verb, noun)
|
||||
client := &http.Client{}
|
||||
// 提交请求
|
||||
request, err := http.NewRequest("POST", juejueziURL, strings.NewReader(juejueziStr))
|
||||
if err != nil {
|
||||
log.Errorln("[juejuezi]:", err)
|
||||
}
|
||||
request.Header.Add("Referer", referer)
|
||||
request.Header.Add("User-Agent", ua)
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Errorln("[juejuezi]:", err)
|
||||
}
|
||||
data, err = io.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
return
|
||||
}
|
||||
79
plugin/lolicon/lolicon.go
Normal file
79
plugin/lolicon/lolicon.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// Package lolicon 基于 https://api.lolicon.app 随机图片
|
||||
package lolicon
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
api = "https://api.lolicon.app/setu/v2"
|
||||
capacity = 10
|
||||
)
|
||||
|
||||
var (
|
||||
queue = make(chan string, capacity)
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("lolicon", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "lolicon\n" +
|
||||
"- 来份萝莉",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("来份萝莉").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
go func() {
|
||||
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
|
||||
data, err := web.GetData(api)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
}
|
||||
json := gjson.ParseBytes(data)
|
||||
if e := json.Get("error").Str; e != "" {
|
||||
ctx.SendChain(message.Text("ERROR: ", e))
|
||||
continue
|
||||
}
|
||||
url := json.Get("data.0.urls.original").Str
|
||||
url = strings.ReplaceAll(url, "i.pixiv.cat", "i.pixiv.re")
|
||||
name := url[strings.LastIndex(url, "/")+1 : len(url)-4]
|
||||
m, err := pool.GetImage(name)
|
||||
if err != nil {
|
||||
m.SetFile(url)
|
||||
_, err = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
if err == nil {
|
||||
queue <- m.String()
|
||||
} else {
|
||||
queue <- url
|
||||
}
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case <-time.After(time.Minute):
|
||||
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
|
||||
case img := <-queue:
|
||||
id := ctx.SendChain(message.Image(img))
|
||||
if id.ID() == 0 {
|
||||
id = ctx.SendChain(message.Image(img).Add("cache", "0"))
|
||||
if id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:图片发送失败,可能被风控了~"))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
// user hash file
|
||||
@@ -4,7 +4,6 @@ package manager
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -12,20 +11,21 @@ import (
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
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/plugin_manager/timer"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/manager/timer"
|
||||
)
|
||||
|
||||
const (
|
||||
datapath = "data/manager/"
|
||||
confile = datapath + "config.db"
|
||||
hint = "====群管====\n" +
|
||||
hint = "====群管====\n" +
|
||||
"- 禁言@QQ 1分钟\n" +
|
||||
"- 解除禁言 @QQ\n" +
|
||||
"- 我要自闭 1分钟\n" +
|
||||
@@ -41,32 +41,32 @@ const (
|
||||
"- 群聊转发 1234 XXX\n" +
|
||||
"- 私聊转发 0000 XXX\n" +
|
||||
"- 在MM月dd日的hh点mm分时(用http://url)提醒大家XXX\n" +
|
||||
"- 在MM月[每周|周几]的hh点mm分时(用http://url)提醒大家XXX\n" +
|
||||
"- 在MM月[每周 | 周几]的hh点mm分时(用http://url)提醒大家XXX\n" +
|
||||
"- 取消在MM月dd日的hh点mm分的提醒\n" +
|
||||
"- 取消在MM月[每周|周几]的hh点mm分的提醒\n" +
|
||||
"- 取消在MM月[每周 | 周几]的hh点mm分的提醒\n" +
|
||||
"- 在\"cron\"时(用[url])提醒大家[xxx]\n" +
|
||||
"- 取消在\"cron\"的提醒\n" +
|
||||
"- 列出所有提醒\n" +
|
||||
"- 翻牌\n" +
|
||||
"- 设置欢迎语XXX\n" +
|
||||
"- [开启|关闭]入群验证"
|
||||
"- 设置欢迎语XXX(可加{at}在欢迎时@对方)\n" +
|
||||
"- 测试欢迎语\n" +
|
||||
"- [开启 | 关闭]入群验证"
|
||||
)
|
||||
|
||||
var (
|
||||
db = &sql.Sqlite{DBPath: confile}
|
||||
limit = rate.NewManager(time.Minute*5, 2)
|
||||
db = &sql.Sqlite{}
|
||||
clock timer.Clock
|
||||
)
|
||||
|
||||
var engine = control.Register("manager", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: hint,
|
||||
})
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("manager", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: hint,
|
||||
PrivateDataFolder: "manager",
|
||||
})
|
||||
|
||||
go func() {
|
||||
process.SleepAbout1sTo2s()
|
||||
_ = os.MkdirAll(datapath, 0755)
|
||||
db.DBPath = engine.DataFolder() + "config.db"
|
||||
clock = timer.NewClock(db)
|
||||
err := db.Create("welcome", &welcome{})
|
||||
if err != nil {
|
||||
@@ -77,8 +77,9 @@ func init() { // 插件主体
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// 升为管理
|
||||
engine.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupAdmin(
|
||||
ctx.Event.GroupID,
|
||||
@@ -93,7 +94,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text(nickname + " 升为了管理~"))
|
||||
})
|
||||
// 取消管理
|
||||
engine.OnRegex(`^取消管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^取消管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupAdmin(
|
||||
ctx.Event.GroupID,
|
||||
@@ -108,7 +109,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("残念~ " + nickname + " 暂时失去了管理员的资格"))
|
||||
})
|
||||
// 踢出群聊
|
||||
engine.OnRegex(`^踢出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^踢出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupKick(
|
||||
ctx.Event.GroupID,
|
||||
@@ -123,7 +124,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("残念~ " + nickname + " 被放逐"))
|
||||
})
|
||||
// 退出群聊
|
||||
engine.OnRegex(`^退出群聊.*?(\d+)`, zero.OnlyToMe, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^退出群聊.*?(\d+)`, zero.OnlyToMe, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupLeave(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 要退出的群的群号
|
||||
@@ -131,7 +132,7 @@ func init() { // 插件主体
|
||||
)
|
||||
})
|
||||
// 开启全体禁言
|
||||
engine.OnRegex(`^开启全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^开启全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupWholeBan(
|
||||
ctx.Event.GroupID,
|
||||
@@ -140,7 +141,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("全员自闭开始~"))
|
||||
})
|
||||
// 解除全员禁言
|
||||
engine.OnRegex(`^解除全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^解除全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupWholeBan(
|
||||
ctx.Event.GroupID,
|
||||
@@ -149,7 +150,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("全员自闭结束~"))
|
||||
})
|
||||
// 禁言
|
||||
engine.OnRegex(`^禁言.*?(\d+).*?\s(\d+)(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^禁言.*?(\d+).*?\s(\d+)(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
duration := math.Str2Int64(ctx.State["regex_matched"].([]string)[2])
|
||||
switch ctx.State["regex_matched"].([]string)[3] {
|
||||
@@ -173,7 +174,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("小黑屋收留成功~"))
|
||||
})
|
||||
// 解除禁言
|
||||
engine.OnRegex(`^解除禁言.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^解除禁言.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupBan(
|
||||
ctx.Event.GroupID,
|
||||
@@ -183,7 +184,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("小黑屋释放成功~"))
|
||||
})
|
||||
// 自闭禁言
|
||||
engine.OnRegex(`^(我要自闭|禅定).*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^(我要自闭|禅定).*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
duration := math.Str2Int64(ctx.State["regex_matched"].([]string)[2])
|
||||
switch ctx.State["regex_matched"].([]string)[3] {
|
||||
@@ -207,8 +208,12 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("那我就不手下留情了~"))
|
||||
})
|
||||
// 修改名片
|
||||
engine.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[2]) > 60 {
|
||||
ctx.SendChain(message.Text("名字太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupCard(
|
||||
ctx.Event.GroupID,
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
|
||||
@@ -217,8 +222,12 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
})
|
||||
// 修改头衔
|
||||
engine.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
|
||||
@@ -227,8 +236,12 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
})
|
||||
// 申请头衔
|
||||
engine.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
ctx.Event.UserID, // 被修改群头衔的人
|
||||
@@ -237,7 +250,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("嗯!不错的头衔呢~"))
|
||||
})
|
||||
// 群聊转发
|
||||
engine.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 对CQ码进行反转义
|
||||
content := ctx.State["regex_matched"].([]string)[2]
|
||||
@@ -250,7 +263,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
|
||||
})
|
||||
// 私聊转发
|
||||
engine.OnRegex(`^私聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^私聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 对CQ码进行反转义
|
||||
content := ctx.State["regex_matched"].([]string)[2]
|
||||
@@ -263,7 +276,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
|
||||
})
|
||||
// 定时提醒
|
||||
engine.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, ctx.Event.GroupID, false)
|
||||
@@ -275,7 +288,7 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
// 定时 cron 提醒
|
||||
engine.OnRegex(`^在"(.*)"时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^在"(.*)"时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
var url, alert string
|
||||
@@ -298,7 +311,7 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
// 取消定时
|
||||
engine.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, ctx.Event.GroupID, true)
|
||||
@@ -311,10 +324,10 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
// 取消 cron 定时
|
||||
engine.OnRegex(`^取消在"(.*)"的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^取消在"(.*)"的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.Timer{Cron: dateStrs[1], GrpId: ctx.Event.GroupID}
|
||||
ts := timer.Timer{Cron: dateStrs[1], GrpID: ctx.Event.GroupID}
|
||||
ti := ts.GetTimerID()
|
||||
ok := clock.CancelTimer(ti)
|
||||
if ok {
|
||||
@@ -324,17 +337,13 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
// 列出本群所有定时
|
||||
engine.OnFullMatch("列出所有提醒", zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnFullMatch("列出所有提醒", zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(clock.ListTimers(ctx.Event.GroupID)))
|
||||
})
|
||||
// 随机点名
|
||||
engine.OnFullMatchGroup([]string{"翻牌"}, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
engine.OnFullMatchGroup([]string{"翻牌"}, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
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,
|
||||
@@ -345,7 +354,6 @@ func init() { // 插件主体
|
||||
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("幸运儿居然是我自己"))
|
||||
@@ -367,13 +375,13 @@ func init() { // 插件主体
|
||||
)
|
||||
})
|
||||
// 入群欢迎
|
||||
engine.OnNotice().SetBlock(false).FirstPriority().
|
||||
engine.OnNotice().SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.NoticeType == "group_increase" && ctx.Event.SelfID != ctx.Event.UserID {
|
||||
var w welcome
|
||||
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(w.Msg))
|
||||
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(strings.ReplaceAll(w.Msg, "{at}", "[CQ:at,qq="+strconv.FormatInt(ctx.Event.UserID, 10)+"]")))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("欢迎~"))
|
||||
}
|
||||
@@ -419,16 +427,15 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
// 退群提醒
|
||||
engine.OnNotice().SetBlock(false).SetPriority(40).
|
||||
engine.OnNotice().SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.NoticeType == "group_decrease" {
|
||||
userid := ctx.Event.UserID
|
||||
nickname := ctx.GetStrangerInfo(userid, false).Get("nickname").String()
|
||||
ctx.SendChain(message.Text(nickname, "(", userid, ")", "离开了我们..."))
|
||||
ctx.SendChain(message.Text(ctxext.CardOrNickName(ctx, userid), "(", userid, ")", "离开了我们..."))
|
||||
}
|
||||
})
|
||||
// 设置欢迎语
|
||||
engine.OnRegex(`^设置欢迎语([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^设置欢迎语([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
w := &welcome{
|
||||
GrpID: ctx.Event.GroupID,
|
||||
@@ -441,8 +448,19 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("出错啦: ", err))
|
||||
}
|
||||
})
|
||||
// 测试欢迎语
|
||||
engine.OnFullMatch("测试欢迎语", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var w welcome
|
||||
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
|
||||
if err == nil {
|
||||
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(strings.ReplaceAll(w.Msg, "{at}", "[CQ:at,qq="+strconv.FormatInt(ctx.Event.UserID, 10)+"]")))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("欢迎~"))
|
||||
}
|
||||
})
|
||||
// 入群后验证开关
|
||||
engine.OnRegex(`^(.*)入群验证$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^(.*)入群验证$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
option := ctx.State["regex_matched"].([]string)[1]
|
||||
c, ok := control.Lookup("manager")
|
||||
@@ -467,7 +485,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
})
|
||||
// 加群 gist 验证开关
|
||||
engine.OnRegex(`^(.*)gist加群自动审批$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
engine.OnRegex(`^(.*)gist加群自动审批$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
option := ctx.State["regex_matched"].([]string)[1]
|
||||
c, ok := control.Lookup("manager")
|
||||
@@ -491,19 +509,10 @@ func init() { // 插件主体
|
||||
}
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
})
|
||||
// 运行 CQ 码
|
||||
engine.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(0).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var cmd = ctx.State["regex_matched"].([]string)[1]
|
||||
cmd = strings.ReplaceAll(cmd, "[", "[")
|
||||
cmd = strings.ReplaceAll(cmd, "]", "]")
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(cmd)
|
||||
})
|
||||
// 根据 gist 自动同意加群
|
||||
// 加群请在github新建一个gist,其文件名为本群群号的字符串的md5(小写),内容为一行,是当前unix时间戳(10分钟内有效)。
|
||||
// 然后请将您的用户名和gist哈希(小写)按照username/gisthash的格式填写到回答即可。
|
||||
engine.OnRequest().SetBlock(false).FirstPriority().Handle(func(ctx *zero.Ctx) {
|
||||
engine.OnRequest().SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
||||
/*if ctx.Event.RequestType == "friend" {
|
||||
ctx.SetFriendAddRequest(ctx.Event.Flag, true, "")
|
||||
}*/
|
||||
16
plugin/manager/timer/msg.go
Normal file
16
plugin/manager/timer/msg.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package timer
|
||||
|
||||
import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func (t *Timer) sendmsg(grp int64, ctx *zero.Ctx) {
|
||||
ctx.Event = new(zero.Event)
|
||||
ctx.Event.GroupID = grp
|
||||
if t.URL == "" {
|
||||
ctx.SendChain(atall, message.Text(t.Alert))
|
||||
} else {
|
||||
ctx.SendChain(atall, message.Text(t.Alert), message.Image(t.URL).Add("cache", "0"))
|
||||
}
|
||||
}
|
||||
@@ -14,29 +14,29 @@ import (
|
||||
)
|
||||
|
||||
// GetTimerInfo 获得标准化定时字符串
|
||||
func (ts *Timer) GetTimerInfo() string {
|
||||
if ts.Cron != "" {
|
||||
return fmt.Sprintf("[%d]%s", ts.GrpId, ts.Cron)
|
||||
func (t *Timer) GetTimerInfo() string {
|
||||
if t.Cron != "" {
|
||||
return fmt.Sprintf("[%d]%s", t.GrpID, t.Cron)
|
||||
}
|
||||
return fmt.Sprintf("[%d]%d月%d日%d周%d:%d", ts.GrpId, ts.Month(), ts.Day(), ts.Week(), ts.Hour(), ts.Minute())
|
||||
return fmt.Sprintf("[%d]%d月%d日%d周%d:%d", t.GrpID, t.Month(), t.Day(), t.Week(), t.Hour(), t.Minute())
|
||||
}
|
||||
|
||||
// GetTimerInfo 获得标准化 ID
|
||||
func (ts *Timer) GetTimerID() uint32 {
|
||||
key := ts.GetTimerInfo()
|
||||
// GetTimerID 获得标准化 ID
|
||||
func (t *Timer) GetTimerID() uint32 {
|
||||
key := t.GetTimerInfo()
|
||||
m := md5.Sum(helper.StringToBytes(key))
|
||||
return binary.LittleEndian.Uint32(m[:4])
|
||||
}
|
||||
|
||||
// GetFilledCronTimer 获得以cron填充好的ts
|
||||
func GetFilledCronTimer(croncmd string, alert string, img string, botqq, gid int64) *Timer {
|
||||
var ts Timer
|
||||
ts.Alert = alert
|
||||
ts.Cron = croncmd
|
||||
ts.Url = img
|
||||
ts.Selfid = botqq
|
||||
ts.GrpId = gid
|
||||
return &ts
|
||||
var t Timer
|
||||
t.Alert = alert
|
||||
t.Cron = croncmd
|
||||
t.URL = img
|
||||
t.SelfID = botqq
|
||||
t.GrpID = gid
|
||||
return &t
|
||||
}
|
||||
|
||||
// GetFilledTimer 获得填充好的ts
|
||||
@@ -46,79 +46,79 @@ func GetFilledTimer(dateStrs []string, botqq, grp int64, matchDateOnly bool) *Ti
|
||||
hourStr := []rune(dateStrs[3])
|
||||
minuteStr := []rune(dateStrs[4])
|
||||
|
||||
var ts Timer
|
||||
var t Timer
|
||||
mon := time.Month(chineseNum2Int(monthStr))
|
||||
if (mon != -1 && mon <= 0) || mon > 12 { // 月份非法
|
||||
ts.Alert = "月份非法!"
|
||||
return &ts
|
||||
t.Alert = "月份非法!"
|
||||
return &t
|
||||
}
|
||||
ts.SetMonth(mon)
|
||||
t.SetMonth(mon)
|
||||
lenOfDW := len(dayWeekStr)
|
||||
switch {
|
||||
case lenOfDW == 4: // 包括末尾的"日"
|
||||
dayWeekStr = []rune{dayWeekStr[0], dayWeekStr[2]} // 去除中间的十
|
||||
d := chineseNum2Int(dayWeekStr)
|
||||
if (d != -1 && d <= 0) || d > 31 { // 日期非法
|
||||
ts.Alert = "日期非法1!"
|
||||
return &ts
|
||||
t.Alert = "日期非法1!"
|
||||
return &t
|
||||
}
|
||||
ts.SetDay(d)
|
||||
t.SetDay(d)
|
||||
case dayWeekStr[lenOfDW-1] == rune('日'): // xx日
|
||||
dayWeekStr = dayWeekStr[:lenOfDW-1]
|
||||
d := chineseNum2Int(dayWeekStr)
|
||||
if (d != -1 && d <= 0) || d > 31 { // 日期非法
|
||||
ts.Alert = "日期非法2!"
|
||||
return &ts
|
||||
t.Alert = "日期非法2!"
|
||||
return &t
|
||||
}
|
||||
ts.SetDay(d)
|
||||
t.SetDay(d)
|
||||
case dayWeekStr[0] == rune('每'): // 每周
|
||||
ts.SetWeek(-1)
|
||||
t.SetWeek(-1)
|
||||
default: // 周x
|
||||
w := chineseNum2Int(dayWeekStr[1:])
|
||||
if w == 7 { // 周天是0
|
||||
w = 0
|
||||
}
|
||||
if w < 0 || w > 6 { // 星期非法
|
||||
ts.Alert = "星期非法!"
|
||||
return &ts
|
||||
t.Alert = "星期非法!"
|
||||
return &t
|
||||
}
|
||||
ts.SetWeek(time.Weekday(w))
|
||||
t.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
|
||||
t.Alert = "小时非法!"
|
||||
return &t
|
||||
}
|
||||
ts.SetHour(h)
|
||||
t.SetHour(h)
|
||||
if len(minuteStr) == 3 {
|
||||
minuteStr = []rune{minuteStr[0], minuteStr[2]} // 去除中间的十
|
||||
}
|
||||
min := chineseNum2Int(minuteStr)
|
||||
if min < -1 || min > 59 { // 分钟非法
|
||||
ts.Alert = "分钟非法!"
|
||||
return &ts
|
||||
t.Alert = "分钟非法!"
|
||||
return &t
|
||||
}
|
||||
ts.SetMinute(min)
|
||||
t.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"
|
||||
t.URL = urlStr[3:] // utf-8下用为3字节
|
||||
logrus.Println("[群管]" + t.URL)
|
||||
if !strings.HasPrefix(t.URL, "http") {
|
||||
t.URL = "illegal"
|
||||
logrus.Println("[群管]url非法!")
|
||||
return &ts
|
||||
return &t
|
||||
}
|
||||
}
|
||||
ts.Alert = dateStrs[6]
|
||||
ts.SetEn(true)
|
||||
t.Alert = dateStrs[6]
|
||||
t.SetEn(true)
|
||||
}
|
||||
ts.Selfid = botqq
|
||||
ts.GrpId = grp
|
||||
return &ts
|
||||
t.SelfID = botqq
|
||||
t.GrpID = grp
|
||||
return &t
|
||||
}
|
||||
|
||||
// chineseNum2Int 汉字数字转int,仅支持-10~99,最多两位数,其中"每"解释为-1,"每二"为-2,以此类推
|
||||
@@ -155,13 +155,12 @@ func chineseNum2Int(rs []rune) int {
|
||||
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
|
||||
}
|
||||
match := []rune("零一二三四五六七八九十")
|
||||
for i, m := range match {
|
||||
if c == m {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -15,13 +15,13 @@ func firstWeek(date *time.Time, week time.Weekday) (d time.Time) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ts *Timer) nextWakeTime() (date time.Time) {
|
||||
func (t *Timer) nextWakeTime() (date time.Time) {
|
||||
date = time.Now()
|
||||
m := ts.Month()
|
||||
d := ts.Day()
|
||||
h := ts.Hour()
|
||||
mn := ts.Minute()
|
||||
w := ts.Week()
|
||||
m := t.Month()
|
||||
d := t.Day()
|
||||
h := t.Hour()
|
||||
mn := t.Minute()
|
||||
w := t.Week()
|
||||
var unit time.Duration
|
||||
logrus.Debugln("[timer] unit init:", unit)
|
||||
if mn >= 0 {
|
||||
@@ -74,35 +74,35 @@ func (ts *Timer) nextWakeTime() (date time.Time) {
|
||||
}
|
||||
switch stable {
|
||||
case 0b0101:
|
||||
if ts.Day() != time.Now().Day() || ts.Month() != time.Now().Month() {
|
||||
if t.Day() != time.Now().Day() || t.Month() != time.Now().Month() {
|
||||
h = 0
|
||||
}
|
||||
case 0b1001:
|
||||
if ts.Month() != time.Now().Month() {
|
||||
if t.Month() != time.Now().Month() {
|
||||
d = 0
|
||||
}
|
||||
case 0b0001:
|
||||
if ts.Month() != time.Now().Month() {
|
||||
if t.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())
|
||||
date = time.Date(date.Year(), m, d, h, 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) {
|
||||
if t.Month() < 0 {
|
||||
if t.Day() > 0 || (t.Day() == 0 && t.Week() >= 0) {
|
||||
date = date.AddDate(0, 1, 0)
|
||||
} else if ts.Day() < 0 || ts.Week() < 0 {
|
||||
if ts.Hour() > 0 {
|
||||
} else if t.Day() < 0 || t.Week() < 0 {
|
||||
if t.Hour() > 0 {
|
||||
date = date.AddDate(0, 0, 1)
|
||||
} else if ts.Minute() > 0 {
|
||||
} else if t.Minute() > 0 {
|
||||
date = date.Add(time.Hour)
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ func (ts *Timer) nextWakeTime() (date time.Time) {
|
||||
}
|
||||
}
|
||||
logrus.Debugln("[timer] date after fix:", date)
|
||||
if stable&0x8 != 0 && date.Hour() != int(h) {
|
||||
if stable&0x8 != 0 && date.Hour() != h {
|
||||
switch {
|
||||
case stable&0x4 == 0:
|
||||
date = date.AddDate(0, 0, 1).Add(-time.Hour)
|
||||
@@ -124,7 +124,7 @@ func (ts *Timer) nextWakeTime() (date time.Time) {
|
||||
}
|
||||
}
|
||||
logrus.Debugln("[timer] date after s8:", date)
|
||||
if stable&0x4 != 0 && date.Day() != int(d) {
|
||||
if stable&0x4 != 0 && date.Day() != d {
|
||||
switch {
|
||||
case stable*0x1 == 0:
|
||||
date = date.AddDate(0, 1, -1)
|
||||
@@ -140,7 +140,7 @@ func (ts *Timer) nextWakeTime() (date time.Time) {
|
||||
default:
|
||||
date = date.AddDate(1, 0, 0)
|
||||
}
|
||||
date = firstWeek(&date, time.Weekday(w))
|
||||
date = firstWeek(&date, w)
|
||||
}
|
||||
logrus.Debugln("[timer] date after s2:", date)
|
||||
if time.Until(date) <= 0 {
|
||||
@@ -149,14 +149,14 @@ func (ts *Timer) nextWakeTime() (date time.Time) {
|
||||
return date
|
||||
}
|
||||
|
||||
func (ts *Timer) judgeHM() {
|
||||
if ts.Hour() < 0 || ts.Hour() == time.Now().Hour() {
|
||||
if ts.Minute() < 0 || ts.Minute() == time.Now().Minute() {
|
||||
if ts.Selfid != 0 {
|
||||
ts.sendmsg(ts.GrpId, zero.GetBot(ts.Selfid))
|
||||
func (t *Timer) judgeHM() {
|
||||
if t.Hour() < 0 || t.Hour() == time.Now().Hour() {
|
||||
if t.Minute() < 0 || t.Minute() == time.Now().Minute() {
|
||||
if t.SelfID != 0 {
|
||||
t.sendmsg(t.GrpID, zero.GetBot(t.SelfID))
|
||||
} else {
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) (_ bool) {
|
||||
ts.sendmsg(ts.GrpId, ctx)
|
||||
t.sendmsg(t.GrpID, ctx)
|
||||
return
|
||||
})
|
||||
}
|
||||
@@ -1,26 +1,28 @@
|
||||
package timer
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
)
|
||||
|
||||
// Timer 计时器
|
||||
type Timer struct {
|
||||
Id uint32 `db:"id"`
|
||||
ID uint32 `db:"id"`
|
||||
En1Month4Day5Week3Hour5Min6 int32 `db:"emdwhm"`
|
||||
Selfid int64 `db:"sid"`
|
||||
GrpId int64 `db:"gid"`
|
||||
SelfID int64 `db:"sid"`
|
||||
GrpID int64 `db:"gid"`
|
||||
Alert string `db:"alert"`
|
||||
Cron string `db:"cron"`
|
||||
Url string `db:"url"`
|
||||
URL string `db:"url"`
|
||||
}
|
||||
|
||||
// InsertInto 插入自身
|
||||
func (t *Timer) InsertInto(db *sql.Sqlite) error {
|
||||
return db.Insert("timer", t)
|
||||
}
|
||||
|
||||
/*
|
||||
func getTimerFrom(db *sql.Sqlite, id uint32) (t Timer, err error) {
|
||||
err = db.Find("timer", &t, "where id = "+strconv.Itoa(int(id)))
|
||||
return
|
||||
}
|
||||
*/
|
||||
@@ -7,15 +7,14 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"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"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
)
|
||||
|
||||
// Clock 时钟
|
||||
type Clock struct {
|
||||
db *sql.Sqlite
|
||||
timers *(map[uint32]*Timer)
|
||||
@@ -37,10 +36,12 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// NewClock 添加一个新时钟
|
||||
func NewClock(db *sql.Sqlite) (c Clock) {
|
||||
c.loadTimers(db)
|
||||
c.cron = cron.New()
|
||||
c.entries = make(map[uint32]cron.EntryID)
|
||||
c.timers = &map[uint32]*Timer{}
|
||||
c.loadTimers(db)
|
||||
c.cron.Start()
|
||||
return
|
||||
}
|
||||
@@ -50,9 +51,9 @@ func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
|
||||
var key uint32
|
||||
if save {
|
||||
key = ts.GetTimerID()
|
||||
ts.Id = key
|
||||
ts.ID = key
|
||||
} else {
|
||||
key = ts.Id
|
||||
key = ts.ID
|
||||
}
|
||||
t, ok := c.GetTimer(key)
|
||||
if t != ts && ok { // 避免重复注册定时器
|
||||
@@ -61,30 +62,34 @@ func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
|
||||
logrus.Println("[群管]注册计时器", key)
|
||||
if ts.Cron != "" {
|
||||
var ctx *zero.Ctx
|
||||
if ts.Selfid != 0 {
|
||||
ctx = zero.GetBot(ts.Selfid)
|
||||
if ts.SelfID != 0 {
|
||||
ctx = zero.GetBot(ts.SelfID)
|
||||
} else {
|
||||
zero.RangeBot(func(id int64, c *zero.Ctx) bool {
|
||||
ctx = c
|
||||
ts.Selfid = id
|
||||
ts.SelfID = id
|
||||
return false
|
||||
})
|
||||
}
|
||||
eid, err := c.cron.AddFunc(ts.Cron, func() { ts.sendmsg(ts.GrpId, ctx) })
|
||||
eid, err := c.cron.AddFunc(ts.Cron, func() { ts.sendmsg(ts.GrpID, ctx) })
|
||||
if err == nil {
|
||||
c.entmu.Lock()
|
||||
c.entries[key] = eid
|
||||
c.entmu.Unlock()
|
||||
if save {
|
||||
err = c.AddTimer(ts)
|
||||
err = c.AddTimerIntoDB(ts)
|
||||
}
|
||||
if err == nil {
|
||||
err = c.AddTimerIntoMap(ts)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
ts.Alert = err.Error()
|
||||
} else {
|
||||
if save {
|
||||
_ = c.AddTimer(ts)
|
||||
_ = c.AddTimerIntoDB(ts)
|
||||
}
|
||||
_ = c.AddTimerIntoMap(ts)
|
||||
for ts.En() {
|
||||
nextdate := ts.nextWakeTime()
|
||||
sleepsec := time.Until(nextdate)
|
||||
@@ -135,7 +140,7 @@ func (c *Clock) ListTimers(grpID int64) []string {
|
||||
c.timersmu.RLock()
|
||||
keys := make([]string, 0, len(*c.timers))
|
||||
for _, v := range *c.timers {
|
||||
if v.GrpId == grpID {
|
||||
if v.GrpID == grpID {
|
||||
k := v.GetTimerInfo()
|
||||
start := strings.Index(k, "]")
|
||||
msg := strings.ReplaceAll(k[start+1:]+"\n", "-1", "每")
|
||||
@@ -147,11 +152,11 @@ func (c *Clock) ListTimers(grpID int64) []string {
|
||||
}
|
||||
c.timersmu.RUnlock()
|
||||
return keys
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTimer 获得定时器
|
||||
func (c *Clock) GetTimer(key uint32) (t *Timer, ok bool) {
|
||||
c.timersmu.RLock()
|
||||
t, ok = (*c.timers)[key]
|
||||
@@ -159,25 +164,31 @@ func (c *Clock) GetTimer(key uint32) (t *Timer, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Clock) AddTimer(t *Timer) (err error) {
|
||||
// AddTimerIntoDB 添加定时器
|
||||
func (c *Clock) AddTimerIntoDB(t *Timer) (err error) {
|
||||
c.timersmu.Lock()
|
||||
(*c.timers)[t.Id] = t
|
||||
err = c.db.Insert("timer", t)
|
||||
c.timersmu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// AddTimerIntoMap 添加定时器到缓存
|
||||
func (c *Clock) AddTimerIntoMap(t *Timer) (err error) {
|
||||
c.timersmu.Lock()
|
||||
(*c.timers)[t.ID] = t
|
||||
c.timersmu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Clock) loadTimers(db *sql.Sqlite) {
|
||||
if file.IsExist(db.DBPath) {
|
||||
c.db = db
|
||||
err := c.db.Create("timer", &Timer{})
|
||||
if err == nil {
|
||||
var t Timer
|
||||
c.db.FindFor("timer", &t, "", func() error {
|
||||
tescape := t
|
||||
go c.RegisterTimer(&tescape, false)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
c.db = db
|
||||
err := c.db.Create("timer", &Timer{})
|
||||
if err == nil {
|
||||
var t Timer
|
||||
_ = c.db.FindFor("timer", &t, "", func() error {
|
||||
tescape := t
|
||||
go c.RegisterTimer(&tescape, false)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -22,3 +23,11 @@ func TestNextWakeTime(t *testing.T) {
|
||||
t.Log(t1)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
func TestClock(t *testing.T) {
|
||||
db := &sql.Sqlite{DBPath: "test.db"}
|
||||
c := NewClock(db)
|
||||
c.AddTimerIntoDB(GetFilledTimer([]string{"", "12", "-1", "12", "0", "", "test"}, 0, 0, false))
|
||||
t.Log(c.ListTimers(0))
|
||||
t.Fail()
|
||||
}
|
||||
87
plugin/manager/timer/wrap.go
Normal file
87
plugin/manager/timer/wrap.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package timer
|
||||
|
||||
import "time"
|
||||
|
||||
// En isEnabled 1bit
|
||||
func (t *Timer) En() (en bool) {
|
||||
return t.En1Month4Day5Week3Hour5Min6&0x800000 != 0
|
||||
}
|
||||
|
||||
// Month 4bits
|
||||
func (t *Timer) Month() (mon time.Month) {
|
||||
mon = time.Month((t.En1Month4Day5Week3Hour5Min6 & 0x780000) >> 19)
|
||||
if mon == 0b1111 {
|
||||
mon = -1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Day 5bits
|
||||
func (t *Timer) Day() (d int) {
|
||||
d = int((t.En1Month4Day5Week3Hour5Min6 & 0x07c000) >> 14)
|
||||
if d == 0b11111 {
|
||||
d = -1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Week 3bits
|
||||
func (t *Timer) Week() (w time.Weekday) {
|
||||
w = time.Weekday((t.En1Month4Day5Week3Hour5Min6 & 0x003800) >> 11)
|
||||
if w == 0b111 {
|
||||
w = -1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Hour 5bits
|
||||
func (t *Timer) Hour() (h int) {
|
||||
h = int((t.En1Month4Day5Week3Hour5Min6 & 0x0007c0) >> 6)
|
||||
if h == 0b11111 {
|
||||
h = -1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Minute 6bits
|
||||
func (t *Timer) Minute() (min int) {
|
||||
min = int(t.En1Month4Day5Week3Hour5Min6 & 0x00003f)
|
||||
if min == 0b111111 {
|
||||
min = -1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetEn ...
|
||||
func (t *Timer) SetEn(en bool) {
|
||||
if en {
|
||||
t.En1Month4Day5Week3Hour5Min6 |= 0x800000
|
||||
} else {
|
||||
t.En1Month4Day5Week3Hour5Min6 &= 0x7fffff
|
||||
}
|
||||
}
|
||||
|
||||
// SetMonth ...
|
||||
func (t *Timer) SetMonth(mon time.Month) {
|
||||
t.En1Month4Day5Week3Hour5Min6 = ((int32(mon) << 19) & 0x780000) | (t.En1Month4Day5Week3Hour5Min6 & 0x87ffff)
|
||||
}
|
||||
|
||||
// SetDay ...
|
||||
func (t *Timer) SetDay(d int) {
|
||||
t.En1Month4Day5Week3Hour5Min6 = ((int32(d) << 14) & 0x07c000) | (t.En1Month4Day5Week3Hour5Min6 & 0xf83fff)
|
||||
}
|
||||
|
||||
// SetWeek ...
|
||||
func (t *Timer) SetWeek(w time.Weekday) {
|
||||
t.En1Month4Day5Week3Hour5Min6 = ((int32(w) << 11) & 0x003800) | (t.En1Month4Day5Week3Hour5Min6 & 0xffc7ff)
|
||||
}
|
||||
|
||||
// SetHour ...
|
||||
func (t *Timer) SetHour(h int) {
|
||||
t.En1Month4Day5Week3Hour5Min6 = ((int32(h) << 6) & 0x0007c0) | (t.En1Month4Day5Week3Hour5Min6 & 0xfff83f)
|
||||
}
|
||||
|
||||
// SetMinute ...
|
||||
func (t *Timer) SetMinute(min int) {
|
||||
t.En1Month4Day5Week3Hour5Min6 = (int32(min) & 0x00003f) | (t.En1Month4Day5Week3Hour5Min6 & 0xffffc0)
|
||||
}
|
||||
@@ -8,11 +8,10 @@ import (
|
||||
reg "github.com/fumiama/go-registry"
|
||||
)
|
||||
|
||||
var sr = reg.NewRegedit("reilia.eastasia.azurecontainer.io:32664", "fumiama", "--")
|
||||
var sr = reg.NewRegedit("reilia.westeurope.cloudapp.azure.com:32664", "fumiama", "--")
|
||||
|
||||
func TestGetHoliday(t *testing.T) {
|
||||
registry.Connect()
|
||||
holidaymap = make(map[string]*Holiday)
|
||||
h := GetHoliday("元旦")
|
||||
registry.Close()
|
||||
t.Fatal(h)
|
||||
@@ -24,11 +23,11 @@ func TestSetHoliday(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = SetHoliday("元旦", 1, 2022, 1, 1)
|
||||
err = SetHoliday("元旦", 1, 2023, 1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = SetHoliday("春节", 7, 2022, 1, 31)
|
||||
err = SetHoliday("春节", 7, 2023, 1, 21)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -21,32 +21,23 @@ 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}
|
||||
}
|
||||
|
||||
var (
|
||||
registry = reg.NewRegReader("reilia.eastasia.azurecontainer.io:32664", "fumiama")
|
||||
holidaymap map[string]*Holiday
|
||||
)
|
||||
var registry = reg.NewRegReader("reilia.westeurope.cloudapp.azure.com:32664", "fumiama")
|
||||
|
||||
// GetHoliday 从 reg 服务器获取节日
|
||||
func GetHoliday(name string) *Holiday {
|
||||
var dur, year int
|
||||
var month time.Month
|
||||
var day int
|
||||
h, ok := holidaymap[name]
|
||||
if ok {
|
||||
return h
|
||||
}
|
||||
ret, err := registry.Get("holiday/" + name)
|
||||
if err != nil {
|
||||
return NewHoliday(name+err.Error(), 0, 0, 0, 0)
|
||||
}
|
||||
fmt.Sscanf(ret, "%d_%d_%d_%d", &dur, &year, &month, &day)
|
||||
logrus.Debugln("[moyu]获取节日:", name, dur, year, month, day)
|
||||
h = NewHoliday(name, dur, year, month, day)
|
||||
holidaymap[name] = h
|
||||
return h
|
||||
return NewHoliday(name, dur, year, month, day)
|
||||
}
|
||||
|
||||
// 获取两个时间相差
|
||||
// String 获取两个时间相差
|
||||
func (h *Holiday) String() string {
|
||||
d := time.Until(h.date)
|
||||
switch {
|
||||
69
plugin/moyu/run.go
Normal file
69
plugin/moyu/run.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Package moyu 摸鱼
|
||||
package moyu
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("moyu", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: true,
|
||||
Help: "moyu\n" +
|
||||
"- /启用 moyu\n" +
|
||||
"- /禁用 moyu",
|
||||
})
|
||||
|
||||
// 定时任务每天10点执行一次
|
||||
_, err := process.CronTab.AddFunc("0 10 * * *", func() { sendNotice() })
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据拼接消息链并发送
|
||||
func sendNotice() {
|
||||
m, ok := control.Lookup("moyu")
|
||||
if ok {
|
||||
if registry.Connect() != nil {
|
||||
return
|
||||
}
|
||||
msg := message.Message{
|
||||
message.Text(time.Now().Format("2006-01-02")),
|
||||
message.Text("上午好,摸鱼人!\n工作再累,一定不要忘记摸鱼哦!有事没事起身去茶水间,去厕所,去廊道走走别老在工位上坐着,钱是老板的,但命是自己的。\n"),
|
||||
message.Text(weekend()),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("元旦")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("春节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("清明节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("劳动节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("端午节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("中秋节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("国庆节")),
|
||||
message.Text("\n"),
|
||||
message.Text("上班是帮老板赚钱,摸鱼是赚老板的钱!最后,祝愿天下所有摸鱼人,都能愉快的渡过每一天…"),
|
||||
}
|
||||
_ = registry.Close()
|
||||
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, msg)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
226
plugin/moyu_calendar/calendar.go
Normal file
226
plugin/moyu_calendar/calendar.go
Normal file
@@ -0,0 +1,226 @@
|
||||
// Package moyucalendar 摸鱼人日历
|
||||
package moyucalendar
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
xpath "github.com/antchfx/htmlquery"
|
||||
)
|
||||
|
||||
var ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"
|
||||
var weixin = regexp.MustCompile(`url \+= '(.+)';`)
|
||||
|
||||
var client = &http.Client{}
|
||||
|
||||
func init() {
|
||||
control.Register("moyucalendar", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: true,
|
||||
Help: "摸鱼人日历\n" +
|
||||
"- /启用 moyucalendar\n" +
|
||||
"- /禁用 moyucalendar",
|
||||
}).OnFullMatch("摸鱼人日历").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
title := fmt.Sprintf("摸鱼人日历 %d月%d日", time.Now().Month(), time.Now().Day())
|
||||
sg, cookies, err := sougou(title, "摸鱼人日历", ua)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
wx, err := redirect(sg, cookies, ua)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
image, err := calendar(wx, ua)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(image))
|
||||
})
|
||||
|
||||
// 定时任务每天8点30分执行一次
|
||||
_, err := process.CronTab.AddFunc("30 8 * * *", func() {
|
||||
m, ok := control.Lookup("moyucalendar")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
title := fmt.Sprintf("摸鱼人日历 %d月%d日", time.Now().Month(), time.Now().Day())
|
||||
sg, cookies, err := sougou(title, "摸鱼人日历", ua)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
wx, err := redirect(sg, cookies, ua)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
image, err := calendar(wx, ua)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
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.Message{message.Image(image)})
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func sougou(title, publisher, ua string) (string, []*http.Cookie, error) {
|
||||
u, _ := url.Parse("https://weixin.sogou.com/weixin")
|
||||
u.RawQuery = url.Values{
|
||||
"type": []string{"2"},
|
||||
"s_from": []string{"input"},
|
||||
"query": []string{title},
|
||||
}.Encode()
|
||||
req, err := http.NewRequest("GET", u.String(), nil)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
req.Header.Set("User-Agent", ua)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", nil, errors.New("status not ok")
|
||||
}
|
||||
// 解析XPATH
|
||||
doc, err := xpath.Parse(resp.Body)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
// 取出每个返回的结果
|
||||
list := xpath.Find(doc, `//*[@class="news-list"]/li/div[@class="txt-box"]`)
|
||||
if len(list) == 0 {
|
||||
return "", nil, errors.New("sougou result not found")
|
||||
}
|
||||
var match string
|
||||
for i := range list {
|
||||
account := xpath.FindOne(list[i], `//div[@class="s-p"]/a[@class="account"]`)
|
||||
if account == nil {
|
||||
continue
|
||||
}
|
||||
if xpath.InnerText(account) != publisher {
|
||||
continue
|
||||
}
|
||||
target := xpath.FindOne(list[i], `//h3/a[@target="_blank"]`)
|
||||
if target == nil {
|
||||
continue
|
||||
}
|
||||
match = xpath.SelectAttr(target, "href")
|
||||
break
|
||||
}
|
||||
if match == "" {
|
||||
return "", nil, errors.New("sougou result not found")
|
||||
}
|
||||
return "https://weixin.sogou.com" + match, resp.Cookies(), nil
|
||||
}
|
||||
|
||||
func redirect(link string, cookies []*http.Cookie, ua string) (string, error) {
|
||||
req, err := http.NewRequest("GET", link, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("User-Agent", ua)
|
||||
var c = make([]string, 0, 4)
|
||||
for _, cookie := range cookies {
|
||||
if cookie.Name != "ABTEST" && cookie.Name != "SNUID" &&
|
||||
cookie.Name != "IPLOC" && cookie.Name != "SUID" {
|
||||
continue
|
||||
}
|
||||
c = append(c, cookie.Name+"="+cookie.Value)
|
||||
}
|
||||
req.Header.Set("Cookie", strings.Join(c, "; "))
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", errors.New("status not ok")
|
||||
}
|
||||
br := bufio.NewReader(resp.Body)
|
||||
var u = make([]string, 0)
|
||||
for {
|
||||
b, _, err := br.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
matcha := weixin.FindStringSubmatch(string(b))
|
||||
if len(matcha) < 2 {
|
||||
continue
|
||||
}
|
||||
u = append(u, strings.ReplaceAll(matcha[1], "@", ""))
|
||||
}
|
||||
if len(u) == 0 {
|
||||
return "", errors.New("weixin url not found")
|
||||
}
|
||||
return strings.Join(u, ""), nil
|
||||
}
|
||||
|
||||
func calendar(link, ua string) (string, error) {
|
||||
req, err := http.NewRequest("GET", link, nil)
|
||||
req.Header.Set("User-Agent", ua)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", errors.New("status not ok")
|
||||
}
|
||||
doc, err := xpath.Parse(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
html := xpath.OutputHTML(doc, false)
|
||||
if !strings.Contains(html, time.Now().Format("2006-01-02")) {
|
||||
return "", errors.New("calendar not today")
|
||||
}
|
||||
images := xpath.Find(doc, `//*[@id="js_content"]/p/img`)
|
||||
if images == nil {
|
||||
return "", errors.New("calendar not found")
|
||||
}
|
||||
var image string
|
||||
for i := range images {
|
||||
if xpath.SelectAttr(images[i], "data-w") != "540" {
|
||||
continue
|
||||
}
|
||||
image = xpath.SelectAttr(images[i], "data-src")
|
||||
break
|
||||
}
|
||||
if image == "" {
|
||||
return "", errors.New("image not found")
|
||||
}
|
||||
return image, nil
|
||||
}
|
||||
@@ -5,36 +5,31 @@ import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"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/zbputils/control/order"
|
||||
)
|
||||
|
||||
var limit = rate.NewManager(time.Minute*3, 5)
|
||||
|
||||
func init() {
|
||||
control.Register("music", &control.Options{
|
||||
control.Register("music", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "点歌\n" +
|
||||
"- 点歌[xxx]\n" +
|
||||
"- 网易点歌[xxx]\n" +
|
||||
"- 酷我点歌[xxx]\n" +
|
||||
"- 酷狗点歌[xxx]",
|
||||
}).OnRegex("^(.{0,2})点歌(.{1,25})$").SetBlock(true).FirstPriority().
|
||||
}).OnRegex(`^(.{0,2})点歌\s?(.{1,25})$`).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.SendChain(message.Text("请稍后重试0x0..."))
|
||||
return
|
||||
}
|
||||
// switch 平台
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "酷我":
|
||||
@@ -236,7 +231,7 @@ func netGet(url string, header http.Header) []byte {
|
||||
return nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
result, _ := ioutil.ReadAll(res.Body)
|
||||
result, _ := io.ReadAll(res.Body)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -250,6 +245,6 @@ func netPost(url string, data url.Values, header http.Header) []byte {
|
||||
return nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
result, _ := ioutil.ReadAll(res.Body)
|
||||
result, _ := io.ReadAll(res.Body)
|
||||
return result
|
||||
}
|
||||
114
plugin/nativesetu/data.go
Normal file
114
plugin/nativesetu/data.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package nativesetu
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"io/fs"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/corona10/goimagehash"
|
||||
"github.com/sirupsen/logrus"
|
||||
_ "golang.org/x/image/webp" // import webp decoding
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
)
|
||||
|
||||
// setuclass holds setus in a folder, which is the class name.
|
||||
type setuclass struct {
|
||||
ImgID int64 `db:"imgid"` // ImgID 图片唯一 id (dhash)
|
||||
Name string `db:"name"` // Name 图片名
|
||||
Path string `db:"path"` // Path 图片路径
|
||||
}
|
||||
|
||||
var ns = &nsetu{db: &sql.Sqlite{}}
|
||||
|
||||
type nsetu struct {
|
||||
db *sql.Sqlite
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func (n *nsetu) List() (l []string) {
|
||||
if file.IsExist(n.db.DBPath) {
|
||||
err := n.db.Open()
|
||||
if err == nil {
|
||||
l, err = n.db.ListTables()
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Errorln("[nsetu]", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (n *nsetu) scanall(path string) error {
|
||||
model := &setuclass{}
|
||||
root := os.DirFS(path)
|
||||
_ = n.db.Close()
|
||||
_ = os.Remove(n.db.DBPath)
|
||||
return fs.WalkDir(root, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
clsn := d.Name()
|
||||
if clsn != "." {
|
||||
n.mu.Lock()
|
||||
err = n.db.Create(clsn, model)
|
||||
n.mu.Unlock()
|
||||
if err == nil {
|
||||
err = n.scanclass(root, path, clsn)
|
||||
if err != nil {
|
||||
logrus.Errorln("[nsetu]", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (n *nsetu) scanclass(root fs.FS, path, clsn string) error {
|
||||
ds, err := fs.ReadDir(root, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.mu.Lock()
|
||||
_ = n.db.Truncate(clsn)
|
||||
n.mu.Unlock()
|
||||
for _, d := range ds {
|
||||
nm := d.Name()
|
||||
ln := strings.ToLower(nm)
|
||||
if !d.IsDir() &&
|
||||
(strings.HasSuffix(ln, ".jpg") || strings.HasSuffix(ln, ".jpeg") ||
|
||||
strings.HasSuffix(ln, ".png") || strings.HasSuffix(ln, ".gif") || strings.HasSuffix(ln, ".webp")) {
|
||||
relpath := path + "/" + nm
|
||||
logrus.Debugln("[nsetu] read", relpath)
|
||||
f, e := fs.ReadFile(root, relpath)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
b := bytes.NewReader(f)
|
||||
img, _, e := image.Decode(b)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
dh, e := goimagehash.DifferenceHash(img)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
dhi := int64(dh.GetHash())
|
||||
logrus.Debugln("[nsetu] insert", nm, "with id", dhi, "into", clsn)
|
||||
n.mu.Lock()
|
||||
err = n.db.Insert(clsn, &setuclass{ImgID: dhi, Name: nm, Path: relpath})
|
||||
n.mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -10,14 +10,11 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
|
||||
)
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
|
||||
const (
|
||||
datapath = "data/nsetu"
|
||||
dbfile = datapath + "/data.db"
|
||||
cfgfile = datapath + "/setupath.txt"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -25,7 +22,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("nativesetu", &control.Options{
|
||||
engine := control.Register("nativesetu", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "本地涩图\n" +
|
||||
"- 本地[xxx]\n" +
|
||||
@@ -33,32 +30,51 @@ func init() {
|
||||
"- 设置本地setu绝对路径[xxx]\n" +
|
||||
"- 刷新所有本地setu\n" +
|
||||
"- 所有本地setu分类",
|
||||
PrivateDataFolder: "nsetu",
|
||||
})
|
||||
engine.OnRegex(`^本地(.*)$`, func(ctx *zero.Ctx) bool { return rule.FirstValueInList(setuclasses)(ctx) }).SetBlock(true).SetPriority(36).
|
||||
|
||||
ns.db.DBPath = engine.DataFolder() + "data.db"
|
||||
cfgfile := engine.DataFolder() + "setupath.txt"
|
||||
if file.IsExist(cfgfile) {
|
||||
b, err := os.ReadFile(cfgfile)
|
||||
if err == nil {
|
||||
setupath = helper.BytesToString(b)
|
||||
logrus.Println("[nsetu] set setu dir to", setupath)
|
||||
}
|
||||
}
|
||||
|
||||
engine.OnRegex(`^本地(.*)$`, ctxext.FirstValueInList(ns)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
imgtype := ctx.State["regex_matched"].([]string)[1]
|
||||
sc := new(setuclass)
|
||||
mu.RLock()
|
||||
err := db.Pick(imgtype, sc)
|
||||
mu.RUnlock()
|
||||
ns.mu.RLock()
|
||||
err := ns.db.Pick(imgtype, sc)
|
||||
ns.mu.RUnlock()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
p := "file:///" + setupath + "/" + sc.Path
|
||||
if ctx.Event.GroupID != 0 {
|
||||
ctx.SendGroupForwardMessage(ctx.Event.GroupID, message.Message{
|
||||
ctxext.FakeSenderForwardNode(ctx,
|
||||
message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p),
|
||||
)})
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^刷新本地(.*)$`, func(ctx *zero.Ctx) bool { return rule.FirstValueInList(setuclasses)(ctx) }, zero.SuperUserPermission).SetBlock(true).SetPriority(36).
|
||||
engine.OnRegex(`^刷新本地(.*)$`, ctxext.FirstValueInList(ns), zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
imgtype := ctx.State["regex_matched"].([]string)[1]
|
||||
err := scanclass(os.DirFS(setupath), imgtype, imgtype)
|
||||
err := ns.scanclass(os.DirFS(setupath), imgtype, imgtype)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^设置本地setu绝对路径(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(36).
|
||||
engine.OnRegex(`^设置本地setu绝对路径(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
setupath = ctx.State["regex_matched"].([]string)[1]
|
||||
err := os.WriteFile(cfgfile, helper.StringToBytes(setupath), 0644)
|
||||
@@ -68,21 +84,21 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("刷新所有本地setu", zero.SuperUserPermission).SetBlock(true).SetPriority(36).
|
||||
engine.OnFullMatch("刷新所有本地setu", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := scanall(setupath)
|
||||
err := ns.scanall(setupath)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("所有本地setu分类").SetBlock(true).SetPriority(36).
|
||||
engine.OnFullMatch("所有本地setu分类").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := "所有本地setu分类"
|
||||
mu.RLock()
|
||||
for i, c := range setuclasses {
|
||||
n, err := db.Count(c)
|
||||
ns.mu.RLock()
|
||||
for i, c := range ns.List() {
|
||||
n, err := ns.db.Count(c)
|
||||
if err == nil {
|
||||
msg += fmt.Sprintf("\n%02d. %s(%d)", i, c, n)
|
||||
} else {
|
||||
@@ -90,7 +106,7 @@ func init() {
|
||||
logrus.Errorln("[nsetu]", err)
|
||||
}
|
||||
}
|
||||
mu.RUnlock()
|
||||
ns.mu.RUnlock()
|
||||
ctx.SendChain(message.Text(msg))
|
||||
})
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// Package nativewife 本地老婆
|
||||
package nativewife
|
||||
|
||||
import (
|
||||
@@ -11,29 +12,26 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/picture"
|
||||
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/zbputils/control/order"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
)
|
||||
|
||||
const base = "data/nwife"
|
||||
|
||||
var baseuri = "file:///" + file.BOTPATH + "/" + base
|
||||
|
||||
func init() {
|
||||
err := os.MkdirAll(base, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
engine := control.Register("nwife", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "nativewife\n- 抽wife[@xxx]\n- 添加wife[名字][图片]\n- 删除wife[名字]\n- [让|不让]所有人均可添加wife",
|
||||
engine := control.Register("nwife", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "nativewife\n- 抽wife[@xxx]\n- 添加wife[名字][图片]\n- 删除wife[名字]\n- [让 | 不让]所有人均可添加wife",
|
||||
PrivateDataFolder: "nwife",
|
||||
})
|
||||
engine.OnPrefix("抽wife", zero.OnlyGroup).SetBlock(true).SetPriority(20).
|
||||
base := engine.DataFolder()
|
||||
baseuri := "file:///" + file.BOTPATH + "/" + base
|
||||
engine.OnPrefix("抽wife", zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
grpf := strconv.FormatInt(ctx.Event.GroupID, 36)
|
||||
wifes, err := os.ReadDir(base + "/" + grpf)
|
||||
@@ -49,13 +47,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("大家的wife都是", wn, "\n"), message.Image(baseuri+"/"+grpf+"/"+wn), message.Text("\n哦~"))
|
||||
default:
|
||||
// 获取名字
|
||||
name := ctx.State["args"].(string)
|
||||
if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
|
||||
qq, _ := strconv.ParseInt(ctx.Event.Message[1].Data["qq"], 10, 64)
|
||||
name = ctx.GetGroupMemberInfo(ctx.Event.GroupID, qq, false).Get("nickname").Str
|
||||
} else if name == "" {
|
||||
name = ctx.Event.Sender.NickName
|
||||
}
|
||||
name := ctxext.NickName(ctx)
|
||||
now := time.Now()
|
||||
s := md5.Sum(helper.StringToBytes(fmt.Sprintf("%s%d%d%d", name, now.Year(), now.Month(), now.Day())))
|
||||
r := rand.New(rand.NewSource(int64(binary.LittleEndian.Uint64(s[:]))))
|
||||
@@ -65,7 +57,7 @@ func init() {
|
||||
}
|
||||
})
|
||||
// 上传一张图
|
||||
engine.OnPrefix("添加wife", zero.OnlyGroup, chkAddWifePermission, picture.MustGiven).SetBlock(true).SetPriority(20).
|
||||
engine.OnPrefix("添加wife", zero.OnlyGroup, chkAddWifePermission, ctxext.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
name := ""
|
||||
for _, elem := range ctx.Event.Message {
|
||||
@@ -81,9 +73,13 @@ func init() {
|
||||
url := ctx.State["image_url"].([]string)[0]
|
||||
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
|
||||
if file.IsNotExist(grpfolder) {
|
||||
os.Mkdir(grpfolder, 0755)
|
||||
err := os.Mkdir(grpfolder, 0755)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("错误:", err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
err = file.DownloadTo(url, grpfolder+"/"+name, true)
|
||||
err := file.DownloadTo(url, grpfolder+"/"+name, true)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
|
||||
} else {
|
||||
@@ -93,7 +89,7 @@ func init() {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有找到wife的名字!"))
|
||||
}
|
||||
})
|
||||
engine.OnPrefix("删除wife", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(20).
|
||||
engine.OnPrefix("删除wife", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
name := ""
|
||||
for _, elem := range ctx.Event.Message {
|
||||
@@ -107,7 +103,7 @@ func init() {
|
||||
}
|
||||
if name != "" {
|
||||
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
|
||||
err = os.Remove(grpfolder + "/" + name)
|
||||
err := os.Remove(grpfolder + "/" + name)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
|
||||
} else {
|
||||
@@ -117,7 +113,7 @@ func init() {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有找到wife的名字!"))
|
||||
}
|
||||
})
|
||||
engine.OnSuffix("所有人均可添加wife", zero.SuperUserPermission, zero.OnlyGroup).SetBlock(true).SetPriority(20).
|
||||
engine.OnSuffix("所有人均可添加wife", zero.SuperUserPermission, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
text := ""
|
||||
for _, elem := range ctx.Event.Message {
|
||||
@@ -2,18 +2,24 @@
|
||||
package nbnhhsh
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
zero.OnRegex(`^[??]{1,2} ?([a-z0-9]+)$`).SetBlock(false).
|
||||
control.Register("nbnhhsh", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "拼音首字母释义工具\n- ?? [缩写]",
|
||||
}).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), ", ")))
|
||||
@@ -25,7 +31,7 @@ func getValue(text string) []string {
|
||||
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)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err == nil {
|
||||
resp.Body.Close()
|
||||
json := gjson.ParseBytes(body)
|
||||
@@ -3,23 +3,25 @@ package novel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/antchfx/htmlquery"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
ub "github.com/FloatTech/ZeroBot-Plugin/utils/binary"
|
||||
ub "github.com/FloatTech/zbputils/binary"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -35,38 +37,31 @@ const (
|
||||
idReg = `/(\d+)/`
|
||||
)
|
||||
|
||||
var (
|
||||
gCurCookieJar *cookiejar.Jar
|
||||
engine = control.Register("novel", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "铅笔小说网搜索\n- 小说[xxx]",
|
||||
})
|
||||
limit = rate.NewManager(time.Minute, 5)
|
||||
)
|
||||
var gCurCookieJar *cookiejar.Jar
|
||||
|
||||
func init() {
|
||||
engine.OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).
|
||||
control.Register("novel", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "铅笔小说网搜索\n- 小说[xxx]",
|
||||
}).OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.GroupID).Acquire() {
|
||||
ctx.SendChain(message.Text("请稍后重试0x0..."))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
login(username, password)
|
||||
searchKey := ctx.State["regex_matched"].([]string)[1]
|
||||
searchHtml := search(searchKey)
|
||||
var m message.Message
|
||||
doc, err := htmlquery.Parse(strings.NewReader(searchHtml))
|
||||
searchHTML := search(searchKey)
|
||||
doc, err := htmlquery.Parse(strings.NewReader(searchHTML))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
}
|
||||
htmlTitle := htmlquery.InnerText(htmlquery.FindOne(doc, "/html/head/title"))
|
||||
if htmlTitle == websiteTitle {
|
||||
switch htmlTitle {
|
||||
case websiteTitle:
|
||||
list, err := htmlquery.QueryAll(doc, "//dl[@id='nr']")
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
}
|
||||
if len(list) != 0 {
|
||||
txt := ""
|
||||
for _, v := range list {
|
||||
bookName := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[1]/h3/a[1]"))
|
||||
category := htmlquery.InnerText(htmlquery.FindOne(v, "/dt/span[1]"))
|
||||
@@ -82,31 +77,27 @@ func init() {
|
||||
|
||||
webpageURL := websiteURL + "/book/" + id + "/"
|
||||
downloadURL := websiteURL + "/modules/article/txtarticle.php?id=" + id
|
||||
text := fmt.Sprintf("书名:%s\n类型:%s\n作者:%s\n状态:%s\n字数:%s\n简介:%s\n更新时间:%s\n最新章节:%s\n网页链接:%s\n下载地址:%s\n", bookName, category, author, status, wordNumbers, description, updateTime, latestChapter, webpageURL, downloadURL)
|
||||
m = append(m,
|
||||
message.CustomNode(
|
||||
zero.BotConfig.NickName[0],
|
||||
ctx.Event.SelfID,
|
||||
text),
|
||||
)
|
||||
txt += fmt.Sprintf("书名:%s\n类型:%s\n作者:%s\n状态:%s\n字数:%s\n简介:%s\n更新时间:%s\n最新章节:%s\n网页链接:%s\n下载地址:%s\n\n", bookName, category, author, status, wordNumbers, description, updateTime, latestChapter, webpageURL, downloadURL)
|
||||
}
|
||||
if id := ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
m).Get("message_id").Int(); id == 0 {
|
||||
data, err := text.RenderToBase64(txt, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
log.Println("err:", err)
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + helper.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
} else {
|
||||
text := htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@id='tipss']"))
|
||||
text = strings.Replace(text, " ", "", -1)
|
||||
text = strings.Replace(text, "本站", websiteURL, -1)
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.ReplaceAll(text, "本站", websiteURL)
|
||||
ctx.SendChain(message.Text(text))
|
||||
}
|
||||
} else if htmlTitle == errorTitle {
|
||||
case errorTitle:
|
||||
ctx.SendChain(message.Text(errorTitle))
|
||||
text := htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@style='text-align: center;padding:10px']"))
|
||||
text = strings.Replace(text, " ", "", -1)
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
ctx.SendChain(message.Text(text))
|
||||
} else {
|
||||
default:
|
||||
bookName := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:book_name']"), "content")
|
||||
category := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:category']"), "content")
|
||||
author := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:author']"), "content")
|
||||
@@ -153,7 +144,7 @@ func login(username, password string) {
|
||||
defer loginResp.Body.Close()
|
||||
}
|
||||
|
||||
func search(searchKey string) (searchHtml string) {
|
||||
func search(searchKey string) (searchHTML string) {
|
||||
searchKeyData, err := ub.UTF82GBK(helper.StringToBytes(searchKey))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
@@ -173,7 +164,7 @@ func search(searchKey string) (searchHtml string) {
|
||||
log.Errorln("[novel]", err)
|
||||
}
|
||||
defer searchResp.Body.Close()
|
||||
searchData, err := ioutil.ReadAll(searchResp.Body)
|
||||
searchData, err := io.ReadAll(searchResp.Body)
|
||||
if err != nil {
|
||||
log.Errorf("[novel] get response for url=%s got error=%s\n", searchURL, err.Error())
|
||||
}
|
||||
@@ -181,6 +172,6 @@ func search(searchKey string) (searchHtml string) {
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
}
|
||||
searchHtml = helper.BytesToString(searchData)
|
||||
return searchHtml
|
||||
searchHTML = helper.BytesToString(searchData)
|
||||
return searchHTML
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user