mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 22:00:11 +08:00
Compare commits
No commits in common. "master" and "v1.9.8" have entirely different histories.
4
.github/workflows/gomod2nix.yml
vendored
4
.github/workflows/gomod2nix.yml
vendored
@ -18,12 +18,10 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@master
|
uses: actions/setup-go@master
|
||||||
with:
|
with:
|
||||||
go-version: "1.25"
|
go-version: "1.20"
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: gomod2nix update
|
- name: gomod2nix update
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
42
.github/workflows/nightly-docker.yml
vendored
Normal file
42
.github/workflows/nightly-docker.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
name: 打包最新版为 Docker Image
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
jobs:
|
||||||
|
docker-builder:
|
||||||
|
name: build docker
|
||||||
|
runs-on: ubuntu-23.04
|
||||||
|
steps:
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@master
|
||||||
|
- run: sudo apt-get install -y qemu-user-static
|
||||||
|
|
||||||
|
- name: Set up nix
|
||||||
|
uses: cachix/install-nix-action@v27
|
||||||
|
with:
|
||||||
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
|
extra_nix_config: |
|
||||||
|
sandbox = true
|
||||||
|
|
||||||
|
- name: Speed Up nix
|
||||||
|
uses: DeterminateSystems/magic-nix-cache-action@main
|
||||||
|
|
||||||
|
- name: build docker
|
||||||
|
run: |
|
||||||
|
mkdir output/
|
||||||
|
|
||||||
|
# https://discourse.nixos.org/t/nix-github-actions-aarch64/11034
|
||||||
|
nix build .#packages.aarch64-linux.docker_builder -o aarch64-linux.docker --print-out-paths --option system aarch64-linux --extra-platforms aarch64-linux
|
||||||
|
cp $(readlink aarch64-linux.docker) ./output/aarch64-linux.docker.tar.gz
|
||||||
|
|
||||||
|
nix build .#packages.x86_64-linux.docker_builder -o x86_64-linux.docker --print-out-paths --option system x86_64-linux --extra-platforms x86_64-linux
|
||||||
|
cp $(readlink x86_64-linux.docker) ./output/x86_64-linux.docker.tar.gz
|
||||||
|
|
||||||
|
# gomod2nix did not provide this
|
||||||
|
# nix build .#packages.i686-linux.docker_builder -o i686-linux.docker --print-out-paths --option system i686-linux --extra-platforms i686-linux
|
||||||
|
# cp $(readlink i686-linux.docker) ./output/i686-linux.docker.tar.gz
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@master
|
||||||
|
if: ${{ !github.head_ref }}
|
||||||
|
with:
|
||||||
|
path: output/
|
||||||
5
.github/workflows/nightly.yml
vendored
5
.github/workflows/nightly.yml
vendored
@ -27,12 +27,10 @@ jobs:
|
|||||||
fail-fast: true
|
fail-fast: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Setup Go environment
|
- name: Setup Go environment
|
||||||
uses: actions/setup-go@master
|
uses: actions/setup-go@master
|
||||||
with:
|
with:
|
||||||
go-version: '1.25'
|
go-version: '1.20'
|
||||||
- name: Cache downloaded module
|
- name: Cache downloaded module
|
||||||
uses: actions/cache@master
|
uses: actions/cache@master
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@ -47,7 +45,6 @@ jobs:
|
|||||||
GOARCH: ${{ matrix.goarch }}
|
GOARCH: ${{ matrix.goarch }}
|
||||||
IS_PR: ${{ !!github.head_ref }}
|
IS_PR: ${{ !!github.head_ref }}
|
||||||
run: |
|
run: |
|
||||||
GOOS= GOARCH= go generate ./...
|
|
||||||
if [ $GOOS = "windows" ]; then export BINARY_SUFFIX="$BINARY_SUFFIX.exe"; fi
|
if [ $GOOS = "windows" ]; then export BINARY_SUFFIX="$BINARY_SUFFIX.exe"; fi
|
||||||
if $IS_PR ; then echo $PR_PROMPT; fi
|
if $IS_PR ; then echo $PR_PROMPT; fi
|
||||||
export BINARY_NAME="$BINARY_PREFIX$GOOS_$GOARCH$BINARY_SUFFIX"
|
export BINARY_NAME="$BINARY_PREFIX$GOOS_$GOARCH$BINARY_SUFFIX"
|
||||||
|
|||||||
7
.github/workflows/pull.yml
vendored
7
.github/workflows/pull.yml
vendored
@ -26,18 +26,15 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@master
|
uses: actions/setup-go@master
|
||||||
with:
|
with:
|
||||||
go-version: '1.24'
|
go-version: '1.20'
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Tidy Modules
|
- name: Tidy Modules
|
||||||
run: |
|
run: go mod tidy
|
||||||
go mod tidy
|
|
||||||
go generate main.go
|
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@master
|
uses: golangci/golangci-lint-action@master
|
||||||
|
|||||||
8
.github/workflows/push.yml
vendored
8
.github/workflows/push.yml
vendored
@ -8,17 +8,13 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@master
|
uses: actions/setup-go@master
|
||||||
with:
|
with:
|
||||||
go-version: '1.24'
|
go-version: '1.20'
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Tidy Modules
|
- name: Tidy Modules
|
||||||
run: |
|
run: go mod tidy
|
||||||
go mod tidy
|
|
||||||
go generate main.go
|
|
||||||
|
|
||||||
- name: Run Lint
|
- name: Run Lint
|
||||||
uses: golangci/golangci-lint-action@master
|
uses: golangci/golangci-lint-action@master
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@master
|
uses: actions/setup-go@master
|
||||||
with:
|
with:
|
||||||
go-version: '1.25'
|
go-version: '1.20'
|
||||||
|
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@master
|
uses: goreleaser/goreleaser-action@master
|
||||||
|
|||||||
@ -56,7 +56,7 @@ run:
|
|||||||
deadline: 5m
|
deadline: 5m
|
||||||
issues-exit-code: 1
|
issues-exit-code: 1
|
||||||
tests: false
|
tests: false
|
||||||
go: '1.24'
|
go: '1.20'
|
||||||
|
|
||||||
# output configuration options
|
# output configuration options
|
||||||
output:
|
output:
|
||||||
@ -64,12 +64,12 @@ output:
|
|||||||
- format: "colored-line-number"
|
- format: "colored-line-number"
|
||||||
print-issued-lines: true
|
print-issued-lines: true
|
||||||
print-linter-name: true
|
print-linter-name: true
|
||||||
|
uniq-by-line: true
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
# Fix found issues (if it's supported by the linter)
|
# Fix found issues (if it's supported by the linter)
|
||||||
fix: true
|
fix: true
|
||||||
exclude-use-default: false
|
exclude-use-default: false
|
||||||
uniq-by-line: true
|
|
||||||
exclude:
|
exclude:
|
||||||
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Seek|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Seek|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
||||||
- 'identifier ".*" contain non-ASCII character: U\+.*'
|
- 'identifier ".*" contain non-ASCII character: U\+.*'
|
||||||
|
|||||||
@ -4,7 +4,6 @@ env:
|
|||||||
before:
|
before:
|
||||||
hooks:
|
hooks:
|
||||||
- go mod tidy
|
- go mod tidy
|
||||||
- go generate ./...
|
|
||||||
- go install github.com/tc-hib/go-winres@latest
|
- go install github.com/tc-hib/go-winres@latest
|
||||||
- go-winres make
|
- go-winres make
|
||||||
builds:
|
builds:
|
||||||
|
|||||||
147
README.md
147
README.md
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
[](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin)
|
[](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin)
|
||||||
[](https://t.me/zerobotplugin)
|
[](https://t.me/zerobotplugin)
|
||||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -192,18 +192,6 @@ zerobot [-h] [-m] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w]
|
|||||||
|
|
||||||
- [x] 早安 | 晚安
|
- [x] 早安 | 晚安
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>违禁词检测</summary>
|
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/antiabuse"
|
|
||||||
`
|
|
||||||
- [x] 添加违禁词
|
|
||||||
|
|
||||||
- [x] 删除违禁词
|
|
||||||
|
|
||||||
- [x] 查看违禁词
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>ATRI</summary>
|
<summary>ATRI</summary>
|
||||||
@ -268,8 +256,6 @@ zerobot [-h] [-m] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w]
|
|||||||
|
|
||||||
- [x] 赞我
|
- [x] 赞我
|
||||||
|
|
||||||
- [x] 群签到
|
|
||||||
|
|
||||||
- [x] [开启 | 关闭]入群验证
|
- [x] [开启 | 关闭]入群验证
|
||||||
|
|
||||||
- [x] [开启 | 关闭]gist加群自动审批
|
- [x] [开启 | 关闭]gist加群自动审批
|
||||||
@ -290,20 +276,6 @@ zerobot [-h] [-m] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w]
|
|||||||
|
|
||||||
- 设置欢迎语可选添加参数说明:{at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名
|
- 设置欢迎语可选添加参数说明:{at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>群应用:AI声聊</summary>
|
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/airecord"`
|
|
||||||
|
|
||||||
- [x] 设置AI语音群号1048452984(tips:机器人任意所在群聊即可)
|
|
||||||
|
|
||||||
- [x] 设置AI语音模型
|
|
||||||
|
|
||||||
- [x] 查看AI语音配置
|
|
||||||
|
|
||||||
- [x] 发送AI语音xxx
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>定时指令触发器</summary>
|
<summary>定时指令触发器</summary>
|
||||||
@ -412,18 +384,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
- [x] 设置默认限速为每 m [分钟 | 秒] n 次触发
|
- [x] 设置默认限速为每 m [分钟 | 秒] n 次触发
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>aiimage</summary>
|
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiimage"`
|
|
||||||
|
|
||||||
- [x] 设置AI画图密钥xxx
|
|
||||||
- [x] 设置AI画图接口地址https://api.siliconflow.cn/v1/images/generations
|
|
||||||
- [x] 设置AI画图模型名Kwai-Kolors/Kolors
|
|
||||||
- [x] 查看AI画图配置
|
|
||||||
- [x] AI画图 [描述]
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>AIWife</summary>
|
<summary>AIWife</summary>
|
||||||
@ -571,7 +531,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
<details>
|
<details>
|
||||||
<summary>b站动态、专栏、视频、直播解析</summary>
|
<summary>b站动态、专栏、视频、直播解析</summary>
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibiliparse"`
|
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili"`
|
||||||
|
|
||||||
- [x] t.bilibili.com/642277677329285174 | bilibili.com/read/cv17134450 | bilibili.com/video/BV13B4y1x7pS | live.bilibili.com/22603245
|
- [x] t.bilibili.com/642277677329285174 | bilibili.com/read/cv17134450 | bilibili.com/video/BV13B4y1x7pS | live.bilibili.com/22603245
|
||||||
|
|
||||||
@ -579,7 +539,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
<details>
|
<details>
|
||||||
<summary>b站动态、直播推送,需要配合job一起使用</summary>
|
<summary>b站动态、直播推送,需要配合job一起使用</summary>
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibilipush"`
|
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili"`
|
||||||
|
|
||||||
- [x] 添加b站订阅[uid|name]
|
- [x] 添加b站订阅[uid|name]
|
||||||
|
|
||||||
@ -645,17 +605,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
- [x] 磕cp大老师 雪乃
|
- [x] 磕cp大老师 雪乃
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>奇怪语言加解密</summary>
|
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/crypter"`
|
|
||||||
|
|
||||||
- [x] 齁语加密 [文本] 或 h加密 [文本]
|
|
||||||
- [x] 齁语解密 [密文] 或 h解密 [密文]
|
|
||||||
- [x] fumo加密 [文本]
|
|
||||||
- [x] fumo解密 [文本]
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>今日早报</summary>
|
<summary>今日早报</summary>
|
||||||
@ -1078,10 +1027,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
- [x] 酷狗点歌[xxx]
|
- [x] 酷狗点歌[xxx]
|
||||||
|
|
||||||
- [x] qq点歌[xxx]
|
|
||||||
|
|
||||||
- [x] 咪咕点歌[xxx]
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>本地涩图</summary>
|
<summary>本地涩图</summary>
|
||||||
@ -1284,17 +1229,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
- [x] 打劫[对方Q号|@对方QQ]
|
- [x] 打劫[对方Q号|@对方QQ]
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>RSSHub</summary>
|
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/rsshub"`
|
|
||||||
|
|
||||||
- [x] 添加rsshub订阅-/bookfere/weekly
|
|
||||||
- [x] 删除rsshub订阅-/bookfere/weekly
|
|
||||||
- [x] 查看rsshub订阅列表
|
|
||||||
- [x] rsshub同步 (使用job执行定时任务------记录在"@every 10m"触发的指令)
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>在线代码运行</summary>
|
<summary>在线代码运行</summary>
|
||||||
@ -1473,6 +1407,50 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
- [x] 每日特惠
|
- [x] 每日特惠
|
||||||
</details>
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>百度文心AI</summary>
|
||||||
|
|
||||||
|
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI"`
|
||||||
|
|
||||||
|
基于百度文心API的一些功能
|
||||||
|
|
||||||
|
key申请链接:https://wenxin.baidu.com/moduleApi/key
|
||||||
|
|
||||||
|
- [x] 为[自己/本群/QQ号/群+群号]设置文心key [API Key] [Secret Key]
|
||||||
|
|
||||||
|
- [x] 为[自己/本群/QQ号/群+群号]设置画图key [API Key] [Secret Key]
|
||||||
|
|
||||||
|
例:“为10086设置画图key 123 456”;“为群10010设置画图key 789 101”
|
||||||
|
|
||||||
|
文心key和画图key的API key 可以是相同的,只是文心key日限为200,画图日限为50,以此作区别。
|
||||||
|
|
||||||
|
- [x] 文心作文 (x字的)[作文题目]
|
||||||
|
|
||||||
|
- [x] 文心提案 (x字的)[文案标题]
|
||||||
|
|
||||||
|
- [x] 文心摘要 (x字的)[文章内容]
|
||||||
|
|
||||||
|
- [x] 文心小说 (x字的)[小说上文]
|
||||||
|
|
||||||
|
- [x] 文心对联 [上联]
|
||||||
|
|
||||||
|
- [x] 文心问答 [问题]
|
||||||
|
|
||||||
|
- [x] 文心补全 [带“_”的填空题]
|
||||||
|
|
||||||
|
- [x] 文心自定义 [prompt]
|
||||||
|
|
||||||
|
- [x] [bot名称]画几张[图片描述]的[图片类型][图片尺寸]
|
||||||
|
|
||||||
|
指令示例:
|
||||||
|
|
||||||
|
- 文心作文 我的椛椛机器人
|
||||||
|
|
||||||
|
- 文心作文 300字的我的椛椛机器人
|
||||||
|
|
||||||
|
- 椛椛帮我画几张金凤凰,背景绚烂,高饱和,古风,仙境,高清,4K,古风的油画方图
|
||||||
|
|
||||||
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>抽老婆</summary>
|
<summary>抽老婆</summary>
|
||||||
|
|
||||||
@ -1486,7 +1464,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count"`
|
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count"`
|
||||||
|
|
||||||
- [x] 热词 [消息数目]|热词 1000
|
- [x] 热词 [群号] [消息数目]|热词 123456 1000
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
@ -1516,21 +1494,21 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>游戏王白鸽API卡查</summary>
|
<summary>一些游戏王插件</summary>
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygocdb"`
|
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo"`
|
||||||
|
|
||||||
|
##### 白鸽API卡查
|
||||||
|
|
||||||
|
###### `"github.com/FloatTech/ZeroBot-Plugin/plugin/ygo/ygocdb.go"`
|
||||||
- [x] /ydp [xxx]
|
- [x] /ydp [xxx]
|
||||||
- [x] /yds [xxx]
|
- [x] /yds [xxx]
|
||||||
- [x] /ydb [xxx]
|
- [x] /ydb [xxx]
|
||||||
- 注:[xxx]为搜索内容;p:返回一张图片;s:返回一张效果描述;b:高级搜索
|
- 注:[xxx]为搜索内容;p:返回一张图片;s:返回一张效果描述;b:高级搜索
|
||||||
|
|
||||||
</details>
|
##### 集换社卡价查询
|
||||||
<details>
|
|
||||||
<summary>游戏王集换社卡价查询</summary>
|
|
||||||
|
|
||||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygotrade"`
|
|
||||||
|
|
||||||
|
###### `"github.com/FloatTech/ZeroBot-Plugin/plugin/ygo/ygotrade.go"`
|
||||||
- [x] 查卡价 [卡名]
|
- [x] 查卡价 [卡名]
|
||||||
- [x] 查卡价 [卡名] -r [稀有度 稀有度 ...]
|
- [x] 查卡价 [卡名] -r [稀有度 稀有度 ...]
|
||||||
- [x] 查卡店 [卡名]
|
- [x] 查卡店 [卡名]
|
||||||
@ -1600,12 +1578,11 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
- [x] 设置AI聊天触发概率10
|
- [x] 设置AI聊天触发概率10
|
||||||
- [x] 设置AI聊天温度80
|
- [x] 设置AI聊天温度80
|
||||||
- [x] 设置AI聊天(识图|Agent)接口类型[OpenAI|OLLaMA|GenAI]
|
- [x] 设置AI聊天接口类型[OpenAI|OLLaMA|GenAI]
|
||||||
- [x] 设置AI聊天(不)使用Agent模式
|
|
||||||
- [x] 设置AI聊天(不)支持系统提示词
|
- [x] 设置AI聊天(不)支持系统提示词
|
||||||
- [x] 设置AI聊天(识图|Agent)接口地址https://api.siliconflow.cn/v1/chat/completions
|
- [x] 设置AI聊天接口地址https://xxx
|
||||||
- [x] 设置AI聊天(识图|Agent)密钥xxx
|
- [x] 设置AI聊天密钥xxx
|
||||||
- [x] 设置AI聊天(识图|Agent)模型名Qwen/Qwen3-8B
|
- [x] 设置AI聊天模型名xxx
|
||||||
- [x] 查看AI聊天系统提示词
|
- [x] 查看AI聊天系统提示词
|
||||||
- [x] 重置AI聊天系统提示词
|
- [x] 重置AI聊天系统提示词
|
||||||
- [x] 设置AI聊天系统提示词xxx
|
- [x] 设置AI聊天系统提示词xxx
|
||||||
@ -1613,11 +1590,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
- [x] 设置AI聊天(不)响应AT
|
- [x] 设置AI聊天(不)响应AT
|
||||||
- [x] 设置AI聊天最大长度4096
|
- [x] 设置AI聊天最大长度4096
|
||||||
- [x] 设置AI聊天TopP 0.9
|
- [x] 设置AI聊天TopP 0.9
|
||||||
- [x] 设置AI聊天(不)以AI语音输出
|
|
||||||
- [x] 查看AI聊天配置
|
|
||||||
- [x] 重置AI聊天
|
|
||||||
- [x] 群聊总结 [消息数目]|群聊总结 1000
|
|
||||||
- [x] /gpt [内容](使用大模型聊天)
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
@ -1685,7 +1657,6 @@ go version
|
|||||||
go env -w GOPROXY=https://goproxy.cn,direct
|
go env -w GOPROXY=https://goproxy.cn,direct
|
||||||
go env -w GO111MODULE=auto
|
go env -w GO111MODULE=auto
|
||||||
go mod tidy
|
go mod tidy
|
||||||
go generate main.go
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 编辑 main.go 文件,内容按需修改
|
3. 编辑 main.go 文件,内容按需修改
|
||||||
|
|||||||
@ -1,164 +0,0 @@
|
|||||||
// Package abineundo provides an explicit "from the beginning" (Latin: "ab ineundō")
|
|
||||||
// initialization anchor.
|
|
||||||
//
|
|
||||||
// Name origin:
|
|
||||||
//
|
|
||||||
// Latin phrase "ab ineundō" meaning "from which is to be begun".
|
|
||||||
//
|
|
||||||
// Purpose:
|
|
||||||
//
|
|
||||||
// Place this package at the very top of top-level main.go so its init (present
|
|
||||||
// or future) executes before other plugin packages, filling in a predictable
|
|
||||||
// plugin priority.
|
|
||||||
//
|
|
||||||
// Typical usage:
|
|
||||||
//
|
|
||||||
// import (
|
|
||||||
// _ "github.com/your/module/abineundo" // priority anchor
|
|
||||||
// // ... other imports ...
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// A blank identifier import preserves ordering side-effects without expanding the
|
|
||||||
// exported API surface.
|
|
||||||
//
|
|
||||||
// (No further code is required here; the package's presence alone defines ordering semantics.)
|
|
||||||
package abineundo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
_ "embed"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/FloatTech/zbputils/control"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed ref/main/main.go
|
|
||||||
var maincode string
|
|
||||||
|
|
||||||
//go:embed ref/custom/register.go
|
|
||||||
var customcode string
|
|
||||||
|
|
||||||
const (
|
|
||||||
statusnone = iota
|
|
||||||
statushigh
|
|
||||||
statushighend
|
|
||||||
statusmid
|
|
||||||
statusmidend
|
|
||||||
statuslow
|
|
||||||
statuslowend
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
priore = regexp.MustCompile(`^\t// -{28}(高|中|低)优先级区-{28} //$`)
|
|
||||||
mainpluginre = regexp.MustCompile(`^\t_ "github\.com/FloatTech/ZeroBot-Plugin/plugin/(\w+)"\s+// `)
|
|
||||||
custpluginre = regexp.MustCompile(`^\t_ "github\.com/FloatTech/ZeroBot-Plugin/custom/plugin/(\w+)"\s+// `)
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
highprios := make([]string, 0, 64)
|
|
||||||
midprios := make([]string, 0, 64)
|
|
||||||
lowprios := make([]string, 0, 64)
|
|
||||||
|
|
||||||
status := statusnone
|
|
||||||
scanner := bufio.NewScanner(strings.NewReader(maincode))
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
|
|
||||||
prioword := ""
|
|
||||||
match := priore.FindStringSubmatch(line)
|
|
||||||
if len(match) > 1 {
|
|
||||||
prioword = match[1]
|
|
||||||
}
|
|
||||||
switch prioword {
|
|
||||||
case "高":
|
|
||||||
switch status {
|
|
||||||
case statusnone:
|
|
||||||
status = statushigh
|
|
||||||
case statushigh:
|
|
||||||
status = statushighend
|
|
||||||
default:
|
|
||||||
panic("unexpected")
|
|
||||||
}
|
|
||||||
case "中":
|
|
||||||
switch status {
|
|
||||||
case statushighend:
|
|
||||||
status = statusmid
|
|
||||||
case statusmid:
|
|
||||||
status = statusmidend
|
|
||||||
default:
|
|
||||||
panic("unexpected")
|
|
||||||
}
|
|
||||||
case "低":
|
|
||||||
switch status {
|
|
||||||
case statusmidend:
|
|
||||||
status = statuslow
|
|
||||||
case statuslow:
|
|
||||||
status = statuslowend
|
|
||||||
default:
|
|
||||||
panic("unexpected")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
switch status {
|
|
||||||
case statusnone: // 还未开始匹配
|
|
||||||
continue
|
|
||||||
case statuslowend: // 匹配已结束
|
|
||||||
break
|
|
||||||
default: // 继续匹配插件
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 在对应优先级区域内匹配插件
|
|
||||||
if matches := mainpluginre.FindStringSubmatch(line); len(matches) > 1 {
|
|
||||||
name := matches[1]
|
|
||||||
switch status {
|
|
||||||
case statushigh:
|
|
||||||
highprios = append(highprios, name)
|
|
||||||
case statusmid:
|
|
||||||
midprios = append(midprios, name)
|
|
||||||
case statuslow:
|
|
||||||
lowprios = append(lowprios, name)
|
|
||||||
default: // 在不该匹配到插件的区域匹配到
|
|
||||||
panic("unexpected")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
custprios := make([]string, 0, 64)
|
|
||||||
|
|
||||||
scanner = bufio.NewScanner(strings.NewReader(customcode))
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
|
|
||||||
if matches := custpluginre.FindStringSubmatch(line); len(matches) > 1 {
|
|
||||||
custprios = append(custprios, matches[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成最终插件优先级表
|
|
||||||
m := make(map[string]uint64, 4*(len(highprios)+len(midprios)+len(lowprios)+len(custprios)))
|
|
||||||
i := 0
|
|
||||||
for _, name := range highprios {
|
|
||||||
m[name] = (uint64(i) + 1) * 10
|
|
||||||
logrus.Debugln("[ab] set high plugin", name, "prio to", m[name])
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for _, name := range custprios {
|
|
||||||
m[name] = (uint64(i) + 1) * 10
|
|
||||||
logrus.Debugln("[ab] set cust plugin", name, "prio to", m[name])
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for _, name := range midprios {
|
|
||||||
m[name] = (uint64(i) + 1) * 10
|
|
||||||
logrus.Debugln("[ab] set mid plugin", name, "prio to", m[name])
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for _, name := range lowprios {
|
|
||||||
m[name] = (uint64(i) + 1) * 10
|
|
||||||
logrus.Debugln("[ab] set low plugin", name, "prio to", m[name])
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
control.LoadCustomPriority(m)
|
|
||||||
}
|
|
||||||
2
abineundo/ref/custom/.gitignore
vendored
2
abineundo/ref/custom/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
!.gitignore
|
|
||||||
*
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
// Package main generate necessary files that needed for compiling
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
root := flag.String("r", "", "project root dir")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
fi, err := os.Open(path.Join(*root, "main.go"))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fo, err := os.Create(path.Join(*root, "abineundo/ref/main/main.go"))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(fo, fi)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fi.Close()
|
|
||||||
fo.Close()
|
|
||||||
|
|
||||||
regf := path.Join(*root, "custom/register.go")
|
|
||||||
tgtf := path.Join(*root, "abineundo/ref/custom/register.go")
|
|
||||||
if _, err := os.Stat(regf); err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
_ = os.WriteFile(tgtf, []byte("// Package custom ...\npackage custom\n"), 0644)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fi, err = os.Open(regf)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fo, err = os.Create(tgtf)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(fo, fi)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fi.Close()
|
|
||||||
fo.Close()
|
|
||||||
}
|
|
||||||
2
abineundo/ref/main/.gitignore
vendored
2
abineundo/ref/main/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
!.gitignore
|
|
||||||
*
|
|
||||||
@ -38,18 +38,12 @@ func setConsoleTitle(title string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
debugMode := os.Getenv("DEBUG_MODE") == "1"
|
|
||||||
stdin := windows.Handle(os.Stdin.Fd())
|
stdin := windows.Handle(os.Stdin.Fd())
|
||||||
|
|
||||||
var mode uint32
|
var mode uint32
|
||||||
err := windows.GetConsoleMode(stdin, &mode)
|
err := windows.GetConsoleMode(stdin, &mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if debugMode {
|
panic(err)
|
||||||
logrus.Warnf("调试模式下忽略控制台模式获取失败: %v", err)
|
|
||||||
return // 调试模式下直接返回,跳过后续配置
|
|
||||||
} else {
|
|
||||||
panic(err) // 非调试模式下 panic
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mode &^= windows.ENABLE_QUICK_EDIT_MODE // 禁用快速编辑模式
|
mode &^= windows.ENABLE_QUICK_EDIT_MODE // 禁用快速编辑模式
|
||||||
|
|||||||
2
data
2
data
@ -1 +1 @@
|
|||||||
Subproject commit 1b0abcd3fe4943fa3298885cf0311e8d94a02c0b
|
Subproject commit 4f751a1cda692b5b8cb909ce1376a3a0ea0d57cc
|
||||||
99
go.mod
99
go.mod
@ -1,36 +1,36 @@
|
|||||||
module github.com/FloatTech/ZeroBot-Plugin
|
module github.com/FloatTech/ZeroBot-Plugin
|
||||||
|
|
||||||
go 1.24.2
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Baidu-AIP/golang-sdk v1.1.1
|
github.com/Baidu-AIP/golang-sdk v1.1.1
|
||||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20251028071248-0c948e3db65c
|
github.com/FloatTech/AnimeAPI v1.7.1-0.20250530055006-50f5c7587c5b
|
||||||
github.com/FloatTech/floatbox v0.0.0-20251002074805-f95cbc7edb31
|
github.com/FloatTech/floatbox v0.0.0-20250513111443-adba80e84e80
|
||||||
github.com/FloatTech/gg v1.1.3
|
github.com/FloatTech/gg v1.1.3
|
||||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef
|
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef
|
||||||
github.com/FloatTech/rendercard v0.2.0
|
github.com/FloatTech/rendercard v0.2.0
|
||||||
github.com/FloatTech/sqlite v1.7.2
|
github.com/FloatTech/sqlite v1.7.1
|
||||||
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d
|
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562
|
||||||
github.com/FloatTech/zbpctrl v1.7.0
|
github.com/FloatTech/zbpctrl v1.7.0
|
||||||
github.com/FloatTech/zbputils v1.7.2-0.20251002080916-b554b7039913
|
github.com/FloatTech/zbputils v1.7.2-0.20250601113004-1bee2a7cd4b6
|
||||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
|
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
|
||||||
github.com/RomiChan/websocket v1.4.3-0.20251002072000-d3eb41798438
|
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
|
||||||
github.com/Tnze/go-mc v1.20.2
|
github.com/Tnze/go-mc v1.20.2
|
||||||
github.com/antchfx/htmlquery v1.3.4
|
github.com/antchfx/htmlquery v1.3.4
|
||||||
github.com/corona10/goimagehash v1.1.0
|
github.com/corona10/goimagehash v1.1.0
|
||||||
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3
|
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/fumiama/ahsai v0.1.1
|
github.com/fumiama/ahsai v0.1.0
|
||||||
github.com/fumiama/cron v1.3.0
|
github.com/fumiama/cron v1.3.0
|
||||||
github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa
|
github.com/fumiama/deepinfra v0.0.0-20250601112706-0175c95164c1
|
||||||
github.com/fumiama/go-base16384 v1.7.0
|
github.com/fumiama/go-base16384 v1.7.0
|
||||||
github.com/fumiama/go-onebot-agent v0.0.0-20250926145606-37ebfa6131c8
|
|
||||||
github.com/fumiama/go-registry v0.2.7
|
github.com/fumiama/go-registry v0.2.7
|
||||||
github.com/fumiama/gotracemoe v0.0.3
|
github.com/fumiama/gotracemoe v0.0.3
|
||||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565
|
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565
|
||||||
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4
|
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4
|
||||||
github.com/fumiama/terasu v1.0.1
|
github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce
|
||||||
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6
|
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6
|
||||||
|
github.com/go-ego/gse v0.80.3
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/jinzhu/gorm v1.9.16
|
github.com/jinzhu/gorm v1.9.16
|
||||||
@ -38,68 +38,63 @@ require (
|
|||||||
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5
|
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5
|
||||||
github.com/lithammer/fuzzysearch v1.1.8
|
github.com/lithammer/fuzzysearch v1.1.8
|
||||||
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5
|
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5
|
||||||
github.com/mmcdole/gofeed v1.3.0
|
|
||||||
github.com/mroth/weightedrand v1.0.0
|
github.com/mroth/weightedrand v1.0.0
|
||||||
github.com/notnil/chess v1.10.0
|
github.com/notnil/chess v1.9.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/shirou/gopsutil/v4 v4.25.11
|
github.com/shirou/gopsutil/v3 v3.24.5
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/tidwall/gjson v1.18.0
|
github.com/tidwall/gjson v1.18.0
|
||||||
github.com/wcharczuk/go-chart/v2 v2.1.2
|
github.com/wcharczuk/go-chart/v2 v2.1.2
|
||||||
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20251002074418-56567b7fc282
|
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250330133859-27c25d9412b5
|
||||||
gitlab.com/gomidi/midi/v2 v2.3.16
|
gitlab.com/gomidi/midi/v2 v2.1.7
|
||||||
golang.org/x/image v0.32.0
|
golang.org/x/image v0.24.0
|
||||||
golang.org/x/sys v0.38.0
|
golang.org/x/sys v0.30.0
|
||||||
golang.org/x/text v0.30.0
|
golang.org/x/text v0.22.0
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/PuerkitoBio/goquery v1.10.3 // indirect
|
|
||||||
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
|
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
|
||||||
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect
|
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca // indirect
|
||||||
github.com/andybalholm/cascadia v1.3.3 // indirect
|
github.com/antchfx/xpath v1.3.3 // indirect
|
||||||
github.com/antchfx/xpath v1.3.5 // indirect
|
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/ebitengine/oto/v3 v3.4.0 // indirect
|
|
||||||
github.com/ebitengine/purego v0.9.1 // indirect
|
|
||||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
||||||
|
github.com/faiface/beep v1.1.0 // indirect
|
||||||
github.com/fumiama/go-simple-protobuf v0.2.0 // indirect
|
github.com/fumiama/go-simple-protobuf v0.2.0 // indirect
|
||||||
github.com/fumiama/gofastTEA v0.1.3 // indirect
|
github.com/fumiama/gofastTEA v0.0.10 // indirect
|
||||||
github.com/fumiama/imgsz v0.0.4 // indirect
|
github.com/fumiama/imgsz v0.0.2 // indirect
|
||||||
github.com/fumiama/orbyte v0.0.0-20251002065953-3bb358367eb5 // indirect
|
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/hajimehoshi/oto v0.7.1 // indirect
|
||||||
github.com/gopxl/beep/v2 v2.1.1 // indirect
|
github.com/jfreymuth/oggvorbis v1.0.1 // indirect
|
||||||
github.com/jfreymuth/oggvorbis v1.0.5 // indirect
|
github.com/jfreymuth/vorbis v1.0.0 // indirect
|
||||||
github.com/jfreymuth/vorbis v1.0.2 // indirect
|
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
|
||||||
github.com/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
|
github.com/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
|
||||||
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d // indirect
|
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mmcdole/goxpp v1.1.1 // indirect
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
|
||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||||
github.com/pkumza/numcn v1.0.0 // indirect
|
github.com/pkumza/numcn v1.0.0 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/tetratelabs/wazero v1.9.0 // indirect
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/tidwall/match v1.2.0 // indirect
|
github.com/tetratelabs/wazero v1.5.0 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
github.com/tidwall/pretty v1.2.0 // indirect
|
||||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||||
|
github.com/vcaesar/cedar v0.20.2 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
golang.org/x/net v0.46.0 // indirect
|
golang.org/x/exp/shiny v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a // indirect
|
||||||
modernc.org/libc v1.66.10 // indirect
|
golang.org/x/net v0.33.0 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/libc v1.61.0 // indirect
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
modernc.org/sqlite v1.39.1 // indirect
|
modernc.org/memory v1.8.0 // indirect
|
||||||
|
modernc.org/sqlite v1.33.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace modernc.org/sqlite => github.com/fumiama/sqlite3 v1.29.10-simp
|
replace modernc.org/sqlite => github.com/fumiama/sqlite3 v1.29.10-simp
|
||||||
|
|||||||
252
go.sum
252
go.sum
@ -1,50 +1,43 @@
|
|||||||
github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhvrx4cw=
|
github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhvrx4cw=
|
||||||
github.com/Baidu-AIP/golang-sdk v1.1.1/go.mod h1:bXnGw7xPeKt8aF7UCELKrV6UZ/46spItONK1RQBQj1Y=
|
github.com/Baidu-AIP/golang-sdk v1.1.1/go.mod h1:bXnGw7xPeKt8aF7UCELKrV6UZ/46spItONK1RQBQj1Y=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20251028071248-0c948e3db65c h1:fmvlRUzwoK6KdoRSW+XeTQ9myKHimd0pV6GbmRJLNRo=
|
github.com/FloatTech/AnimeAPI v1.7.1-0.20250530055006-50f5c7587c5b h1:H/1xpchTGmdoHqrszH4gjafCyHIhsGSFryAkBNsu8OI=
|
||||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20251028071248-0c948e3db65c/go.mod h1:cuDd67B23xmICSmFBhWzXN51blod2BlM1liN9Ux0pSc=
|
github.com/FloatTech/AnimeAPI v1.7.1-0.20250530055006-50f5c7587c5b/go.mod h1:XXG1eBJf+eeWacQx5azsQKL5Gg7jDYTFyyZGIa/56js=
|
||||||
github.com/FloatTech/floatbox v0.0.0-20251002074805-f95cbc7edb31 h1:2K+/M64ixD1Pg5hr00Nbxr7GoWQOgahvpmp1pAMnrYc=
|
github.com/FloatTech/floatbox v0.0.0-20250513111443-adba80e84e80 h1:lFD1pd8NkYCrw0QpTX/T5pJ67I7AL5eGxQ4v0r9f81Q=
|
||||||
github.com/FloatTech/floatbox v0.0.0-20251002074805-f95cbc7edb31/go.mod h1:kf+Ywc2lk8PLdg3RX0vrUmFLPO6k+23MFmt4GviV8C0=
|
github.com/FloatTech/floatbox v0.0.0-20250513111443-adba80e84e80/go.mod h1:IWoFFqu+0FeaHHQdddyiTRL5z7gJME6qHC96qh0R2sc=
|
||||||
github.com/FloatTech/gg v1.1.3 h1:+GlL02lTKsxJQr4WCuNwVxC1/eBZrCvypCIBtxuOFb4=
|
github.com/FloatTech/gg v1.1.3 h1:+GlL02lTKsxJQr4WCuNwVxC1/eBZrCvypCIBtxuOFb4=
|
||||||
github.com/FloatTech/gg v1.1.3/go.mod h1:/9oLP54CMfq4r+71XL26uaFTJ1uL1boAyX67680/1HE=
|
github.com/FloatTech/gg v1.1.3/go.mod h1:/9oLP54CMfq4r+71XL26uaFTJ1uL1boAyX67680/1HE=
|
||||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef h1:CJbK/2FRwPuZpeb6M4sWK2d7oXDnBEGhpkQuQrgc91A=
|
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef h1:CJbK/2FRwPuZpeb6M4sWK2d7oXDnBEGhpkQuQrgc91A=
|
||||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
|
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
|
||||||
github.com/FloatTech/rendercard v0.2.0 h1:PBTZ2gCEy/dAEGSfWecrGTrWDYpiBJD1dVzNDDaOxh4=
|
github.com/FloatTech/rendercard v0.2.0 h1:PBTZ2gCEy/dAEGSfWecrGTrWDYpiBJD1dVzNDDaOxh4=
|
||||||
github.com/FloatTech/rendercard v0.2.0/go.mod h1:Sbojcy1t3NfFz7/WicZRmR/uKFxNMYkKF8qHx69dxY0=
|
github.com/FloatTech/rendercard v0.2.0/go.mod h1:Sbojcy1t3NfFz7/WicZRmR/uKFxNMYkKF8qHx69dxY0=
|
||||||
github.com/FloatTech/sqlite v1.7.2 h1:b8COegNLSzofzOyARsVwSbz9OOzWEa8IElsTlx1TBLw=
|
github.com/FloatTech/sqlite v1.7.1 h1:XKUY0+MNaRmvEIgRv7QLbl7PFVpUfQ72+XQg+no2Vq0=
|
||||||
github.com/FloatTech/sqlite v1.7.2/go.mod h1:/4tzfCGhrZnnjC1U8vcfwGQeF6eR649fhOsS3+Le0+s=
|
github.com/FloatTech/sqlite v1.7.1/go.mod h1:/4tzfCGhrZnnjC1U8vcfwGQeF6eR649fhOsS3+Le0+s=
|
||||||
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d h1:mUQ/c3wXKsUGa4Sg9DBy01APXKB68PmobhxOyaJI7lY=
|
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562 h1:snfw7FNFym1eNnLrQ/VCf80LiQo9C7jHgrunZDwiRcY=
|
||||||
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||||
github.com/FloatTech/zbpctrl v1.7.0 h1:Hxo6EIhJo+pHjcQP9QgIJgluaT1pHH99zkk3njqTNMo=
|
github.com/FloatTech/zbpctrl v1.7.0 h1:Hxo6EIhJo+pHjcQP9QgIJgluaT1pHH99zkk3njqTNMo=
|
||||||
github.com/FloatTech/zbpctrl v1.7.0/go.mod h1:xmM4dSwHA02Gei3ogCRiG+RTrw/7Z69PfrN5NYf8BPE=
|
github.com/FloatTech/zbpctrl v1.7.0/go.mod h1:xmM4dSwHA02Gei3ogCRiG+RTrw/7Z69PfrN5NYf8BPE=
|
||||||
github.com/FloatTech/zbputils v1.7.2-0.20251002080916-b554b7039913 h1:uGexKAPL26sAWGemyHbfkjYyzFItMsbI8EREBLSZ/sU=
|
github.com/FloatTech/zbputils v1.7.2-0.20250601113004-1bee2a7cd4b6 h1:85LGKvgkWMZU065WOIEVaaeHDNYK01CwdNr/m+jzTKw=
|
||||||
github.com/FloatTech/zbputils v1.7.2-0.20251002080916-b554b7039913/go.mod h1:mNvv0+wCou042n/3QkK23WmbayNctT5wgkKC3A6nbmM=
|
github.com/FloatTech/zbputils v1.7.2-0.20250601113004-1bee2a7cd4b6/go.mod h1:ArZ0fMAcmPEIXOqDmfzbSx+oYH8sssApQnbCu694iS8=
|
||||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||||
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
|
|
||||||
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
|
|
||||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
|
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
|
||||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
||||||
github.com/RomiChan/websocket v1.4.3-0.20251002072000-d3eb41798438 h1:I0bdwHZ+2DY45b39xPoTD2u+Z8zhvBuu9aZfjMZeiZM=
|
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5 h1:bBmmB7he0iVN4m5mcehfheeRUEer/Avo4ujnxI3uCqs=
|
||||||
github.com/RomiChan/websocket v1.4.3-0.20251002072000-d3eb41798438/go.mod h1:GO+9i5UYB4BuZEel6BfGx7O1u3ggwgZWUnGxPATUoTE=
|
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5/go.mod h1:0UcFaCkhp6vZw6l5Dpq0Dp673CoF9GdvA8lTfst0GiU=
|
||||||
github.com/Tnze/go-mc v1.20.2 h1:arHCE/WxLCxY73C/4ZNLdOymRYtdwoXE05ohB7HVN6Q=
|
github.com/Tnze/go-mc v1.20.2 h1:arHCE/WxLCxY73C/4ZNLdOymRYtdwoXE05ohB7HVN6Q=
|
||||||
github.com/Tnze/go-mc v1.20.2/go.mod h1:geoRj2HsXSkB3FJBuhr7wCzXegRlzWsVXd7h7jiJ6aQ=
|
github.com/Tnze/go-mc v1.20.2/go.mod h1:geoRj2HsXSkB3FJBuhr7wCzXegRlzWsVXd7h7jiJ6aQ=
|
||||||
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d h1:ir/IFJU5xbja5UaBEQLjcvn7aAU01nqU/NUyOBEU+ew=
|
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d h1:ir/IFJU5xbja5UaBEQLjcvn7aAU01nqU/NUyOBEU+ew=
|
||||||
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d/go.mod h1:PRWNwWq0yifz6XDPZu48aSld8BWwBfr2JKB2bGWiEd4=
|
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d/go.mod h1:PRWNwWq0yifz6XDPZu48aSld8BWwBfr2JKB2bGWiEd4=
|
||||||
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
|
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca h1:kWzLcty5V2rzOqJM7Tp/MfSX0RMSI1x4IOLApEefYxA=
|
||||||
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
|
|
||||||
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
|
|
||||||
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
|
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
|
|
||||||
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
|
|
||||||
github.com/antchfx/htmlquery v1.3.4 h1:Isd0srPkni2iNTWCwVj/72t7uCphFeor5Q8nCzj1jdQ=
|
github.com/antchfx/htmlquery v1.3.4 h1:Isd0srPkni2iNTWCwVj/72t7uCphFeor5Q8nCzj1jdQ=
|
||||||
github.com/antchfx/htmlquery v1.3.4/go.mod h1:K9os0BwIEmLAvTqaNSua8tXLWRWZpocZIH73OzWQbwM=
|
github.com/antchfx/htmlquery v1.3.4/go.mod h1:K9os0BwIEmLAvTqaNSua8tXLWRWZpocZIH73OzWQbwM=
|
||||||
|
github.com/antchfx/xpath v1.3.3 h1:tmuPQa1Uye0Ym1Zn65vxPgfltWb/Lxu2jeqIGteJSRs=
|
||||||
github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||||
github.com/antchfx/xpath v1.3.5 h1:PqbXLC3TkfeZyakF5eeh3NTWEbYl4VHNVeufANzDbKQ=
|
|
||||||
github.com/antchfx/xpath v1.3.5/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
|
||||||
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
|
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
|
||||||
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||||
|
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -56,77 +49,77 @@ github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1
|
|||||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/ebitengine/oto/v3 v3.4.0 h1:br0PgASsEWaoWn38b2Goe7m1GKFYfNgnsjSd5Gg+/bQ=
|
|
||||||
github.com/ebitengine/oto/v3 v3.4.0/go.mod h1:IOleLVD0m+CMak3mRVwsYY8vTctQgOM0iiL6S7Ar7eI=
|
|
||||||
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
|
|
||||||
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
|
||||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
|
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
|
||||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
|
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
|
||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||||
github.com/fumiama/ahsai v0.1.1 h1:/t5tdKRim0TK6YwgNFQfqtDOW7Y2tFBsmdUWt3JK+C0=
|
github.com/faiface/beep v1.1.0 h1:A2gWP6xf5Rh7RG/p9/VAW2jRSDEGQm5sbOb38sf5d4c=
|
||||||
github.com/fumiama/ahsai v0.1.1/go.mod h1:rBhHLgN2bygcqLpBi+XQa8B8Afn4UkPHQ5vvQibdbDQ=
|
github.com/faiface/beep v1.1.0/go.mod h1:6I8p6kK2q4opL/eWb+kAkk38ehnTunWeToJB+s51sT4=
|
||||||
|
github.com/fumiama/ahsai v0.1.0 h1:LXD61Kaj6kJHa3AEGsLIfKNzcgaVxg7JB72OR4yNNZ4=
|
||||||
|
github.com/fumiama/ahsai v0.1.0/go.mod h1:fFeNnqgo44i8FIaguK659aQryuZeFy+4klYLQu/rfdk=
|
||||||
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
|
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
|
||||||
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
|
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
|
||||||
github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa h1:UMMNejpPp8dn92GPaVSZ2XKNSgp7+CVneOkZfExUilk=
|
github.com/fumiama/deepinfra v0.0.0-20250601112706-0175c95164c1 h1:qE3l/y4Y1gMD2NokQ5Nw4NIUjL8ZwYLPIHOExQNu4hM=
|
||||||
github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa/go.mod h1:uqsWK/GM9OvKV0pXZOQB63rWugBbiXInY8E1JoRKhkg=
|
github.com/fumiama/deepinfra v0.0.0-20250601112706-0175c95164c1/go.mod h1:wW05PQSn8mo1mZIoa6LBUE+3xIBjkoONvnfPTV5ZOhY=
|
||||||
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
|
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
|
||||||
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||||
github.com/fumiama/go-onebot-agent v0.0.0-20250926145606-37ebfa6131c8 h1:aXk5IVXvPy2IfajL6gH+V/6ZOVV1BBVKjnFISLvyw60=
|
|
||||||
github.com/fumiama/go-onebot-agent v0.0.0-20250926145606-37ebfa6131c8/go.mod h1:oH8DGDpRPjUAu8Fd/K+RxsB+z0Yis+BHeJAh+ZkO5EM=
|
|
||||||
github.com/fumiama/go-registry v0.2.7 h1:tLEqgEpsiybQMqBv0dLHm5leia/z1DhajMupwnOHeNs=
|
github.com/fumiama/go-registry v0.2.7 h1:tLEqgEpsiybQMqBv0dLHm5leia/z1DhajMupwnOHeNs=
|
||||||
github.com/fumiama/go-registry v0.2.7/go.mod h1:m+wp5fF8dYgVoFkBPZl+vlK90loymaJE0JCtocVQLEs=
|
github.com/fumiama/go-registry v0.2.7/go.mod h1:m+wp5fF8dYgVoFkBPZl+vlK90loymaJE0JCtocVQLEs=
|
||||||
github.com/fumiama/go-simple-protobuf v0.2.0 h1:ACyN1MAlu7pDR3EszWgzUeNP+IRsSHwH6V9JCJA5R5o=
|
github.com/fumiama/go-simple-protobuf v0.2.0 h1:ACyN1MAlu7pDR3EszWgzUeNP+IRsSHwH6V9JCJA5R5o=
|
||||||
github.com/fumiama/go-simple-protobuf v0.2.0/go.mod h1:5yYNapXq1tQMOZg9bOIVhQlZk9pQqpuFIO4DZLbsdy4=
|
github.com/fumiama/go-simple-protobuf v0.2.0/go.mod h1:5yYNapXq1tQMOZg9bOIVhQlZk9pQqpuFIO4DZLbsdy4=
|
||||||
github.com/fumiama/gofastTEA v0.1.3 h1:fxOi2D66knV6QN170hb59YiqxPhjlgizvBw+o0OjxUA=
|
github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoGhhQ=
|
||||||
github.com/fumiama/gofastTEA v0.1.3/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
|
github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
|
||||||
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
|
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
|
||||||
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
|
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
|
||||||
github.com/fumiama/imgsz v0.0.4 h1:Lsasu2hdSSFS+vnD+nvR1UkiRMK7hcpyYCC0FzgSMFI=
|
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
|
||||||
github.com/fumiama/imgsz v0.0.4/go.mod h1:bISOQVTlw9sRytPwe8ir7tAaEmyz9hSNj9n8mXMBG0E=
|
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
|
||||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 h1:sQuR2+N5HurnvsZhiKdEg+Ig354TaqgCQRxd/0KgIOQ=
|
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 h1:sQuR2+N5HurnvsZhiKdEg+Ig354TaqgCQRxd/0KgIOQ=
|
||||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565/go.mod h1:UUEvyLTJ7yoOA/viKG4wEis4ERydM7+Ny6gZUWgkS80=
|
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565/go.mod h1:UUEvyLTJ7yoOA/viKG4wEis4ERydM7+Ny6gZUWgkS80=
|
||||||
github.com/fumiama/libc v0.0.0-20240530081950-6f6d8586b5c5 h1:jDxsIupsT84A6WHcs6kWbst+KqrRQ8/o0VyoFMnbBOA=
|
github.com/fumiama/libc v0.0.0-20240530081950-6f6d8586b5c5 h1:jDxsIupsT84A6WHcs6kWbst+KqrRQ8/o0VyoFMnbBOA=
|
||||||
github.com/fumiama/libc v0.0.0-20240530081950-6f6d8586b5c5/go.mod h1:15P6ublJ9FJR8YQCGy8DeQ2Uwur7iW9Hserr/T3OFZE=
|
github.com/fumiama/libc v0.0.0-20240530081950-6f6d8586b5c5/go.mod h1:15P6ublJ9FJR8YQCGy8DeQ2Uwur7iW9Hserr/T3OFZE=
|
||||||
github.com/fumiama/orbyte v0.0.0-20251002065953-3bb358367eb5 h1:j9o0XVvdAeLwrBYMnh0SerrMc9CgNU6AGszbsvFzoc0=
|
|
||||||
github.com/fumiama/orbyte v0.0.0-20251002065953-3bb358367eb5/go.mod h1:FOjdw7KdCbK2eH3gRPhwFNCoXKpu9sN5vPH4El/8e0c=
|
|
||||||
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4 h1:zN9e09TYKXI1mNkuS6YbH+Sn+4k5tBir+ovhZZcRYAs=
|
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4 h1:zN9e09TYKXI1mNkuS6YbH+Sn+4k5tBir+ovhZZcRYAs=
|
||||||
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4/go.mod h1:iZf1H/Jcw5gjOOFb4C5nlweJtViWc7uwUxRCe14pbYk=
|
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4/go.mod h1:iZf1H/Jcw5gjOOFb4C5nlweJtViWc7uwUxRCe14pbYk=
|
||||||
github.com/fumiama/sqlite3 v1.29.10-simp h1:c5y3uKyU0q9t0/SyfynzYyuslQ5zP+5CD8e0yYY554A=
|
github.com/fumiama/sqlite3 v1.29.10-simp h1:c5y3uKyU0q9t0/SyfynzYyuslQ5zP+5CD8e0yYY554A=
|
||||||
github.com/fumiama/sqlite3 v1.29.10-simp/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA=
|
github.com/fumiama/sqlite3 v1.29.10-simp/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA=
|
||||||
github.com/fumiama/terasu v1.0.1 h1:WdP12r8xhRTyeCGWBtZx0QP0Eg5S3obJyS5MQVbBilE=
|
github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce h1:T6iDDU16rFyxV/FwfJJR6qcgkIlXJEIFlUTSmTD1h6s=
|
||||||
github.com/fumiama/terasu v1.0.1/go.mod h1:ksDiLG3X7RM+B9XW2qvP+v8PU8hv+xhN5vdJdLoBWX4=
|
github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce/go.mod h1:UVx8YP1jKKL1Cj+uy+OnQRM2Ih6U36Mqy9GSf7jabsI=
|
||||||
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6 h1:LtDgr628eji8jRpjPCxsk7ibjcfi97QieZVCTjxLCBw=
|
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6 h1:LtDgr628eji8jRpjPCxsk7ibjcfi97QieZVCTjxLCBw=
|
||||||
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6/go.mod h1:lEaZsT4FRSqcjnQ5q8y+mkenkzR/r1D3BJmfdp0vqDg=
|
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6/go.mod h1:lEaZsT4FRSqcjnQ5q8y+mkenkzR/r1D3BJmfdp0vqDg=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8=
|
||||||
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||||
|
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||||
|
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
|
||||||
|
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
|
||||||
|
github.com/go-ego/gse v0.80.3 h1:YNFkjMhlhQnUeuoFcUEd1ivh6SOB764rT8GDsEbDiEg=
|
||||||
|
github.com/go-ego/gse v0.80.3/go.mod h1:Gt3A9Ry1Eso2Kza4MRaiZ7f2DTAvActmETY46Lxg0gU=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gopxl/beep/v2 v2.1.1 h1:6FYIYMm2qPAdWkjX+7xwKrViS1x0Po5kDMdRkq8NVbU=
|
github.com/hajimehoshi/go-mp3 v0.3.0/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||||
github.com/gopxl/beep/v2 v2.1.1/go.mod h1:ZAm9TGQ9lvpoiFLd4zf5B1IuyxZhgRACMId1XJbaW0E=
|
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||||
github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ=
|
github.com/hajimehoshi/oto v0.7.1 h1:I7maFPz5MBCwiutOrz++DLdbr4rTzBsbBuV2VpgU9kk=
|
||||||
github.com/jfreymuth/oggvorbis v1.0.5/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos=
|
||||||
github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE=
|
github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
|
||||||
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
|
||||||
|
github.com/jfreymuth/oggvorbis v1.0.1 h1:NT0eXBgE2WHzu6RT/6zcb2H10Kxj6Fm3PccT0LE6bqw=
|
||||||
|
github.com/jfreymuth/oggvorbis v1.0.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk=
|
||||||
|
github.com/jfreymuth/vorbis v1.0.0 h1:SmDf783s82lIjGZi8EGUUaS7YxPHgRj4ZXW/h7rUi7U=
|
||||||
|
github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0=
|
||||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
@ -135,11 +128,8 @@ github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
|||||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
|
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
|
||||||
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
|
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
|
||||||
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5 h1:BXnB1Gz4y/zwQh+ZFNy7rgd+ZfMOrwRr4uZSHEI+ieY=
|
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5 h1:BXnB1Gz4y/zwQh+ZFNy7rgd+ZfMOrwRr4uZSHEI+ieY=
|
||||||
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5/go.mod h1:c9+VS9GaommgIOzNWb5ze4lYwfT8BZ2UDyGiuQTT7yc=
|
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5/go.mod h1:c9+VS9GaommgIOzNWb5ze4lYwfT8BZ2UDyGiuQTT7yc=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
|
||||||
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
|
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
|
||||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
||||||
@ -150,107 +140,105 @@ github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d h1:hTRDIpJ1FjS9ULJuEzu69n
|
|||||||
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d/go.mod h1:7xD3p0XnHvJFQ3t/stEJd877CSIMkH/fACVWen5pYnc=
|
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d/go.mod h1:7xD3p0XnHvJFQ3t/stEJd877CSIMkH/fACVWen5pYnc=
|
||||||
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5 h1:wnbHIeP1UX8ClYEWKGnw66PfYvReCHu9G5lXSte3Sqc=
|
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5 h1:wnbHIeP1UX8ClYEWKGnw66PfYvReCHu9G5lXSte3Sqc=
|
||||||
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5/go.mod h1:7KaV9YIR92M1FpbczAcfYQ3UZ5ayT27pNtunDmXvLBo=
|
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5/go.mod h1:7KaV9YIR92M1FpbczAcfYQ3UZ5ayT27pNtunDmXvLBo=
|
||||||
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k=
|
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||||
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
|
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
|
||||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||||
github.com/mmcdole/gofeed v1.3.0 h1:5yn+HeqlcvjMeAI4gu6T+crm7d0anY85+M+v6fIFNG4=
|
github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU=
|
||||||
github.com/mmcdole/gofeed v1.3.0/go.mod h1:9TGv2LcJhdXePDzxiuMnukhV2/zb6VtnZt1mS+SjkLE=
|
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA=
|
||||||
github.com/mmcdole/goxpp v1.1.1 h1:RGIX+D6iQRIunGHrKqnA2+700XMCnNv0bAOOv5MUhx8=
|
|
||||||
github.com/mmcdole/goxpp v1.1.1/go.mod h1:v+25+lT2ViuQ7mVxcncQ8ch1URund48oH+jhjiwEgS8=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
|
||||||
github.com/mroth/weightedrand v1.0.0 h1:V8JeHChvl2MP1sAoXq4brElOcza+jxLkRuwvtQu8L3E=
|
github.com/mroth/weightedrand v1.0.0 h1:V8JeHChvl2MP1sAoXq4brElOcza+jxLkRuwvtQu8L3E=
|
||||||
github.com/mroth/weightedrand v1.0.0/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
github.com/mroth/weightedrand v1.0.0/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||||
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/notnil/chess v1.10.0 h1:RR3MgS9G6zZmJ+VPTJolyxdaIgxoUPyUUY+2iaw35G0=
|
github.com/notnil/chess v1.9.0 h1:YMxR5kUVjtwcuFptGU0/3q7eG3MSHQNbg0VUekvRKV0=
|
||||||
github.com/notnil/chess v1.10.0/go.mod h1:cRuJUIBFq9Xki05TWHJxHYkC+fFpq45IWwk94DdlCrA=
|
github.com/notnil/chess v1.9.0/go.mod h1:cRuJUIBFq9Xki05TWHJxHYkC+fFpq45IWwk94DdlCrA=
|
||||||
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
|
|
||||||
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
|
|
||||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkumza/numcn v1.0.0 h1:ZT5cf9IJkUZgRgEtCiNNykk0RwsrKXSTsvDHOwUTzgE=
|
github.com/pkumza/numcn v1.0.0 h1:ZT5cf9IJkUZgRgEtCiNNykk0RwsrKXSTsvDHOwUTzgE=
|
||||||
github.com/pkumza/numcn v1.0.0/go.mod h1:QSeH+al9dWCd8di5HZM/ZqHqhZmUKfph572e9Ev/ETc=
|
github.com/pkumza/numcn v1.0.0/go.mod h1:QSeH+al9dWCd8di5HZM/ZqHqhZmUKfph572e9Ev/ETc=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/shirou/gopsutil/v4 v4.25.11 h1:X53gB7muL9Gnwwo2evPSE+SfOrltMoR6V3xJAXZILTY=
|
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||||
github.com/shirou/gopsutil/v4 v4.25.11/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
|
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||||
|
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||||
|
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||||
|
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08qYa0=
|
||||||
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
|
github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
||||||
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
|
|
||||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
|
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||||
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||||
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||||
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||||
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
github.com/vcaesar/cedar v0.20.2 h1:TDx7AdZhilKcfE1WvdToTJf5VrC/FXcUOW+KY1upLZ4=
|
||||||
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
|
github.com/vcaesar/cedar v0.20.2/go.mod h1:lyuGvALuZZDPNXwpzv/9LyxW+8Y6faN7zauFezNsnik=
|
||||||
|
github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4=
|
||||||
github.com/wcharczuk/go-chart/v2 v2.1.2 h1:Y17/oYNuXwZg6TFag06qe8sBajwwsuvPiJJXcUcLL6E=
|
github.com/wcharczuk/go-chart/v2 v2.1.2 h1:Y17/oYNuXwZg6TFag06qe8sBajwwsuvPiJJXcUcLL6E=
|
||||||
github.com/wcharczuk/go-chart/v2 v2.1.2/go.mod h1:Zi4hbaqlWpYajnXB2K22IUYVXRXaLfSGNNR7P4ukyyQ=
|
github.com/wcharczuk/go-chart/v2 v2.1.2/go.mod h1:Zi4hbaqlWpYajnXB2K22IUYVXRXaLfSGNNR7P4ukyyQ=
|
||||||
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20251002074418-56567b7fc282 h1:YctW/t88sQ0H8cJ69PWULU6xWfh8kNsX/XgCpW2OPHw=
|
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250330133859-27c25d9412b5 h1:HsMcBsVpYuQv+W8pjX5WdwYROrFQP9c5Pbf4x4adDus=
|
||||||
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20251002074418-56567b7fc282/go.mod h1:trueIIVRywKJa3ov4QphzVvzYzgCNrlXdf9JvPJOFW8=
|
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250330133859-27c25d9412b5/go.mod h1:C86nQ0gIdAri4K2vg8IIQIslt08zzrKMcqYt8zhkx1M=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
gitlab.com/gomidi/midi/v2 v2.3.16 h1:yufWSENyjnJ4LFQa9BerzUm4E4aLfTyzw5nmnCteO0c=
|
gitlab.com/gomidi/midi/v2 v2.1.7 h1:lIjVXH+bnGG04j/kUVOFILt0BQvBeGz8Kyz0l6aM830=
|
||||||
gitlab.com/gomidi/midi/v2 v2.3.16/go.mod h1:jDpP4O4skYi+7iVwt6Zyp18bd2M4hkjtMuw2cmgKgfw=
|
gitlab.com/gomidi/midi/v2 v2.1.7/go.mod h1:Cj6K9VH5GhYvPgL2JddxHBmZiP3nxKxB5XyTxiXvL9U=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
golang.org/x/exp/shiny v0.0.0-20250305212735-054e65f0b394 h1:bFYqOIMdeiCEdzPJkLiOoMDzW/v3tjW4AA/RmUZYsL8=
|
||||||
|
golang.org/x/exp/shiny v0.0.0-20250305212735-054e65f0b394/go.mod h1:ygj7T6vSGhhm/9yTpOQQNvuAUFziTH7RUiH74EoE2C8=
|
||||||
|
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||||
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=
|
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
||||||
golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc=
|
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a h1:sYbmY3FwUWCBTodZL1S3JUuOvaW6kM2o+clDzzDNBWg=
|
||||||
|
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a/go.mod h1:Ede7gF0KGoHlj822RtphAHK1jLdrcuRBZg0sF1Q+SPc=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
|
||||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
|
||||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
@ -258,41 +246,39 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
|
||||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@ -312,43 +298,31 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
|
||||||
modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk=
|
modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk=
|
||||||
modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
|
||||||
modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs=
|
modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs=
|
||||||
modernc.org/ccgo/v4 v4.17.8/go.mod h1:buJnJ6Fn0tyAdP/dqePbrrvLyr6qslFfTbFrCuaYvtA=
|
|
||||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
|
||||||
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
||||||
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||||
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
|
||||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
|
||||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
|
||||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
|
||||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
|
||||||
|
|||||||
198
gomod2nix.toml
198
gomod2nix.toml
@ -5,11 +5,11 @@ schema = 3
|
|||||||
version = "v1.1.1"
|
version = "v1.1.1"
|
||||||
hash = "sha256-hKshA0K92bKuK92mmtM0osVmqLJcSbeobeWSDpQoRCo="
|
hash = "sha256-hKshA0K92bKuK92mmtM0osVmqLJcSbeobeWSDpQoRCo="
|
||||||
[mod."github.com/FloatTech/AnimeAPI"]
|
[mod."github.com/FloatTech/AnimeAPI"]
|
||||||
version = "v1.7.1-0.20250926171956-ba37dfebfc4a"
|
version = "v1.7.1-0.20250530055006-50f5c7587c5b"
|
||||||
hash = "sha256-wtr9hgHSPsD5NqSmI3Lo8RVWE+cNMIUGo2bcsKTN8Gg="
|
hash = "sha256-xDXPwphMS26J02q/ysQy3CJPK5B9c7uoqwFt1xFIF5Q="
|
||||||
[mod."github.com/FloatTech/floatbox"]
|
[mod."github.com/FloatTech/floatbox"]
|
||||||
version = "v0.0.0-20251002074805-f95cbc7edb31"
|
version = "v0.0.0-20250513111443-adba80e84e80"
|
||||||
hash = "sha256-c50unGhF0JVPHN8geZM/YYQKgGqJgCtVksh4Ij1Pg+4="
|
hash = "sha256-Zt9zkUa3qqldrSttAq66YLPZPxrnkOR2MaU7oapIWEE="
|
||||||
[mod."github.com/FloatTech/gg"]
|
[mod."github.com/FloatTech/gg"]
|
||||||
version = "v1.1.3"
|
version = "v1.1.3"
|
||||||
hash = "sha256-7K/R2mKjUHVnoJ3b1wDObJ5Un2Htj59Y97G1Ja1tuPo="
|
hash = "sha256-7K/R2mKjUHVnoJ3b1wDObJ5Un2Htj59Y97G1Ja1tuPo="
|
||||||
@ -20,26 +20,23 @@ schema = 3
|
|||||||
version = "v0.2.0"
|
version = "v0.2.0"
|
||||||
hash = "sha256-fgntEYGh2mEl618hM13kb0GGeQEXdP+lochYX8F2OXs="
|
hash = "sha256-fgntEYGh2mEl618hM13kb0GGeQEXdP+lochYX8F2OXs="
|
||||||
[mod."github.com/FloatTech/sqlite"]
|
[mod."github.com/FloatTech/sqlite"]
|
||||||
version = "v1.7.2"
|
version = "v1.7.1"
|
||||||
hash = "sha256-R9QaP5FQwtWpHdbCoNX/rYOS/CgkIeRdFB9cwJ4n/JM="
|
hash = "sha256-1x8xH5fFDlLts8YfzgO3vLF45Q7Ah+mYI6Wn8JG/qE0="
|
||||||
[mod."github.com/FloatTech/ttl"]
|
[mod."github.com/FloatTech/ttl"]
|
||||||
version = "v0.0.0-20250224045156-012b1463287d"
|
version = "v0.0.0-20240716161252-965925764562"
|
||||||
hash = "sha256-C5xBt0roPgahradCOTgkhL+j5bvoSXmGwdqcu0aSczc="
|
hash = "sha256-/XjfdVXEzYgeM+OYuyy76tf13lO91vCcwpjWgkRGteU="
|
||||||
[mod."github.com/FloatTech/zbpctrl"]
|
[mod."github.com/FloatTech/zbpctrl"]
|
||||||
version = "v1.7.0"
|
version = "v1.7.0"
|
||||||
hash = "sha256-HDDnE0oktWJH1tkxuQwUUbeJhmVwY5fyc/vR72D2mkU="
|
hash = "sha256-HDDnE0oktWJH1tkxuQwUUbeJhmVwY5fyc/vR72D2mkU="
|
||||||
[mod."github.com/FloatTech/zbputils"]
|
[mod."github.com/FloatTech/zbputils"]
|
||||||
version = "v1.7.2-0.20251002080916-b554b7039913"
|
version = "v1.7.2-0.20250601113004-1bee2a7cd4b6"
|
||||||
hash = "sha256-9z7c79uuFl2LKaCgW1gQN5lmMjgKIcKrakcBlb3zJ90="
|
hash = "sha256-pNL591h1gGP60wKEuvvF3DoshbaphoLze7Pa7gDA9bQ="
|
||||||
[mod."github.com/PuerkitoBio/goquery"]
|
|
||||||
version = "v1.10.3"
|
|
||||||
hash = "sha256-Mth7nYm/MtcOhPMbHj7gXF+Mot7eDUBVN570RitGR/c="
|
|
||||||
[mod."github.com/RomiChan/syncx"]
|
[mod."github.com/RomiChan/syncx"]
|
||||||
version = "v0.0.0-20240418144900-b7402ffdebc7"
|
version = "v0.0.0-20240418144900-b7402ffdebc7"
|
||||||
hash = "sha256-L1j1vgiwqXpF9pjMoRRlrQUHzoULisw/01plaEAwxs4="
|
hash = "sha256-L1j1vgiwqXpF9pjMoRRlrQUHzoULisw/01plaEAwxs4="
|
||||||
[mod."github.com/RomiChan/websocket"]
|
[mod."github.com/RomiChan/websocket"]
|
||||||
version = "v1.4.3-0.20251002072000-d3eb41798438"
|
version = "v1.4.3-0.20220227141055-9b2c6168c9c5"
|
||||||
hash = "sha256-vLu9Va+9AbOIdh1LEetz5JlJK0P2IXKsYRvCdAO8tYw="
|
hash = "sha256-Adx+gvqB+CCoUXx7ebIaBDjVkav+wS5qZPmaqcApBWA="
|
||||||
[mod."github.com/Tnze/go-mc"]
|
[mod."github.com/Tnze/go-mc"]
|
||||||
version = "v1.20.2"
|
version = "v1.20.2"
|
||||||
hash = "sha256-Nu4PXNxeARH0itm6yIIplFaywL2yQnPJFksmmuyIptI="
|
hash = "sha256-Nu4PXNxeARH0itm6yIIplFaywL2yQnPJFksmmuyIptI="
|
||||||
@ -47,17 +44,14 @@ schema = 3
|
|||||||
version = "v0.0.0-20170805034717-80a9c64b256d"
|
version = "v0.0.0-20170805034717-80a9c64b256d"
|
||||||
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
|
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
|
||||||
[mod."github.com/ajstarks/svgo"]
|
[mod."github.com/ajstarks/svgo"]
|
||||||
version = "v0.0.0-20211024235047-1546f124cd8b"
|
version = "v0.0.0-20200320125537-f189e35d30ca"
|
||||||
hash = "sha256-sPwt5sImKFk949TzUeYEF2UiJDqHxXFJKRL2Y7JWJ6Y="
|
hash = "sha256-ALeRuEJN9jHjGb4wNKJcxC59vVx8Tj7hHikEGkaZZ0s="
|
||||||
[mod."github.com/andybalholm/cascadia"]
|
|
||||||
version = "v1.3.3"
|
|
||||||
hash = "sha256-jv7ZshpSd7FZzKKN6hqlUgiR8C3y85zNIS/hq7g76Ho="
|
|
||||||
[mod."github.com/antchfx/htmlquery"]
|
[mod."github.com/antchfx/htmlquery"]
|
||||||
version = "v1.3.4"
|
version = "v1.3.4"
|
||||||
hash = "sha256-nrtIgRgdOvo0iIQyrhHOFKOmoT8e2gduUsct3f5zDNA="
|
hash = "sha256-nrtIgRgdOvo0iIQyrhHOFKOmoT8e2gduUsct3f5zDNA="
|
||||||
[mod."github.com/antchfx/xpath"]
|
[mod."github.com/antchfx/xpath"]
|
||||||
version = "v1.3.5"
|
version = "v1.3.3"
|
||||||
hash = "sha256-AVM0rR81hgVAI0QVzlz4WijFUjByf6Zew3ZwuikKw2Q="
|
hash = "sha256-Ent9bgBTjKS8/61LKrIu/JcBI/Qsv6EEIojwsMjCgdY="
|
||||||
[mod."github.com/corona10/goimagehash"]
|
[mod."github.com/corona10/goimagehash"]
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
hash = "sha256-HyS8nc7kUNnDaVBDzJ9Ym4pRs83YB4M2vHSRwfm6mr4="
|
hash = "sha256-HyS8nc7kUNnDaVBDzJ9Ym4pRs83YB4M2vHSRwfm6mr4="
|
||||||
@ -70,30 +64,24 @@ schema = 3
|
|||||||
[mod."github.com/dustin/go-humanize"]
|
[mod."github.com/dustin/go-humanize"]
|
||||||
version = "v1.0.1"
|
version = "v1.0.1"
|
||||||
hash = "sha256-yuvxYYngpfVkUg9yAmG99IUVmADTQA0tMbBXe0Fq0Mc="
|
hash = "sha256-yuvxYYngpfVkUg9yAmG99IUVmADTQA0tMbBXe0Fq0Mc="
|
||||||
[mod."github.com/ebitengine/oto/v3"]
|
|
||||||
version = "v3.4.0"
|
|
||||||
hash = "sha256-8JU4iu+2pUKWVWMpEe8EAZ8FVo3MZdILu82vVVmDSVY="
|
|
||||||
[mod."github.com/ebitengine/purego"]
|
|
||||||
version = "v0.9.0"
|
|
||||||
hash = "sha256-jSlhGjhuYf15zHy7shSKR1rQN1sRyH5zXAzWqy+huHY="
|
|
||||||
[mod."github.com/ericpauley/go-quantize"]
|
[mod."github.com/ericpauley/go-quantize"]
|
||||||
version = "v0.0.0-20200331213906-ae555eb2afa4"
|
version = "v0.0.0-20200331213906-ae555eb2afa4"
|
||||||
hash = "sha256-sMN6D7IlDpDqUWM8ppoE5Sdb7DvLAJaN6qAucBWJ3rs="
|
hash = "sha256-sMN6D7IlDpDqUWM8ppoE5Sdb7DvLAJaN6qAucBWJ3rs="
|
||||||
|
[mod."github.com/faiface/beep"]
|
||||||
|
version = "v1.1.0"
|
||||||
|
hash = "sha256-66qAbnJjUjhXofxlGCa6G1+vjQcSTyN/POCZvYzHaQo="
|
||||||
[mod."github.com/fumiama/ahsai"]
|
[mod."github.com/fumiama/ahsai"]
|
||||||
version = "v0.1.1"
|
version = "v0.1.0"
|
||||||
hash = "sha256-knYw0R5fhjE/asc/TwlGJDzVr+Oaj8sH7kr7x6Mqs3E="
|
hash = "sha256-lSoos+SFjALcL0ZYPsbOb8wntwn2fcubvSsz0YKgL9c="
|
||||||
[mod."github.com/fumiama/cron"]
|
[mod."github.com/fumiama/cron"]
|
||||||
version = "v1.3.0"
|
version = "v1.3.0"
|
||||||
hash = "sha256-/sN7X8dKXQgv8J+EDzVUB+o+AY9gBC8e1C6sYhaTy1k="
|
hash = "sha256-/sN7X8dKXQgv8J+EDzVUB+o+AY9gBC8e1C6sYhaTy1k="
|
||||||
[mod."github.com/fumiama/deepinfra"]
|
[mod."github.com/fumiama/deepinfra"]
|
||||||
version = "v0.0.0-20250924162107-cf156d49a0fa"
|
version = "v0.0.0-20250601112706-0175c95164c1"
|
||||||
hash = "sha256-D0lgA7jBDLE8v9ePDiWwH439eB5+cDlj2fKRAc0wUms="
|
hash = "sha256-/8Hufq5n84QHOgS0igYQWo1zxjOBBbrqad2wQfKHBhY="
|
||||||
[mod."github.com/fumiama/go-base16384"]
|
[mod."github.com/fumiama/go-base16384"]
|
||||||
version = "v1.7.0"
|
version = "v1.7.0"
|
||||||
hash = "sha256-vTAsBBYe2ISzb2Nba5E96unodZSkhMcqo6hbwR01nz8="
|
hash = "sha256-vTAsBBYe2ISzb2Nba5E96unodZSkhMcqo6hbwR01nz8="
|
||||||
[mod."github.com/fumiama/go-onebot-agent"]
|
|
||||||
version = "v0.0.0-20250926145606-37ebfa6131c8"
|
|
||||||
hash = "sha256-oq1SSyddsXhsFvSHFhqSEAF9SH03b2jI0KvGbsFPXYQ="
|
|
||||||
[mod."github.com/fumiama/go-registry"]
|
[mod."github.com/fumiama/go-registry"]
|
||||||
version = "v0.2.7"
|
version = "v0.2.7"
|
||||||
hash = "sha256-Rjl+z0Hlp2LMi8+pnFe5HrxctyHMi7UPiK33g/OgLdA="
|
hash = "sha256-Rjl+z0Hlp2LMi8+pnFe5HrxctyHMi7UPiK33g/OgLdA="
|
||||||
@ -101,53 +89,53 @@ schema = 3
|
|||||||
version = "v0.2.0"
|
version = "v0.2.0"
|
||||||
hash = "sha256-2kULBi1sXsFDX2g/KRFmCGkwF60o/UXacNUbIYa/cvw="
|
hash = "sha256-2kULBi1sXsFDX2g/KRFmCGkwF60o/UXacNUbIYa/cvw="
|
||||||
[mod."github.com/fumiama/gofastTEA"]
|
[mod."github.com/fumiama/gofastTEA"]
|
||||||
version = "v0.1.3"
|
version = "v0.0.10"
|
||||||
hash = "sha256-/Qu57mkkFt7aFufhlkMYPgrWj5XCGbuM28EHDD8w4XY="
|
hash = "sha256-FOCbkXoS8s/K54yZbhX5pmaN/ouELnCHZoNS8a90VAg="
|
||||||
[mod."github.com/fumiama/gotracemoe"]
|
[mod."github.com/fumiama/gotracemoe"]
|
||||||
version = "v0.0.3"
|
version = "v0.0.3"
|
||||||
hash = "sha256-O3cDkVXu5NG1ZtzubxhH+S91zfgu4uH1L+OiSGYSNXQ="
|
hash = "sha256-O3cDkVXu5NG1ZtzubxhH+S91zfgu4uH1L+OiSGYSNXQ="
|
||||||
[mod."github.com/fumiama/imgsz"]
|
[mod."github.com/fumiama/imgsz"]
|
||||||
version = "v0.0.4"
|
version = "v0.0.2"
|
||||||
hash = "sha256-rrGx+v41OEl0ATwL6u5TNcpfkCQbj3jFNnGiQUNu2qs="
|
hash = "sha256-eYUjP1TKWUrsY++rzg4rezOvmvmjADZFBizIIDHnZtY="
|
||||||
[mod."github.com/fumiama/jieba"]
|
[mod."github.com/fumiama/jieba"]
|
||||||
version = "v0.0.0-20221203025406-36c17a10b565"
|
version = "v0.0.0-20221203025406-36c17a10b565"
|
||||||
hash = "sha256-DvDx1pdldkdaSszrbadM/VwqT9TTSmWl6G6a+ysXYEM="
|
hash = "sha256-DvDx1pdldkdaSszrbadM/VwqT9TTSmWl6G6a+ysXYEM="
|
||||||
[mod."github.com/fumiama/orbyte"]
|
|
||||||
version = "v0.0.0-20251002065953-3bb358367eb5"
|
|
||||||
hash = "sha256-mRQwhR0v922UXlJ7lXo/osv21K8kZDaHx3DsBCjmzoo="
|
|
||||||
[mod."github.com/fumiama/slowdo"]
|
[mod."github.com/fumiama/slowdo"]
|
||||||
version = "v0.0.0-20241001074058-27c4fe5259a4"
|
version = "v0.0.0-20241001074058-27c4fe5259a4"
|
||||||
hash = "sha256-rsV3MKRCSOBMIgJXFCGbCHRY2aBAb32ftU49hT3GjqY="
|
hash = "sha256-rsV3MKRCSOBMIgJXFCGbCHRY2aBAb32ftU49hT3GjqY="
|
||||||
[mod."github.com/fumiama/terasu"]
|
[mod."github.com/fumiama/terasu"]
|
||||||
version = "v1.0.1"
|
version = "v0.0.0-20241027183601-987ab91031ce"
|
||||||
hash = "sha256-7pe0ByxkmqWeYsxWNwa8urfv6lK1cEPrW1b5l86eM1Y="
|
hash = "sha256-WiG5BD1Icwq61KpqkQdf6dl64jEhaDJb2zAQROqXwvc="
|
||||||
[mod."github.com/fumiama/unibase2n"]
|
[mod."github.com/fumiama/unibase2n"]
|
||||||
version = "v0.0.0-20240530074540-ec743fd5a6d6"
|
version = "v0.0.0-20240530074540-ec743fd5a6d6"
|
||||||
hash = "sha256-I3xNzjrj5y0fy0dfa75V57GanfmHIHmubEn9/y0BBHw="
|
hash = "sha256-I3xNzjrj5y0fy0dfa75V57GanfmHIHmubEn9/y0BBHw="
|
||||||
[mod."github.com/gabriel-vasile/mimetype"]
|
[mod."github.com/gabriel-vasile/mimetype"]
|
||||||
version = "v1.4.10"
|
version = "v1.0.4"
|
||||||
hash = "sha256-ha8NJOAWcmEfQaybfNxyUupt0+zlWxoAKLjCacew43s="
|
hash = "sha256-5hl9zBo3nkPt8dZfcLoOix8lAKLm3qIkWhopoS4V34E="
|
||||||
|
[mod."github.com/go-ego/gse"]
|
||||||
|
version = "v0.80.3"
|
||||||
|
hash = "sha256-uxTQN4cxE/ZReZqjlIEQ3WYD9w2Ec37LRHQftJXsSZQ="
|
||||||
[mod."github.com/go-ole/go-ole"]
|
[mod."github.com/go-ole/go-ole"]
|
||||||
version = "v1.3.0"
|
version = "v1.2.6"
|
||||||
hash = "sha256-tF8t3VcV71jQ4jbPL91BwR59AKDpUAFV1waIKzkXJu8="
|
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
|
||||||
[mod."github.com/golang/freetype"]
|
[mod."github.com/golang/freetype"]
|
||||||
version = "v0.0.0-20170609003504-e2365dfdc4a0"
|
version = "v0.0.0-20170609003504-e2365dfdc4a0"
|
||||||
hash = "sha256-AHAFBd20/tqxohkWyQkui2bUef9i1HWYgk9LOIFErvA="
|
hash = "sha256-AHAFBd20/tqxohkWyQkui2bUef9i1HWYgk9LOIFErvA="
|
||||||
[mod."github.com/golang/groupcache"]
|
[mod."github.com/golang/groupcache"]
|
||||||
version = "v0.0.0-20241129210726-2c02b8208cf8"
|
version = "v0.0.0-20210331224755-41bb18bfe9da"
|
||||||
hash = "sha256-AdLZ3dJLe/yduoNvZiXugZxNfmwJjNQyQGsIdzYzH74="
|
hash = "sha256-7Gs7CS9gEYZkbu5P4hqPGBpeGZWC64VDwraSKFF+VR0="
|
||||||
[mod."github.com/google/uuid"]
|
[mod."github.com/google/uuid"]
|
||||||
version = "v1.6.0"
|
version = "v1.6.0"
|
||||||
hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw="
|
hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw="
|
||||||
[mod."github.com/gopxl/beep/v2"]
|
[mod."github.com/hajimehoshi/oto"]
|
||||||
version = "v2.1.1"
|
version = "v0.7.1"
|
||||||
hash = "sha256-JLCUJCG+VvNlVF296JWIOUvvUFHlqEAJvZfw853qwwU="
|
hash = "sha256-eRgbEbsziY5F0oI7wAe29FepZG7uGmq2M4deouDHcXI="
|
||||||
[mod."github.com/jfreymuth/oggvorbis"]
|
[mod."github.com/jfreymuth/oggvorbis"]
|
||||||
version = "v1.0.5"
|
version = "v1.0.1"
|
||||||
hash = "sha256-jphTCaPr34ZT9Id4ZZ6zU9Vnxzy6cTjCwjpQ819eGV0="
|
hash = "sha256-DpkiTLxAA/iCoiylpNRvMzvaDWtK+U4UMJYNnnCmJMU="
|
||||||
[mod."github.com/jfreymuth/vorbis"]
|
[mod."github.com/jfreymuth/vorbis"]
|
||||||
version = "v1.0.2"
|
version = "v1.0.0"
|
||||||
hash = "sha256-gVS+/PZ5pDnswpTQNZILcrx5ZNq9ShXd6vXn7Jabes4="
|
hash = "sha256-6kTol+g3NnZ3MazD786fvraw7ydUf0RWNBzHpzgN9Jk="
|
||||||
[mod."github.com/jinzhu/gorm"]
|
[mod."github.com/jinzhu/gorm"]
|
||||||
version = "v1.9.16"
|
version = "v1.9.16"
|
||||||
hash = "sha256-qKEwgNE8NxcX1uzT20LwC1TKVmve/nIy+oxdAKlxAuc="
|
hash = "sha256-qKEwgNE8NxcX1uzT20LwC1TKVmve/nIy+oxdAKlxAuc="
|
||||||
@ -157,9 +145,6 @@ schema = 3
|
|||||||
[mod."github.com/jozsefsallai/gophersauce"]
|
[mod."github.com/jozsefsallai/gophersauce"]
|
||||||
version = "v1.0.1"
|
version = "v1.0.1"
|
||||||
hash = "sha256-29DsfnGmK51DPunR/leRBKCcokN/yLoB7S2HxCsqtgY="
|
hash = "sha256-29DsfnGmK51DPunR/leRBKCcokN/yLoB7S2HxCsqtgY="
|
||||||
[mod."github.com/json-iterator/go"]
|
|
||||||
version = "v1.1.12"
|
|
||||||
hash = "sha256-To8A0h+lbfZ/6zM+2PpRpY3+L6725OPC66lffq6fUoM="
|
|
||||||
[mod."github.com/kanrichan/resvg-go"]
|
[mod."github.com/kanrichan/resvg-go"]
|
||||||
version = "v0.0.2-0.20231001163256-63db194ca9f5"
|
version = "v0.0.2-0.20231001163256-63db194ca9f5"
|
||||||
hash = "sha256-plRZ3yhyCafCXmAD4vnFUoCTRsHmLp7Jn9gFKcEKbds="
|
hash = "sha256-plRZ3yhyCafCXmAD4vnFUoCTRsHmLp7Jn9gFKcEKbds="
|
||||||
@ -176,35 +161,23 @@ schema = 3
|
|||||||
version = "v0.0.0-20231231122217-0372e1059ca5"
|
version = "v0.0.0-20231231122217-0372e1059ca5"
|
||||||
hash = "sha256-Dr1xDbO+eR4Y/EpPgQ/S6g6C5etRFKWr8de77skcJR8="
|
hash = "sha256-Dr1xDbO+eR4Y/EpPgQ/S6g6C5etRFKWr8de77skcJR8="
|
||||||
[mod."github.com/lufia/plan9stats"]
|
[mod."github.com/lufia/plan9stats"]
|
||||||
version = "v0.0.0-20251013123823-9fd1530e3ec3"
|
version = "v0.0.0-20211012122336-39d0f177ccd0"
|
||||||
hash = "sha256-N760qPHHaMcxICyA3Ap/b/3exi40AStu7458VPvC9GI="
|
hash = "sha256-thb+rkDx5IeWMgw5/5jgu5gZ+6RjJAUXeMgSkJHhRlA="
|
||||||
[mod."github.com/mattn/go-isatty"]
|
[mod."github.com/mattn/go-isatty"]
|
||||||
version = "v0.0.20"
|
version = "v0.0.20"
|
||||||
hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
|
hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
|
||||||
[mod."github.com/mmcdole/gofeed"]
|
|
||||||
version = "v1.3.0"
|
|
||||||
hash = "sha256-GHpqGZvNg+3RSIkVKXrWg6/e8dJD8Y5v2Sx6MzmRlQ0="
|
|
||||||
[mod."github.com/mmcdole/goxpp"]
|
|
||||||
version = "v1.1.1"
|
|
||||||
hash = "sha256-LtZDUtflL06HnDuQiCS6cpoF3VPk+gmABkYXBvdQOz0="
|
|
||||||
[mod."github.com/modern-go/concurrent"]
|
|
||||||
version = "v0.0.0-20180306012644-bacd9c7ef1dd"
|
|
||||||
hash = "sha256-OTySieAgPWR4oJnlohaFTeK1tRaVp/b0d1rYY8xKMzo="
|
|
||||||
[mod."github.com/modern-go/reflect2"]
|
|
||||||
version = "v1.0.2"
|
|
||||||
hash = "sha256-+W9EIW7okXIXjWEgOaMh58eLvBZ7OshW2EhaIpNLSBU="
|
|
||||||
[mod."github.com/mroth/weightedrand"]
|
[mod."github.com/mroth/weightedrand"]
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
hash = "sha256-bP+yIaBUY5+oI455mNM8zh14z/SNPaQg44L3RJ0/v/c="
|
hash = "sha256-bP+yIaBUY5+oI455mNM8zh14z/SNPaQg44L3RJ0/v/c="
|
||||||
[mod."github.com/ncruces/go-strftime"]
|
[mod."github.com/ncruces/go-strftime"]
|
||||||
version = "v1.0.0"
|
version = "v0.1.9"
|
||||||
hash = "sha256-GYIwYDONuv/yTE0AEugCHQbtV3oiBaco93xUNYFcVBQ="
|
hash = "sha256-T0iw+UEckzueWHT88PkTnZZixyKCEa+DTLzIiiohuWY="
|
||||||
[mod."github.com/nfnt/resize"]
|
[mod."github.com/nfnt/resize"]
|
||||||
version = "v0.0.0-20180221191011-83c6a9932646"
|
version = "v0.0.0-20180221191011-83c6a9932646"
|
||||||
hash = "sha256-yvPV+HlDOyJsiwAcVHQkmtw8DHSXyw+cXHkigXm8rAA="
|
hash = "sha256-yvPV+HlDOyJsiwAcVHQkmtw8DHSXyw+cXHkigXm8rAA="
|
||||||
[mod."github.com/notnil/chess"]
|
[mod."github.com/notnil/chess"]
|
||||||
version = "v1.10.0"
|
version = "v1.9.0"
|
||||||
hash = "sha256-hsUOS4rVuMW+UCPJzhsZh3PHCi1Lol12BwKujcICayo="
|
hash = "sha256-2bHp/H5hBE/hPMT1HLOBqMaCZ/DYWJMDri26O9Yzoms="
|
||||||
[mod."github.com/pbnjay/memory"]
|
[mod."github.com/pbnjay/memory"]
|
||||||
version = "v0.0.0-20210728143218-7b4eea64cf58"
|
version = "v0.0.0-20210728143218-7b4eea64cf58"
|
||||||
hash = "sha256-QI+F1oPLOOtwNp8+m45OOoSfYFs3QVjGzE0rFdpF/IA="
|
hash = "sha256-QI+F1oPLOOtwNp8+m45OOoSfYFs3QVjGzE0rFdpF/IA="
|
||||||
@ -215,8 +188,8 @@ schema = 3
|
|||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
hash = "sha256-cPxqj5tb10+MurN1Lehkk/v8KjaxXpL08+pVgL4x4Hg="
|
hash = "sha256-cPxqj5tb10+MurN1Lehkk/v8KjaxXpL08+pVgL4x4Hg="
|
||||||
[mod."github.com/power-devops/perfstat"]
|
[mod."github.com/power-devops/perfstat"]
|
||||||
version = "v0.0.0-20240221224432-82ca36839d55"
|
version = "v0.0.0-20210106213030-5aafc221ea8c"
|
||||||
hash = "sha256-ujzuJ1ttQgjHQJEij4O/2+I8DZaUVZQCQgA4ysfqulI="
|
hash = "sha256-ywykDYuqcMt0TvZOz1l9Z6Z2JMTYQw8cP2fT8AtpmX4="
|
||||||
[mod."github.com/remyoudompheng/bigfft"]
|
[mod."github.com/remyoudompheng/bigfft"]
|
||||||
version = "v0.0.0-20230129092748-24d4a6f8daec"
|
version = "v0.0.0-20230129092748-24d4a6f8daec"
|
||||||
hash = "sha256-vYmpyCE37eBYP/navhaLV4oX4/nu0Z/StAocLIFqrmM="
|
hash = "sha256-vYmpyCE37eBYP/navhaLV4oX4/nu0Z/StAocLIFqrmM="
|
||||||
@ -224,53 +197,62 @@ schema = 3
|
|||||||
version = "v3.24.5"
|
version = "v3.24.5"
|
||||||
hash = "sha256-tc+t1u7gf5A+Bd956dYeM8pGbxs9ezQHqKAKfLQLpuQ="
|
hash = "sha256-tc+t1u7gf5A+Bd956dYeM8pGbxs9ezQHqKAKfLQLpuQ="
|
||||||
[mod."github.com/shoenig/go-m1cpu"]
|
[mod."github.com/shoenig/go-m1cpu"]
|
||||||
version = "v0.1.7"
|
version = "v0.1.6"
|
||||||
hash = "sha256-kIKIE9uxHOniFHGgMgtypYB/OPI8VSQxFUHXehlpuYY="
|
hash = "sha256-hT+JP30BBllsXosK/lo89HV/uxxPLsUyO3dRaDiLnCg="
|
||||||
[mod."github.com/sirupsen/logrus"]
|
[mod."github.com/sirupsen/logrus"]
|
||||||
version = "v1.9.3"
|
version = "v1.9.3"
|
||||||
hash = "sha256-EnxsWdEUPYid+aZ9H4/iMTs1XMvCLbXZRDyvj89Ebms="
|
hash = "sha256-EnxsWdEUPYid+aZ9H4/iMTs1XMvCLbXZRDyvj89Ebms="
|
||||||
[mod."github.com/tetratelabs/wazero"]
|
[mod."github.com/tetratelabs/wazero"]
|
||||||
version = "v1.9.0"
|
version = "v1.5.0"
|
||||||
hash = "sha256-b8D0cDMuDgyjvJ6LFY8REdcL95BIjM27SeOEQWfB0+0="
|
hash = "sha256-fGdJM4LJrZA9jxHuYVo4EUQ3I1k0IVG3QQCBCgZkeZI="
|
||||||
[mod."github.com/tidwall/gjson"]
|
[mod."github.com/tidwall/gjson"]
|
||||||
version = "v1.18.0"
|
version = "v1.18.0"
|
||||||
hash = "sha256-CO6hqDu8Y58Po6A01e5iTpwiUBQ5khUZsw7czaJHw0I="
|
hash = "sha256-CO6hqDu8Y58Po6A01e5iTpwiUBQ5khUZsw7czaJHw0I="
|
||||||
[mod."github.com/tidwall/match"]
|
[mod."github.com/tidwall/match"]
|
||||||
version = "v1.2.0"
|
version = "v1.1.1"
|
||||||
hash = "sha256-O2wTU0SmNIEEOxfncl2BW2czgWeIW5vqR6+A7dtNtXI="
|
hash = "sha256-M2klhPId3Q3T3VGkSbOkYl/2nLHnsG+yMbXkPkyrRdg="
|
||||||
[mod."github.com/tidwall/pretty"]
|
[mod."github.com/tidwall/pretty"]
|
||||||
version = "v1.2.1"
|
version = "v1.2.0"
|
||||||
hash = "sha256-S0uTDDGD8qr415Ut7QinyXljCp0TkL4zOIrlJ+9OMl8="
|
hash = "sha256-esRQGsn2Ee/CiySlwyuOICSLdqUkH4P7u8qXszos8Yc="
|
||||||
[mod."github.com/tklauser/go-sysconf"]
|
[mod."github.com/tklauser/go-sysconf"]
|
||||||
version = "v0.3.15"
|
version = "v0.3.12"
|
||||||
hash = "sha256-Twh9dD/mfNb7Qr5p/KmaK5Xi25VJwj5jESZeJr0qeUc="
|
hash = "sha256-91VBZNb3L2TZkEETF1AE4wnraLoGxKeofUbC5ZiWVHk="
|
||||||
[mod."github.com/tklauser/numcpus"]
|
[mod."github.com/tklauser/numcpus"]
|
||||||
version = "v0.10.0"
|
version = "v0.6.1"
|
||||||
hash = "sha256-NWg68H2Y6MijtlscPaZlLQwgPthEwLV+WpRT01m6kkI="
|
hash = "sha256-8eFcw4YI0w6+GPhU5xMMQjiio94q/O5PpNO3QsvXve0="
|
||||||
|
[mod."github.com/vcaesar/cedar"]
|
||||||
|
version = "v0.20.2"
|
||||||
|
hash = "sha256-3WblBdkR9AZcvZCKSteBV5kdhahiFHG2dbLWfwrVkwM="
|
||||||
[mod."github.com/wcharczuk/go-chart/v2"]
|
[mod."github.com/wcharczuk/go-chart/v2"]
|
||||||
version = "v2.1.2"
|
version = "v2.1.2"
|
||||||
hash = "sha256-GXWWea/u6BezTsPPrWhTYiTetPP/YW6P+Sj4YdocPaM="
|
hash = "sha256-GXWWea/u6BezTsPPrWhTYiTetPP/YW6P+Sj4YdocPaM="
|
||||||
[mod."github.com/wdvxdr1123/ZeroBot"]
|
[mod."github.com/wdvxdr1123/ZeroBot"]
|
||||||
version = "v1.8.2-0.20251002074418-56567b7fc282"
|
version = "v1.8.2-0.20250330133859-27c25d9412b5"
|
||||||
hash = "sha256-KaoqopWcXqiRhGYNaA3UqYtXf27yMuBEj/bvqOWxaC4="
|
hash = "sha256-gT3uFTg5E0Th3r1M1vLzr0QtOjbMusqEjD/ckoBdDFc="
|
||||||
[mod."github.com/yusufpapurcu/wmi"]
|
[mod."github.com/yusufpapurcu/wmi"]
|
||||||
version = "v1.2.4"
|
version = "v1.2.4"
|
||||||
hash = "sha256-N+YDBjOW59YOsZ2lRBVtFsEEi48KhNQRb63/0ZSU3bA="
|
hash = "sha256-N+YDBjOW59YOsZ2lRBVtFsEEi48KhNQRb63/0ZSU3bA="
|
||||||
[mod."gitlab.com/gomidi/midi/v2"]
|
[mod."gitlab.com/gomidi/midi/v2"]
|
||||||
version = "v2.3.16"
|
version = "v2.1.7"
|
||||||
hash = "sha256-o+6UtQH+TRSQlcX8J53esAA/b2c9e7BY7gcO5iSeOy0="
|
hash = "sha256-fbgxSMCk7PVII3sNEKuGWbN56fy3eM564Xb+lnYTxRQ="
|
||||||
|
[mod."golang.org/x/exp/shiny"]
|
||||||
|
version = "v0.0.0-20250305212735-054e65f0b394"
|
||||||
|
hash = "sha256-+xzaSlgRHFa+sGnQG90/72vcJMhletsob/L+KG24P/A="
|
||||||
[mod."golang.org/x/image"]
|
[mod."golang.org/x/image"]
|
||||||
version = "v0.32.0"
|
version = "v0.24.0"
|
||||||
hash = "sha256-a5C5nG4IKFkqM/EXjt29wzjrkYEFLKlg5C0aBnXnlZw="
|
hash = "sha256-nhcznNf4ePM7d0Jy2Si0dpMt7KQfRF5Y5QzMpwFCAVg="
|
||||||
|
[mod."golang.org/x/mobile"]
|
||||||
|
version = "v0.0.0-20231127183840-76ac6878050a"
|
||||||
|
hash = "sha256-GdXSvrqQiJX6pOqc2Yr8gG0ZWysEE81YRl5qkt3JCMA="
|
||||||
[mod."golang.org/x/net"]
|
[mod."golang.org/x/net"]
|
||||||
version = "v0.46.0"
|
version = "v0.33.0"
|
||||||
hash = "sha256-GkAUXwqEJZF2t5dmxJVEE+t58EDzO24KtihqHqsrZH0="
|
hash = "sha256-9swkU9vp6IflUUqAzK+y8PytSmrKLuryidP3RmRfe0w="
|
||||||
[mod."golang.org/x/sys"]
|
[mod."golang.org/x/sys"]
|
||||||
version = "v0.37.0"
|
|
||||||
hash = "sha256-5aT0xP02sW1o9sfJHtWoGGNVYDdwb9FyiX/n6RAlzPo="
|
|
||||||
[mod."golang.org/x/text"]
|
|
||||||
version = "v0.30.0"
|
version = "v0.30.0"
|
||||||
hash = "sha256-VPT1Y2zzgdk+Q3Gx8hdwKdxbVh0/Zn/HwDpILCW3ZNA="
|
hash = "sha256-BuhWtwDkciVioc03rxty6G2vcZVnPX85lI7tgQOFVP8="
|
||||||
|
[mod."golang.org/x/text"]
|
||||||
|
version = "v0.22.0"
|
||||||
|
hash = "sha256-kUwLNFk9K/YuWmO5/u2IshrmhT2CCuk+mAShSlTTeZo="
|
||||||
[mod."gopkg.in/yaml.v3"]
|
[mod."gopkg.in/yaml.v3"]
|
||||||
version = "v3.0.1"
|
version = "v3.0.1"
|
||||||
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
||||||
@ -279,11 +261,11 @@ schema = 3
|
|||||||
hash = "sha256-SJYYRaiDUmIbqy9l/IgiT/4VkFsPYsaslqGEowut34w="
|
hash = "sha256-SJYYRaiDUmIbqy9l/IgiT/4VkFsPYsaslqGEowut34w="
|
||||||
replaced = "github.com/fumiama/libc"
|
replaced = "github.com/fumiama/libc"
|
||||||
[mod."modernc.org/mathutil"]
|
[mod."modernc.org/mathutil"]
|
||||||
version = "v1.7.1"
|
version = "v1.6.0"
|
||||||
hash = "sha256-COZ5rF2GhQVR1r6a0DanJ8qwQ94JSKdQxTMWrDzE0Cc="
|
hash = "sha256-lfuEiS1odd2TWrTylnaGihSJ9myqKs3FLdpvd7PqTnE="
|
||||||
[mod."modernc.org/memory"]
|
[mod."modernc.org/memory"]
|
||||||
version = "v1.11.0"
|
version = "v1.8.0"
|
||||||
hash = "sha256-MkybF8vvrxXS5j7O8w3skwTo0aMo1yjWS0K440rYcHM="
|
hash = "sha256-ucvPr73zg8LjvU+bcoIPKTgwgcon3U9VhKrLEMH81xg="
|
||||||
[mod."modernc.org/sqlite"]
|
[mod."modernc.org/sqlite"]
|
||||||
version = "v1.29.10-simp"
|
version = "v1.29.10-simp"
|
||||||
hash = "sha256-HCUVN6gZDG0g2WIsQ4ksqE1+XR1IjxvnqEBEU2MO1eE="
|
hash = "sha256-HCUVN6gZDG0g2WIsQ4ksqE1+XR1IjxvnqEBEU2MO1eE="
|
||||||
|
|||||||
@ -3,13 +3,13 @@
|
|||||||
package banner
|
package banner
|
||||||
|
|
||||||
// Version ...
|
// Version ...
|
||||||
var Version = "v1.10.0"
|
var Version = "v1.9.8"
|
||||||
|
|
||||||
// Copyright ...
|
// Copyright ...
|
||||||
var Copyright = "© 2020 - 2025 FloatTech"
|
var Copyright = "© 2020 - 2025 FloatTech"
|
||||||
|
|
||||||
// Banner ...
|
// Banner ...
|
||||||
var Banner = "* OneBot + ZeroBot + Golang\n" +
|
var Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||||
"* Version " + Version + " - 2025-09-30 23:45:28 +0800 CST\n" +
|
"* Version " + Version + " - 2025-06-01 18:52:48 +0900 JST\n" +
|
||||||
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
|
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
|
||||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||||
|
|||||||
@ -27,7 +27,7 @@ var Banner = "* OneBot + ZeroBot + Golang\n" +
|
|||||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||||
`
|
`
|
||||||
|
|
||||||
const timeformat = `2006-01-02 15:04:05 +0800 CST`
|
const timeformat = `2006-01-02 15:04:05 +0900 JST`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
f, err := os.Create("banner/banner.go")
|
f, err := os.Create("banner/banner.go")
|
||||||
|
|||||||
5
kanban/version_less_than_1.21.go
Normal file
5
kanban/version_less_than_1.21.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//go:build go1.21
|
||||||
|
|
||||||
|
package kanban
|
||||||
|
|
||||||
|
const Error int = "请使用小于1.21版本的Go"
|
||||||
19
main.go
19
main.go
@ -1,8 +1,6 @@
|
|||||||
// Package main ZeroBot-Plugin main file
|
// Package main ZeroBot-Plugin main file
|
||||||
package main
|
package main
|
||||||
|
|
||||||
//go:generate go run github.com/FloatTech/ZeroBot-Plugin/abineundo/ref -r .
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
@ -14,9 +12,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/abineundo" // 设置插件优先级
|
_ "github.com/FloatTech/ZeroBot-Plugin/console" // 更改控制台属性
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/console" // 更改控制台属性
|
|
||||||
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 打印 banner
|
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 打印 banner
|
||||||
|
|
||||||
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
|
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
|
||||||
// ----------------------插件优先级按顺序从高到低---------------------- //
|
// ----------------------插件优先级按顺序从高到低---------------------- //
|
||||||
@ -40,8 +38,6 @@ import (
|
|||||||
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleepmanage" // 统计睡眠时间
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleepmanage" // 统计睡眠时间
|
||||||
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/airecord" // 群应用:AI声聊
|
|
||||||
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
|
||||||
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager" // 群管
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager" // 群管
|
||||||
@ -69,7 +65,6 @@ import (
|
|||||||
_ "github.com/FloatTech/ZeroBot-Plugin/custom" // 自定义插件合集
|
_ "github.com/FloatTech/ZeroBot-Plugin/custom" // 自定义插件合集
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aifalse" // 服务器监控
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aifalse" // 服务器监控
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiimage" // AI画图
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/animetrace" // AnimeTrace 动画/Galgame识别
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/animetrace" // AnimeTrace 动画/Galgame识别
|
||||||
@ -79,8 +74,6 @@ import (
|
|||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/base64gua" // base64卦加解密
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/base64gua" // base64卦加解密
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baseamasiro" // base天城文加解密
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baseamasiro" // base天城文加解密
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // b站相关
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // b站相关
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibiliparse" // b站相关
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibilipush" // b站相关
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bookreview" // 哀伤雪刃吧推书记录
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bookreview" // 哀伤雪刃吧推书记录
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chess" // 国际象棋
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chess" // 国际象棋
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
|
||||||
@ -88,7 +81,6 @@ import (
|
|||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chrev" // 英文字符翻转
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chrev" // 英文字符翻转
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/crypter" // 奇怪语言加解密
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dailynews" // 今日早报
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dailynews" // 今日早报
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
|
||||||
@ -136,7 +128,6 @@ import (
|
|||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan" // realcugan清晰术
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan" // realcugan清晰术
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/robbery" // 打劫群友的ATRI币
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/robbery" // 打劫群友的ATRI币
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/rsshub" // RSSHub订阅姬
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数
|
||||||
@ -151,11 +142,11 @@ import (
|
|||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet" // 钱包
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet" // 钱包
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes" // 据意查句
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes" // 据意查句
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi" // warframeAPI插件
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi" // warframeAPI插件
|
||||||
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinvilg" // 百度文心AI画图
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife" // 抽老婆
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife" // 抽老婆
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordcount" // 聊天热词
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordcount" // 聊天热词
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygocdb" // 游戏王白鸽API卡查
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo" // 游戏王相关插件
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygotrade" // 游戏王集换社卡价查询
|
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
||||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/yujn" // 遇见API
|
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/yujn" // 遇见API
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
package aichat
|
package aichat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -15,99 +13,19 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var cfg = newconfig()
|
||||||
cfg = newconfig()
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
apitypes = map[string]uint8{
|
|
||||||
"OpenAI": 0,
|
|
||||||
"OLLaMA": 1,
|
|
||||||
"GenAI": 2,
|
|
||||||
}
|
|
||||||
apilist = [3]string{"OpenAI", "OLLaMA", "GenAI"}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ModelType 支持打印 string 并生产 protocal
|
|
||||||
type ModelType int
|
|
||||||
|
|
||||||
func newModelType(typ string) (ModelType, error) {
|
|
||||||
t, ok := apitypes[typ]
|
|
||||||
if !ok {
|
|
||||||
return 0, errors.New("未知类型 " + typ)
|
|
||||||
}
|
|
||||||
return ModelType(t), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mt ModelType) String() string {
|
|
||||||
return apilist[mt]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mt ModelType) protocol(modn string, temp float32, topp float32, maxn uint) (mod model.Protocol, err error) {
|
|
||||||
switch cfg.Type {
|
|
||||||
case 0:
|
|
||||||
mod = model.NewOpenAI(
|
|
||||||
modn, cfg.Separator,
|
|
||||||
temp, topp, maxn,
|
|
||||||
)
|
|
||||||
case 1:
|
|
||||||
mod = model.NewOLLaMA(
|
|
||||||
modn, cfg.Separator,
|
|
||||||
temp, topp, maxn,
|
|
||||||
)
|
|
||||||
case 2:
|
|
||||||
mod = model.NewGenAI(
|
|
||||||
modn,
|
|
||||||
temp, topp, maxn,
|
|
||||||
)
|
|
||||||
default:
|
|
||||||
err = errors.New("unsupported model type " + strconv.Itoa(int(cfg.Type)))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModelBool 支持打印成 "是/否"
|
|
||||||
type ModelBool bool
|
|
||||||
|
|
||||||
func (mb ModelBool) String() string {
|
|
||||||
if mb {
|
|
||||||
return "是"
|
|
||||||
}
|
|
||||||
return "否"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModelKey 支持隐藏密钥
|
|
||||||
type ModelKey string
|
|
||||||
|
|
||||||
func (mk ModelKey) String() string {
|
|
||||||
if len(mk) == 0 {
|
|
||||||
return "未设置"
|
|
||||||
}
|
|
||||||
if len(mk) <= 4 {
|
|
||||||
return "****"
|
|
||||||
}
|
|
||||||
key := string(mk)
|
|
||||||
return key[:2] + strings.Repeat("*", len(key)-4) + key[len(key)-2:]
|
|
||||||
}
|
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
ModelName string
|
ModelName string
|
||||||
ImageModelName string
|
Type int
|
||||||
AgentModelName string
|
MaxN uint
|
||||||
Type ModelType
|
TopP float32
|
||||||
ImageType ModelType
|
SystemP string
|
||||||
AgentType ModelType
|
API string
|
||||||
MaxN uint
|
Key string
|
||||||
TopP float32
|
Separator string
|
||||||
SystemP string
|
NoReplyAT bool
|
||||||
API string
|
NoSystemP bool
|
||||||
ImageAPI string
|
|
||||||
AgentAPI string
|
|
||||||
Key ModelKey
|
|
||||||
ImageKey ModelKey
|
|
||||||
AgentKey ModelKey
|
|
||||||
Separator string
|
|
||||||
NoSystemP ModelBool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newconfig() config {
|
func newconfig() config {
|
||||||
@ -118,50 +36,10 @@ func newconfig() config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) String() string {
|
|
||||||
topp, maxn := c.mparams()
|
|
||||||
sb := strings.Builder{}
|
|
||||||
sb.WriteString(fmt.Sprintf("• 模型名:%s\n", c.ModelName))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 图像模型名:%s\n", c.ImageModelName))
|
|
||||||
sb.WriteString(fmt.Sprintf("• Agent模型名:%s\n", c.AgentModelName))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 接口类型:%v\n", c.Type))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 图像接口类型:%v\n", c.ImageType))
|
|
||||||
sb.WriteString(fmt.Sprintf("• Agent接口类型:%v\n", c.AgentType))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 最大长度:%d\n", maxn))
|
|
||||||
sb.WriteString(fmt.Sprintf("• TopP:%.1f\n", topp))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 系统提示词:%s\n", c.SystemP))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 接口地址:%s\n", c.API))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 图像接口地址:%s\n", c.ImageAPI))
|
|
||||||
sb.WriteString(fmt.Sprintf("• Agent接口地址:%s\n", c.AgentAPI))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 密钥:%v\n", c.Key))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 图像密钥:%v\n", c.ImageKey))
|
|
||||||
sb.WriteString(fmt.Sprintf("• Agent密钥:%v\n", c.AgentKey))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 分隔符:%s\n", c.Separator))
|
|
||||||
sb.WriteString(fmt.Sprintf("• 支持系统提示词:%v\n", !c.NoSystemP))
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) isvalid() bool {
|
func (c *config) isvalid() bool {
|
||||||
return c.ModelName != "" && c.API != "" && c.Key != ""
|
return c.ModelName != "" && c.API != "" && c.Key != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取全局模型参数:TopP和最大长度
|
|
||||||
func (c *config) mparams() (topp float32, maxn uint) {
|
|
||||||
// 处理TopP参数
|
|
||||||
topp = c.TopP
|
|
||||||
if topp == 0 {
|
|
||||||
topp = 0.9
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理最大长度参数
|
|
||||||
maxn = c.MaxN
|
|
||||||
if maxn == 0 {
|
|
||||||
maxn = 4096
|
|
||||||
}
|
|
||||||
|
|
||||||
return topp, maxn
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureconfig(ctx *zero.Ctx) bool {
|
func ensureconfig(ctx *zero.Ctx) bool {
|
||||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -179,7 +57,7 @@ func ensureconfig(ctx *zero.Ctx) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func newextrasetstr[T ~string](ptr *T) func(ctx *zero.Ctx) {
|
func newextrasetstr(ptr *string) func(ctx *zero.Ctx) {
|
||||||
return func(ctx *zero.Ctx) {
|
return func(ctx *zero.Ctx) {
|
||||||
args := strings.TrimSpace(ctx.State["args"].(string))
|
args := strings.TrimSpace(ctx.State["args"].(string))
|
||||||
if args == "" {
|
if args == "" {
|
||||||
@ -191,7 +69,7 @@ func newextrasetstr[T ~string](ptr *T) func(ctx *zero.Ctx) {
|
|||||||
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*ptr = T(args)
|
*ptr = args
|
||||||
err := c.SetExtra(&cfg)
|
err := c.SetExtra(&cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||||
@ -201,7 +79,7 @@ func newextrasetstr[T ~string](ptr *T) func(ctx *zero.Ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newextrasetbool[T ~bool](ptr *T) func(ctx *zero.Ctx) {
|
func newextrasetbool(ptr *bool) func(ctx *zero.Ctx) {
|
||||||
return func(ctx *zero.Ctx) {
|
return func(ctx *zero.Ctx) {
|
||||||
args := ctx.State["regex_matched"].([]string)
|
args := ctx.State["regex_matched"].([]string)
|
||||||
isno := args[1] == "不"
|
isno := args[1] == "不"
|
||||||
@ -210,7 +88,7 @@ func newextrasetbool[T ~bool](ptr *T) func(ctx *zero.Ctx) {
|
|||||||
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*ptr = T(isno)
|
*ptr = isno
|
||||||
err := c.SetExtra(&cfg)
|
err := c.SetExtra(&cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||||
@ -273,30 +151,3 @@ func newextrasetfloat32(ptr *float32) func(ctx *zero.Ctx) {
|
|||||||
ctx.SendChain(message.Text("成功"))
|
ctx.SendChain(message.Text("成功"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newextrasetmodeltype(ptr *ModelType) func(ctx *zero.Ctx) {
|
|
||||||
return func(ctx *zero.Ctx) {
|
|
||||||
args := strings.TrimSpace(ctx.State["args"].(string))
|
|
||||||
if args == "" {
|
|
||||||
ctx.SendChain(message.Text("ERROR: empty args"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
|
||||||
if !ok {
|
|
||||||
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
typ, err := newModelType(args)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*ptr = typ
|
|
||||||
err = c.SetExtra(&cfg)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("成功"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,29 +1,22 @@
|
|||||||
// Package aichat OpenAI聊天和群聊总结
|
// Package aichat OpenAI聊天
|
||||||
package aichat
|
package aichat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/fumiama/deepinfra"
|
"github.com/fumiama/deepinfra"
|
||||||
"github.com/fumiama/deepinfra/model"
|
"github.com/fumiama/deepinfra/model"
|
||||||
goba "github.com/fumiama/go-onebot-agent"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
|
||||||
"github.com/FloatTech/AnimeAPI/airecord"
|
|
||||||
"github.com/FloatTech/floatbox/process"
|
"github.com/FloatTech/floatbox/process"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/chat"
|
"github.com/FloatTech/zbputils/chat"
|
||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -34,62 +27,44 @@ var (
|
|||||||
Brief: "OpenAI聊天",
|
Brief: "OpenAI聊天",
|
||||||
Help: "- 设置AI聊天触发概率10\n" +
|
Help: "- 设置AI聊天触发概率10\n" +
|
||||||
"- 设置AI聊天温度80\n" +
|
"- 设置AI聊天温度80\n" +
|
||||||
"- 设置AI聊天(识图|Agent)接口类型[OpenAI|OLLaMA|GenAI]\n" +
|
"- 设置AI聊天接口类型[OpenAI|OLLaMA|GenAI]\n" +
|
||||||
"- 设置AI聊天(不)使用Agent模式\n" +
|
|
||||||
"- 设置AI聊天(不)支持系统提示词\n" +
|
"- 设置AI聊天(不)支持系统提示词\n" +
|
||||||
"- 设置AI聊天(识图|Agent)接口地址https://api.siliconflow.cn/v1/chat/completions\n" +
|
"- 设置AI聊天接口地址https://xxx\n" +
|
||||||
"- 设置AI聊天(识图|Agent)密钥xxx\n" +
|
"- 设置AI聊天密钥xxx\n" +
|
||||||
"- 设置AI聊天(识图|Agent)模型名Qwen/Qwen3-8B\n" +
|
"- 设置AI聊天模型名xxx\n" +
|
||||||
"- 查看AI聊天系统提示词\n" +
|
"- 查看AI聊天系统提示词\n" +
|
||||||
"- 重置AI聊天系统提示词\n" +
|
"- 重置AI聊天系统提示词\n" +
|
||||||
"- 设置AI聊天系统提示词xxx\n" +
|
"- 设置AI聊天系统提示词xxx\n" +
|
||||||
"- 设置AI聊天分隔符</think>(留空则清除)\n" +
|
"- 设置AI聊天分隔符</think>(留空则清除)\n" +
|
||||||
"- 设置AI聊天(不)响应AT\n" +
|
"- 设置AI聊天(不)响应AT\n" +
|
||||||
"- 设置AI聊天最大长度4096\n" +
|
"- 设置AI聊天最大长度4096\n" +
|
||||||
"- 设置AI聊天TopP 0.9\n" +
|
"- 设置AI聊天TopP 0.9",
|
||||||
"- 设置AI聊天(不)以AI语音输出\n" +
|
|
||||||
"- 查看AI聊天配置\n" +
|
|
||||||
"- 重置AI聊天\n" +
|
|
||||||
"- 群聊总结 [消息数目]|群聊总结 1000\n" +
|
|
||||||
"- /gpt [内容] (使用大模型聊天)\n",
|
|
||||||
|
|
||||||
PrivateDataFolder: "aichat",
|
PrivateDataFolder: "aichat",
|
||||||
}).ApplySingle(single.New(
|
})
|
||||||
single.WithKeyFn(func(ctx *zero.Ctx) int64 {
|
|
||||||
if ctx.Event.GroupID == 0 {
|
|
||||||
return -ctx.Event.UserID
|
|
||||||
}
|
|
||||||
return ctx.Event.GroupID
|
|
||||||
}),
|
|
||||||
// no post option, silently quit
|
|
||||||
))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var apitypes = map[string]uint8{
|
||||||
limit = ctxext.NewLimiterManager(time.Second*30, 1)
|
"OpenAI": 0,
|
||||||
)
|
"OLLaMA": 1,
|
||||||
|
"GenAI": 2,
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
en.OnMessage(ensureconfig, func(ctx *zero.Ctx) bool {
|
en.OnMessage(ensureconfig, func(ctx *zero.Ctx) bool {
|
||||||
gid := ctx.Event.GroupID
|
|
||||||
if gid == 0 {
|
|
||||||
gid = -ctx.Event.UserID
|
|
||||||
}
|
|
||||||
stor, err := newstorage(ctx, gid)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Warnln("ERROR: ", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
ctx.State["__aichat_stor__"] = stor
|
|
||||||
return ctx.ExtractPlainText() != "" &&
|
return ctx.ExtractPlainText() != "" &&
|
||||||
(!stor.noreplyat() || (stor.noreplyat() && !ctx.Event.IsToMe))
|
(!cfg.NoReplyAT || (cfg.NoReplyAT && !ctx.Event.IsToMe))
|
||||||
}).SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
}).SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
||||||
gid := ctx.Event.GroupID
|
gid := ctx.Event.GroupID
|
||||||
if gid == 0 {
|
if gid == 0 {
|
||||||
gid = -ctx.Event.UserID
|
gid = -ctx.Event.UserID
|
||||||
}
|
}
|
||||||
stor := ctx.State["__aichat_stor__"].(storage)
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
rate := stor.rate()
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rate := c.GetData(gid)
|
||||||
|
temp := (rate >> 8) & 0xff
|
||||||
|
rate &= 0xff
|
||||||
if !ctx.Event.IsToMe && rand.Intn(100) >= int(rate) {
|
if !ctx.Event.IsToMe && rand.Intn(100) >= int(rate) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -100,66 +75,47 @@ func init() {
|
|||||||
logrus.Warnln("ERROR: get extra err: empty key")
|
logrus.Warnln("ERROR: get extra err: empty key")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
temperature := stor.temp()
|
|
||||||
topp, maxn := cfg.mparams()
|
|
||||||
|
|
||||||
if !stor.noagent() && cfg.AgentAPI != "" && cfg.AgentModelName != "" {
|
if temp <= 0 {
|
||||||
x := deepinfra.NewAPI(cfg.AgentAPI, string(cfg.AgentKey))
|
temp = 70 // default setting
|
||||||
mod, err := cfg.Type.protocol(cfg.AgentModelName, temperature, topp, maxn)
|
}
|
||||||
if err != nil {
|
if temp > 100 {
|
||||||
logrus.Warnln("ERROR: ", err)
|
temp = 100
|
||||||
return
|
|
||||||
}
|
|
||||||
role := goba.PermRoleUser
|
|
||||||
if zero.AdminPermission(ctx) {
|
|
||||||
role = goba.PermRoleAdmin
|
|
||||||
if zero.SuperUserPermission(ctx) {
|
|
||||||
role = goba.PermRoleOwner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ag := chat.AgentOf(ctx.Event.SelfID)
|
|
||||||
if cfg.ImageAPI != "" && !ag.CanViewImage() {
|
|
||||||
mod, err := cfg.ImageType.protocol(cfg.ImageModelName, temperature, topp, maxn)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Warnln("ERROR: ", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ag.SetViewImageAPI(deepinfra.NewAPI(cfg.ImageAPI, string(cfg.ImageKey)), mod)
|
|
||||||
}
|
|
||||||
ctx.NoTimeout()
|
|
||||||
hasresp := false
|
|
||||||
for i := 0; i < 8; i++ { // 最大运行 8 轮因为问答上下文只有 16
|
|
||||||
reqs := chat.CallAgent(ag, zero.SuperUserPermission(ctx), x, mod, gid, role)
|
|
||||||
if len(reqs) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
hasresp = true
|
|
||||||
for _, req := range reqs {
|
|
||||||
resp := ctx.CallAction(req.Action, req.Params)
|
|
||||||
logrus.Infoln("[aichat] agent get resp:", reqs)
|
|
||||||
ag.AddResponse(gid, &goba.APIResponse{
|
|
||||||
Status: resp.Status,
|
|
||||||
Data: json.RawMessage(resp.Data.Raw),
|
|
||||||
Message: resp.Message,
|
|
||||||
Wording: resp.Wording,
|
|
||||||
RetCode: resp.RetCode,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if hasresp {
|
|
||||||
ag.AddTerminus(gid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// no response, fall back to normal chat
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x := deepinfra.NewAPI(cfg.API, string(cfg.Key))
|
x := deepinfra.NewAPI(cfg.API, cfg.Key)
|
||||||
mod, err := cfg.Type.protocol(cfg.ModelName, temperature, topp, maxn)
|
var mod model.Protocol
|
||||||
if err != nil {
|
maxn := cfg.MaxN
|
||||||
logrus.Warnln("ERROR: ", err)
|
if maxn == 0 {
|
||||||
|
maxn = 4096
|
||||||
|
}
|
||||||
|
topp := cfg.TopP
|
||||||
|
if topp == 0 {
|
||||||
|
topp = 0.9
|
||||||
|
}
|
||||||
|
|
||||||
|
switch cfg.Type {
|
||||||
|
case 0:
|
||||||
|
mod = model.NewOpenAI(
|
||||||
|
cfg.ModelName, cfg.Separator,
|
||||||
|
float32(temp)/100, topp, maxn,
|
||||||
|
)
|
||||||
|
case 1:
|
||||||
|
mod = model.NewOLLaMA(
|
||||||
|
cfg.ModelName, cfg.Separator,
|
||||||
|
float32(temp)/100, topp, maxn,
|
||||||
|
)
|
||||||
|
case 2:
|
||||||
|
mod = model.NewGenAI(
|
||||||
|
cfg.ModelName,
|
||||||
|
float32(temp)/100, topp, maxn,
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
logrus.Warnln("[aichat] unsupported AI type", cfg.Type)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, err := x.Request(chat.GetChatContext(mod, gid, cfg.SystemP, bool(cfg.NoSystemP)))
|
|
||||||
|
data, err := x.Request(chat.Ask(mod, gid, cfg.SystemP, cfg.NoSystemP))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Warnln("[aichat] post err:", err)
|
logrus.Warnln("[aichat] post err:", err)
|
||||||
return
|
return
|
||||||
@ -167,7 +123,7 @@ func init() {
|
|||||||
|
|
||||||
txt := chat.Sanitize(strings.Trim(data, "\n "))
|
txt := chat.Sanitize(strings.Trim(data, "\n "))
|
||||||
if len(txt) > 0 {
|
if len(txt) > 0 {
|
||||||
chat.AddChatReply(gid, txt)
|
chat.Reply(gid, txt)
|
||||||
nick := zero.BotConfig.NickName[rand.Intn(len(zero.BotConfig.NickName))]
|
nick := zero.BotConfig.NickName[rand.Intn(len(zero.BotConfig.NickName))]
|
||||||
txt = strings.ReplaceAll(txt, "{name}", ctx.CardOrNickName(ctx.Event.UserID))
|
txt = strings.ReplaceAll(txt, "{name}", ctx.CardOrNickName(ctx.Event.UserID))
|
||||||
txt = strings.ReplaceAll(txt, "{me}", nick)
|
txt = strings.ReplaceAll(txt, "{me}", nick)
|
||||||
@ -179,53 +135,111 @@ func init() {
|
|||||||
if t == "" {
|
if t == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logrus.Infoln("[aichat] 回复内容:", t)
|
if id != nil {
|
||||||
recCfg := airecord.GetConfig()
|
id = ctx.SendChain(message.Reply(id), message.Text(t))
|
||||||
record := ""
|
|
||||||
if !stor.norecord() {
|
|
||||||
record = ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, t)
|
|
||||||
}
|
|
||||||
if record != "" {
|
|
||||||
ctx.SendChain(message.Record(record))
|
|
||||||
} else {
|
} else {
|
||||||
if id != nil {
|
id = ctx.SendChain(message.Text(t))
|
||||||
id = ctx.SendChain(message.Reply(id), message.Text(t))
|
|
||||||
} else {
|
|
||||||
id = ctx.SendChain(message.Text(t))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
process.SleepAbout1sTo2s()
|
process.SleepAbout1sTo2s()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
en.OnPrefix("设置AI聊天触发概率", zero.AdminPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天触发概率", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
Handle(ctxext.NewStorageSaveBitmapHandler(bitmaprate, 0, 100))
|
args := strings.TrimSpace(ctx.State["args"].(string))
|
||||||
en.OnPrefix("设置AI聊天温度", zero.AdminPermission).SetBlock(true).
|
if args == "" {
|
||||||
Handle(ctxext.NewStorageSaveBitmapHandler(bitmaptemp, 0, 100))
|
ctx.SendChain(message.Text("ERROR: empty args"))
|
||||||
en.OnPrefix("设置AI聊天接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
return
|
||||||
Handle(newextrasetmodeltype(&cfg.Type))
|
}
|
||||||
en.OnPrefix("设置AI聊天识图接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
Handle(newextrasetmodeltype(&cfg.ImageType))
|
if !ok {
|
||||||
en.OnPrefix("设置AI聊天Agent接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||||
Handle(newextrasetmodeltype(&cfg.AgentType))
|
return
|
||||||
|
}
|
||||||
|
r, err := strconv.Atoi(args)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: parse rate err: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r > 100 {
|
||||||
|
r = 100
|
||||||
|
} else if r < 0 {
|
||||||
|
r = 0
|
||||||
|
}
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
if gid == 0 {
|
||||||
|
gid = -ctx.Event.UserID
|
||||||
|
}
|
||||||
|
val := c.GetData(gid) & (^0xff)
|
||||||
|
err = c.SetData(gid, val|int64(r&0xff))
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: set data err: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(message.Text("成功"))
|
||||||
|
})
|
||||||
|
en.OnPrefix("设置AI聊天温度", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
|
args := strings.TrimSpace(ctx.State["args"].(string))
|
||||||
|
if args == "" {
|
||||||
|
ctx.SendChain(message.Text("ERROR: empty args"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
|
if !ok {
|
||||||
|
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r, err := strconv.Atoi(args)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: parse rate err: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r > 100 {
|
||||||
|
r = 100
|
||||||
|
} else if r < 0 {
|
||||||
|
r = 0
|
||||||
|
}
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
if gid == 0 {
|
||||||
|
gid = -ctx.Event.UserID
|
||||||
|
}
|
||||||
|
val := c.GetData(gid) & (^0xff00)
|
||||||
|
err = c.SetData(gid, val|(int64(r&0xff)<<8))
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: set data err: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(message.Text("成功"))
|
||||||
|
})
|
||||||
|
en.OnPrefix("设置AI聊天接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
|
args := strings.TrimSpace(ctx.State["args"].(string))
|
||||||
|
if args == "" {
|
||||||
|
ctx.SendChain(message.Text("ERROR: empty args"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
|
if !ok {
|
||||||
|
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
typ, ok := apitypes[args]
|
||||||
|
if !ok {
|
||||||
|
ctx.SendChain(message.Text("ERROR: 未知类型 ", args))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cfg.Type = int(typ)
|
||||||
|
err := c.SetExtra(&cfg)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(message.Text("成功"))
|
||||||
|
})
|
||||||
en.OnPrefix("设置AI聊天接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetstr(&cfg.API))
|
Handle(newextrasetstr(&cfg.API))
|
||||||
en.OnPrefix("设置AI聊天识图接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(newextrasetstr(&cfg.ImageAPI))
|
|
||||||
en.OnPrefix("设置AI聊天Agent接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(newextrasetstr(&cfg.AgentAPI))
|
|
||||||
en.OnPrefix("设置AI聊天密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetstr(&cfg.Key))
|
Handle(newextrasetstr(&cfg.Key))
|
||||||
en.OnPrefix("设置AI聊天识图密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(newextrasetstr(&cfg.ImageKey))
|
|
||||||
en.OnPrefix("设置AI聊天Agent密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(newextrasetstr(&cfg.AgentKey))
|
|
||||||
en.OnPrefix("设置AI聊天模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetstr(&cfg.ModelName))
|
Handle(newextrasetstr(&cfg.ModelName))
|
||||||
en.OnPrefix("设置AI聊天识图模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(newextrasetstr(&cfg.ImageModelName))
|
|
||||||
en.OnPrefix("设置AI聊天Agent模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(newextrasetstr(&cfg.AgentModelName))
|
|
||||||
en.OnPrefix("设置AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetstr(&cfg.SystemP))
|
Handle(newextrasetstr(&cfg.SystemP))
|
||||||
en.OnFullMatch("查看AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnFullMatch("查看AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
@ -248,240 +262,11 @@ func init() {
|
|||||||
en.OnPrefix("设置AI聊天分隔符", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天分隔符", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetstr(&cfg.Separator))
|
Handle(newextrasetstr(&cfg.Separator))
|
||||||
en.OnRegex("^设置AI聊天(不)?响应AT$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnRegex("^设置AI聊天(不)?响应AT$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(ctxext.NewStorageSaveBoolHandler(bitmapnrat))
|
Handle(newextrasetbool(&cfg.NoReplyAT))
|
||||||
en.OnRegex("^设置AI聊天(不)?支持系统提示词$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnRegex("^设置AI聊天(不)?支持系统提示词$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetbool(&cfg.NoSystemP))
|
Handle(newextrasetbool(&cfg.NoSystemP))
|
||||||
en.OnRegex("^设置AI聊天(不)?使用Agent模式$", ensureconfig, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(ctxext.NewStorageSaveBoolHandler(bitmapnagt))
|
|
||||||
en.OnPrefix("设置AI聊天最大长度", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天最大长度", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetuint(&cfg.MaxN))
|
Handle(newextrasetuint(&cfg.MaxN))
|
||||||
en.OnPrefix("设置AI聊天TopP", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
en.OnPrefix("设置AI聊天TopP", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(newextrasetfloat32(&cfg.TopP))
|
Handle(newextrasetfloat32(&cfg.TopP))
|
||||||
en.OnRegex("^设置AI聊天(不)?以AI语音输出$", ensureconfig, zero.AdminPermission).SetBlock(true).
|
|
||||||
Handle(ctxext.NewStorageSaveBoolHandler(bitmapnrec))
|
|
||||||
en.OnFullMatch("查看AI聊天配置", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
gid := ctx.Event.GroupID
|
|
||||||
stor, err := newstorage(ctx, gid)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(
|
|
||||||
message.Text(
|
|
||||||
"【当前AI聊天本群配置】\n",
|
|
||||||
"• 触发概率:", int(stor.rate()), "\n",
|
|
||||||
"• 温度:", stor.temp(), "\n",
|
|
||||||
"• 以AI语音输出:", ModelBool(!stor.norecord()), "\n",
|
|
||||||
"• 使用Agent:", ModelBool(!stor.noagent()), "\n",
|
|
||||||
"• 响应@:", ModelBool(!stor.noreplyat()), "\n",
|
|
||||||
),
|
|
||||||
message.Text("【当前AI聊天全局配置】\n", &cfg),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
en.OnFullMatch("重置AI聊天", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
|
||||||
chat.ResetChat()
|
|
||||||
ctx.SendChain(message.Text("成功"))
|
|
||||||
})
|
|
||||||
|
|
||||||
// 添加群聊总结功能
|
|
||||||
en.OnRegex(`^群聊总结\s?(\d*)$`, ensureconfig, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(limit.LimitByGroup).Handle(func(ctx *zero.Ctx) {
|
|
||||||
ctx.SendChain(message.Text("少女思考中..."))
|
|
||||||
gid := ctx.Event.GroupID
|
|
||||||
if gid == 0 {
|
|
||||||
gid = -ctx.Event.UserID
|
|
||||||
}
|
|
||||||
p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
|
||||||
if p > 1000 {
|
|
||||||
p = 1000
|
|
||||||
}
|
|
||||||
if p == 0 {
|
|
||||||
p = 200
|
|
||||||
}
|
|
||||||
group := ctx.GetGroupInfo(gid, false)
|
|
||||||
if group.MemberCount == 0 {
|
|
||||||
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "未加入", group.Name, "(", gid, "),无法获取总结"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var messages []string
|
|
||||||
|
|
||||||
h := ctx.GetGroupMessageHistory(gid, 0, p, false)
|
|
||||||
h.Get("messages").ForEach(func(_, msgObj gjson.Result) bool {
|
|
||||||
nickname := msgObj.Get("sender.nickname").Str
|
|
||||||
text := strings.TrimSpace(message.ParseMessageFromString(msgObj.Get("raw_message").Str).ExtractPlainText())
|
|
||||||
if text != "" {
|
|
||||||
messages = append(messages, nickname+": "+text)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
if len(messages) == 0 {
|
|
||||||
ctx.SendChain(message.Text("ERROR: 历史消息为空或者无法获得历史消息"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构造总结请求提示 (使用通用版省流提示词)
|
|
||||||
// 使用反引号定义多行字符串,更清晰
|
|
||||||
promptTemplate := `请对以下群聊对话进行【极简总结】。
|
|
||||||
要求:
|
|
||||||
1. 剔除客套与废话,直击主题。
|
|
||||||
2. 使用 Markdown 列表格式。
|
|
||||||
3. 按以下结构输出:
|
|
||||||
- 🎯 核心议题:(一句话概括)
|
|
||||||
- 💡 关键观点/结论:(提取3-5个重点)
|
|
||||||
- ✅ 下一步/待办:(如果有,明确谁做什么)
|
|
||||||
|
|
||||||
群聊对话内容如下:
|
|
||||||
`
|
|
||||||
summaryPrompt := promptTemplate + strings.Join(messages, "\n")
|
|
||||||
|
|
||||||
stor, err := newstorage(ctx, gid)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 调用大模型API进行总结
|
|
||||||
summary, err := llmchat(summaryPrompt, stor.temp())
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var b strings.Builder
|
|
||||||
b.WriteString("群 ")
|
|
||||||
b.WriteString(group.Name)
|
|
||||||
b.WriteByte('(')
|
|
||||||
b.WriteString(strconv.FormatInt(gid, 10))
|
|
||||||
b.WriteString(") 的 ")
|
|
||||||
b.WriteString(strconv.FormatInt(p, 10))
|
|
||||||
b.WriteString(" 条消息总结:\n\n")
|
|
||||||
b.WriteString(summary)
|
|
||||||
|
|
||||||
// 分割总结内容为多段(按1000字符长度切割)
|
|
||||||
summaryText := b.String()
|
|
||||||
msg := make(message.Message, 0)
|
|
||||||
for len(summaryText) > 0 {
|
|
||||||
if len(summaryText) <= 1000 {
|
|
||||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text(summaryText)))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找1000字符内的最后一个换行符,尽量在换行处分割
|
|
||||||
chunk := summaryText[:1000]
|
|
||||||
lastNewline := strings.LastIndex(chunk, "\n")
|
|
||||||
if lastNewline > 0 {
|
|
||||||
chunk = summaryText[:lastNewline+1]
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text(chunk)))
|
|
||||||
summaryText = summaryText[len(chunk):]
|
|
||||||
}
|
|
||||||
if len(msg) > 0 {
|
|
||||||
ctx.Send(msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 添加 /gpt 命令处理(同时支持回复消息和直接使用)
|
|
||||||
en.OnKeyword("/gpt", ensureconfig).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
|
||||||
gid := ctx.Event.GroupID
|
|
||||||
if gid == 0 {
|
|
||||||
gid = -ctx.Event.UserID
|
|
||||||
}
|
|
||||||
text := ctx.MessageString()
|
|
||||||
|
|
||||||
var query string
|
|
||||||
var replyContent string
|
|
||||||
|
|
||||||
// 检查是否是回复消息 (使用MessageElement检查而不是CQ码)
|
|
||||||
for _, elem := range ctx.Event.Message {
|
|
||||||
if elem.Type == "reply" {
|
|
||||||
// 提取被回复的消息ID
|
|
||||||
replyIDStr := elem.Data["id"]
|
|
||||||
replyID, err := strconv.ParseInt(replyIDStr, 10, 64)
|
|
||||||
if err == nil {
|
|
||||||
// 获取被回复的消息内容
|
|
||||||
replyMsg := ctx.GetMessage(replyID)
|
|
||||||
if replyMsg.Elements != nil {
|
|
||||||
replyContent = replyMsg.Elements.ExtractPlainText()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break // 找到回复元素后退出循环
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提取 /gpt 后面的内容
|
|
||||||
parts := strings.SplitN(text, "/gpt", 2)
|
|
||||||
|
|
||||||
var gContent string
|
|
||||||
if len(parts) > 1 {
|
|
||||||
gContent = strings.TrimSpace(parts[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
// 组合内容:优先使用回复内容,如果同时有/gpt内容则拼接
|
|
||||||
switch {
|
|
||||||
case replyContent != "" && gContent != "":
|
|
||||||
query = replyContent + "\n" + gContent
|
|
||||||
case replyContent != "":
|
|
||||||
query = replyContent
|
|
||||||
case gContent != "":
|
|
||||||
query = gContent
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
stor, err := newstorage(ctx, gid)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 调用大模型API进行聊天
|
|
||||||
reply, err := llmchat(query, stor.temp())
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分割总结内容为多段(按1000字符长度切割)
|
|
||||||
msg := make(message.Message, 0)
|
|
||||||
for len(reply) > 0 {
|
|
||||||
if len(reply) <= 1000 {
|
|
||||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text(reply)))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找1000字符内的最后一个换行符,尽量在换行处分割
|
|
||||||
chunk := reply[:1000]
|
|
||||||
lastNewline := strings.LastIndex(chunk, "\n")
|
|
||||||
if lastNewline > 0 {
|
|
||||||
chunk = reply[:lastNewline+1]
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text(chunk)))
|
|
||||||
reply = reply[len(chunk):]
|
|
||||||
}
|
|
||||||
if len(msg) > 0 {
|
|
||||||
ctx.Send(msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// llmchat 调用大模型API包装
|
|
||||||
func llmchat(prompt string, temp float32) (string, error) {
|
|
||||||
topp, maxn := cfg.mparams()
|
|
||||||
|
|
||||||
x := deepinfra.NewAPI(cfg.API, string(cfg.Key))
|
|
||||||
|
|
||||||
mod, err := cfg.Type.protocol(cfg.ModelName, temp, topp, maxn)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := x.Request(mod.User(model.NewContentText(prompt)))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.TrimSpace(data), nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
package aichat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
bitmaprate = 0x0000ff
|
|
||||||
bitmaptemp = 0x00ff00
|
|
||||||
bitmapnagt = 0x010000
|
|
||||||
bitmapnrec = 0x020000
|
|
||||||
bitmapnrat = 0x040000
|
|
||||||
)
|
|
||||||
|
|
||||||
type storage ctxext.Storage
|
|
||||||
|
|
||||||
func newstorage(ctx *zero.Ctx, gid int64) (storage, error) {
|
|
||||||
s, err := ctxext.NewStorage(ctx, gid)
|
|
||||||
return storage(s), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s storage) rate() uint8 {
|
|
||||||
return uint8((ctxext.Storage)(s).Get(bitmaprate))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s storage) temp() float32 {
|
|
||||||
temp := int8((ctxext.Storage)(s).Get(bitmaptemp))
|
|
||||||
// 处理温度参数
|
|
||||||
if temp <= 0 {
|
|
||||||
temp = 70 // default setting
|
|
||||||
}
|
|
||||||
if temp > 100 {
|
|
||||||
temp = 100
|
|
||||||
}
|
|
||||||
return float32(temp) / 100
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s storage) noagent() bool {
|
|
||||||
return (ctxext.Storage)(s).GetBool(bitmapnagt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s storage) norecord() bool {
|
|
||||||
return (ctxext.Storage)(s).GetBool(bitmapnrec)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s storage) noreplyat() bool {
|
|
||||||
return (ctxext.Storage)(s).GetBool(bitmapnrat)
|
|
||||||
}
|
|
||||||
@ -1,149 +0,0 @@
|
|||||||
package aichat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestStorage_rate(t *testing.T) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
// 测试默认值
|
|
||||||
if rate := s.rate(); rate != 0 {
|
|
||||||
t.Errorf("default rate() = %v, want 0", rate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置值并测试
|
|
||||||
s = storage((ctxext.Storage)(s).Set(int64(100), bitmaprate))
|
|
||||||
if rate := s.rate(); rate != 100 {
|
|
||||||
t.Errorf("rate() after set = %v, want 100", rate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStorage_temp(t *testing.T) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
setValue int64
|
|
||||||
expected float32
|
|
||||||
}{
|
|
||||||
{"default temp (0)", 0, 0.70}, // 默认值 70/100
|
|
||||||
{"valid temp 50", 50, 0.50}, // 50/100 = 0.50
|
|
||||||
{"valid temp 80", 80, 0.80}, // 80/100 = 0.80
|
|
||||||
{"max temp 100", 100, 1.00}, // 100/100 = 1.00
|
|
||||||
{"over max temp", 127, 1.00}, // 限制为 100/100 = 1.00
|
|
||||||
{"negative temp", -10, 0.70}, // 默认值 70/100
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s = storage((ctxext.Storage)(s).Set(tt.setValue, bitmaptemp))
|
|
||||||
|
|
||||||
result := s.temp()
|
|
||||||
if result != tt.expected {
|
|
||||||
t.Errorf("temp() = %v, want %v", result, tt.expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStorage_noagent(t *testing.T) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
// 测试默认值
|
|
||||||
if noagent := s.noagent(); noagent != false {
|
|
||||||
t.Errorf("default noagent() = %v, want false", noagent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置为 true 并测试
|
|
||||||
s = storage((ctxext.Storage)(s).Set(1, bitmapnagt))
|
|
||||||
if noagent := s.noagent(); noagent != true {
|
|
||||||
t.Errorf("noagent() after set true = %v, want true", noagent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStorage_norecord(t *testing.T) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
// 测试默认值
|
|
||||||
if norecord := s.norecord(); norecord != false {
|
|
||||||
t.Errorf("default norecord() = %v, want false", norecord)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置为 true 并测试
|
|
||||||
s = storage((ctxext.Storage)(s).Set(1, bitmapnrec))
|
|
||||||
if norecord := s.norecord(); norecord != true {
|
|
||||||
t.Errorf("norecord() after set true = %v, want true", norecord)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStorage_noreplyat(t *testing.T) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
// 测试默认值
|
|
||||||
if noreplyat := s.noreplyat(); noreplyat != false {
|
|
||||||
t.Errorf("default noreplyat() = %v, want false", noreplyat)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置为 true 并测试
|
|
||||||
s = storage((ctxext.Storage)(s).Set(1, bitmapnrat))
|
|
||||||
if noreplyat := s.noreplyat(); noreplyat != true {
|
|
||||||
t.Errorf("noreplyat() after set true = %v, want true", noreplyat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStorage_Integration(t *testing.T) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
// 设置各种值
|
|
||||||
s = storage((ctxext.Storage)(s).Set(int64(75), bitmaprate))
|
|
||||||
s = storage((ctxext.Storage)(s).Set(int64(85), bitmaptemp))
|
|
||||||
s = storage((ctxext.Storage)(s).Set(1, bitmapnagt))
|
|
||||||
s = storage((ctxext.Storage)(s).Set(0, bitmapnrec))
|
|
||||||
s = storage((ctxext.Storage)(s).Set(1, bitmapnrat))
|
|
||||||
|
|
||||||
// 验证所有方法
|
|
||||||
if rate := s.rate(); rate != 75 {
|
|
||||||
t.Errorf("rate() = %v, want 75", rate)
|
|
||||||
}
|
|
||||||
|
|
||||||
if temp := s.temp(); temp != 0.85 {
|
|
||||||
t.Errorf("temp() = %v, want 0.85", temp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if noagent := s.noagent(); !noagent {
|
|
||||||
t.Errorf("noagent() = %v, want true", noagent)
|
|
||||||
}
|
|
||||||
|
|
||||||
if norecord := s.norecord(); norecord {
|
|
||||||
t.Errorf("norecord() = %v, want false", norecord)
|
|
||||||
}
|
|
||||||
|
|
||||||
if noreplyat := s.noreplyat(); !noreplyat {
|
|
||||||
t.Errorf("noreplyat() = %v, want true", noreplyat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkStorage_rate(b *testing.B) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
s = storage((ctxext.Storage)(s).Set(int64(100), bitmaprate))
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
s.rate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkStorage_temp(b *testing.B) {
|
|
||||||
s := storage(ctxext.Storage(0))
|
|
||||||
|
|
||||||
s = storage((ctxext.Storage)(s).Set(int64(80), bitmaptemp))
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
s.temp()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -25,10 +25,10 @@ import (
|
|||||||
"github.com/FloatTech/zbputils/ctxext"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
"github.com/FloatTech/zbputils/img/text"
|
"github.com/FloatTech/zbputils/img/text"
|
||||||
"github.com/disintegration/imaging"
|
"github.com/disintegration/imaging"
|
||||||
"github.com/shirou/gopsutil/v4/cpu"
|
"github.com/shirou/gopsutil/v3/cpu"
|
||||||
"github.com/shirou/gopsutil/v4/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"github.com/shirou/gopsutil/v4/host"
|
"github.com/shirou/gopsutil/v3/host"
|
||||||
"github.com/shirou/gopsutil/v4/mem"
|
"github.com/shirou/gopsutil/v3/mem"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/text/cases"
|
"golang.org/x/text/cases"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
// Package aiimage 提供AI画图功能配置
|
|
||||||
package aiimage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
sql "github.com/FloatTech/sqlite"
|
|
||||||
)
|
|
||||||
|
|
||||||
// storage 管理画图配置存储
|
|
||||||
type storage struct {
|
|
||||||
sync.RWMutex
|
|
||||||
db sql.Sqlite
|
|
||||||
}
|
|
||||||
|
|
||||||
// imageConfig 存储AI画图配置信息
|
|
||||||
type imageConfig struct {
|
|
||||||
ID int64 `db:"id"` // 主键ID
|
|
||||||
APIKey string `db:"apiKey"` // API密钥
|
|
||||||
APIURL string `db:"apiUrl"` // API地址
|
|
||||||
ModelName string `db:"modelName"` // 画图模型名称
|
|
||||||
}
|
|
||||||
|
|
||||||
// getConfig 获取当前配置
|
|
||||||
func (sdb *storage) getConfig() imageConfig {
|
|
||||||
sdb.RLock()
|
|
||||||
defer sdb.RUnlock()
|
|
||||||
cfg := imageConfig{}
|
|
||||||
_ = sdb.db.Find("config", &cfg, "WHERE id = 1")
|
|
||||||
return cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
// setConfig 设置AI画图配置
|
|
||||||
func (sdb *storage) setConfig(apiKey, apiURL, modelName string) error {
|
|
||||||
sdb.Lock()
|
|
||||||
defer sdb.Unlock()
|
|
||||||
return sdb.db.Insert("config", &imageConfig{
|
|
||||||
ID: 1,
|
|
||||||
APIKey: apiKey,
|
|
||||||
APIURL: apiURL,
|
|
||||||
ModelName: modelName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrintConfig 返回格式化后的配置信息
|
|
||||||
func (sdb *storage) PrintConfig() string {
|
|
||||||
cfg := sdb.getConfig()
|
|
||||||
var builder strings.Builder
|
|
||||||
builder.WriteString("当前AI画图配置:\n")
|
|
||||||
builder.WriteString(fmt.Sprintf("• 密钥: %s\n", cfg.APIKey))
|
|
||||||
builder.WriteString(fmt.Sprintf("• 接口地址: %s\n", cfg.APIURL))
|
|
||||||
builder.WriteString(fmt.Sprintf("• 模型名: %s\n", cfg.ModelName))
|
|
||||||
return builder.String()
|
|
||||||
}
|
|
||||||
@ -1,171 +0,0 @@
|
|||||||
// Package aiimage AI画图
|
|
||||||
package aiimage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
|
||||||
"github.com/FloatTech/floatbox/web"
|
|
||||||
sql "github.com/FloatTech/sqlite"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
|
||||||
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
|
||||||
"github.com/FloatTech/zbputils/control"
|
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var sdb = &storage{}
|
|
||||||
|
|
||||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
||||||
DisableOnDefault: false,
|
|
||||||
Extra: control.ExtraFromString("aiimage"),
|
|
||||||
Brief: "AI画图",
|
|
||||||
Help: "- 设置AI画图密钥xxx\n" +
|
|
||||||
"- 设置AI画图接口地址https://api.siliconflow.cn/v1/images/generations\n" +
|
|
||||||
"- 设置AI画图模型名Kwai-Kolors/Kolors\n" +
|
|
||||||
"- 查看AI画图配置\n" +
|
|
||||||
"- AI画图 [描述]",
|
|
||||||
PrivateDataFolder: "aiimage",
|
|
||||||
})
|
|
||||||
|
|
||||||
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
|
||||||
sdb.db = sql.New(en.DataFolder() + "aiimage.db")
|
|
||||||
err := sdb.db.Open(time.Hour)
|
|
||||||
if err == nil {
|
|
||||||
// 创建配置表
|
|
||||||
err = sdb.db.Create("config", &imageConfig{})
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("[ERROR]:", err))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("[ERROR]:", err))
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
en.OnPrefix("设置AI画图密钥", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
apiKey := strings.TrimSpace(ctx.State["args"].(string))
|
|
||||||
cfg := sdb.getConfig()
|
|
||||||
err := sdb.setConfig(apiKey, cfg.APIURL, cfg.ModelName)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: 设置API密钥失败: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("成功设置API密钥"))
|
|
||||||
})
|
|
||||||
|
|
||||||
en.OnPrefix("设置AI画图接口地址", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
apiURL := strings.TrimSpace(ctx.State["args"].(string))
|
|
||||||
cfg := sdb.getConfig()
|
|
||||||
err := sdb.setConfig(cfg.APIKey, apiURL, cfg.ModelName)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: 设置API地址失败: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("成功设置API地址"))
|
|
||||||
})
|
|
||||||
|
|
||||||
en.OnPrefix("设置AI画图模型名", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
modelName := strings.TrimSpace(ctx.State["args"].(string))
|
|
||||||
cfg := sdb.getConfig()
|
|
||||||
err := sdb.setConfig(cfg.APIKey, cfg.APIURL, modelName)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: 设置模型失败: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("成功设置模型: ", modelName))
|
|
||||||
})
|
|
||||||
|
|
||||||
en.OnFullMatch("查看AI画图配置", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
ctx.SendChain(message.Text(sdb.PrintConfig()))
|
|
||||||
})
|
|
||||||
|
|
||||||
en.OnPrefix("AI画图", getdb).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
ctx.SendChain(message.Text("少女思考中..."))
|
|
||||||
prompt := strings.TrimSpace(ctx.State["args"].(string))
|
|
||||||
if prompt == "" {
|
|
||||||
ctx.SendChain(message.Text("请输入图片描述"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := sdb.getConfig()
|
|
||||||
if cfg.APIKey == "" || cfg.APIURL == "" || cfg.ModelName == "" {
|
|
||||||
ctx.SendChain(message.Text("请先配置API密钥、地址和模型"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 准备请求数据
|
|
||||||
reqBytes, _ := json.Marshal(map[string]interface{}{
|
|
||||||
"model": cfg.ModelName,
|
|
||||||
"prompt": prompt,
|
|
||||||
"image_size": "1024x1024",
|
|
||||||
"batch_size": 4,
|
|
||||||
"num_inference_steps": 20,
|
|
||||||
"guidance_scale": 7.5,
|
|
||||||
})
|
|
||||||
|
|
||||||
// 发送API请求
|
|
||||||
data, err := web.RequestDataWithHeaders(
|
|
||||||
web.NewDefaultClient(),
|
|
||||||
cfg.APIURL,
|
|
||||||
"POST",
|
|
||||||
func(req *http.Request) error {
|
|
||||||
req.Header.Set("Authorization", "Bearer "+cfg.APIKey)
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
bytes.NewReader(reqBytes),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("API请求失败: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析API响应
|
|
||||||
jsonData := gjson.ParseBytes(data)
|
|
||||||
images := jsonData.Get("images")
|
|
||||||
if !images.Exists() {
|
|
||||||
images = jsonData.Get("data")
|
|
||||||
if !images.Exists() {
|
|
||||||
ctx.SendChain(message.Text("未获取到图片URL"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送生成的图片和相关信息
|
|
||||||
inferenceTime := jsonData.Get("timings.inference").Float()
|
|
||||||
seed := jsonData.Get("seed").Int()
|
|
||||||
msg := make(message.Message, 0, 1)
|
|
||||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text("图片生成成功!\n",
|
|
||||||
"提示词: ", prompt, "\n",
|
|
||||||
"模型: ", cfg.ModelName, "\n",
|
|
||||||
"推理时间: ", inferenceTime, "秒\n",
|
|
||||||
"种子: ", seed)))
|
|
||||||
|
|
||||||
// 添加所有图片
|
|
||||||
images.ForEach(func(_, value gjson.Result) bool {
|
|
||||||
url := value.Get("url").String()
|
|
||||||
if url != "" {
|
|
||||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Image(url)))
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
if len(msg) > 0 {
|
|
||||||
ctx.Send(msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
// Package airecord 群应用:AI声聊
|
|
||||||
package airecord
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
|
||||||
|
|
||||||
"github.com/FloatTech/AnimeAPI/airecord"
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
|
||||||
"github.com/FloatTech/zbputils/control"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
||||||
DisableOnDefault: false,
|
|
||||||
Extra: control.ExtraFromString("airecord"),
|
|
||||||
Brief: "群应用:AI声聊",
|
|
||||||
Help: "- 设置AI语音群号1048452984(tips:机器人任意所在群聊即可)\n" +
|
|
||||||
"- 设置AI语音模型\n" +
|
|
||||||
"- 查看AI语音配置\n" +
|
|
||||||
"- 发送AI语音xxx",
|
|
||||||
PrivateDataFolder: "airecord",
|
|
||||||
})
|
|
||||||
|
|
||||||
en.OnPrefix("设置AI语音群号", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
u := strings.TrimSpace(ctx.State["args"].(string))
|
|
||||||
num, err := strconv.ParseInt(u, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: parse gid err: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = airecord.SetCustomGID(num)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: set gid err: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("设置AI语音群号为", num))
|
|
||||||
})
|
|
||||||
en.OnFullMatch("设置AI语音模型", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
|
|
||||||
recv, cancel := next.Repeat()
|
|
||||||
defer cancel()
|
|
||||||
jsonData := ctx.GetAICharacters(0, 1)
|
|
||||||
|
|
||||||
// 转换为字符串数组
|
|
||||||
var names []string
|
|
||||||
// 初始化两个映射表
|
|
||||||
nameToID := make(map[string]string)
|
|
||||||
nameToURL := make(map[string]string)
|
|
||||||
characters := jsonData.Get("#.characters")
|
|
||||||
|
|
||||||
// 遍历每个角色对象
|
|
||||||
characters.ForEach(func(_, group gjson.Result) bool {
|
|
||||||
group.ForEach(func(_, character gjson.Result) bool {
|
|
||||||
// 提取当前角色的三个字段
|
|
||||||
name := character.Get("character_name").String()
|
|
||||||
names = append(names, name)
|
|
||||||
// 存入映射表(重复名称会覆盖,保留最后出现的条目)
|
|
||||||
nameToID[name] = character.Get("character_id").String()
|
|
||||||
nameToURL[name] = character.Get("preview_url").String()
|
|
||||||
return true // 继续遍历
|
|
||||||
})
|
|
||||||
return true // 继续遍历
|
|
||||||
})
|
|
||||||
var builder strings.Builder
|
|
||||||
// 写入开头文本
|
|
||||||
builder.WriteString("请选择语音模型序号:\n")
|
|
||||||
|
|
||||||
// 遍历names数组,拼接序号和名称
|
|
||||||
for i, v := range names {
|
|
||||||
// 将数字转换为字符串(不依赖fmt)
|
|
||||||
numStr := strconv.Itoa(i)
|
|
||||||
// 拼接格式:"序号. 名称\n"
|
|
||||||
builder.WriteString(numStr)
|
|
||||||
builder.WriteString(". ")
|
|
||||||
builder.WriteString(v)
|
|
||||||
builder.WriteString("\n")
|
|
||||||
}
|
|
||||||
// 获取最终字符串
|
|
||||||
ctx.SendChain(message.Text(builder.String()))
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-time.After(time.Second * 120):
|
|
||||||
ctx.SendChain(message.Text("设置AI语音模型指令过期"))
|
|
||||||
return
|
|
||||||
case ct := <-recv:
|
|
||||||
msg := ct.Event.Message.ExtractPlainText()
|
|
||||||
num, err := strconv.Atoi(msg)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("请输入数字!"))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if num < 0 || num >= len(names) {
|
|
||||||
ctx.SendChain(message.Text("序号非法!"))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err = airecord.SetRecordModel(names[num], nameToID[names[num]])
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: set model err: ", err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("已选择语音模型: ", names[num]))
|
|
||||||
ctx.SendChain(message.Record(nameToURL[names[num]]))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
en.OnFullMatch("查看AI语音配置", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
ctx.SendChain(message.Text(airecord.PrintRecordConfig()))
|
|
||||||
})
|
|
||||||
en.OnPrefix("发送AI语音", zero.UserOrGrpAdmin).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
u := strings.TrimSpace(ctx.State["args"].(string))
|
|
||||||
recCfg := airecord.GetConfig()
|
|
||||||
record := ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, u)
|
|
||||||
if record == "" {
|
|
||||||
id := ctx.SendGroupAIRecord(recCfg.ModelID, ctx.Event.GroupID, u)
|
|
||||||
if id == "" {
|
|
||||||
ctx.SendChain(message.Text("ERROR: get record err: empty record"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Record(record))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -23,7 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.Register("animetrace", &ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "AnimeTrace 动画/Galgame识别插件",
|
Brief: "AnimeTrace 动画/Galgame识别插件",
|
||||||
Help: "- Gal识图\n- 动漫识图\n- 动漫识图 2\n- 动漫识图 [模型名]\n- Gal识图 [模型名]",
|
Help: "- Gal识图\n- 动漫识图\n- 动漫识图 2\n- 动漫识图 [模型名]\n- Gal识图 [模型名]",
|
||||||
|
|||||||
@ -17,12 +17,7 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const bandur time.Duration = time.Minute * 10
|
||||||
bandur time.Duration = time.Minute * 2
|
|
||||||
add = "添加违禁词"
|
|
||||||
del = "删除违禁词"
|
|
||||||
list = "查看违禁词"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
managers *ctrl.Manager[*zero.Ctx] // managers lazy load
|
managers *ctrl.Manager[*zero.Ctx] // managers lazy load
|
||||||
@ -46,7 +41,7 @@ func init() {
|
|||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "违禁词检测",
|
Brief: "违禁词检测",
|
||||||
Help: "- [添加|删除|查看]违禁词",
|
Help: "- /[添加|删除|查看]违禁词",
|
||||||
PrivateDataFolder: "anti_abuse",
|
PrivateDataFolder: "anti_abuse",
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -61,14 +56,10 @@ func init() {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
notAntiabuse := func(ctx *zero.Ctx) bool {
|
engine.OnMessage(onceRule, zero.OnlyGroup, func(ctx *zero.Ctx) bool {
|
||||||
if zero.PrefixRule(add)(ctx) || zero.PrefixRule(del)(ctx) || zero.PrefixRule(list)(ctx) {
|
if !ctx.Event.IsToMe {
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
engine.OnMessage(onceRule, notAntiabuse, zero.OnlyGroup, func(ctx *zero.Ctx) bool {
|
|
||||||
uid := ctx.Event.UserID
|
uid := ctx.Event.UserID
|
||||||
gid := ctx.Event.GroupID
|
gid := ctx.Event.GroupID
|
||||||
msg := strings.ReplaceAll(ctx.MessageString(), "\n", "")
|
msg := strings.ReplaceAll(ctx.MessageString(), "\n", "")
|
||||||
@ -79,8 +70,7 @@ func init() {
|
|||||||
if err := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).Manager.DoBlock(uid); err == nil {
|
if err := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).Manager.DoBlock(uid); err == nil {
|
||||||
t := time.Now().Unix()
|
t := time.Now().Unix()
|
||||||
cache.Set(uid, struct{}{})
|
cache.Set(uid, struct{}{})
|
||||||
ctx.SetThisGroupBan(uid, int64(bandur.Seconds()))
|
ctx.SetThisGroupBan(uid, int64(bandur.Minutes()))
|
||||||
ctx.DeleteMessage(ctx.Event.MessageID)
|
|
||||||
ctx.SendChain(message.Text("检测到违禁词, 已封禁/屏蔽", bandur))
|
ctx.SendChain(message.Text("检测到违禁词, 已封禁/屏蔽", bandur))
|
||||||
db.Lock()
|
db.Lock()
|
||||||
defer db.Unlock()
|
defer db.Unlock()
|
||||||
@ -102,9 +92,9 @@ func init() {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
engine.OnPrefix(add, zero.OnlyGroup, zero.AdminPermission, onceRule).SetBlock(true).Handle(
|
engine.OnCommand("添加违禁词", zero.OnlyGroup, zero.AdminPermission, onceRule).Handle(
|
||||||
func(ctx *zero.Ctx) {
|
func(ctx *zero.Ctx) {
|
||||||
args := strings.TrimSpace(ctx.State["args"].(string))
|
args := ctx.State["args"].(string)
|
||||||
if err := db.insertWord(ctx.Event.GroupID, args); err != nil {
|
if err := db.insertWord(ctx.Event.GroupID, args); err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
} else {
|
} else {
|
||||||
@ -112,9 +102,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
engine.OnPrefix(del, zero.OnlyGroup, zero.AdminPermission, onceRule).SetBlock(true).Handle(
|
engine.OnCommand("删除违禁词", zero.OnlyGroup, zero.AdminPermission, onceRule).Handle(
|
||||||
func(ctx *zero.Ctx) {
|
func(ctx *zero.Ctx) {
|
||||||
args := strings.TrimSpace(ctx.State["args"].(string))
|
args := ctx.State["args"].(string)
|
||||||
if err := db.deleteWord(ctx.Event.GroupID, args); err != nil {
|
if err := db.deleteWord(ctx.Event.GroupID, args); err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
} else {
|
} else {
|
||||||
@ -122,7 +112,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
engine.OnPrefix(list, zero.OnlyGroup, onceRule).SetBlock(true).Handle(
|
engine.OnCommand("查看违禁词", zero.OnlyGroup, onceRule).Handle(
|
||||||
func(ctx *zero.Ctx) {
|
func(ctx *zero.Ctx) {
|
||||||
b, err := text.RenderToBase64(db.listWords(ctx.Event.GroupID), text.FontFile, 400, 20)
|
b, err := text.RenderToBase64(db.listWords(ctx.Event.GroupID), text.FontFile, 400, 20)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@ -30,6 +31,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
re = regexp.MustCompile(`^\d+$`)
|
||||||
danmakuTypeMap = map[int64]string{
|
danmakuTypeMap = map[int64]string{
|
||||||
0: "普通消息",
|
0: "普通消息",
|
||||||
1: "礼物",
|
1: "礼物",
|
||||||
@ -71,7 +73,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
engine.OnRegex(`^>user info\s?(.{1,25})$`, bz.RequireUser(cfg)).SetBlock(true).
|
engine.OnRegex(`^>user info\s?(.{1,25})$`, getPara).SetBlock(true).
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
id := ctx.State["uid"].(string)
|
id := ctx.State["uid"].(string)
|
||||||
card, err := bz.GetMemberCard(id)
|
card, err := bz.GetMemberCard(id)
|
||||||
@ -89,7 +91,7 @@ func init() {
|
|||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
engine.OnRegex(`^>vup info\s?(.{1,25})$`, bz.RequireUser(cfg)).SetBlock(true).
|
engine.OnRegex(`^>vup info\s?(.{1,25})$`, getPara).SetBlock(true).
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
id := ctx.State["uid"].(string)
|
id := ctx.State["uid"].(string)
|
||||||
// 获取详情
|
// 获取详情
|
||||||
@ -112,7 +114,7 @@ func init() {
|
|||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
engine.OnRegex(`^查成分\s?(.{1,25})$`, bz.RequireUser(cfg), getdb).SetBlock(true).
|
engine.OnRegex(`^查成分\s?(.{1,25})$`, getPara, getdb).SetBlock(true).
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
id := ctx.State["uid"].(string)
|
id := ctx.State["uid"].(string)
|
||||||
today := time.Now().Format("20060102")
|
today := time.Now().Format("20060102")
|
||||||
@ -132,7 +134,7 @@ func init() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
vupLen := len(vups)
|
vupLen := len(vups)
|
||||||
medals, err := cfg.GetMedalWall(id)
|
medals, err := bz.GetMedalWall(cfg, id)
|
||||||
sort.Sort(bz.MedalSorter(medals))
|
sort.Sort(bz.MedalSorter(medals))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
@ -273,7 +275,7 @@ func init() {
|
|||||||
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
|
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
|
||||||
})
|
})
|
||||||
|
|
||||||
engine.OnRegex(`^查弹幕\s?(\S{1,25})\s?(\d*)$`, bz.RequireUser(cfg)).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
engine.OnRegex(`^查弹幕\s?(\S{1,25})\s?(\d*)$`, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
id := ctx.State["uid"].(string)
|
id := ctx.State["uid"].(string)
|
||||||
pagenum := ctx.State["regex_matched"].([]string)[2]
|
pagenum := ctx.State["regex_matched"].([]string)[2]
|
||||||
if pagenum == "" {
|
if pagenum == "" {
|
||||||
@ -580,3 +582,51 @@ func int2rbg(t int64) (int64, int64, int64) {
|
|||||||
b, g, r := int64(buf[0]), int64(buf[1]), int64(buf[2])
|
b, g, r := int64(buf[0]), int64(buf[1]), int64(buf[2])
|
||||||
return r, g, b
|
return r, g, b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getPara(ctx *zero.Ctx) bool {
|
||||||
|
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
if !re.MatchString(keyword) {
|
||||||
|
searchRes, err := bz.SearchUser(cfg, keyword)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
|
||||||
|
recv, cancel := next.Repeat()
|
||||||
|
defer cancel()
|
||||||
|
ctx.SendChain(message.Text("输入为纯数字, 请选择查询uid还是用户名, 输入对应序号:\n0. 查询uid\n1. 查询用户名"))
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-time.After(time.Second * 10):
|
||||||
|
ctx.SendChain(message.Text("时间太久啦!", zero.BotConfig.NickName[0], "帮你选择查询uid"))
|
||||||
|
ctx.State["uid"] = keyword
|
||||||
|
return true
|
||||||
|
case c := <-recv:
|
||||||
|
msg := c.Event.Message.ExtractPlainText()
|
||||||
|
num, err := strconv.Atoi(msg)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("请输入数字!"))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if num < 0 || num > 1 {
|
||||||
|
ctx.SendChain(message.Text("序号非法!"))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if num == 0 {
|
||||||
|
ctx.State["uid"] = keyword
|
||||||
|
return true
|
||||||
|
} else if num == 1 {
|
||||||
|
searchRes, err := bz.SearchUser(cfg, keyword)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// Package bilibiliparse bilibili卡片解析
|
// Package bilibili bilibili卡片解析
|
||||||
package bilibiliparse
|
package bilibili
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -24,12 +24,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
enableVideoSummary = int64(0x10)
|
enableHex = 0x10
|
||||||
disableVideoSummary = ^enableVideoSummary
|
unableHex = 0x7fffffff_fffffffd
|
||||||
enableVideoDownload = int64(0x20)
|
|
||||||
disableVideoDownload = ^enableVideoDownload
|
|
||||||
bilibiliparseReferer = "https://www.bilibili.com"
|
bilibiliparseReferer = "https://www.bilibili.com"
|
||||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -43,12 +40,11 @@ var (
|
|||||||
searchArticleRe = regexp.MustCompile(searchArticle)
|
searchArticleRe = regexp.MustCompile(searchArticle)
|
||||||
searchLiveRoomRe = regexp.MustCompile(searchLiveRoom)
|
searchLiveRoomRe = regexp.MustCompile(searchLiveRoom)
|
||||||
cachePath string
|
cachePath string
|
||||||
cfg = bz.NewCookieConfig("data/Bilibili/config.json")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 插件主体
|
// 插件主体
|
||||||
func init() {
|
func init() {
|
||||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
en := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "b站链接解析",
|
Brief: "b站链接解析",
|
||||||
Help: "例:- t.bilibili.com/642277677329285174\n- bilibili.com/read/cv17134450\n- bilibili.com/video/BV13B4y1x7pS\n- live.bilibili.com/22603245 ",
|
Help: "例:- t.bilibili.com/642277677329285174\n- bilibili.com/read/cv17134450\n- bilibili.com/video/BV13B4y1x7pS\n- live.bilibili.com/22603245 ",
|
||||||
@ -96,9 +92,9 @@ func init() {
|
|||||||
data := c.GetData(ctx.Event.GroupID)
|
data := c.GetData(ctx.Event.GroupID)
|
||||||
switch option {
|
switch option {
|
||||||
case "开启", "打开", "启用":
|
case "开启", "打开", "启用":
|
||||||
data |= enableVideoSummary
|
data |= enableHex
|
||||||
case "关闭", "关掉", "禁用":
|
case "关闭", "关掉", "禁用":
|
||||||
data &= disableVideoSummary
|
data &= unableHex
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -109,35 +105,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
ctx.SendChain(message.Text("已", option, "视频总结"))
|
ctx.SendChain(message.Text("已", option, "视频总结"))
|
||||||
})
|
})
|
||||||
en.OnRegex(`^(开启|打开|启用|关闭|关掉|禁用)视频上传$`, zero.AdminPermission).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
gid := ctx.Event.GroupID
|
|
||||||
if gid <= 0 {
|
|
||||||
// 个人用户设为负数
|
|
||||||
gid = -ctx.Event.UserID
|
|
||||||
}
|
|
||||||
option := ctx.State["regex_matched"].([]string)[1]
|
|
||||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
|
||||||
if !ok {
|
|
||||||
ctx.SendChain(message.Text("找不到服务!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := c.GetData(ctx.Event.GroupID)
|
|
||||||
switch option {
|
|
||||||
case "开启", "打开", "启用":
|
|
||||||
data |= enableVideoDownload
|
|
||||||
case "关闭", "关掉", "禁用":
|
|
||||||
data &= disableVideoDownload
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err := c.SetData(gid, data)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("出错啦: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("已", option, "视频上传"))
|
|
||||||
})
|
|
||||||
en.OnRegex(searchVideo).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleVideo)
|
en.OnRegex(searchVideo).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleVideo)
|
||||||
en.OnRegex(searchDynamic).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleDynamic)
|
en.OnRegex(searchDynamic).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleDynamic)
|
||||||
en.OnRegex(searchArticle).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleArticle)
|
en.OnRegex(searchArticle).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleArticle)
|
||||||
@ -154,13 +121,13 @@ func handleVideo(ctx *zero.Ctx) {
|
|||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
msg, err := card.ToVideoMessage()
|
msg, err := videoCard2msg(card)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
if ok && c.GetData(ctx.Event.GroupID)&enableVideoSummary == enableVideoSummary {
|
if ok && c.GetData(ctx.Event.GroupID)&enableHex == enableHex {
|
||||||
summaryMsg, err := getVideoSummary(cfg, card)
|
summaryMsg, err := getVideoSummary(cfg, card)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg = append(msg, message.Text("ERROR: ", err))
|
msg = append(msg, message.Text("ERROR: ", err))
|
||||||
@ -169,18 +136,16 @@ func handleVideo(ctx *zero.Ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.SendChain(msg...)
|
ctx.SendChain(msg...)
|
||||||
if ok && c.GetData(ctx.Event.GroupID)&enableVideoDownload == enableVideoDownload {
|
downLoadMsg, err := getVideoDownload(cfg, card, cachePath)
|
||||||
downLoadMsg, err := getVideoDownload(cfg, card, cachePath)
|
if err != nil {
|
||||||
if err != nil {
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(downLoadMsg...)
|
|
||||||
}
|
}
|
||||||
|
ctx.SendChain(downLoadMsg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDynamic(ctx *zero.Ctx) {
|
func handleDynamic(ctx *zero.Ctx) {
|
||||||
msg, err := cfg.GetDetailMessage(ctx.State["regex_matched"].([]string)[2])
|
msg, err := dynamicDetail(cfg, ctx.State["regex_matched"].([]string)[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
@ -194,21 +159,16 @@ func handleArticle(ctx *zero.Ctx) {
|
|||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.SendChain(card.ToArticleMessage(ctx.State["regex_matched"].([]string)[1])...)
|
ctx.SendChain(articleCard2msg(card, ctx.State["regex_matched"].([]string)[1])...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleLive(ctx *zero.Ctx) {
|
func handleLive(ctx *zero.Ctx) {
|
||||||
cookie, err := cfg.Load()
|
card, err := bz.GetLiveRoomInfo(ctx.State["regex_matched"].([]string)[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
card, err := bz.GetLiveRoomInfo(ctx.State["regex_matched"].([]string)[1], cookie)
|
ctx.SendChain(liveCard2msg(card)...)
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(card.ToMessage()...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getVideoSummary AI视频总结
|
// getVideoSummary AI视频总结
|
||||||
@ -1,5 +1,5 @@
|
|||||||
// Package bilibilipush b站推送
|
// Package bilibili b站推送
|
||||||
package bilibilipush
|
package bilibili
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -34,11 +34,10 @@ var (
|
|||||||
lastTime = map[int64]int64{}
|
lastTime = map[int64]int64{}
|
||||||
liveStatus = map[int64]int{}
|
liveStatus = map[int64]int{}
|
||||||
upMap = map[int64]string{}
|
upMap = map[int64]string{}
|
||||||
cfg = bz.NewCookieConfig("data/Bilibili/config.json")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
en := control.Register("bilibilipush", &ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "b站推送",
|
Brief: "b站推送",
|
||||||
Help: "- 添加b站订阅[uid|name]\n" +
|
Help: "- 添加b站订阅[uid|name]\n" +
|
||||||
@ -76,7 +75,7 @@ func init() {
|
|||||||
ctx.SendChain(message.Text("已关闭艾特全体Oo"))
|
ctx.SendChain(message.Text("已关闭艾特全体Oo"))
|
||||||
})
|
})
|
||||||
|
|
||||||
en.OnRegex(`^添加[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, bz.RequireUser(cfg)).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnRegex(`^添加[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||||
name, err := getName(buid, cfg)
|
name, err := getName(buid, cfg)
|
||||||
if err != nil || name == "" {
|
if err != nil || name == "" {
|
||||||
@ -94,7 +93,7 @@ func init() {
|
|||||||
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
|
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
|
||||||
})
|
})
|
||||||
|
|
||||||
en.OnRegex(`^取消[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, bz.RequireUser(cfg)).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnRegex(`^取消[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||||
name, err := getName(buid, cfg)
|
name, err := getName(buid, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -111,7 +110,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
ctx.SendChain(message.Text("已取消" + name + "的订阅"))
|
ctx.SendChain(message.Text("已取消" + name + "的订阅"))
|
||||||
})
|
})
|
||||||
en.OnRegex(`^取消[B|b]站动态订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, bz.RequireUser(cfg)).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnRegex(`^取消[B|b]站动态订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||||
name, err := getName(buid, cfg)
|
name, err := getName(buid, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -128,7 +127,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
ctx.SendChain(message.Text("已取消" + name + "的动态订阅"))
|
ctx.SendChain(message.Text("已取消" + name + "的动态订阅"))
|
||||||
})
|
})
|
||||||
en.OnRegex(`^取消[B|b]站直播订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, bz.RequireUser(cfg)).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnRegex(`^取消[B|b]站直播订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||||
gid := ctx.Event.GroupID
|
gid := ctx.Event.GroupID
|
||||||
if gid == 0 {
|
if gid == 0 {
|
||||||
@ -334,7 +333,7 @@ func sendDynamic(ctx *zero.Ctx) error {
|
|||||||
err = errors.Errorf("动态%v的解析有问题,%v", cardList[i].Get("desc.dynamic_id_str"), err)
|
err = errors.Errorf("动态%v的解析有问题,%v", cardList[i].Get("desc.dynamic_id_str"), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msg, err := dc.ToMessage()
|
msg, err := dynamicCard2msg(&dc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Errorf("动态%v的解析有问题,%v", cardList[i].Get("desc.dynamic_id_str"), err)
|
err = errors.Errorf("动态%v的解析有问题,%v", cardList[i].Get("desc.dynamic_id_str"), err)
|
||||||
return err
|
return err
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package bilibilipush
|
package bilibili
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
342
plugin/bilibili/card2msg.go
Normal file
342
plugin/bilibili/card2msg.go
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
package bilibili
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
bz "github.com/FloatTech/AnimeAPI/bilibili"
|
||||||
|
"github.com/FloatTech/floatbox/binary"
|
||||||
|
"github.com/FloatTech/floatbox/web"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
msgType = map[int]string{
|
||||||
|
1: "转发了动态",
|
||||||
|
2: "有图营业",
|
||||||
|
4: "无图营业",
|
||||||
|
8: "投稿了视频",
|
||||||
|
16: "投稿了短视频",
|
||||||
|
64: "投稿了文章",
|
||||||
|
256: "投稿了音频",
|
||||||
|
2048: "发布了简报",
|
||||||
|
4200: "发布了直播",
|
||||||
|
4308: "发布了直播",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// dynamicCard2msg 处理DynCard
|
||||||
|
func dynamicCard2msg(dynamicCard *bz.DynamicCard) (msg []message.Segment, err error) {
|
||||||
|
var (
|
||||||
|
card bz.Card
|
||||||
|
vote bz.Vote
|
||||||
|
cType int
|
||||||
|
)
|
||||||
|
msg = make([]message.Segment, 0, 16)
|
||||||
|
// 初始化结构体
|
||||||
|
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Card), &card)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if dynamicCard.Extension.Vote != "" {
|
||||||
|
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Extension.Vote), &vote)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cType = dynamicCard.Desc.Type
|
||||||
|
// 生成消息
|
||||||
|
switch cType {
|
||||||
|
case 1:
|
||||||
|
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
|
||||||
|
card.Item.Content, "\n",
|
||||||
|
"转发的内容: \n"))
|
||||||
|
var originMsg []message.Segment
|
||||||
|
var co bz.Card
|
||||||
|
co, err = bz.LoadCardDetail(card.Origin)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
originMsg, err = card2msg(dynamicCard, &co, card.Item.OrigType)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg = append(msg, originMsg...)
|
||||||
|
case 2:
|
||||||
|
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Item.Description))
|
||||||
|
for i := 0; i < len(card.Item.Pictures); i++ {
|
||||||
|
msg = append(msg, message.Image(card.Item.Pictures[i].ImgSrc))
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
msg = append(msg, message.Text(card.User.Uname, "在", time.Unix(int64(card.Item.Timestamp), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Item.Content, "\n"))
|
||||||
|
if dynamicCard.Extension.Vote != "" {
|
||||||
|
msg = append(msg, message.Text("【投票】", vote.Desc, "\n",
|
||||||
|
"截止日期: ", time.Unix(int64(vote.Endtime), 0).Format("2006-01-02 15:04:05"), "\n",
|
||||||
|
"参与人数: ", bz.HumanNum(vote.JoinNum), "\n",
|
||||||
|
"投票选项( 最多选择", vote.ChoiceCnt, "项 )\n"))
|
||||||
|
for i := 0; i < len(vote.Options); i++ {
|
||||||
|
msg = append(msg, message.Text("- ", vote.Options[i].Idx, ". ", vote.Options[i].Desc, "\n"))
|
||||||
|
if vote.Options[i].ImgURL != "" {
|
||||||
|
msg = append(msg, message.Image(vote.Options[i].ImgURL))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
msg = append(msg, message.Text(card.Owner.Name, "在", time.Unix(int64(card.Pubdate), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Title))
|
||||||
|
msg = append(msg, message.Image(card.Pic))
|
||||||
|
msg = append(msg, message.Text(card.Desc, "\n",
|
||||||
|
card.ShareSubtitle, "\n",
|
||||||
|
"视频链接: ", card.ShortLink, "\n"))
|
||||||
|
case 16:
|
||||||
|
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Item.Description))
|
||||||
|
msg = append(msg, message.Image(card.Item.Cover.Default))
|
||||||
|
case 64:
|
||||||
|
msg = append(msg, message.Text(card.Author.(map[string]any)["name"], "在", time.Unix(int64(card.PublishTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Title, "\n",
|
||||||
|
card.Summary))
|
||||||
|
for i := 0; i < len(card.ImageUrls); i++ {
|
||||||
|
msg = append(msg, message.Image(card.ImageUrls[i]))
|
||||||
|
}
|
||||||
|
if card.ID != 0 {
|
||||||
|
msg = append(msg, message.Text("文章链接: https://www.bilibili.com/read/cv", card.ID, "\n"))
|
||||||
|
}
|
||||||
|
case 256:
|
||||||
|
msg = append(msg, message.Text(card.Upper, "在", time.Unix(int64(card.Ctime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Title))
|
||||||
|
msg = append(msg, message.Image(card.Cover))
|
||||||
|
msg = append(msg, message.Text(card.Intro, "\n"))
|
||||||
|
if card.ID != 0 {
|
||||||
|
msg = append(msg, message.Text("音频链接: https://www.bilibili.com/audio/au", card.ID, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2048:
|
||||||
|
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
|
||||||
|
card.Vest.Content, "\n",
|
||||||
|
card.Sketch.Title, "\n",
|
||||||
|
card.Sketch.DescText, "\n"))
|
||||||
|
msg = append(msg, message.Image(card.Sketch.CoverURL))
|
||||||
|
msg = append(msg, message.Text("分享链接: ", card.Sketch.TargetURL, "\n"))
|
||||||
|
case 4308:
|
||||||
|
if dynamicCard.Desc.UserProfile.Info.Uname != "" {
|
||||||
|
msg = append(msg, message.Text(dynamicCard.Desc.UserProfile.Info.Uname, msgType[cType], "\n"))
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Image(card.LivePlayInfo.Cover))
|
||||||
|
msg = append(msg, message.Text("\n", card.LivePlayInfo.Title, "\n",
|
||||||
|
"房间号: ", card.LivePlayInfo.RoomID, "\n",
|
||||||
|
"分区: ", card.LivePlayInfo.ParentAreaName))
|
||||||
|
if card.LivePlayInfo.ParentAreaName != card.LivePlayInfo.AreaName {
|
||||||
|
msg = append(msg, message.Text("-", card.LivePlayInfo.AreaName))
|
||||||
|
}
|
||||||
|
if card.LivePlayInfo.LiveStatus == 0 {
|
||||||
|
msg = append(msg, message.Text("未开播 \n"))
|
||||||
|
} else {
|
||||||
|
msg = append(msg, message.Text("直播中 ", card.LivePlayInfo.WatchedShow, "\n"))
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Text("直播链接: ", card.LivePlayInfo.Link))
|
||||||
|
default:
|
||||||
|
msg = append(msg, message.Text("动态id: ", dynamicCard.Desc.DynamicIDStr, "未知动态类型: ", cType, "\n"))
|
||||||
|
}
|
||||||
|
if dynamicCard.Desc.DynamicIDStr != "" {
|
||||||
|
msg = append(msg, message.Text("动态链接: ", bz.TURL, dynamicCard.Desc.DynamicIDStr))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// card2msg cType=1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308时,处理Card字符串,cType为card类型
|
||||||
|
func card2msg(dynamicCard *bz.DynamicCard, card *bz.Card, cType int) (msg []message.Segment, err error) {
|
||||||
|
var (
|
||||||
|
vote bz.Vote
|
||||||
|
)
|
||||||
|
msg = make([]message.Segment, 0, 16)
|
||||||
|
// 生成消息
|
||||||
|
switch cType {
|
||||||
|
case 1:
|
||||||
|
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
|
||||||
|
card.Item.Content, "\n",
|
||||||
|
"转发的内容: \n"))
|
||||||
|
var originMsg []message.Segment
|
||||||
|
var co bz.Card
|
||||||
|
co, err = bz.LoadCardDetail(card.Origin)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
originMsg, err = card2msg(dynamicCard, &co, card.Item.OrigType)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg = append(msg, originMsg...)
|
||||||
|
case 2:
|
||||||
|
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Item.Description))
|
||||||
|
for i := 0; i < len(card.Item.Pictures); i++ {
|
||||||
|
msg = append(msg, message.Image(card.Item.Pictures[i].ImgSrc))
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
msg = append(msg, message.Text(card.User.Uname, "在", time.Unix(int64(card.Item.Timestamp), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Item.Content, "\n"))
|
||||||
|
if dynamicCard.Extension.Vote != "" {
|
||||||
|
msg = append(msg, message.Text("【投票】", vote.Desc, "\n",
|
||||||
|
"截止日期: ", time.Unix(int64(vote.Endtime), 0).Format("2006-01-02 15:04:05"), "\n",
|
||||||
|
"参与人数: ", bz.HumanNum(vote.JoinNum), "\n",
|
||||||
|
"投票选项( 最多选择", vote.ChoiceCnt, "项 )\n"))
|
||||||
|
for i := 0; i < len(vote.Options); i++ {
|
||||||
|
msg = append(msg, message.Text("- ", vote.Options[i].Idx, ". ", vote.Options[i].Desc, "\n"))
|
||||||
|
if vote.Options[i].ImgURL != "" {
|
||||||
|
msg = append(msg, message.Image(vote.Options[i].ImgURL))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
msg = append(msg, message.Text(card.Owner.Name, "在", time.Unix(int64(card.Pubdate), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Title))
|
||||||
|
msg = append(msg, message.Image(card.Pic))
|
||||||
|
msg = append(msg, message.Text(card.Desc, "\n",
|
||||||
|
card.ShareSubtitle, "\n",
|
||||||
|
"视频链接: ", card.ShortLink, "\n"))
|
||||||
|
case 16:
|
||||||
|
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Item.Description))
|
||||||
|
msg = append(msg, message.Image(card.Item.Cover.Default))
|
||||||
|
case 64:
|
||||||
|
msg = append(msg, message.Text(card.Author.(map[string]any)["name"], "在", time.Unix(int64(card.PublishTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Title, "\n",
|
||||||
|
card.Summary))
|
||||||
|
for i := 0; i < len(card.ImageUrls); i++ {
|
||||||
|
msg = append(msg, message.Image(card.ImageUrls[i]))
|
||||||
|
}
|
||||||
|
if card.ID != 0 {
|
||||||
|
msg = append(msg, message.Text("文章链接: https://www.bilibili.com/read/cv", card.ID, "\n"))
|
||||||
|
}
|
||||||
|
case 256:
|
||||||
|
msg = append(msg, message.Text(card.Upper, "在", time.Unix(int64(card.Ctime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
|
||||||
|
card.Title))
|
||||||
|
msg = append(msg, message.Image(card.Cover))
|
||||||
|
msg = append(msg, message.Text(card.Intro, "\n"))
|
||||||
|
if card.ID != 0 {
|
||||||
|
msg = append(msg, message.Text("音频链接: https://www.bilibili.com/audio/au", card.ID, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2048:
|
||||||
|
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
|
||||||
|
card.Vest.Content, "\n",
|
||||||
|
card.Sketch.Title, "\n",
|
||||||
|
card.Sketch.DescText, "\n"))
|
||||||
|
msg = append(msg, message.Image(card.Sketch.CoverURL))
|
||||||
|
msg = append(msg, message.Text("分享链接: ", card.Sketch.TargetURL, "\n"))
|
||||||
|
case 4308:
|
||||||
|
if dynamicCard.Desc.UserProfile.Info.Uname != "" {
|
||||||
|
msg = append(msg, message.Text(dynamicCard.Desc.UserProfile.Info.Uname, msgType[cType], "\n"))
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Image(card.LivePlayInfo.Cover))
|
||||||
|
msg = append(msg, message.Text("\n", card.LivePlayInfo.Title, "\n",
|
||||||
|
"房间号: ", card.LivePlayInfo.RoomID, "\n",
|
||||||
|
"分区: ", card.LivePlayInfo.ParentAreaName))
|
||||||
|
if card.LivePlayInfo.ParentAreaName != card.LivePlayInfo.AreaName {
|
||||||
|
msg = append(msg, message.Text("-", card.LivePlayInfo.AreaName))
|
||||||
|
}
|
||||||
|
if card.LivePlayInfo.LiveStatus == 0 {
|
||||||
|
msg = append(msg, message.Text("未开播 \n"))
|
||||||
|
} else {
|
||||||
|
msg = append(msg, message.Text("直播中 ", card.LivePlayInfo.WatchedShow, "\n"))
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Text("直播链接: ", card.LivePlayInfo.Link))
|
||||||
|
default:
|
||||||
|
msg = append(msg, message.Text("动态id: ", dynamicCard.Desc.DynamicIDStr, "未知动态类型: ", cType, "\n"))
|
||||||
|
}
|
||||||
|
if dynamicCard.Desc.DynamicIDStr != "" {
|
||||||
|
msg = append(msg, message.Text("动态链接: ", bz.TURL, dynamicCard.Desc.DynamicIDStr))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// dynamicDetail 用动态id查动态信息
|
||||||
|
func dynamicDetail(cookiecfg *bz.CookieConfig, dynamicIDStr string) (msg []message.Segment, err error) {
|
||||||
|
dyc, err := bz.GetDynamicDetail(cookiecfg, dynamicIDStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return dynamicCard2msg(&dyc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// articleCard2msg 专栏转消息
|
||||||
|
func articleCard2msg(card bz.Card, defaultID string) (msg []message.Segment) {
|
||||||
|
msg = make([]message.Segment, 0, 16)
|
||||||
|
for i := 0; i < len(card.OriginImageUrls); i++ {
|
||||||
|
msg = append(msg, message.Image(card.OriginImageUrls[i]))
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Text("\n", card.Title, "\n", "UP主: ", card.AuthorName, "\n",
|
||||||
|
"阅读: ", bz.HumanNum(card.Stats.View), " 评论: ", bz.HumanNum(card.Stats.Reply), "\n",
|
||||||
|
bz.CVURL, defaultID))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// liveCard2msg 直播卡片转消息
|
||||||
|
func liveCard2msg(card bz.RoomCard) (msg []message.Segment) {
|
||||||
|
msg = make([]message.Segment, 0, 16)
|
||||||
|
msg = append(msg, message.Image(card.RoomInfo.Keyframe))
|
||||||
|
msg = append(msg, message.Text("\n", card.RoomInfo.Title, "\n",
|
||||||
|
"主播: ", card.AnchorInfo.BaseInfo.Uname, "\n",
|
||||||
|
"房间号: ", card.RoomInfo.RoomID, "\n"))
|
||||||
|
if card.RoomInfo.ShortID != 0 {
|
||||||
|
msg = append(msg, message.Text("短号: ", card.RoomInfo.ShortID, "\n"))
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Text("分区: ", card.RoomInfo.ParentAreaName))
|
||||||
|
if card.RoomInfo.ParentAreaName != card.RoomInfo.AreaName {
|
||||||
|
msg = append(msg, message.Text("-", card.RoomInfo.AreaName))
|
||||||
|
}
|
||||||
|
if card.RoomInfo.LiveStatus == 0 {
|
||||||
|
msg = append(msg, message.Text("未开播 \n"))
|
||||||
|
} else {
|
||||||
|
msg = append(msg, message.Text("直播中 ", bz.HumanNum(card.RoomInfo.Online), "人气\n"))
|
||||||
|
}
|
||||||
|
if card.RoomInfo.ShortID != 0 {
|
||||||
|
msg = append(msg, message.Text("直播间链接: ", bz.LURL, card.RoomInfo.ShortID))
|
||||||
|
} else {
|
||||||
|
msg = append(msg, message.Text("直播间链接: ", bz.LURL, card.RoomInfo.RoomID))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// videoCard2msg 视频卡片转消息
|
||||||
|
func videoCard2msg(card bz.Card) (msg []message.Segment, err error) {
|
||||||
|
var (
|
||||||
|
mCard bz.MemberCard
|
||||||
|
onlineTotal bz.OnlineTotal
|
||||||
|
)
|
||||||
|
msg = make([]message.Segment, 0, 16)
|
||||||
|
mCard, err = bz.GetMemberCard(card.Owner.Mid)
|
||||||
|
msg = append(msg, message.Text("标题: ", card.Title, "\n"))
|
||||||
|
if card.Rights.IsCooperation == 1 {
|
||||||
|
for i := 0; i < len(card.Staff); i++ {
|
||||||
|
msg = append(msg, message.Text(card.Staff[i].Title, ": ", card.Staff[i].Name, " 粉丝: ", bz.HumanNum(card.Staff[i].Follower), "\n"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
msg = append(msg, message.Text("UP主: ", card.Owner.Name, "\n"))
|
||||||
|
} else {
|
||||||
|
msg = append(msg, message.Text("UP主: ", card.Owner.Name, " 粉丝: ", bz.HumanNum(mCard.Fans), "\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Image(card.Pic))
|
||||||
|
data, err := web.GetData(fmt.Sprintf(bz.OnlineTotalURL, card.BvID, card.CID))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, &onlineTotal)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg = append(msg, message.Text("👀播放: ", bz.HumanNum(card.Stat.View), " 💬弹幕: ", bz.HumanNum(card.Stat.Danmaku),
|
||||||
|
"\n👍点赞: ", bz.HumanNum(card.Stat.Like), " 💰投币: ", bz.HumanNum(card.Stat.Coin),
|
||||||
|
"\n📁收藏: ", bz.HumanNum(card.Stat.Favorite), " 🔗分享: ", bz.HumanNum(card.Stat.Share),
|
||||||
|
"\n📝简介: ", card.Desc,
|
||||||
|
"\n🏄♂️ 总共 ", onlineTotal.Data.Total, " 人在观看,", onlineTotal.Data.Count, " 人在网页端观看\n",
|
||||||
|
bz.VURL, card.BvID, "\n\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
55
plugin/bilibili/card2msg_test.go
Normal file
55
plugin/bilibili/card2msg_test.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package bilibili
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
bz "github.com/FloatTech/AnimeAPI/bilibili"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestArticleInfo(t *testing.T) {
|
||||||
|
card, err := bz.GetArticleInfo("17279244")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(articleCard2msg(card, "17279244"))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMemberCard(t *testing.T) {
|
||||||
|
card, err := bz.GetMemberCard(2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Logf("%+v\n", card)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVideoInfo(t *testing.T) {
|
||||||
|
card, err := bz.GetVideoInfo("10007")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(videoCard2msg(card))
|
||||||
|
card, err = bz.GetVideoInfo("BV1xx411c7mD")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(videoCard2msg(card))
|
||||||
|
card, err = bz.GetVideoInfo("bv1xx411c7mD")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(videoCard2msg(card))
|
||||||
|
card, err = bz.GetVideoInfo("BV1mF411j7iU")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(videoCard2msg(card))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLiveRoomInfo(t *testing.T) {
|
||||||
|
card, err := bz.GetLiveRoomInfo("83171")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(liveCard2msg(card))
|
||||||
|
}
|
||||||
@ -43,15 +43,8 @@ func init() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
engine.OnPrefix(`查询水群`, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
engine.OnPrefix(`查询水群`, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
param := ctx.State["args"].(string)
|
|
||||||
var uid int64
|
|
||||||
if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
|
|
||||||
uid, _ = strconv.ParseInt(ctx.Event.Message[1].Data["qq"], 10, 64)
|
|
||||||
} else if param == "" {
|
|
||||||
uid = ctx.Event.UserID
|
|
||||||
}
|
|
||||||
name := ctx.NickName()
|
name := ctx.NickName()
|
||||||
todayTime, todayMessage, totalTime, totalMessage := ctdb.getChatTime(ctx.Event.GroupID, uid)
|
todayTime, todayMessage, totalTime, totalMessage := ctdb.getChatTime(ctx.Event.GroupID, ctx.Event.UserID)
|
||||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("%s今天水了%d分%d秒,发了%d条消息;总计水了%d分%d秒,发了%d条消息。", name, todayTime/60, todayTime%60, todayMessage, totalTime/60, totalTime%60, totalMessage)))
|
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("%s今天水了%d分%d秒,发了%d条消息;总计水了%d分%d秒,发了%d条消息。", name, todayTime/60, todayTime%60, todayMessage, totalTime/60, totalTime%60, totalMessage)))
|
||||||
})
|
})
|
||||||
engine.OnFullMatch("查看水群排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
|
engine.OnFullMatch("查看水群排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,7 +35,16 @@ var (
|
|||||||
Brief: "国际象棋",
|
Brief: "国际象棋",
|
||||||
Help: helpString,
|
Help: helpString,
|
||||||
PrivateDataFolder: "chess",
|
PrivateDataFolder: "chess",
|
||||||
}).ApplySingle(ctxext.GroupSingle)
|
}).ApplySingle(single.New(
|
||||||
|
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||||
|
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||||
|
ctx.Send(
|
||||||
|
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||||
|
message.Text("有操作正在执行, 请稍后再试..."),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@ -1,95 +0,0 @@
|
|||||||
// Package crypter Fumo语
|
|
||||||
package crypter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Base64字符表
|
|
||||||
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
||||||
|
|
||||||
// Fumo语字符表 - 使用各种fumo变体来表示base64字符
|
|
||||||
var fumoChars = []string{
|
|
||||||
"fumo-", "Fumo-", "fUmo-", "fuMo-", "fumO-", "FUmo-", "FuMo-", "FumO-",
|
|
||||||
"fUMo-", "fUmO-", "fuMO-", "FUMo-", "FUmO-", "fUMO-", "FUMO-", "fumo.",
|
|
||||||
"Fumo.", "fUmo.", "fuMo.", "fumO.", "FUmo.", "FuMo.", "FumO.", "fUMo.",
|
|
||||||
"fUmO.", "fuMO.", "FUMo.", "FUmO.", "fUMO.", "FUMO.", "fumo,", "Fumo,",
|
|
||||||
"fUmo,", "fuMo,", "fumO,", "FUmo,", "FuMo,", "FumO,", "fUMo,", "fUmO,",
|
|
||||||
"fuMO,", "FUMo,", "FuMO,", "fUMO,", "FUMO,", "fumo+", "Fumo+", "fUmo+",
|
|
||||||
"fuMo+", "fumO+", "FUmo+", "FuMo+", "FumO+", "fUMo+", "fUmO+", "fuMO+",
|
|
||||||
"FUMo+", "FUmO+", "fUMO+", "FUMO+", "fumo|", "Fumo|", "fUmo|", "fuMo|",
|
|
||||||
"fumO|", "FUmo|", "FuMo|", "FumO|", "fUMo|", "fUmO|", "fuMO|", "fumo/",
|
|
||||||
"Fumo/", "fUmo/",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base64 2 Fumo
|
|
||||||
// 创建编码映射表
|
|
||||||
var encodeMap = make(map[byte]string)
|
|
||||||
|
|
||||||
// 创建解码映射表
|
|
||||||
var decodeMap = make(map[string]byte)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
for i := 0; i < 64 && i < len(fumoChars); i++ {
|
|
||||||
base64Char := base64Chars[i]
|
|
||||||
fumoChar := fumoChars[i]
|
|
||||||
|
|
||||||
encodeMap[base64Char] = fumoChar
|
|
||||||
decodeMap[fumoChar] = base64Char
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加密
|
|
||||||
func encryptFumo(text string) string {
|
|
||||||
if text == "" {
|
|
||||||
return "请输入要加密的文本"
|
|
||||||
}
|
|
||||||
textBytes := []byte(text)
|
|
||||||
base64String := base64.StdEncoding.EncodeToString(textBytes)
|
|
||||||
base64Body := strings.TrimRight(base64String, "=")
|
|
||||||
paddingCount := len(base64String) - len(base64Body)
|
|
||||||
var fumoBody strings.Builder
|
|
||||||
for _, char := range base64Body {
|
|
||||||
if fumoChar, exists := encodeMap[byte(char)]; exists {
|
|
||||||
fumoBody.WriteString(fumoChar)
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("Fumo加密失败: 未知字符 %c", char)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result := fumoBody.String() + strings.Repeat("=", paddingCount)
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解密
|
|
||||||
func decryptFumo(fumoText string) string {
|
|
||||||
if fumoText == "" {
|
|
||||||
return "请输入要解密的Fumo语密文"
|
|
||||||
}
|
|
||||||
fumoBody := strings.TrimRight(fumoText, "=")
|
|
||||||
paddingCount := len(fumoText) - len(fumoBody)
|
|
||||||
fumoPattern := regexp.MustCompile(`(\w+[-.,+|/])`)
|
|
||||||
fumoWords := fumoPattern.FindAllString(fumoBody, -1)
|
|
||||||
reconstructed := strings.Join(fumoWords, "")
|
|
||||||
if reconstructed != fumoBody {
|
|
||||||
return "Fumo解密失败: 包含无效的Fumo字符或格式错误"
|
|
||||||
}
|
|
||||||
var base64Body strings.Builder
|
|
||||||
for _, fumoWord := range fumoWords {
|
|
||||||
if base64Char, exists := decodeMap[fumoWord]; exists {
|
|
||||||
base64Body.WriteByte(base64Char)
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("Fumo解密失败: 包含无效的Fumo字符 %s", fumoWord)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base64String := base64Body.String() + strings.Repeat("=", paddingCount)
|
|
||||||
decodedBytes, err := base64.StdEncoding.DecodeString(base64String)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Sprintf("Fumo解密失败: Base64解码错误 %v", err)
|
|
||||||
}
|
|
||||||
originalText := string(decodedBytes)
|
|
||||||
return originalText
|
|
||||||
}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
// Package crypter 处理函数
|
|
||||||
package crypter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/FloatTech/AnimeAPI/airecord"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
// hou
|
|
||||||
func houEncryptHandler(ctx *zero.Ctx) {
|
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
|
||||||
result := encodeHou(text)
|
|
||||||
logrus.Infoln("[crypter] 回复内容:", result)
|
|
||||||
recCfg := airecord.GetConfig()
|
|
||||||
record := ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, result)
|
|
||||||
if record != "" {
|
|
||||||
ctx.SendChain(message.Record(record))
|
|
||||||
} else {
|
|
||||||
ctx.SendChain(message.Text(result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func houDecryptHandler(ctx *zero.Ctx) {
|
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
|
||||||
result := decodeHou(text)
|
|
||||||
ctx.SendChain(message.Text(result))
|
|
||||||
}
|
|
||||||
|
|
||||||
// fumo
|
|
||||||
func fumoEncryptHandler(ctx *zero.Ctx) {
|
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
|
||||||
result := encryptFumo(text)
|
|
||||||
ctx.SendChain(message.Text(result))
|
|
||||||
}
|
|
||||||
|
|
||||||
func fumoDecryptHandler(ctx *zero.Ctx) {
|
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
|
||||||
result := decryptFumo(text)
|
|
||||||
ctx.SendChain(message.Text(result))
|
|
||||||
}
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
// Package crypter 齁语加解密
|
|
||||||
package crypter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 齁语密码表
|
|
||||||
var houCodebook = []string{
|
|
||||||
"齁", "哦", "噢", "喔", "咕", "咿", "嗯", "啊",
|
|
||||||
"~", "哈", "!", "唔", "哼", "❤", "呃", "呼",
|
|
||||||
}
|
|
||||||
|
|
||||||
// 索引: 0 1 2 3 4 5 6 7
|
|
||||||
// 8 9 10 11 12 13 14 15
|
|
||||||
|
|
||||||
// 创建映射表
|
|
||||||
var houCodebookMap = make(map[string]int)
|
|
||||||
|
|
||||||
// 初始化映射表
|
|
||||||
func init() {
|
|
||||||
for idx, ch := range houCodebook {
|
|
||||||
houCodebookMap[ch] = idx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeHou(text string) string {
|
|
||||||
if text == "" {
|
|
||||||
return "请输入要加密的文本"
|
|
||||||
}
|
|
||||||
var encoded strings.Builder
|
|
||||||
textBytes := []byte(text)
|
|
||||||
for _, b := range textBytes {
|
|
||||||
high := (b >> 4) & 0x0F
|
|
||||||
low := b & 0x0F
|
|
||||||
encoded.WriteString(houCodebook[high])
|
|
||||||
encoded.WriteString(houCodebook[low])
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoded.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeHou(code string) string {
|
|
||||||
if code == "" {
|
|
||||||
return "请输入要解密的齁语密文"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤出有效的齁语字符
|
|
||||||
var validChars []string
|
|
||||||
for _, r := range code {
|
|
||||||
charStr := string(r)
|
|
||||||
if _, exists := houCodebookMap[charStr]; exists {
|
|
||||||
validChars = append(validChars, charStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(validChars)%2 != 0 {
|
|
||||||
return "齁语密文长度错误,无法解密"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解密过程
|
|
||||||
var byteList []byte
|
|
||||||
for i := 0; i < len(validChars); i += 2 {
|
|
||||||
highIdx, highExists := houCodebookMap[validChars[i]]
|
|
||||||
lowIdx, lowExists := houCodebookMap[validChars[i+1]]
|
|
||||||
|
|
||||||
if !highExists || !lowExists {
|
|
||||||
return "齁语密文包含无效字符"
|
|
||||||
}
|
|
||||||
|
|
||||||
originalByte := byte((highIdx << 4) | lowIdx)
|
|
||||||
byteList = append(byteList, originalByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := string(byteList)
|
|
||||||
|
|
||||||
if !isValidUTF8(result) {
|
|
||||||
return "齁语解密失败,结果不是有效的文本"
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字符串是否为有效的UTF-8编码
|
|
||||||
func isValidUTF8(s string) bool {
|
|
||||||
// Go的string类型默认就是UTF-8,如果转换没有出错说明是有效的
|
|
||||||
return len(s) > 0 || s == ""
|
|
||||||
}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
// Package crypter 奇怪语言加解密
|
|
||||||
package crypter
|
|
||||||
|
|
||||||
import (
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
|
||||||
"github.com/FloatTech/zbputils/control"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
||||||
DisableOnDefault: false,
|
|
||||||
Brief: "奇怪语言加解密",
|
|
||||||
Help: "多种语言加解密插件\n" +
|
|
||||||
"- 齁语加解密:\n" +
|
|
||||||
"- 齁语加密 [文本] 或 h加密 [文本]\n" +
|
|
||||||
"- 齁语解密 [密文] 或 h解密 [密文]\n\n" +
|
|
||||||
"- Fumo语加解密:\n" +
|
|
||||||
"- fumo加密 [文本]\n" +
|
|
||||||
"- fumo解密 [密文]\n\n",
|
|
||||||
PublicDataFolder: "Crypter",
|
|
||||||
})
|
|
||||||
|
|
||||||
// hou
|
|
||||||
engine.OnRegex(`^(?:齁语加密|h加密)\s*(.+)$`).SetBlock(true).Handle(houEncryptHandler)
|
|
||||||
engine.OnRegex(`^(?:齁语解密|h解密)\s*(.+)$`).SetBlock(true).Handle(houDecryptHandler)
|
|
||||||
|
|
||||||
// Fumo
|
|
||||||
engine.OnRegex(`^fumo加密\s*(.+)$`).SetBlock(true).Handle(fumoEncryptHandler)
|
|
||||||
engine.OnRegex(`^fumo解密\s*(.+)$`).SetBlock(true).Handle(fumoDecryptHandler)
|
|
||||||
}
|
|
||||||
@ -2,14 +2,16 @@
|
|||||||
package dailynews
|
package dailynews
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/FloatTech/floatbox/binary"
|
||||||
"github.com/FloatTech/floatbox/web"
|
"github.com/FloatTech/floatbox/web"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const api = "https://uapis.cn/api/v1/daily/news-image"
|
const api = "http://dwz.2xb.cn/zaob"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
@ -26,6 +28,7 @@ func init() {
|
|||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.SendChain(message.ImageBytes(data))
|
picURL := gjson.Get(binary.BytesToString(data), "imageUrl").String()
|
||||||
|
ctx.SendChain(message.Image(picURL))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
target := datapath + `materials/` + name
|
target := datapath + `materials/` + name
|
||||||
if file.IsNotExist(target) {
|
if file.IsNotExist(target) {
|
||||||
data, err := web.GetData(`https://gitea.seku.su/fumiama/ImageMaterials/raw/branch/master/` + name)
|
data, err := web.GetData(`https://gitea.seku.su/fumiama/ImageMaterials/raw/branch/main/` + name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.Remove(target)
|
_ = os.Remove(target)
|
||||||
exit(err)
|
exit(err)
|
||||||
@ -48,7 +48,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
|
|||||||
func dlblock(name string) (string, error) {
|
func dlblock(name string) (string, error) {
|
||||||
target := datapath + `materials/` + name
|
target := datapath + `materials/` + name
|
||||||
if file.IsNotExist(target) {
|
if file.IsNotExist(target) {
|
||||||
data, err := web.GetData(`https://gitea.seku.su/fumiama/ImageMaterials/raw/branch/master/` + name)
|
data, err := web.GetData(`https://gitea.seku.su/fumiama/ImageMaterials/raw/branch/main/` + name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.Remove(target)
|
_ = os.Remove(target)
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/FloatTech/zbputils/ctxext"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
|
||||||
// 图片输出
|
// 图片输出
|
||||||
@ -64,7 +65,17 @@ var (
|
|||||||
"- 下载歌单[网易云歌单链接/ID]到[歌单名称]\n" +
|
"- 下载歌单[网易云歌单链接/ID]到[歌单名称]\n" +
|
||||||
"- 解除绑定 [歌单名称]",
|
"- 解除绑定 [歌单名称]",
|
||||||
PrivateDataFolder: "guessmusic",
|
PrivateDataFolder: "guessmusic",
|
||||||
}).ApplySingle(ctxext.NewGroupSingle("已经有正在进行的游戏..."))
|
}).ApplySingle(single.New(
|
||||||
|
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||||
|
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||||
|
ctx.Break()
|
||||||
|
ctx.Send(
|
||||||
|
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||||
|
message.Text("已经有正在进行的游戏..."),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
// 用于存放歌曲三个片段的缓存文件夹
|
// 用于存放歌曲三个片段的缓存文件夹
|
||||||
cachePath = engine.DataFolder() + "cache/"
|
cachePath = engine.DataFolder() + "cache/"
|
||||||
// 用于存放用户的配置
|
// 用于存放用户的配置
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
package kfccrazythursday
|
package kfccrazythursday
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/FloatTech/floatbox/web"
|
"github.com/FloatTech/floatbox/web"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
@ -13,6 +15,12 @@ const (
|
|||||||
crazyURL = "https://api.pearktrue.cn/api/kfc/"
|
crazyURL = "https://api.pearktrue.cn/api/kfc/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type crazyResponse struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
@ -26,7 +34,17 @@ func init() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据来源API修改返回方式到直接输出文本
|
var resp crazyResponse
|
||||||
ctx.SendChain(message.Text(string(data)))
|
if err := json.Unmarshal(data, &resp); err != nil {
|
||||||
|
ctx.SendChain(message.Text("JSON解析失败: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Code != 200 {
|
||||||
|
ctx.SendChain(message.Text("API返回错误: ", resp.Msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.SendChain(message.Text(resp.Text))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,6 @@ const (
|
|||||||
"- 列出所有提醒\n" +
|
"- 列出所有提醒\n" +
|
||||||
"- 翻牌\n" +
|
"- 翻牌\n" +
|
||||||
"- 赞我\n" +
|
"- 赞我\n" +
|
||||||
"- 群签到\n" +
|
|
||||||
"- 对信息回复: 回应表情 [表情]\n" +
|
"- 对信息回复: 回应表情 [表情]\n" +
|
||||||
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}]\n" +
|
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}]\n" +
|
||||||
"- 测试欢迎语\n" +
|
"- 测试欢迎语\n" +
|
||||||
@ -406,12 +405,6 @@ func init() { // 插件主体
|
|||||||
ctx.SendLike(ctx.Event.UserID, 10)
|
ctx.SendLike(ctx.Event.UserID, 10)
|
||||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("给你赞了10下哦,记得回我~"))
|
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("给你赞了10下哦,记得回我~"))
|
||||||
})
|
})
|
||||||
// 群签到
|
|
||||||
engine.OnFullMatch("群签到", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
ctx.SetGroupSign(ctx.Event.GroupID)
|
|
||||||
ctx.SendChain(message.Text("群签到成功,可在手机端输入框中的打卡查看"))
|
|
||||||
})
|
|
||||||
facere := regexp.MustCompile(`\[CQ:face,id=(\d+)\]`)
|
facere := regexp.MustCompile(`\[CQ:face,id=(\d+)\]`)
|
||||||
// 给消息回应表情
|
// 给消息回应表情
|
||||||
engine.OnRegex(`^\[CQ:reply,id=(-?\d+)\].*回应表情\s*(.+)\s*$`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
engine.OnRegex(`^\[CQ:reply,id=(-?\d+)\].*回应表情\s*(.+)\s*$`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
||||||
|
|||||||
@ -21,10 +21,6 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
longZhuURL = "https://www.hhlqilongzhu.cn/api/joox/juhe_music.php?msg=%v"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
@ -33,8 +29,7 @@ func init() {
|
|||||||
"- 网易点歌[xxx]\n" +
|
"- 网易点歌[xxx]\n" +
|
||||||
"- 酷我点歌[xxx]\n" +
|
"- 酷我点歌[xxx]\n" +
|
||||||
"- 酷狗点歌[xxx]\n" +
|
"- 酷狗点歌[xxx]\n" +
|
||||||
"- 咪咕点歌[xxx]\n" +
|
"- 咪咕点歌[xxx]",
|
||||||
"- qq点歌[xxx]\n",
|
|
||||||
}).OnRegex(`^(.{0,2})点歌\s?(.{1,25})$`).SetBlock(true).Limit(ctxext.LimitByUser).
|
}).OnRegex(`^(.{0,2})点歌\s?(.{1,25})$`).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
// switch 平台
|
// switch 平台
|
||||||
@ -47,37 +42,12 @@ func init() {
|
|||||||
ctx.SendChain(kugou(ctx.State["regex_matched"].([]string)[2]))
|
ctx.SendChain(kugou(ctx.State["regex_matched"].([]string)[2]))
|
||||||
case "网易":
|
case "网易":
|
||||||
ctx.SendChain(cloud163(ctx.State["regex_matched"].([]string)[2]))
|
ctx.SendChain(cloud163(ctx.State["regex_matched"].([]string)[2]))
|
||||||
case "qq":
|
default: // 默认 QQ音乐
|
||||||
ctx.SendChain(qqmusic(ctx.State["regex_matched"].([]string)[2]))
|
ctx.SendChain(qqmusic(ctx.State["regex_matched"].([]string)[2]))
|
||||||
default: // 默认聚合点歌
|
|
||||||
ctx.SendChain(longzhu(ctx.State["regex_matched"].([]string)[2]))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// longzhu 聚合平台
|
|
||||||
func longzhu(keyword string) message.Segment {
|
|
||||||
data, _ := web.GetData(fmt.Sprintf(longZhuURL, url.QueryEscape(keyword)))
|
|
||||||
// 假设 data 是包含整个 JSON 数组的字节切片
|
|
||||||
results := gjson.ParseBytes(data).Array()
|
|
||||||
for _, result := range results {
|
|
||||||
if strings.Contains(strings.ToLower(result.Get("title").String()), strings.ToLower(keyword)) {
|
|
||||||
if musicURL := result.Get("full_track").String(); musicURL != "" {
|
|
||||||
return message.Record(musicURL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = gjson.GetBytes(data, "#.full_track").Array()
|
|
||||||
if len(results) > 0 {
|
|
||||||
if musicURL := results[0].String(); musicURL != "" {
|
|
||||||
return message.Record(musicURL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return message.Text("点歌失败, 找不到 ", keyword, " 的相关结果")
|
|
||||||
}
|
|
||||||
|
|
||||||
// migu 返回咪咕音乐卡片
|
// migu 返回咪咕音乐卡片
|
||||||
func migu(keyword string) message.Segment {
|
func migu(keyword string) message.Segment {
|
||||||
headers := http.Header{
|
headers := http.Header{
|
||||||
|
|||||||
@ -2,11 +2,9 @@
|
|||||||
package niuniu
|
package niuniu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/FloatTech/AnimeAPI/niu"
|
"github.com/FloatTech/AnimeAPI/niu"
|
||||||
@ -20,6 +18,12 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type lastLength struct {
|
||||||
|
TimeLimit time.Time
|
||||||
|
Count int
|
||||||
|
Length float64
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
@ -43,8 +47,8 @@ var (
|
|||||||
})
|
})
|
||||||
dajiaoLimiter = rate.NewManager[string](time.Second*90, 1)
|
dajiaoLimiter = rate.NewManager[string](time.Second*90, 1)
|
||||||
jjLimiter = rate.NewManager[string](time.Second*150, 1)
|
jjLimiter = rate.NewManager[string](time.Second*150, 1)
|
||||||
jjCount = syncx.Map[string, *niu.PKRecord]{}
|
jjCount = syncx.Map[string, *lastLength]{}
|
||||||
register = syncx.Map[string, *niu.PKRecord]{}
|
register = syncx.Map[string, *lastLength]{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -61,7 +65,7 @@ func init() {
|
|||||||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text("牛牛拍卖行有以下牛牛")))
|
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text("牛牛拍卖行有以下牛牛")))
|
||||||
for _, info := range auction {
|
for _, info := range auction {
|
||||||
msg := fmt.Sprintf("商品序号: %d\n牛牛原所属: %d\n牛牛价格: %d%s\n牛牛大小: %.2fcm",
|
msg := fmt.Sprintf("商品序号: %d\n牛牛原所属: %d\n牛牛价格: %d%s\n牛牛大小: %.2fcm",
|
||||||
info.ID, info.UserID, info.Money, wallet.GetWalletName(), info.Length)
|
info.ID+1, info.UserID, info.Money, wallet.GetWalletName(), info.Length)
|
||||||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text(msg)))
|
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text(msg)))
|
||||||
}
|
}
|
||||||
if id := ctx.Send(messages).ID(); id == 0 {
|
if id := ctx.Send(messages).ID(); id == 0 {
|
||||||
@ -77,7 +81,7 @@ func init() {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
ctx.SendChain(message.At(uid), message.Text(" 超时,已自动取消"))
|
ctx.SendChain(message.At(uid), message.Text(" 超时,已自动取消"))
|
||||||
return
|
return
|
||||||
case r := <-recv:
|
case r := <-recv:
|
||||||
answer = r.Event.Message.String()
|
answer = r.Event.Message.String()
|
||||||
@ -86,6 +90,7 @@ func init() {
|
|||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
n--
|
||||||
msg, err := niu.Auction(gid, uid, n)
|
msg, err := niu.Auction(gid, uid, n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR:", err))
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
@ -99,21 +104,11 @@ func init() {
|
|||||||
en.OnFullMatch("出售牛牛", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnFullMatch("出售牛牛", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
gid := ctx.Event.GroupID
|
gid := ctx.Event.GroupID
|
||||||
uid := ctx.Event.UserID
|
uid := ctx.Event.UserID
|
||||||
key := fmt.Sprintf("%d_%d", gid, uid)
|
|
||||||
sell, err := niu.Sell(gid, uid)
|
sell, err := niu.Sell(gid, uid)
|
||||||
if errors.Is(err, niu.ErrCanceled) || errors.Is(err, niu.ErrNoNiuNiu) {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text(err))
|
|
||||||
jjCount.Delete(key)
|
|
||||||
return
|
|
||||||
} else if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR:", err))
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数据库操作成功之后,及时删除残留的缓存
|
|
||||||
if _, ok := jjCount.Load(key); ok {
|
|
||||||
jjCount.Delete(key)
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(sell))
|
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(sell))
|
||||||
})
|
})
|
||||||
en.OnFullMatch("牛牛背包", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnFullMatch("牛牛背包", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
@ -140,33 +135,29 @@ func init() {
|
|||||||
cost int
|
cost int
|
||||||
scope string
|
scope string
|
||||||
description string
|
description string
|
||||||
|
count int
|
||||||
}{
|
}{
|
||||||
1: {"伟哥", 100, "打胶", "可以让你打胶每次都增长"},
|
1: {"伟哥", 300, "打胶", "可以让你打胶每次都增长", 5},
|
||||||
2: {"媚药", 100, "打胶", "可以让你打胶每次都减少"},
|
2: {"媚药", 300, "打胶", "可以让你打胶每次都减少", 5},
|
||||||
3: {"击剑神器", 300, "jj", "可以让你每次击剑都立于不败之地"},
|
3: {"击剑神器", 500, "jj", "可以让你每次击剑都立于不败之地", 2},
|
||||||
4: {"击剑神稽", 300, "jj", "可以让你每次击剑都失败"},
|
4: {"击剑神稽", 500, "jj", "可以让你每次击剑都失败", 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
var messages message.Message
|
var messages message.Message
|
||||||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx,
|
|
||||||
message.Text("输入对应序号进行购买商品"),
|
|
||||||
message.Text(
|
|
||||||
"使用说明:\n"+
|
|
||||||
"商品id-商品数量\n"+
|
|
||||||
"如想购买10个伟哥\n"+
|
|
||||||
"即:1-10")))
|
|
||||||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text("牛牛商店当前售卖的物品如下")))
|
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text("牛牛商店当前售卖的物品如下")))
|
||||||
for id := 1; id <= len(propMap); id++ {
|
for id := range propMap {
|
||||||
product := propMap[id]
|
product := propMap[id]
|
||||||
productInfo := fmt.Sprintf("商品%d\n商品名: %s\n商品价格: %dATRI币\n商品作用域: %s\n商品描述: %s",
|
productInfo := fmt.Sprintf("商品%d\n商品名: %s\n商品价格: %dATRI币\n商品作用域: %s\n商品描述: %s\n使用次数:%d",
|
||||||
id, product.name, product.cost, product.scope, product.description)
|
id, product.name, product.cost, product.scope, product.description, product.count)
|
||||||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text(productInfo)))
|
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text(productInfo)))
|
||||||
}
|
}
|
||||||
if id := ctx.Send(messages).ID(); id == 0 {
|
if id := ctx.Send(messages).ID(); id == 0 {
|
||||||
ctx.Send(message.Text("发送商店失败"))
|
ctx.Send(message.Text("发送商店失败"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(\d+)-(\d+)$`)).Repeat()
|
|
||||||
|
ctx.SendChain(message.Text("输入对应序号进行购买商品"))
|
||||||
|
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(\d+)$`)).Repeat()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
timer := time.NewTimer(120 * time.Second)
|
timer := time.NewTimer(120 * time.Second)
|
||||||
answer := ""
|
answer := ""
|
||||||
@ -174,17 +165,17 @@ func init() {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
ctx.SendChain(message.At(uid), message.Text(" 超时,已自动取消"))
|
ctx.SendChain(message.At(uid), message.Text(" 超时,已自动取消"))
|
||||||
return
|
return
|
||||||
case r := <-recv:
|
case r := <-recv:
|
||||||
answer = r.Event.Message.String()
|
answer = r.Event.Message.String()
|
||||||
|
n, err := strconv.Atoi(answer)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 解析输入的商品ID和数量
|
if err = niu.Store(gid, uid, n); err != nil {
|
||||||
parts := strings.Split(answer, "-")
|
|
||||||
productID, _ := strconv.Atoi(parts[0])
|
|
||||||
quantity, _ := strconv.Atoi(parts[1])
|
|
||||||
|
|
||||||
if err := niu.Store(gid, uid, productID, quantity); err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -205,16 +196,16 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if time.Since(last.TimeLimit) > time.Hour {
|
if time.Since(last.TimeLimit) > time.Hour {
|
||||||
ctx.SendChain(message.Text("时间已经过期了,牛牛已被收回!"))
|
ctx.SendChain(message.Text("时间已经过期了,牛牛已被收回!"))
|
||||||
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
|
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if last.Count < 4 {
|
if last.Count < 4 {
|
||||||
ctx.SendChain(message.Text("你还没有被厥够4次呢,不能赎牛牛"))
|
ctx.SendChain(message.Text("你还没有被厥够4次呢,不能赎牛牛"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.SendChain(message.Text("再次确认一下哦,这次赎牛牛,牛牛长度将会变成", last.Length, "cm\n还需要嘛【是|否】"))
|
ctx.SendChain(message.Text("再次确认一下哦,这次赎牛牛,牛牛长度将会变成", last.Length, "cm\n还需要嘛【是|否】"))
|
||||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(是|否)$`)).Repeat()
|
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(是|否)$`)).Repeat()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
timer := time.NewTimer(2 * time.Minute)
|
timer := time.NewTimer(2 * time.Minute)
|
||||||
@ -231,11 +222,11 @@ func init() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := niu.Redeem(gid, uid, *last); err != nil {
|
if err := niu.Redeem(gid, uid, last.Length); err == nil {
|
||||||
ctx.SendChain(message.Text("ERROR:", err))
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 成功赎回,删除残留的缓存。
|
|
||||||
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
|
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
|
||||||
|
|
||||||
ctx.SendChain(message.At(uid), message.Text(fmt.Sprintf("恭喜你!成功赎回牛牛,当前长度为:%.2fcm", last.Length)))
|
ctx.SendChain(message.At(uid), message.Text(fmt.Sprintf("恭喜你!成功赎回牛牛,当前长度为:%.2fcm", last.Length)))
|
||||||
@ -341,7 +332,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
uid := ctx.Event.UserID
|
uid := ctx.Event.UserID
|
||||||
gid := ctx.Event.GroupID
|
gid := ctx.Event.GroupID
|
||||||
msg, length, niuID, err := niu.JJ(gid, uid, adduser, patternParsed[0].Text()[1])
|
msg, length, err := niu.JJ(gid, uid, adduser, patternParsed[0].Text()[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
jjLimiter.Delete(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
|
jjLimiter.Delete(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
|
||||||
@ -350,27 +341,22 @@ func init() {
|
|||||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(msg))
|
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(msg))
|
||||||
j := fmt.Sprintf("%d_%d", gid, adduser)
|
j := fmt.Sprintf("%d_%d", gid, adduser)
|
||||||
count, ok := jjCount.Load(j)
|
count, ok := jjCount.Load(j)
|
||||||
var c niu.PKRecord
|
var c lastLength
|
||||||
// 按照最后一次被 jj 时的时间计算,超过60分钟则重置
|
// 按照最后一次被jj时的时间计算,超过60分钟则重置
|
||||||
if !ok {
|
if !ok {
|
||||||
// 第一次被 jj
|
c = lastLength{
|
||||||
c = niu.PKRecord{
|
|
||||||
NiuID: niuID,
|
|
||||||
TimeLimit: time.Now(),
|
TimeLimit: time.Now(),
|
||||||
Count: 1,
|
Count: 1,
|
||||||
Length: length,
|
Length: length,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c = niu.PKRecord{
|
c = lastLength{
|
||||||
NiuID: niuID,
|
|
||||||
TimeLimit: time.Now(),
|
TimeLimit: time.Now(),
|
||||||
Count: count.Count + 1,
|
Count: count.Count + 1,
|
||||||
Length: count.Length,
|
Length: count.Length,
|
||||||
}
|
}
|
||||||
// 超时了,重置
|
|
||||||
if time.Since(c.TimeLimit) > time.Hour {
|
if time.Since(c.TimeLimit) > time.Hour {
|
||||||
c = niu.PKRecord{
|
c = lastLength{
|
||||||
NiuID: niuID,
|
|
||||||
TimeLimit: time.Now(),
|
TimeLimit: time.Now(),
|
||||||
Count: 1,
|
Count: 1,
|
||||||
Length: length,
|
Length: length,
|
||||||
@ -386,9 +372,6 @@ func init() {
|
|||||||
)))
|
)))
|
||||||
|
|
||||||
if c.Count >= 4 {
|
if c.Count >= 4 {
|
||||||
if c.Count == 6 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
id := ctx.SendPrivateMessage(adduser,
|
id := ctx.SendPrivateMessage(adduser,
|
||||||
message.Text(fmt.Sprintf("你在%d群里已经被厥冒烟了,快去群里赎回你原本的牛牛!\n发送:`赎牛牛`即可!", gid)))
|
message.Text(fmt.Sprintf("你在%d群里已经被厥冒烟了,快去群里赎回你原本的牛牛!\n发送:`赎牛牛`即可!", gid)))
|
||||||
if id == 0 {
|
if id == 0 {
|
||||||
@ -403,8 +386,8 @@ func init() {
|
|||||||
key := fmt.Sprintf("%d_%d", gid, uid)
|
key := fmt.Sprintf("%d_%d", gid, uid)
|
||||||
data, ok := register.Load(key)
|
data, ok := register.Load(key)
|
||||||
switch {
|
switch {
|
||||||
case !ok || time.Since(data.TimeLimit) > time.Hour*24:
|
case !ok || time.Since(data.TimeLimit) > time.Hour*12:
|
||||||
data = &niu.PKRecord{
|
data = &lastLength{
|
||||||
TimeLimit: time.Now(),
|
TimeLimit: time.Now(),
|
||||||
Count: 1,
|
Count: 1,
|
||||||
}
|
}
|
||||||
@ -413,7 +396,6 @@ func init() {
|
|||||||
ctx.SendChain(message.Text("你的钱不够你注销牛牛了,这次注销需要", data.Count*50, wallet.GetWalletName()))
|
ctx.SendChain(message.Text("你的钱不够你注销牛牛了,这次注销需要", data.Count*50, wallet.GetWalletName()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data.Count++
|
|
||||||
}
|
}
|
||||||
register.Store(key, data)
|
register.Store(key, data)
|
||||||
msg, err := niu.Cancel(gid, uid)
|
msg, err := niu.Cancel(gid, uid)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package nsfw
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/FloatTech/AnimeAPI/nsfw"
|
"github.com/FloatTech/AnimeAPI/nsfw"
|
||||||
|
"github.com/FloatTech/floatbox/process"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
@ -10,6 +11,8 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const hso = "https://gchat.qpic.cn/gchatpic_new//--4234EDEC5F147A4C319A41149D7E0EA9/0"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
@ -30,6 +33,23 @@ func init() {
|
|||||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(judge(p))))
|
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(judge(p))))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
control.Register("nsfwauto", &ctrl.Options[*zero.Ctx]{
|
||||||
|
DisableOnDefault: true,
|
||||||
|
Brief: "nsfw图片自动识别",
|
||||||
|
Help: "- 当图片属于非 neutral 类别时自动发送评价",
|
||||||
|
}).OnMessage(zero.HasPicture).SetBlock(false).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
url := ctx.State["image_url"].([]string)
|
||||||
|
if len(url) > 0 {
|
||||||
|
process.SleepAbout1sTo2s()
|
||||||
|
p, err := nsfw.Classify(url[0])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
process.SleepAbout1sTo2s()
|
||||||
|
autojudge(ctx, p)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func judge(p *nsfw.Picture) string {
|
func judge(p *nsfw.Picture) string {
|
||||||
@ -53,3 +73,31 @@ func judge(p *nsfw.Picture) string {
|
|||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autojudge(ctx *zero.Ctx, p *nsfw.Picture) {
|
||||||
|
if p.Neutral > 0.3 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c := ""
|
||||||
|
if p.Drawings > 0.3 {
|
||||||
|
c = "二次元"
|
||||||
|
} else {
|
||||||
|
c = "三次元"
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
if p.Hentai > 0.3 {
|
||||||
|
c += " hentai"
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if p.Porn > 0.3 {
|
||||||
|
c += " porn"
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if p.Sexy > 0.3 {
|
||||||
|
c += " hso"
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(c, "\n"), message.Image(hso)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
// Package nsfwauto 图片合规性审查的自动版本
|
|
||||||
package nsfwauto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/FloatTech/AnimeAPI/nsfw"
|
|
||||||
"github.com/FloatTech/floatbox/process"
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
|
||||||
"github.com/FloatTech/zbputils/control"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
const hso = "https://gchat.qpic.cn/gchatpic_new//--4234EDEC5F147A4C319A41149D7E0EA9/0"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
||||||
DisableOnDefault: true,
|
|
||||||
Brief: "nsfw图片自动识别",
|
|
||||||
Help: "- 当图片属于非 neutral 类别时自动发送评价",
|
|
||||||
}).OnMessage(zero.HasPicture).SetBlock(false).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
|
||||||
url := ctx.State["image_url"].([]string)
|
|
||||||
if len(url) > 0 {
|
|
||||||
process.SleepAbout1sTo2s()
|
|
||||||
p, err := nsfw.Classify(url[0])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
process.SleepAbout1sTo2s()
|
|
||||||
autojudge(ctx, p)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func autojudge(ctx *zero.Ctx, p *nsfw.Picture) {
|
|
||||||
if p.Neutral > 0.3 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c := ""
|
|
||||||
if p.Drawings > 0.3 {
|
|
||||||
c = "二次元"
|
|
||||||
} else {
|
|
||||||
c = "三次元"
|
|
||||||
}
|
|
||||||
i := 0
|
|
||||||
if p.Hentai > 0.3 {
|
|
||||||
c += " hentai"
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if p.Porn > 0.3 {
|
|
||||||
c += " porn"
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if p.Sexy > 0.3 {
|
|
||||||
c += " hso"
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i > 0 {
|
|
||||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(c, "\n"), message.Image(hso)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -17,7 +17,7 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
|
||||||
// 反并发
|
// 反并发
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||||
// 数据库
|
// 数据库
|
||||||
sql "github.com/FloatTech/sqlite"
|
sql "github.com/FloatTech/sqlite"
|
||||||
// 画图
|
// 画图
|
||||||
@ -67,7 +67,16 @@ var (
|
|||||||
"\"娶群友\"&\"(娶|嫁)@对方QQ\"指令好感度随机增加1~5。\n\"A牛B的C\"会导致C恨A, 好感度-5;\nB为了报复A, 好感度+5(什么柜子play)\nA为BC做媒,成功B、C对A好感度+1反之-1\n做媒成功BC好感度+1" +
|
"\"娶群友\"&\"(娶|嫁)@对方QQ\"指令好感度随机增加1~5。\n\"A牛B的C\"会导致C恨A, 好感度-5;\nB为了报复A, 好感度+5(什么柜子play)\nA为BC做媒,成功B、C对A好感度+1反之-1\n做媒成功BC好感度+1" +
|
||||||
"\nTips: 群老婆列表过0点刷新",
|
"\nTips: 群老婆列表过0点刷新",
|
||||||
PrivateDataFolder: "qqwife",
|
PrivateDataFolder: "qqwife",
|
||||||
}).ApplySingle(ctxext.NewGroupSingle("别着急,民政局门口排长队了!"))
|
}).ApplySingle(single.New(
|
||||||
|
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||||
|
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||||
|
ctx.Send(
|
||||||
|
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||||
|
message.Text("别着急,民政局门口排长队了!"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
getdb = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
getdb = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||||
民政局.db = sql.New(engine.DataFolder() + "结婚登记表.db")
|
民政局.db = sql.New(engine.DataFolder() + "结婚登记表.db")
|
||||||
err := 民政局.db.Open(time.Hour)
|
err := 民政局.db.Open(time.Hour)
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import (
|
|||||||
sql "github.com/FloatTech/sqlite"
|
sql "github.com/FloatTech/sqlite"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||||
|
|
||||||
"github.com/FloatTech/AnimeAPI/wallet"
|
"github.com/FloatTech/AnimeAPI/wallet"
|
||||||
"github.com/FloatTech/floatbox/math"
|
"github.com/FloatTech/floatbox/math"
|
||||||
@ -44,7 +45,16 @@ func init() {
|
|||||||
"7. 每日可打劫或被打劫一次\n" +
|
"7. 每日可打劫或被打劫一次\n" +
|
||||||
"8. 打劫失败不计入次数\n",
|
"8. 打劫失败不计入次数\n",
|
||||||
PrivateDataFolder: "robbery",
|
PrivateDataFolder: "robbery",
|
||||||
}).ApplySingle(ctxext.NewGroupSingle("别着急,警察局门口排长队了!"))
|
}).ApplySingle(single.New(
|
||||||
|
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||||
|
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||||
|
ctx.Send(
|
||||||
|
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||||
|
message.Text("别着急,警察局门口排长队了!"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||||
police.db = sql.New(engine.DataFolder() + "robbery.db")
|
police.db = sql.New(engine.DataFolder() + "robbery.db")
|
||||||
err := police.db.Open(time.Hour)
|
err := police.db.Open(time.Hour)
|
||||||
|
|||||||
@ -1,134 +0,0 @@
|
|||||||
// Package domain rsshub领域逻辑
|
|
||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/mmcdole/gofeed"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// syncRss 同步所有频道
|
|
||||||
// 返回:更新的频道&订阅信息 map[int64]*RssClientView
|
|
||||||
// 1. 获取所有频道
|
|
||||||
// 2. 遍历所有频道,检查频道是否更新
|
|
||||||
// 3. 如果更新,获取更新的内容,但是返回的数据
|
|
||||||
func (repo *RssDomain) syncRss(ctx context.Context) (updated map[int64]*RssClientView, err error) {
|
|
||||||
updated = make(map[int64]*RssClientView)
|
|
||||||
// 获取所有频道
|
|
||||||
sources, err := repo.storage.GetSources(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 遍历所有源,获取每个channel对应的rss内容
|
|
||||||
rssView := make([]*RssClientView, len(sources))
|
|
||||||
for i, channel := range sources {
|
|
||||||
var feed *gofeed.Feed
|
|
||||||
// 从site获取rss内容
|
|
||||||
feed, err = repo.rssHubClient.FetchFeed(channel.RssHubFeedPath)
|
|
||||||
// 如果获取失败,则跳过
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] fetch path(%+v) error: %v", channel.RssHubFeedPath, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
rv := convertFeedToRssView(0, channel.RssHubFeedPath, feed)
|
|
||||||
rssView[i] = rv
|
|
||||||
}
|
|
||||||
// 检查频道是否更新
|
|
||||||
for _, cv := range rssView {
|
|
||||||
if cv == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var needUpdate bool
|
|
||||||
needUpdate, err = repo.checkSourceNeedUpdate(ctx, cv.Source)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] checkSourceNeedUpdate error: %v", err)
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 保存
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub syncRss] cv %+v, need update(real): %v", cv.Source, needUpdate)
|
|
||||||
// 如果需要更新,更新channel 和 content
|
|
||||||
if needUpdate {
|
|
||||||
err = repo.storage.UpsertSource(ctx, cv.Source)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] upsert source error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var updateChannelView = &RssClientView{Source: cv.Source, Contents: []*RssContent{}}
|
|
||||||
err = repo.processContentsUpdate(ctx, cv, updateChannelView)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] processContentsUpdate error: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(updateChannelView.Contents) == 0 {
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub syncRss] cv %s, no new content", cv.Source.RssHubFeedPath)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
updateChannelView.Sort()
|
|
||||||
updated[updateChannelView.Source.ID] = updateChannelView
|
|
||||||
logrus.WithContext(ctx).Debugf("[rsshub syncRss] cv %s, new contents: %v", cv.Source.RssHubFeedPath, len(updateChannelView.Contents))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkSourceNeedUpdate 检查频道是否需要更新
|
|
||||||
func (repo *RssDomain) checkSourceNeedUpdate(ctx context.Context, source *RssSource) (needUpdate bool, err error) {
|
|
||||||
var sourceInDB *RssSource
|
|
||||||
sourceInDB, err = repo.storage.GetSourceByRssHubFeedLink(ctx, source.RssHubFeedPath)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if sourceInDB == nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] source not found: %v", source.RssHubFeedPath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
source.ID = sourceInDB.ID
|
|
||||||
// 检查是否需要更新到db
|
|
||||||
if sourceInDB.IfNeedUpdate(source) {
|
|
||||||
needUpdate = true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// processContentsUpdate 处理内容(s)更新
|
|
||||||
func (repo *RssDomain) processContentsUpdate(ctx context.Context, cv *RssClientView, updateChannelView *RssClientView) error {
|
|
||||||
var err error
|
|
||||||
for _, content := range cv.Contents {
|
|
||||||
if content == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
content.RssSourceID = cv.Source.ID
|
|
||||||
var existed bool
|
|
||||||
existed, err = repo.processContentItemUpdate(ctx, content)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] upsert content error: %v", err)
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !existed {
|
|
||||||
updateChannelView.Contents = append(updateChannelView.Contents, content)
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub syncRss] cv %s, add new content: %v", cv.Source.RssHubFeedPath, content.Title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// processContentItemUpdate 处理单个内容更新
|
|
||||||
func (repo *RssDomain) processContentItemUpdate(ctx context.Context, content *RssContent) (existed bool, err error) {
|
|
||||||
existed, err = repo.storage.IsContentHashIDExist(ctx, content.HashID)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 不需要更新&不需要发送
|
|
||||||
if existed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 保存
|
|
||||||
err = repo.storage.UpsertContent(ctx, content)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] upsert content error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"hash/fnv"
|
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ======== RSS ========[START]
|
|
||||||
|
|
||||||
func genHashForFeedItem(link, guid string) string {
|
|
||||||
h := fnv.New32()
|
|
||||||
// 分三次写入数据:link、分隔符、guid
|
|
||||||
_, _ = h.Write([]byte(link))
|
|
||||||
_, _ = h.Write([]byte("||"))
|
|
||||||
_, _ = h.Write([]byte(guid))
|
|
||||||
|
|
||||||
encoded := hex.EncodeToString(h.Sum(nil))
|
|
||||||
return encoded
|
|
||||||
}
|
|
||||||
|
|
||||||
// RssClientView 频道视图
|
|
||||||
type RssClientView struct {
|
|
||||||
Source *RssSource
|
|
||||||
Contents []*RssContent
|
|
||||||
}
|
|
||||||
|
|
||||||
// ======== RSS ========[END]
|
|
||||||
|
|
||||||
// ======== DB ========[START]
|
|
||||||
|
|
||||||
const (
|
|
||||||
tableNameRssSource = "rss_source"
|
|
||||||
tableNameRssContent = "rss_content"
|
|
||||||
tableNameRssSubscribe = "rss_subscribe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RssSource RSS频道
|
|
||||||
type RssSource struct {
|
|
||||||
// Id 自增id
|
|
||||||
ID int64 `gorm:"column:id;primary_key;AUTO_INCREMENT"`
|
|
||||||
// RssHubFeedPath 频道路由 用于区分rss_hub 不同的频道 例如: `/bangumi/tv/calendar/today`
|
|
||||||
RssHubFeedPath string `gorm:"column:rss_hub_feed_path;not null;unique;" json:"rss_hub_feed_path"`
|
|
||||||
// Title 频道标题
|
|
||||||
Title string `gorm:"column:title" json:"title"`
|
|
||||||
// ChannelDesc 频道描述
|
|
||||||
ChannelDesc string `gorm:"column:channel_desc" json:"channel_desc"`
|
|
||||||
// ImageURL 频道图片
|
|
||||||
ImageURL string `gorm:"column:image_url" json:"image_url"`
|
|
||||||
// Link 频道链接
|
|
||||||
Link string `gorm:"column:link" json:"link"`
|
|
||||||
// UpdatedParsed RSS页面更新时间
|
|
||||||
UpdatedParsed time.Time `gorm:"column:updated_parsed" json:"updated_parsed"`
|
|
||||||
// Mtime update time
|
|
||||||
Mtime time.Time `gorm:"column:mtime;default:current_timestamp;" json:"mtime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName ...
|
|
||||||
func (RssSource) TableName() string {
|
|
||||||
return tableNameRssSource
|
|
||||||
}
|
|
||||||
|
|
||||||
// IfNeedUpdate ...
|
|
||||||
func (r RssSource) IfNeedUpdate(cmp *RssSource) bool {
|
|
||||||
if r.Link != cmp.Link {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return r.UpdatedParsed.Unix() < cmp.UpdatedParsed.Unix()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RssContent 订阅的RSS频道的推送信息
|
|
||||||
type RssContent struct {
|
|
||||||
// Id 自增id
|
|
||||||
ID int64 `gorm:"column:id;primary_key;AUTO_INCREMENT"`
|
|
||||||
HashID string `gorm:"column:hash_id;unique" json:"hash_id"`
|
|
||||||
RssSourceID int64 `gorm:"column:rss_source_id;not null" json:"rss_source_id"`
|
|
||||||
Title string `gorm:"column:title" json:"title"`
|
|
||||||
Description string `gorm:"column:description" json:"description"`
|
|
||||||
Link string `gorm:"column:link" json:"link"`
|
|
||||||
Date time.Time `gorm:"column:date" json:"date"`
|
|
||||||
Author string `gorm:"column:author" json:"author"`
|
|
||||||
Thumbnail string `gorm:"column:thumbnail" json:"thumbnail"`
|
|
||||||
Content string `gorm:"column:content" json:"content"`
|
|
||||||
// Mtime update time
|
|
||||||
Mtime time.Time `gorm:"column:mtime;default:current_timestamp;" json:"mtime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName ...
|
|
||||||
func (RssContent) TableName() string {
|
|
||||||
return tableNameRssContent
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort ... order by Date desc
|
|
||||||
func (r *RssClientView) Sort() {
|
|
||||||
sort.Slice(r.Contents, func(i, j int) bool {
|
|
||||||
return r.Contents[i].Date.Unix() > r.Contents[j].Date.Unix()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// RssSubscribe 订阅关系表:群组-RSS频道
|
|
||||||
type RssSubscribe struct {
|
|
||||||
// Id 自增id
|
|
||||||
ID int64 `gorm:"column:id;primary_key;AUTO_INCREMENT"`
|
|
||||||
// 订阅群组
|
|
||||||
GroupID int64 `gorm:"column:group_id;not null;uniqueIndex:uk_sid_gid"`
|
|
||||||
// 订阅频道
|
|
||||||
RssSourceID int64 `gorm:"column:rss_source_id;not null;uniqueIndex:uk_sid_gid"`
|
|
||||||
// Mtime update time
|
|
||||||
Mtime time.Time `gorm:"column:mtime;default:current_timestamp;" json:"mtime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName ...
|
|
||||||
func (RssSubscribe) TableName() string {
|
|
||||||
return tableNameRssSubscribe
|
|
||||||
}
|
|
||||||
|
|
||||||
// ======== DB ========[END]
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/FloatTech/floatbox/web"
|
|
||||||
"github.com/mmcdole/gofeed"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// RSSHubMirrors RSSHub镜像站地址列表,第一个为默认地址
|
|
||||||
rssHubMirrors = []string{
|
|
||||||
"https://rsshub.rssforever.com",
|
|
||||||
"https://rss.injahow.cn",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// RssHubClient rss hub client (http)
|
|
||||||
type RssHubClient struct {
|
|
||||||
*http.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchFeed 获取rss feed信息
|
|
||||||
func (c *RssHubClient) FetchFeed(path string) (feed *gofeed.Feed, err error) {
|
|
||||||
var data []byte
|
|
||||||
// 遍历 rssHubMirrors,直到获取成功
|
|
||||||
for _, mirror := range rssHubMirrors {
|
|
||||||
data, err = web.RequestDataWith(c.Client, mirror+path, "GET", "", web.RandUA(), nil)
|
|
||||||
if err == nil && len(data) > 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("[rsshub FetchFeed] fetch feed error: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(data) == 0 {
|
|
||||||
logrus.Errorf("[rsshub FetchFeed] fetch feed error: data is empty")
|
|
||||||
return nil, errors.New("feed data is empty")
|
|
||||||
}
|
|
||||||
feed, err = gofeed.NewParser().Parse(bytes.NewBuffer(data))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertFeedToRssView(channelID int64, cPath string, feed *gofeed.Feed) (view *RssClientView) {
|
|
||||||
var imgURL string
|
|
||||||
if feed.Image != nil {
|
|
||||||
imgURL = feed.Image.URL
|
|
||||||
}
|
|
||||||
view = &RssClientView{
|
|
||||||
Source: &RssSource{
|
|
||||||
ID: channelID,
|
|
||||||
RssHubFeedPath: cPath,
|
|
||||||
Title: feed.Title,
|
|
||||||
ChannelDesc: feed.Description,
|
|
||||||
ImageURL: imgURL,
|
|
||||||
Link: feed.Link,
|
|
||||||
UpdatedParsed: *(feed.UpdatedParsed),
|
|
||||||
Mtime: time.Now(),
|
|
||||||
},
|
|
||||||
// 不用定长,后面可能会过滤一些元素再append
|
|
||||||
Contents: []*RssContent{},
|
|
||||||
}
|
|
||||||
// convert feed items to rss content
|
|
||||||
for _, item := range feed.Items {
|
|
||||||
if item.Link == "" || item.Title == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var thumbnail string
|
|
||||||
if item.Image != nil {
|
|
||||||
thumbnail = item.Image.URL
|
|
||||||
}
|
|
||||||
var publishedParsed = item.PublishedParsed
|
|
||||||
if publishedParsed == nil {
|
|
||||||
publishedParsed = &time.Time{}
|
|
||||||
}
|
|
||||||
aus, _ := json.Marshal(item.Authors)
|
|
||||||
view.Contents = append(view.Contents, &RssContent{
|
|
||||||
ID: 0,
|
|
||||||
HashID: genHashForFeedItem(item.Link, item.GUID),
|
|
||||||
RssSourceID: channelID,
|
|
||||||
Title: item.Title,
|
|
||||||
Description: item.Description,
|
|
||||||
Link: item.Link,
|
|
||||||
Date: *publishedParsed,
|
|
||||||
Author: string(aus),
|
|
||||||
Thumbnail: thumbnail,
|
|
||||||
Content: item.Content,
|
|
||||||
Mtime: time.Now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -1,178 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RssDomain RssRepo定义
|
|
||||||
type RssDomain struct {
|
|
||||||
storage *repoStorage
|
|
||||||
rssHubClient *RssHubClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRssDomain 新建RssDomain,调用方保证单例模式
|
|
||||||
func NewRssDomain(dbPath string) (*RssDomain, error) {
|
|
||||||
return newRssDomain(dbPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRssDomain(dbPath string) (*RssDomain, error) {
|
|
||||||
if _, err := os.Stat(dbPath); err != nil || os.IsNotExist(err) {
|
|
||||||
// 生成文件
|
|
||||||
f, err := os.Create(dbPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
}
|
|
||||||
orm, err := gorm.Open("sqlite3", dbPath)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
repo := &RssDomain{
|
|
||||||
storage: &repoStorage{orm: orm},
|
|
||||||
rssHubClient: &RssHubClient{Client: http.DefaultClient},
|
|
||||||
}
|
|
||||||
err = repo.storage.initDB()
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return repo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscribe QQ群订阅Rss频道
|
|
||||||
func (repo *RssDomain) Subscribe(ctx context.Context, gid int64, feedPath string) (
|
|
||||||
rv *RssClientView, isChannelExisted, isSubExisted bool, err error) {
|
|
||||||
// 验证
|
|
||||||
feed, err := repo.rssHubClient.FetchFeed(feedPath)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] add source error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] try get source success: %v", len(feed.Title))
|
|
||||||
// 新建source结构体
|
|
||||||
rv = convertFeedToRssView(0, feedPath, feed)
|
|
||||||
feedChannel, err := repo.storage.GetSourceByRssHubFeedLink(ctx, feedPath)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query source by feedPath error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 如果已经存在
|
|
||||||
if feedChannel != nil {
|
|
||||||
logrus.WithContext(ctx).Warningf("[rsshub Subscribe] source existed: %v", feedChannel)
|
|
||||||
isChannelExisted = true
|
|
||||||
} else {
|
|
||||||
// 不存在的情况,要把更新时间置空,保证下一次同步时能够更新
|
|
||||||
rv.Source.UpdatedParsed = time.Time{}
|
|
||||||
}
|
|
||||||
// 保存
|
|
||||||
err = repo.storage.UpsertSource(ctx, rv.Source)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] save source error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.Infof("[rsshub Subscribe] save/update source success %v", rv.Source.ID)
|
|
||||||
// 添加群号到订阅
|
|
||||||
subscribe, err := repo.storage.GetSubscribeByID(ctx, gid, rv.Source.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query subscribe error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] query subscribe success: %v", subscribe)
|
|
||||||
// 如果已经存在,直接返回
|
|
||||||
if subscribe != nil {
|
|
||||||
isSubExisted = true
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] subscribe existed: %v", subscribe)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 如果不存在,保存
|
|
||||||
err = repo.storage.CreateSubscribe(ctx, gid, rv.Source.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] save subscribe error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] success: %v", len(rv.Contents))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unsubscribe 群组取消订阅
|
|
||||||
func (repo *RssDomain) Unsubscribe(ctx context.Context, gid int64, feedPath string) (err error) {
|
|
||||||
existedSubscribes, ifExisted, err := repo.storage.GetIfExistedSubscribe(ctx, gid, feedPath)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query sub by route error: %v", err)
|
|
||||||
return errors.New("数据库错误")
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] query source by route success: %v", existedSubscribes)
|
|
||||||
// 如果不存在订阅关系,直接返回
|
|
||||||
if !ifExisted || existedSubscribes == nil {
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] source existed: %v", ifExisted)
|
|
||||||
return errors.New("频道不存在")
|
|
||||||
}
|
|
||||||
err = repo.storage.DeleteSubscribe(ctx, existedSubscribes.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] delete source error: %v", err)
|
|
||||||
return errors.New("删除失败")
|
|
||||||
}
|
|
||||||
// 查询是否还有群订阅这个频道
|
|
||||||
subscribesNeedsToDel, err := repo.storage.GetSubscribesBySource(ctx, feedPath)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query source by route error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 没有群订阅的时候,把频道删除
|
|
||||||
if len(subscribesNeedsToDel) == 0 {
|
|
||||||
err = repo.storage.DeleteSource(ctx, existedSubscribes.RssSourceID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] delete source error: %v", err)
|
|
||||||
return errors.New("清除频道信息失败")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSubscribedChannelsByGroupID 获取群对应的订阅的频道信息
|
|
||||||
func (repo *RssDomain) GetSubscribedChannelsByGroupID(ctx context.Context, gid int64) ([]*RssClientView, error) {
|
|
||||||
channels, err := repo.storage.GetSubscribedChannelsByGroupID(ctx, gid)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub GetSubscribedChannelsByGroupID] GetSubscribedChannelsByGroupID error: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rv := make([]*RssClientView, len(channels))
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub GetSubscribedChannelsByGroupID] query subscribe success: %v", len(channels))
|
|
||||||
for i, cn := range channels {
|
|
||||||
rv[i] = &RssClientView{
|
|
||||||
Source: cn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync 同步任务,按照群组订阅情况做好map切片
|
|
||||||
func (repo *RssDomain) Sync(ctx context.Context) (groupView map[int64][]*RssClientView, err error) {
|
|
||||||
groupView = make(map[int64][]*RssClientView)
|
|
||||||
// 获取所有Rss频道
|
|
||||||
// 获取所有频道
|
|
||||||
updatedViews, err := repo.syncRss(ctx)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Sync] sync rss feed error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub Sync] updated channels: %v", len(updatedViews))
|
|
||||||
subscribes, err := repo.storage.GetSubscribes(ctx)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub Sync] get subscribes error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, subscribe := range subscribes {
|
|
||||||
groupView[subscribe.GroupID] = append(groupView[subscribe.GroupID], updatedViews[subscribe.RssSourceID])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNewRssDomain(t *testing.T) {
|
|
||||||
dm, err := newRssDomain("rsshub.db")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if dm == nil {
|
|
||||||
t.Fatal("domain is nil")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//var testRssHubChannelUrl = "https://rsshub.rssforever.com/bangumi/tv/calendar/today"
|
|
||||||
|
|
||||||
var dm, _ = newRssDomain("rsshub.db")
|
|
||||||
|
|
||||||
func TestSub(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
feedLink string
|
|
||||||
gid int64
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "test1",
|
|
||||||
feedLink: "/bangumi/tv/calendar/today",
|
|
||||||
gid: 99,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "test2",
|
|
||||||
feedLink: "/go-weekly",
|
|
||||||
gid: 99,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "test3",
|
|
||||||
feedLink: "/go-weekly",
|
|
||||||
gid: 123,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "test3",
|
|
||||||
feedLink: "/go-weekly",
|
|
||||||
gid: 321,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "test3",
|
|
||||||
feedLink: "/go-weekly",
|
|
||||||
gid: 4123,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
channel, ifExisted, ifSub, err := dm.Subscribe(ctx, tc.gid, tc.feedLink)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t.Logf("[TEST] add sub res: %+v,%+v,%+v\n", channel, ifExisted, ifSub)
|
|
||||||
res, ext, err := dm.storage.GetIfExistedSubscribe(ctx, tc.gid, tc.feedLink)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t.Logf("[TEST] if exist: %+v,%+v", res, ext)
|
|
||||||
channels, err := dm.GetSubscribedChannelsByGroupID(ctx, 2)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t.Logf("[TEST] 2 channels: %+v", channels)
|
|
||||||
// del
|
|
||||||
//err = dm.Unsubscribe(ctx, tc.gid, tc.feedLink)
|
|
||||||
//if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//res, ext, err = dm.storage.GetIfExistedSubscribe(ctx, tc.gid, tc.feedLink)
|
|
||||||
//if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//t.Logf("[TEST] after del: %+v,%+v", res, ext)
|
|
||||||
//if res != nil || ext {
|
|
||||||
// t.Fatal("delete failed")
|
|
||||||
//}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_SyncFeed(t *testing.T) {
|
|
||||||
feed, err := dm.Sync(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rs, _ := json.Marshal(feed)
|
|
||||||
t.Logf("[Test] feed: %+v", string(rs))
|
|
||||||
}
|
|
||||||
@ -1,271 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// repoStorage db struct for rss
|
|
||||||
type repoStorage struct {
|
|
||||||
orm *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
// initDB ...
|
|
||||||
func (s *repoStorage) initDB() (err error) {
|
|
||||||
err = s.orm.AutoMigrate(&RssSource{}, &RssContent{}, &RssSubscribe{}).Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("[rsshub initDB] error: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
// s.orm.LogMode(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSubscribesBySource Impl
|
|
||||||
func (s *repoStorage) GetSubscribesBySource(ctx context.Context, feedPath string) ([]*RssSubscribe, error) {
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub GetSubscribesBySource] feedPath: %s", feedPath)
|
|
||||||
rs := make([]*RssSubscribe, 0)
|
|
||||||
err := s.orm.Model(&RssSubscribe{}).Joins(fmt.Sprintf("%s left join %s on %s.rss_source_id=%s.id", tableNameRssSubscribe, tableNameRssSource, tableNameRssSubscribe, tableNameRssSource)).
|
|
||||||
Where("rss_source.rss_hub_feed_path = ?", feedPath).Select("rss_subscribe.*").Find(&rs).Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub GetSubscribesBySource] error: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return rs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIfExistedSubscribe Impl
|
|
||||||
func (s *repoStorage) GetIfExistedSubscribe(ctx context.Context, gid int64, feedPath string) (*RssSubscribe, bool, error) {
|
|
||||||
rs := RssSubscribe{}
|
|
||||||
|
|
||||||
err := s.orm.Table(tableNameRssSubscribe).
|
|
||||||
Select("rss_subscribe.id, rss_subscribe.group_id, rss_subscribe.rss_source_id, rss_subscribe.mtime").
|
|
||||||
Joins(fmt.Sprintf("INNER JOIN %s ON %s.rss_source_id=%s.id",
|
|
||||||
tableNameRssSource, tableNameRssSubscribe, tableNameRssSource)).
|
|
||||||
Where("rss_source.rss_hub_feed_path = ? AND rss_subscribe.group_id = ?", feedPath, gid).Scan(&rs).Error
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub GetIfExistedSubscribe] error: %v", err)
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
if rs.ID == 0 {
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
return &rs, true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== RepoSource ==================== [Start]
|
|
||||||
|
|
||||||
// UpsertSource Impl
|
|
||||||
func (s *repoStorage) UpsertSource(ctx context.Context, source *RssSource) (err error) {
|
|
||||||
// Update columns to default value on `id` conflict
|
|
||||||
querySource := &RssSource{RssHubFeedPath: source.RssHubFeedPath}
|
|
||||||
err = s.orm.First(querySource, "rss_hub_feed_path = ?", querySource.RssHubFeedPath).Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
err = s.orm.Create(source).Omit("id").Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] add source error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
source.ID = querySource.ID
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub] update source: %+v", source.UpdatedParsed)
|
|
||||||
err = s.orm.Model(&source).Where(&RssSource{ID: source.ID}).
|
|
||||||
Updates(&RssSource{
|
|
||||||
Title: source.Title,
|
|
||||||
ChannelDesc: source.ChannelDesc,
|
|
||||||
ImageURL: source.ImageURL,
|
|
||||||
Link: source.Link,
|
|
||||||
UpdatedParsed: source.UpdatedParsed,
|
|
||||||
Mtime: time.Now(),
|
|
||||||
}).Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] update source error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.Println("[rsshub] add source success: ", source.ID)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSources Impl
|
|
||||||
func (s *repoStorage) GetSources(ctx context.Context) (sources []RssSource, err error) {
|
|
||||||
sources = []RssSource{}
|
|
||||||
err = s.orm.Find(&sources, "id > 0").Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, errors.New("source not found")
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] get sources error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Infof("[rsshub] get sources success: %d", len(sources))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSourceByRssHubFeedLink Impl
|
|
||||||
func (s *repoStorage) GetSourceByRssHubFeedLink(ctx context.Context, rssHubFeedLink string) (source *RssSource, err error) {
|
|
||||||
source = &RssSource{RssHubFeedPath: rssHubFeedLink}
|
|
||||||
err = s.orm.Take(source, source).Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] get source error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteSource Impl
|
|
||||||
func (s *repoStorage) DeleteSource(ctx context.Context, fID int64) (err error) {
|
|
||||||
err = s.orm.Delete(&RssSource{}, "id = ?", fID).Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.DeleteSource: %v", err)
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return errors.New("source not found")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== RepoSource ==================== [End]
|
|
||||||
|
|
||||||
// ==================== RepoContent ==================== [Start]
|
|
||||||
|
|
||||||
// UpsertContent Impl
|
|
||||||
func (s *repoStorage) UpsertContent(ctx context.Context, content *RssContent) (err error) {
|
|
||||||
// check params
|
|
||||||
if content == nil {
|
|
||||||
err = errors.New("content is nil")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// check params.RssHubFeedPath and params.HashID
|
|
||||||
if content.RssSourceID < 0 || content.HashID == "" || content.Title == "" {
|
|
||||||
err = errors.New("content.RssSourceID or content.HashID or content.Title is empty")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = s.orm.Create(content).Omit("id").Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.UpsertContent: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteSourceContents Impl
|
|
||||||
func (s *repoStorage) DeleteSourceContents(ctx context.Context, channelID int64) (rows int64, err error) {
|
|
||||||
err = s.orm.Delete(&RssSubscribe{}).Where(&RssSubscribe{RssSourceID: channelID}).Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.DeleteSourceContents: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsContentHashIDExist Impl
|
|
||||||
func (s *repoStorage) IsContentHashIDExist(ctx context.Context, hashID string) (bool, error) {
|
|
||||||
wanted := &RssContent{HashID: hashID}
|
|
||||||
err := s.orm.Take(wanted, wanted).Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.IsContentHashIDExist: %v", err)
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== RepoContent ==================== [End]
|
|
||||||
|
|
||||||
// ==================== RepoSubscribe ==================== [Start]
|
|
||||||
|
|
||||||
// CreateSubscribe Impl
|
|
||||||
func (s *repoStorage) CreateSubscribe(ctx context.Context, gid, rssSourceID int64) (err error) {
|
|
||||||
// check subscribe
|
|
||||||
if rssSourceID < 0 || gid == 0 {
|
|
||||||
err = errors.New("gid or rssSourceID is empty")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = s.orm.Create(&RssSubscribe{GroupID: gid, RssSourceID: rssSourceID}).Omit("id").Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.CreateSubscribe: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteSubscribe Impl
|
|
||||||
func (s *repoStorage) DeleteSubscribe(ctx context.Context, subscribeID int64) (err error) {
|
|
||||||
err = s.orm.Delete(&RssSubscribe{}, "id = ?", subscribeID).Error
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.DeleteSubscribe error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSubscribeByID Impl
|
|
||||||
func (s *repoStorage) GetSubscribeByID(ctx context.Context, gid int64, subscribeID int64) (res *RssSubscribe, err error) {
|
|
||||||
res = &RssSubscribe{}
|
|
||||||
err = s.orm.First(res, &RssSubscribe{GroupID: gid, RssSourceID: subscribeID}).Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.GetSubscribeByID: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSubscribedChannelsByGroupID Impl
|
|
||||||
func (s *repoStorage) GetSubscribedChannelsByGroupID(ctx context.Context, gid int64) (res []*RssSource, err error) {
|
|
||||||
res = make([]*RssSource, 0)
|
|
||||||
err = s.orm.Model(&RssSource{}).
|
|
||||||
Joins(fmt.Sprintf("join %s on rss_source_id=%s.id", tableNameRssSubscribe, tableNameRssSource)).Where("rss_subscribe.group_id = ?", gid).
|
|
||||||
Select("rss_source.*").
|
|
||||||
Find(&res).
|
|
||||||
Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
err = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.GetSubscribedChannelsByGroupID: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSubscribes Impl
|
|
||||||
func (s *repoStorage) GetSubscribes(ctx context.Context) (res []*RssSubscribe, err error) {
|
|
||||||
res = make([]*RssSubscribe, 0)
|
|
||||||
err = s.orm.Find(&res).Error
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
err = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.GetSubscribes: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== RepoSubscribe ==================== [End]
|
|
||||||
@ -1,152 +0,0 @@
|
|||||||
// Package rsshub rss_hub订阅插件
|
|
||||||
package rsshub
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
|
||||||
"github.com/FloatTech/zbputils/control"
|
|
||||||
zbpCtxExt "github.com/FloatTech/zbputils/ctxext"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
|
||||||
|
|
||||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/rsshub/domain"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 初始化 repo
|
|
||||||
var (
|
|
||||||
rssRepo *domain.RssDomain
|
|
||||||
initErr error
|
|
||||||
regexpForSQL = regexp.MustCompile(`[\^<>\[\]%&\*\(\)\{\}\|\=]|(union\s+select|update\s+|delete\s+|drop\s+|truncate\s+|insert\s+|exec\s+|declare\s+)`)
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// 注册插件
|
|
||||||
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
||||||
// 默认不启动
|
|
||||||
DisableOnDefault: false,
|
|
||||||
Brief: "rsshub订阅姬",
|
|
||||||
// 详细帮助
|
|
||||||
Help: "rsshub订阅姬desu~ \n" +
|
|
||||||
"支持的详细订阅列表文档可见:\n" +
|
|
||||||
"https://rsshub.netlify.app/zh/ \n" +
|
|
||||||
"- 添加rsshub订阅-/bookfere/weekly \n" +
|
|
||||||
"- 删除rsshub订阅-/bookfere/weekly \n" +
|
|
||||||
"- 查看rsshub订阅列表 \n" +
|
|
||||||
"- rsshub同步 \n" +
|
|
||||||
"Tips: 定时刷新rsshub订阅信息需要配合job一起使用, 全局只需要设置一个, 无视响应状态推送, 下为例子\n" +
|
|
||||||
"记录在\"@every 10m\"触发的指令)\n" +
|
|
||||||
"rsshub同步",
|
|
||||||
// 插件数据存储路径
|
|
||||||
PrivateDataFolder: "rsshub",
|
|
||||||
OnEnable: func(ctx *zero.Ctx) {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬现在启动了哦"))
|
|
||||||
},
|
|
||||||
OnDisable: func(ctx *zero.Ctx) {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬现在关闭了哦"))
|
|
||||||
},
|
|
||||||
}).ApplySingle(zbpCtxExt.DefaultSingle)
|
|
||||||
)
|
|
||||||
|
|
||||||
// init 命令路由
|
|
||||||
func init() {
|
|
||||||
rssRepo, initErr = domain.NewRssDomain(engine.DataFolder() + "rsshub.db")
|
|
||||||
if initErr != nil {
|
|
||||||
logrus.Errorln("rsshub订阅姬:初始化失败", initErr)
|
|
||||||
panic(initErr)
|
|
||||||
}
|
|
||||||
engine.OnFullMatch("rsshub同步", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
|
||||||
// 群组-频道推送视图 map[群组]推送内容数组
|
|
||||||
groupToFeedsMap, err := rssRepo.Sync(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorln("rsshub同步失败", err)
|
|
||||||
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text("rsshub同步失败", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 没有更新的[群组-频道推送视图]则不推送
|
|
||||||
if len(groupToFeedsMap) == 0 {
|
|
||||||
logrus.Info("rsshub未发现更新")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sendRssUpdateMsg(ctx, groupToFeedsMap)
|
|
||||||
})
|
|
||||||
// 添加订阅
|
|
||||||
engine.OnPrefix("添加rsshub订阅-", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
|
||||||
routeStr := ctx.State["args"].(string)
|
|
||||||
input := regexpForSQL.ReplaceAllString(routeStr, "")
|
|
||||||
logrus.Debugf("添加rsshub订阅:raw(%s), replaced(%s)", routeStr, input)
|
|
||||||
rv, _, isSubExisted, err := rssRepo.Subscribe(context.Background(), ctx.Event.GroupID, input)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬:添加失败", err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if isSubExisted {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬:已存在,更新成功"))
|
|
||||||
} else {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬:添加成功\n", rv.Source.Title))
|
|
||||||
}
|
|
||||||
// 添加成功,发送订阅源快照
|
|
||||||
msg, err := newRssDetailsMsg(ctx, rv)
|
|
||||||
if len(msg) == 0 || err != nil {
|
|
||||||
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text("rsshub推送错误", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if id := ctx.Send(msg).ID(); id == 0 {
|
|
||||||
ctx.SendChain(message.Text("ERROR: 发送订阅源快照失败,可能被风控了"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
engine.OnPrefix("删除rsshub订阅-", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
|
||||||
routeStr := ctx.State["args"].(string)
|
|
||||||
input := regexpForSQL.ReplaceAllString(routeStr, "")
|
|
||||||
logrus.Debugf("删除rsshub订阅:raw(%s), replaced(%s)", routeStr, input)
|
|
||||||
err := rssRepo.Unsubscribe(context.Background(), ctx.Event.GroupID, input)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬:删除失败 ", err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text(fmt.Sprintf("rsshub订阅姬:删除%s成功", input)))
|
|
||||||
})
|
|
||||||
engine.OnFullMatch("查看rsshub订阅列表", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
|
||||||
rv, err := rssRepo.GetSubscribedChannelsByGroupID(context.Background(), ctx.Event.GroupID)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬:查询失败 ", err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 添加成功,发送订阅源信息
|
|
||||||
msg, err := newRssSourcesMsg(ctx, rv)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("rsshub订阅姬:查询失败 ", err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(msg) == 0 {
|
|
||||||
ctx.SendChain(message.Text("ん? 没有订阅的频道哦~"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(msg...)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendRssUpdateMsg 发送Rss更新消息
|
|
||||||
func sendRssUpdateMsg(ctx *zero.Ctx, groupToFeedsMap map[int64][]*domain.RssClientView) {
|
|
||||||
for groupID, views := range groupToFeedsMap {
|
|
||||||
logrus.Infof("rsshub插件在群 %d 触发推送检查", groupID)
|
|
||||||
for _, view := range views {
|
|
||||||
if view == nil || len(view.Contents) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
msg, err := newRssDetailsMsg(ctx, view)
|
|
||||||
if len(msg) == 0 || err != nil {
|
|
||||||
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg, err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
logrus.Infof("rsshub插件在群 %d 开始推送 %s", groupID, view.Source.Title)
|
|
||||||
ctx.SendGroupMessage(groupID, message.Text(fmt.Sprintf("%s\n该rsshub频道下有更新了哦~", view.Source.Title)))
|
|
||||||
if res := ctx.SendGroupForwardMessage(groupID, msg); !res.Exists() {
|
|
||||||
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
package rsshub
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/FloatTech/floatbox/binary"
|
|
||||||
"github.com/FloatTech/zbputils/img/text"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
|
||||||
|
|
||||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/rsshub/domain"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
rssHubPushErrMsg = "RssHub推送错误"
|
|
||||||
)
|
|
||||||
|
|
||||||
// formatRssViewToMessagesSlice 格式化RssClientView为消息切片
|
|
||||||
func formatRssViewToMessagesSlice(view *domain.RssClientView) ([]message.Message, error) {
|
|
||||||
// 取前20条
|
|
||||||
cts := view.Contents
|
|
||||||
if len(cts) > 20 {
|
|
||||||
cts = cts[:20]
|
|
||||||
}
|
|
||||||
// 2n+1条消息
|
|
||||||
fv := make([]message.Message, len(cts)*2+1)
|
|
||||||
// 订阅源头图
|
|
||||||
toastPic, err := text.RenderToBase64(fmt.Sprintf("%s\n\n\n%s\n\n\n更新时间:%v\n\n\n",
|
|
||||||
view.Source.Title, view.Source.Link, view.Source.UpdatedParsed.Local().Format(time.DateTime)),
|
|
||||||
text.SakuraFontFile, 1200, 40)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fv[0] = message.Message{message.Image("base64://" + binary.BytesToString(toastPic))}
|
|
||||||
// 元素信息
|
|
||||||
for idx, item := range cts {
|
|
||||||
contentStr := fmt.Sprintf("%s\n\n\n", item.Title)
|
|
||||||
// Date为空时不显示
|
|
||||||
if !item.Date.IsZero() {
|
|
||||||
contentStr += fmt.Sprintf("更新时间:\n%v\n", item.Date.Local().Format(time.DateTime))
|
|
||||||
}
|
|
||||||
var content []byte
|
|
||||||
content, err = text.RenderToBase64(contentStr, text.SakuraFontFile, 1200, 40)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("RssHub订阅姬渲染图片失败")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
itemMessagePic := message.Message{message.Image("base64://" + binary.BytesToString(content))}
|
|
||||||
fv[2*idx+1] = itemMessagePic
|
|
||||||
fv[2*idx+2] = message.Message{message.Text(item.Link)}
|
|
||||||
}
|
|
||||||
return fv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// newRssSourcesMsg Rss订阅源列表
|
|
||||||
func newRssSourcesMsg(ctx *zero.Ctx, view []*domain.RssClientView) (message.Message, error) {
|
|
||||||
var msgSlice []message.Message
|
|
||||||
// 生成消息
|
|
||||||
for _, v := range view {
|
|
||||||
if v == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
item, err := formatRssViewToMessagesSlice(v)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
msgSlice = append(msgSlice, item...)
|
|
||||||
}
|
|
||||||
// 伪造一个发送者为RssHub订阅姬的消息节点
|
|
||||||
msg := make(message.Message, len(msgSlice))
|
|
||||||
for i, item := range msgSlice {
|
|
||||||
msg[i] = fakeSenderForwardNode(ctx.Event.SelfID, item...)
|
|
||||||
}
|
|
||||||
return msg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// newRssDetailsMsg Rss订阅源详情(包含文章信息列表)
|
|
||||||
func newRssDetailsMsg(ctx *zero.Ctx, view *domain.RssClientView) (message.Message, error) {
|
|
||||||
// 生成消息
|
|
||||||
msgSlice, err := formatRssViewToMessagesSlice(view)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 伪造一个发送者为RssHub订阅姬的消息节点
|
|
||||||
msg := make(message.Message, len(msgSlice))
|
|
||||||
for i, item := range msgSlice {
|
|
||||||
msg[i] = fakeSenderForwardNode(ctx.Event.SelfID, item...)
|
|
||||||
}
|
|
||||||
return msg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// fakeSenderForwardNode 伪造一个发送者为RssHub订阅姬的消息节点
|
|
||||||
func fakeSenderForwardNode(userID int64, msgs ...message.Segment) message.Segment {
|
|
||||||
return message.CustomNode(
|
|
||||||
"RssHub订阅姬",
|
|
||||||
userID,
|
|
||||||
msgs)
|
|
||||||
}
|
|
||||||
@ -2,7 +2,6 @@ package score
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
@ -12,10 +11,7 @@ import (
|
|||||||
var sdb *scoredb
|
var sdb *scoredb
|
||||||
|
|
||||||
// scoredb 分数数据库
|
// scoredb 分数数据库
|
||||||
type scoredb struct {
|
type scoredb gorm.DB
|
||||||
db *gorm.DB
|
|
||||||
scoremu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// scoretable 分数结构体
|
// scoretable 分数结构体
|
||||||
type scoretable struct {
|
type scoretable struct {
|
||||||
@ -56,31 +52,25 @@ func initialize(dbpath string) *scoredb {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
gdb.AutoMigrate(&scoretable{}).AutoMigrate(&signintable{})
|
gdb.AutoMigrate(&scoretable{}).AutoMigrate(&signintable{})
|
||||||
return &scoredb{
|
return (*scoredb)(gdb)
|
||||||
db: gdb,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close ...
|
// Close ...
|
||||||
func (sdb *scoredb) Close() error {
|
func (sdb *scoredb) Close() error {
|
||||||
db := sdb.db
|
db := (*gorm.DB)(sdb)
|
||||||
return db.Close()
|
return db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScoreByUID 取得分数
|
// GetScoreByUID 取得分数
|
||||||
func (sdb *scoredb) GetScoreByUID(uid int64) (s scoretable) {
|
func (sdb *scoredb) GetScoreByUID(uid int64) (s scoretable) {
|
||||||
sdb.scoremu.Lock()
|
db := (*gorm.DB)(sdb)
|
||||||
defer sdb.scoremu.Unlock()
|
|
||||||
db := sdb.db
|
|
||||||
db.Model(&scoretable{}).FirstOrCreate(&s, "uid = ? ", uid)
|
db.Model(&scoretable{}).FirstOrCreate(&s, "uid = ? ", uid)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertOrUpdateScoreByUID 插入或更新分数
|
// InsertOrUpdateScoreByUID 插入或更新分数
|
||||||
func (sdb *scoredb) InsertOrUpdateScoreByUID(uid int64, score int) (err error) {
|
func (sdb *scoredb) InsertOrUpdateScoreByUID(uid int64, score int) (err error) {
|
||||||
sdb.scoremu.Lock()
|
db := (*gorm.DB)(sdb)
|
||||||
defer sdb.scoremu.Unlock()
|
|
||||||
db := sdb.db
|
|
||||||
s := scoretable{
|
s := scoretable{
|
||||||
UID: uid,
|
UID: uid,
|
||||||
Score: score,
|
Score: score,
|
||||||
@ -101,18 +91,14 @@ func (sdb *scoredb) InsertOrUpdateScoreByUID(uid int64, score int) (err error) {
|
|||||||
|
|
||||||
// GetSignInByUID 取得签到次数
|
// GetSignInByUID 取得签到次数
|
||||||
func (sdb *scoredb) GetSignInByUID(uid int64) (si signintable) {
|
func (sdb *scoredb) GetSignInByUID(uid int64) (si signintable) {
|
||||||
sdb.scoremu.Lock()
|
db := (*gorm.DB)(sdb)
|
||||||
defer sdb.scoremu.Unlock()
|
|
||||||
db := sdb.db
|
|
||||||
db.Model(&signintable{}).FirstOrCreate(&si, "uid = ? ", uid)
|
db.Model(&signintable{}).FirstOrCreate(&si, "uid = ? ", uid)
|
||||||
return si
|
return si
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertOrUpdateSignInCountByUID 插入或更新签到次数
|
// InsertOrUpdateSignInCountByUID 插入或更新签到次数
|
||||||
func (sdb *scoredb) InsertOrUpdateSignInCountByUID(uid int64, count int) (err error) {
|
func (sdb *scoredb) InsertOrUpdateSignInCountByUID(uid int64, count int) (err error) {
|
||||||
sdb.scoremu.Lock()
|
db := (*gorm.DB)(sdb)
|
||||||
defer sdb.scoremu.Unlock()
|
|
||||||
db := sdb.db
|
|
||||||
si := signintable{
|
si := signintable{
|
||||||
UID: uid,
|
UID: uid,
|
||||||
Count: count,
|
Count: count,
|
||||||
@ -132,9 +118,7 @@ func (sdb *scoredb) InsertOrUpdateSignInCountByUID(uid int64, count int) (err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sdb *scoredb) GetScoreRankByTopN(n int) (st []scoretable, err error) {
|
func (sdb *scoredb) GetScoreRankByTopN(n int) (st []scoretable, err error) {
|
||||||
sdb.scoremu.Lock()
|
db := (*gorm.DB)(sdb)
|
||||||
defer sdb.scoremu.Unlock()
|
|
||||||
db := sdb.db
|
|
||||||
err = db.Model(&scoretable{}).Order("score desc").Limit(n).Find(&st).Error
|
err = db.Model(&scoretable{}).Order("score desc").Limit(n).Find(&st).Error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,19 @@
|
|||||||
package thesaurus
|
package thesaurus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-ego/gse"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
|
||||||
"github.com/FloatTech/AnimeAPI/kimoi"
|
"github.com/FloatTech/AnimeAPI/kimoi"
|
||||||
|
"github.com/FloatTech/floatbox/ctxext"
|
||||||
|
"github.com/FloatTech/floatbox/process"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
)
|
)
|
||||||
@ -14,35 +23,143 @@ func init() {
|
|||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "词典匹配回复, 仅@触发",
|
Brief: "词典匹配回复, 仅@触发",
|
||||||
|
Help: "- 切换[kimo|傲娇|可爱]词库",
|
||||||
PublicDataFolder: "Chat",
|
PublicDataFolder: "Chat",
|
||||||
})
|
})
|
||||||
engine.OnMessage(zero.OnlyToMe, canmatch()).
|
engine.OnRegex(`^切换(kimo|傲娇|可爱)词库$`, zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
msg := ctx.ExtractPlainText()
|
if !ok {
|
||||||
r, err := kimoi.Chat(msg)
|
ctx.SendChain(message.Text("ERROR: 找不到 manager"))
|
||||||
if err == nil {
|
return
|
||||||
c := 0
|
}
|
||||||
for r.Confidence < 0.2 && c < 3 {
|
gid := ctx.Event.GroupID
|
||||||
r, err = kimoi.Chat(msg)
|
if gid == 0 {
|
||||||
if err != nil {
|
gid = -ctx.Event.UserID
|
||||||
|
}
|
||||||
|
d := c.GetData(gid)
|
||||||
|
t := int64(0)
|
||||||
|
switch ctx.State["regex_matched"].([]string)[1] {
|
||||||
|
case "kimo":
|
||||||
|
t = tKIMO
|
||||||
|
case "傲娇":
|
||||||
|
t = tDERE
|
||||||
|
case "可爱":
|
||||||
|
t = tKAWA
|
||||||
|
}
|
||||||
|
err := c.SetData(gid, (d&^3)|t)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(message.Text("成功!"))
|
||||||
|
})
|
||||||
|
go func() {
|
||||||
|
var seg gse.Segmenter
|
||||||
|
err := seg.LoadDictEmbed()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
smd, err := engine.GetLazyData("simai.yml", false)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sm := simai{D: make(map[string][]string, 8192), K: make(map[string][]string, 16384)}
|
||||||
|
err = yaml.Unmarshal(smd, &sm)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
chatListD := make([]string, 0, len(sm.D))
|
||||||
|
for k := range sm.D {
|
||||||
|
chatListD = append(chatListD, k)
|
||||||
|
}
|
||||||
|
chatListK := make([]string, 0, len(sm.K))
|
||||||
|
for k := range sm.K {
|
||||||
|
chatListK = append(chatListK, k)
|
||||||
|
}
|
||||||
|
logrus.Infoln("[thesaurus]加载", len(chatListD), "条傲娇词库", len(chatListK), "条可爱词库")
|
||||||
|
|
||||||
|
engine.OnMessage(zero.OnlyToMe, canmatch(tKIMO)).
|
||||||
|
SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
||||||
|
msg := ctx.ExtractPlainText()
|
||||||
|
r, err := kimoi.Chat(msg)
|
||||||
|
if err == nil {
|
||||||
|
c := 0
|
||||||
|
for r.Confidence < 0.2 && c < 3 {
|
||||||
|
r, err = kimoi.Chat(msg)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
if r.Confidence < 0.2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c++
|
ctx.Block()
|
||||||
|
ctx.SendChain(message.Text(r.Reply))
|
||||||
}
|
}
|
||||||
if r.Confidence < 0.2 {
|
})
|
||||||
return
|
engine.OnMessage(zero.OnlyToMe, canmatch(tDERE), match(chatListD, &seg)).
|
||||||
}
|
SetBlock(false).
|
||||||
ctx.Block()
|
Handle(randreply(sm.D))
|
||||||
ctx.SendChain(message.Text(r.Reply))
|
engine.OnMessage(zero.OnlyToMe, canmatch(tKAWA), match(chatListK, &seg)).
|
||||||
}
|
SetBlock(false).
|
||||||
})
|
Handle(randreply(sm.K))
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func canmatch() zero.Rule {
|
type simai struct {
|
||||||
|
D map[string][]string `yaml:"傲娇"`
|
||||||
|
K map[string][]string `yaml:"可爱"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
tKIMO = iota
|
||||||
|
tDERE
|
||||||
|
tKAWA
|
||||||
|
)
|
||||||
|
|
||||||
|
func match(l []string, seg *gse.Segmenter) zero.Rule {
|
||||||
|
return func(ctx *zero.Ctx) bool {
|
||||||
|
return ctxext.JiebaSimilarity(0.66, seg, func(ctx *zero.Ctx) string {
|
||||||
|
return ctx.ExtractPlainText()
|
||||||
|
}, l...)(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func canmatch(typ int64) zero.Rule {
|
||||||
return func(ctx *zero.Ctx) bool {
|
return func(ctx *zero.Ctx) bool {
|
||||||
if zero.HasPicture(ctx) {
|
if zero.HasPicture(ctx) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return ctx.ExtractPlainText() != ""
|
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
if gid == 0 {
|
||||||
|
gid = -ctx.Event.UserID
|
||||||
|
}
|
||||||
|
d := c.GetData(gid)
|
||||||
|
return ctx.ExtractPlainText() != "" && d&3 == typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func randreply(m map[string][]string) zero.Handler {
|
||||||
|
return func(ctx *zero.Ctx) {
|
||||||
|
ctx.Block()
|
||||||
|
key := ctx.State["matched"].(string)
|
||||||
|
val := m[key]
|
||||||
|
nick := zero.BotConfig.NickName[rand.Intn(len(zero.BotConfig.NickName))]
|
||||||
|
text := val[rand.Intn(len(val))]
|
||||||
|
text = strings.ReplaceAll(text, "{name}", ctx.CardOrNickName(ctx.Event.UserID))
|
||||||
|
text = strings.ReplaceAll(text, "{me}", nick)
|
||||||
|
id := ctx.Event.MessageID
|
||||||
|
for _, t := range strings.Split(text, "{segment}") {
|
||||||
|
if t == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
process.SleepAbout1sTo2s()
|
||||||
|
id = ctx.SendChain(message.Reply(id), message.Text(t))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
670
plugin/wenxinvilg/main.go
Normal file
670
plugin/wenxinvilg/main.go
Normal file
@ -0,0 +1,670 @@
|
|||||||
|
// Package wenxin 百度文心AI
|
||||||
|
package wenxin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||||
|
"github.com/FloatTech/floatbox/process"
|
||||||
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
|
"github.com/FloatTech/zbputils/control"
|
||||||
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
|
||||||
|
// 数据库
|
||||||
|
sql "github.com/FloatTech/sqlite"
|
||||||
|
// 百度文心大模型
|
||||||
|
model "github.com/FloatTech/AnimeAPI/wenxinAI/erniemodle"
|
||||||
|
// 百度文心AI画图API
|
||||||
|
wenxin "github.com/FloatTech/AnimeAPI/wenxinAI/ernievilg"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
serviceErr = "[wenxinvilg]ERROR:\n"
|
||||||
|
modelErr = "[wenxinmodel]ERROR:\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
type keydb struct {
|
||||||
|
sync.RWMutex
|
||||||
|
db sql.Sqlite
|
||||||
|
}
|
||||||
|
|
||||||
|
// db内容
|
||||||
|
type apikey struct {
|
||||||
|
ID int64 // 群号
|
||||||
|
APIKey string // API Key
|
||||||
|
SecretKey string // Secret Key
|
||||||
|
Token string // AccessToken
|
||||||
|
Updatetime int64 // token的有效时间
|
||||||
|
MaxLimit int // 总使用次数
|
||||||
|
DayLimit int // 当天的使用次数
|
||||||
|
Lasttime string // 记录使用的时间,用于刷新使用次数
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
name = "椛椛"
|
||||||
|
limit int
|
||||||
|
vilginfo keydb
|
||||||
|
modelinfo keydb
|
||||||
|
dtype = [...]string{
|
||||||
|
"古风", "油画", "水彩画", "卡通画", "二次元", "浮世绘", "蒸汽波艺术", "low poly", "像素风格", "概念艺术", "未来主义", "赛博朋克", "写实风格", "洛丽塔风格", "巴洛克风格", "超现实主义",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() { // 插件主体
|
||||||
|
go func() {
|
||||||
|
process.GlobalInitMutex.Lock()
|
||||||
|
defer process.GlobalInitMutex.Unlock()
|
||||||
|
name = zero.BotConfig.NickName[0]
|
||||||
|
}()
|
||||||
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
|
DisableOnDefault: false,
|
||||||
|
Brief: "文心AI画图",
|
||||||
|
Help: "基于百度文心的免费AI画图插件,\n因为是免费的,图片质量你懂的。\n" +
|
||||||
|
"key申请链接:https://wenxin.baidu.com/moduleApi/key\n" +
|
||||||
|
"key和erniemodel插件的key相同。\n" +
|
||||||
|
"注意:每个apikey每日上限50次,总上限500次请求。次数超过了请自行更新apikey\n" +
|
||||||
|
"- 为[自己/本群/QQ号/群+群号]设置画图key [API Key] [Secret Key]\n" +
|
||||||
|
"例:\n为自己设置画图key 123 456\n为10086设置画图key 123 456\n为群10010设置画图key 789 101\n" +
|
||||||
|
"- [bot名称]画几张[图片描述]的[图片类型][图片尺寸]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"图片描述指南:\n图片主体,细节词(请用逗号连接)\n官方prompt指南:https://wenxin.baidu.com/wenxin/docs#Ol7ece95m\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"图片类型当前支持:" + strings.Join(dtype[:], "、") +
|
||||||
|
"\n————————————————————\n" +
|
||||||
|
"图片尺寸当前只支持:方图/长图/横图\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"指令示例:\n" +
|
||||||
|
name + "帮我画几张金凤凰,背景绚烂,高饱和,古风,仙境,高清,4K,古风的油画方图",
|
||||||
|
PrivateDataFolder: "wenxinAI",
|
||||||
|
}).ApplySingle(single.New(
|
||||||
|
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||||
|
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||||
|
ctx.Break()
|
||||||
|
ctx.Send(
|
||||||
|
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||||
|
message.Text(zero.BotConfig.NickName[0], "正在给别人画图,请不要打扰哦"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||||
|
vilginfo.db = sql.New(engine.DataFolder() + "ernieVilg.db")
|
||||||
|
err := vilginfo.db.Open(time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
// 画图
|
||||||
|
engine.OnRegex(`画几张(.*[^的$])的(.*[^\s$])(方图|长图|横图)$`, zero.OnlyToMe, getdb).SetBlock(true).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
uid := -ctx.Event.UserID
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
// 获取个人和群的key
|
||||||
|
userinfo, err1 := vilginfo.checkGroup(uid, "vilg")
|
||||||
|
info, err2 := vilginfo.checkGroup(gid, "vilg")
|
||||||
|
switch {
|
||||||
|
// 如果是个人请求且报错
|
||||||
|
case gid == 0 && err1 != nil:
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err1))
|
||||||
|
return
|
||||||
|
// 如果群报错而个人没有,就切换成个人的
|
||||||
|
case err2 != nil && err1 == nil:
|
||||||
|
gid = uid
|
||||||
|
info = userinfo
|
||||||
|
// 如果都报错就以群为优先级
|
||||||
|
case err1 != nil && err2 != nil:
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err2))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 判断使用次数
|
||||||
|
check := false
|
||||||
|
switch {
|
||||||
|
// 群和个人都没有次数了
|
||||||
|
case info.DayLimit == 0 && userinfo.DayLimit == 0:
|
||||||
|
ctx.SendChain(message.Text("我已经画了", limit, "张了!我累了!不画不画,就不画!"))
|
||||||
|
return
|
||||||
|
// 个人还有次数的话
|
||||||
|
case info.DayLimit == 0 && userinfo.DayLimit != 0:
|
||||||
|
check = true
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
// 群和个人都没有总次数了
|
||||||
|
case info.MaxLimit == 0 && userinfo.MaxLimit == 0:
|
||||||
|
ctx.SendChain(message.Text("设置的key使用次数超过了限额,请更换key。"))
|
||||||
|
return
|
||||||
|
// 个人还有总次数的话
|
||||||
|
case info.MaxLimit == 0 && userinfo.MaxLimit != 0:
|
||||||
|
check = true
|
||||||
|
}
|
||||||
|
if check { // 如果只有个人有次数就切换回个人key
|
||||||
|
gid = uid
|
||||||
|
info = userinfo
|
||||||
|
}
|
||||||
|
// 创建任务
|
||||||
|
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
if len([]rune(keyword)) >= 64 { // 描述不能超过64个字
|
||||||
|
ctx.SendChain(message.Text("要求太多了啦!减少点!"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
picType := ctx.State["regex_matched"].([]string)[2]
|
||||||
|
chooseSize := ctx.State["regex_matched"].([]string)[3]
|
||||||
|
wtime := 3
|
||||||
|
picSize := "1024*1024"
|
||||||
|
switch chooseSize {
|
||||||
|
case "长图":
|
||||||
|
wtime = 5
|
||||||
|
picSize = "1024*1536"
|
||||||
|
case "横图":
|
||||||
|
wtime = 5
|
||||||
|
picSize = "1536*1024"
|
||||||
|
}
|
||||||
|
taskID, err := wenxin.BuildWork(info.Token, keyword, picType, picSize)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if taskID < 1 {
|
||||||
|
ctx.SendChain(message.Text("要求太复杂力!想不出来..."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 开始画图
|
||||||
|
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "知道了,我可能需要", time.Duration(wtime*10)*time.Second, "左右才能画好哦,请等待..."))
|
||||||
|
i := 0
|
||||||
|
for range time.NewTicker(10 * time.Second).C {
|
||||||
|
// 等待 wtime * 10秒
|
||||||
|
i++
|
||||||
|
if i <= wtime {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if i > 60{// 十分钟还不出图就放弃
|
||||||
|
ctx.SendChain(message.Text("呜呜呜,要求太复杂力!画不出来..."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 获取结果*/
|
||||||
|
picURL, status, err := wenxin.GetPic(info.Token, taskID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if status == "0" {
|
||||||
|
lastTime := time.Duration(i * 10 * int(time.Second))
|
||||||
|
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("我画好了!\n本次绘画用了", lastTime))}
|
||||||
|
for _, imginfo := range picURL {
|
||||||
|
msg = append(msg,
|
||||||
|
ctxext.FakeSenderForwardNode(ctx,
|
||||||
|
message.Image(imginfo.Image)))
|
||||||
|
}
|
||||||
|
if id := ctx.Send(msg).ID(); id == 0 {
|
||||||
|
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = vilginfo.update(gid, 1)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err))
|
||||||
|
}
|
||||||
|
process.SleepAbout1sTo2s()
|
||||||
|
ctx.SendChain(message.Text("累死了,今天我最多只能画", info.DayLimit-1, "张图哦"))
|
||||||
|
})
|
||||||
|
engine.OnRegex(`^为(群)?(自己|本群|\d+)设置画图key\s(.*[^\s$])\s(.+)$`, getdb).SetBlock(true).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
mode := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
user := ctx.State["regex_matched"].([]string)[2]
|
||||||
|
aKey := ctx.State["regex_matched"].([]string)[3]
|
||||||
|
sKey := ctx.State["regex_matched"].([]string)[4]
|
||||||
|
dbID := -ctx.Event.UserID // 默认给自己
|
||||||
|
switch {
|
||||||
|
case mode != "": // 指定群的话
|
||||||
|
gid, err := strconv.ParseInt(user, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbID = gid
|
||||||
|
case user == "本群": // 用于本群
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
if gid == 0 {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, "请指定群聊,或者使用指令;\n为群xxx设置AI画图key xxx xxx"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbID = gid
|
||||||
|
case user != "自己": // 给别人开key
|
||||||
|
uid, err := strconv.ParseInt(user, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbID = -uid
|
||||||
|
}
|
||||||
|
err := vilginfo.insert(dbID, "vilg", aKey, sKey)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(serviceErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(message.Text("成功!"))
|
||||||
|
})
|
||||||
|
/*********************************************************/
|
||||||
|
en := control.Register("wenxinmodel", &ctrl.Options[*zero.Ctx]{
|
||||||
|
DisableOnDefault: false,
|
||||||
|
Brief: "文心AI文本处理",
|
||||||
|
Help: "基于百度文心AI的API文本处理\n" +
|
||||||
|
"key申请链接:https://wenxin.baidu.com/moduleApi/key\n" +
|
||||||
|
"key和ernievilg插件的key相同。\n" +
|
||||||
|
"注意:每个apikey每日上限200条,总上限2000条。次数超过了请自行更新apikey\n" +
|
||||||
|
"- 为[自己/本群/QQ号/群+群号]设置文心key [API Key] [Secret Key]\n" +
|
||||||
|
"例:\n为自己设置文心key 123 456\n为10086设置文心key 123 456\n为群10010设置文心key 789 101\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心作文 (x字的)[作文题目]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心提案 (x字的)[文案标题]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心摘要 (x字的)[文章内容]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心小说 (x字的)[小说上文]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心对联 [上联]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心问答 [问题]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心补全 [带“_”的填空题]\n" +
|
||||||
|
"————————————————————\n" +
|
||||||
|
"- 文心自定义 [prompt]\n\n" +
|
||||||
|
"prompt: [问题描述] [问题类型]:[题目] [解答类型]:[解题必带内容]\n" +
|
||||||
|
"指令示例:\n" +
|
||||||
|
"文心自定义 请写出下面这道题的解题过程。\\n题目:养殖场养鸭376只,养鸡的只数比鸭多258只,这个养殖场一共养鸭和鸡多少只?\\n解:\n\n" +
|
||||||
|
"文心自定义 1+1=?\n" +
|
||||||
|
"文心自定义 歌曲名:大风车转啊转\\n歌词:",
|
||||||
|
}).ApplySingle(single.New(
|
||||||
|
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||||
|
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||||
|
ctx.Break()
|
||||||
|
ctx.Send(
|
||||||
|
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||||
|
message.Text(zero.BotConfig.NickName[0], "正在给别人编辑,请不要打扰哦"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
getmodeldb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||||
|
modelinfo.db = sql.New(engine.DataFolder() + "ernieModel.db")
|
||||||
|
err := modelinfo.db.Open(time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
en.OnRegex(`^为(群)?(自己|本群|\d+)设置文心key\s(.*[^\s$])\s(.+)$`, getmodeldb).SetBlock(true).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
mode := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
user := ctx.State["regex_matched"].([]string)[2]
|
||||||
|
aKey := ctx.State["regex_matched"].([]string)[3]
|
||||||
|
sKey := ctx.State["regex_matched"].([]string)[4]
|
||||||
|
dbID := -ctx.Event.UserID // 默认给自己
|
||||||
|
switch {
|
||||||
|
case mode != "": // 指定群的话
|
||||||
|
gid, err := strconv.ParseInt(user, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbID = gid
|
||||||
|
case user == "本群": // 用于本群
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
if gid == 0 {
|
||||||
|
ctx.SendChain(message.Text(modelErr, "请指定群聊,或者使用指令;\n为群xxx设置AI画图key xxx xxx"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbID = gid
|
||||||
|
case user != "自己": // 给别人开key
|
||||||
|
uid, err := strconv.ParseInt(user, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbID = -uid
|
||||||
|
}
|
||||||
|
err := modelinfo.insert(dbID, "model", aKey, sKey)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(message.Text("成功!"))
|
||||||
|
})
|
||||||
|
|
||||||
|
var erniemodel = map[string]int{
|
||||||
|
"作文": 1,
|
||||||
|
"提案": 2,
|
||||||
|
"摘要": 3,
|
||||||
|
"对联": 4,
|
||||||
|
"问答": 5,
|
||||||
|
"小说": 6,
|
||||||
|
"补全": 7,
|
||||||
|
"自定义": 8}
|
||||||
|
var erniePrompt = map[string]string{
|
||||||
|
"作文": "zuowen",
|
||||||
|
"提案": "adtext",
|
||||||
|
"摘要": "Summarization",
|
||||||
|
"对联": "couplet",
|
||||||
|
"问答": "Dialogue",
|
||||||
|
"小说": "novel",
|
||||||
|
"补全": "cloze"}
|
||||||
|
en.OnRegex(`^文心(作文|提案|摘要|小说)\s?((\d+)字的)?(.*)$`, getmodeldb).SetBlock(true).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
uid := -ctx.Event.UserID
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
// 获取个人和群的key
|
||||||
|
userinfo, err1 := modelinfo.checkGroup(uid, "model")
|
||||||
|
info, err2 := modelinfo.checkGroup(gid, "model")
|
||||||
|
switch {
|
||||||
|
// 如果是个人请求且报错
|
||||||
|
case gid == 0 && err1 != nil:
|
||||||
|
ctx.SendChain(message.Text(modelErr, err1))
|
||||||
|
return
|
||||||
|
// 如果群报错而个人没有,就切换成个人的
|
||||||
|
case err2 != nil && err1 == nil:
|
||||||
|
gid = uid
|
||||||
|
info = userinfo
|
||||||
|
// 如果都报错就以群为优先级
|
||||||
|
case err1 != nil && err2 != nil:
|
||||||
|
ctx.SendChain(message.Text(modelErr, err2))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 判断使用次数
|
||||||
|
check := false
|
||||||
|
switch {
|
||||||
|
// 群和个人都没有次数了
|
||||||
|
case info.DayLimit == 0 && userinfo.DayLimit == 0:
|
||||||
|
ctx.SendChain(message.Text("今日请求次数已到200次了,明天在玩吧"))
|
||||||
|
return
|
||||||
|
// 个人还有次数的话
|
||||||
|
case info.DayLimit == 0 && userinfo.DayLimit != 0:
|
||||||
|
check = true
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
// 群和个人都没有总次数了
|
||||||
|
case info.MaxLimit == 0 && userinfo.MaxLimit == 0:
|
||||||
|
ctx.SendChain(message.Text("设置的key使用次数超过了限额,请更换key。"))
|
||||||
|
return
|
||||||
|
// 个人还有总次数的话
|
||||||
|
case info.MaxLimit == 0 && userinfo.MaxLimit != 0:
|
||||||
|
check = true
|
||||||
|
}
|
||||||
|
if check { // 如果只有个人有次数就切换回个人key
|
||||||
|
gid = uid
|
||||||
|
info = userinfo
|
||||||
|
}
|
||||||
|
// 调用API
|
||||||
|
modelStr := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
mun := ctx.State["regex_matched"].([]string)[3]
|
||||||
|
minlen := 1
|
||||||
|
maxlen := 128
|
||||||
|
if mun != "" {
|
||||||
|
maxNum, err := strconv.Atoi(mun)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
minlen = maxNum
|
||||||
|
if maxNum > 128 {
|
||||||
|
maxlen = maxNum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyword := ctx.State["regex_matched"].([]string)[4]
|
||||||
|
if len([]rune(keyword)) >= 1000 { // 描述不能超过1000
|
||||||
|
ctx.SendChain(message.Text("是你写作文还是我写?减少点!"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result, err := model.GetResult(info.Token, erniemodel[modelStr], keyword, minlen, maxlen, erniePrompt[modelStr])
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if id := ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(keyword, ",", result))); id.ID() == 0 {
|
||||||
|
ctx.SendChain(message.Text("ERROR: 请求超时!"))
|
||||||
|
}
|
||||||
|
err = modelinfo.update(gid, 1)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
en.OnRegex(`^文心(对联|问答|补全|自定义)\s?(.*)$`, getmodeldb).SetBlock(true).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
uid := -ctx.Event.UserID
|
||||||
|
gid := ctx.Event.GroupID
|
||||||
|
// 获取个人和群的key
|
||||||
|
userinfo, err1 := modelinfo.checkGroup(uid, "model")
|
||||||
|
info, err2 := modelinfo.checkGroup(gid, "model")
|
||||||
|
switch {
|
||||||
|
// 如果是个人请求且报错
|
||||||
|
case gid == 0 && err1 != nil:
|
||||||
|
ctx.SendChain(message.Text(modelErr, err1))
|
||||||
|
return
|
||||||
|
// 如果群报错而个人没有,就切换成个人的
|
||||||
|
case err2 != nil && err1 == nil:
|
||||||
|
gid = uid
|
||||||
|
info = userinfo
|
||||||
|
// 如果都报错就以群为优先级
|
||||||
|
case err1 != nil && err2 != nil:
|
||||||
|
ctx.SendChain(message.Text(modelErr, err2))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 判断使用次数
|
||||||
|
check := false
|
||||||
|
switch {
|
||||||
|
// 群和个人都没有次数了
|
||||||
|
case info.DayLimit == 0 && userinfo.DayLimit == 0:
|
||||||
|
ctx.SendChain(message.Text("今日请求次数已到200次了,明天在玩吧"))
|
||||||
|
return
|
||||||
|
// 个人还有次数的话
|
||||||
|
case info.DayLimit == 0 && userinfo.DayLimit != 0:
|
||||||
|
check = true
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
// 群和个人都没有总次数了
|
||||||
|
case info.MaxLimit == 0 && userinfo.MaxLimit == 0:
|
||||||
|
ctx.SendChain(message.Text("设置的key使用次数超过了限额,请更换key。"))
|
||||||
|
return
|
||||||
|
// 个人还有总次数的话
|
||||||
|
case info.MaxLimit == 0 && userinfo.MaxLimit != 0:
|
||||||
|
check = true
|
||||||
|
}
|
||||||
|
if check { // 如果只有个人有次数就切换回个人key
|
||||||
|
gid = uid
|
||||||
|
info = userinfo
|
||||||
|
}
|
||||||
|
// 创建任务
|
||||||
|
modelStr := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
keyword := ctx.State["regex_matched"].([]string)[2]
|
||||||
|
if len([]rune(keyword)) >= 1000 { // 描述不能超过1000
|
||||||
|
ctx.SendChain(message.Text("你在写作文吗?减少点!"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result, err := model.GetResult(info.Token, erniemodel[modelStr], keyword, 1, 128, erniePrompt[modelStr])
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if id := ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(result))); id.ID() == 0 {
|
||||||
|
ctx.SendChain(message.Text("ERROR: 请求超时!"))
|
||||||
|
}
|
||||||
|
err = modelinfo.update(gid, 1)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text(modelErr, err))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登记group的key
|
||||||
|
func (sql *keydb) insert(gid int64, model, akey, skey string) error {
|
||||||
|
sql.Lock()
|
||||||
|
defer sql.Unlock()
|
||||||
|
// 给db文件创建表格(没有才创建),表格名称groupinfo,表格结构apikey
|
||||||
|
err := sql.db.Create("groupinfo", &apikey{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 获取group信息
|
||||||
|
groupinfo := apikey{} // 用于暂存数据
|
||||||
|
err = sql.db.Find("groupinfo", &groupinfo, "WHERE ID = ?", gid)
|
||||||
|
if err != nil {
|
||||||
|
// 如果该group没有注册过
|
||||||
|
err = sql.db.Find("groupinfo", &groupinfo, "WHERE APIKey = ? and SecretKey = ?", akey, skey)
|
||||||
|
if err == nil {
|
||||||
|
// 如果key存在过将当前的数据迁移过去
|
||||||
|
groupinfo.ID = gid
|
||||||
|
} else {
|
||||||
|
groupinfo = apikey{
|
||||||
|
ID: gid,
|
||||||
|
APIKey: akey,
|
||||||
|
SecretKey: skey,
|
||||||
|
}
|
||||||
|
switch model {
|
||||||
|
case "vilg":
|
||||||
|
groupinfo.MaxLimit = 500
|
||||||
|
case "model":
|
||||||
|
groupinfo.MaxLimit = 2000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sql.db.Insert("groupinfo", &groupinfo)
|
||||||
|
}
|
||||||
|
// 进行更新
|
||||||
|
groupinfo.APIKey = akey
|
||||||
|
groupinfo.SecretKey = skey
|
||||||
|
groupinfo.Token = ""
|
||||||
|
groupinfo.Updatetime = 0
|
||||||
|
switch model {
|
||||||
|
case "vilg":
|
||||||
|
groupinfo.MaxLimit = 500
|
||||||
|
case "model":
|
||||||
|
groupinfo.MaxLimit = 2000
|
||||||
|
}
|
||||||
|
return sql.db.Insert("groupinfo", &groupinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取group信息
|
||||||
|
func (sql *keydb) checkGroup(gid int64, model string) (groupinfo apikey, err error) {
|
||||||
|
sql.Lock()
|
||||||
|
defer sql.Unlock()
|
||||||
|
// 给db文件创建表格(没有才创建),表格名称groupinfo,表格结构apikey
|
||||||
|
err = sql.db.Create("groupinfo", &apikey{})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch model {
|
||||||
|
case "vilg":
|
||||||
|
limit = 50
|
||||||
|
model = "画图"
|
||||||
|
case "model":
|
||||||
|
limit = 200
|
||||||
|
model = "文心"
|
||||||
|
}
|
||||||
|
// 先判断该群是否已经设置过key了
|
||||||
|
if ok := sql.db.CanFind("groupinfo", "WHERE ID = ?", gid); !ok {
|
||||||
|
if gid > 0 {
|
||||||
|
err = errors.New("该群没有设置过apikey,请前往https://wenxin.baidu.com/moduleApi/key获取key值后,发送指令:\n为本群设置" + model + "key [API Key] [Secret Key]\n或\n为自己设置" + model + "key [API Key] [Secret Key]")
|
||||||
|
} else {
|
||||||
|
err = errors.New("你没有设置过apikey,请前往https://wenxin.baidu.com/moduleApi/key获取key值后,发送指令:\n为自己设置" + model + "key [API Key] [Secret Key]")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 获取group信息
|
||||||
|
err = sql.db.Find("groupinfo", &groupinfo, "WHERE ID = ?", gid)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 如果隔天使用刷新次数
|
||||||
|
if time.Now().Format("2006/01/02") != groupinfo.Lasttime {
|
||||||
|
groupinfo.DayLimit = limit
|
||||||
|
groupinfo.Lasttime = time.Now().Format("2006/01/02")
|
||||||
|
}
|
||||||
|
if err = sql.db.Insert("groupinfo", &groupinfo); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 如果token有效期过期
|
||||||
|
if time.Since(time.Unix(groupinfo.Updatetime, 0)).Hours() > 24 || groupinfo.Token == "" {
|
||||||
|
token, err1 := wenxin.GetToken(groupinfo.APIKey, groupinfo.SecretKey)
|
||||||
|
if err1 != nil {
|
||||||
|
err = err1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
groupinfo.Token = token
|
||||||
|
groupinfo.Updatetime = time.Now().Unix()
|
||||||
|
err = sql.db.Insert("groupinfo", &groupinfo)
|
||||||
|
if err == nil {
|
||||||
|
// 更新相同key的他人次数
|
||||||
|
otherinfo := apikey{}
|
||||||
|
var groups []int64 // 将相同的key的ID暂存
|
||||||
|
// 无视没有找到相同的key的err
|
||||||
|
_ = sql.db.FindFor("groupinfo", &otherinfo, "WHERE ID <> ? AND APIKey = ? AND SecretKey = ?", func() error {
|
||||||
|
groups = append(groups, otherinfo.ID)
|
||||||
|
return nil
|
||||||
|
}, gid, groupinfo.APIKey, groupinfo.SecretKey)
|
||||||
|
if len(groups) != 0 { // 如果有相同的key就更新
|
||||||
|
for _, group := range groups {
|
||||||
|
err = sql.db.Find("groupinfo", &otherinfo, "WHERE ID = ?", group)
|
||||||
|
if err == nil {
|
||||||
|
otherinfo.Token = groupinfo.Token
|
||||||
|
otherinfo.Updatetime = groupinfo.Updatetime
|
||||||
|
err = sql.db.Insert("groupinfo", &otherinfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录次数(-sub)
|
||||||
|
func (sql *keydb) update(gid int64, sub int) error {
|
||||||
|
sql.Lock()
|
||||||
|
defer sql.Unlock()
|
||||||
|
// 给db文件创建表格(没有才创建),表格名称groupinfo,表格结构apikey
|
||||||
|
err := sql.db.Create("groupinfo", &apikey{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
groupinfo := apikey{} // 用于暂存数据
|
||||||
|
// 获取group信息
|
||||||
|
err = sql.db.Find("groupinfo", &groupinfo, "WHERE ID = ?", gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
groupinfo.MaxLimit -= sub
|
||||||
|
groupinfo.DayLimit -= sub
|
||||||
|
err = sql.db.Insert("groupinfo", &groupinfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 更新相同key的他人次数
|
||||||
|
otherinfo := apikey{}
|
||||||
|
var groups []int64 // 将相同的key的ID暂存
|
||||||
|
// 无视没有找到相同的key的err
|
||||||
|
_ = sql.db.FindFor("groupinfo", &otherinfo, "WHERE ID <> ? AND APIKey = ? AND SecretKey = ?", func() error {
|
||||||
|
groups = append(groups, otherinfo.ID)
|
||||||
|
return nil
|
||||||
|
}, gid, groupinfo.APIKey, groupinfo.SecretKey)
|
||||||
|
if len(groups) != 0 { // 如果有相同的key就更新
|
||||||
|
for _, group := range groups {
|
||||||
|
err = sql.db.Find("groupinfo", &otherinfo, "WHERE ID = ?", group)
|
||||||
|
if err == nil {
|
||||||
|
otherinfo.MaxLimit = groupinfo.MaxLimit
|
||||||
|
otherinfo.DayLimit = groupinfo.DayLimit
|
||||||
|
otherinfo.Lasttime = groupinfo.Lasttime
|
||||||
|
err = sql.db.Insert("groupinfo", &otherinfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@ -3,9 +3,8 @@ package wife
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"strings"
|
||||||
|
|
||||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
@ -16,16 +15,16 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func init() {
|
||||||
cards = []string{}
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
re = regexp.MustCompile(`^\[(.*?)\](.*)\..*$`)
|
|
||||||
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Help: "- 抽老婆",
|
Help: "- 抽老婆",
|
||||||
Brief: "从老婆库抽每日老婆",
|
Brief: "从老婆库抽每日老婆",
|
||||||
PublicDataFolder: "Wife",
|
PublicDataFolder: "Wife",
|
||||||
}).ApplySingle(ctxext.DefaultSingle)
|
}).ApplySingle(ctxext.DefaultSingle)
|
||||||
getJSON = fcext.DoOnceOnSuccess(
|
_ = os.MkdirAll(engine.DataFolder()+"wives", 0755)
|
||||||
|
cards := []string{}
|
||||||
|
engine.OnFullMatch("抽老婆", fcext.DoOnceOnSuccess(
|
||||||
func(ctx *zero.Ctx) bool {
|
func(ctx *zero.Ctx) bool {
|
||||||
data, err := engine.GetLazyData("wife.json", true)
|
data, err := engine.GetLazyData("wife.json", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,45 +39,26 @@ var (
|
|||||||
logrus.Infof("[wife]加载%d个老婆", len(cards))
|
logrus.Infof("[wife]加载%d个老婆", len(cards))
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
)
|
)).SetBlock(true).
|
||||||
)
|
|
||||||
|
|
||||||
func card2name(card string) (string, string) {
|
|
||||||
match := re.FindStringSubmatch(card)
|
|
||||||
if len(match) >= 3 {
|
|
||||||
return match[1], match[2]
|
|
||||||
}
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
_ = os.MkdirAll(engine.DataFolder()+"wives", 0755)
|
|
||||||
engine.OnFullMatch("抽老婆", getJSON).SetBlock(true).
|
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
card := cards[fcext.RandSenderPerDayN(ctx.Event.UserID, len(cards))]
|
card := cards[fcext.RandSenderPerDayN(ctx.Event.UserID, len(cards))]
|
||||||
data, err := engine.GetLazyData("wives/"+card, true)
|
data, err := engine.GetLazyData("wives/"+card, true)
|
||||||
var msgText string
|
card, _, _ = strings.Cut(card, ".")
|
||||||
work, name := card2name(card)
|
|
||||||
if work != "" && name != "" {
|
|
||||||
msgText = fmt.Sprintf("今天的二次元老婆是~来自【%s】的【%s】哒", work, name)
|
|
||||||
} else {
|
|
||||||
msgText = fmt.Sprintf("今天的二次元老婆是~【%s】哒", card)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(
|
ctx.SendChain(
|
||||||
message.At(ctx.Event.UserID),
|
message.At(ctx.Event.UserID),
|
||||||
message.Text(msgText, "\n【图片下载失败: ", err, "】"),
|
message.Text("今天的二次元老婆是~【", card, "】哒\n【图片下载失败: ", err, "】"),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id := ctx.SendChain(
|
if id := ctx.SendChain(
|
||||||
message.At(ctx.Event.UserID),
|
message.At(ctx.Event.UserID),
|
||||||
message.Text(msgText),
|
message.Text("今天的二次元老婆是~【", card, "】哒"),
|
||||||
message.ImageBytes(data),
|
message.ImageBytes(data),
|
||||||
); id.ID() == 0 {
|
); id.ID() == 0 {
|
||||||
ctx.SendChain(
|
ctx.SendChain(
|
||||||
message.At(ctx.Event.UserID),
|
message.At(ctx.Event.UserID),
|
||||||
message.Text(msgText, "\n【图片发送失败, 多半是被夹了,请联系维护者】"),
|
message.Text("今天的二次元老婆是~【", card, "】哒\n【图片发送失败, 请联系维护者】"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,157 +0,0 @@
|
|||||||
// Package wife 抽老婆
|
|
||||||
package wife
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"math/rand"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
|
||||||
"github.com/FloatTech/zbputils/control"
|
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
|
||||||
|
|
||||||
zbmath "github.com/FloatTech/floatbox/math"
|
|
||||||
"github.com/FloatTech/imgfactory"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
sizeList = []int{0, 3, 5, 8}
|
|
||||||
enguess = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
||||||
DisableOnDefault: false,
|
|
||||||
Help: "- 猜老婆",
|
|
||||||
Brief: "从老婆库猜老婆",
|
|
||||||
}).ApplySingle(ctxext.NewGroupSingle("已经有正在进行的游戏..."))
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
enguess.OnFullMatch("猜老婆", getJSON).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
|
||||||
class := 3
|
|
||||||
|
|
||||||
card := cards[rand.Intn(len(cards))]
|
|
||||||
pic, err := engine.GetLazyData("wives/"+card, true)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("[猜老婆]error:\n", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
work, name := card2name(card)
|
|
||||||
name = strings.ToLower(name)
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(pic))
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("[猜老婆]error:\n", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dst := imgfactory.Size(img, img.Bounds().Dx(), img.Bounds().Dy())
|
|
||||||
q, err := mosaic(dst, class)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(
|
|
||||||
message.Reply(ctx.Event.MessageID),
|
|
||||||
message.Text("[猜老婆]图片生成失败:\n", err),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if id := ctx.SendChain(
|
|
||||||
message.ImageBytes(q),
|
|
||||||
); id.ID() != 0 {
|
|
||||||
ctx.SendChain(message.Text("请回答该二次元角色名字\n以“xxx酱”格式回答\n发送“跳过”结束猜题"))
|
|
||||||
}
|
|
||||||
var next *zero.FutureEvent
|
|
||||||
if ctx.Event.GroupID == 0 {
|
|
||||||
next = zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(·)?[^酱]+酱|^跳过$`), ctx.CheckSession())
|
|
||||||
} else {
|
|
||||||
next = zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(·)?[^酱]+酱|^跳过$`), zero.CheckGroup(ctx.Event.GroupID))
|
|
||||||
}
|
|
||||||
recv, cancel := next.Repeat()
|
|
||||||
defer cancel()
|
|
||||||
tick := time.NewTimer(105 * time.Second)
|
|
||||||
after := time.NewTimer(120 * time.Second)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-tick.C:
|
|
||||||
ctx.SendChain(message.Text("[猜老婆]你还有15s作答时间"))
|
|
||||||
case <-after.C:
|
|
||||||
ctx.Send(
|
|
||||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
|
||||||
message.ImageBytes(pic),
|
|
||||||
message.Text("[猜老婆]倒计时结束,游戏结束...\n角色是:\n", name, "\n出自《", work, "》\n"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
case c := <-recv:
|
|
||||||
// tick.Reset(105 * time.Second)
|
|
||||||
// after.Reset(120 * time.Second)
|
|
||||||
msg := strings.ReplaceAll(c.Event.Message.String(), "酱", "")
|
|
||||||
if msg == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if msg == "跳过" {
|
|
||||||
if msgID := ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
|
||||||
message.Text("已跳过猜题\n角色是:\n", name, "\n出自《", work, "》\n"),
|
|
||||||
message.ImageBytes(pic))); msgID.ID() == 0 {
|
|
||||||
ctx.SendChain(message.Text("太棒了,你猜对了!\n图片发送失败,可能被风控\n角色是:\n", name, "\n出自《", work, "》"))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
class--
|
|
||||||
if strings.Contains(name, strings.ToLower(msg)) {
|
|
||||||
if msgID := ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
|
||||||
message.Text("太棒了,你猜对了!\n角色是:\n", name, "\n出自《", work, "》\n"),
|
|
||||||
message.ImageBytes(pic))); msgID.ID() == 0 {
|
|
||||||
ctx.SendChain(message.Text("太棒了,你猜对了!\n图片发送失败,可能被风控\n角色是:\n", name, "\n出自《", work, "》"))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if class < 1 {
|
|
||||||
if msgID := ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
|
||||||
message.Text("很遗憾,次数到了,游戏结束!\n角色是:\n", name, "\n出自《", work, "》\n"),
|
|
||||||
message.ImageBytes(pic))); msgID.ID() == 0 {
|
|
||||||
ctx.SendChain(message.Text("很遗憾,次数到了,游戏结束!\n图片发送失败,可能被风控\n角色是:\n", name, "\n出自《", work, "》"))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
q, err = mosaic(dst, class)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(
|
|
||||||
message.Text("回答错误,你还有", class, "次机会\n请继续作答\n(提示:", work, ")"),
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
msg = ""
|
|
||||||
if class == 2 {
|
|
||||||
msg = "(提示:" + work + ")\n"
|
|
||||||
}
|
|
||||||
ctx.SendChain(
|
|
||||||
message.Text("回答错误,你还有", class, "次机会\n", msg, "请继续作答(难度降低)\n"),
|
|
||||||
message.ImageBytes(q),
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 马赛克生成
|
|
||||||
func mosaic(dst *imgfactory.Factory, level int) ([]byte, error) {
|
|
||||||
b := dst.Image().Bounds()
|
|
||||||
p := imgfactory.NewFactoryBG(dst.W(), dst.H(), color.NRGBA{255, 255, 255, 255})
|
|
||||||
markSize := zbmath.Max(b.Max.X, b.Max.Y) * sizeList[level] / 200
|
|
||||||
|
|
||||||
for yOfMarknum := 0; yOfMarknum <= zbmath.Ceil(b.Max.Y, markSize); yOfMarknum++ {
|
|
||||||
for xOfMarknum := 0; xOfMarknum <= zbmath.Ceil(b.Max.X, markSize); xOfMarknum++ {
|
|
||||||
a := dst.Image().At(xOfMarknum*markSize+markSize/2, yOfMarknum*markSize+markSize/2)
|
|
||||||
cc := color.NRGBAModel.Convert(a).(color.NRGBA)
|
|
||||||
for y := 0; y < markSize; y++ {
|
|
||||||
for x := 0; x < markSize; x++ {
|
|
||||||
xOfPic := xOfMarknum*markSize + x
|
|
||||||
yOfPic := yOfMarknum*markSize + y
|
|
||||||
p.Image().Set(xOfPic, yOfPic, cc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return imgfactory.ToBytes(p.Blur(3).Image())
|
|
||||||
}
|
|
||||||
@ -2,16 +2,16 @@
|
|||||||
package wordcount
|
package wordcount
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fumiama/jieba"
|
"github.com/go-ego/gse"
|
||||||
"github.com/golang/freetype"
|
"github.com/golang/freetype"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
@ -27,32 +27,31 @@ import (
|
|||||||
|
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
re = regexp.MustCompile(`^[一-龥]+$`)
|
re = regexp.MustCompile(`^[一-龥]+$`)
|
||||||
stopwords []string
|
stopwords []string
|
||||||
|
seg gse.Segmenter
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "聊天热词",
|
Brief: "聊天热词",
|
||||||
Help: "- 热词 [消息数目]|热词 1000",
|
Help: "- 热词 [群号] [消息数目]|热词 123456 1000",
|
||||||
PublicDataFolder: "WordCount",
|
PublicDataFolder: "WordCount",
|
||||||
})
|
})
|
||||||
cachePath := engine.DataFolder() + "cache/"
|
cachePath := engine.DataFolder() + "cache/"
|
||||||
dat, err := file.GetLazyData("data/Chat/dict.txt", control.Md5File, true)
|
// 读取gse内置中文词典
|
||||||
if err != nil {
|
err := seg.LoadDictEmbed()
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
seg, err := jieba.LoadDictionary(bytes.NewReader(dat))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
_ = os.RemoveAll(cachePath)
|
_ = os.RemoveAll(cachePath)
|
||||||
_ = os.MkdirAll(cachePath, 0755)
|
_ = os.MkdirAll(cachePath, 0755)
|
||||||
engine.OnRegex(`^热词\s?(\d*)$`, zero.OnlyGroup, fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
engine.OnRegex(`^热词\s?(\d*)\s?(\d*)$`, zero.OnlyGroup, fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||||
_, err := engine.GetLazyData("stopwords.txt", false)
|
_, err := engine.GetLazyData("stopwords.txt", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
@ -86,14 +85,17 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||||
p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
gid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||||
|
p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
|
||||||
if p > 10000 {
|
if p > 10000 {
|
||||||
p = 10000
|
p = 10000
|
||||||
}
|
}
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
p = 1000
|
p = 1000
|
||||||
}
|
}
|
||||||
gid := ctx.Event.GroupID
|
if gid == 0 {
|
||||||
|
gid = ctx.Event.GroupID
|
||||||
|
}
|
||||||
group := ctx.GetGroupInfo(gid, false)
|
group := ctx.GetGroupInfo(gid, false)
|
||||||
if group.MemberCount == 0 {
|
if group.MemberCount == 0 {
|
||||||
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "未加入", group.Name, "(", gid, "),无法获得热词呢"))
|
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "未加入", group.Name, "(", gid, "),无法获得热词呢"))
|
||||||
@ -106,21 +108,44 @@ func init() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
messageMap := make(map[string]int, 256)
|
messageMap := make(map[string]int, 256)
|
||||||
h := ctx.GetGroupMessageHistory(gid, 0, p, false)
|
msghists := make(chan *gjson.Result, 256)
|
||||||
h.Get("messages").ForEach(func(_, msgObj gjson.Result) bool {
|
go func() {
|
||||||
tex := strings.TrimSpace(message.ParseMessageFromString(msgObj.Get("raw_message").Str).ExtractPlainText())
|
h := ctx.GetLatestGroupMessageHistory(gid)
|
||||||
if tex != "" {
|
messageSeq := h.Get("messages.0.message_seq").Int()
|
||||||
words := seg.Cut(tex, true)
|
msghists <- &h
|
||||||
for _, word := range words {
|
for i := 1; i < int(p/20) && messageSeq != 0; i++ {
|
||||||
word = strings.TrimSpace(word)
|
h := ctx.GetGroupMessageHistory(gid, messageSeq)
|
||||||
i := sort.SearchStrings(stopwords, word)
|
msghists <- &h
|
||||||
if re.MatchString(word) && (i >= len(stopwords) || stopwords[i] != word) {
|
messageSeq = h.Get("messages.0.message_seq").Int()
|
||||||
messageMap[word]++
|
}
|
||||||
|
close(msghists)
|
||||||
|
}()
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var mapmu sync.Mutex
|
||||||
|
for h := range msghists {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(h *gjson.Result) {
|
||||||
|
for _, v := range h.Get("messages.#.message").Array() {
|
||||||
|
tex := strings.TrimSpace(message.ParseMessageFromString(v.Str).ExtractPlainText())
|
||||||
|
if tex == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
segments := seg.Segment(helper.StringToBytes(tex))
|
||||||
|
words := gse.ToSlice(segments, true)
|
||||||
|
for _, word := range words {
|
||||||
|
word = strings.TrimSpace(word)
|
||||||
|
i := sort.SearchStrings(stopwords, word)
|
||||||
|
if re.MatchString(word) && (i >= len(stopwords) || stopwords[i] != word) {
|
||||||
|
mapmu.Lock()
|
||||||
|
messageMap[word]++
|
||||||
|
mapmu.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
wg.Done()
|
||||||
return true
|
}(h)
|
||||||
})
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
wc := rankByWordCount(messageMap)
|
wc := rankByWordCount(messageMap)
|
||||||
if len(wc) > 20 {
|
if len(wc) > 20 {
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
|
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,7 +69,16 @@ func init() {
|
|||||||
"- 团队六阶猜单词\n" +
|
"- 团队六阶猜单词\n" +
|
||||||
"- 团队七阶猜单词",
|
"- 团队七阶猜单词",
|
||||||
PublicDataFolder: "Wordle",
|
PublicDataFolder: "Wordle",
|
||||||
}).ApplySingle(ctxext.NewGroupSingle("已经有正在进行的游戏..."))
|
}).ApplySingle(single.New(
|
||||||
|
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||||
|
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||||
|
ctx.Send(
|
||||||
|
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||||
|
message.Text("已经有正在进行的游戏..."),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
|
||||||
en.OnRegex(`^(个人|团队)(五阶|六阶|七阶)?猜单词$`, zero.OnlyGroup, fcext.DoOnceOnSuccess(
|
en.OnRegex(`^(个人|团队)(五阶|六阶|七阶)?猜单词$`, zero.OnlyGroup, fcext.DoOnceOnSuccess(
|
||||||
func(ctx *zero.Ctx) bool {
|
func(ctx *zero.Ctx) bool {
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
// Package ygocdb 游戏王卡查插件
|
// Package ygo 一些关于ygo的插件
|
||||||
package ygocdb
|
package ygo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/FloatTech/floatbox/web"
|
"github.com/FloatTech/floatbox/web"
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
control "github.com/FloatTech/zbputils/control"
|
control "github.com/FloatTech/zbputils/control"
|
||||||
@ -38,7 +39,7 @@ type searchResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
en := control.Register("ygocdb", &ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "游戏王百鸽API", // 本插件基于游戏王百鸽API"https://www.ygo-sem.cn/"
|
Brief: "游戏王百鸽API", // 本插件基于游戏王百鸽API"https://www.ygo-sem.cn/"
|
||||||
Help: "- /ydp [xxx]\n" +
|
Help: "- /ydp [xxx]\n" +
|
||||||
@ -1,5 +1,5 @@
|
|||||||
// Package ygotrade 游戏王卡价查询插件
|
// Package ygo 一些关于ygo的插件
|
||||||
package ygotrade
|
package ygo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -46,7 +46,7 @@ type tradeInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
engine := control.Register("ygotrade", &ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Brief: "游戏王卡价查询", // 本插件基于集换社API
|
Brief: "游戏王卡价查询", // 本插件基于集换社API
|
||||||
Help: "- 查卡价 [卡名]\n- 查卡价 [卡名] -r [稀有度 稀有度 ...]\n- 查卡店 [卡名]\n- 查卡店 [卡名] -r [稀有度]",
|
Help: "- 查卡价 [卡名]\n- 查卡价 [卡名] -r [稀有度 稀有度 ...]\n- 查卡店 [卡名]\n- 查卡店 [卡名] -r [稀有度]",
|
||||||
@ -72,7 +72,7 @@ func init() {
|
|||||||
|
|
||||||
func sendYmgal(y ymgal, ctx *zero.Ctx) {
|
func sendYmgal(y ymgal, ctx *zero.Ctx) {
|
||||||
if y.PictureList == "" {
|
if y.PictureList == "" {
|
||||||
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "暂时没有这样的图呢"))
|
ctx.SendChain(message.Text(zero.BotConfig.NickName[0] + "暂时没有这样的图呢"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(y.Title))}
|
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(y.Title))}
|
||||||
|
|||||||
3
run.bat
3
run.bat
@ -3,6 +3,5 @@ go env -w GOPROXY=https://goproxy.cn,direct
|
|||||||
go env -w GO111MODULE=auto
|
go env -w GO111MODULE=auto
|
||||||
go mod tidy
|
go mod tidy
|
||||||
::go build -ldflags="-s -w" -o ZeroBot-Plugin.exe
|
::go build -ldflags="-s -w" -o ZeroBot-Plugin.exe
|
||||||
go generate main.go
|
go run main.go
|
||||||
go run -ldflags "-s -w" main.go
|
|
||||||
pause
|
pause
|
||||||
|
|||||||
3
run.sh
3
run.sh
@ -3,5 +3,4 @@ go env -w GOPROXY=https://goproxy.cn,direct
|
|||||||
go env -w GO111MODULE=auto
|
go env -w GO111MODULE=auto
|
||||||
go mod tidy
|
go mod tidy
|
||||||
#go build -ldflags="-s -w" -o ZeroBot-Plugin
|
#go build -ldflags="-s -w" -o ZeroBot-Plugin
|
||||||
go generate main.go
|
go run main.go
|
||||||
go run -ldflags "-s -w" main.go
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
"0409": {
|
"0409": {
|
||||||
"identity": {
|
"identity": {
|
||||||
"name": "ZeroBot-Plugin",
|
"name": "ZeroBot-Plugin",
|
||||||
"version": "1.10.0.2279"
|
"version": "1.9.8.2223"
|
||||||
},
|
},
|
||||||
"description": "",
|
"description": "",
|
||||||
"minimum-os": "vista",
|
"minimum-os": "vista",
|
||||||
@ -36,23 +36,23 @@
|
|||||||
"#1": {
|
"#1": {
|
||||||
"0000": {
|
"0000": {
|
||||||
"fixed": {
|
"fixed": {
|
||||||
"file_version": "1.10.0.2279",
|
"file_version": "1.9.8.2223",
|
||||||
"product_version": "v1.10.0",
|
"product_version": "v1.9.8",
|
||||||
"timestamp": "2025-09-30T23:54:09+08:00"
|
"timestamp": "2025-06-01T18:52:57+08:00"
|
||||||
},
|
},
|
||||||
"info": {
|
"info": {
|
||||||
"0409": {
|
"0409": {
|
||||||
"Comments": "OneBot plugins based on ZeroBot",
|
"Comments": "OneBot plugins based on ZeroBot",
|
||||||
"CompanyName": "FloatTech",
|
"CompanyName": "FloatTech",
|
||||||
"FileDescription": "https://github.com/FloatTech/ZeroBot-Plugin",
|
"FileDescription": "https://github.com/FloatTech/ZeroBot-Plugin",
|
||||||
"FileVersion": "1.10.0.2279",
|
"FileVersion": "1.9.8.2223",
|
||||||
"InternalName": "",
|
"InternalName": "",
|
||||||
"LegalCopyright": "© 2020 - 2025 FloatTech. All Rights Reserved.",
|
"LegalCopyright": "© 2020 - 2025 FloatTech. All Rights Reserved.",
|
||||||
"LegalTrademarks": "",
|
"LegalTrademarks": "",
|
||||||
"OriginalFilename": "ZBP.EXE",
|
"OriginalFilename": "ZBP.EXE",
|
||||||
"PrivateBuild": "",
|
"PrivateBuild": "",
|
||||||
"ProductName": "ZeroBot-Plugin",
|
"ProductName": "ZeroBot-Plugin",
|
||||||
"ProductVersion": "v1.10.0",
|
"ProductVersion": "v1.9.8",
|
||||||
"SpecialBuild": ""
|
"SpecialBuild": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user