mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-06 15:20:22 +00:00
Compare commits
96 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38935937ae | ||
|
|
a3685e2e83 | ||
|
|
3a5e391191 | ||
|
|
09a9dd53fd | ||
|
|
5e064249be | ||
|
|
67555512e7 | ||
|
|
591df6439c | ||
|
|
7dfb7dfe24 | ||
|
|
8e56f137b6 | ||
|
|
3b61c73c17 | ||
|
|
44dac98b37 | ||
|
|
1a7f98379a | ||
|
|
4109ef0612 | ||
|
|
93a9bf6c5b | ||
|
|
0b7b35cdcc | ||
|
|
350ef86dd6 | ||
|
|
2d69ae2e42 | ||
|
|
e95367f4b2 | ||
|
|
3101911aa2 | ||
|
|
ac73087f93 | ||
|
|
d375a3bbbb | ||
|
|
c46ca1d4c2 | ||
|
|
2a1cca8ebb | ||
|
|
d1fdc989b6 | ||
|
|
672215f753 | ||
|
|
4160175fcf | ||
|
|
8f8ba55fc9 | ||
|
|
1dbb4aa837 | ||
|
|
c183c4f17d | ||
|
|
fa6d14d89a | ||
|
|
65b92b9da3 | ||
|
|
a7056c4601 | ||
|
|
1dce0f7859 | ||
|
|
bdffbfab67 | ||
|
|
98b21d0fdf | ||
|
|
cccea70db1 | ||
|
|
d2bcd0bc9f | ||
|
|
08653fd3b6 | ||
|
|
75d0671d9b | ||
|
|
51ec3c32a9 | ||
|
|
ec0032c5ab | ||
|
|
2723f3662c | ||
|
|
539b050b97 | ||
|
|
a0b9623a9f | ||
|
|
6b263418a0 | ||
|
|
92989ce9fd | ||
|
|
173925b57a | ||
|
|
43735722bf | ||
|
|
d89e7aebec | ||
|
|
4677d789f2 | ||
|
|
2fb445746e | ||
|
|
505dfef48c | ||
|
|
19a9a8ef83 | ||
|
|
119730bada | ||
|
|
c46748524a | ||
|
|
29f833db41 | ||
|
|
1232856b21 | ||
|
|
770ae6ebd0 | ||
|
|
8c9ced0bda | ||
|
|
3b3dd3df99 | ||
|
|
0817e6233d | ||
|
|
aa4f428194 | ||
|
|
73717dec73 | ||
|
|
57e2ef3bab | ||
|
|
a5d0b8db8e | ||
|
|
3faec79371 | ||
|
|
c3e0520aec | ||
|
|
76db0b6fb4 | ||
|
|
40a8473ce0 | ||
|
|
21c1d104b8 | ||
|
|
0dda861863 | ||
|
|
b21f2f7166 | ||
|
|
e533170160 | ||
|
|
8236874779 | ||
|
|
4cc1dc2d1b | ||
|
|
18424bea7c | ||
|
|
0cc6251c0d | ||
|
|
63d87be789 | ||
|
|
7e3b898383 | ||
|
|
217fa62004 | ||
|
|
e667fb8708 | ||
|
|
2fef6f51b5 | ||
|
|
81bba8595a | ||
|
|
96aefc3938 | ||
|
|
5bb0493f02 | ||
|
|
e8fa6b8b07 | ||
|
|
ec15178ba7 | ||
|
|
1d469a40d5 | ||
|
|
4df30a56a3 | ||
|
|
6bc1e407d5 | ||
|
|
48442330c1 | ||
|
|
3623a88b16 | ||
|
|
ffca19edab | ||
|
|
52a8a9de6f | ||
|
|
b9e303196f | ||
|
|
da3a7e12bd |
55
.github/workflows/prerelease.yml
vendored
55
.github/workflows/prerelease.yml
vendored
@@ -1,55 +0,0 @@
|
||||
name: 测试版
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- p*
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
my-job:
|
||||
name: Build ZeroBot-Plugin on Push Tag 🚀
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Go
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
# A list of files, directories, and wildcard patterns to cache and restore
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-build-${{ hashFiles('**/go.sum') }}
|
||||
|
||||
- name: Tidy Go modules
|
||||
run: go mod tidy
|
||||
|
||||
- name: Build linux-x64
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x64
|
||||
- name: Build linux-x86
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x86
|
||||
- name: Build windows-x64
|
||||
run: CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x64.exe
|
||||
- name: Build windows-x86
|
||||
run: CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x86.exe
|
||||
- name: Build arm64
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=7 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-arm64
|
||||
- name: Build armv6
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-armv6
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: artifacts/zerobot-plugin-*
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
56
.github/workflows/release.yml
vendored
56
.github/workflows/release.yml
vendored
@@ -1,55 +1,27 @@
|
||||
name: 稳定版
|
||||
name: compile
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
my-job:
|
||||
name: Build ZeroBot-Plugin on Push Tag 🚀
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: '1.17'
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Go
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
with:
|
||||
# A list of files, directories, and wildcard patterns to cache and restore
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-build-${{ hashFiles('**/go.sum') }}
|
||||
|
||||
- name: Tidy Go modules
|
||||
run: go mod tidy
|
||||
|
||||
- name: Build linux-x64
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x64
|
||||
- name: Build linux-x86
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-x86
|
||||
- name: Build windows-x64
|
||||
run: CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x64.exe
|
||||
- name: Build windows-x86
|
||||
run: CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-windows-x86.exe
|
||||
- name: Build arm64
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=7 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-arm64
|
||||
- name: Build armv6
|
||||
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-s -w" -o artifacts/zerobot-plugin-linux-armv6
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: artifacts/zerobot-plugin-*
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,9 +3,13 @@ data/control
|
||||
data/SetuTime/search
|
||||
data/manager
|
||||
data/acgimage
|
||||
data/fortune
|
||||
data/hs
|
||||
plugins/*.so
|
||||
plugins/*.dll
|
||||
.idea/
|
||||
.DS_Store
|
||||
.vscode
|
||||
go-zero*
|
||||
nohup.out
|
||||
zerobot
|
||||
79
.goreleaser.yml
Normal file
79
.goreleaser.yml
Normal file
@@ -0,0 +1,79 @@
|
||||
project_name: zbp
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
builds:
|
||||
- id: nowin
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GO111MODULE=on
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w
|
||||
- id: win
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GO111MODULE=on
|
||||
goos:
|
||||
- windows
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w
|
||||
|
||||
checksum:
|
||||
name_template: "zbp_checksums.txt"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- "^docs:"
|
||||
- "^test:"
|
||||
- fix typo
|
||||
- Merge pull request
|
||||
- Merge branch
|
||||
- Merge remote-tracking
|
||||
- go mod tidy
|
||||
|
||||
archives:
|
||||
- id: nowin
|
||||
builds:
|
||||
- nowin
|
||||
- win
|
||||
name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
|
||||
nfpms:
|
||||
- license: GPL 3.0
|
||||
homepage: https://github.com/FloatTech/ZeroBot-Plugin
|
||||
file_name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
maintainer: FloatTech
|
||||
46
README.md
46
README.md
@@ -10,18 +10,39 @@
|
||||
[](https://github.com/takayama-lily/node-onebot)
|
||||
[](https://github.com/yyuueexxiinngg/onebot-kotlin)
|
||||
|
||||
[](https://goreportcard.com/report/github.com/github.com/Yiwen-Chan/ZeroBot-Plugin)
|
||||
[](https://goreportcard.com/report/github.com/github.com/FloatTech/ZeroBot-Plugin)
|
||||
[](https://github.com/howmanybots/onebot)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
|
||||
[](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
|
||||
|
||||
</div>
|
||||
|
||||
## 命令行参数
|
||||
```bash
|
||||
zerobot -h -t token -u url [-d|w] [-g] qq1 qq2 qq3 ...
|
||||
```
|
||||
- **-h**: 显示帮助
|
||||
- **-t token**: 设置`AccessToken`,默认为空
|
||||
- **-u url**: 设置`Url`,默认为`ws://127.0.0.1:6700`
|
||||
- **-d|w**: 开启 debug | warning 级别及以上日志输出
|
||||
- **-g**: 开启 [webgui](https://github.com/FloatTech/bot-manager)
|
||||
- **qqs**: superusers 的 qq 号
|
||||
|
||||
## 功能
|
||||
> 在编译时,以下功能除插件控制外,均可通过注释`main.go`中的相应`import`而物理禁用,减小插件体积。
|
||||
> 通过插件控制,还可动态管理某个功能在某个群的打开/关闭。
|
||||
- **web管理** `import _ "github.com/FloatTech/ZeroBot-Plugin/control/web"`
|
||||
- 开启后可执行文件大约增加 5M ,默认注释不开启。如需开启请自行编辑`main.go`取消注释
|
||||
- 需要配合 [webgui](https://github.com/FloatTech/bot-manager) 使用
|
||||
- **动态加载插件** `import _ github.com/FloatTech/ZeroBot-Plugin-Dynamic/dyloader`
|
||||
- 本功能需要`cgo`,故已分离出主线。详见[ZeroBot-Plugin-Dynamic](https://github.com/FloatTech/ZeroBot-Plugin-Dynamic)
|
||||
- **插件控制**
|
||||
- [x] /启用 xxx
|
||||
- [x] /禁用 xxx
|
||||
- [x] /启用 xxx (在发送的群/用户启用xxx)
|
||||
- [x] /禁用 xxx (在发送的群/用户禁用xxx)
|
||||
- [x] /全局启用 xxx
|
||||
- [x] /全局禁用 xxx
|
||||
- [x] /还原 xxx (在发送的群/用户还原xxx的开启状态到初始状态)
|
||||
- [x] /用法 xxx
|
||||
- [x] /服务列表
|
||||
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat"`
|
||||
@@ -101,8 +122,11 @@
|
||||
- [x] 设置随机图片网址[url]
|
||||
- [x] 太涩了(撤回最近发的图)
|
||||
- [x] 评价图片(发送一张图片让bot评分)
|
||||
- **浅草寺求签** `github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji`
|
||||
- [x] 求签|运势|占卜
|
||||
- **每日运势** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_fortune`
|
||||
- [x] 运势|抽签
|
||||
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师]
|
||||
- **浅草寺求签** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji`
|
||||
- [x] 求签|占卜
|
||||
- **bilibili** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili"`
|
||||
- [x] >vup info [名字|uid]
|
||||
- [x] >user info [名字|uid]
|
||||
@@ -114,6 +138,7 @@
|
||||
- [x] [回复]查重
|
||||
- **AIfalse** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false"`
|
||||
- [x] 查询计算机当前活跃度 [身体检查]
|
||||
- [x] 清理缓存
|
||||
- [ ] 简易语音
|
||||
- [ ] 爬图合成 [@xxx]
|
||||
- **minecraft** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft"`
|
||||
@@ -133,6 +158,9 @@
|
||||
- [x] ?? [缩写]
|
||||
- **选择困难症帮手** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose"`
|
||||
- [x] 选择[选择项1]还是[选项2]还是[更多选项]
|
||||
- **投胎** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn"`
|
||||
- [x] reborn
|
||||
- 注:本插件来源于[tgbot](https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py)
|
||||
- **TODO...**
|
||||
|
||||
## 使用方法
|
||||
@@ -152,7 +180,7 @@
|
||||
### 本地运行
|
||||
|
||||
1. 下载安装 [Go](https://studygolang.com/dl) 环境
|
||||
2. 下载本项目[压缩包](https://github.com/Yiwen-Chan/ZeroBot-Plugin/archive/master.zip),本地解压
|
||||
2. 下载本项目[压缩包](https://github.com/FloatTech/ZeroBot-Plugin/archive/master.zip),本地解压
|
||||
3. 编辑 main.go 文件,内容按需修改
|
||||
4. 双击 build.bat 文件 或 直接双击 run.bat 文件
|
||||
5. 运行 OneBot 框架,并同时运行本插件
|
||||
@@ -164,7 +192,7 @@
|
||||
1. 点击右上角 Fork 本项目,并转跳到自己 Fork 的仓库
|
||||
2. 点击仓库上方的 Actions 按钮,确认使用 Actions
|
||||
3. 编辑 main.go 文件,内容按需修改
|
||||
4. 前往 Release 页面发布一个 Release,`tag`形如`vx.y.z`,以触发稳定版编译流程
|
||||
4. 前往 Release 页面发布一个 Release,`tag`形如`v1.2.3`,以触发稳定版编译流程
|
||||
5. 点击 Actions 按钮,等待编译完成,回到 Release 页面下载编译好的文件
|
||||
6. 运行 OneBot 框架,并同时运行本插件
|
||||
7. 啾咪~
|
||||
@@ -204,4 +232,4 @@ GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags "-s -w"
|
||||
|
||||
## License
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FYiwen-Chan%2FZeroBot-Plugin?ref=badge_large)
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FFloatTech%2FZeroBot-Plugin?ref=badge_large)
|
||||
|
||||
@@ -4,9 +4,28 @@ import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
)
|
||||
|
||||
var enmap = make(map[string]*zero.Engine)
|
||||
|
||||
// Register 注册插件控制器
|
||||
func Register(service string, o *Options) *zero.Engine {
|
||||
engine := zero.New()
|
||||
engine.UsePreHandler(newctrl(service, o).Handler())
|
||||
enmap[service] = engine
|
||||
return engine
|
||||
}
|
||||
|
||||
// Delete 删除插件控制器,不会删除数据
|
||||
func Delete(service string) {
|
||||
engine, ok := enmap[service]
|
||||
if ok {
|
||||
engine.Delete()
|
||||
mu.RLock()
|
||||
_, ok = managers[service]
|
||||
mu.RUnlock()
|
||||
if ok {
|
||||
mu.Lock()
|
||||
delete(managers, service)
|
||||
mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
168
control/rule.go
168
control/rule.go
@@ -4,6 +4,7 @@ package control
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -11,11 +12,11 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/extension"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/data"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
)
|
||||
|
||||
var (
|
||||
db = &data.Sqlite{DBPath: "data/control/plugins.db"}
|
||||
db = &sql.Sqlite{DBPath: "data/control/plugins.db"}
|
||||
// managers 每个插件对应的管理
|
||||
managers = map[string]*Control{}
|
||||
mu = sync.RWMutex{}
|
||||
@@ -40,8 +41,8 @@ func newctrl(service string, o *Options) *Control {
|
||||
}(),
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
managers[service] = m
|
||||
mu.Unlock()
|
||||
err := db.Create(service, &grpcfg{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -49,41 +50,60 @@ func newctrl(service string, o *Options) *Control {
|
||||
return m
|
||||
}
|
||||
|
||||
// enable enables a group to pass the Manager.
|
||||
func (m *Control) enable(groupID int64) {
|
||||
// Enable enables a group to pass the Manager.
|
||||
// groupID == 0 (ALL) will operate on all grps.
|
||||
func (m *Control) Enable(groupID int64) {
|
||||
m.Lock()
|
||||
err := db.Insert(m.service, &grpcfg{groupID, 0})
|
||||
m.Unlock()
|
||||
if err != nil {
|
||||
logrus.Errorf("[control] %v", err)
|
||||
}
|
||||
m.Unlock()
|
||||
}
|
||||
|
||||
// disable disables a group to pass the Manager.
|
||||
func (m *Control) disable(groupID int64) {
|
||||
// Disable disables a group to pass the Manager.
|
||||
// groupID == 0 (ALL) will operate on all grps.
|
||||
func (m *Control) Disable(groupID int64) {
|
||||
m.Lock()
|
||||
err := db.Insert(m.service, &grpcfg{groupID, 1})
|
||||
m.Unlock()
|
||||
if err != nil {
|
||||
logrus.Errorf("[control] %v", err)
|
||||
}
|
||||
m.Unlock()
|
||||
}
|
||||
|
||||
func (m *Control) isEnabledIn(gid int64) bool {
|
||||
m.RLock()
|
||||
var c grpcfg
|
||||
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10))
|
||||
if err == nil {
|
||||
m.RUnlock()
|
||||
logrus.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable)
|
||||
return c.Disable == 0
|
||||
// Reset resets the default config of a group.
|
||||
// groupID == 0 (ALL) is not allowed.
|
||||
func (m *Control) Reset(groupID int64) {
|
||||
if groupID != 0 {
|
||||
m.Lock()
|
||||
err := db.Del(m.service, "WHERE gid = "+strconv.FormatInt(groupID, 10))
|
||||
m.Unlock()
|
||||
if err != nil {
|
||||
logrus.Errorf("[control] %v", err)
|
||||
}
|
||||
}
|
||||
logrus.Errorf("[control] %v", err)
|
||||
}
|
||||
|
||||
// IsEnabledIn 开启群
|
||||
func (m *Control) IsEnabledIn(gid int64) bool {
|
||||
var c grpcfg
|
||||
var err error
|
||||
if gid != 0 {
|
||||
m.RLock()
|
||||
err = db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10))
|
||||
m.RUnlock()
|
||||
if err == nil {
|
||||
logrus.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable)
|
||||
return c.Disable == 0
|
||||
}
|
||||
}
|
||||
m.RLock()
|
||||
err = db.Find(m.service, &c, "WHERE gid = 0")
|
||||
m.RUnlock()
|
||||
if m.options.DisableOnDefault {
|
||||
m.disable(gid)
|
||||
} else {
|
||||
m.enable(gid)
|
||||
if err == nil {
|
||||
logrus.Debugf("[control] plugin %s of all : %d", m.service, c.GroupID, c.Disable)
|
||||
return c.Disable == 0
|
||||
}
|
||||
return !m.options.DisableOnDefault
|
||||
}
|
||||
@@ -92,21 +112,26 @@ func (m *Control) isEnabledIn(gid int64) bool {
|
||||
func (m *Control) Handler() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
ctx.State["manager"] = m
|
||||
return m.isEnabledIn(ctx.Event.GroupID)
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
// 个人用户
|
||||
grp = -ctx.Event.UserID
|
||||
}
|
||||
return m.IsEnabledIn(grp)
|
||||
}
|
||||
}
|
||||
|
||||
// lookup returns a Manager by the service name, if
|
||||
// Lookup returns a Manager by the service name, if
|
||||
// not exist, it will returns nil.
|
||||
func lookup(service string) (*Control, bool) {
|
||||
func Lookup(service string) (*Control, bool) {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
m, ok := managers[service]
|
||||
mu.RUnlock()
|
||||
return m, ok
|
||||
}
|
||||
|
||||
// forEach iterates through managers.
|
||||
func forEach(iterator func(key string, manager *Control) bool) {
|
||||
// ForEach iterates through managers.
|
||||
func ForEach(iterator func(key string, manager *Control) bool) {
|
||||
mu.RLock()
|
||||
m := copyMap(managers)
|
||||
mu.RUnlock()
|
||||
@@ -134,42 +159,71 @@ func init() {
|
||||
panic(err)
|
||||
} else {
|
||||
hasinit = true
|
||||
zero.OnCommandGroup([]string{"启用", "enable"}, zero.AdminPermission, zero.OnlyGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
service, ok := lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.Send("没有找到指定服务!")
|
||||
}
|
||||
service.enable(ctx.Event.GroupID)
|
||||
ctx.Send(message.Text("已启用服务: " + model.Args))
|
||||
})
|
||||
zero.OnCommandGroup([]string{
|
||||
"启用", "enable", "禁用", "disable",
|
||||
"全局启用", "enableall", "全局禁用", "disableall",
|
||||
}, func(ctx *zero.Ctx) bool {
|
||||
if zero.OnlyGroup(ctx) {
|
||||
return zero.AdminPermission(ctx)
|
||||
}
|
||||
return zero.OnlyToMe(ctx)
|
||||
}).Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
}
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
// 个人用户
|
||||
grp = -ctx.Event.UserID
|
||||
}
|
||||
if strings.Contains(model.Command, "全局") || strings.Contains(model.Command, "all") {
|
||||
grp = 0
|
||||
}
|
||||
if strings.Contains(model.Command, "启用") || strings.Contains(model.Command, "enable") {
|
||||
service.Enable(grp)
|
||||
ctx.SendChain(message.Text("已启用服务: " + model.Args))
|
||||
} else {
|
||||
service.Disable(grp)
|
||||
ctx.SendChain(message.Text("已禁用服务: " + model.Args))
|
||||
}
|
||||
})
|
||||
|
||||
zero.OnCommandGroup([]string{"禁用", "disable"}, zero.AdminPermission, zero.OnlyGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
service, ok := lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.Send("没有找到指定服务!")
|
||||
}
|
||||
service.disable(ctx.Event.GroupID)
|
||||
ctx.Send(message.Text("已关闭服务: " + model.Args))
|
||||
})
|
||||
zero.OnCommandGroup([]string{"还原", "reset"}, func(ctx *zero.Ctx) bool {
|
||||
if zero.OnlyGroup(ctx) {
|
||||
return zero.AdminPermission(ctx)
|
||||
}
|
||||
return zero.OnlyToMe(ctx)
|
||||
}).Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
}
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
// 个人用户
|
||||
grp = -ctx.Event.UserID
|
||||
}
|
||||
service.Reset(grp)
|
||||
ctx.SendChain(message.Text("已还原服务的默认启用状态: " + model.Args))
|
||||
})
|
||||
|
||||
zero.OnCommandGroup([]string{"用法", "usage"}, zero.AdminPermission, zero.OnlyGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
service, ok := lookup(model.Args)
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.Send("没有找到指定服务!")
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
}
|
||||
if service.options.Help != "" {
|
||||
ctx.Send(service.options.Help)
|
||||
ctx.SendChain(message.Text(service.options.Help))
|
||||
} else {
|
||||
ctx.Send("该服务无帮助!")
|
||||
ctx.SendChain(message.Text("该服务无帮助!"))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -177,17 +231,17 @@ func init() {
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := `---服务列表---`
|
||||
i := 0
|
||||
forEach(func(key string, manager *Control) bool {
|
||||
ForEach(func(key string, manager *Control) bool {
|
||||
i++
|
||||
msg += "\n" + strconv.Itoa(i) + `: `
|
||||
if manager.isEnabledIn(ctx.Event.GroupID) {
|
||||
if manager.IsEnabledIn(ctx.Event.GroupID) {
|
||||
msg += "●" + key
|
||||
} else {
|
||||
msg += "○" + key
|
||||
}
|
||||
return true
|
||||
})
|
||||
ctx.Send(message.Text(msg))
|
||||
ctx.SendChain(message.Text(msg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package control
|
||||
package web
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -34,8 +36,8 @@ var (
|
||||
type logWriter struct {
|
||||
}
|
||||
|
||||
// InitGui 初始化gui
|
||||
func InitGui() {
|
||||
// initGui 初始化gui
|
||||
func initGui() {
|
||||
// 将日志重定向到前端hook
|
||||
writer := io.MultiWriter(l, os.Stderr)
|
||||
log.SetOutput(writer)
|
||||
@@ -61,11 +63,6 @@ func controller() {
|
||||
}
|
||||
}()
|
||||
|
||||
if log.GetLevel() != log.DebugLevel {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
gin.DefaultWriter = io.Discard
|
||||
}
|
||||
|
||||
engine := gin.New()
|
||||
// 支持跨域
|
||||
engine.Use(cors())
|
||||
@@ -91,8 +88,8 @@ func controller() {
|
||||
// 获取插件列表
|
||||
engine.POST("/get_plugins", func(context *gin.Context) {
|
||||
var datas []map[string]interface{}
|
||||
forEach(func(key string, manager *Control) bool {
|
||||
datas = append(datas, map[string]interface{}{"id": 1, "handle_type": "", "name": key, "enable": manager.isEnabledIn(0)})
|
||||
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
|
||||
datas = append(datas, map[string]interface{}{"id": 1, "handle_type": "", "name": key, "enable": manager.IsEnabledIn(0)})
|
||||
return true
|
||||
})
|
||||
context.JSON(200, datas)
|
||||
@@ -139,14 +136,14 @@ func updateAllPluginStatus(context *gin.Context) {
|
||||
return true
|
||||
})
|
||||
|
||||
forEach(func(key string, manager *Control) bool {
|
||||
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
|
||||
if enable {
|
||||
for _, group := range groups {
|
||||
manager.enable(group)
|
||||
manager.Enable(group)
|
||||
}
|
||||
} else {
|
||||
for _, group := range groups {
|
||||
manager.disable(group)
|
||||
manager.Disable(group)
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -173,7 +170,7 @@ func updatePluginAllGroupStatus(context *gin.Context) {
|
||||
name = parse["name"].(string)
|
||||
enable = parse["enable"].(bool)
|
||||
}
|
||||
control, b := lookup(name)
|
||||
control, b := ctrl.Lookup(name)
|
||||
if !b {
|
||||
context.JSON(404, nil)
|
||||
return
|
||||
@@ -181,9 +178,9 @@ func updatePluginAllGroupStatus(context *gin.Context) {
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
|
||||
for _, group := range ctx.GetGroupList().Array() {
|
||||
if enable {
|
||||
control.enable(group.Get("group_id").Int())
|
||||
control.Enable(group.Get("group_id").Int())
|
||||
} else {
|
||||
control.disable(group.Get("group_id").Int())
|
||||
control.Disable(group.Get("group_id").Int())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,15 +207,15 @@ func updatePluginStatus(context *gin.Context) {
|
||||
name := parse["name"].(string)
|
||||
enable := parse["enable"].(bool)
|
||||
fmt.Println(name)
|
||||
control, b := lookup(name)
|
||||
control, b := ctrl.Lookup(name)
|
||||
if !b {
|
||||
context.JSON(404, "服务不存在")
|
||||
return
|
||||
}
|
||||
if enable {
|
||||
control.enable(groupID)
|
||||
control.Enable(groupID)
|
||||
} else {
|
||||
control.disable(groupID)
|
||||
control.Disable(groupID)
|
||||
}
|
||||
context.JSON(200, nil)
|
||||
}
|
||||
@@ -242,12 +239,12 @@ func getPluginStatus(context *gin.Context) {
|
||||
groupID = int64(parse["group_id"].(float64))
|
||||
name = parse["name"].(string)
|
||||
}
|
||||
control, b := lookup(name)
|
||||
control, b := ctrl.Lookup(name)
|
||||
if !b {
|
||||
context.JSON(404, "服务不存在")
|
||||
return
|
||||
}
|
||||
context.JSON(200, gin.H{"enable": control.isEnabledIn(groupID)})
|
||||
context.JSON(200, gin.H{"enable": control.IsEnabledIn(groupID)})
|
||||
}
|
||||
|
||||
// getPluginsStatus
|
||||
@@ -268,8 +265,8 @@ func getPluginsStatus(context *gin.Context) {
|
||||
groupID = int64(parse["group_id"].(float64))
|
||||
}
|
||||
var datas []map[string]interface{}
|
||||
forEach(func(key string, manager *Control) bool {
|
||||
enable := manager.isEnabledIn(groupID)
|
||||
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
|
||||
enable := manager.IsEnabledIn(groupID)
|
||||
datas = append(datas, map[string]interface{}{"name": key, "enable": enable})
|
||||
return true
|
||||
})
|
||||
11
control/web/init.go
Normal file
11
control/web/init.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Package web 网页管理后端
|
||||
package web
|
||||
|
||||
import "flag"
|
||||
|
||||
func init() {
|
||||
// 解析命令行参数,输入 `-g` 即可启用 gui
|
||||
if *flag.Bool("g", false, "Enable web gui.") {
|
||||
initGui()
|
||||
}
|
||||
}
|
||||
906
data/Reborn/rate.json
Normal file
906
data/Reborn/rate.json
Normal file
@@ -0,0 +1,906 @@
|
||||
[
|
||||
{
|
||||
"name": "印度",
|
||||
"weight": 0.179369185
|
||||
},
|
||||
{
|
||||
"weight": 0.116660088,
|
||||
"name": "中华人民共和国"
|
||||
},
|
||||
{
|
||||
"name": "尼日利亚",
|
||||
"weight": 0.052104876
|
||||
},
|
||||
{
|
||||
"weight": 0.04490831,
|
||||
"name": "巴基斯坦"
|
||||
},
|
||||
{
|
||||
"weight": 0.029767875,
|
||||
"name": "印尼"
|
||||
},
|
||||
{
|
||||
"weight": 0.02917347,
|
||||
"name": "美国"
|
||||
},
|
||||
{
|
||||
"name": "刚果民主共和国",
|
||||
"weight": 0.026980482
|
||||
},
|
||||
{
|
||||
"weight": 0.02653533,
|
||||
"name": "埃塞俄比亚"
|
||||
},
|
||||
{
|
||||
"name": "孟加拉国",
|
||||
"weight": 0.022001723
|
||||
},
|
||||
{
|
||||
"name": "巴西",
|
||||
"weight": 0.020641351
|
||||
},
|
||||
{
|
||||
"name": "埃及",
|
||||
"weight": 0.019722924
|
||||
},
|
||||
{
|
||||
"name": "菲律宾",
|
||||
"weight": 0.017944256
|
||||
},
|
||||
{
|
||||
"name": "墨西哥",
|
||||
"weight": 0.015798468
|
||||
},
|
||||
{
|
||||
"weight": 0.015156998,
|
||||
"name": "坦桑尼亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.013686862,
|
||||
"name": "乌干达"
|
||||
},
|
||||
{
|
||||
"weight": 0.010405389,
|
||||
"name": "俄罗斯"
|
||||
},
|
||||
{
|
||||
"weight": 0.010217107,
|
||||
"name": "苏丹"
|
||||
},
|
||||
{
|
||||
"weight": 0.010079201,
|
||||
"name": "越南"
|
||||
},
|
||||
{
|
||||
"name": "阿富汗",
|
||||
"weight": 0.009796745
|
||||
},
|
||||
{
|
||||
"name": "伊朗",
|
||||
"weight": 0.009789926
|
||||
},
|
||||
{
|
||||
"name": "肯尼亚",
|
||||
"weight": 0.009216044
|
||||
},
|
||||
{
|
||||
"weight": 0.008870993,
|
||||
"name": "安哥拉"
|
||||
},
|
||||
{
|
||||
"name": "土耳其",
|
||||
"weight": 0.008815318
|
||||
},
|
||||
{
|
||||
"weight": 0.008267509,
|
||||
"name": "莫桑比克"
|
||||
},
|
||||
{
|
||||
"name": "南非",
|
||||
"weight": 0.007826801
|
||||
},
|
||||
{
|
||||
"weight": 0.00755071,
|
||||
"name": "尼日尔"
|
||||
},
|
||||
{
|
||||
"name": "伊拉克",
|
||||
"weight": 0.007350484
|
||||
},
|
||||
{
|
||||
"name": "喀麦隆",
|
||||
"weight": 0.006786572
|
||||
},
|
||||
{
|
||||
"weight": 0.006782117,
|
||||
"name": "缅甸"
|
||||
},
|
||||
{
|
||||
"name": "日本",
|
||||
"weight": 0.006518972
|
||||
},
|
||||
{
|
||||
"weight": 0.006384764,
|
||||
"name": "加纳"
|
||||
},
|
||||
{
|
||||
"weight": 0.006183538,
|
||||
"name": "阿尔及利亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.006075416,
|
||||
"name": "马里"
|
||||
},
|
||||
{
|
||||
"name": "法国",
|
||||
"weight": 0.00571344
|
||||
},
|
||||
{
|
||||
"name": "英国",
|
||||
"weight": 0.005662409
|
||||
},
|
||||
{
|
||||
"name": "马达加斯加",
|
||||
"weight": 0.00559132
|
||||
},
|
||||
{
|
||||
"weight": 0.005562893,
|
||||
"name": "也门"
|
||||
},
|
||||
{
|
||||
"name": "哥伦比亚",
|
||||
"weight": 0.005525953
|
||||
},
|
||||
{
|
||||
"name": "布基纳法索",
|
||||
"weight": 0.005378297
|
||||
},
|
||||
{
|
||||
"name": "科特迪瓦",
|
||||
"weight": 0.005352997
|
||||
},
|
||||
{
|
||||
"name": "阿根廷",
|
||||
"weight": 0.005171935
|
||||
},
|
||||
{
|
||||
"name": "赞比亚",
|
||||
"weight": 0.005147159
|
||||
},
|
||||
{
|
||||
"name": "德国",
|
||||
"weight": 0.005096501
|
||||
},
|
||||
{
|
||||
"weight": 0.005067552,
|
||||
"name": "泰国"
|
||||
},
|
||||
{
|
||||
"name": "马拉维",
|
||||
"weight": 0.005017242
|
||||
},
|
||||
{
|
||||
"name": "乍得",
|
||||
"weight": 0.004825619
|
||||
},
|
||||
{
|
||||
"name": "摩洛哥",
|
||||
"weight": 0.004571552
|
||||
},
|
||||
{
|
||||
"weight": 0.004266592,
|
||||
"name": "马来西亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.004130712,
|
||||
"name": "南苏丹"
|
||||
},
|
||||
{
|
||||
"name": "委内瑞拉",
|
||||
"weight": 0.00410843
|
||||
},
|
||||
{
|
||||
"weight": 0.003903682,
|
||||
"name": "乌兹别克斯坦"
|
||||
},
|
||||
{
|
||||
"weight": 0.003891083,
|
||||
"name": "秘鲁"
|
||||
},
|
||||
{
|
||||
"weight": 0.003854943,
|
||||
"name": "尼泊尔"
|
||||
},
|
||||
{
|
||||
"name": "沙特阿拉伯",
|
||||
"weight": 0.003683713
|
||||
},
|
||||
{
|
||||
"name": "塞内加尔",
|
||||
"weight": 0.003671814
|
||||
},
|
||||
{
|
||||
"name": "津巴布韦",
|
||||
"weight": 0.003628572
|
||||
},
|
||||
{
|
||||
"name": "意大利",
|
||||
"weight": 0.003591173
|
||||
},
|
||||
{
|
||||
"weight": 0.003564036,
|
||||
"name": "贝宁"
|
||||
},
|
||||
{
|
||||
"weight": 0.003318383,
|
||||
"name": "索马里"
|
||||
},
|
||||
{
|
||||
"name": "几内亚",
|
||||
"weight": 0.003229938
|
||||
},
|
||||
{
|
||||
"name": "韩国",
|
||||
"weight": 0.00302709
|
||||
},
|
||||
{
|
||||
"name": "危地马拉",
|
||||
"weight": 0.002989448
|
||||
},
|
||||
{
|
||||
"weight": 0.002933277,
|
||||
"name": "西班牙"
|
||||
},
|
||||
{
|
||||
"name": "布隆迪",
|
||||
"weight": 0.002916273
|
||||
},
|
||||
{
|
||||
"name": "乌克兰",
|
||||
"weight": 0.002865519
|
||||
},
|
||||
{
|
||||
"name": "叙利亚",
|
||||
"weight": 0.002803866
|
||||
},
|
||||
{
|
||||
"name": "加拿大",
|
||||
"weight": 0.002769376
|
||||
},
|
||||
{
|
||||
"name": "朝鲜",
|
||||
"weight": 0.002663995
|
||||
},
|
||||
{
|
||||
"name": "柬埔寨",
|
||||
"weight": 0.002507218
|
||||
},
|
||||
{
|
||||
"weight": 0.002459301,
|
||||
"name": "卢旺达"
|
||||
},
|
||||
{
|
||||
"weight": 0.002433661,
|
||||
"name": "波兰"
|
||||
},
|
||||
{
|
||||
"weight": 0.002264484,
|
||||
"name": "澳大利亚"
|
||||
},
|
||||
{
|
||||
"name": "斯里兰卡",
|
||||
"weight": 0.002205474
|
||||
},
|
||||
{
|
||||
"weight": 0.00217928,
|
||||
"name": "哈萨克斯坦"
|
||||
},
|
||||
{
|
||||
"name": "厄瓜多尔",
|
||||
"weight": 0.002114416
|
||||
},
|
||||
{
|
||||
"name": "塞拉利昂",
|
||||
"weight": 0.002042686
|
||||
},
|
||||
{
|
||||
"name": "海地",
|
||||
"weight": 0.001815248
|
||||
},
|
||||
{
|
||||
"name": "智利",
|
||||
"weight": 0.001761297
|
||||
},
|
||||
{
|
||||
"name": "多哥",
|
||||
"weight": 0.001756614
|
||||
},
|
||||
{
|
||||
"name": "约旦",
|
||||
"weight": 0.001738363
|
||||
},
|
||||
{
|
||||
"weight": 0.001716995,
|
||||
"name": "玻利维亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.001432103,
|
||||
"name": "巴布亚新几内亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.001424043,
|
||||
"name": "塔吉克斯坦"
|
||||
},
|
||||
{
|
||||
"name": "多米尼加",
|
||||
"weight": 0.001376899
|
||||
},
|
||||
{
|
||||
"name": "荷兰",
|
||||
"weight": 0.001365722
|
||||
},
|
||||
{
|
||||
"name": "罗马尼亚",
|
||||
"weight": 0.001342703
|
||||
},
|
||||
{
|
||||
"weight": 0.001340039,
|
||||
"name": "台湾"
|
||||
},
|
||||
{
|
||||
"name": "突尼斯",
|
||||
"weight": 0.001327688
|
||||
},
|
||||
{
|
||||
"name": "中非",
|
||||
"weight": 0.001269639
|
||||
},
|
||||
{
|
||||
"name": "洪都拉斯",
|
||||
"weight": 0.001219191
|
||||
},
|
||||
{
|
||||
"name": "刚果共和国",
|
||||
"weight": 0.001209073
|
||||
},
|
||||
{
|
||||
"weight": 0.001189154,
|
||||
"name": "利比里亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.001150376,
|
||||
"name": "以色列"
|
||||
},
|
||||
{
|
||||
"weight": 0.001149654,
|
||||
"name": "厄立特里亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.001119049,
|
||||
"name": "老挝"
|
||||
},
|
||||
{
|
||||
"name": "阿塞拜疆",
|
||||
"weight": 0.001039837
|
||||
},
|
||||
{
|
||||
"name": "利比亚",
|
||||
"weight": 0.001029222
|
||||
},
|
||||
{
|
||||
"name": "巴勒斯坦",
|
||||
"weight": 0.000992651
|
||||
},
|
||||
{
|
||||
"name": "吉尔吉斯斯坦",
|
||||
"weight": 0.000957294
|
||||
},
|
||||
{
|
||||
"weight": 0.000907425,
|
||||
"name": "比利时"
|
||||
},
|
||||
{
|
||||
"name": "瑞典",
|
||||
"weight": 0.000890654
|
||||
},
|
||||
{
|
||||
"name": "巴拉圭",
|
||||
"weight": 0.00085764
|
||||
},
|
||||
{
|
||||
"name": "毛里塔尼亚",
|
||||
"weight": 0.000842302
|
||||
},
|
||||
{
|
||||
"weight": 0.000830493,
|
||||
"name": "古巴"
|
||||
},
|
||||
{
|
||||
"name": "萨尔瓦多",
|
||||
"weight": 0.000822881
|
||||
},
|
||||
{
|
||||
"name": "尼加拉瓜",
|
||||
"weight": 0.000782782
|
||||
},
|
||||
{
|
||||
"weight": 0.000764766,
|
||||
"name": "阿曼"
|
||||
},
|
||||
{
|
||||
"name": "黎巴嫩",
|
||||
"weight": 0.000751395
|
||||
},
|
||||
{
|
||||
"name": "土库曼斯坦",
|
||||
"weight": 0.000743841
|
||||
},
|
||||
{
|
||||
"weight": 0.000680867,
|
||||
"name": "阿联酋"
|
||||
},
|
||||
{
|
||||
"weight": 0.000677997,
|
||||
"name": "捷克"
|
||||
},
|
||||
{
|
||||
"weight": 0.000643037,
|
||||
"name": "白俄罗斯"
|
||||
},
|
||||
{
|
||||
"weight": 0.000642255,
|
||||
"name": "瑞士"
|
||||
},
|
||||
{
|
||||
"name": "匈牙利",
|
||||
"weight": 0.000612393
|
||||
},
|
||||
{
|
||||
"name": "奥地利",
|
||||
"weight": 0.000602473
|
||||
},
|
||||
{
|
||||
"name": "希腊",
|
||||
"weight": 0.000595922
|
||||
},
|
||||
{
|
||||
"weight": 0.000592992,
|
||||
"name": "葡萄牙"
|
||||
},
|
||||
{
|
||||
"weight": 0.000566764,
|
||||
"name": "科威特"
|
||||
},
|
||||
{
|
||||
"weight": 0.000538867,
|
||||
"name": "哥斯达黎加"
|
||||
},
|
||||
{
|
||||
"name": "巴拿马",
|
||||
"weight": 0.000513904
|
||||
},
|
||||
{
|
||||
"name": "挪威",
|
||||
"weight": 0.000466485
|
||||
},
|
||||
{
|
||||
"name": "丹麦",
|
||||
"weight": 0.000460789
|
||||
},
|
||||
{
|
||||
"name": "爱尔兰",
|
||||
"weight": 0.000455762
|
||||
},
|
||||
{
|
||||
"name": "新西兰",
|
||||
"weight": 0.000451486
|
||||
},
|
||||
{
|
||||
"name": "纳米比亚",
|
||||
"weight": 0.000450165
|
||||
},
|
||||
{
|
||||
"name": "香港",
|
||||
"weight": 0.000448826
|
||||
},
|
||||
{
|
||||
"weight": 0.000441931,
|
||||
"name": "冈比亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.000436542,
|
||||
"name": "塞尔维亚"
|
||||
},
|
||||
{
|
||||
"name": "芬兰",
|
||||
"weight": 0.000417327
|
||||
},
|
||||
{
|
||||
"weight": 0.00041658,
|
||||
"name": "几内亚比绍"
|
||||
},
|
||||
{
|
||||
"weight": 0.000410456,
|
||||
"name": "保加利亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.000382945,
|
||||
"name": "蒙古"
|
||||
},
|
||||
{
|
||||
"name": "莱索托",
|
||||
"weight": 0.00037228
|
||||
},
|
||||
{
|
||||
"weight": 0.000361607,
|
||||
"name": "新加坡"
|
||||
},
|
||||
{
|
||||
"name": "斯洛伐克",
|
||||
"weight": 0.000361482
|
||||
},
|
||||
{
|
||||
"weight": 0.00035722,
|
||||
"name": "加蓬"
|
||||
},
|
||||
{
|
||||
"name": "博茨瓦纳",
|
||||
"weight": 0.000348221
|
||||
},
|
||||
{
|
||||
"weight": 0.000323338,
|
||||
"name": "乌拉圭"
|
||||
},
|
||||
{
|
||||
"name": "赤道几内亚",
|
||||
"weight": 0.000318155
|
||||
},
|
||||
{
|
||||
"name": "东帝汶",
|
||||
"weight": 0.000316195
|
||||
},
|
||||
{
|
||||
"name": "牙买加",
|
||||
"weight": 0.000312724
|
||||
},
|
||||
{
|
||||
"name": "格鲁吉亚",
|
||||
"weight": 0.000307685
|
||||
},
|
||||
{
|
||||
"weight": 0.000265076,
|
||||
"name": "阿尔巴尼亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.000252622,
|
||||
"name": "克罗地亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.000250708,
|
||||
"name": "亚美尼亚"
|
||||
},
|
||||
{
|
||||
"name": "波黑",
|
||||
"weight": 0.000232069
|
||||
},
|
||||
{
|
||||
"name": "摩尔多瓦",
|
||||
"weight": 0.000204405
|
||||
},
|
||||
{
|
||||
"name": "科索沃",
|
||||
"weight": 0.000196993
|
||||
},
|
||||
{
|
||||
"weight": 0.000189047,
|
||||
"name": "立陶宛"
|
||||
},
|
||||
{
|
||||
"weight": 0.000182006,
|
||||
"name": "卡塔尔"
|
||||
},
|
||||
{
|
||||
"name": "波多黎各",
|
||||
"weight": 0.000182004
|
||||
},
|
||||
{
|
||||
"name": "吉布提",
|
||||
"weight": 0.000174383
|
||||
},
|
||||
{
|
||||
"name": "北马其顿",
|
||||
"weight": 0.000158321
|
||||
},
|
||||
{
|
||||
"weight": 0.000146886,
|
||||
"name": "科摩罗"
|
||||
},
|
||||
{
|
||||
"weight": 0.000144027,
|
||||
"name": "巴林"
|
||||
},
|
||||
{
|
||||
"weight": 0.000129782,
|
||||
"name": "斯洛文尼亚"
|
||||
},
|
||||
{
|
||||
"weight": 0.000126232,
|
||||
"name": "西撒哈拉"
|
||||
},
|
||||
{
|
||||
"name": "拉脱维亚",
|
||||
"weight": 0.000124966
|
||||
},
|
||||
{
|
||||
"name": "所罗门群岛",
|
||||
"weight": 0.000120169
|
||||
},
|
||||
{
|
||||
"name": "斐济",
|
||||
"weight": 0.000110985
|
||||
},
|
||||
{
|
||||
"weight": 0.000110769,
|
||||
"name": "特立尼达和多巴哥"
|
||||
},
|
||||
{
|
||||
"weight": 0.000109656,
|
||||
"name": "毛里求斯"
|
||||
},
|
||||
{
|
||||
"weight": 8.8e-5,
|
||||
"name": "爱沙尼亚"
|
||||
},
|
||||
{
|
||||
"weight": 8.61e-5,
|
||||
"name": "圭亚那"
|
||||
},
|
||||
{
|
||||
"name": "不丹",
|
||||
"weight": 8.61e-5
|
||||
},
|
||||
{
|
||||
"weight": 7.49e-5,
|
||||
"name": "佛得角"
|
||||
},
|
||||
{
|
||||
"name": "塞浦路斯",
|
||||
"weight": 6.8e-5
|
||||
},
|
||||
{
|
||||
"name": "伯利兹",
|
||||
"weight": 6.4e-5
|
||||
},
|
||||
{
|
||||
"weight": 6.01e-5,
|
||||
"name": "苏里南"
|
||||
},
|
||||
{
|
||||
"name": "文莱",
|
||||
"weight": 5.2e-5
|
||||
},
|
||||
{
|
||||
"weight": 5.1e-5,
|
||||
"name": "黑山"
|
||||
},
|
||||
{
|
||||
"name": "瓦努阿图",
|
||||
"weight": 5.1e-5
|
||||
},
|
||||
{
|
||||
"name": "卢森堡",
|
||||
"weight": 5.07e-5
|
||||
},
|
||||
{
|
||||
"name": "马尔代夫",
|
||||
"weight": 4.27e-5
|
||||
},
|
||||
{
|
||||
"name": "巴哈马",
|
||||
"weight": 4.06e-5
|
||||
},
|
||||
{
|
||||
"weight": 3.82e-5,
|
||||
"name": "澳门"
|
||||
},
|
||||
{
|
||||
"weight": 3.48e-5,
|
||||
"name": "马耳他"
|
||||
},
|
||||
{
|
||||
"name": "冰岛",
|
||||
"weight": 3.45e-5
|
||||
},
|
||||
{
|
||||
"weight": 3.03e-5,
|
||||
"name": "新喀里多尼亚"
|
||||
},
|
||||
{
|
||||
"name": "萨摩亚",
|
||||
"weight": 2.83e-5
|
||||
},
|
||||
{
|
||||
"weight": 2.8e-5,
|
||||
"name": "法属波利尼西亚"
|
||||
},
|
||||
{
|
||||
"name": "关岛",
|
||||
"weight": 2.36e-5
|
||||
},
|
||||
{
|
||||
"weight": 2.32e-5,
|
||||
"name": "巴巴多斯"
|
||||
},
|
||||
{
|
||||
"name": "基里巴斯",
|
||||
"weight": 1.83e-5
|
||||
},
|
||||
{
|
||||
"weight": 1.71e-5,
|
||||
"name": "圣卢西亚"
|
||||
},
|
||||
{
|
||||
"name": "库拉索",
|
||||
"weight": 1.51e-5
|
||||
},
|
||||
{
|
||||
"weight": 1.5e-5,
|
||||
"name": "汤加"
|
||||
},
|
||||
{
|
||||
"weight": 1.42e-5,
|
||||
"name": "密克罗尼西亚联邦"
|
||||
},
|
||||
{
|
||||
"weight": 1.13e-5,
|
||||
"name": "格林纳达"
|
||||
},
|
||||
{
|
||||
"name": "安提瓜和巴布达",
|
||||
"weight": 1.05e-5
|
||||
},
|
||||
{
|
||||
"weight": 9.93e-6,
|
||||
"name": "圣文森特和格林纳丁斯"
|
||||
},
|
||||
{
|
||||
"name": "泽西",
|
||||
"weight": 9.66e-6
|
||||
},
|
||||
{
|
||||
"weight": 9.64e-6,
|
||||
"name": "阿鲁巴"
|
||||
},
|
||||
{
|
||||
"weight": 9.15e-6,
|
||||
"name": "美属维尔京群岛"
|
||||
},
|
||||
{
|
||||
"weight": 9.08e-6,
|
||||
"name": "马绍尔群岛"
|
||||
},
|
||||
{
|
||||
"weight": 8.9e-6,
|
||||
"name": "塞舌尔"
|
||||
},
|
||||
{
|
||||
"name": "美属萨摩亚",
|
||||
"weight": 7.97e-6
|
||||
},
|
||||
{
|
||||
"name": "多米尼克",
|
||||
"weight": 7.57e-6
|
||||
},
|
||||
{
|
||||
"weight": 6.41e-6,
|
||||
"name": "马恩岛"
|
||||
},
|
||||
{
|
||||
"weight": 6.09e-6,
|
||||
"name": "北马里亚纳群岛"
|
||||
},
|
||||
{
|
||||
"name": "开曼群岛",
|
||||
"weight": 5.77e-6
|
||||
},
|
||||
{
|
||||
"name": "格陵兰",
|
||||
"weight": 5.63e-6
|
||||
},
|
||||
{
|
||||
"weight": 5.54e-6,
|
||||
"name": "法罗群岛"
|
||||
},
|
||||
{
|
||||
"weight": 5.17e-6,
|
||||
"name": "圣基茨和尼维斯"
|
||||
},
|
||||
{
|
||||
"weight": 5.11e-6,
|
||||
"name": "百慕大"
|
||||
},
|
||||
{
|
||||
"weight": 4.38e-6,
|
||||
"name": "根西"
|
||||
},
|
||||
{
|
||||
"weight": 4.31e-6,
|
||||
"name": "特克斯和凯科斯群岛"
|
||||
},
|
||||
{
|
||||
"name": "荷属圣马丁",
|
||||
"weight": 4.14e-6
|
||||
},
|
||||
{
|
||||
"weight": 3.87e-6,
|
||||
"name": "安道尔"
|
||||
},
|
||||
{
|
||||
"name": "法国(法属圣马丁)",
|
||||
"weight": 3.6e-6
|
||||
},
|
||||
{
|
||||
"name": "直布罗陀",
|
||||
"weight": 3.2e-6
|
||||
},
|
||||
{
|
||||
"weight": 2.87e-6,
|
||||
"name": "列支敦士登"
|
||||
},
|
||||
{
|
||||
"name": "英属维尔京群岛",
|
||||
"weight": 2.57e-6
|
||||
},
|
||||
{
|
||||
"weight": 2.1e-6,
|
||||
"name": "圣马力诺"
|
||||
},
|
||||
{
|
||||
"weight": 1.75e-6,
|
||||
"name": "瑙鲁"
|
||||
},
|
||||
{
|
||||
"name": "摩纳哥",
|
||||
"weight": 1.75e-6
|
||||
},
|
||||
{
|
||||
"name": "图瓦卢",
|
||||
"weight": 1.72e-6
|
||||
},
|
||||
{
|
||||
"name": "库克群岛",
|
||||
"weight": 1.44e-6
|
||||
},
|
||||
{
|
||||
"name": "帕劳",
|
||||
"weight": 1.44e-6
|
||||
},
|
||||
{
|
||||
"weight": 1.41e-6,
|
||||
"name": "安圭拉"
|
||||
},
|
||||
{
|
||||
"weight": 1.05e-6,
|
||||
"name": "法国(瓦利斯和富图纳)"
|
||||
},
|
||||
{
|
||||
"weight": 6.6e-7,
|
||||
"name": "法国(圣巴泰勒米)"
|
||||
},
|
||||
{
|
||||
"name": "蒙特塞拉特",
|
||||
"weight": 4.35e-7
|
||||
},
|
||||
{
|
||||
"weight": 3.77e-7,
|
||||
"name": "圣赫勒拿、阿森松和特里斯坦-达库尼亚"
|
||||
},
|
||||
{
|
||||
"name": "法国(圣皮埃尔和密克隆)",
|
||||
"weight": 2.86e-7
|
||||
},
|
||||
{
|
||||
"name": "福克兰群岛",
|
||||
"weight": 2.48e-7
|
||||
}
|
||||
]
|
||||
14
go.mod
14
go.mod
@@ -3,18 +3,20 @@ module github.com/FloatTech/ZeroBot-Plugin
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/FloatTech/AnimeAPI v1.1.9
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.1.5
|
||||
github.com/FloatTech/AnimeAPI v1.1.10
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.4.3
|
||||
github.com/FloatTech/bot-manager v1.0.0
|
||||
github.com/fogleman/gg v1.3.0
|
||||
github.com/gin-gonic/gin v1.7.4
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/imroc/req v0.3.0
|
||||
github.com/mroth/weightedrand v0.4.1
|
||||
github.com/robfig/cron v1.2.0
|
||||
github.com/shirou/gopsutil v3.21.8+incompatible
|
||||
github.com/shirou/gopsutil v3.21.9+incompatible
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/tidwall/gjson v1.9.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.4
|
||||
modernc.org/sqlite v1.13.0
|
||||
github.com/tidwall/gjson v1.10.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.3.2
|
||||
modernc.org/sqlite v1.13.1
|
||||
)
|
||||
|
||||
27
go.sum
27
go.sum
@@ -1,8 +1,9 @@
|
||||
github.com/FloatTech/AnimeAPI v1.1.9 h1:H1hZmgwZPNHdx39K9JvY3awT8TTsCl9kKA1uVMyCjRg=
|
||||
github.com/FloatTech/AnimeAPI v1.1.9/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
|
||||
github.com/FloatTech/AnimeAPI v1.1.10 h1:fYkv65P1HBukHi3GpzYulGx/xLshEL9635QXALDryf0=
|
||||
github.com/FloatTech/AnimeAPI v1.1.10/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
|
||||
github.com/FloatTech/ZeroBot-Plugin v1.1.5/go.mod h1:kWuUARvU7gs4xLggi8Sy37ja2GRL6k0X6kewe5TiZRs=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.1.5 h1:SighsMMD7s0cB4r5ya/7B8sOLQ6W1wY2xhgwFc1fO3c=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.1.5/go.mod h1:W7ag6hml1pZTNzRXKU74OMr6rS8awQKSU+o2g7Gj4O0=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4 h1:WW0BmmLLqAg+m6qGkrKbsfSIm91fkj3/udt3R7Myodo=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4/go.mod h1:W7ag6hml1pZTNzRXKU74OMr6rS8awQKSU+o2g7Gj4O0=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.4.3 h1:jn/dH+OwPSRozkmeCeQQPrAGJRBudcm3OK5tXhGItRk=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.4.3/go.mod h1:MVOQQ4e6AVGFm993blXXU4Sd6bAsLY2+Zb+/HMrEeEc=
|
||||
github.com/FloatTech/bot-manager v1.0.0 h1:d63J5htLhVBc2ITG09WBJI+qAB0ubPjYhfXl6hljBNk=
|
||||
@@ -77,6 +78,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b h1:6Xjqolv/0DDdUqlpnsTomXQvjvvkz7Ux7TcMALvozEw=
|
||||
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
|
||||
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
@@ -86,8 +89,9 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
||||
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU=
|
||||
github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil v3.21.9+incompatible h1:LTLpUnfX81MkHeCtSrwNKZwuW5Id6kCa7/P43NdcNn4=
|
||||
github.com/shirou/gopsutil v3.21.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
@@ -103,12 +107,15 @@ github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go
|
||||
github.com/tdf1939/ZeroBot-Plugin-Gif v0.0.0-20210828060956-389b1dc33652/go.mod h1:bkxKi7un9gCDvUUZAiIJF6k90pyj8rmxiXLJkiHcsMY=
|
||||
github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3/go.mod h1:FgTEOcosTWrkOr7++gbtPSj1rX5loRWrf/AL+hm3Cnw=
|
||||
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/gjson v1.9.0 h1:+Od7AE26jAaMgVC31cQV/Ope5iKXulNMflrlB7k+F9E=
|
||||
github.com/tidwall/gjson v1.9.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
||||
github.com/tidwall/gjson v1.10.0 h1:FcpcxUhNwjb4ppKSlz5Bv8V1jc9ncrVAySohlNBrPUk=
|
||||
github.com/tidwall/gjson v1.10.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
@@ -119,8 +126,9 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.2/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.3/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.4 h1:eC/41Tlkj1jxXW91x4K+qjUlaQXKGgUeLhxw7C6+qkM=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.4/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
|
||||
github.com/wdvxdr1123/ZeroBot v1.3.2 h1:EFZNb3awNbwxRtmDkWv3PH6Z9rUV6ZLFa3hBmRMRRCA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.3.2/go.mod h1:i2DIqQjtjE+3gvVi9r9sc+QpNaUuyTXx/HNXXayIpwI=
|
||||
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=
|
||||
@@ -211,8 +219,9 @@ modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
|
||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.13.0 h1:cwhUj0jTBgPjk/demWheV+T6xi6ifTfsGIFKFq0g3Ck=
|
||||
modernc.org/sqlite v1.13.0/go.mod h1:2qO/6jZJrcQaxFUHxOwa6Q6WfiGSsiVj6GXX0Ker+Jg=
|
||||
modernc.org/sqlite v1.13.1 h1:s/qk6VTTVyQIyhVNWa50whBBcI3+2oREbx85t227iOo=
|
||||
modernc.org/sqlite v1.13.1/go.mod h1:2qO/6jZJrcQaxFUHxOwa6Q6WfiGSsiVj6GXX0Ker+Jg=
|
||||
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/tcl v1.5.9 h1:DZMfR+RDJRhcrmMEMTJgVIX+Wf5qhfVX0llI0rsc20w=
|
||||
|
||||
70
main.go
70
main.go
@@ -8,6 +8,10 @@ import (
|
||||
|
||||
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
|
||||
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
|
||||
|
||||
// 插件控制
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/control/web" // web 后端控制
|
||||
|
||||
// 词库类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri" // ATRI词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat" // 基础词库
|
||||
@@ -23,10 +27,12 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin-Gif" // 制图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_hs" // 炉石
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft" // MCSManager
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_music" // 点歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定
|
||||
|
||||
// b站相关
|
||||
@@ -42,64 +48,76 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_setutime" // 来份涩图
|
||||
|
||||
// 以下为内置依赖,勿动
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
contents = []string{
|
||||
"* OneBot + ZeroBot + Golang",
|
||||
"* Version 1.1.5 - 2021-09-09 20:52:33 +0800 CST",
|
||||
"* Copyright © 2020 - 2021 Kanri, DawnNights, Fumiama, Suika",
|
||||
"* Version 1.1.7 - 2021-10-09 12:50:23 +0800 CST",
|
||||
"* Copyright © 2020 - 2021 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
banner = strings.Join(contents, "\n")
|
||||
// 是否禁用gui
|
||||
disableGui bool
|
||||
token *string
|
||||
url *string
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 解析命令行参数,输入`-g`即可禁用gui
|
||||
flag.BoolVar(&disableGui, "g", false, "Disable the gui")
|
||||
// 解析命令行参数
|
||||
d := flag.Bool("d", false, "Enable debug level log and higher.")
|
||||
w := flag.Bool("w", false, "Enable warning level log and higher.")
|
||||
h := flag.Bool("h", false, "Display this help.")
|
||||
// 直接写死 AccessToken 时,请更改下面第二个参数
|
||||
token = flag.String("t", "", "Set AccessToken of WSClient.")
|
||||
// 直接写死 URL 时,请更改下面第二个参数
|
||||
url = flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
|
||||
flag.Parse()
|
||||
if !disableGui {
|
||||
control.InitGui()
|
||||
if *h {
|
||||
printBanner()
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
} else {
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
}
|
||||
|
||||
log.SetLevel(log.DebugLevel)
|
||||
}
|
||||
|
||||
func main() {
|
||||
func printBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
"\n", banner, "\n",
|
||||
"============================================================\n",
|
||||
) // 启动打印
|
||||
)
|
||||
}
|
||||
|
||||
func main() {
|
||||
printBanner()
|
||||
zero.Run(zero.Config{
|
||||
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
|
||||
CommandPrefix: "/",
|
||||
|
||||
// SuperUsers 某些功能需要主人权限,可通过以下两种方式修改
|
||||
// []string{}:通过代码写死的方式添加主人账号
|
||||
// os.Args[1:]:通过命令行参数的方式添加主人账号
|
||||
SuperUsers: append([]string{"12345678", "87654321"}, os.Args[1:]...),
|
||||
|
||||
// flag.Args():通过命令行参数的方式添加主人账号
|
||||
SuperUsers: append([]string{"12345678", "87654321"}, flag.Args()...),
|
||||
Driver: []zero.Driver{
|
||||
&driver.WSClient{
|
||||
// OneBot 正向WS 默认使用 6700 端口
|
||||
Url: "ws://127.0.0.1:6700",
|
||||
AccessToken: "",
|
||||
},
|
||||
driver.NewWebSocketClient(*url, *token),
|
||||
},
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
// 帮助
|
||||
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send(banner)
|
||||
ctx.SendChain(message.Text(banner))
|
||||
})
|
||||
select {}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package acgimage
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -21,9 +21,8 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
botpath, _ = os.Getwd()
|
||||
datapath = botpath + "/data/acgimage/"
|
||||
cacheuri = "file:///" + datapath + "cache"
|
||||
datapath = file.BOT_PATH + "/data/acgimage/"
|
||||
cacheuri = "file:///" + datapath + "cache"
|
||||
// r18有一定保护,一般不会发出图片
|
||||
randapi = "&loli=true&r18=true"
|
||||
msgof = make(map[int64]int64)
|
||||
@@ -46,10 +45,10 @@ func init() { // 插件主体
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["regex_matched"].([]string)[1]
|
||||
if !strings.HasPrefix(url, "http") {
|
||||
ctx.Send("URL非法!")
|
||||
ctx.SendChain(message.Text("URL非法!"))
|
||||
} else {
|
||||
randapi = url
|
||||
ctx.Send("设置好啦")
|
||||
ctx.SendChain(message.Text("设置好啦"))
|
||||
}
|
||||
})
|
||||
// 有保护的随机图片
|
||||
@@ -61,14 +60,14 @@ func init() { // 插件主体
|
||||
replyClass(ctx, dhash, class, false, lastvisit, comment)
|
||||
}()
|
||||
} else {
|
||||
ctx.Send("你太快啦!")
|
||||
ctx.SendChain(message.Text("你太快啦!"))
|
||||
}
|
||||
})
|
||||
// 直接随机图片,无r18保护,后果自负。如果出r18图可尽快通过发送"太涩了"撤回
|
||||
engine.OnFullMatch("直接随机", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if block {
|
||||
ctx.Send("请稍后再试哦")
|
||||
ctx.SendChain(message.Text("请稍后再试哦"))
|
||||
} else if randapi != "" {
|
||||
block = true
|
||||
var url string
|
||||
@@ -77,7 +76,7 @@ func init() { // 插件主体
|
||||
} else {
|
||||
url = randapi
|
||||
}
|
||||
setLastMsg(ctx.Event.GroupID, ctx.Send(message.Image(url).Add("cache", "0")))
|
||||
setLastMsg(ctx.Event.GroupID, ctx.SendChain(message.Image(url).Add("cache", "0")))
|
||||
block = false
|
||||
}
|
||||
})
|
||||
@@ -89,7 +88,7 @@ func init() { // 插件主体
|
||||
// 上传一张图进行评价
|
||||
engine.OnKeywordGroup([]string{"评价图片"}, zero.OnlyGroup, picture.CmdMatch, picture.MustGiven).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send("少女祈祷中...")
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
for _, url := range ctx.State["image_url"].([]string) {
|
||||
go func(target string) {
|
||||
class, lastvisit, dhash, comment := classify.Classify(target, true)
|
||||
@@ -101,7 +100,7 @@ func init() { // 插件主体
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dhash := ctx.State["regex_matched"].([]string)[1]
|
||||
if len(dhash) == 5*3 {
|
||||
ctx.Send(message.Image(apihead + dhash))
|
||||
ctx.SendChain(message.Image(apihead + dhash))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -124,19 +123,18 @@ func replyClass(ctx *zero.Ctx, dhash string, class int, noimg bool, lv int64, co
|
||||
if dhash != "" && !noimg {
|
||||
b14, err3 := url.QueryUnescape(dhash)
|
||||
if err3 == nil {
|
||||
ctx.Send(comment + "\n给你点提示哦:" + b14)
|
||||
ctx.SendChain(message.Text(comment + "\n给你点提示哦:" + b14))
|
||||
ctx.Event.GroupID = 0
|
||||
ctx.Send(img)
|
||||
ctx.SendChain(img)
|
||||
}
|
||||
} else {
|
||||
ctx.Send(comment)
|
||||
ctx.SendChain(message.Text(comment))
|
||||
}
|
||||
} else {
|
||||
comment := message.Text(comment)
|
||||
if !noimg {
|
||||
ctx.SendChain(img, comment)
|
||||
ctx.SendChain(img, message.Text(comment))
|
||||
} else {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), comment)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(comment))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package aifalse
|
||||
|
||||
import (
|
||||
"math"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
@@ -30,6 +31,15 @@ func init() { // 插件主体
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnFullMatch("清理缓存", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := os.RemoveAll("data/cache/*")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("错误: ", err.Error()))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func cpuPercent() float64 {
|
||||
|
||||
@@ -12,17 +12,16 @@ import (
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
)
|
||||
|
||||
var engine *zero.Engine
|
||||
var engine = control.Register("bilibili", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibili\n" +
|
||||
"- >vup info [名字|uid]\n" +
|
||||
"- >user info [名字|uid]\n" +
|
||||
"- /开启粉丝日报",
|
||||
})
|
||||
|
||||
// 查成分的
|
||||
func init() {
|
||||
engine = control.Register("bilibili", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibili\n" +
|
||||
"- >vup info [名字|uid]\n" +
|
||||
"- >user info [名字|uid]\n" +
|
||||
"- /开启粉丝日报",
|
||||
})
|
||||
engine.OnRegex(`^>user info\s(.{1,25})$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
package diana
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin_diana/data"
|
||||
@@ -28,22 +28,22 @@ func init() {
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
// 绕过第一行发病
|
||||
ctx.Send((*data.Array)[rand.Intn(len(*data.Array)-1)+1])
|
||||
ctx.SendChain(message.Text((*data.Array)[rand.Intn(len(*data.Array)-1)+1]))
|
||||
})
|
||||
// 逆天
|
||||
engine.OnFullMatch("发大病").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 第一行是发病
|
||||
ctx.Send((*data.Array)[0])
|
||||
ctx.SendChain(message.Text((*data.Array)[0]))
|
||||
})
|
||||
// 增加小作文
|
||||
engine.OnRegex(`^教你一篇小作文(.*)$`, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := data.AddText(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
ctx.Send("记住啦!")
|
||||
ctx.SendChain(message.Text("记住啦!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,20 +3,23 @@ package data
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
)
|
||||
|
||||
const (
|
||||
datapath = "data/Diana"
|
||||
pbfile = datapath + "/text.pb"
|
||||
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/data/Diana/text.pb"
|
||||
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + pbfile
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -42,7 +45,7 @@ func init() {
|
||||
log.Printf("[Diana]读取%d条小作文", arrl)
|
||||
md5s = make([]*[16]byte, arrl)
|
||||
for i, t := range *Array {
|
||||
m := md5.Sum(str2bytes(t))
|
||||
m := md5.Sum(helper.StringToBytes(t))
|
||||
md5s[i] = &m
|
||||
}
|
||||
} else {
|
||||
@@ -53,7 +56,7 @@ func init() {
|
||||
|
||||
// LoadText 加载小作文
|
||||
func LoadText() error {
|
||||
if _, err := os.Stat(pbfile); err == nil || os.IsExist(err) {
|
||||
if file.IsExist(pbfile) {
|
||||
f, err := os.Open(pbfile)
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
@@ -92,7 +95,7 @@ func LoadText() error {
|
||||
|
||||
// AddText 添加小作文
|
||||
func AddText(txt string) error {
|
||||
sum := md5.Sum(str2bytes(txt))
|
||||
sum := md5.Sum(helper.StringToBytes(txt))
|
||||
if txt != "" && !isin(&sum) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
@@ -116,7 +119,7 @@ func isin(sum *[16]byte) bool {
|
||||
func savecompo() error {
|
||||
data, err := compo.Marshal()
|
||||
if err == nil {
|
||||
if _, err := os.Stat(datapath); err == nil || os.IsExist(err) {
|
||||
if file.IsExist(datapath) {
|
||||
f, err1 := os.OpenFile(pbfile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err1 == nil {
|
||||
_, err2 := f.Write(data)
|
||||
@@ -125,13 +128,7 @@ func savecompo() error {
|
||||
}
|
||||
return err1
|
||||
}
|
||||
return errors.New("datapath is not exist")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// str2bytes Fast convert
|
||||
func str2bytes(s string) []byte {
|
||||
x := (*[2]uintptr)(unsafe.Pointer(&s))
|
||||
h := [3]uintptr{x[0], x[1], x[1]}
|
||||
return *(*[]byte)(unsafe.Pointer(&h))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Package diana 嘉然相关
|
||||
package diana
|
||||
|
||||
import (
|
||||
@@ -37,12 +38,12 @@ func init() {
|
||||
zhiwangjson := zhiwangapi(msg)
|
||||
|
||||
if zhiwangjson == nil || zhiwangjson.Code != 0 {
|
||||
ctx.Send("api返回错误")
|
||||
ctx.SendChain(message.Text("api返回错误"))
|
||||
return
|
||||
}
|
||||
|
||||
if len(zhiwangjson.Data.Related) == 0 {
|
||||
ctx.Send("枝网没搜到,查重率为0%,我的评价是:一眼真")
|
||||
ctx.SendChain(message.Text("枝网没搜到,查重率为0%,我的评价是:一眼真"))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
405
plugin_fortune/cfg.pb.go
Normal file
405
plugin_fortune/cfg.pb.go
Normal file
@@ -0,0 +1,405 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: cfg.proto
|
||||
|
||||
package fortune
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Conf struct {
|
||||
Kind map[int64]uint32 `protobuf:"bytes,1,rep,name=kind,proto3" json:"kind,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Conf) Reset() { *m = Conf{} }
|
||||
func (m *Conf) String() string { return proto.CompactTextString(m) }
|
||||
func (*Conf) ProtoMessage() {}
|
||||
func (*Conf) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f81ba022997f8a9d, []int{0}
|
||||
}
|
||||
func (m *Conf) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Conf) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Conf.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *Conf) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Conf.Merge(m, src)
|
||||
}
|
||||
func (m *Conf) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *Conf) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Conf.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Conf proto.InternalMessageInfo
|
||||
|
||||
func (m *Conf) GetKind() map[int64]uint32 {
|
||||
if m != nil {
|
||||
return m.Kind
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Conf)(nil), "fortune.conf")
|
||||
proto.RegisterMapType((map[int64]uint32)(nil), "fortune.conf.KindEntry")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("cfg.proto", fileDescriptor_f81ba022997f8a9d) }
|
||||
|
||||
var fileDescriptor_f81ba022997f8a9d = []byte{
|
||||
// 154 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x4e, 0x4b, 0xd7,
|
||||
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4f, 0xcb, 0x2f, 0x2a, 0x29, 0xcd, 0x4b, 0x55, 0xca,
|
||||
0xe1, 0x62, 0x49, 0xce, 0xcf, 0x4b, 0x13, 0xd2, 0xe6, 0x62, 0xc9, 0xce, 0xcc, 0x4b, 0x91, 0x60,
|
||||
0x54, 0x60, 0xd6, 0xe0, 0x36, 0x12, 0xd7, 0x83, 0xca, 0xeb, 0x81, 0x24, 0xf5, 0xbc, 0x33, 0xf3,
|
||||
0x52, 0x5c, 0xf3, 0x4a, 0x8a, 0x2a, 0x83, 0xc0, 0x8a, 0xa4, 0xcc, 0xb9, 0x38, 0xe1, 0x42, 0x42,
|
||||
0x02, 0x5c, 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x20, 0xa6, 0x90,
|
||||
0x08, 0x17, 0x6b, 0x59, 0x62, 0x4e, 0x69, 0xaa, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6f, 0x10, 0x84,
|
||||
0x63, 0xc5, 0x64, 0xc1, 0xe8, 0x24, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f,
|
||||
0x1e, 0xc9, 0x31, 0xce, 0x78, 0x2c, 0xc7, 0x90, 0xc4, 0x06, 0x76, 0x8f, 0x31, 0x20, 0x00, 0x00,
|
||||
0xff, 0xff, 0x8a, 0xa2, 0xbe, 0x9e, 0x9c, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Conf) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Conf) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Conf) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.Kind) > 0 {
|
||||
for k := range m.Kind {
|
||||
v := m.Kind[k]
|
||||
baseI := i
|
||||
i = encodeVarintCfg(dAtA, i, uint64(v))
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
i = encodeVarintCfg(dAtA, i, uint64(k))
|
||||
i--
|
||||
dAtA[i] = 0x8
|
||||
i = encodeVarintCfg(dAtA, i, uint64(baseI-i))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintCfg(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovCfg(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *Conf) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Kind) > 0 {
|
||||
for k, v := range m.Kind {
|
||||
_ = k
|
||||
_ = v
|
||||
mapEntrySize := 1 + sovCfg(uint64(k)) + 1 + sovCfg(uint64(v))
|
||||
n += mapEntrySize + 1 + sovCfg(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovCfg(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozCfg(x uint64) (n int) {
|
||||
return sovCfg(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Conf) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: conf: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: conf: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthCfg
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthCfg
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Kind == nil {
|
||||
m.Kind = make(map[int64]uint32)
|
||||
}
|
||||
var mapkey int64
|
||||
var mapvalue uint32
|
||||
for iNdEx < postIndex {
|
||||
entryPreIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
if fieldNum == 1 {
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
mapkey |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if fieldNum == 2 {
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
mapvalue |= uint32(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iNdEx = entryPreIndex
|
||||
skippy, err := skipCfg(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthCfg
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
m.Kind[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipCfg(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthCfg
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipCfg(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCfg
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthCfg
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupCfg
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthCfg
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthCfg = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowCfg = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupCfg = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
6
plugin_fortune/cfg.proto
Normal file
6
plugin_fortune/cfg.proto
Normal file
@@ -0,0 +1,6 @@
|
||||
syntax = "proto3";
|
||||
package fortune;
|
||||
|
||||
message conf {
|
||||
map<int64, uint32> kind = 1;
|
||||
}
|
||||
55
plugin_fortune/data.go
Normal file
55
plugin_fortune/data.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package fortune
|
||||
|
||||
import (
|
||||
"errors"
|
||||
io "io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
)
|
||||
|
||||
var (
|
||||
conf Conf
|
||||
mu sync.Mutex
|
||||
)
|
||||
|
||||
func loadcfg(name string) error {
|
||||
name = base + name
|
||||
if file.IsExist(name) {
|
||||
f, err := os.Open(name)
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
data, err1 := io.ReadAll(f)
|
||||
if err1 == nil {
|
||||
if len(data) > 0 {
|
||||
return conf.Unmarshal(data)
|
||||
}
|
||||
}
|
||||
return err1
|
||||
}
|
||||
} else { // 如果没有 cfg,则使用空 map
|
||||
conf.Kind = make(map[int64]uint32)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func savecfg(name string) error {
|
||||
name = base + name
|
||||
data, err := conf.Marshal()
|
||||
if err == nil {
|
||||
if file.IsExist(base) {
|
||||
f, err1 := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err1 == nil {
|
||||
mu.Lock()
|
||||
_, err2 := f.Write(data)
|
||||
f.Close()
|
||||
mu.Unlock()
|
||||
return err2
|
||||
}
|
||||
return err1
|
||||
}
|
||||
return errors.New("base dir is not exist")
|
||||
}
|
||||
return err
|
||||
}
|
||||
306
plugin_fortune/fortune.go
Normal file
306
plugin_fortune/fortune.go
Normal file
@@ -0,0 +1,306 @@
|
||||
// Package fortune 每日运势
|
||||
package fortune
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fogleman/gg"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
|
||||
)
|
||||
|
||||
var (
|
||||
// 底图缓存位置
|
||||
base = "data/fortune/"
|
||||
// 素材下载网站
|
||||
site = "https://pan.dihe.moe/fortune/"
|
||||
// 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌
|
||||
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师
|
||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师"}
|
||||
// 映射底图与 index
|
||||
index = make(map[string]uint32)
|
||||
)
|
||||
|
||||
func init() {
|
||||
err := loadcfg("cfg.pb")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i, s := range table {
|
||||
index[s] = uint32(i)
|
||||
}
|
||||
err = os.MkdirAll(base, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// 插件主体
|
||||
en := control.Register("fortune", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "每日运势: \n" +
|
||||
"- 运势|抽签\n" +
|
||||
"- 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师]",
|
||||
})
|
||||
en.OnRegex(`^设置底图(.*)`).SetBlock(true).SecondPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid <= 0 {
|
||||
// 个人用户设为负数
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
i, ok := index[ctx.State["regex_matched"].([]string)[1]]
|
||||
if ok {
|
||||
conf.Kind[gid] = i
|
||||
savecfg("cfg.pb")
|
||||
ctx.SendChain(message.Text("设置成功~"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("没有这个底图哦~"))
|
||||
}
|
||||
})
|
||||
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).SecondPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 检查签文文件是否存在
|
||||
mikuji := base + "运势签文.json"
|
||||
if file.IsNotExist(mikuji) {
|
||||
ctx.SendChain(message.Text("正在下载签文文件,请稍后..."))
|
||||
err := file.DownloadTo(site+"运势签文.json", mikuji)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("下载签文文件完毕"))
|
||||
}
|
||||
// 检查字体文件是否存在
|
||||
ttf := base + "sakura.ttf"
|
||||
if file.IsNotExist(ttf) {
|
||||
ctx.SendChain(message.Text("正在下载字体文件,请稍后..."))
|
||||
err := file.DownloadTo(site+"sakura.ttf", ttf)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("下载字体文件完毕"))
|
||||
}
|
||||
// 获取该群背景类型,默认车万
|
||||
kind := "车万"
|
||||
gid := ctx.Event.GroupID
|
||||
if gid <= 0 {
|
||||
// 个人用户设为负数
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
logrus.Debugln("[fortune]gid:", ctx.Event.GroupID, "uid:", ctx.Event.UserID)
|
||||
if v, ok := conf.Kind[gid]; ok {
|
||||
kind = table[v]
|
||||
}
|
||||
// 检查背景图片是否存在
|
||||
folder := base + kind
|
||||
if file.IsNotExist(folder) {
|
||||
ctx.SendChain(message.Text("正在下载背景图片,请稍后..."))
|
||||
zipfile := kind + ".zip"
|
||||
zipcache := base + zipfile
|
||||
err := file.DownloadTo(site+zipfile, zipcache)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("下载背景图片完毕"))
|
||||
err = unpack(zipcache, folder+"/")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("解压背景图片完毕"))
|
||||
// 释放空间
|
||||
os.Remove(zipcache)
|
||||
}
|
||||
// 生成种子
|
||||
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
|
||||
seed := ctx.Event.UserID + t
|
||||
// 随机获取背景
|
||||
background, err := randimage(folder+"/", seed)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 随机获取签文
|
||||
title, text, err := randtext(mikuji, seed)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 绘制背景
|
||||
d, err := draw(background, title, text)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 发送图片
|
||||
ctx.SendChain(message.Image("base64://" + helper.BytesToString(d)))
|
||||
})
|
||||
}
|
||||
|
||||
// @function unpack 解压资源包
|
||||
// @param tgt 压缩文件位置
|
||||
// @param dest 解压位置
|
||||
// @return 错误信息
|
||||
func unpack(tgt, dest string) error {
|
||||
// 路径目录不存在则创建目录
|
||||
if file.IsNotExist(dest) {
|
||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
reader, err := zip.OpenReader(tgt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer reader.Close()
|
||||
// 遍历解压到文件
|
||||
for _, file := range reader.File {
|
||||
// 打开解压文件
|
||||
rc, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 打开目标文件
|
||||
w, err := os.OpenFile(dest+file.Name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
rc.Close()
|
||||
return err
|
||||
}
|
||||
// 复制到文件
|
||||
_, err = io.Copy(w, rc)
|
||||
rc.Close()
|
||||
w.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// @function randimage 随机选取文件夹下的文件
|
||||
// @param path 文件夹路径
|
||||
// @param seed 随机数种子
|
||||
// @return 文件路径 & 错误信息
|
||||
func randimage(path string, seed int64) (string, error) {
|
||||
rd, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
rand.Seed(seed)
|
||||
return path + rd[rand.Intn(len(rd))].Name(), nil
|
||||
}
|
||||
|
||||
// @function randtext 随机选取签文
|
||||
// @param file 文件路径
|
||||
// @param seed 随机数种子
|
||||
// @return 签名 & 签文 & 错误信息
|
||||
func randtext(file string, seed int64) (string, string, error) {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
temp := []map[string]string{}
|
||||
if err := json.Unmarshal(data, &temp); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
rand.Seed(seed)
|
||||
r := rand.Intn(len(temp))
|
||||
return temp[r]["title"], temp[r]["content"], nil
|
||||
}
|
||||
|
||||
// @function draw 绘制运势图
|
||||
// @param background 背景图片路径
|
||||
// @param seed 随机数种子
|
||||
// @param title 签名
|
||||
// @param text 签文
|
||||
// @return 错误信息
|
||||
func draw(background, title, text string) ([]byte, error) {
|
||||
// 加载背景
|
||||
back, err := gg.LoadImage(background)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas := gg.NewContext(back.Bounds().Size().Y, back.Bounds().Size().X)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
// 写标题
|
||||
canvas.SetRGB(1, 1, 1)
|
||||
if err := canvas.LoadFontFace(base+"sakura.ttf", 45); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sw, _ := canvas.MeasureString(title)
|
||||
canvas.DrawString(title, 140-sw/2, 112)
|
||||
// 写正文
|
||||
canvas.SetRGB(0, 0, 0)
|
||||
if err := canvas.LoadFontFace(base+"sakura.ttf", 23); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tw, th := canvas.MeasureString("测")
|
||||
tw, th = tw+10, th+10
|
||||
r := []rune(text)
|
||||
xsum := rowsnum(len(r), 9)
|
||||
switch xsum {
|
||||
default:
|
||||
for i, o := range r {
|
||||
xnow := rowsnum(i+1, 9)
|
||||
ysum := math.Min(len(r)-(xnow-1)*9, 9)
|
||||
ynow := i%9 + 1
|
||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(ysum, ynow, th)+320.0)
|
||||
}
|
||||
case 2:
|
||||
div := rowsnum(len(r), 2)
|
||||
for i, o := range r {
|
||||
xnow := rowsnum(i+1, div)
|
||||
ysum := math.Min(len(r)-(xnow-1)*div, div)
|
||||
ynow := i%div + 1
|
||||
switch xnow {
|
||||
case 1:
|
||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow, th)+320.0)
|
||||
case 2:
|
||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow+(9-ysum), th)+320.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 转成 base64
|
||||
buffer := new(bytes.Buffer)
|
||||
encoder := base64.NewEncoder(base64.StdEncoding, buffer)
|
||||
var opt jpeg.Options
|
||||
opt.Quality = 70
|
||||
err = jpeg.Encode(encoder, canvas.Image(), &opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encoder.Close()
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func offest(total, now int, distance float64) float64 {
|
||||
if total%2 == 0 {
|
||||
return (float64(now-total/2) - 1) * distance
|
||||
}
|
||||
return (float64(now-total/2) - 1.5) * distance
|
||||
}
|
||||
|
||||
func rowsnum(total, div int) int {
|
||||
temp := total / div
|
||||
if total%div != 0 {
|
||||
temp++
|
||||
}
|
||||
return temp
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package hs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/imroc/req"
|
||||
"github.com/tidwall/gjson"
|
||||
@@ -14,9 +14,10 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
)
|
||||
|
||||
const cachedir = "data/hs/"
|
||||
var cachedir = file.BOT_PATH + "/data/hs/"
|
||||
|
||||
var header = req.Header{
|
||||
"user-agent": `Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36`,
|
||||
@@ -41,40 +42,48 @@ func init() {
|
||||
SetBlock(true).SetPriority(20).Handle(func(ctx *zero.Ctx) {
|
||||
List := ctx.State["regex_matched"].([]string)[1]
|
||||
g := sh(List)
|
||||
im, _ := req.Get(`https://res.fbigame.com/hs/v13/`+
|
||||
gjson.Get(g, `list.0.CardID`).String()+
|
||||
`.png?auth_key=`+
|
||||
gjson.Get(g, `list.0.auth_key`).String(), header)
|
||||
cachefile := cachedir + strconv.Itoa(int(time.Now().Unix()))
|
||||
err := im.ToFile(cachefile)
|
||||
if err == nil {
|
||||
file, err := os.Open(cachefile)
|
||||
if err == nil {
|
||||
defer file.Close()
|
||||
sg, _ := req.Post("https://pic.sogou.com/pic/upload_pic.jsp", req.FileUpload{
|
||||
File: file,
|
||||
FieldName: "image", // FieldName 是表单字段名
|
||||
FileName: "avatar.png", // Filename 是要上传的文件的名称,我们使用它来猜测mimetype,并将其上传到服务器上
|
||||
})
|
||||
var tx string
|
||||
t := int(gjson.Get(g, `list.#`).Int())
|
||||
if t == 0 {
|
||||
ctx.Send("查询为空!")
|
||||
return
|
||||
}
|
||||
for i := 0; i < t && i < 10; i++ {
|
||||
tx += strconv.Itoa(i+1) + ". 法力:" +
|
||||
gjson.Get(g, `list.`+strconv.Itoa(i)+`.COST`).String() +
|
||||
" " +
|
||||
gjson.Get(g, `list.`+strconv.Itoa(i)+`.CARDNAME`).String() +
|
||||
"\n"
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Image(sg.String()),
|
||||
message.Text(tx),
|
||||
)
|
||||
}
|
||||
t := int(gjson.Get(g, `list.#`).Int())
|
||||
if t == 0 {
|
||||
ctx.SendChain(message.Text("查询为空!"))
|
||||
return
|
||||
}
|
||||
var sk message.Message
|
||||
var data []byte
|
||||
for i := 0; i < t && i < 5; i++ {
|
||||
cid := gjson.Get(g, `list.`+strconv.Itoa(i)+`.CardID`).String()
|
||||
cachefile := cachedir + cid
|
||||
imgcq := `[CQ:image,file=` + "file:///" + cachefile + `]`
|
||||
if file.IsNotExist(cachefile) {
|
||||
im, err := req.Get(`https://res.fbigame.com/hs/v13/`+cid+
|
||||
`.png?auth_key=`+gjson.Get(g, `list.`+strconv.Itoa(i)+`.auth_key`).String(),
|
||||
header,
|
||||
)
|
||||
if err == nil {
|
||||
data, err = io.ReadAll(im.Response().Body)
|
||||
if err == nil {
|
||||
err = im.Response().Body.Close()
|
||||
if err == nil {
|
||||
err = os.WriteFile(cachefile, data, 0644)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
imgcq = err.Error()
|
||||
}
|
||||
}
|
||||
sk = append(
|
||||
sk,
|
||||
message.CustomNode(
|
||||
ctx.Event.Sender.NickName,
|
||||
ctx.Event.UserID,
|
||||
imgcq, // 图片
|
||||
),
|
||||
)
|
||||
}
|
||||
ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
sk,
|
||||
)
|
||||
})
|
||||
// 卡组
|
||||
engine.OnRegex(`^[\s\S]*?(AAE[a-zA-Z0-9/\+=]{70,})[\s\S]*$`).
|
||||
|
||||
@@ -70,7 +70,7 @@ func init() {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
soutujson := soutuapi(keyword)
|
||||
pom1 := "https://i.pixiv.cat"
|
||||
rannum := randint()
|
||||
rannum := randintn(len(soutujson.Illusts))
|
||||
pom2 := soutujson.Illusts[rannum].ImageUrls.Large[19:]
|
||||
ctx.SendChain(message.Image(pom1 + pom2))
|
||||
})
|
||||
@@ -88,7 +88,7 @@ func soutuapi(keyword string) *resultjson {
|
||||
fmt.Println(err)
|
||||
}
|
||||
req.Header.Add("accept", "application/json, text/plain, */*")
|
||||
|
||||
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36")
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
@@ -102,8 +102,8 @@ func soutuapi(keyword string) *resultjson {
|
||||
return result
|
||||
}
|
||||
|
||||
// randint 从json里的30条数据中随机获取一条返回
|
||||
func randint() int {
|
||||
// randintn 从json里的30条数据中随机获取一条返回
|
||||
func randintn(len int) int {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return rand.Intn(30)
|
||||
return rand.Intn(len)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -30,7 +31,7 @@ func init() {
|
||||
}).OnFullMatch("来份萝莉").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
go func() {
|
||||
for i := 0; i < min(cap(queue)-len(queue), 2); i++ {
|
||||
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
|
||||
resp, err := http.Get(api)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
@@ -60,10 +61,3 @@ func init() {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
timer "github.com/FloatTech/ZeroBot-Plugin-Timer"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -56,7 +59,7 @@ func init() { // 插件主体
|
||||
// 菜单
|
||||
zero.OnFullMatch("群管系统", zero.AdminPermission).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send(hint)
|
||||
ctx.SendChain(message.Text(hint))
|
||||
})
|
||||
// 升为管理
|
||||
zero.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
@@ -252,9 +255,9 @@ func init() { // 插件主体
|
||||
ts.Grpid = uint64(ctx.Event.GroupID)
|
||||
if ts.Enable {
|
||||
go timer.RegisterTimer(ts, true)
|
||||
ctx.Send("记住了~")
|
||||
ctx.SendChain(message.Text("记住了~"))
|
||||
} else {
|
||||
ctx.Send("参数非法!")
|
||||
ctx.SendChain(message.Text("参数非法!"))
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -271,9 +274,9 @@ func init() { // 插件主体
|
||||
t.Enable = false
|
||||
delete(*timer.Timers, ti) // 避免重复取消
|
||||
_ = timer.SaveTimers()
|
||||
ctx.Send("取消成功~")
|
||||
ctx.SendChain(message.Text("取消成功~"))
|
||||
} else {
|
||||
ctx.Send("没有这个定时器哦~")
|
||||
ctx.SendChain(message.Text("没有这个定时器哦~"))
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -281,7 +284,7 @@ func init() { // 插件主体
|
||||
zero.OnFullMatch("列出所有提醒", zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
ctx.Send(fmt.Sprint(timer.ListTimers(uint64(ctx.Event.GroupID))))
|
||||
ctx.SendChain(message.Text(timer.ListTimers(uint64(ctx.Event.GroupID))))
|
||||
}
|
||||
})
|
||||
// 随机点名
|
||||
@@ -300,13 +303,7 @@ func init() { // 插件主体
|
||||
sort.SliceStable(temp, func(i, j int) bool {
|
||||
return temp[i].Get("last_sent_time").Int() < temp[j].Get("last_sent_time").Int()
|
||||
})
|
||||
max := func(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
temp = temp[max(0, len(temp)-10):]
|
||||
temp = temp[math.Max(0, len(temp)-10):]
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
who := temp[rand.Intn(len(temp))]
|
||||
if who.Get("user_id").Int() == ctx.Event.SelfID {
|
||||
@@ -334,9 +331,9 @@ func init() { // 插件主体
|
||||
if ctx.Event.NoticeType == "group_increase" {
|
||||
word, ok := config.Welcome[uint64(ctx.Event.GroupID)]
|
||||
if ok {
|
||||
ctx.Send(word)
|
||||
ctx.SendChain(message.Text(word))
|
||||
} else {
|
||||
ctx.Send("欢迎~")
|
||||
ctx.SendChain(message.Text("欢迎~"))
|
||||
}
|
||||
enable, ok1 := config.Checkin[uint64(ctx.Event.GroupID)]
|
||||
if ok1 && enable {
|
||||
@@ -353,7 +350,7 @@ func init() { // 插件主体
|
||||
ans, err := strconv.Atoi(text)
|
||||
if err == nil {
|
||||
if ans != r {
|
||||
ctx.Send("答案不对哦,再想想吧~")
|
||||
ctx.SendChain(message.Text("答案不对哦,再想想吧~"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -366,12 +363,12 @@ func init() { // 插件主体
|
||||
recv, cancel := next.Repeat()
|
||||
select {
|
||||
case <-time.After(time.Minute):
|
||||
ctx.Send("拜拜啦~")
|
||||
ctx.SendChain(message.Text("拜拜啦~"))
|
||||
ctx.SetGroupKick(ctx.Event.GroupID, uid, false)
|
||||
cancel()
|
||||
case <-recv:
|
||||
cancel()
|
||||
ctx.Send("答对啦~")
|
||||
ctx.SendChain(message.Text("答对啦~"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -388,9 +385,9 @@ func init() { // 插件主体
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
config.Welcome[uint64(ctx.Event.GroupID)] = ctx.State["regex_matched"].([]string)[1]
|
||||
if saveConfig() == nil {
|
||||
ctx.Send("记住啦!")
|
||||
ctx.SendChain(message.Text("记住啦!"))
|
||||
} else {
|
||||
ctx.Send("出错啦!")
|
||||
ctx.SendChain(message.Text("出错啦!"))
|
||||
}
|
||||
})
|
||||
// 入群验证开关
|
||||
@@ -406,9 +403,9 @@ func init() { // 插件主体
|
||||
return
|
||||
}
|
||||
if saveConfig() == nil {
|
||||
ctx.Send("已" + option)
|
||||
ctx.SendChain(message.Text("已", option))
|
||||
} else {
|
||||
ctx.Send("出错啦!")
|
||||
ctx.SendChain(message.Text("出错啦!"))
|
||||
}
|
||||
})
|
||||
// 运行 CQ 码
|
||||
@@ -417,6 +414,7 @@ func init() { // 插件主体
|
||||
var cmd = ctx.State["regex_matched"].([]string)[1]
|
||||
cmd = strings.ReplaceAll(cmd, "[", "[")
|
||||
cmd = strings.ReplaceAll(cmd, "]", "]")
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(cmd)
|
||||
})
|
||||
}
|
||||
@@ -430,7 +428,7 @@ func strToInt(str string) int64 {
|
||||
func loadConfig() {
|
||||
mkdirerr := os.MkdirAll(datapath, 0755)
|
||||
if mkdirerr == nil {
|
||||
if _, err := os.Stat(confile); err == nil || os.IsExist(err) {
|
||||
if file.IsExist(confile) {
|
||||
f, err := os.Open(confile)
|
||||
if err == nil {
|
||||
data, err1 := io.ReadAll(f)
|
||||
@@ -455,7 +453,7 @@ func saveConfig() error {
|
||||
data, err := config.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
} else if _, err := os.Stat(datapath); err == nil || os.IsExist(err) {
|
||||
} else if file.IsExist(datapath) {
|
||||
f, err1 := os.OpenFile(confile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err1 != nil {
|
||||
return err1
|
||||
|
||||
@@ -19,24 +19,23 @@ import (
|
||||
|
||||
const api = "http://your.addr:23333/api/start_server/%s/?apikey=apikey"
|
||||
|
||||
var engine *zero.Engine
|
||||
var engine = control.Register("minecraft", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "minecraft\n" +
|
||||
"- /mcstart xxx\n" +
|
||||
"- /mcstop xxx\n" +
|
||||
"- /mclist servername\n" +
|
||||
"- https://github.com/Suwings/MCSManager",
|
||||
})
|
||||
|
||||
func init() {
|
||||
engine = control.Register("minecraft", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "minecraft\n" +
|
||||
"- /mcstart xxx\n" +
|
||||
"- /mcstop xxx\n" +
|
||||
"- /mclist servername\n" +
|
||||
"- https://github.com/Suwings/MCSManager",
|
||||
})
|
||||
engine.OnCommand("mcstart").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
model := extension.CommandModel{}
|
||||
_ = ctx.Parse(&model)
|
||||
ctx.SendChain(message.Text("开启服务器: ", model.Args, "....."))
|
||||
result := start(model.Args)
|
||||
ctx.Send(result)
|
||||
ctx.SendChain(message.Text(result))
|
||||
})
|
||||
engine.OnCommand("mcstop").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
@@ -44,7 +43,7 @@ func init() {
|
||||
_ = ctx.Parse(&model)
|
||||
ctx.SendChain(message.Text("开启服务器: ", model.Args, "....."))
|
||||
result := stop(model.Args)
|
||||
ctx.Send(result)
|
||||
ctx.SendChain(message.Text(result))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ func init() {
|
||||
}).OnRegex("^(.{0,2})点歌(.{1,25})$").SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
ctx.SendChain(message.Text("请稍后重试0x0..."))
|
||||
return
|
||||
}
|
||||
// switch 平台
|
||||
|
||||
@@ -17,14 +17,12 @@ const (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// TODO: 1.17 特性暂不增加
|
||||
// rand.Seed(time.Now().UnixMicro())
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
control.Register("omikuji", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "浅草寺求签\n" +
|
||||
"- 求签|运势|占卜",
|
||||
}).OnFullMatchGroup([]string{"求签", "运势", "占卜"}).SetPriority(10).SetBlock(true).
|
||||
"- 求签|占卜",
|
||||
}).OnFullMatchGroup([]string{"求签", "占卜"}).SetPriority(10).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
miku := rand.Intn(100) + 1
|
||||
ctx.SendChain(
|
||||
|
||||
21
plugin_reborn/born.go
Normal file
21
plugin_reborn/born.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package reborn
|
||||
|
||||
import (
|
||||
wr "github.com/mroth/weightedrand"
|
||||
)
|
||||
|
||||
var (
|
||||
gender, _ = wr.NewChooser(
|
||||
wr.Choice{Item: "男孩子", Weight: 50707},
|
||||
wr.Choice{Item: "女孩子", Weight: 48292},
|
||||
wr.Choice{Item: "雌雄同体", Weight: 1001},
|
||||
)
|
||||
)
|
||||
|
||||
func randcoun() string {
|
||||
return areac.Pick().(string)
|
||||
}
|
||||
|
||||
func randgen() string {
|
||||
return gender.Pick().(string)
|
||||
}
|
||||
93
plugin_reborn/load.go
Normal file
93
plugin_reborn/load.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package reborn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
wr "github.com/mroth/weightedrand"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
)
|
||||
|
||||
const (
|
||||
datapath = "data/Reborn"
|
||||
jsonfile = datapath + "/rate.json"
|
||||
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + jsonfile
|
||||
)
|
||||
|
||||
type rate []struct {
|
||||
Name string `json:"name"`
|
||||
Weight float64 `json:"weight"`
|
||||
}
|
||||
|
||||
var (
|
||||
areac *wr.Chooser
|
||||
)
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
time.Sleep(time.Second)
|
||||
err := os.MkdirAll(datapath, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
area := make(rate, 226)
|
||||
err = load(&area)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
choices := make([]wr.Choice, len(area))
|
||||
for i, a := range area {
|
||||
choices[i].Item = a.Name
|
||||
choices[i].Weight = uint(a.Weight * 1e9)
|
||||
}
|
||||
areac, err = wr.NewChooser(choices...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Printf("[Reborn]读取%d个国家/地区", len(area))
|
||||
}()
|
||||
}
|
||||
|
||||
// load 加载rate数据
|
||||
func load(area *rate) error {
|
||||
if file.IsExist(jsonfile) {
|
||||
f, err := os.Open(jsonfile)
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
data, err1 := io.ReadAll(f)
|
||||
if err1 == nil {
|
||||
if len(data) > 0 {
|
||||
return json.Unmarshal(data, area)
|
||||
}
|
||||
}
|
||||
return err1
|
||||
}
|
||||
} else { // 如果没有小作文,则从 url 下载
|
||||
f, err := os.Create(jsonfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
resp, err := http.Get(pburl)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
if resp.ContentLength > 0 {
|
||||
log.Printf("[Reborn]从镜像下载国家和地区%d字节...", resp.ContentLength)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err == nil && len(data) > 0 {
|
||||
_, _ = f.Write(data)
|
||||
return json.Unmarshal(data, area)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
28
plugin_reborn/main.go
Normal file
28
plugin_reborn/main.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Package reborn 投胎 来自 https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py
|
||||
package reborn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
control.Register("reborn", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "投胎\n- reborn",
|
||||
}).OnFullMatch("reborn").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if rand.Int31() > 1<<27 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("投胎成功!\n您出生在 %s, 是 %s。", randcoun(), randgen())))
|
||||
} else {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("投胎失败!\n您没能活到出生,祝您下次好运!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func init() {
|
||||
}).OnRegex(`^>runcode\s(.+?)\s([\s\S]+)$`).SetBlock(true).SecondPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
ctx.SendChain(message.Text("请稍后重试0x0..."))
|
||||
} else {
|
||||
language := ctx.State["regex_matched"].([]string)[1]
|
||||
language = strings.ToLower(language)
|
||||
|
||||
@@ -3,20 +3,31 @@ package saucenao
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/ascii2d"
|
||||
"github.com/FloatTech/AnimeAPI/picture"
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
"github.com/FloatTech/AnimeAPI/saucenao"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
)
|
||||
|
||||
var (
|
||||
datapath = file.BOT_PATH + "/data/saucenao/"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
_ = os.RemoveAll(datapath)
|
||||
err := os.MkdirAll(datapath, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
engine := control.Register("saucenao", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "搜图\n" +
|
||||
@@ -27,7 +38,7 @@ func init() { // 插件主体
|
||||
engine.OnRegex(`^搜图(\d+)$`).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
ctx.Send("少女祈祷中......")
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
// 获取P站插图信息
|
||||
illust, err := pixiv.Works(id)
|
||||
if err != nil {
|
||||
@@ -35,30 +46,48 @@ func init() { // 插件主体
|
||||
return
|
||||
}
|
||||
if illust.Pid > 0 {
|
||||
// 改用 i.pixiv.cat 镜像站
|
||||
link := illust.ImageUrls
|
||||
link = strings.ReplaceAll(link, "i.pximg.net", "i.pixiv.cat")
|
||||
// 发送搜索结果
|
||||
ctx.SendChain(
|
||||
message.Image(link),
|
||||
message.Text(
|
||||
"\n",
|
||||
"标题:", illust.Title, "\n",
|
||||
"插画ID:", illust.Pid, "\n",
|
||||
"画师:", illust.UserName, "\n",
|
||||
"画师ID:", illust.UserId, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
|
||||
),
|
||||
name := strconv.FormatInt(illust.Pid, 10)
|
||||
filepath := datapath + name
|
||||
switch {
|
||||
case file.IsExist(filepath + ".jpg"):
|
||||
filepath = "file:///" + filepath + ".jpg"
|
||||
case file.IsExist(filepath + ".png"):
|
||||
filepath = "file:///" + filepath + ".png"
|
||||
case file.IsExist(filepath + ".gif"):
|
||||
filepath = "file:///" + filepath + ".gif"
|
||||
default:
|
||||
filepath = ""
|
||||
}
|
||||
if filepath == "" {
|
||||
logrus.Debug("[sausenao]开始下载", name)
|
||||
filepath, err = pixiv.Download(illust.ImageUrls, datapath, name)
|
||||
if err == nil {
|
||||
filepath = "file:///" + filepath
|
||||
}
|
||||
}
|
||||
txt := message.Text(
|
||||
"标题:", illust.Title, "\n",
|
||||
"插画ID:", illust.Pid, "\n",
|
||||
"画师:", illust.UserName, "\n",
|
||||
"画师ID:", illust.UserId, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
|
||||
)
|
||||
if filepath != "" {
|
||||
// 发送搜索结果
|
||||
ctx.SendChain(message.Image(filepath), message.Text("\n"), txt)
|
||||
} else {
|
||||
// 图片下载失败,仅发送文字结果
|
||||
ctx.SendChain(txt)
|
||||
}
|
||||
} else {
|
||||
ctx.Send("图片不存在!")
|
||||
ctx.SendChain(message.Text("图片不存在!"))
|
||||
}
|
||||
})
|
||||
// 以图搜图
|
||||
engine.OnKeywordGroup([]string{"以图搜图", "搜索图片", "以图识图"}, picture.CmdMatch, picture.MustGiven).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 开始搜索图片
|
||||
ctx.Send("少女祈祷中......")
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
for _, pic := range ctx.State["image_url"].([]string) {
|
||||
fmt.Println(pic)
|
||||
if result, err := saucenao.SauceNAO(pic); err != nil {
|
||||
|
||||
@@ -18,13 +18,15 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/data"
|
||||
fileutil "github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
)
|
||||
|
||||
// Pools 图片缓冲池
|
||||
type imgpool struct {
|
||||
Lock sync.Mutex
|
||||
DB *data.Sqlite
|
||||
DB *sql.Sqlite
|
||||
Path string
|
||||
Group int64
|
||||
List []string
|
||||
@@ -40,7 +42,7 @@ const (
|
||||
// NewPoolsCache 返回一个缓冲池对象
|
||||
func newPools() *imgpool {
|
||||
cache := &imgpool{
|
||||
DB: &data.Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
|
||||
DB: &sql.Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
|
||||
Path: "data/SetuTime/cache/",
|
||||
Group: 0,
|
||||
List: []string{"涩图", "二次元", "风景", "车万"}, // 可以自己加类别,得自己加图片进数据库
|
||||
@@ -48,6 +50,8 @@ func newPools() *imgpool {
|
||||
Pool: map[string][]*pixiv.Illust{},
|
||||
Form: 0,
|
||||
}
|
||||
// 每次启动清理缓存
|
||||
os.RemoveAll(cache.Path)
|
||||
err := os.MkdirAll(cache.Path, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -104,7 +108,7 @@ func init() { // 插件主体
|
||||
var imgtype = ctx.State["regex_matched"].([]string)[1]
|
||||
// 补充池子
|
||||
go func() {
|
||||
times := min(pool.Max-pool.size(imgtype), 2)
|
||||
times := math.Min(pool.Max-pool.size(imgtype), 2)
|
||||
for i := 0; i < times; i++ {
|
||||
illust := &pixiv.Illust{}
|
||||
// 查询出一张图片
|
||||
@@ -120,7 +124,6 @@ func init() { // 插件主体
|
||||
ctx.SendGroupMessage(pool.Group, []message.MessageSegment{message.Image(file(illust))})
|
||||
// 向缓冲池添加一张图片
|
||||
pool.push(imgtype, illust)
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
}()
|
||||
@@ -167,7 +170,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send("添加成功")
|
||||
ctx.SendChain(message.Text("添加成功"))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^删除(.*?)(\d+)$`, firstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
|
||||
@@ -178,10 +181,10 @@ func init() { // 插件主体
|
||||
)
|
||||
// 查询数据库
|
||||
if err := pool.DB.Del(imgtype, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send("删除成功")
|
||||
ctx.SendChain(message.Text("删除成功"))
|
||||
})
|
||||
|
||||
// 查询数据库涩图数量
|
||||
@@ -198,7 +201,7 @@ func init() { // 插件主体
|
||||
state = append(state, ": ")
|
||||
state = append(state, fmt.Sprintf("%d", num))
|
||||
}
|
||||
ctx.Send(strings.Join(state, ""))
|
||||
ctx.SendChain(message.Text(state))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -215,18 +218,6 @@ func firstValueInList(list []string) zero.Rule {
|
||||
}
|
||||
}
|
||||
|
||||
// min 返回两数最小值
|
||||
func min(a, b int) int {
|
||||
switch {
|
||||
default:
|
||||
return a
|
||||
case a > b:
|
||||
return b
|
||||
case a < b:
|
||||
return a
|
||||
}
|
||||
}
|
||||
|
||||
// size 返回缓冲池指定类型的现有大小
|
||||
func (p *imgpool) size(imgtype string) int {
|
||||
return len(p.Pool[imgtype])
|
||||
@@ -259,8 +250,7 @@ func (p *imgpool) pop(imgtype string) (illust *pixiv.Illust) {
|
||||
|
||||
func file(i *pixiv.Illust) string {
|
||||
filename := fmt.Sprint(i.Pid)
|
||||
pwd, _ := os.Getwd()
|
||||
filepath := pwd + `/` + pool.Path + filename
|
||||
filepath := fileutil.BOT_PATH + `/` + pool.Path + filename
|
||||
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
|
||||
return `file:///` + filepath + ".jpg"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/*
|
||||
* @Author: Kanri
|
||||
* @Date: 2021-10-15 21:23:14
|
||||
* @LastEditors: Kanri
|
||||
* @LastEditTime: 2021-10-15 21:42:51
|
||||
* @Description:
|
||||
*/
|
||||
// Package shindan 基于 https://shindanmaker.com 的测定小功能
|
||||
package shindan
|
||||
|
||||
@@ -52,6 +59,7 @@ func handle(ctx *zero.Ctx) {
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
// TODO: 可注入
|
||||
ctx.Send(text)
|
||||
}
|
||||
|
||||
|
||||
11
utils/file/dir_nowin.go
Normal file
11
utils/file/dir_nowin.go
Normal file
@@ -0,0 +1,11 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package file
|
||||
|
||||
import "os"
|
||||
|
||||
func Pwd() (path string) {
|
||||
path, _ = os.Getwd()
|
||||
return
|
||||
}
|
||||
14
utils/file/dir_win.go
Normal file
14
utils/file/dir_win.go
Normal file
@@ -0,0 +1,14 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Pwd() string {
|
||||
path, _ := os.Getwd()
|
||||
return strings.ReplaceAll(path, "\\", "/")
|
||||
}
|
||||
23
utils/file/dl.go
Normal file
23
utils/file/dl.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Package file 文件实用工具
|
||||
package file
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
// DownloadTo 下载到路径
|
||||
func DownloadTo(url, file string) error {
|
||||
resp, err := http.Get(url)
|
||||
if err == nil {
|
||||
var f *os.File
|
||||
f, err = os.Create(file)
|
||||
if err == nil {
|
||||
_, err = io.Copy(f, resp.Body)
|
||||
resp.Body.Close()
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
17
utils/file/f.go
Normal file
17
utils/file/f.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package file
|
||||
|
||||
import "os"
|
||||
|
||||
var BOT_PATH = Pwd()
|
||||
|
||||
// IsExist 文件/路径存在
|
||||
func IsExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
// IsExist 文件/路径不存在
|
||||
func IsNotExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err != nil && os.IsNotExist(err)
|
||||
}
|
||||
18
utils/math/math.go
Normal file
18
utils/math/math.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Package math 计算实用工具
|
||||
package math
|
||||
|
||||
// Max 返回两数最大值,该函数将被内联
|
||||
func Max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Min 返回两数最小值,该函数将被内联
|
||||
func Min(a, b int) int {
|
||||
if a > b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Package data 数据库/数据处理相关工具
|
||||
package data
|
||||
// Package sql 数据库/数据处理相关工具
|
||||
package sql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
Reference in New Issue
Block a user