Compare commits

...

129 Commits

Author SHA1 Message Date
Kanri
40544b0c4d Update README.md 2021-06-23 23:50:48 +08:00
Yiwen-Chan
4b95225355 🐛 修复下载图片的碧油鸡 2021-06-21 21:02:47 +08:00
Yiwen-Chan
7c523be12d 🐛 修复 linux 路径问题 2021-06-21 20:14:02 +08:00
Yiwen-Chan
6da2044be5 📝 更新 README 2021-06-21 18:05:23 +08:00
Yiwen-Chan
0ebc54a17b ✏️ 修复一些碧油鸡 2021-06-21 17:59:38 +08:00
Kanri
31d29e7fa5 Merge pull request #32 from fumiama/master
更新随机图片插件
2021-06-20 21:33:28 -05:00
fumiama
21e3659ed3 更新随机图片插件 2021-06-21 00:33:34 +08:00
Yiwen-Chan
9a611e9eca 升级 AnimeAPI 依赖 2021-06-19 20:11:56 +08:00
Yiwen-Chan
7ca9f2158b 🚧🎨️ 重大重构中 2021-06-19 20:08:45 +08:00
Kanri
0fe0a5e4e8 Merge pull request #31 from fumiama/master
增加二次元图片评价功能
2021-06-19 06:18:29 -05:00
fumiama
8b7749168a 评价增加引用 2021-06-19 15:46:48 +08:00
fumiama
3fc165d636 classify不阻塞请求 2021-06-19 15:22:51 +08:00
fumiama
48632e25b8 增加二次元图片评价功能 2021-06-19 14:37:13 +08:00
Kanri
16901e33a6 Merge pull request #30 from fumiama/master
群管增加翻牌,修复计时器空指针错误,简易随机增加分类识别
2021-06-18 01:43:38 -05:00
fumiama
85b6276b25 更新readme 2021-06-17 23:28:30 +08:00
fumiama
725f1bcee3 普通随机图也可撤回 2021-06-17 23:27:27 +08:00
fumiama
1353335bc9 添加arm build 2021-06-17 22:42:54 +08:00
fumiama
3a867bc20e 评价改为本地 2021-06-17 22:39:40 +08:00
fumiama
b6bada7b83 增加设置评价图片网址 2021-06-17 22:26:00 +08:00
fumiama
3238205765 分离随机与评价 2021-06-17 22:22:11 +08:00
fumiama
e60280722f 适配多群组 2021-06-17 21:15:38 +08:00
fumiama
8ec4b5251b 完善判断 2021-06-17 20:05:38 +08:00
fumiama
8be003500c 增加撤回 2021-06-17 19:57:45 +08:00
fumiama
2f360d1d8a 带分类识别的随机 2021-06-17 16:24:00 +08:00
fumiama
91d13c12b2 避免伪随机 2021-06-17 00:21:25 +08:00
fumiama
61858a8cf9 解决无群名片时为空 2021-06-17 00:09:11 +08:00
fumiama
425e605ab2 翻牌不@ 2021-06-17 00:01:26 +08:00
fumiama
48cd620fc1 群管增加翻牌,修复计时器空指针错误 2021-06-16 23:40:04 +08:00
Kanri
940b70f61a 💚 更新 action 2021-06-10 17:10:55 +08:00
Kanri
d6b4289918 Update linux.yml 2021-06-10 17:10:28 +08:00
Kanri
811fe358b2 Merge pull request #29 from fumiama/master
群管避免不同群计时重叠
2021-06-09 06:06:01 -05:00
fumiama
bb581ab60d 群管避免不同群计时重叠 2021-06-09 18:56:05 +08:00
Kanri
29be1bd5ec Merge pull request #27 from fumiama/master
修复图片搜索缓存路径win下异常
2021-06-06 03:26:30 -05:00
源文雨
64302d3181 Merge branch 'Yiwen-Chan:master' into master 2021-06-06 16:20:02 +08:00
fumiama
b4173ecab9 修复图片搜索缓存路径win下异常 2021-06-06 16:16:47 +08:00
Yiwen-Chan
9aa1275275 ✏️ 修复 shindan 2021-06-06 15:58:13 +08:00
Kanri
ce326ce977 Merge pull request #26 from fumiama/master
群管增加定时器保存功能
2021-06-06 01:54:32 -05:00
fumiama
77cad0915c 将timer分离 2021-06-06 14:46:58 +08:00
fumiama
a382dea51f 恢复main 2021-06-06 14:27:53 +08:00
fumiama
5cc7c40417 群管增加定时器保存功能 2021-06-06 14:27:16 +08:00
fumiama
77aeb38927 模块化utils、引入protobuf 2021-06-06 01:19:48 +08:00
Kanri
d7ce199bf7 Merge pull request #25 from fumiama/master
修复按id搜图时失败、更新README
2021-06-05 03:13:29 -05:00
源文雨
18781e3e64 Merge branch 'Yiwen-Chan:master' into master 2021-06-04 14:31:58 +08:00
fumiama
0595fb223a 恢复main 2021-06-04 14:27:22 +08:00
fumiama
b7620460d3 修复按id搜图时失败 2021-06-04 14:26:57 +08:00
源文雨
bf6180a0ac Update README.md 2021-06-04 14:11:04 +08:00
Kanri
f201eb6497 Merge pull request #24 from fumiama/master
以入参形式指定superusers、增加简易随机图片、分离搜图与涩图
2021-06-04 01:07:47 -05:00
fumiama
f126d44764 上一个随机图片未完成前拒绝请求 2021-06-04 13:51:37 +08:00
fumiama
33dc16956d 分离搜图与随机图(随机图需要cgo而搜图不用) 2021-06-04 13:45:50 +08:00
fumiama
6e3f395f07 模块化消息扩展、增加简易随机图片 2021-06-03 23:46:37 +08:00
fumiama
da44b02b43 以0755创建目录以避免无法保存cache 2021-06-03 22:49:36 +08:00
fumiama
c742ab43a3 修正bulid_mips 2021-06-03 20:08:54 +08:00
fumiama
b1b831ff87 以入参形式指定superusers避免反复编译 2021-06-03 20:06:16 +08:00
fumiama
b82e0aeb2e 增加mips架构编译脚本 2021-06-03 19:42:59 +08:00
fumiama
17ab5f1c37 shindan api失效时提示出错 2021-06-03 16:57:36 +08:00
Yiwen-Chan
b1f4d6fb93 🚑 更新 P站 IP地址 2021-06-03 12:05:06 +08:00
Kanri
710a46f674 Merge pull request #22 from Ink-33/master
🎨 启用linter
2021-05-30 10:12:53 -05:00
Ink33
71b2df2d9f 🎨 启用linter 2021-05-30 23:07:08 +08:00
Kanri
734d838182 Merge pull request #21 from fumiama/master
群管避免重复注册定时器
2021-05-12 07:01:45 -05:00
源文雨
17c60ce961 Merge branch 'Yiwen-Chan:master' into master 2021-05-12 19:06:22 +08:00
fumiama
fd3e4ba7f5 Merge branch 'master' of https://github.com/fumiama/ZeroBot-Plugin 2021-05-12 19:05:46 +08:00
fumiama
ec21395606 群管避免重复注册定时器 2021-05-12 19:05:33 +08:00
Kanri
333cfdcb04 Merge pull request #20 from fumiama/master
群管定时提醒bug修复
2021-05-10 03:05:27 -05:00
源文雨
12ca43a5d4 Merge branch 'Yiwen-Chan:master' into master 2021-05-10 14:32:26 +08:00
fumiama
32eed9a4d8 修复汉字转换周天错误 2021-05-10 13:09:16 +08:00
fumiama
8801b8659b 群管定时提醒检查参数错误、修复按周提醒判断错误 2021-05-10 13:06:44 +08:00
Kanri
807752b07d Merge pull request #19 from fumiama/master
群管增加定时提醒功能
2021-05-09 22:36:11 -05:00
fumiama
a1a6770fdc 取消提醒时避免重复取消 2021-05-09 11:07:27 +08:00
fumiama
e9da9be361 群管增加取消提醒 2021-05-09 11:03:21 +08:00
fumiama
eda51bd549 群管增加定时提醒功能 2021-05-09 00:32:43 +08:00
Yiwen-Chan
34b82f8cb9 🌐 增加涩图数据库 2021-05-08 16:56:37 +08:00
Yiwen-Chan
dcc31ecaa1 ✏️ 修改 gitignore 规则 2021-05-08 16:54:59 +08:00
Yiwen-Chan
dbe30433a1 ✏️ 修复GitHub搜索正则 2021-05-02 19:04:55 +08:00
Yiwen-Chan
6e24552be8 增加 GitHub 搜索返回图片 2021-05-02 18:52:40 +08:00
Yiwen-Chan
2c8812f45e 增加github搜索返回图片 2021-05-02 18:45:00 +08:00
Yiwen-Chan
3a293f5e2d ✏️ 修改戳别字 2021-04-30 18:20:14 +08:00
Yiwen-Chan
a4592465dc 🐛 修复 ATRI 个别图文件名错误 2021-04-28 13:55:44 +08:00
Yiwen-Chan
a0c39a7464 🐛 修复run命令被转义的问题 2021-04-26 18:11:03 +08:00
Yiwen-Chan
f4af5bea99 ✏️ 更改ATRI睡觉时间为凌晨1点到6点 2021-04-24 21:00:36 +08:00
Yiwen-Chan
3bec61fb78 ✏️ 修复语音发送 2021-04-23 23:56:08 +08:00
Yiwen-Chan
d75494a418 🔖 新版本 2021-04-23 23:53:10 +08:00
Yiwen-Chan
c5268d2981 📝 更新 README 2021-04-23 23:52:55 +08:00
Yiwen-Chan
65beaa5a41 ✏️ 词库小修改 2021-04-23 23:52:24 +08:00
Yiwen-Chan
55e5f645fa Merge branch 'master' of github.com:Yiwen-Chan/ZeroBot-Plugin 2021-04-21 13:10:28 +08:00
Yiwen-Chan
e22b534ed9 🔒 防止昵称CQ码注入 2021-04-21 13:10:14 +08:00
Kanri
6cac126ad8 Update README.md 2021-04-21 00:32:54 +08:00
Kanri
38bb4722b9 Merge pull request #16 from fossabot/add-license-scan-badge
Add license scan report and status
2021-04-20 11:32:14 -05:00
Kanri
0adaac13c4 Merge pull request #17 from Yiwen-Chan/add-license-1
📄 使用 GPL v3
2021-04-20 11:27:40 -05:00
Kanri
283e559344 📄 使用 GPL v3 2021-04-21 00:27:27 +08:00
Kanri
6a46db14e1 Delete LICENSE 2021-04-21 00:25:25 +08:00
Yiwen-Chan
117df2dbe1 ✏️ 一些小改动 2021-04-20 23:39:19 +08:00
Yiwen-Chan
c9560cd635 增加运行bat 2021-04-20 23:38:52 +08:00
Yiwen-Chan
79b0d31df9 ✏️ 修复涩图缓存提示发送失败 2021-04-20 23:38:25 +08:00
fossabot
355690e4e6 Add license scan report and status
Signed off by: fossabot <badges@fossa.com>
2021-04-20 07:32:22 -07:00
Yiwen-Chan
189e5e7eba 📝 更新 README 2021-04-20 16:22:26 +08:00
Yiwen-Chan
d1dd04a973 ✏️ 修改缓冲图片群为0 2021-04-20 16:17:35 +08:00
Yiwen-Chan
0ea1f68bbe ✏️ 防止 \r 换行文本过长刷屏 2021-04-20 16:16:08 +08:00
Yiwen-Chan
9992e351b4 Merge branch 'master' of github.com:Yiwen-Chan/ZeroBot-Plugin 2021-04-20 15:40:11 +08:00
Yiwen-Chan
b0bf100096 增加椛椛词库 2021-04-20 15:39:49 +08:00
Kanri
766f4e3953 Merge pull request #15 from z594024037/master
啾咪~
2021-04-20 02:28:28 -05:00
Yzqd
dcd0ce1194 Update README.md 2021-04-20 15:19:22 +08:00
Yiwen-Chan
b9e7122b29 ✏️ 对 ATRI 稍微调整 2021-04-20 03:05:13 +08:00
Yiwen-Chan
0e4f1dfaa6 增加 ATRI 模块 2021-04-20 02:39:06 +08:00
Yiwen-Chan
f6213798ba 📝 更新 README 2021-04-19 12:17:24 +08:00
Yiwen-Chan
8411ed5e3e 增加群温度 2021-04-19 12:15:14 +08:00
Yiwen-Chan
6706adf586 增加在线运行代码的限制 2021-04-18 23:05:18 +08:00
Yiwen-Chan
3a11769b11 🐛 修复直接使用昵称无法触发回复的问题 2021-04-18 23:04:53 +08:00
Yiwen-Chan
d680fbaa4f 🔖 ZeroBot 版本 1.0.0 正式版 2021-04-18 22:08:00 +08:00
Yiwen-Chan
c208e1b120 🎨 优化 shindan 的触发 2021-04-18 21:50:11 +08:00
Yiwen-Chan
1e7decc966 增加 shindanmaker.com 的新玩法 2021-04-17 19:17:58 +08:00
Yiwen-Chan
ae9b0c2756 ✏️ 统一风格 2021-04-17 16:50:15 +08:00
Yiwen-Chan
763060c42b ✏️ 更改搜索 GitHub 仓库命令 2021-04-17 16:21:27 +08:00
Yiwen-Chan
e53eacd908 🎨 改进代码结构 2021-04-17 16:20:04 +08:00
Kanri
c199d1dd8c Merge pull request #14 from DawnNights/master
增加语言模板查看功能
2021-04-17 03:04:53 -05:00
夜黎
d7e3709b76 增加语言模板查看功能 2021-04-17 15:44:09 +08:00
Yiwen-Chan
acc9d1473d 🎨 优化代码结构 2021-04-17 14:24:07 +08:00
Kanri
db331c6a87 Merge pull request #12 from DawnNights/master
添加简易在线运行代码功能
2021-04-16 23:28:17 -05:00
2081878832
3a35fdb4d9 添加简易在线运行代码功能 2021-04-17 12:07:06 +08:00
Kanri
27c3095e5d Merge pull request #11 from Yiwen-Chan/revert-10-master
Revert "添加简易在线运行代码功能"
2021-04-16 21:15:42 -05:00
Kanri
b8e84b4049 Revert "添加简易在线运行代码功能" 2021-04-17 10:14:15 +08:00
Kanri
ac0526a03e Merge pull request #10 from DawnNights/master
添加简易在线运行代码功能
2021-04-16 21:12:21 -05:00
夜黎
4a4aa5620d 添加简易在线运行代码功能 2021-04-17 02:31:32 +08:00
Yiwen-Chan
d092e06fdb 🎨 改进代码结构 2021-04-16 19:18:43 +08:00
Yiwen-Chan
a960b7c732 ️ 更好的识图触发模式 2021-04-16 19:18:29 +08:00
Yiwen-Chan
4a00a5e2fb 🐛 修复艾特转义 2021-04-16 19:17:41 +08:00
Yiwen-Chan
d250f2e9b1 🎨 改进词库代码 2021-04-15 20:12:06 +08:00
Kanri
8acda6b28b Merge pull request #9 from DawnNights/master
添加简易词库学习
2021-04-12 22:52:04 -05:00
DawnNight
5ffd5065ff 添加简易词库学习 2021-04-13 11:40:31 +08:00
DawnNight
5833e7dd42 Update chat.go 2021-04-13 11:39:59 +08:00
48 changed files with 1654 additions and 906 deletions

24
.github/workflows/golint.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Lint
on: [push]
jobs:
golangci:
name: lint_golangci-lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- name: golangci-lint
uses: golangci/golangci-lint-action@v2.5.2
with:
version: latest
- name: Commit back
continue-on-error: true
run: |
git config --local user.name 'github-actions[bot]'
git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add --all
git commit -m "🎨 改进代码样式"
git push

View File

@@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.15
go-version: 1.16
- name: Check out code into the Go module directory
uses: actions/checkout@v2
@@ -39,4 +39,4 @@ jobs:
uses: actions/upload-artifact@v2
with:
name: ZeroBot-Plugin-linux
path: ./artifacts
path: ./artifacts

20
.github/workflows/suggester.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Suggester
on: [pull_request]
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- name: golangci-lint
uses: golangci/golangci-lint-action@v2.5.2
with:
version: latest
- name: Suggester
uses: reviewdog/action-suggester@v1.0.1
with:
tool_name: golangci-lint

View File

@@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.15
go-version: 1.16
- name: Check out code into the Go module directory
uses: actions/checkout@v2

5
.gitignore vendored
View File

@@ -1,2 +1,3 @@
data/*
main.exe
data/SetuTime/cache
data/SetuTime/search
data/manager

94
.golangci.yml Normal file
View File

@@ -0,0 +1,94 @@
linters-settings:
errcheck:
ignore: fmt:.*,io/ioutil:^Read.*
ignoretests: true
goimports:
local-prefixes: github.com/Yiwen-Chan/ZeroBot-Plugin
gocritic:
disabled-checks:
- exitAfterDefer
forbidigo:
# Forbid the following identifiers
forbid:
- ^fmt\.Errorf$ # consider errors.Errorf in github.com/pkg/errors
linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
fast: true
enable:
- bodyclose
- deadcode
- depguard
- dogsled
- dupl
- errcheck
- exportloopref
- exhaustive
#- funlen
#- goconst
- gocritic
#- gocyclo
- gofmt
- goimports
- goprintffuncname
#- gosec
- gosimple
- govet
- ineffassign
- misspell
- nolintlint
- rowserrcheck
- staticcheck
- structcheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace
- prealloc
- predeclared
- asciicheck
- forbidigo
- makezero
- revive
#- interfacer
# don't enable:
# - scopelint
# - gochecknoglobals
# - gocognit
# - godot
# - godox
# - goerr113
# - interfacer
# - maligned
# - nestif
# - testpackage
# - wsl
run:
# default concurrency is a available CPU number.
# concurrency: 4 # explicitly omit this value to fully utilize available resources.
deadline: 5m
issues-exit-code: 1
tests: false
# output configuration options
output:
format: "colored-line-number"
print-issued-lines: true
print-linter-name: true
uniq-by-line: true
issues:
# Fix found issues (if it's supported by the linter)
fix: true
exclude-use-default: false
exclude:
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"

143
LICENSE
View File

@@ -1,5 +1,5 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
@@ -7,15 +7,17 @@
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
@@ -24,34 +26,44 @@ them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
@@ -60,7 +72,7 @@ modification follow.
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
@@ -537,45 +549,35 @@ to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
@@ -633,29 +635,40 @@ the "copyright" line and a pointer to where the full notice is found.
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -10,15 +10,25 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/Yiwen-Chan/ZeroBot-Plugin?style=flat-square&logo=go)](https://goreportcard.com/report/github.com/github.com/Yiwen-Chan/ZeroBot-Plugin)
[![Badge](https://img.shields.io/badge/onebot-v11-black?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==)](https://github.com/howmanybots/onebot)
[![Badge](https://img.shields.io/badge/zerobot-v1.0.1-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![License](https://img.shields.io/github/license/Yiwen-Chan/OneBot-YaYa.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/Yiwen-Chan/ZeroBot-Plugin/master/LICENSE)
[![Badge](https://img.shields.io/badge/zerobot-v1.2.1-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![License](https://img.shields.io/github/license/Yiwen-Chan/OneBot-YaYa.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
[![qq group](https://img.shields.io/badge/group-1048452984-red?style=flat-square&logo=tencent-qq)](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
</div>
### 功能
- 群管
- 聊天 `import _ "github.com/FloatTech/ZeroBot-Plugin/chat"`
- [x] [BOT名字]
- [x] [戳一戳BOT]
- [x] 空调开
- [x] 空调关
- [x] 群温度
- [x] 设置温度[正整数]
- ATRI `import _ "github.com/FloatTech/ZeroBot-Plugin/atri"`
- [x] 具体指令看代码
- 注:本插件基于 [ATRI](https://github.com/Kyomotoi/ATRI) ,为 Golang 移植版
- 群管 `import _ "github.com/FloatTech/ZeroBot-Plugin/manager"`
- [x] 禁言[@xxx][分钟]
- [x] 解除禁言[@xxx]
- [x] 我要自闭 [分钟]
@@ -33,20 +43,46 @@
- [x] 退出群聊[群号]
- [x] *入群欢迎
- [x] *退群通知
- [x] 在[月份]月[日期]日的[小时]点[分钟]分时(用[url])提醒大家[消息]
- [x] 在[月份]月[每周or周几]的[小时]点[分钟]分时(用[url])提醒大家[消息]
- [x] 取消在[月份]月[日期]日的[小时]点[分钟]分的提醒
- [x] 取消在[月份]月[每周or周几]的[小时]点[分钟]分的提醒
- [x] 翻牌
- [ ] 同意入群请求
- [ ] 同意好友请求
- [ ] 撤回[@xxx] [xxx]
- [ ] 警告[@xxx]
- [x] run[xxx]
- 涩图
- [x] 来份[涩图/二次元/风景]
- [x] 添加[涩图/二次元/风景][P站图片ID]
- [x] 删除[涩图/二次元/风景][P站图片ID]
- [x] setu -s
- [x] setu -x
- [x] setu -p
- 点歌
- 涩图 `import _ "github.com/FloatTech/ZeroBot-Plugin/setutime"`
- [x] 来份[涩图/二次元/风景/车万]
- [x] 添加[涩图/二次元/风景/车万][P站图片ID]
- [x] 删除[涩图/二次元/风景/车万][P站图片ID]
- [x] >setu status
- 搜图 `import _ "github.com/FloatTech/ZeroBot-Plugin/picsearcher"`
- [x] 以图搜图|搜索图片|以图识图[图片]
- [x] 搜图[P站图片ID]
- 简易随机图片(调用url) `import _ "github.com/FloatTech/ZeroBot-Plugin/randimg"`
- [x] 随机图片
- [x] 直接随机无r18检测后果自负
- [x] 设置随机图片网址[url]
- [x] 太涩了(撤回最近发的图)
- [x] 评价图片:发送一张图片进行评分
- 点歌 `import _ "github.com/FloatTech/ZeroBot-Plugin/music"`
- [x] 点歌[xxx]
- [x] 网易点歌[xxx]
- [x] 酷我点歌[xxx]
- [x] 酷狗点歌[xxx]
- shindan `import _ "github.com/FloatTech/ZeroBot-Plugin/shindan"`
- [x] 今天是什么少女[@xxx]
- [x] 异世界转生[@xxx]
- [x] 卖萌[@xxx]
- GitHub仓库搜索 `import _ "github.com/FloatTech/ZeroBot-Plugin/github"`
- [x] >github [xxx]
- [x] >github -p [xxx]
- 在线代码运行 `import _ "github.com/FloatTech/ZeroBot-Plugin/runcode"`
- [x] >runcode help
- [x] >runcode [on/off]
- [x] >runcode [language] [code block]
- TODO...
### 使用方法
@@ -60,18 +96,25 @@
| [yyuueexxiinngg/cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg | |
| [takayama-lily/onebot](https://github.com/takayama-lily/onebot) | [OICQ](https://github.com/takayama-lily/oicq) | takayama | |
#### 本地编译
#### 本地运行
1. 下载安装 [Go](https://studygolang.com/dl/golang/go1.16.2.windows-amd64.msi) 环境
2. 下载安装 [TDM-GCC](https://github.com/jmeubank/tdm-gcc/releases),并添加到环境变量
3. [clone](https://github.com/Yiwen-Chan/ZeroBot-Plugin/archive/master.zip) 本项目,本地解压
4. 编辑 main.go 文件,内容按需修改
5. 双击点击 build.bat 文
6. 运行框架,并同时运行本插件
2. [clone](https://github.com/Yiwen-Chan/ZeroBot-Plugin/archive/master.zip) 本项目,本地解压
3. 编辑 main.go 文件,内容按需修改
4. 双击 build.bat 文件 或 直接双击 run.bat 文件
5. 运行 OneBot 框架,并同时运行本插
#### 利用 Actions 编译 (推荐)
#### 利用 Actions 在线编译 (推荐)
1. 点击右上角 Fork 本项目,并转跳到自己 Fork 的仓库
2. 点击仓库上方的 Actions 按钮,确认使用 Actions
3. 编辑 main.go 文件,内容按需修改,返回仓库
3. 编辑 main.go 文件,内容按需修改,提交修改后 Actions 自动执行
4. 点击 Actions 按钮,等待编译完成,在 Actions 里下载编译好的文件
5. 运行框架,并同时运行本插件
5. 运行 OneBot 框架,并同时运行本插件
6. 啾咪~
### 特别感谢
- [ZeroBot](https://github.com/wdvxdr1123/ZeroBot)
- [ATRI](https://github.com/Kyomotoi/ATRI)
## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FYiwen-Chan%2FZeroBot-Plugin.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FYiwen-Chan%2FZeroBot-Plugin?ref=badge_large)

BIN
atri/AZ.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
atri/AZ1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
atri/FN.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
atri/NO.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
atri/RocketPunch.amr Normal file

Binary file not shown.

BIN
atri/SUKI.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
atri/SUKI1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

BIN
atri/SUKI2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB

BIN
atri/WH.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
atri/WH1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
atri/WH2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
atri/WH3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
atri/WQ.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
atri/WQ1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

BIN
atri/YES.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

248
atri/atri.go Normal file
View File

@@ -0,0 +1,248 @@
// 本文件基于 https://github.com/Kyomotoi/ATRI
// 为 Golang 移植版,语料、素材均来自上述项目
// 本项目遵守 AGPL v3 协议进行开源
package atri
import (
"math/rand"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var (
PRIO = -1
RES = "https://raw.dihe.moe/Yiwen-Chan/ZeroBot-Plugin/master/atri/"
ENABLE = true
)
func init() { // 插件主体
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
ENABLE = true
ctx.SendChain(randText("嗯呜呜……夏生先生……?"))
})
zero.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
ENABLE = false
ctx.SendChain(randText("Zzz……Zzz……"))
})
zero.OnFullMatch("萝卜子", AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
switch rand.Intn(2) {
case 0:
ctx.SendChain(randText("萝卜子是对机器人的蔑称!", "是亚托莉......萝卜子可是对机器人的蔑称"))
case 1:
ctx.SendChain(randRecord("RocketPunch.amr"))
}
})
zero.OnKeywordGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
if rand.Intn(10) == 0 {
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
}
})
zero.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO - 1).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
})
zero.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
switch {
case now < 6: // 凌晨
ctx.SendChain(randText(
"zzzz......",
"zzzzzzzz......",
"zzz...好涩哦..zzz....",
"别...不要..zzz..那..zzz..",
"嘻嘻..zzz..呐~..zzzz..",
"...zzz....哧溜哧溜....",
))
case now >= 6 && now < 9:
ctx.SendChain(randText(
"啊......早上好...(哈欠)",
"唔......吧唧...早上...哈啊啊~~~\n早上好......",
"早上好......",
"早上好呜......呼啊啊~~~~",
"啊......早上好。\n昨晚也很激情呢",
"吧唧吧唧......怎么了...已经早上了么...",
"早上好!",
"......看起来像是傍晚,其实已经早上了吗?",
"早上好......欸~~~脸好近呢",
))
case now >= 9 && now < 18:
ctx.SendChain(randText(
"哼!这个点还早啥,昨晚干啥去了!?",
"熬夜了对吧熬夜了对吧熬夜了对吧???!",
"是不是熬夜是不是熬夜是不是熬夜?!",
))
case now >= 18 && now < 24:
ctx.SendChain(randText(
"早个啥?哼唧!我都准备洗洗睡了!",
"不是...你看看几点了,哼!",
"晚上好哇",
))
}
})
zero.OnFullMatchGroup([]string{"中午好", "午安"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
switch {
case now < 6: // 凌晨
ctx.SendChain(randText(
"午安w",
"午觉要好好睡哦ATRI会陪伴在你身旁的w",
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
"睡你午觉去!哼唧!!",
))
}
})
zero.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
switch {
case now < 6: // 凌晨
ctx.SendChain(randText(
"zzzz......",
"zzzzzzzz......",
"zzz...好涩哦..zzz....",
"别...不要..zzz..那..zzz..",
"嘻嘻..zzz..呐~..zzzz..",
"...zzz....哧溜哧溜....",
))
case now >= 6 && now < 11:
ctx.SendChain(randText(
"你可猝死算了吧!",
"?啊这",
"亲,这边建议赶快去睡觉呢~~~",
"不可忍不可忍不可忍!!为何这还不猝死!!",
))
case now >= 11 && now < 15:
ctx.SendChain(randText(
"午安w",
"午觉要好好睡哦ATRI会陪伴在你身旁的w",
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
"睡你午觉去!哼唧!!",
))
case now >= 15 && now < 19:
ctx.SendChain(randText(
"难不成??晚上不想睡觉??现在休息",
"就......挺离谱的...现在睡觉",
"现在还是白天哦,睡觉还太早了",
))
case now >= 19 && now < 24:
ctx.SendChain(randText(
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
"......(打瞌睡)",
"呼...呼...已经睡着了哦~...呼......",
"......我、我会在这守着你的,请务必好好睡着",
))
}
})
zero.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(randText(
"当然,我是高性能的嘛~",
"小事一桩,我是高性能的嘛",
"怎么样?还是我比较高性能吧?",
"哼哼!我果然是高性能的呢!",
"因为我是高性能的嘛!嗯哼!",
"因为我是高性能的呢!",
"哎呀~,我可真是太高性能了",
"正是,因为我是高性能的",
"是的。我是高性能的嘛♪",
"毕竟我可是高性能的!",
"嘿嘿,我的高性能发挥出来啦♪",
"我果然是很高性能的机器人吧!",
"是吧!谁叫我这么高性能呢!哼哼!",
"交给我吧,有高性能的我陪着呢",
"呣......我的高性能,毫无遗憾地施展出来了......",
))
})
zero.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(randText(
"当然,我是高性能的嘛~",
"没事没事,因为我是高性能的嘛!嗯哼!",
"没事的,因为我是高性能的呢!",
"正是,因为我是高性能的",
"是的。我是高性能的嘛♪",
"毕竟我可是高性能的!",
"那种程度的事不算什么的。\n别看我这样我可是高性能的",
"没问题的,我可是高性能的",
))
})
zero.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
if rand.Intn(2) == 0 {
ctx.SendChain(randImage("YES.png", "NO.jpg"))
}
})
zero.OnFullMatchGroup([]string{"啊这"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
if rand.Intn(2) == 0 {
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
}
})
zero.OnFullMatchGroup([]string{"我好了"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(randText("不许好!", "憋回去!"))
})
zero.OnFullMatchGroup([]string{"", "?", "¿"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
switch rand.Intn(5) {
case 0:
ctx.SendChain(randText("?", "", "嗯?", "(。´・ω・)ん?", "ん?"))
case 1, 2:
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
}
})
zero.OnKeyword("离谱", AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
switch rand.Intn(5) {
case 0:
ctx.SendChain(randText("?", "", "嗯?", "(。´・ω・)ん?", "ん?"))
case 1, 2:
ctx.SendChain(randImage("WH.jpg"))
}
})
zero.OnKeyword("答应我", AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(randText("我无法回应你的请求"))
})
}
func randText(text ...string) message.MessageSegment {
length := len(text)
return message.Text(text[rand.Intn(length)])
}
func randImage(file ...string) message.MessageSegment {
length := len(file)
return message.Image(RES + file[rand.Intn(length)])
}
func randRecord(file ...string) message.MessageSegment {
length := len(file)
return message.Record(RES + file[rand.Intn(length)])
}
// AtriSwitch 控制 ATRI 的开关
func AtriSwitch() zero.Rule {
return func(ctx *zero.Ctx) bool {
return ENABLE
}
}
// AtriSleep 凌晨0点到6点ATRI 在睡觉,不回应任何请求
func AtriSleep() zero.Rule {
return func(ctx *zero.Ctx) bool {
if now := time.Now().Hour(); now >= 1 && now < 6 {
return false
}
return true
}
}

View File

@@ -2,6 +2,7 @@ package chat
import (
"math/rand"
"strconv"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -44,4 +45,58 @@ func init() { // 插件主体
}
return
})
// 群空调
var AirConditTemp = map[int64]int{}
var AirConditSwitch = map[int64]bool{}
zero.OnFullMatch("空调开").SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
AirConditSwitch[ctx.Event.GroupID] = true
ctx.SendChain(message.Text("❄️哔~"))
})
zero.OnFullMatch("空调关").SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
AirConditSwitch[ctx.Event.GroupID] = false
delete(AirConditTemp, ctx.Event.GroupID)
ctx.SendChain(message.Text("💤哔~"))
})
zero.OnRegex(`设置温度(\d+)`).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
AirConditTemp[ctx.Event.GroupID] = 26
}
if AirConditSwitch[ctx.Event.GroupID] {
temp := ctx.State["regex_matched"].([]string)[1]
AirConditTemp[ctx.Event.GroupID], _ = strconv.Atoi(temp)
ctx.SendChain(message.Text(
"❄️风速中", "\n",
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
))
return
} else {
ctx.SendChain(message.Text(
"💤", "\n",
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
))
return
}
})
zero.OnFullMatch(`群温度`).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
AirConditTemp[ctx.Event.GroupID] = 26
}
if AirConditSwitch[ctx.Event.GroupID] {
ctx.SendChain(message.Text(
"❄️风速中", "\n",
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
))
return
} else {
ctx.SendChain(message.Text(
"💤", "\n",
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
))
return
}
})
}

BIN
data/SetuTime/SetuTime.db Normal file

Binary file not shown.

View File

@@ -8,13 +8,14 @@ import (
"net/url"
"strings"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/tidwall/gjson"
)
func init() { // 插件主体
zero.OnRegex(`>G\s(.*)`).SetBlock(true).FirstPriority().
zero.OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
// 发送请求
header := http.Header{
@@ -22,7 +23,7 @@ func init() { // 插件主体
}
api, _ := url.Parse("https://api.github.com/search/repositories")
api.RawQuery = url.Values{
"q": []string{ctx.State["regex_matched"].([]string)[1]},
"q": []string{ctx.State["regex_matched"].([]string)[2]},
}.Encode()
body, err := netGet(api.String(), header)
if err != nil {
@@ -36,8 +37,13 @@ func init() { // 插件主体
}
repo := info.Get("items.0")
// 发送结果
ctx.SendChain(
message.Text(
switch ctx.State["regex_matched"].([]string)[1] {
case "-p ": // 图片模式
ctx.SendChain(message.Image(
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
).Add("cache", 0))
default:
ctx.SendChain(message.Text(
repo.Get("full_name").Str, "\n",
"Description: ",
repo.Get("description").Str, "\n",
@@ -51,8 +57,8 @@ func init() { // 插件主体
repo.Get("pushed_at").Str, "\n",
"Jump: ",
repo.Get("html_url").Str, "\n",
),
)
))
}
})
}

19
go.mod
View File

@@ -1,12 +1,19 @@
module github.com/Yiwen-Chan/ZeroBot-Plugin
module github.com/FloatTech/ZeroBot-Plugin
go 1.15
go 1.16
require (
github.com/antchfx/htmlquery v1.2.3
github.com/mattn/go-sqlite3 v1.14.6
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2
github.com/antchfx/xpath v1.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/sirupsen/logrus v1.8.1
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
github.com/tidwall/gjson v1.7.4
github.com/wdvxdr1123/ZeroBot v1.1.2
github.com/tidwall/gjson v1.8.0
github.com/tidwall/pretty v1.2.0 // indirect
github.com/wdvxdr1123/ZeroBot v1.2.1
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect
modernc.org/sqlite v1.10.8
)

118
go.sum
View File

@@ -1,34 +1,55 @@
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07 h1:7fBPLLoZysaa9PI9ApgzyVMrMLMWBam273YgKwy7Ddg=
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07/go.mod h1:GYrQD70HvBzry1XiZ1tHFNOsOqRkR+ao4XGYZqV4I9c=
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2 h1:I7RSCsJVT6elehdaSiWB4n96y06fQxMsvAG494S5Od0=
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2/go.mod h1:femu/wVuqVSN/rg209qksMx8/2OKUF8l1PZCNg4RwVA=
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/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
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.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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
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.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/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/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/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=
@@ -41,31 +62,96 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
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/tidwall/gjson v1.7.4 h1:19cchw8FOxkG5mdLRkGf9jqIqEyqdZhPqW60XfyFxk8=
github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/wdvxdr1123/ZeroBot v1.1.2 h1:SGl7lSdFatdSCcVPXTIC56xoMUtXwyz1xWBSkPOAgEU=
github.com/wdvxdr1123/ZeroBot v1.1.2/go.mod h1:N4bGSEHCKOrplRHNM8XJFXcXFsK0OUSvmTVakomS+k8=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/wdvxdr1123/ZeroBot v1.2.1 h1:ougeP+VOAGlQWCAUSB7fjA5trzEvPepU7pujsoYTCq8=
github.com/wdvxdr1123/ZeroBot v1.2.1/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/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=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
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/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=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
modernc.org/cc/v3 v3.33.5 h1:gfsIOmcv80EelyQyOHn/Xhlzex8xunhQxWiJRMYmPrI=
modernc.org/cc/v3 v3.33.5/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo=
modernc.org/ccgo/v3 v3.9.4 h1:mt2+HyTZKxva27O6T4C9//0xiNQ/MornL3i8itM5cCs=
modernc.org/ccgo/v3 v3.9.4/go.mod h1:19XAY9uOrYnDhOgfHwCABasBvK69jgC4I8+rizbk3Bc=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.5 h1:zv111ldxmP7DJ5mOIqzRbza7ZDl3kh4ncKfASB2jIYY=
modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.10.8 h1:tZzV+/FwlSBddiJAHLR+qxsw2nx7jpLMKOCVu6NTjxI=
modernc.org/sqlite v1.10.8/go.mod h1:k45BYY2DU82vbS/dJ24OzHCtjPeMEcZ1DV2POiE8nRs=
modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/tcl v1.5.2 h1:sYNjGr4zK6cDH74USl8wVJRrvDX6UOLpG0j4lFvR0W0=
modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=

56
main.go
View File

@@ -3,16 +3,30 @@ package main
import (
"fmt"
log "github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
// 词库类
_ "github.com/FloatTech/ZeroBot-Plugin/atri" // ATRI词库
_ "github.com/FloatTech/ZeroBot-Plugin/chat" // 基础词库
// 实用类
_ "github.com/FloatTech/ZeroBot-Plugin/github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/manager" // 群管
_ "github.com/FloatTech/ZeroBot-Plugin/runcode" // 在线运行代码
// 娱乐类
_ "github.com/FloatTech/ZeroBot-Plugin/music" // 点歌
//_ "github.com/FloatTech/ZeroBot-ACGImage" //简易随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/setutime" // 涩图
_ "github.com/FloatTech/ZeroBot-Plugin/shindan" // 测定
// 以下为内置依赖,勿动
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/driver"
"github.com/wdvxdr1123/ZeroBot/message"
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/chat"
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/github"
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/manager"
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/music"
//_ "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime"
log "github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
)
func init() {
@@ -24,20 +38,34 @@ func init() {
}
func main() {
fmt.Printf(`
fmt.Print(`
====================[ZeroBot-Plugin]====================
* OneBot + ZeroBot + Golang
* Copyright © 2018-2020 Kanri, All Rights Reserved
* Project: https://github.com/Yiwen-Chan/ZeroBot-Plugin
* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST
* Copyright © 2021 Kanri, DawnNights, Fumiama
* Project: https://github.com/FloatTech/ZeroBot-Plugin
========================================================
`)
`) // 启动打印
zero.Run(zero.Config{
NickName: []string{"椛椛"},
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
CommandPrefix: "/",
SuperUsers: []string{"825111790", "213864964"}, // 必须修改,否则无权限
SuperUsers: []string{"213864964"}, // 必须修改,否则无权限
Driver: []zero.Driver{
driver.NewWebSocketClient("127.0.0.1", "6700", ""),
&driver.WSClient{
Url: "ws://127.0.0.1:6700",
AccessToken: "",
},
},
})
// 帮助
zero.OnFullMatchGroup([]string{"help", "/help", ".help", "菜单", "帮助"}, zero.OnlyToMe).SetBlock(true).SetPriority(999).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(
"* OneBot + ZeroBot + Golang ", "\n",
"* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST", "\n",
"* Copyright © 2021 Kanri, DawnNights, Fumiama ", "\n",
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
))
})
select {}
}

View File

@@ -1,31 +1,39 @@
package manager
import (
"fmt"
"math/rand"
"strconv"
"strings"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
timer "github.com/FloatTech/ZeroBot-Plugin-Timer"
)
func init() { // 插件主体
// 菜单
zero.OnFullMatch("群管系统", zero.AdminPermission).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
ctx.Send(`====群管====
- 禁言@QQ 1分钟
- 解除禁言 @QQ
- 我要自闭 1分钟
- 开启全员禁言
- 解除全员禁言
- 升为管理@QQ
- 取消管理@QQ
- 修改名片@QQ XXX
- 修改头衔@QQ XXX
- 申请头衔 XXX
- 踢出群聊@QQ
- 退出群聊 1234
- 群聊转发 1234 XXX
- 聊转发 0000 XXX`)
ctx.SendChain(message.Text(
"====群管====", "\n",
"- 禁言@QQ 1分钟", "\n",
"- 解除禁言 @QQ", "\n",
"- 我要自闭 1分钟", "\n",
"- 开启全员禁言", "\n",
"- 解除全员禁言", "\n",
"- 升为管理@QQ", "\n",
"- 取消管理@QQ", "\n",
"- 修改名片@QQ XXX", "\n",
"- 修改头衔@QQ XXX", "\n",
"- 申请头衔 XXX", "\n",
"- 出群聊@QQ", "\n",
"- 退出群聊 1234", "\n",
"- 聊转发 1234 XXX", "\n",
"- 私聊转发 0000 XXX",
))
return
})
// 升为管理
@@ -41,7 +49,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
false,
).Get("nickname").Str
ctx.Send(nickname + " 升为了管理~")
ctx.SendChain(message.Text(nickname + " 升为了管理~"))
return
})
// 取消管理
@@ -57,7 +65,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
false,
).Get("nickname").Str
ctx.Send("残念~ " + nickname + " 暂时失去了管理员的资格")
ctx.SendChain(message.Text("残念~ " + nickname + " 暂时失去了管理员的资格"))
return
})
// 踢出群聊
@@ -73,7 +81,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
false,
).Get("nickname").Str
ctx.Send("残念~ " + nickname + " 被放逐")
ctx.SendChain(message.Text("残念~ " + nickname + " 被放逐"))
return
})
// 退出群聊
@@ -92,7 +100,7 @@ func init() { // 插件主体
ctx.Event.GroupID,
true,
)
ctx.Send("全员自闭开始~")
ctx.SendChain(message.Text("全员自闭开始~"))
return
})
// 解除全员禁言
@@ -102,7 +110,7 @@ func init() { // 插件主体
ctx.Event.GroupID,
false,
)
ctx.Send("全员自闭结束~")
ctx.SendChain(message.Text("全员自闭结束~"))
return
})
// 禁言
@@ -127,7 +135,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
duration*60, // 要禁言的时间(分钟)
)
ctx.Send("小黑屋收留成功~")
ctx.SendChain(message.Text("小黑屋收留成功~"))
return
})
// 解除禁言
@@ -138,7 +146,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要解除禁言的人的qq
0,
)
ctx.Send("小黑屋释放成功~")
ctx.SendChain(message.Text("小黑屋释放成功~"))
return
})
// 自闭禁言
@@ -163,7 +171,7 @@ func init() { // 插件主体
ctx.Event.UserID,
duration*60, // 要自闭的时间(分钟)
)
ctx.Send("那我就不手下留情了~")
ctx.SendChain(message.Text("那我就不手下留情了~"))
return
})
// 修改名片
@@ -174,7 +182,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
ctx.State["regex_matched"].([]string)[2], // 修改成的群名片
)
ctx.Send("嗯!已经修改了")
ctx.SendChain(message.Text("嗯!已经修改了"))
return
})
// 修改头衔
@@ -185,7 +193,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
)
ctx.Send("嗯!已经修改了")
ctx.SendChain(message.Text("嗯!已经修改了"))
return
})
// 申请头衔
@@ -196,7 +204,7 @@ func init() { // 插件主体
ctx.Event.UserID, // 被修改群头衔的人
ctx.State["regex_matched"].([]string)[1], // 修改成的群头衔
)
ctx.Send("嗯!不错的头衔呢~")
ctx.SendChain(message.Text("嗯!不错的头衔呢~"))
return
})
// 群聊转发
@@ -210,7 +218,7 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的群
content, // 需要发送的信息
)
ctx.Send("📧 --> " + ctx.State["regex_matched"].([]string)[1])
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
return
})
// 私聊转发
@@ -224,14 +232,61 @@ func init() { // 插件主体
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的人的qq
content, // 需要发送的信息
)
ctx.Send("📧 --> " + ctx.State["regex_matched"].([]string)[1])
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
return
})
// 定时提醒
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimeStamp(dateStrs, false)
ts.Grpid = uint64(ctx.Event.GroupID)
if ts.Enable {
go timer.RegisterTimer(ts, true)
ctx.Send("记住了~")
} else {
ctx.Send("参数非法!")
}
return
})
// 取消定时
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimeStamp(dateStrs, true)
ti := timer.GetTimerInfo(ts)
t, ok := (*timer.Timers)[ti]
if ok {
t.Enable = false
delete(*timer.Timers, ti) //避免重复取消
timer.SaveTimers()
ctx.Send("取消成功~")
} else {
ctx.Send("没有这个定时器哦~")
}
return
})
// 随机点名
zero.OnFullMatchGroup([]string{"翻牌"}).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
list := ctx.GetGroupMemberList(ctx.Event.GroupID)
rand.Seed(time.Now().UnixNano())
rand_index := fmt.Sprint(rand.Intn(int(list.Get("#").Int())))
random_card := list.Get(rand_index + ".card").String()
if random_card == "" {
random_card = list.Get(rand_index + ".nickname").String()
}
ctx.Send(random_card + ",就是你啦!")
}
})
// 入群欢迎
zero.OnNotice().SetBlock(false).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.NoticeType == "group_increase" {
ctx.Send("欢迎~")
ctx.SendChain(message.Text("欢迎~"))
}
return
})
@@ -239,7 +294,7 @@ func init() { // 插件主体
zero.OnNotice().SetBlock(false).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.NoticeType == "group_decrease" {
ctx.Send("有人跑路了~")
ctx.SendChain(message.Text("有人跑路了~"))
}
return
})

View File

@@ -1,3 +1,6 @@
/*
QQ音乐、网易云、酷狗、酷我 点歌
*/
package music
import (

7
run.bat Normal file
View File

@@ -0,0 +1,7 @@
go version
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GO111MODULE=auto
go mod tidy
::go build -ldflags="-s -w" -o ZeroBot-Plugin.exe
go run main.go
pause

View File

@@ -1,6 +1,6 @@
go version
gcc -v
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GO111MODULE=auto
go build -ldflags="-s -w" -o ZeroBot-Plugin-windows.exe
pause
go mod tidy
#go build -ldflags="-s -w" -o ZeroBot-Plugin
go run main.go

262
runcode/code_runner.go Normal file
View File

@@ -0,0 +1,262 @@
/*
基于 https://tool.runoob.com 的在线运行代码
*/
package runcode
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/tidwall/gjson"
)
var limit = rate.NewManager(time.Minute*3, 5)
func init() {
RunAllow := true
templates := map[string]string{
"py2": "print 'Hello World!'",
"ruby": "puts \"Hello World!\";",
"rb": "puts \"Hello World!\";",
"php": "<?php\n\techo 'Hello World!';\n?>",
"javascript": "console.log(\"Hello World!\");",
"js": "console.log(\"Hello World!\");",
"node.js": "console.log(\"Hello World!\");",
"scala": "object Main {\n def main(args:Array[String])\n {\n println(\"Hello World!\")\n }\n\t\t\n}",
"go": "package main\n\nimport \"fmt\"\n\nfunc main() {\n fmt.Println(\"Hello, World!\")\n}",
"c": "#include <stdio.h>\n\nint main()\n{\n printf(\"Hello, World! \n\");\n return 0;\n}",
"c++": "#include <iostream>\nusing namespace std;\n\nint main()\n{\n cout << \"Hello World\";\n return 0;\n}",
"cpp": "#include <iostream>\nusing namespace std;\n\nint main()\n{\n cout << \"Hello World\";\n return 0;\n}",
"java": "public class HelloWorld {\n public static void main(String []args) {\n System.out.println(\"Hello World!\");\n }\n}",
"rust": "fn main() {\n println!(\"Hello World!\");\n}",
"rs": "fn main() {\n println!(\"Hello World!\");\n}",
"c#": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
"cs": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
"csharp": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
"shell": "echo 'Hello World!'",
"bash": "echo 'Hello World!'",
"erlang": "% escript will ignore the first line\n\nmain(_) ->\n io:format(\"Hello World!~n\").",
"perl": "print \"Hello, World!\n\";",
"python": "print(\"Hello, World!\")",
"py": "print(\"Hello, World!\")",
"swift": "var myString = \"Hello, World!\"\nprint(myString)",
"lua": "var myString = \"Hello, World!\"\nprint(myString)",
"pascal": "runcode Hello;\nbegin\n writeln ('Hello, world!')\nend.",
"kotlin": "fun main(args : Array<String>){\n println(\"Hello World!\")\n}",
"kt": "fun main(args : Array<String>){\n println(\"Hello World!\")\n}",
"r": "myString <- \"Hello, World!\"\nprint ( myString)",
"vb": "Module Module1\n\n Sub Main()\n Console.WriteLine(\"Hello World!\")\n End Sub\n\nEnd Module",
"typescript": "const hello : string = \"Hello World!\"\nconsole.log(hello)",
"ts": "const hello : string = \"Hello World!\"\nconsole.log(hello)",
}
table := map[string][2]string{
"py2": {"0", "py"},
"ruby": {"1", "rb"},
"rb": {"1", "rb"},
"php": {"3", "php"},
"javascript": {"4", "js"},
"js": {"4", "js"},
"node.js": {"4", "js"},
"scala": {"5", "scala"},
"go": {"6", "go"},
"c": {"7", "c"},
"c++": {"7", "cpp"},
"cpp": {"7", "cpp"},
"java": {"8", "java"},
"rust": {"9", "rs"},
"rs": {"9", "rs"},
"c#": {"10", "cs"},
"cs": {"10", "cs"},
"csharp": {"10", "cs"},
"shell": {"10", "sh"},
"bash": {"10", "sh"},
"erlang": {"12", "erl"},
"perl": {"14", "pl"},
"python": {"15", "py3"},
"py": {"15", "py3"},
"swift": {"16", "swift"},
"lua": {"17", "lua"},
"pascal": {"18", "pas"},
"kotlin": {"19", "kt"},
"kt": {"19", "kt"},
"r": {"80", "r"},
"vb": {"84", "vb"},
"typescript": {"1010", "ts"},
"ts": {"1010", "ts"},
}
zero.OnFullMatch(">runcode help").SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(
"使用说明: ", "\n",
">runcode [language] [code block]", "\n",
"模板查看: ", "\n",
">runcode [language] help", "\n",
"支持语种: ", "\n",
"Go || Python || C/C++ || C# || Java || Lua ", "\n",
"JavaScript || TypeScript || PHP || Shell ", "\n",
"Kotlin || Rust || Erlang || Ruby || Swift ", "\n",
"R || VB || Py2 || Perl || Pascal || Scala ", "\n",
))
})
zero.OnFullMatch(">runcode on", zero.AdminPermission).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
RunAllow = true
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text("在线运行代码功能已启用"),
)
})
zero.OnFullMatch(">runcode off", zero.AdminPermission).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
RunAllow = false
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text("在线运行代码功能已禁用"),
)
})
zero.OnRegex(`^>runcode\s(.+?)\s([\s\S]+)$`).SetBlock(true).SecondPriority().
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.Send("请稍后重试0x0...")
return
}
language := ctx.State["regex_matched"].([]string)[1]
language = strings.ToLower(language)
if runType, exist := table[language]; !exist {
// 不支持语言
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text("语言不是受支持的编程语种呢~"),
)
return
} else {
if RunAllow == false {
// 运行代码被禁用
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text("在线运行代码功能已被禁用"),
)
return
}
// 执行运行
block := ctx.State["regex_matched"].([]string)[2]
block = message.UnescapeCQCodeText(block)
if block == "help" {
//输出模板
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, " ", language, "-template:\n"),
message.Text(
">runcode ", language, "\n",
templates[language],
),
)
return
}
if output, err := runCode(block, runType); err != nil {
// 运行失败
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text("ERROR: ", err),
)
return
} else {
// 运行成功
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text(output),
)
return
}
}
})
}
func runCode(code string, runType [2]string) (string, error) {
// 对菜鸟api发送数据并返回结果
api := "https://tool.runoob.com/compile2.php"
header := http.Header{
"Content-Type": []string{"application/x-www-form-urlencoded; charset=UTF-8"},
"Referer": []string{"https://c.runoob.com/"},
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0"},
}
val := url.Values{
"code": []string{code},
"token": []string{"4381fe197827ec87cbac9552f14ec62a"},
"stdin": []string{""},
"language": []string{runType[0]},
"fileext": []string{runType[1]},
}
// 发送请求
client := &http.Client{
Timeout: time.Duration(15 * time.Second),
}
request, _ := http.NewRequest("POST", api, strings.NewReader(val.Encode()))
request.Header = header
body, err := client.Do(request)
if err != nil {
return "", err
}
defer body.Body.Close()
if body.StatusCode != http.StatusOK {
return "", fmt.Errorf("code %d", body.StatusCode)
}
res, err := ioutil.ReadAll(body.Body)
if err != nil {
return "", err
}
// 结果处理
content := gjson.ParseBytes(res)
if e := content.Get("errors").Str; e != "\n\n" {
return "", fmt.Errorf(cutTooLong(clearNewLineSuffix(e)))
}
output := content.Get("output").Str
return cutTooLong(clearNewLineSuffix(output)), nil
}
// 清除末尾多余的换行符
func clearNewLineSuffix(text string) string {
for strings.HasSuffix(text, "\n") {
text = text[:len(text)-1]
}
return text
}
// 截断过长文本
func cutTooLong(text string) string {
temp := []rune(text)
count := 0
for i := range temp {
switch {
case temp[i] == 13 && i < len(temp)-1 && temp[i+1] == 10:
// 匹配 \r\n 跳过,等 \n 自己加
case temp[i] == 10:
count++
case temp[i] == 13:
count++
}
if count > 30 || i > 1000 {
temp = append(temp[:i-1], []rune("\n............\n............")...)
break
}
}
return string(temp)
}

111
setutime/classify.go Normal file
View File

@@ -0,0 +1,111 @@
package setutime
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"strconv"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/tidwall/gjson"
)
var (
CACHE_IMG_FILE = "/tmp/setugt"
CACHE_URI = "file:///" + CACHE_IMG_FILE
VOTE_API_URL = "http://saki.fumiama.top/vote?uuid=零号&img=%s&class=%d"
CLASSIFY_HEAD = "http://saki.fumiama.top:62002/dice?url="
MsgofGrp = make(map[int64]int64)
dhashofmsg = make(map[int64]string)
)
func Classify(ctx *zero.Ctx, targeturl string, noimg bool) {
get_url := CLASSIFY_HEAD + url.QueryEscape(targeturl)
if noimg {
get_url += "&noimg=true"
}
resp, err := http.Get(get_url)
if err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
} else {
if noimg {
data, err1 := ioutil.ReadAll(resp.Body)
if err1 == nil {
dhash := gjson.GetBytes(data, "img").String()
class := int(gjson.GetBytes(data, "class").Int())
replyClass(ctx, dhash, class, noimg)
} else {
ctx.Send(fmt.Sprintf("ERROR: %v", err1))
}
} else {
class, err1 := strconv.Atoi(resp.Header.Get("Class"))
dhash := resp.Header.Get("DHash")
if err1 != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err1))
}
defer resp.Body.Close()
// 写入文件
data, _ := ioutil.ReadAll(resp.Body)
f, _ := os.OpenFile(CACHE_IMG_FILE, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
defer f.Close()
f.Write(data)
replyClass(ctx, dhash, class, noimg)
}
}
}
func Vote(ctx *zero.Ctx, class int) {
msg, ok := MsgofGrp[ctx.Event.GroupID]
if ok {
ctx.DeleteMessage(msg)
delete(MsgofGrp, ctx.Event.GroupID)
dhash, ok2 := dhashofmsg[msg]
if ok2 {
http.Get(fmt.Sprintf(VOTE_API_URL, dhash, class))
delete(dhashofmsg, msg)
}
}
}
func replyClass(ctx *zero.Ctx, dhash string, class int, noimg bool) {
if class > 4 {
switch class {
case 5:
ctx.Send("[5]影响不好啦!")
case 6:
ctx.Send("[6]太涩啦,🐛了!")
}
if dhash != "" && !noimg {
b14, err3 := url.QueryUnescape(dhash)
if err3 == nil {
ctx.Send("给你点提示哦:" + b14)
}
}
} else {
var last_message_id int64
if !noimg {
last_message_id = ctx.SendChain(message.Image(CACHE_URI).Add("no_cache", "0"))
last_group_id := ctx.Event.GroupID
MsgofGrp[last_group_id] = last_message_id
dhashofmsg[last_message_id] = dhash
} else {
last_message_id = ctx.Event.MessageID
}
switch class {
case 0:
ctx.SendChain(message.Reply(last_message_id), message.Text("[0]一堆像素点"))
case 1:
ctx.SendChain(message.Reply(last_message_id), message.Text("[1]普通"))
case 2:
ctx.SendChain(message.Reply(last_message_id), message.Text("[2]有点意思"))
case 3:
ctx.SendChain(message.Reply(last_message_id), message.Text("[3]不错"))
case 4:
ctx.SendChain(message.Reply(last_message_id), message.Text("[4]我好啦!"))
}
}
}

View File

@@ -2,137 +2,166 @@ package setutime
import (
"fmt"
"os"
"strconv"
"strings"
"time"
utils "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime/utils"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/ascii2d"
"github.com/FloatTech/AnimeAPI/pixiv"
"github.com/FloatTech/AnimeAPI/saucenao"
)
var (
CACHEPATH = os.TempDir() // 缓冲图片路径
)
func init() { // 插件主体
// 根据PID搜图
zero.OnRegex(`^搜图(\d+)$`).SetBlock(true).SetPriority(30).
Handle(func(ctx *zero.Ctx) {
id := utils.Str2Int(ctx.State["regex_matched"].([]string)[1])
id, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
ctx.Send("少女祈祷中......")
// 获取P站插图信息
illust := &utils.Illust{}
if err := illust.IllustInfo(id); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
illust, err := pixiv.Works(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 下载P站插图
if _, err := illust.PixivPicDown(CACHEPATH); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
if _, err := download(illust, "data/SetuTime/search/"); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 发送搜索结果
ctx.Send(illust.DetailPic)
return
ctx.SendChain(
message.Image(file(illust)),
message.Text(
"\n",
"标题:", illust.Title, "\n",
"插画ID", illust.Pid, "\n",
"画师:", illust.UserName, "\n",
"画师ID", illust.UserId, "\n",
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
),
)
})
// 通过回复以图搜图
zero.OnRegex(`\[CQ:reply,id=(.*?)\](.*)搜索图片`).SetBlock(true).SetPriority(32).
// 以图搜图
zero.OnMessage(FullMatchText("以图搜图", "搜索图片", "以图识图"), MustHasPicture()).SetBlock(true).SetPriority(999).
Handle(func(ctx *zero.Ctx) {
var pics []string // 图片搜索池子
// 获取回复的上文图片链接
id := utils.Str2Int(ctx.State["regex_matched"].([]string)[1])
for _, elem := range ctx.GetMessage(id).Elements {
if elem.Type == "image" {
pics = append(pics, elem.Data["url"])
}
}
// 没有收到图片则向用户索取
if len(pics) == 0 {
ctx.Send("请发送多张图片!")
next := ctx.FutureEvent("message", ctx.CheckSession())
recv, cancel := next.Repeat()
for e := range recv { // 循环获取channel发来的信息
if len(e.Message) == 1 && e.Message[0].Type == "text" {
cancel() // 如果是纯文本则退出索取
break
}
for _, elem := range e.Message {
if elem.Type == "image" { // 将信息中的图片添加到搜索池子
pics = append(pics, elem.Data["url"])
}
}
if len(pics) >= 5 {
cancel() // 如果是图片数量大于等于5则退出索取
break
}
}
}
if len(pics) == 0 {
ctx.Send("没有收到图片,搜图结束......")
return
}
// 开始搜索图片
ctx.Send("少女祈祷中......")
for _, pic := range pics {
if text, err := utils.SauceNaoSearch(pic); err == nil {
ctx.Send(text) // 返回SauceNAO的结果
continue
for _, pic := range ctx.State["image_url"].([]string) {
fmt.Println(pic)
if result, err := saucenao.SauceNAO(pic); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
} else {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
}
if text, err := utils.Ascii2dSearch(pic); err == nil {
ctx.Send(text) // 返回Ascii2d的结果
// 返回SauceNAO的结果
ctx.SendChain(
message.Text("我有把握是这个!"),
message.Image(result.Thumbnail),
message.Text(
"\n",
"相似度:", result.Similarity, "\n",
"标题:", result.Title, "\n",
"插画ID", result.PixivID, "\n",
"画师:", result.MemberName, "\n",
"画师ID", result.MemberID, "\n",
"直链:", "https://pixivel.moe/detail?id=", result.PixivID,
),
)
continue
}
if result, err := ascii2d.Ascii2d(pic); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
} else {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
}
}
return
})
// 通过命令以图搜图
zero.OnKeywordGroup([]string{"以图识图", "以图搜图", "搜索图片"}).SetBlock(true).SetPriority(33).
Handle(func(ctx *zero.Ctx) {
var pics []string // 图片搜索池子
// 获取信息中图片链接
for _, elem := range ctx.Event.Message {
if elem.Type == "image" {
pics = append(pics, elem.Data["url"])
}
}
// 没有收到图片则向用户索取
if len(pics) == 0 {
ctx.Send("请发送多张图片!")
next := ctx.FutureEvent("message", zero.CheckUser(ctx.Event.UserID))
recv, cancel := next.Repeat()
for e := range recv { // 循环获取channel发来的信息
if len(e.Message) == 1 && e.Message[0].Type == "text" {
cancel() // 如果是纯文本则退出索取
break
}
for _, elem := range e.Message {
if elem.Type == "image" { // 将信息中的图片添加到搜索池子
pics = append(pics, elem.Data["url"])
}
}
if len(pics) >= 5 {
cancel() // 如果是图片数量大于等于5则退出索取
break
}
}
}
if len(pics) == 0 {
ctx.Send("没有收到图片,搜图结束......")
return
}
// 开始搜索图片
ctx.Send("少女祈祷中......")
for _, pic := range pics {
if text, err := utils.SauceNaoSearch(pic); err == nil {
ctx.Send(text) // 返回SauceNAO的结果
// 返回Ascii2d的结果
ctx.SendChain(
message.Text(
"大概是这个?", "\n",
"标题:", result.Title, "\n",
"插画ID", result.Pid, "\n",
"画师:", result.UserName, "\n",
"画师ID", result.UserId, "\n",
"直链:", "https://pixivel.moe/detail?id=", result.Pid,
),
)
continue
} else {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
}
if text, err := utils.Ascii2dSearch(pic); err == nil {
ctx.Send(text) // 返回Ascii2d的结果
continue
} else {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
}
}
return
})
}
// FullMatchText 如果信息中文本完全匹配则返回 true
func FullMatchText(src ...string) zero.Rule {
return func(ctx *zero.Ctx) bool {
msg := ctx.Event.Message
for _, elem := range msg {
if elem.Type == "text" {
text := elem.Data["text"]
text = strings.ReplaceAll(text, " ", "")
text = strings.ReplaceAll(text, "\r", "")
text = strings.ReplaceAll(text, "\n", "")
for _, s := range src {
if text == s {
return true
}
}
}
}
return false
}
}
// HasPicture 消息含有图片返回 true
func HasPicture() zero.Rule {
return func(ctx *zero.Ctx) bool {
msg := ctx.Event.Message
url := []string{}
// 如果是回复信息则将信息替换成被回复的那条
if msg[0].Type == "reply" {
id, _ := strconv.Atoi(msg[0].Data["id"])
msg = ctx.GetMessage(int64(id)).Elements
}
// 遍历信息中所有图片
for _, elem := range msg {
if elem.Type == "image" {
url = append(url, elem.Data["url"])
}
}
// 如果有图片就返回true
if len(url) > 0 {
ctx.State["image_url"] = url
return true
}
return false
}
}
// MustHasPicture 消息不存在图片阻塞60秒至有图片超时返回 false
func MustHasPicture() zero.Rule {
return func(ctx *zero.Ctx) bool {
if HasPicture()(ctx) {
return true
}
// 没有图片就索取
ctx.Send("请发送一张图片")
next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID), HasPicture())
recv, cancel := next.Repeat()
select {
case e := <-recv:
cancel()
newCtx := &zero.Ctx{Event: e, State: zero.State{}}
if HasPicture()(newCtx) {
ctx.State["image_url"] = newCtx.State["image_url"]
return true
}
return false
case <-time.After(time.Second * 60):
return false
}
}
}

73
setutime/rand_image.go Normal file
View File

@@ -0,0 +1,73 @@
package setutime
import (
"fmt"
"strings"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var (
RANDOM_API_URL = "https://api.pixivweb.com/anime18r.php?return=img"
BLOCK_REQUEST = false
)
func init() { // 插件主体
zero.OnRegex(`^设置随机图片网址(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
url := ctx.State["regex_matched"].([]string)[1]
if !strings.HasPrefix(url, "http") {
ctx.Send("URL非法!")
} else {
RANDOM_API_URL = url
}
return
})
// 有保护的随机图片
zero.OnFullMatch("随机图片").SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
Classify(ctx, RANDOM_API_URL, false)
}
return
})
// 直接随机图片,危险,仅管理员可用
zero.OnFullMatch("直接随机", zero.AdminPermission).SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
if BLOCK_REQUEST {
ctx.Send("请稍后再试哦")
} else {
BLOCK_REQUEST = true
last_message_id := ctx.SendChain(message.Image(RANDOM_API_URL).Add("no_cache", "0"))
last_group_id := ctx.Event.GroupID
MsgofGrp[last_group_id] = last_message_id
BLOCK_REQUEST = false
}
}
return
})
// 撤回最后的随机图片
zero.OnFullMatch("不许好").SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
Vote(ctx, 5)
})
// 撤回最后的随机图片
zero.OnFullMatch("太涩了").SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
Vote(ctx, 6)
})
// 上传一张图进行评价
zero.OnFullMatch("评价图片", MustHasPicture()).SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.GroupID > 0 {
ctx.Send("少女祈祷中......")
for _, pic := range ctx.State["image_url"].([]string) {
fmt.Println(pic)
Classify(ctx, pic, true)
}
}
return
})
}

View File

@@ -1,140 +1,146 @@
package setutime
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/Yiwen-Chan/ZeroBot-Plugin/setutime/utils"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/pixiv"
)
var limit = rate.NewManager(time.Minute*1, 5)
// Pools 图片缓冲池
type Pool struct {
Lock sync.Mutex
DB *Sqlite
Path string
Group int64
List []string
Max int
Pool map[string][]*pixiv.Illust
Form int64
}
var (
BOTPATH = utils.PathExecute() // 当前bot运行目录
DATAPATH = BOTPATH + "data/SetuTime/" // 数据目录
DBPATH = DATAPATH + "SetuTime.db" // 数据库路径
CACHEPATH = DATAPATH + "cache/" // 缓冲图片路径
CACHEGROUP int64 = 868047498 // 缓冲图片群,不修改无法缓存
PoolList = []string{"涩图", "二次元", "风景", "车万"} // 可自定义
DB = utils.Sqlite{DBPath: DBPATH} // 新建涩图数据库对象
PoolsCache = utils.NewPoolsCache() // 新建一个缓冲池对象
FORM = "PIC" // 默认 PIC 格式
)
func init() {
PoolsCache.Group = CACHEGROUP // 图片缓冲群
PoolsCache.Path = CACHEPATH // 缓冲图片路径
utils.CreatePath(DBPATH)
utils.CreatePath(CACHEPATH)
for i := range PoolList {
if err := DB.Create(PoolList[i], &utils.Illust{}); err != nil {
// NewPoolsCache 返回一个缓冲池对象
func NewPools() *Pool {
cache := &Pool{
DB: &Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
Path: "data/SetuTime/cache/",
Group: 0,
List: []string{"涩图", "二次元", "风景", "车万"}, // 可以自己加类别,得自己加图片进数据库
Max: 10,
Pool: map[string][]*pixiv.Illust{},
Form: 0,
}
err := os.MkdirAll(cache.Path, 0644)
if err != nil {
panic(err)
}
for i := range cache.List {
if err := cache.DB.Create(cache.List[i], &pixiv.Illust{}); err != nil {
panic(err)
}
}
return cache
}
var (
POOL = NewPools()
limit = rate.NewManager(time.Minute*1, 5)
)
func init() { // 插件主体
zero.OnRegex(`^来份(.*)$`, FirstValueInList(PoolList)).SetBlock(true).SetPriority(20).
zero.OnRegex(`^来份(.*)$`, FirstValueInList(POOL.List)).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.Send("请稍后重试0x0...")
ctx.SendChain(message.Text("少女祈祷中......"))
return
}
var type_ = ctx.State["regex_matched"].([]string)[1]
// 补充池子
go func() {
times := utils.Min(PoolsCache.Max-PoolsCache.Size(type_), 2)
times := Min(POOL.Max-POOL.Size(type_), 2)
for i := 0; i < times; i++ {
illust := &utils.Illust{}
illust := &pixiv.Illust{}
// 查询出一张图片
if err := DB.Select(type_, illust, "ORDER BY RANDOM() limit 1"); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
if err := POOL.DB.Select(type_, illust, "ORDER BY RANDOM() limit 1"); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
ctx.SendGroupMessage(PoolsCache.Group, "正在下载"+illust.ImageUrls)
file, err := illust.PixivPicDown(PoolsCache.Path)
if err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
continue
}
if id := ctx.SendGroupMessage(PoolsCache.Group, illust.NormalPic(file)); id == 0 {
ctx.Send(fmt.Sprintf("ERROR: %v", "发送到缓存群失败,请确认缓存群群号"))
// 下载图片
if _, err := download(illust, POOL.Path); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
ctx.SendGroupMessage(POOL.Group, []message.MessageSegment{message.Image(file(illust))})
// 向缓冲池添加一张图片
if err := PoolsCache.Push(type_, illust); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
continue
}
POOL.Push(type_, illust)
time.Sleep(time.Second * 1)
}
}()
// 如果没有缓存阻塞5秒
if PoolsCache.Size(type_) == 0 {
ctx.Send("[SetuTime] 正在填充弹药......")
if POOL.Size(type_) == 0 {
ctx.SendChain(message.Text("INFO: 正在填充弹药......"))
<-time.After(time.Second * 5)
if PoolsCache.Size(type_) == 0 {
ctx.Send("[SetuTime] 等待填充,请稍后再试......")
if POOL.Size(type_) == 0 {
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
return
}
}
// 从缓冲池里抽一张
if id := ctx.Send(PoolsCache.GetOnePic(type_, FORM)); id == 0 {
ctx.Send(fmt.Sprintf("ERROR: %v", errors.New("可能被风控了")))
if id := ctx.SendChain(message.Image(file(POOL.Pop(type_)))); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
return
})
zero.OnRegex(`^添加(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
zero.OnRegex(`^添加(.*?)(\d+)$`, FirstValueInList(POOL.List), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
Handle(func(ctx *zero.Ctx) {
var (
type_ = ctx.State["regex_matched"].([]string)[1]
id = utils.Str2Int(ctx.State["regex_matched"].([]string)[2])
illust = &utils.Illust{}
type_ = ctx.State["regex_matched"].([]string)[1]
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
ctx.Send("少女祈祷中......")
ctx.SendChain(message.Text("少女祈祷中......"))
// 查询P站插图信息
if err := illust.IllustInfo(id); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
illust, err := pixiv.Works(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 下载插画
if _, err := illust.PixivPicDown(PoolsCache.Path); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
if _, err := download(illust, POOL.Path); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
file := fmt.Sprintf("%s%d.jpg", PoolsCache.Path, illust.Pid)
if id := ctx.Send(illust.DetailPic(file)); id == 0 {
ctx.Send(fmt.Sprintf("ERROR: %v", "可能被风控,发送失败"))
// 发送到发送者
if id := ctx.SendChain(message.Image(file(illust))); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控,发送失败"))
return
}
// 添加插画到对应的数据库table
if err := DB.Insert(type_, illust); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
if err := POOL.DB.Insert(type_, illust); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send("添加成功")
return
})
zero.OnRegex(`^删除(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
zero.OnRegex(`^删除(.*?)(\d+)$`, FirstValueInList(POOL.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
Handle(func(ctx *zero.Ctx) {
var (
type_ = ctx.State["regex_matched"].([]string)[1]
id = utils.Str2Int(ctx.State["regex_matched"].([]string)[2])
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
// 查询数据库
if err := DB.Delete(type_, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
if err := POOL.DB.Delete(type_, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
ctx.Send(fmt.Sprintf("ERROR: %v", err))
return
}
@@ -143,36 +149,22 @@ func init() { // 插件主体
})
// 查询数据库涩图数量
zero.OnFullMatchGroup([]string{"setu -s", "setu --status"}).SetBlock(true).SetPriority(23).
zero.OnFullMatchGroup([]string{">setu status"}).SetBlock(true).SetPriority(23).
Handle(func(ctx *zero.Ctx) {
state := []string{"[SetuTime]"}
for i := range PoolList {
num, err := DB.Num(PoolList[i])
for i := range POOL.List {
num, err := POOL.DB.Num(POOL.List[i])
if err != nil {
num = 0
}
state = append(state, "\n")
state = append(state, PoolList[i])
state = append(state, POOL.List[i])
state = append(state, ": ")
state = append(state, fmt.Sprintf("%d", num))
}
ctx.Send(strings.Join(state, ""))
return
})
// 开xml模式
zero.OnFullMatchGroup([]string{"setu -x", "setu --xml"}).SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
FORM = "XML"
ctx.Send("[SetuTime] XML->ON")
return
})
// 关xml模式
zero.OnFullMatchGroup([]string{"setu -p", "setu --pic"}).SetBlock(true).SetPriority(24).
Handle(func(ctx *zero.Ctx) {
FORM = "PIC"
ctx.Send("[SetuTime] XML->OFF")
return
})
}
// FirstValueInList 判断正则匹配的第一个参数是否在列表中
@@ -187,3 +179,81 @@ func FirstValueInList(list []string) zero.Rule {
return false
}
}
// Min 返回两数最小值
func Min(a, b int) int {
switch {
default:
return a
case a > b:
return b
case a < b:
return a
}
}
// Size 返回缓冲池指定类型的现有大小
func (p *Pool) Size(type_ string) int {
return len(p.Pool[type_])
}
// IsFull 返回缓冲池指定类型是否已满
func (p *Pool) IsFull(type_ string) bool {
return len(p.Pool[type_]) >= p.Max
}
// Push 向缓冲池插入一张图片
func (p *Pool) Push(type_ string, illust *pixiv.Illust) {
p.Lock.Lock()
defer p.Lock.Unlock()
p.Pool[type_] = append(p.Pool[type_], illust)
}
// Push 在缓冲池拿出一张图片
func (p *Pool) Pop(type_ string) (illust *pixiv.Illust) {
p.Lock.Lock()
defer p.Lock.Unlock()
if p.Size(type_) == 0 {
return
}
illust = p.Pool[type_][0]
p.Pool[type_] = p.Pool[type_][1:]
return
}
func file(i *pixiv.Illust) string {
filename := fmt.Sprint(i.Pid)
pwd, _ := os.Getwd()
filepath := pwd + `/` + POOL.Path + filename
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
return `file:///` + filepath + ".jpg"
}
if _, err := os.Stat(filepath + ".png"); err == nil || os.IsExist(err) {
return `file:///` + filepath + ".png"
}
if _, err := os.Stat(filepath + ".gif"); err == nil || os.IsExist(err) {
return `file:///` + filepath + ".gif"
}
return ""
}
func download(i *pixiv.Illust, filedir string) (string, error) {
filename := fmt.Sprint(i.Pid)
filepath := filedir + filename
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
return filepath + ".jpg", nil
}
if _, err := os.Stat(filepath + ".png"); err == nil || os.IsExist(err) {
return filepath + ".png", nil
}
if _, err := os.Stat(filepath + ".gif"); err == nil || os.IsExist(err) {
return filepath + ".gif", nil
}
// 下载最大分辨率为 1200 的图片
link := i.ImageUrls
link = strings.ReplaceAll(link, "img-original", "img-master")
link = strings.ReplaceAll(link, "_p0", "_p0_master1200")
link = strings.ReplaceAll(link, ".png", ".jpg")
// 下载
return pixiv.Download(link, filedir, filename)
}

View File

@@ -1,4 +1,4 @@
package utils
package setutime
import (
"database/sql"
@@ -6,7 +6,7 @@ import (
"reflect"
"strings"
_ "github.com/mattn/go-sqlite3"
_ "modernc.org/sqlite"
)
// Sqlite 数据库对象
@@ -20,7 +20,7 @@ type Sqlite struct {
// 返回错误
func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
if db.DB == nil {
database, err := sql.Open("sqlite3", db.DBPath)
database, err := sql.Open("sqlite", db.DBPath)
if err != nil {
return err
}
@@ -62,8 +62,8 @@ func (db *Sqlite) Insert(table string, objptr interface{}) (err error) {
if err != nil {
return err
}
defer rows.Close()
tags, _ := rows.Columns()
rows.Close()
var (
values = values(objptr)
top = len(tags) - 1

View File

@@ -1,100 +0,0 @@
package utils
import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
xpath "github.com/antchfx/htmlquery"
)
// Ascii2dSearch Ascii2d 以图搜图
// 第一个参数 返回错误
// 第二个参数 返回的信息
func Ascii2dSearch(pic string) (text string, err error) {
var (
api = "https://ascii2d.net/search/uri"
)
transport := http.Transport{
DisableKeepAlives: true,
}
client := &http.Client{
Transport: &transport,
}
// 包装请求参数
data := url.Values{}
data.Set("uri", pic) // 图片链接
fromData := strings.NewReader(data.Encode())
// 网络请求
req, _ := http.NewRequest("POST", api, fromData)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
resp, err := client.Do(req)
if err != nil {
return "", err
}
// 色合检索改变到特征检索
var bovwUrl = strings.ReplaceAll(resp.Request.URL.String(), "color", "bovw")
bovwReq, _ := http.NewRequest("POST", bovwUrl, nil)
bovwReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
bovwReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36")
bovwResp, err := client.Do(bovwReq)
if err != nil {
return "", err
}
defer bovwResp.Body.Close()
// 解析XPATH
doc, err := xpath.Parse(resp.Body)
if err != nil {
return "", err
}
// 取出每个返回的结果
list := xpath.Find(doc, `//div[@class="row item-box"]`)
var link string
// 遍历取出第一个返回的PIXIV结果
for _, n := range list {
linkPath := xpath.Find(n, `//div[2]/div[3]/h6/a[1]`)
picPath := xpath.Find(n, `//div[1]/img`)
if len(linkPath) != 0 && len(picPath) != 0 {
link = xpath.SelectAttr(linkPath[0], "href")
if strings.Contains(link, "www.pixiv.net") {
break
}
}
}
// 链接取出PIXIV id
var index = strings.LastIndex(link, "/")
if link == "" || index == -1 {
return "", errors.New("Ascii2d not found")
}
var id = Str2Int(link[index+1:])
if id == 0 {
return "", errors.New("convert to pid error")
}
// 根据PID查询插图信息
var illust = &Illust{}
if err := illust.IllustInfo(id); err != nil {
return "", err
}
if illust.AgeLimit != "all-age" {
return "", errors.New("Ascii2d not found")
}
// 返回插图信息文本
return fmt.Sprintf(
`[SetuTime] emmm大概是这个
标题:%s
插画ID%d
画师:%s
画师ID%d
直链https://pixivel.moe/detail?id=%d`,
illust.Title,
illust.Pid,
illust.UserName,
illust.UserId,
illust.Pid,
), nil
}

View File

@@ -1,74 +0,0 @@
package utils
import (
"crypto/md5"
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"strings"
)
// urlCache 缓存并返回缓存路径
func (this *Illust) PixivPicDown(path string) (savePath string, err error) {
url := this.ImageUrls
pid := this.Pid
url = strings.ReplaceAll(url, "img-original", "img-master")
url = strings.ReplaceAll(url, "_p0", "_p0_master1200")
url = strings.ReplaceAll(url, ".png", ".jpg")
// 文件名为url的hash值
savePath = path + Int2Str(pid) + ".jpg"
// 文件存在或文件大小大于10kb
if PathExists(savePath) && FileSize(savePath) > 10240 {
return savePath, nil
}
// 模拟QQ客户端请求
client := &http.Client{
Transport: &http.Transport{
DisableKeepAlives: true,
// 绕过sni审查
TLSClientConfig: &tls.Config{
ServerName: "-",
InsecureSkipVerify: true,
},
// 更改dns
Dial: func(network, addr string) (net.Conn, error) {
return net.Dial("tcp", "210.140.92.140:443")
},
},
}
reqest, _ := http.NewRequest("GET", url, nil)
reqest.Header.Set("Referer", "https://www.pixiv.net/")
reqest.Header.Set("Host", "i.pximg.net")
reqest.Header.Set("User-Agent", "QQ/8.2.0.1296 CFNetwork/1126")
resp, err := client.Do(reqest)
if err != nil {
return "", err
}
fmt.Println(resp.StatusCode)
if code := resp.StatusCode; code != 200 {
return "", errors.New(fmt.Sprintf("Download failed, code %d", code))
}
defer resp.Body.Close()
// 写入文件
data, _ := ioutil.ReadAll(resp.Body)
f, _ := os.OpenFile(savePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
defer f.Close()
f.Write(data)
return savePath, err
}
// PicHash 返回图片的 md5 值
func PicHash(path string) string {
data, err := ioutil.ReadFile(path)
if err != nil {
return ""
}
return strings.ToUpper(fmt.Sprintf("%x", md5.Sum(data)))
}

View File

@@ -1,113 +0,0 @@
package utils
import (
"fmt"
"sync"
)
// PoolsCache 图片缓冲池
type PoolsCache struct {
Lock sync.Mutex
Max int
Path string
Group int64
Pool map[string][]*Illust
}
// NewPoolsCache 返回一个缓冲池对象
func NewPoolsCache() *PoolsCache {
return &PoolsCache{
Max: 10,
Path: "./data/SetuTime/cache/",
Group: 1048452984,
Pool: map[string][]*Illust{},
}
}
// Size 返回缓冲池指定类型的现有大小
func (p *PoolsCache) Size(type_ string) int {
return len(p.Pool[type_])
}
// IsFull 返回缓冲池指定类型是否已满
func (p *PoolsCache) IsFull(type_ string) bool {
return len(p.Pool[type_]) >= p.Max
}
// Push 向缓冲池插入一张图片,返回错误
func (p *PoolsCache) Push(type_ string, illust *Illust) (err error) {
p.Lock.Lock()
defer p.Lock.Unlock()
p.Pool[type_] = append(p.Pool[type_], illust)
return nil
}
// Push 在缓冲池拿出一张图片,返回错误
func (p *PoolsCache) Pop(type_ string) (illust *Illust) {
p.Lock.Lock()
defer p.Lock.Unlock()
if p.Size(type_) == 0 {
return
}
illust = p.Pool[type_][0]
p.Pool[type_] = p.Pool[type_][1:]
return
}
// Push 在缓冲池拿出一张图片返回指定格式CQ码
func (p *PoolsCache) GetOnePic(type_ string, form string) string {
var (
illust = p.Pop(type_)
file = fmt.Sprintf("%s%d.jpg", p.Path, illust.Pid)
)
switch form {
case "XML":
return illust.BigPic(file)
case "DETAIL":
return illust.DetailPic(file)
default:
return illust.NormalPic(file)
}
}
// BigPic 返回一张XML大图CQ码
func (i *Illust) BigPic(file string) string {
var hash = PicHash(file)
return fmt.Sprintf(`[CQ:xml,data=<?xml version='1.0'
encoding='UTF-8' standalone='yes' ?><msg serviceID="5"
templateID="12345" action="" brief="不够涩!"
sourceMsgId="0" url="" flag="0" adverSign="0" multiMsgFlag="0">
<item layout="0" advertiser_id="0" aid="0"><image uuid="%s.jpg" md5="%s"
GroupFiledid="2235033681" filesize="81322" local_path="%s.jpg"
minWidth="200" minHeight="200" maxWidth="500" maxHeight="1000" />
</item><source name="%s⭐(id:%d author:%s)" icon=""
action="" appid="-1" /></msg>]`,
hash,
hash,
hash,
i.Title,
i.Pid,
i.UserName,
)
}
// NormalPic 返回一张普通图CQ码
func (i *Illust) NormalPic(file string) string {
return fmt.Sprintf(`[CQ:image,file=file:///%s]`, file)
}
// DetailPic 返回一张带详细信息的图片CQ码
func (i *Illust) DetailPic(file string) string {
return fmt.Sprintf(`[SetuTime] %s 标题:%s
插画ID%d
画师:%s
画师ID%d
直链https://pixivel.moe/detail?id=%d`,
i.NormalPic(file),
i.Title,
i.Pid,
i.UserName,
i.UserId,
i.Pid,
)
}

View File

@@ -1,94 +0,0 @@
package utils
import (
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"strings"
"github.com/tidwall/gjson"
)
// Illust 插画信息
type Illust struct {
Pid int64 `db:"pid"`
Title string `db:"title"`
Caption string `db:"caption"`
Tags string `db:"tags"`
ImageUrls string `db:"image_urls"`
AgeLimit string `db:"age_limit"`
CreatedTime string `db:"created_time"`
UserId int64 `db:"user_id"`
UserName string `db:"user_name"`
}
// IllustInfo 根据p站插画id返回插画信息Illust
func (this *Illust) IllustInfo(id int64) (err error) {
api := fmt.Sprintf("https://pixiv.net/ajax/illust/%d", id)
transport := http.Transport{
DisableKeepAlives: true,
// 绕过sni审查
TLSClientConfig: &tls.Config{
ServerName: "-",
InsecureSkipVerify: true,
},
// 更改dns
Dial: func(network, addr string) (net.Conn, error) {
return net.Dial("tcp", "210.140.131.223:443")
},
}
client := &http.Client{
Transport: &transport,
}
// 网络请求
req, err := http.NewRequest("GET", api, nil)
if err != nil {
return err
}
req.Header.Set("Host", "pixiv.net")
req.Header.Set("Referer", "pixiv.net")
req.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
resp, err := client.Do(req)
if err != nil {
return err
}
if code := resp.StatusCode; code != 200 {
return errors.New(fmt.Sprintf("Search illust's info failed, status %d", code))
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
json := gjson.ParseBytes(body).Get("body")
// 如果有"R-18"tag则判断为R-18暂时
var ageLimit = "all-age"
for _, tag := range json.Get("tags.tags.#.tag").Array() {
if tag.Str == "R-18" {
ageLimit = "r18"
break
}
}
// 解决json返回带html格式
var caption = strings.ReplaceAll(json.Get("illustComment").Str, "<br />", "\n")
if index := strings.Index(caption, "<"); index != -1 {
caption = caption[:index]
}
// 解析返回插画信息
this.Pid = json.Get("illustId").Int()
this.Title = json.Get("illustTitle").Str
this.Caption = caption
this.Tags = fmt.Sprintln(json.Get("tags.tags.#.tag").Array())
this.ImageUrls = json.Get("urls.original").Str
this.AgeLimit = ageLimit
this.CreatedTime = json.Get("createDate").Str
this.UserId = json.Get("userId").Int()
this.UserName = json.Get("userName").Str
return nil
}

View File

@@ -1,84 +0,0 @@
package utils
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/tidwall/gjson"
)
// SauceNaoSearch SauceNao 以图搜图 需要链接 返回错误和信息
func SauceNaoSearch(pic string) (text string, err error) {
var (
api = "https://saucenao.com/search.php"
apiKey = "2cc2772ca550dbacb4c35731a79d341d1a143cb5"
minSimilarity = 70.0 // 返回图片结果的最小相似度
)
transport := http.Transport{
DisableKeepAlives: true,
}
client := &http.Client{
Transport: &transport,
}
// 包装请求参数
data := url.Values{}
data.Set("url", pic) // 图片链接
data.Set("api_key", apiKey) // api_key
data.Set("db", "5") // 只搜索Pixiv
data.Set("numres", "1") // 返回一个结果
data.Set("output_type", "2") // 返回JSON格式数据
fromData := strings.NewReader(data.Encode())
// 网络请求
req, err := http.NewRequest("POST", api, fromData)
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
if code := resp.StatusCode; code != 200 {
// 如果返回不是200则立刻抛出错误
return "", errors.New(fmt.Sprintf("SauceNAO not found, code %d", code))
}
content := gjson.ParseBytes(body)
if status := content.Get("header.status").Int(); status != 0 {
// 如果json信息返回status不为0则立刻抛出错误
return "", errors.New(fmt.Sprintf("SauceNAO not found, status %d", status))
}
if content.Get("results.0.header.similarity").Float() < minSimilarity {
return "", errors.New("SauceNAO not found")
}
// 正常发送
return fmt.Sprintf(
`[SetuTime] 我有把握是这个![CQ:image,file=%s]相似度:%s%%
标题:%s
插画ID%d
画师:%s
画师ID%d
直链https://pixivel.moe/detail?id=%d`,
content.Get("results.0.header.thumbnail").Str,
content.Get("results.0.header.similarity").Str,
content.Get("results.0.data.title").Str,
content.Get("results.0.data.pixiv_id").Int(),
content.Get("results.0.data.member_name").Str,
content.Get("results.0.data.member_id").Int(),
content.Get("results.0.data.pixiv_id").Int(),
), nil
}

View File

@@ -1,5 +0,0 @@
package utils
var (
XML = true // 图片XML开关默认开启
)

View File

@@ -1,73 +0,0 @@
package utils
import (
"os"
"strconv"
"strings"
)
// Str2Int string --> int64
func Str2Int(str string) int64 {
val, _ := strconv.Atoi(str)
return int64(val)
}
// Int2Str int64 --> string
func Int2Str(val int64) string {
str := strconv.FormatInt(val, 10)
return str
}
// PathExecute 返回当前运行目录
func PathExecute() string {
dir, err := os.Getwd()
if err != nil {
panic(err)
}
return dir + "/"
}
// CreatePath 生成路径或文件所对应的目录
func CreatePath(path string) {
length := len(path)
switch {
case path[length:] != "/":
path = path[:strings.LastIndex(path, "/")]
case path[length:] != "\\":
path = path[:strings.LastIndex(path, "\\")]
default:
//
}
if !PathExists(path) {
err := os.MkdirAll(path, 0644)
if err != nil {
panic(err)
}
}
}
// PathExists 判断路径或文件是否存在
func PathExists(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}
// FileSize 获取文件大小
func FileSize(file string) int64 {
if fi, err := os.Stat(file); err == nil {
return fi.Size()
}
return 0
}
// Min 返回两数最小值
func Min(a, b int) int {
switch {
default:
return a
case a > b:
return b
case a < b:
return a
}
}

56
shindan/shindan.go Normal file
View File

@@ -0,0 +1,56 @@
/*
基于 https://shindanmaker.com 的测定小功能
*/
package shindan
import (
"strconv"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/shindanmaker"
)
var (
// 限制调用频率
limit = rate.NewManager(time.Minute*5, 5)
)
func init() {
zero.OnPrefix("异世界转生", number(587874)).SetBlock(true).FirstPriority().Handle(handle)
zero.OnPrefix("今天是什么少女", number(162207)).SetBlock(true).FirstPriority().Handle(handle)
zero.OnPrefix("卖萌", number(360578)).SetBlock(true).FirstPriority().Handle(handle)
}
// shindanmaker 处理函数
var handle = func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.Send("请稍后重试0x0...")
return
}
// 获取名字
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
}
// 调用接口
text, err := shindanmaker.Shindanmaker(ctx.State["id"].(int64), name)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
ctx.SendChain(message.Text(text))
}
// 传入 shindanmaker id
var number = func(id int64) func(ctx *zero.Ctx) bool {
return func(ctx *zero.Ctx) bool {
ctx.State["id"] = id
return true
}
}