mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-07 23:50:25 +00:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5729b4e27 | ||
|
|
7f4830d50f | ||
|
|
39d319bf70 | ||
|
|
1dd94c2d37 | ||
|
|
f6934709cc | ||
|
|
1c8ff7b143 | ||
|
|
79080cc2f0 | ||
|
|
e59ab9f798 | ||
|
|
37dfad9a29 | ||
|
|
d84a4a57a8 | ||
|
|
bb14767829 | ||
|
|
dcb83bbeee | ||
|
|
add70383c9 | ||
|
|
d43239841d | ||
|
|
a3115da138 | ||
|
|
454425daf2 | ||
|
|
d8c4aa82e3 | ||
|
|
6fe621fbfe | ||
|
|
f27e603e39 | ||
|
|
ec8c402593 | ||
|
|
be42865c2a | ||
|
|
ac2d9bb596 | ||
|
|
b025ca5738 | ||
|
|
4fd22ee7c7 | ||
|
|
e4fede7a75 | ||
|
|
4fa79497da | ||
|
|
8bf1f0b221 | ||
|
|
7d231dfd8d | ||
|
|
c8d30b9f06 | ||
|
|
1e6bc9abdd | ||
|
|
625ed39d13 | ||
|
|
55e538cdb6 | ||
|
|
b432731c9b | ||
|
|
d14e1be92b | ||
|
|
6c4c4770f9 | ||
|
|
213b4e21ad | ||
|
|
fafbc8165e | ||
|
|
981f4c5dd7 | ||
|
|
d1abd3e1d5 | ||
|
|
6d30750f42 | ||
|
|
78e1aa6783 | ||
|
|
9bfaa0c195 | ||
|
|
36397fb583 | ||
|
|
ae165349b9 | ||
|
|
1584ab8b11 | ||
|
|
5283e6de61 | ||
|
|
caa66d6715 | ||
|
|
f77d9b3509 | ||
|
|
afc1e034e0 | ||
|
|
67c36aab29 | ||
|
|
3e837bf64c | ||
|
|
c2af29f23c | ||
|
|
71d43eb101 | ||
|
|
57c41a7db2 | ||
|
|
91d512498d | ||
|
|
ec59133f96 | ||
|
|
8fc733ffd1 | ||
|
|
6deaa8b36e | ||
|
|
e187a3159c | ||
|
|
0d80a43055 | ||
|
|
9bad003301 | ||
|
|
a5a1edda2d | ||
|
|
6a5ffa0b16 | ||
|
|
531ea7fa0c | ||
|
|
f23e44503c | ||
|
|
3f0e284cee | ||
|
|
6634d94ff4 | ||
|
|
bf3ecfcb55 | ||
|
|
6a83d74eb7 | ||
|
|
a13486faef | ||
|
|
a828f49012 | ||
|
|
2ac3730f87 | ||
|
|
b897a11158 | ||
|
|
62a57fa61d | ||
|
|
0142050d6a | ||
|
|
9cfad308b0 | ||
|
|
28a8ee945c | ||
|
|
2154faec2c | ||
|
|
577b3f3f30 | ||
|
|
99c9cc3de6 | ||
|
|
216d99c05d | ||
|
|
8101c02ca8 |
8
.github/workflows/gomod2nix.yml
vendored
8
.github/workflows/gomod2nix.yml
vendored
@@ -1,6 +1,8 @@
|
||||
name: 自动更新 nix 依赖
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
@@ -23,6 +25,7 @@ jobs:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
ref: master
|
||||
fetch-depth: 0
|
||||
|
||||
- name: gomod2nix update
|
||||
@@ -35,11 +38,12 @@ jobs:
|
||||
git config --local user.name 'github-actions[bot]'
|
||||
git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
||||
git add --all
|
||||
git commit -m "chore: bump deps"
|
||||
git commit -m "chore(nix): bump deps"
|
||||
- name: Create Pull Request
|
||||
if: ${{ !github.head_ref }}
|
||||
continue-on-error: true
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
delete-branch: true
|
||||
branch-suffix: short-commit-hash
|
||||
title: "chore(nix): bump deps"
|
||||
|
||||
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -6,7 +6,7 @@ env:
|
||||
BINARY_PREFIX: "zbp_"
|
||||
BINARY_SUFFIX: ""
|
||||
PR_PROMPT: "::warning:: Build artifact will not be uploaded due to the workflow is trigged by pull request."
|
||||
LD_FLAGS: "-w -s -checklinkname=0"
|
||||
LD_FLAGS: "-w -s"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
17
.github/workflows/push.yml
vendored
17
.github/workflows/push.yml
vendored
@@ -1,5 +1,8 @@
|
||||
name: PushLint
|
||||
on: [ push ]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
@@ -8,17 +11,19 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: '1.24'
|
||||
go-version: '1.25'
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
ref: master
|
||||
fetch-depth: 0
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Tidy Modules
|
||||
- name: Prepare Necessary Runtime Files
|
||||
run: |
|
||||
go mod tidy
|
||||
go generate main.go
|
||||
go mod tidy
|
||||
|
||||
- name: Run Lint
|
||||
uses: golangci/golangci-lint-action@master
|
||||
@@ -37,4 +42,6 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
if: ${{ !github.head_ref }}
|
||||
continue-on-error: true
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
title: "chore(lint): 改进代码样式"
|
||||
|
||||
@@ -57,6 +57,8 @@ run:
|
||||
issues-exit-code: 1
|
||||
tests: false
|
||||
go: '1.24'
|
||||
skip-dirs:
|
||||
- data
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
|
||||
@@ -26,7 +26,7 @@ builds:
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w -checklinkname=0
|
||||
- -s -w
|
||||
- id: win
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
@@ -39,7 +39,7 @@ builds:
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w -checklinkname=0
|
||||
- -s -w
|
||||
|
||||
checksum:
|
||||
name_template: "zbp_checksums.txt"
|
||||
|
||||
49
README.md
49
README.md
@@ -917,6 +917,15 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 疯狂星期四
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>大模型聊天和群聊总结</summary>
|
||||
|
||||
`_ "github.com/FloatTech/ZeroBot-Plugin/plugin/llm"`
|
||||
|
||||
- [x] 群聊总结 [消息数目]|群聊总结 1000
|
||||
- [x] /gpt [内容](使用大模型聊天)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>kokomi原神面板</summary>
|
||||
@@ -1514,6 +1523,16 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- 注:由于需要科学,默认注释。
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>小红书文案</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/xhstext"`
|
||||
|
||||
- [x] 捧场
|
||||
|
||||
- [x] 有梗
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>游戏王白鸽API卡查</summary>
|
||||
@@ -1594,9 +1613,9 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
### *低优先级*
|
||||
|
||||
<details>
|
||||
<summary>OpenAI聊天</summary>
|
||||
<summary>大模型聊天和Agent配置</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aichat"`
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aichatcfg"`
|
||||
|
||||
- [x] 设置AI聊天触发概率10
|
||||
- [x] 设置AI聊天温度80
|
||||
@@ -1614,10 +1633,22 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
- [x] 设置AI聊天最大长度4096
|
||||
- [x] 设置AI聊天TopP 0.9
|
||||
- [x] 设置AI聊天(不)以AI语音输出
|
||||
- [x] 设置AI聊天Agent性格
|
||||
- [x] 查看AI聊天Agent性格
|
||||
- [x] 设置AI聊天Agent性别
|
||||
- [x] 查看AI聊天Agent性别
|
||||
- [x] 重置AI聊天Agent性格性别
|
||||
- [x] 重置AI聊天Agent
|
||||
- [x] 查看AI聊天配置
|
||||
- [x] 重置AI聊天
|
||||
- [x] 群聊总结 [消息数目]|群聊总结 1000
|
||||
- [x] /gpt [内容](使用大模型聊天)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>大模型聊天和Agent</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aichat"`
|
||||
|
||||
- [x] (随意聊天, 概率匹配)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -1693,15 +1724,15 @@ go generate main.go
|
||||
|
||||
```bash
|
||||
# 本机平台
|
||||
go build -ldflags "-s -w -checklinkname=0" -o zerobot -trimpath
|
||||
go build -ldflags "-s -w" -o zerobot -trimpath
|
||||
# x64 Linux 平台 如各种云服务器
|
||||
GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -checklinkname=0" -o zerobot -trimpath
|
||||
GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o zerobot -trimpath
|
||||
# x64 Windows 平台 如大多数家用电脑
|
||||
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -checklinkname=0" -o zerobot.exe -trimpath
|
||||
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o zerobot.exe -trimpath
|
||||
# armv6 Linux 平台 如树莓派 zero W
|
||||
GOOS=linux GOARCH=arm GOARM=6 CGO_ENABLED=0 go build -ldflags "-s -w -checklinkname=0" -o zerobot -trimpath
|
||||
GOOS=linux GOARCH=arm GOARM=6 CGO_ENABLED=0 go build -ldflags "-s -w" -o zerobot -trimpath
|
||||
# (由于引入了github.com/fumiama/sqlite3,本项不再可用)mips Linux 平台 如 路由器 wndr4300
|
||||
GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags "-s -w -checklinkname=0" -o zerobot -trimpath
|
||||
GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags "-s -w" -o zerobot -trimpath
|
||||
```
|
||||
|
||||
5. 运行 OneBot 框架,并同时运行本插件
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//go:build !windows
|
||||
|
||||
// Package console sets console's behavior on init
|
||||
package console
|
||||
package abineundo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,5 +1,4 @@
|
||||
// Package console sets console's behavior on init
|
||||
package console
|
||||
package abineundo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,7 +9,7 @@
|
||||
//
|
||||
// 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.
|
||||
// plugin priority and setup console properties.
|
||||
//
|
||||
// Typical usage:
|
||||
//
|
||||
|
||||
2
data
2
data
Submodule data updated: 1b0abcd3fe...74e3bf5dc8
@@ -18,9 +18,9 @@ buildGoApplication {
|
||||
version = "1.8.0";
|
||||
pwd = ./.;
|
||||
src = ./.;
|
||||
# spec go version manually bcs
|
||||
# https://github.com/nix-community/gomod2nix/blob/30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6/builder/default.nix#L130
|
||||
# do not work
|
||||
go = pkgs.go_1_20;
|
||||
go = pkgs.go_1_24;
|
||||
preBuild = ''
|
||||
go generate main.go
|
||||
'';
|
||||
modules = ./gomod2nix.toml;
|
||||
}
|
||||
|
||||
31
flake.lock
generated
31
flake.lock
generated
@@ -28,11 +28,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742209644,
|
||||
"narHash": "sha256-jMy1XqXqD0/tJprEbUmKilTkvbDY/C0ZGSsJJH4TNCE=",
|
||||
"lastModified": 1767019875,
|
||||
"narHash": "sha256-NodN+lhWTD59b44Q2bPjE1edINfjfRkQYdZsrxifCeU=",
|
||||
"owner": "nix-community",
|
||||
"repo": "gomod2nix",
|
||||
"rev": "8f3534eb8f6c5c3fce799376dc3b91bae6b11884",
|
||||
"rev": "49662a44272806ff785df2990a420edaaca15db4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -43,11 +43,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1745391562,
|
||||
"narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=",
|
||||
"lastModified": 1769461804,
|
||||
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7",
|
||||
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -57,28 +57,11 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-with-go_1_20": {
|
||||
"locked": {
|
||||
"lastModified": 1710843028,
|
||||
"narHash": "sha256-CMbK45c4nSkGvayiEHFkGFH+doGPbgo3AWfecd2t1Fk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "33c51330782cb486764eb598d5907b43dc87b4c2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "33c51330782cb486764eb598d5907b43dc87b4c2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"gomod2nix": "gomod2nix",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-with-go_1_20": "nixpkgs-with-go_1_20"
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
|
||||
109
flake.nix
109
flake.nix
@@ -1,7 +1,6 @@
|
||||
{
|
||||
description = "基于 ZeroBot 的 OneBot 插件";
|
||||
|
||||
inputs.nixpkgs-with-go_1_20.url = "github:NixOS/nixpkgs/33c51330782cb486764eb598d5907b43dc87b4c2";
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
inputs.gomod2nix.url = "github:nix-community/gomod2nix";
|
||||
@@ -11,53 +10,85 @@
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
nixpkgs-with-go_1_20,
|
||||
flake-utils,
|
||||
gomod2nix,
|
||||
...
|
||||
} @ inputs: let
|
||||
allSystems = flake-utils.lib.allSystems;
|
||||
in (
|
||||
flake-utils.lib.eachSystem allSystems
|
||||
(system: let
|
||||
old-nixpkgs = nixpkgs-with-go_1_20.legacyPackages.${system};
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
}: (flake-utils.lib.eachDefaultSystem (
|
||||
system: let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
|
||||
overlays = [
|
||||
(_: _: {
|
||||
go_1_20 = old-nixpkgs.go_1_20;
|
||||
})
|
||||
callPackage = pkgs.callPackage;
|
||||
# Simple test check added to nix flake check
|
||||
go-test = pkgs.stdenvNoCC.mkDerivation {
|
||||
name = "go-test";
|
||||
dontBuild = true;
|
||||
src = ./.;
|
||||
doCheck = true;
|
||||
nativeBuildInputs = with pkgs; [
|
||||
go
|
||||
writableTmpDirAsHomeHook
|
||||
];
|
||||
checkPhase = ''
|
||||
go test -v ./...
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir "$out"
|
||||
'';
|
||||
};
|
||||
|
||||
# The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
|
||||
# This has no effect on other platforms.
|
||||
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;
|
||||
in {
|
||||
# doCheck will fail at write files
|
||||
packages = rec {
|
||||
ZeroBot-Plugin = (callPackage ./. (inputs
|
||||
// {
|
||||
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
|
||||
}))
|
||||
.overrideAttrs (_: {doCheck = false;});
|
||||
|
||||
default = ZeroBot-Plugin;
|
||||
|
||||
docker_builder = pkgs.dockerTools.buildLayeredImage {
|
||||
name = "ZeroBot-Plugin";
|
||||
tag = "latest";
|
||||
contents = [
|
||||
self.packages.${system}.ZeroBot-Plugin
|
||||
pkgs.cacert
|
||||
];
|
||||
# Simple lint check added to nix flake check
|
||||
go-lint = pkgs.stdenvNoCC.mkDerivation {
|
||||
name = "go-lint";
|
||||
dontBuild = true;
|
||||
src = ./.;
|
||||
doCheck = true;
|
||||
nativeBuildInputs = with pkgs; [
|
||||
golangci-lint
|
||||
go
|
||||
writableTmpDirAsHomeHook
|
||||
];
|
||||
checkPhase = ''
|
||||
golangci-lint run
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir "$out"
|
||||
'';
|
||||
};
|
||||
# doCheck will fail at download files
|
||||
ZeroBot-Plugin = (callPackage ./. {
|
||||
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
|
||||
}).overrideAttrs (_: {doCheck = false;});
|
||||
# Build container layered image, useful overtime to save storage on duplicated layers
|
||||
containerImage = pkgs.dockerTools.buildLayeredImage {
|
||||
name = "ZeroBot-Plugin";
|
||||
tag = "latest";
|
||||
created = "now";
|
||||
contents = [
|
||||
pkgs.cacert
|
||||
pkgs.openssl
|
||||
];
|
||||
config = {
|
||||
Cmd = ["${ZeroBot-Plugin}/bin/ZeroBot-Plugin"];
|
||||
};
|
||||
};
|
||||
in {
|
||||
inherit containerImage;
|
||||
checks = {
|
||||
inherit go-test go-lint;
|
||||
};
|
||||
packages.default = ZeroBot-Plugin;
|
||||
devShells.default = callPackage ./shell.nix {
|
||||
inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;
|
||||
};
|
||||
# Custom application to build and load container image into the docker daemon
|
||||
# For now docker is a requirement
|
||||
apps.build-and-load = {
|
||||
type = "app";
|
||||
program = "${pkgs.writeShellScriptBin "build-and-load" ''
|
||||
nix build .#containerImage.${system}
|
||||
docker load < result
|
||||
echo "Container image loaded"
|
||||
''}/bin/build-and-load";
|
||||
};
|
||||
formatter = pkgs.alejandra;
|
||||
})
|
||||
);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
64
go.mod
64
go.mod
@@ -4,35 +4,37 @@ go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/Baidu-AIP/golang-sdk v1.1.1
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20250926171956-ba37dfebfc4a
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20251028071248-0c948e3db65c
|
||||
github.com/FloatTech/floatbox v0.0.0-20251002074805-f95cbc7edb31
|
||||
github.com/FloatTech/gg v1.1.3
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef
|
||||
github.com/FloatTech/rendercard v0.2.0
|
||||
github.com/FloatTech/sqlite v1.7.2
|
||||
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d
|
||||
github.com/FloatTech/zbpctrl v1.7.0
|
||||
github.com/FloatTech/zbputils v1.7.2-0.20251002080916-b554b7039913
|
||||
github.com/FloatTech/zbpctrl v1.7.1
|
||||
github.com/FloatTech/zbputils v1.7.2-0.20260131170726-494cb1776a47
|
||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
|
||||
github.com/RomiChan/websocket v1.4.3-0.20251002072000-d3eb41798438
|
||||
github.com/Tnze/go-mc v1.20.2
|
||||
github.com/antchfx/htmlquery v1.3.4
|
||||
github.com/corona10/goimagehash v1.1.0
|
||||
github.com/antchfx/htmlquery v1.3.5
|
||||
github.com/corona10/goimagehash v1.1.1-0.20240121134706-d8115886f360
|
||||
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/fumiama/ahsai v0.1.1
|
||||
github.com/fumiama/cron v1.3.0
|
||||
github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa
|
||||
github.com/fumiama/go-base16384 v1.7.0
|
||||
github.com/fumiama/go-onebot-agent v0.0.0-20250926145606-37ebfa6131c8
|
||||
github.com/fumiama/deepinfra v0.0.0-20251221163610-e98ee3ba437a
|
||||
github.com/fumiama/go-base16384 v1.7.1
|
||||
github.com/fumiama/go-onebot-agent v0.0.0-20260128132028-05e6b4809f0a
|
||||
github.com/fumiama/go-registry v0.2.7
|
||||
github.com/fumiama/gotracemoe v0.0.3
|
||||
github.com/fumiama/imgsz v0.0.4
|
||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565
|
||||
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4
|
||||
github.com/fumiama/terasu v0.0.0-20251006080703-541b84ca4a5f
|
||||
github.com/fumiama/terasu v1.0.2
|
||||
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/guohuiyuan/music-lib v1.0.2-0.20260121020416-53f6cb24629d
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/jozsefsallai/gophersauce v1.0.1
|
||||
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5
|
||||
@@ -42,15 +44,15 @@ require (
|
||||
github.com/mroth/weightedrand v1.0.0
|
||||
github.com/notnil/chess v1.10.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/shirou/gopsutil/v4 v4.25.12
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.2
|
||||
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20251002074418-56567b7fc282
|
||||
gitlab.com/gomidi/midi/v2 v2.3.16
|
||||
golang.org/x/image v0.31.0
|
||||
golang.org/x/sys v0.36.0
|
||||
golang.org/x/text v0.29.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.8.3-0.20260117102541-393033a35adb
|
||||
gitlab.com/gomidi/midi/v2 v2.3.18
|
||||
golang.org/x/image v0.34.0
|
||||
golang.org/x/sys v0.39.0
|
||||
golang.org/x/text v0.32.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -58,16 +60,15 @@ require (
|
||||
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
|
||||
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca // indirect
|
||||
github.com/andybalholm/cascadia v1.3.1 // 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/ebitengine/oto/v3 v3.3.2 // indirect
|
||||
github.com/ebitengine/purego v0.8.0 // indirect
|
||||
github.com/ebitengine/purego v0.9.1 // indirect
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
||||
github.com/fumiama/go-simple-protobuf v0.2.0 // indirect
|
||||
github.com/fumiama/gofastTEA v0.1.3 // indirect
|
||||
github.com/fumiama/imgsz v0.0.4 // indirect
|
||||
github.com/fumiama/orbyte v0.0.0-20251002065953-3bb358367eb5 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/gopxl/beep/v2 v2.1.1 // indirect
|
||||
@@ -82,25 +83,24 @@ require (
|
||||
github.com/mmcdole/goxpp v1.1.1-0.20240225020742-a0c311522b23 // 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 v0.1.9 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pkumza/numcn v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/tetratelabs/wazero v1.5.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/tidwall/match v1.2.0 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.61.0 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/sqlite v1.33.1 // indirect
|
||||
modernc.org/libc v1.67.1 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
modernc.org/sqlite v1.41.0 // indirect
|
||||
)
|
||||
|
||||
replace modernc.org/sqlite => github.com/fumiama/sqlite3 v1.29.10-simp
|
||||
|
||||
138
go.sum
138
go.sum
@@ -1,7 +1,7 @@
|
||||
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/FloatTech/AnimeAPI v1.7.1-0.20250926171956-ba37dfebfc4a h1:D/+ni0hzmfC+5TVQyGuq/AReGrSNKWTSMqU+lNG60rc=
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20250926171956-ba37dfebfc4a/go.mod h1:cuDd67B23xmICSmFBhWzXN51blod2BlM1liN9Ux0pSc=
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20251028071248-0c948e3db65c h1:fmvlRUzwoK6KdoRSW+XeTQ9myKHimd0pV6GbmRJLNRo=
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20251028071248-0c948e3db65c/go.mod h1:cuDd67B23xmICSmFBhWzXN51blod2BlM1liN9Ux0pSc=
|
||||
github.com/FloatTech/floatbox v0.0.0-20251002074805-f95cbc7edb31 h1:2K+/M64ixD1Pg5hr00Nbxr7GoWQOgahvpmp1pAMnrYc=
|
||||
github.com/FloatTech/floatbox v0.0.0-20251002074805-f95cbc7edb31/go.mod h1:kf+Ywc2lk8PLdg3RX0vrUmFLPO6k+23MFmt4GviV8C0=
|
||||
github.com/FloatTech/gg v1.1.3 h1:+GlL02lTKsxJQr4WCuNwVxC1/eBZrCvypCIBtxuOFb4=
|
||||
@@ -14,10 +14,10 @@ github.com/FloatTech/sqlite v1.7.2 h1:b8COegNLSzofzOyARsVwSbz9OOzWEa8IElsTlx1TBL
|
||||
github.com/FloatTech/sqlite v1.7.2/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-20250224045156-012b1463287d/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||
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/zbputils v1.7.2-0.20251002080916-b554b7039913 h1:uGexKAPL26sAWGemyHbfkjYyzFItMsbI8EREBLSZ/sU=
|
||||
github.com/FloatTech/zbputils v1.7.2-0.20251002080916-b554b7039913/go.mod h1:mNvv0+wCou042n/3QkK23WmbayNctT5wgkKC3A6nbmM=
|
||||
github.com/FloatTech/zbpctrl v1.7.1 h1:0yPEmCForhyMbnhTckmjDUFFDZgQp1RjO2bVF4ZVqOs=
|
||||
github.com/FloatTech/zbpctrl v1.7.1/go.mod h1:xmM4dSwHA02Gei3ogCRiG+RTrw/7Z69PfrN5NYf8BPE=
|
||||
github.com/FloatTech/zbputils v1.7.2-0.20260131170726-494cb1776a47 h1:slMr6r4XDKnYCFmWhcHA02O3MTAUnU8p2gEe843JyQA=
|
||||
github.com/FloatTech/zbputils v1.7.2-0.20260131170726-494cb1776a47/go.mod h1:W2kaR/A5oUtEb7DnveXCc0T374VjI+f3KmOWH9FE5vU=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
|
||||
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
|
||||
@@ -34,12 +34,12 @@ github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca/go.mod h1:K08gAheRH3
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/antchfx/htmlquery v1.3.4 h1:Isd0srPkni2iNTWCwVj/72t7uCphFeor5Q8nCzj1jdQ=
|
||||
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/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
|
||||
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||
github.com/antchfx/htmlquery v1.3.5 h1:aYthDDClnG2a2xePf6tys/UyyM/kRcsFRm+ifhFKoU0=
|
||||
github.com/antchfx/htmlquery v1.3.5/go.mod h1:5oyIPIa3ovYGtLqMPNjBF2Uf25NPCKsMjCnQ8lvjaoA=
|
||||
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.1-0.20240121134706-d8115886f360 h1:SvD9vQN+3r0wskoSrQ7IOyDmOtRIXhT3rlnf819r/bY=
|
||||
github.com/corona10/goimagehash v1.1.1-0.20240121134706-d8115886f360/go.mod h1:PFDP0Q0oYvEuipJHMSbeK8tjbuRzkQqjPDYm3n71ITA=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -53,8 +53,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/ebitengine/oto/v3 v3.3.2 h1:VTWBsKX9eb+dXzaF4jEwQbs4yWIdXukJ0K40KgkpYlg=
|
||||
github.com/ebitengine/oto/v3 v3.3.2/go.mod h1:MZeb/lwoC4DCOdiTIxYezrURTw7EvK/yF863+tmBI+U=
|
||||
github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE=
|
||||
github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
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/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
||||
@@ -63,12 +63,12 @@ github.com/fumiama/ahsai v0.1.1 h1:/t5tdKRim0TK6YwgNFQfqtDOW7Y2tFBsmdUWt3JK+C0=
|
||||
github.com/fumiama/ahsai v0.1.1/go.mod h1:rBhHLgN2bygcqLpBi+XQa8B8Afn4UkPHQ5vvQibdbDQ=
|
||||
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/deepinfra v0.0.0-20250924162107-cf156d49a0fa h1:UMMNejpPp8dn92GPaVSZ2XKNSgp7+CVneOkZfExUilk=
|
||||
github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa/go.mod h1:uqsWK/GM9OvKV0pXZOQB63rWugBbiXInY8E1JoRKhkg=
|
||||
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-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/deepinfra v0.0.0-20251221163610-e98ee3ba437a h1:a0+2vaXajfxsNcIaYG7A/cAb2e4+M3s5J6oyIiPsL3c=
|
||||
github.com/fumiama/deepinfra v0.0.0-20251221163610-e98ee3ba437a/go.mod h1:uqsWK/GM9OvKV0pXZOQB63rWugBbiXInY8E1JoRKhkg=
|
||||
github.com/fumiama/go-base16384 v1.7.1 h1:1P1x6FWRvd7PtbH4idDAGWAjKKcVxggxlROYKRXbw58=
|
||||
github.com/fumiama/go-base16384 v1.7.1/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||
github.com/fumiama/go-onebot-agent v0.0.0-20260128132028-05e6b4809f0a h1:8GYo5nctK2si5WDNX0WmZTxY7TWXRjAOBu5pjK7GDW0=
|
||||
github.com/fumiama/go-onebot-agent v0.0.0-20260128132028-05e6b4809f0a/go.mod h1:rTrS23rvTYuZcSngENJTvcBFTz1nGsImSv+bW7yfhqs=
|
||||
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-simple-protobuf v0.2.0 h1:ACyN1MAlu7pDR3EszWgzUeNP+IRsSHwH6V9JCJA5R5o=
|
||||
@@ -89,13 +89,13 @@ github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4 h1:zN9e09TYKXI1mNku
|
||||
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/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA=
|
||||
github.com/fumiama/terasu v0.0.0-20251006080703-541b84ca4a5f h1:skKZClM6lBzK8VyiFX/a2+nMs4W+pfGOXIgt2LZBVMM=
|
||||
github.com/fumiama/terasu v0.0.0-20251006080703-541b84ca4a5f/go.mod h1:5wnbYtJ8Rv0GG7EIiYSqniKnGDXDvkKqCcZQehh3UCQ=
|
||||
github.com/fumiama/terasu v1.0.2 h1:Dxj2vPIgLHyeMlBd61xYHx5Jg8v7k24yg7taNLlK8/8=
|
||||
github.com/fumiama/terasu v1.0.2/go.mod h1:1eHzpL/GJVcOnqEkh1vUbKu2zo6gojSuueUNJ9yHJE0=
|
||||
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/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
@@ -109,13 +109,16 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw
|
||||
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/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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.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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopxl/beep/v2 v2.1.1 h1:6FYIYMm2qPAdWkjX+7xwKrViS1x0Po5kDMdRkq8NVbU=
|
||||
github.com/gopxl/beep/v2 v2.1.1/go.mod h1:ZAm9TGQ9lvpoiFLd4zf5B1IuyxZhgRACMId1XJbaW0E=
|
||||
github.com/guohuiyuan/music-lib v1.0.2-0.20260121020416-53f6cb24629d h1:6Cw52c4JaYvq55yAa9ZgUQeBL6b3ZWErQqkbeMZiAYw=
|
||||
github.com/guohuiyuan/music-lib v1.0.2-0.20260121020416-53f6cb24629d/go.mod h1:D/6kQDwhQFDNZEMjN8y760DQSVYpOGlQXrYzhKz0rCQ=
|
||||
github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ=
|
||||
github.com/jfreymuth/oggvorbis v1.0.5/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
||||
github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE=
|
||||
@@ -159,8 +162,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
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/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||
github.com/ncruces/go-strftime v1.0.0/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/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/notnil/chess v1.10.0 h1:RR3MgS9G6zZmJ+VPTJolyxdaIgxoUPyUUY+2iaw35G0=
|
||||
@@ -175,21 +178,16 @@ github.com/pkumza/numcn v1.0.0 h1:ZT5cf9IJkUZgRgEtCiNNykk0RwsrKXSTsvDHOwUTzgE=
|
||||
github.com/pkumza/numcn v1.0.0/go.mod h1:QSeH+al9dWCd8di5HZM/ZqHqhZmUKfph572e9Ev/ETc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/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/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
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/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY=
|
||||
github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
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.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
@@ -197,23 +195,25 @@ github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08q
|
||||
github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
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/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
|
||||
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
||||
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
||||
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
||||
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
|
||||
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/wdvxdr1123/ZeroBot v1.8.2-0.20251002074418-56567b7fc282 h1:YctW/t88sQ0H8cJ69PWULU6xWfh8kNsX/XgCpW2OPHw=
|
||||
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20251002074418-56567b7fc282/go.mod h1:trueIIVRywKJa3ov4QphzVvzYzgCNrlXdf9JvPJOFW8=
|
||||
github.com/wdvxdr1123/ZeroBot v1.8.3-0.20260117102541-393033a35adb h1:pwmyrnnMzb0WygAwUgXoZckzJkusK4WSaXxXqsIJYmU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.8.3-0.20260117102541-393033a35adb/go.mod h1:kCLja2sXXgbBTsEOyBNCuT4z9tI+URQ2y0q/GGXprzU=
|
||||
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/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
gitlab.com/gomidi/midi/v2 v2.3.16 h1:yufWSENyjnJ4LFQa9BerzUm4E4aLfTyzw5nmnCteO0c=
|
||||
gitlab.com/gomidi/midi/v2 v2.3.16/go.mod h1:jDpP4O4skYi+7iVwt6Zyp18bd2M4hkjtMuw2cmgKgfw=
|
||||
gitlab.com/gomidi/midi/v2 v2.3.18 h1:sj2fOhtvOe+zI8YJe8qTxLw5zv0ntULLUDwcFOaZQbI=
|
||||
gitlab.com/gomidi/midi/v2 v2.3.18/go.mod h1:jDpP4O4skYi+7iVwt6Zyp18bd2M4hkjtMuw2cmgKgfw=
|
||||
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-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@@ -222,19 +222,19 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
||||
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.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
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.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA=
|
||||
golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA=
|
||||
golang.org/x/image v0.34.0 h1:33gCkyw9hmwbZJeZkct8XyR11yH889EQt/QH4VmXMn8=
|
||||
golang.org/x/image v0.34.0/go.mod h1:2RNFBZRB+vnwwFil8GkMdRvrJOFd1AzdZI6vOY+eJVU=
|
||||
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.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.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -249,8 +249,8 @@ 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.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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=
|
||||
@@ -258,8 +258,8 @@ 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.7.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.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -269,18 +269,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-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-20220722155257-8c9f86f7a55f/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.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.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.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -301,16 +299,16 @@ 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.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.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
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.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.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.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
@@ -326,10 +324,10 @@ 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/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
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/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||
|
||||
120
gomod2nix.toml
120
gomod2nix.toml
@@ -5,8 +5,8 @@ schema = 3
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-hKshA0K92bKuK92mmtM0osVmqLJcSbeobeWSDpQoRCo="
|
||||
[mod."github.com/FloatTech/AnimeAPI"]
|
||||
version = "v1.7.1-0.20250926171956-ba37dfebfc4a"
|
||||
hash = "sha256-wtr9hgHSPsD5NqSmI3Lo8RVWE+cNMIUGo2bcsKTN8Gg="
|
||||
version = "v1.7.1-0.20251028071248-0c948e3db65c"
|
||||
hash = "sha256-EkC8QYgmXElKGM8GzcQ4r/c+lM1ysJOccfoeqhMtAvs="
|
||||
[mod."github.com/FloatTech/floatbox"]
|
||||
version = "v0.0.0-20251002074805-f95cbc7edb31"
|
||||
hash = "sha256-c50unGhF0JVPHN8geZM/YYQKgGqJgCtVksh4Ij1Pg+4="
|
||||
@@ -26,11 +26,11 @@ schema = 3
|
||||
version = "v0.0.0-20250224045156-012b1463287d"
|
||||
hash = "sha256-C5xBt0roPgahradCOTgkhL+j5bvoSXmGwdqcu0aSczc="
|
||||
[mod."github.com/FloatTech/zbpctrl"]
|
||||
version = "v1.7.0"
|
||||
hash = "sha256-HDDnE0oktWJH1tkxuQwUUbeJhmVwY5fyc/vR72D2mkU="
|
||||
version = "v1.7.1"
|
||||
hash = "sha256-wkeiaUTpPVbpH7fcXeoLtG+aGIMJbvoc/9sbi2IXK0I="
|
||||
[mod."github.com/FloatTech/zbputils"]
|
||||
version = "v1.7.2-0.20251002080916-b554b7039913"
|
||||
hash = "sha256-9z7c79uuFl2LKaCgW1gQN5lmMjgKIcKrakcBlb3zJ90="
|
||||
version = "v1.7.2-0.20260128132210-62a44be0a2b5"
|
||||
hash = "sha256-oEhCz8S/q9XyXt9kYMOSQiEc0LbV1IsKWgdiNmkKwxw="
|
||||
[mod."github.com/PuerkitoBio/goquery"]
|
||||
version = "v1.8.0"
|
||||
hash = "sha256-I3QaPWATvBOL/F26fIiYWKS13yBUYo+9o3tcsGIu8tY="
|
||||
@@ -53,14 +53,14 @@ schema = 3
|
||||
version = "v1.3.1"
|
||||
hash = "sha256-M0u22DXSeXUaYtl1KoW1qWL46niFpycFkraCEQ/luYA="
|
||||
[mod."github.com/antchfx/htmlquery"]
|
||||
version = "v1.3.4"
|
||||
hash = "sha256-nrtIgRgdOvo0iIQyrhHOFKOmoT8e2gduUsct3f5zDNA="
|
||||
version = "v1.3.5"
|
||||
hash = "sha256-AyfSTQY2eiNPhTS/FVgaBlSzPOObSaluhSee8Gvc8ho="
|
||||
[mod."github.com/antchfx/xpath"]
|
||||
version = "v1.3.3"
|
||||
hash = "sha256-Ent9bgBTjKS8/61LKrIu/JcBI/Qsv6EEIojwsMjCgdY="
|
||||
version = "v1.3.5"
|
||||
hash = "sha256-AVM0rR81hgVAI0QVzlz4WijFUjByf6Zew3ZwuikKw2Q="
|
||||
[mod."github.com/corona10/goimagehash"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-HyS8nc7kUNnDaVBDzJ9Ym4pRs83YB4M2vHSRwfm6mr4="
|
||||
version = "v1.1.1-0.20240121134706-d8115886f360"
|
||||
hash = "sha256-/corDVYILmy/DMWtgM1D1MK6I7pejA5JNfaxeojwkkA="
|
||||
[mod."github.com/davidscholberg/go-durationfmt"]
|
||||
version = "v0.0.0-20170122144659-64843a2083d3"
|
||||
hash = "sha256-0rdbpBf3AAjMpxvVEGFb2ImgB2i7vdEhIwCyqJs1iHE="
|
||||
@@ -74,8 +74,8 @@ schema = 3
|
||||
version = "v3.3.2"
|
||||
hash = "sha256-TPu3qvJscLZbjwIqC3jj0T1md0mX3lQxcC8GAk7kB1w="
|
||||
[mod."github.com/ebitengine/purego"]
|
||||
version = "v0.8.0"
|
||||
hash = "sha256-fM+5HYIKDPLDrvv2f9/WQG0F20+o0+At0AbPQtF2JP0="
|
||||
version = "v0.9.1"
|
||||
hash = "sha256-iVfU8vaJ7IPa92dUeHeuW+yKvUbe59F/eV7GlDRIAcE="
|
||||
[mod."github.com/ericpauley/go-quantize"]
|
||||
version = "v0.0.0-20200331213906-ae555eb2afa4"
|
||||
hash = "sha256-sMN6D7IlDpDqUWM8ppoE5Sdb7DvLAJaN6qAucBWJ3rs="
|
||||
@@ -86,14 +86,14 @@ schema = 3
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-/sN7X8dKXQgv8J+EDzVUB+o+AY9gBC8e1C6sYhaTy1k="
|
||||
[mod."github.com/fumiama/deepinfra"]
|
||||
version = "v0.0.0-20250924162107-cf156d49a0fa"
|
||||
hash = "sha256-D0lgA7jBDLE8v9ePDiWwH439eB5+cDlj2fKRAc0wUms="
|
||||
version = "v0.0.0-20251221163610-e98ee3ba437a"
|
||||
hash = "sha256-XubewUDOLaN7fgv9E8PAfP7DtADdLm+M2sgSn5OE6eQ="
|
||||
[mod."github.com/fumiama/go-base16384"]
|
||||
version = "v1.7.0"
|
||||
hash = "sha256-vTAsBBYe2ISzb2Nba5E96unodZSkhMcqo6hbwR01nz8="
|
||||
version = "v1.7.1"
|
||||
hash = "sha256-Fd1QaeYx+3q4C3XQXlPFnDmKPsoZH6837fN/7rn8i9s="
|
||||
[mod."github.com/fumiama/go-onebot-agent"]
|
||||
version = "v0.0.0-20250926145606-37ebfa6131c8"
|
||||
hash = "sha256-oq1SSyddsXhsFvSHFhqSEAF9SH03b2jI0KvGbsFPXYQ="
|
||||
version = "v0.0.0-20260128132028-05e6b4809f0a"
|
||||
hash = "sha256-ratY7o52v0KuxgZC4wqHNXdgGXzliEecs8egE3SBLeo="
|
||||
[mod."github.com/fumiama/go-registry"]
|
||||
version = "v0.2.7"
|
||||
hash = "sha256-Rjl+z0Hlp2LMi8+pnFe5HrxctyHMi7UPiK33g/OgLdA="
|
||||
@@ -119,14 +119,14 @@ schema = 3
|
||||
version = "v0.0.0-20241001074058-27c4fe5259a4"
|
||||
hash = "sha256-rsV3MKRCSOBMIgJXFCGbCHRY2aBAb32ftU49hT3GjqY="
|
||||
[mod."github.com/fumiama/terasu"]
|
||||
version = "v0.0.0-20251006080703-541b84ca4a5f"
|
||||
hash = "sha256-FQnOlahP7384Z2TFOCVWOjsWB/aqpbumPOwCo4TlI/k="
|
||||
version = "v1.0.2"
|
||||
hash = "sha256-tYHvvfJT1/R4koqGFPjdU211Dcez2XWuvpRke/tFfQ8="
|
||||
[mod."github.com/fumiama/unibase2n"]
|
||||
version = "v0.0.0-20240530074540-ec743fd5a6d6"
|
||||
hash = "sha256-I3xNzjrj5y0fy0dfa75V57GanfmHIHmubEn9/y0BBHw="
|
||||
[mod."github.com/gabriel-vasile/mimetype"]
|
||||
version = "v1.4.8"
|
||||
hash = "sha256-ElqfQtnoGHyVqtN0mJjeWakQ6N5x+nVaX3+uOV7Q5Xk="
|
||||
version = "v1.4.12"
|
||||
hash = "sha256-vY2g58yUrkT//8fttRKhS9rbg89YSae/BzOARS5uH30="
|
||||
[mod."github.com/go-ole/go-ole"]
|
||||
version = "v1.2.6"
|
||||
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
|
||||
@@ -142,6 +142,9 @@ schema = 3
|
||||
[mod."github.com/gopxl/beep/v2"]
|
||||
version = "v2.1.1"
|
||||
hash = "sha256-JLCUJCG+VvNlVF296JWIOUvvUFHlqEAJvZfw853qwwU="
|
||||
[mod."github.com/guohuiyuan/music-lib"]
|
||||
version = "v1.0.2-0.20260121020416-53f6cb24629d"
|
||||
hash = "sha256-juVJ/nh6zA5Gu5+dRzIx8tElXLscRQYwY9vLvVKh078="
|
||||
[mod."github.com/jfreymuth/oggvorbis"]
|
||||
version = "v1.0.5"
|
||||
hash = "sha256-jphTCaPr34ZT9Id4ZZ6zU9Vnxzy6cTjCwjpQ819eGV0="
|
||||
@@ -197,8 +200,8 @@ schema = 3
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-bP+yIaBUY5+oI455mNM8zh14z/SNPaQg44L3RJ0/v/c="
|
||||
[mod."github.com/ncruces/go-strftime"]
|
||||
version = "v0.1.9"
|
||||
hash = "sha256-T0iw+UEckzueWHT88PkTnZZixyKCEa+DTLzIiiohuWY="
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-GYIwYDONuv/yTE0AEugCHQbtV3oiBaco93xUNYFcVBQ="
|
||||
[mod."github.com/nfnt/resize"]
|
||||
version = "v0.0.0-20180221191011-83c6a9932646"
|
||||
hash = "sha256-yvPV+HlDOyJsiwAcVHQkmtw8DHSXyw+cXHkigXm8rAA="
|
||||
@@ -215,20 +218,17 @@ schema = 3
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-cPxqj5tb10+MurN1Lehkk/v8KjaxXpL08+pVgL4x4Hg="
|
||||
[mod."github.com/power-devops/perfstat"]
|
||||
version = "v0.0.0-20210106213030-5aafc221ea8c"
|
||||
hash = "sha256-ywykDYuqcMt0TvZOz1l9Z6Z2JMTYQw8cP2fT8AtpmX4="
|
||||
version = "v0.0.0-20240221224432-82ca36839d55"
|
||||
hash = "sha256-ujzuJ1ttQgjHQJEij4O/2+I8DZaUVZQCQgA4ysfqulI="
|
||||
[mod."github.com/remyoudompheng/bigfft"]
|
||||
version = "v0.0.0-20230129092748-24d4a6f8daec"
|
||||
hash = "sha256-vYmpyCE37eBYP/navhaLV4oX4/nu0Z/StAocLIFqrmM="
|
||||
[mod."github.com/shirou/gopsutil/v3"]
|
||||
version = "v3.24.5"
|
||||
hash = "sha256-tc+t1u7gf5A+Bd956dYeM8pGbxs9ezQHqKAKfLQLpuQ="
|
||||
[mod."github.com/shoenig/go-m1cpu"]
|
||||
version = "v0.1.6"
|
||||
hash = "sha256-hT+JP30BBllsXosK/lo89HV/uxxPLsUyO3dRaDiLnCg="
|
||||
[mod."github.com/shirou/gopsutil/v4"]
|
||||
version = "v4.25.12"
|
||||
hash = "sha256-gzk9GW4+tXUWmxAVD3by/k4D/+l++TvajRVTkQJvwmM="
|
||||
[mod."github.com/sirupsen/logrus"]
|
||||
version = "v1.9.3"
|
||||
hash = "sha256-EnxsWdEUPYid+aZ9H4/iMTs1XMvCLbXZRDyvj89Ebms="
|
||||
version = "v1.9.4"
|
||||
hash = "sha256-ltRvmtM3XTCAFwY0IesfRqYIivyXPPuvkFjL4ARh1wg="
|
||||
[mod."github.com/tetratelabs/wazero"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-fGdJM4LJrZA9jxHuYVo4EUQ3I1k0IVG3QQCBCgZkeZI="
|
||||
@@ -236,41 +236,41 @@ schema = 3
|
||||
version = "v1.18.0"
|
||||
hash = "sha256-CO6hqDu8Y58Po6A01e5iTpwiUBQ5khUZsw7czaJHw0I="
|
||||
[mod."github.com/tidwall/match"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-M2klhPId3Q3T3VGkSbOkYl/2nLHnsG+yMbXkPkyrRdg="
|
||||
[mod."github.com/tidwall/pretty"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-esRQGsn2Ee/CiySlwyuOICSLdqUkH4P7u8qXszos8Yc="
|
||||
hash = "sha256-O2wTU0SmNIEEOxfncl2BW2czgWeIW5vqR6+A7dtNtXI="
|
||||
[mod."github.com/tidwall/pretty"]
|
||||
version = "v1.2.1"
|
||||
hash = "sha256-S0uTDDGD8qr415Ut7QinyXljCp0TkL4zOIrlJ+9OMl8="
|
||||
[mod."github.com/tklauser/go-sysconf"]
|
||||
version = "v0.3.12"
|
||||
hash = "sha256-91VBZNb3L2TZkEETF1AE4wnraLoGxKeofUbC5ZiWVHk="
|
||||
version = "v0.3.16"
|
||||
hash = "sha256-hNVbsk0G+M9bLtHNywPD0nCW0z/9pM4jQV53nnDo/MY="
|
||||
[mod."github.com/tklauser/numcpus"]
|
||||
version = "v0.6.1"
|
||||
hash = "sha256-8eFcw4YI0w6+GPhU5xMMQjiio94q/O5PpNO3QsvXve0="
|
||||
version = "v0.11.0"
|
||||
hash = "sha256-ObydGqAvRiHwVfO2ytmL28pRHyuCWYWwjH4hWdgI/Vs="
|
||||
[mod."github.com/wcharczuk/go-chart/v2"]
|
||||
version = "v2.1.2"
|
||||
hash = "sha256-GXWWea/u6BezTsPPrWhTYiTetPP/YW6P+Sj4YdocPaM="
|
||||
[mod."github.com/wdvxdr1123/ZeroBot"]
|
||||
version = "v1.8.2-0.20251002074418-56567b7fc282"
|
||||
hash = "sha256-KaoqopWcXqiRhGYNaA3UqYtXf27yMuBEj/bvqOWxaC4="
|
||||
version = "v1.8.3-0.20260117102541-393033a35adb"
|
||||
hash = "sha256-Yz2OTU05kDZOHX8J04jX5Jg5ya9rwqsH0TySSBhMOp0="
|
||||
[mod."github.com/yusufpapurcu/wmi"]
|
||||
version = "v1.2.4"
|
||||
hash = "sha256-N+YDBjOW59YOsZ2lRBVtFsEEi48KhNQRb63/0ZSU3bA="
|
||||
[mod."gitlab.com/gomidi/midi/v2"]
|
||||
version = "v2.3.16"
|
||||
hash = "sha256-o+6UtQH+TRSQlcX8J53esAA/b2c9e7BY7gcO5iSeOy0="
|
||||
version = "v2.3.18"
|
||||
hash = "sha256-lkU9M+h56+Ai/bpQDST3Su71dhjp1Vk2S7/okrELo7s="
|
||||
[mod."golang.org/x/image"]
|
||||
version = "v0.31.0"
|
||||
hash = "sha256-ZFTlu9+4QToPPLA8C5UcG2eq/lQylq81RoG/WtYo9rg="
|
||||
version = "v0.34.0"
|
||||
hash = "sha256-7V1bDhd++dCw11DCXOAUb5f1Hj51EfS0DZ03pq0V/p0="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.43.0"
|
||||
hash = "sha256-bf3iQFrsC8BoarVaS0uSspEFAcr1zHp1uziTtBpwV34="
|
||||
version = "v0.48.0"
|
||||
hash = "sha256-oZpddsiJwWCH3Aipa+XXpy7G/xHY5fEagUSok7T0bXE="
|
||||
[mod."golang.org/x/sys"]
|
||||
version = "v0.36.0"
|
||||
hash = "sha256-9h4SHGnlJzmTENUp6226hC8fQ73QrQC3D85NNMxLuXg="
|
||||
version = "v0.39.0"
|
||||
hash = "sha256-dxTBu/JAWUkPbjFIXXRFdhQWyn+YyEpIC+tWqGo0Y6U="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.29.0"
|
||||
hash = "sha256-2cWBtJje+Yc+AnSgCANqBlIwnOMZEGkpQ2cFI45VfLI="
|
||||
version = "v0.32.0"
|
||||
hash = "sha256-9PXtWBKKY9rG4AgjSP4N+I1DhepXhy8SF/vWSIDIoWs="
|
||||
[mod."gopkg.in/yaml.v3"]
|
||||
version = "v3.0.1"
|
||||
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
||||
@@ -279,11 +279,11 @@ schema = 3
|
||||
hash = "sha256-SJYYRaiDUmIbqy9l/IgiT/4VkFsPYsaslqGEowut34w="
|
||||
replaced = "github.com/fumiama/libc"
|
||||
[mod."modernc.org/mathutil"]
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-lfuEiS1odd2TWrTylnaGihSJ9myqKs3FLdpvd7PqTnE="
|
||||
version = "v1.7.1"
|
||||
hash = "sha256-COZ5rF2GhQVR1r6a0DanJ8qwQ94JSKdQxTMWrDzE0Cc="
|
||||
[mod."modernc.org/memory"]
|
||||
version = "v1.8.0"
|
||||
hash = "sha256-ucvPr73zg8LjvU+bcoIPKTgwgcon3U9VhKrLEMH81xg="
|
||||
version = "v1.11.0"
|
||||
hash = "sha256-MkybF8vvrxXS5j7O8w3skwTo0aMo1yjWS0K440rYcHM="
|
||||
[mod."modernc.org/sqlite"]
|
||||
version = "v1.29.10-simp"
|
||||
hash = "sha256-HCUVN6gZDG0g2WIsQ4ksqE1+XR1IjxvnqEBEU2MO1eE="
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
package banner
|
||||
|
||||
// Version ...
|
||||
var Version = "v1.10.0"
|
||||
var Version = "v1.10.18"
|
||||
|
||||
// Copyright ...
|
||||
var Copyright = "© 2020 - 2025 FloatTech"
|
||||
var Copyright = "© 2020 - 2026 FloatTech"
|
||||
|
||||
// Banner ...
|
||||
var Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||
"* Version " + Version + " - 2025-09-30 23:45:28 +0800 CST\n" +
|
||||
"* Version " + Version + " - 2026-02-01 01:08:19 +0800 CST\n" +
|
||||
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||
|
||||
7
main.go
7
main.go
@@ -14,8 +14,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/abineundo" // 设置插件优先级
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/console" // 更改控制台属性
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/abineundo" // 设置插件优先级&更改控制台属性
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 打印 banner
|
||||
|
||||
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
|
||||
@@ -112,6 +111,7 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/kfccrazythursday" // 疯狂星期四
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/llm" // 大模型聊天和群聊总结
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolimi" // 桑帛云 API
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/magicprompt" // magicprompt吟唱提示
|
||||
@@ -154,6 +154,7 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife" // 抽老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordcount" // 聊天热词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/xhstext" // 小红书文案
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygocdb" // 游戏王白鸽API卡查
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygotrade" // 游戏王集换社卡价查询
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
||||
@@ -179,6 +180,8 @@ import (
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aichatcfg" // AI聊天配置
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aichat" // AI聊天
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse" // 骂人
|
||||
|
||||
@@ -1,302 +0,0 @@
|
||||
package aichat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/chat"
|
||||
"github.com/fumiama/deepinfra"
|
||||
"github.com/fumiama/deepinfra/model"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
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 {
|
||||
ModelName string
|
||||
ImageModelName string
|
||||
AgentModelName string
|
||||
Type ModelType
|
||||
ImageType ModelType
|
||||
AgentType ModelType
|
||||
MaxN uint
|
||||
TopP float32
|
||||
SystemP string
|
||||
API string
|
||||
ImageAPI string
|
||||
AgentAPI string
|
||||
Key ModelKey
|
||||
ImageKey ModelKey
|
||||
AgentKey ModelKey
|
||||
Separator string
|
||||
NoSystemP ModelBool
|
||||
}
|
||||
|
||||
func newconfig() config {
|
||||
return config{
|
||||
ModelName: model.ModelDeepDeek,
|
||||
SystemP: chat.SystemPrompt,
|
||||
API: deepinfra.OpenAIDeepInfra,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if !cfg.isvalid() {
|
||||
err := c.GetExtra(&cfg)
|
||||
if err != nil {
|
||||
logrus.Warnln("ERROR: get extra err:", err)
|
||||
}
|
||||
if !cfg.isvalid() {
|
||||
cfg = newconfig()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func newextrasetstr[T ~string](ptr *T) 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
|
||||
}
|
||||
*ptr = T(args)
|
||||
err := c.SetExtra(&cfg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功"))
|
||||
}
|
||||
}
|
||||
|
||||
func newextrasetbool[T ~bool](ptr *T) func(ctx *zero.Ctx) {
|
||||
return func(ctx *zero.Ctx) {
|
||||
args := ctx.State["regex_matched"].([]string)
|
||||
isno := args[1] == "不"
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||
return
|
||||
}
|
||||
*ptr = T(isno)
|
||||
err := c.SetExtra(&cfg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功"))
|
||||
}
|
||||
}
|
||||
|
||||
func newextrasetuint(ptr *uint) 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
|
||||
}
|
||||
n, err := strconv.ParseUint(args, 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: parse args err: ", err))
|
||||
return
|
||||
}
|
||||
*ptr = uint(n)
|
||||
err = c.SetExtra(&cfg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功"))
|
||||
}
|
||||
}
|
||||
|
||||
func newextrasetfloat32(ptr *float32) 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
|
||||
}
|
||||
n, err := strconv.ParseFloat(args, 32)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: parse args err: ", err))
|
||||
return
|
||||
}
|
||||
*ptr = float32(n)
|
||||
err = c.SetExtra(&cfg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||
return
|
||||
}
|
||||
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,18 +1,15 @@
|
||||
// Package aichat OpenAI聊天和群聊总结
|
||||
// Package aichat 大模型聊天和Agent
|
||||
package aichat
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/RomiChan/syncx"
|
||||
"github.com/fumiama/deepinfra"
|
||||
"github.com/fumiama/deepinfra/model"
|
||||
goba "github.com/fumiama/go-onebot-agent"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||
@@ -23,7 +20,6 @@ import (
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/chat"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -31,27 +27,8 @@ var (
|
||||
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Extra: control.ExtraFromString("aichat"),
|
||||
Brief: "OpenAI聊天",
|
||||
Help: "- 设置AI聊天触发概率10\n" +
|
||||
"- 设置AI聊天温度80\n" +
|
||||
"- 设置AI聊天(识图|Agent)接口类型[OpenAI|OLLaMA|GenAI]\n" +
|
||||
"- 设置AI聊天(不)使用Agent模式\n" +
|
||||
"- 设置AI聊天(不)支持系统提示词\n" +
|
||||
"- 设置AI聊天(识图|Agent)接口地址https://api.siliconflow.cn/v1/chat/completions\n" +
|
||||
"- 设置AI聊天(识图|Agent)密钥xxx\n" +
|
||||
"- 设置AI聊天(识图|Agent)模型名Qwen/Qwen3-8B\n" +
|
||||
"- 查看AI聊天系统提示词\n" +
|
||||
"- 重置AI聊天系统提示词\n" +
|
||||
"- 设置AI聊天系统提示词xxx\n" +
|
||||
"- 设置AI聊天分隔符</think>(留空则清除)\n" +
|
||||
"- 设置AI聊天(不)响应AT\n" +
|
||||
"- 设置AI聊天最大长度4096\n" +
|
||||
"- 设置AI聊天TopP 0.9\n" +
|
||||
"- 设置AI聊天(不)以AI语音输出\n" +
|
||||
"- 查看AI聊天配置\n" +
|
||||
"- 重置AI聊天\n" +
|
||||
"- 群聊总结 [消息数目]|群聊总结 1000\n" +
|
||||
"- /gpt [内容] (使用大模型聊天)\n",
|
||||
Brief: "大模型聊天和Agent",
|
||||
Help: "- (随意聊天, 概率匹配)",
|
||||
|
||||
PrivateDataFolder: "aichat",
|
||||
}).ApplySingle(single.New(
|
||||
@@ -66,46 +43,48 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
limit = ctxext.NewLimiterManager(time.Second*30, 1)
|
||||
fastfailnorecord = false
|
||||
)
|
||||
|
||||
func init() {
|
||||
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)
|
||||
en.OnMessage(chat.EnsureConfig, func(ctx *zero.Ctx) bool {
|
||||
stor, ok := ctx.State[zero.StateKeyPrefixKeep+"aichatcfg_stor__"].(chat.Storage)
|
||||
if !ok {
|
||||
logrus.Warnln("ERROR: cannot get stor")
|
||||
return false
|
||||
}
|
||||
ctx.State["__aichat_stor__"] = stor
|
||||
return ctx.ExtractPlainText() != "" &&
|
||||
(!stor.noreplyat() || (stor.noreplyat() && !ctx.Event.IsToMe))
|
||||
mp := ctx.State[control.StateKeySyncxState].(*syncx.Map[string, any])
|
||||
if _, ok := mp.Load(chat.StateKeyAgentHooked); !ok && !stor.NoAgent() {
|
||||
logrus.Infoln("[aichat] skip agent for ctx has not been hooked by agent")
|
||||
return false
|
||||
}
|
||||
if !(ctx.ExtractPlainText() != "" &&
|
||||
(!stor.NoReplyAt() || (stor.NoReplyAt() && !ctx.Event.IsToMe))) {
|
||||
return false
|
||||
}
|
||||
rate := stor.Rate()
|
||||
if !ctx.Event.IsToMe && rand.Intn(100) >= int(rate) {
|
||||
return false
|
||||
}
|
||||
if ctx.Event.IsToMe {
|
||||
ctx.Block()
|
||||
}
|
||||
return true
|
||||
}).SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
stor := ctx.State["__aichat_stor__"].(storage)
|
||||
rate := stor.rate()
|
||||
if !ctx.Event.IsToMe && rand.Intn(100) >= int(rate) {
|
||||
return
|
||||
}
|
||||
if ctx.Event.IsToMe {
|
||||
ctx.Block()
|
||||
}
|
||||
if cfg.Key == "" {
|
||||
logrus.Warnln("ERROR: get extra err: empty key")
|
||||
return
|
||||
}
|
||||
temperature := stor.temp()
|
||||
topp, maxn := cfg.mparams()
|
||||
stor := ctx.State[zero.StateKeyPrefixKeep+"aichatcfg_stor__"].(chat.Storage)
|
||||
temperature := stor.Temp()
|
||||
topp, maxn := chat.AC.MParams()
|
||||
mp := ctx.State[control.StateKeySyncxState].(*syncx.Map[string, any])
|
||||
|
||||
if !stor.noagent() && cfg.AgentAPI != "" && cfg.AgentModelName != "" {
|
||||
x := deepinfra.NewAPI(cfg.AgentAPI, string(cfg.AgentKey))
|
||||
mod, err := cfg.Type.protocol(cfg.AgentModelName, temperature, topp, maxn)
|
||||
logrus.Debugln("[aichat] agent mode test: noagent", stor.NoAgent(), "hasapi", chat.AC.AgentAPI != "", "hasmodel", chat.AC.AgentModelName != "")
|
||||
if !stor.NoAgent() && chat.AC.AgentAPI != "" && chat.AC.AgentModelName != "" && chat.AC.Key != "" {
|
||||
logrus.Debugln("[aichat] enter agent mode")
|
||||
x := deepinfra.NewAPI(chat.AC.AgentAPI, string(chat.AC.AgentKey))
|
||||
mod, err := chat.AC.Type.Protocol(chat.AC.AgentModelName, temperature, topp, maxn)
|
||||
if err != nil {
|
||||
logrus.Warnln("ERROR: ", err)
|
||||
return
|
||||
@@ -117,49 +96,79 @@ func init() {
|
||||
role = goba.PermRoleOwner
|
||||
}
|
||||
}
|
||||
ag := chat.AgentOf(ctx.Event.SelfID)
|
||||
if cfg.ImageAPI != "" && !ag.CanViewImage() {
|
||||
mod, err := cfg.ImageType.protocol(cfg.ImageModelName, temperature, topp, maxn)
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
logrus.Warnln("ERROR: cannot get ctrl mamager")
|
||||
}
|
||||
ag := chat.AgentOf(ctx.Event.SelfID, c.Service)
|
||||
logrus.Debugln("[aichat] got agent")
|
||||
if chat.AC.ImageAPI != "" && !ag.CanViewImage() {
|
||||
mod, err := chat.AC.ImageType.Protocol(chat.AC.ImageModelName, temperature, topp, maxn)
|
||||
if err != nil {
|
||||
logrus.Warnln("ERROR: ", err)
|
||||
return
|
||||
}
|
||||
ag.SetViewImageAPI(deepinfra.NewAPI(cfg.ImageAPI, string(cfg.ImageKey)), mod)
|
||||
ag.SetViewImageAPI(deepinfra.NewAPI(chat.AC.ImageAPI, string(chat.AC.ImageKey)), mod)
|
||||
logrus.Debugln("[aichat] agent set img")
|
||||
}
|
||||
ctx.NoTimeout()
|
||||
logrus.Debugln("[aichat] agent set no timeout")
|
||||
hasresp := false
|
||||
// ispuremsg := false
|
||||
// hassavemem := false
|
||||
for i := 0; i < 8; i++ { // 最大运行 8 轮因为问答上下文只有 16
|
||||
reqs := chat.CallAgent(ag, zero.SuperUserPermission(ctx), x, mod, gid, role)
|
||||
reqs := chat.CallAgent(ag, zero.SuperUserPermission(ctx), i+1, x, mod, gid, role)
|
||||
if len(reqs) == 0 {
|
||||
logrus.Debugln("[aichat] agent call got empty response")
|
||||
break
|
||||
}
|
||||
hasresp = true
|
||||
mp.Store(chat.StateKeyAgentTriggered, struct{}{})
|
||||
for _, req := range reqs {
|
||||
resp := ctx.CallAction(req.Action, req.Params)
|
||||
logrus.Infoln("[aichat] agent get resp:", reqs)
|
||||
if req.Action == goba.SVM { // is a fake action
|
||||
/*if hassavemem {
|
||||
ag.AddTerminus(gid)
|
||||
logrus.Warnln("[aichat] agent call save mem multi times, force inserting EOA")
|
||||
return
|
||||
}
|
||||
hassavemem = true*/
|
||||
continue
|
||||
}
|
||||
/*if req.Action == "send_private_msg" || req.Action == "send_group_msg" {
|
||||
if ispuremsg {
|
||||
ag.AddTerminus(gid)
|
||||
logrus.Warnln("[aichat] agent call send msg multi times, force inserting EOA")
|
||||
return
|
||||
}
|
||||
ispuremsg = true
|
||||
}*/
|
||||
logrus.Debugln("[chat] agent triggered", gid, "add requ:", &req)
|
||||
ag.AddRequest(gid, &req)
|
||||
rsp := ctx.CallAction(req.Action, req.Params)
|
||||
logrus.Debugln("[chat] agent triggered", gid, "add resp:", &rsp)
|
||||
ag.AddResponse(gid, &goba.APIResponse{
|
||||
Status: resp.Status,
|
||||
Data: json.RawMessage(resp.Data.Raw),
|
||||
Message: resp.Message,
|
||||
Wording: resp.Wording,
|
||||
RetCode: resp.RetCode,
|
||||
Status: rsp.Status,
|
||||
Data: json.RawMessage(rsp.Data.Raw),
|
||||
Message: rsp.Message,
|
||||
Wording: rsp.Wording,
|
||||
RetCode: rsp.RetCode,
|
||||
})
|
||||
}
|
||||
}
|
||||
if hasresp {
|
||||
ag.AddTerminus(gid)
|
||||
return
|
||||
}
|
||||
// no response, fall back to normal chat
|
||||
logrus.Debugln("[aichat] agent fell back to normal chat")
|
||||
}
|
||||
|
||||
x := deepinfra.NewAPI(cfg.API, string(cfg.Key))
|
||||
mod, err := cfg.Type.protocol(cfg.ModelName, temperature, topp, maxn)
|
||||
x := deepinfra.NewAPI(chat.AC.API, string(chat.AC.Key))
|
||||
mod, err := chat.AC.Type.Protocol(chat.AC.ModelName, temperature, topp, maxn)
|
||||
if err != nil {
|
||||
logrus.Warnln("ERROR: ", err)
|
||||
return
|
||||
}
|
||||
data, err := x.Request(chat.GetChatContext(mod, gid, cfg.SystemP, bool(cfg.NoSystemP)))
|
||||
data, err := x.Request(chat.GetChatContext(mod, gid, chat.AC.SystemP, bool(chat.AC.NoSystemP)))
|
||||
if err != nil {
|
||||
logrus.Warnln("[aichat] post err:", err)
|
||||
return
|
||||
@@ -179,298 +188,24 @@ func init() {
|
||||
if t == "" {
|
||||
continue
|
||||
}
|
||||
logrus.Infoln("[aichat] 回复内容:", t)
|
||||
logrus.Debugln("[aichat] 回复内容:", t)
|
||||
recCfg := airecord.GetConfig()
|
||||
record := ""
|
||||
if !stor.norecord() {
|
||||
if !fastfailnorecord && !stor.NoRecord() {
|
||||
record = ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, t)
|
||||
}
|
||||
if record != "" {
|
||||
ctx.SendChain(message.Record(record))
|
||||
} else {
|
||||
if id != nil {
|
||||
id = ctx.SendChain(message.Reply(id), message.Text(t))
|
||||
} else {
|
||||
id = ctx.SendChain(message.Text(t))
|
||||
if record != "" {
|
||||
ctx.SendChain(message.Record(record))
|
||||
continue
|
||||
}
|
||||
fastfailnorecord = true
|
||||
}
|
||||
if id != nil {
|
||||
id = ctx.SendChain(message.Reply(id), message.Text(t))
|
||||
} else {
|
||||
id = ctx.SendChain(message.Text(t))
|
||||
}
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
}
|
||||
})
|
||||
en.OnPrefix("设置AI聊天触发概率", zero.AdminPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBitmapHandler(bitmaprate, 0, 100))
|
||||
en.OnPrefix("设置AI聊天温度", zero.AdminPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBitmapHandler(bitmaptemp, 0, 100))
|
||||
en.OnPrefix("设置AI聊天接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(newextrasetmodeltype(&cfg.Type))
|
||||
en.OnPrefix("设置AI聊天识图接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(newextrasetmodeltype(&cfg.ImageType))
|
||||
en.OnPrefix("设置AI聊天Agent接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(newextrasetmodeltype(&cfg.AgentType))
|
||||
en.OnPrefix("设置AI聊天接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
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).
|
||||
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).
|
||||
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).
|
||||
Handle(newextrasetstr(&cfg.SystemP))
|
||||
en.OnFullMatch("查看AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(cfg.SystemP))
|
||||
})
|
||||
en.OnFullMatch("重置AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||
return
|
||||
}
|
||||
cfg.SystemP = chat.SystemPrompt
|
||||
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).
|
||||
Handle(newextrasetstr(&cfg.Separator))
|
||||
en.OnRegex("^设置AI聊天(不)?响应AT$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBoolHandler(bitmapnrat))
|
||||
en.OnRegex("^设置AI聊天(不)?支持系统提示词$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
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).
|
||||
Handle(newextrasetuint(&cfg.MaxN))
|
||||
en.OnPrefix("设置AI聊天TopP", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
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
|
||||
}
|
||||
|
||||
// 构造总结请求提示
|
||||
summaryPrompt := "请总结这个群聊内容,要求按发言顺序梳理,明确标注每个发言者的昵称,并完整呈现其核心观点、提出的问题、发表的看法或做出的回应,确保不遗漏关键信息,且能体现成员间的对话逻辑和互动关系:\n" +
|
||||
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 := (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)
|
||||
}
|
||||
183
plugin/aichatcfg/main.go
Normal file
183
plugin/aichatcfg/main.go
Normal file
@@ -0,0 +1,183 @@
|
||||
// Package aichatcfg aichat 的配置, 优先级要比 aichat 高
|
||||
package aichatcfg
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/chat"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
var (
|
||||
// en data [8 temp] [8 rate] LSB
|
||||
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Extra: control.ExtraFromString("aichat"),
|
||||
Brief: "aichat 的配置",
|
||||
Help: "- 设置AI聊天触发概率10\n" +
|
||||
"- 设置AI聊天温度80\n" +
|
||||
"- 设置AI聊天(|识图|Agent)接口类型[OpenAI|OLLaMA|GenAI]\n" +
|
||||
"- 设置AI聊天(不)使用Agent模式\n" +
|
||||
"- 设置AI聊天(不)支持系统提示词\n" +
|
||||
"- 设置AI聊天(|识图|Agent)接口地址https://api.siliconflow.cn/v1/chat/completions\n" +
|
||||
"- 设置AI聊天(|识图|Agent)密钥xxx\n" +
|
||||
"- 设置AI聊天(|识图|Agent)模型名Qwen/Qwen3-8B\n" +
|
||||
"- 查看AI聊天系统提示词\n" +
|
||||
"- 重置AI聊天系统提示词\n" +
|
||||
"- 设置AI聊天系统提示词xxx\n" +
|
||||
"- 设置AI聊天Agent性格xxx" +
|
||||
"- 查看AI聊天Agent性格" +
|
||||
"- 设置AI聊天Agent性别xxx" +
|
||||
"- 查看AI聊天Agent性别" +
|
||||
"- 重置AI聊天Agent性格性别\n" +
|
||||
"- 设置AI聊天分隔符</think>(留空则清除)\n" +
|
||||
"- 设置AI聊天(不)响应AT\n" +
|
||||
"- 设置AI聊天最大长度4096\n" +
|
||||
"- 设置AI聊天TopP 0.9\n" +
|
||||
"- 设置AI聊天(不)以AI语音输出\n" +
|
||||
"- 查看AI聊天配置\n" +
|
||||
"- 重置AI聊天Agent\n" +
|
||||
"- 重置AI聊天\n",
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
en.UsePreHandler(chat.EnsureConfig, func(ctx *zero.Ctx) bool {
|
||||
k := zero.StateKeyPrefixKeep + "aichatcfg_stor__"
|
||||
if _, ok := ctx.State[k]; ok {
|
||||
return true
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
stor, err := chat.NewStorage(ctx, gid)
|
||||
if err != nil {
|
||||
logrus.Warnln("ERROR: ", err)
|
||||
return false
|
||||
}
|
||||
ctx.State[k] = stor
|
||||
return true
|
||||
})
|
||||
en.OnPrefix("设置AI聊天触发概率", zero.AdminPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBitmapHandler(chat.BitmapRate, 0, 100))
|
||||
en.OnPrefix("设置AI聊天温度", zero.AdminPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBitmapHandler(chat.BitmapTemp, 0, 100))
|
||||
en.OnPrefix("设置AI聊天接口类型", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetModelType(&chat.AC.Type))
|
||||
en.OnPrefix("设置AI聊天识图接口类型", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetModelType(&chat.AC.ImageType))
|
||||
en.OnPrefix("设置AI聊天Agent接口类型", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetModelType(&chat.AC.AgentType))
|
||||
en.OnPrefix("设置AI聊天接口地址", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.API))
|
||||
en.OnPrefix("设置AI聊天识图接口地址", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.ImageAPI))
|
||||
en.OnPrefix("设置AI聊天Agent接口地址", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.AgentAPI))
|
||||
en.OnPrefix("设置AI聊天密钥", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.Key))
|
||||
en.OnPrefix("设置AI聊天识图密钥", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.ImageKey))
|
||||
en.OnPrefix("设置AI聊天Agent密钥", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.AgentKey))
|
||||
en.OnPrefix("设置AI聊天模型名", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.ModelName))
|
||||
en.OnPrefix("设置AI聊天识图模型名", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.ImageModelName))
|
||||
en.OnPrefix("设置AI聊天Agent模型名", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.AgentModelName))
|
||||
en.OnPrefix("设置AI聊天系统提示词", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.SystemP))
|
||||
en.OnPrefix("设置AI聊天Agent性格", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.AgentChar), func(_ *zero.Ctx) {
|
||||
chat.AgentCharConfig.Chars = chat.AC.AgentChar
|
||||
})
|
||||
en.OnPrefix("设置AI聊天Agent性别", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.AgentSex), func(_ *zero.Ctx) {
|
||||
chat.AgentCharConfig.Sex = chat.AC.AgentSex
|
||||
})
|
||||
en.OnFullMatch("查看AI聊天系统提示词", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(chat.AC.SystemP))
|
||||
})
|
||||
en.OnFullMatch("查看AI聊天Agent性格", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(chat.AC.AgentChar))
|
||||
})
|
||||
en.OnFullMatch("重置AI聊天系统提示词", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||
return
|
||||
}
|
||||
chat.AC.SystemP = chat.SystemPrompt
|
||||
err := c.SetExtra(&chat.AC)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功"))
|
||||
})
|
||||
en.OnFullMatch("重置AI聊天Agent性格性别", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("ERROR: no such plugin"))
|
||||
return
|
||||
}
|
||||
chat.ResetAgentCharConfig()
|
||||
err := c.SetExtra(&chat.AC)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功, 请重置AI聊天Agent"))
|
||||
})
|
||||
en.OnPrefix("设置AI聊天分隔符", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetStr(&chat.AC.Separator))
|
||||
en.OnRegex("^设置AI聊天(不)?响应AT$", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBoolHandler(chat.BitmapNrat))
|
||||
en.OnRegex("^设置AI聊天(不)?支持系统提示词$", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetBool(&chat.AC.NoSystemP))
|
||||
en.OnRegex("^设置AI聊天(不)?使用Agent模式$", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBoolHandler(chat.BitmapNagt))
|
||||
en.OnPrefix("设置AI聊天最大长度", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetUint(&chat.AC.MaxN))
|
||||
en.OnPrefix("设置AI聊天TopP", chat.EnsureConfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(chat.NewExtraSetFloat32(&chat.AC.TopP))
|
||||
en.OnRegex("^设置AI聊天(不)?以AI语音输出$", zero.AdminPermission).SetBlock(true).
|
||||
Handle(ctxext.NewStorageSaveBoolHandler(chat.BitmapNrec))
|
||||
en.OnFullMatch("查看AI聊天配置", chat.EnsureConfig, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
stor, err := chat.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语音输出:", chat.ModelBool(!stor.NoRecord()), "\n",
|
||||
"• 使用Agent:", chat.ModelBool(!stor.NoAgent()), "\n",
|
||||
"• 响应@:", chat.ModelBool(!stor.NoReplyAt()), "\n",
|
||||
),
|
||||
message.Text("【当前AI聊天全局配置】\n", &chat.AC),
|
||||
)
|
||||
})
|
||||
en.OnFullMatch("重置AI聊天Agent", chat.EnsureConfig, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
chat.ResetAgents()
|
||||
ctx.SendChain(message.Text("成功"))
|
||||
})
|
||||
en.OnFullMatch("重置AI聊天", chat.EnsureConfig, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
chat.ResetChat()
|
||||
ctx.SendChain(message.Text("成功"))
|
||||
})
|
||||
}
|
||||
@@ -25,10 +25,10 @@ import (
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"github.com/shirou/gopsutil/v4/host"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
@@ -3,7 +3,6 @@ package crypter
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/AnimeAPI/airecord"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
@@ -12,7 +11,6 @@ import (
|
||||
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 != "" {
|
||||
|
||||
@@ -36,7 +36,7 @@ var (
|
||||
lotsList = func() map[string]info {
|
||||
lotsList, err := getList()
|
||||
if err != nil {
|
||||
logrus.Infoln("[drawlots]加载失败:", err)
|
||||
logrus.Infoln("[drawlots]加载失败:", err, "(如果从未使用过该插件, 这是正常现象)")
|
||||
} else {
|
||||
logrus.Infoln("[drawlots]加载", len(lotsList), "个抽签")
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/pkg/errors"
|
||||
@@ -30,7 +28,7 @@ func init() {
|
||||
var err1 error
|
||||
t2s, err1 = gocc.New("t2s")
|
||||
if err1 != nil {
|
||||
log.Infof("[guessmusic]:%s", err1)
|
||||
panic(err1)
|
||||
}
|
||||
|
||||
engine.OnRegex(`^(个人|团队)猜歌(-(.*))?$`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
|
||||
246
plugin/llm/main.go
Normal file
246
plugin/llm/main.go
Normal file
@@ -0,0 +1,246 @@
|
||||
// Package llm 大模型聊天和群聊总结
|
||||
package llm
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fumiama/deepinfra"
|
||||
"github.com/fumiama/deepinfra/model"
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/chat"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
var (
|
||||
// en data [8 temp] [8 rate] LSB
|
||||
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "大模型聊天和群聊总结",
|
||||
Help: "- 群聊总结 [消息数目]|群聊总结 1000\n" +
|
||||
"- /gpt [内容] (使用大模型聊天)\n",
|
||||
}).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 (
|
||||
limit = ctxext.NewLimiterManager(time.Second*30, 1)
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 添加群聊总结功能
|
||||
en.OnRegex(`^群聊总结\s?(\d*)$`, chat.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 := chat.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", chat.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 := chat.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 := chat.AC.MParams()
|
||||
|
||||
x := deepinfra.NewAPI(chat.AC.API, string(chat.AC.Key))
|
||||
|
||||
mod, err := chat.AC.Type.Protocol(chat.AC.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
|
||||
}
|
||||
@@ -3,8 +3,9 @@ package minecraftobserver
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/jinzhu/gorm"
|
||||
"testing"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
func cleanTestData(t *testing.T) {
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
// Package music QQ音乐、网易云、酷狗、酷我、咪咕 点歌
|
||||
// Package music 整合多平台音乐点播能力
|
||||
package music
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/guohuiyuan/music-lib/kugou"
|
||||
"github.com/guohuiyuan/music-lib/kuwo"
|
||||
"github.com/guohuiyuan/music-lib/migu"
|
||||
"github.com/guohuiyuan/music-lib/netease"
|
||||
"github.com/guohuiyuan/music-lib/qq"
|
||||
"github.com/pkg/errors"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
longZhuURL = "https://www.hhlqilongzhu.cn/api/joox/juhe_music.php?msg=%v"
|
||||
)
|
||||
var platformMap = map[string]func(string) (message.Segment, error){
|
||||
"咪咕": getMiguMusic,
|
||||
"酷我": getKuwoMusic,
|
||||
"酷狗": getKugouMusic,
|
||||
"网易": getNeteaseMusic,
|
||||
"qq": getQQMusic,
|
||||
"": getKuwoMusic, // 默认点歌指向酷我
|
||||
}
|
||||
|
||||
func init() {
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "点歌",
|
||||
Help: "- 点歌[xxx]\n" +
|
||||
Help: "- 点歌[xxx] (默认酷我)\n" +
|
||||
"- 网易点歌[xxx]\n" +
|
||||
"- 酷我点歌[xxx]\n" +
|
||||
"- 酷狗点歌[xxx]\n" +
|
||||
@@ -37,203 +38,146 @@ func init() {
|
||||
"- qq点歌[xxx]\n",
|
||||
}).OnRegex(`^(.{0,2})点歌\s?(.{1,25})$`).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// switch 平台
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "咪咕":
|
||||
ctx.SendChain(migu(ctx.State["regex_matched"].([]string)[2]))
|
||||
case "酷我":
|
||||
ctx.SendChain(kuwo(ctx.State["regex_matched"].([]string)[2]))
|
||||
case "酷狗":
|
||||
ctx.SendChain(kugou(ctx.State["regex_matched"].([]string)[2]))
|
||||
case "网易":
|
||||
ctx.SendChain(cloud163(ctx.State["regex_matched"].([]string)[2]))
|
||||
case "qq":
|
||||
ctx.SendChain(qqmusic(ctx.State["regex_matched"].([]string)[2]))
|
||||
default: // 默认聚合点歌
|
||||
ctx.SendChain(longzhu(ctx.State["regex_matched"].([]string)[2]))
|
||||
matches := ctx.State["regex_matched"].([]string)
|
||||
platformPrefix := matches[1]
|
||||
keyword := matches[2]
|
||||
|
||||
processFunc, ok := platformMap[platformPrefix]
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("不支持的点播平台:", platformPrefix))
|
||||
return
|
||||
}
|
||||
|
||||
seg, err := processFunc(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("点歌失败:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(seg)
|
||||
})
|
||||
}
|
||||
|
||||
// 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 返回咪咕音乐卡片
|
||||
func migu(keyword string) message.Segment {
|
||||
headers := http.Header{
|
||||
"Cookie": []string{"audioplayer_exist=1; audioplayer_open=0; migu_cn_cookie_id=3ad476db-f021-4bda-ab91-c485ac3d56a0; Hm_lvt_ec5a5474d9d871cb3d82b846d861979d=1671119573; Hm_lpvt_ec5a5474d9d871cb3d82b846d861979d=1671119573; WT_FPC=id=279ef92eaf314cbb8d01671116477485:lv=1671119583092:ss=1671116477485"},
|
||||
"csrf": []string{"LWKACV45JSQ"},
|
||||
"User-Agent": []string{"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"},
|
||||
"Referer": []string{"http://m.music.migu.cn"},
|
||||
"proxy": []string{"false"},
|
||||
}
|
||||
// 搜索音乐信息 第一首歌
|
||||
search, _ := url.Parse("http://m.music.migu.cn/migu/remoting/scr_search_tag")
|
||||
search.RawQuery = url.Values{
|
||||
"keyword": []string{keyword},
|
||||
"type": []string{"2"},
|
||||
"pgc": []string{"1"},
|
||||
"rows": []string{"10"},
|
||||
}.Encode()
|
||||
info := gjson.ParseBytes(netGet(search.String(), headers)).Get("musics.0")
|
||||
// 返回音乐卡片
|
||||
return message.CustomMusic(
|
||||
fmt.Sprintf("https://music.migu.cn/v3/music/song/%s", info.Get("copyrightId").String()),
|
||||
info.Get("mp3").String(),
|
||||
info.Get("songName").String(),
|
||||
).Add("content", info.Get("artist").Str).Add("image", info.Get("cover").Str).Add("subtype", "migu")
|
||||
}
|
||||
|
||||
// kuwo 返回酷我音乐卡片
|
||||
func kuwo(keyword string) message.Segment {
|
||||
headers := http.Header{
|
||||
"Cookie": []string{"Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1610284708,1610699237; _ga=GA1.2.1289529848.1591618534; kw_token=LWKACV45JSQ; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1610699468; _gid=GA1.2.1868980507.1610699238; _gat=1"},
|
||||
"csrf": []string{"LWKACV45JSQ"},
|
||||
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
|
||||
"Referer": []string{"https://www.kuwo.cn/search/list?key="},
|
||||
}
|
||||
// 搜索音乐信息 第一首歌
|
||||
search, _ := url.Parse("https://www.kuwo.cn/api/www/search/searchMusicBykeyWord")
|
||||
search.RawQuery = url.Values{
|
||||
"key": []string{keyword},
|
||||
"pn": []string{"1"},
|
||||
"rn": []string{"1"},
|
||||
"httpsStatus": []string{"1"},
|
||||
}.Encode()
|
||||
info := gjson.ParseBytes(netGet(search.String(), headers)).Get("data.list.0")
|
||||
// 获得音乐直链
|
||||
music, _ := url.Parse("http://www.kuwo.cn/api/v1/www/music/playUrl")
|
||||
music.RawQuery = url.Values{
|
||||
"mid": []string{fmt.Sprintf("%d", info.Get("rid").Int())},
|
||||
"type": []string{"convert_url3"},
|
||||
"br": []string{"320kmp3"},
|
||||
"httpsStatus": []string{"1"},
|
||||
}.Encode()
|
||||
audio := gjson.ParseBytes(netGet(music.String(), headers))
|
||||
// 返回音乐卡片
|
||||
return message.CustomMusic(
|
||||
fmt.Sprintf("https://www.kuwo.cn/play_detail/%d", info.Get("rid").Int()),
|
||||
audio.Get("data.url").Str,
|
||||
info.Get("name").Str,
|
||||
).Add("content", info.Get("artist").Str).Add("image", info.Get("pic").Str).Add("subtype", "kuwo")
|
||||
}
|
||||
|
||||
// kugou 返回酷狗音乐卡片
|
||||
func kugou(keyword string) message.Segment {
|
||||
stamp := time.Now().UnixNano() / 1e6
|
||||
hash := md5str(
|
||||
fmt.Sprintf(
|
||||
"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwtbitrate=0callback=callback123clienttime=%dclientver=2000dfid=-inputtype=0iscorrection=1isfuzzy=0keyword=%smid=%dpage=1pagesize=30platform=WebFilterprivilege_filter=0srcappid=2919tag=emuserid=-1uuid=%dNVPh5oo715z5DIWAeQlhMDsWXXQV4hwt",
|
||||
stamp, keyword, stamp, stamp,
|
||||
),
|
||||
)
|
||||
// 搜索音乐信息 第一首歌
|
||||
h1 := http.Header{
|
||||
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
|
||||
}
|
||||
search, _ := url.Parse("https://complexsearch.kugou.com/v2/search/song")
|
||||
search.RawQuery = url.Values{
|
||||
"callback": []string{"callback123"},
|
||||
"keyword": []string{keyword},
|
||||
"page": []string{"1"},
|
||||
"pagesize": []string{"30"},
|
||||
"bitrate": []string{"0"},
|
||||
"isfuzzy": []string{"0"},
|
||||
"tag": []string{"em"},
|
||||
"inputtype": []string{"0"},
|
||||
"platform": []string{"WebFilter"},
|
||||
"userid": []string{"-1"},
|
||||
"clientver": []string{"2000"},
|
||||
"iscorrection": []string{"1"},
|
||||
"privilege_filter": []string{"0"},
|
||||
"srcappid": []string{"2919"},
|
||||
"clienttime": []string{fmt.Sprintf("%d", stamp)},
|
||||
"mid": []string{fmt.Sprintf("%d", stamp)},
|
||||
"uuid": []string{fmt.Sprintf("%d", stamp)},
|
||||
"dfid": []string{"-"},
|
||||
"signature": []string{hash},
|
||||
}.Encode()
|
||||
res := netGet(search.String(), h1)
|
||||
info := gjson.ParseBytes(res[12 : len(res)-2]).Get("data.lists.0")
|
||||
// 获得音乐直链
|
||||
h2 := http.Header{
|
||||
"Cookie": []string{"kg_mid=d8e70a262c93d47599c6196c612d6f4f; Hm_lvt_aedee6983d4cfc62f509129360d6bb3d=1610278505,1611631363,1611722252; kg_dfid=33ZWee1kircl0jcJ1h0WF1fX; Hm_lpvt_aedee6983d4cfc62f509129360d6bb3d=1611727348; kg_dfid_collect=d41d8cd98f00b204e9800998ecf8427e"},
|
||||
"Host": []string{"wwwapi.kugou.com"},
|
||||
"TE": []string{"Trailers"},
|
||||
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
|
||||
}
|
||||
music := "https://wwwapi.kugou.com/yy/index.php?r=play%2Fgetdata&hash=" + info.Get("FileHash").Str + "&album_id=" + info.Get("AlbumID").Str
|
||||
audio := gjson.ParseBytes(netGet(music, h2)).Get("data")
|
||||
// 返回音乐卡片
|
||||
return message.CustomMusic(
|
||||
"https://www.kugou.com/song/#hash="+audio.Get("hash").Str+"&album_id="+audio.Get("album_id").Str,
|
||||
strings.ReplaceAll(audio.Get("play_backup_url").Str, "\\/", "/"),
|
||||
audio.Get("audio_name").Str,
|
||||
).Add("content", audio.Get("author_name").Str).Add("image", audio.Get("img").Str).Add("subtype", "kugou")
|
||||
}
|
||||
|
||||
// cloud163 返回网易云音乐卡片
|
||||
func cloud163(keyword string) (msg message.Segment) {
|
||||
requestURL := "http://music.163.com/api/search/get/web?type=1&limit=1&s=" + url.QueryEscape(keyword)
|
||||
data, err := web.GetData(requestURL)
|
||||
func getMiguMusic(keyword string) (message.Segment, error) {
|
||||
songs, err := migu.Search(keyword)
|
||||
if err != nil {
|
||||
msg = message.Text("ERROR: ", err)
|
||||
return
|
||||
return message.Segment{}, errors.Wrap(err, "咪咕音乐搜索失败")
|
||||
}
|
||||
msg = message.Music("163", gjson.ParseBytes(data).Get("result.songs.0.id").Int())
|
||||
return
|
||||
}
|
||||
if len(songs) == 0 {
|
||||
return message.Segment{}, errors.New("咪咕音乐未找到相关歌曲:" + keyword)
|
||||
}
|
||||
song := songs[0]
|
||||
|
||||
// qqmusic 返回QQ音乐卡片
|
||||
func qqmusic(keyword string) (msg message.Segment) {
|
||||
requestURL := "https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?platform=yqq.json&key=" + url.QueryEscape(keyword)
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), requestURL, "GET", "", web.RandUA(), nil)
|
||||
playURL, err := migu.GetDownloadURL(&song)
|
||||
if err != nil {
|
||||
msg = message.Text("ERROR: ", err)
|
||||
return
|
||||
return message.Segment{}, errors.Wrap(err, "获取咪咕播放链接失败")
|
||||
}
|
||||
msg = message.Music("qq", gjson.ParseBytes(data).Get("data.song.itemlist.0.id").Int())
|
||||
return
|
||||
if playURL == "" {
|
||||
return message.Segment{}, errors.New("获取咪咕播放链接失败:链接为空")
|
||||
}
|
||||
|
||||
return message.CustomMusic(
|
||||
fmt.Sprintf("https://music.migu.cn/v3/music/song/%s", song.ID),
|
||||
playURL,
|
||||
song.Name,
|
||||
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "migu"), nil
|
||||
}
|
||||
|
||||
// md5str 返回字符串 MD5
|
||||
func md5str(s string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(s))
|
||||
result := strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
|
||||
return result
|
||||
}
|
||||
|
||||
// netGet 返回请求数据
|
||||
func netGet(url string, header http.Header) []byte {
|
||||
client := &http.Client{}
|
||||
request, _ := http.NewRequest("GET", url, nil)
|
||||
request.Header = header
|
||||
res, err := client.Do(request)
|
||||
func getKuwoMusic(keyword string) (message.Segment, error) {
|
||||
songs, err := kuwo.Search(keyword)
|
||||
if err != nil {
|
||||
return nil
|
||||
return message.Segment{}, errors.Wrap(err, "酷我音乐搜索失败")
|
||||
}
|
||||
defer res.Body.Close()
|
||||
result, _ := io.ReadAll(res.Body)
|
||||
return result
|
||||
if len(songs) == 0 {
|
||||
return message.Segment{}, errors.New("酷我音乐未找到相关歌曲:" + keyword)
|
||||
}
|
||||
song := songs[0]
|
||||
|
||||
playURL, err := kuwo.GetDownloadURL(&song)
|
||||
if err != nil {
|
||||
return message.Segment{}, errors.Wrap(err, "获取酷我播放链接失败")
|
||||
}
|
||||
if playURL == "" {
|
||||
return message.Segment{}, errors.New("获取酷我播放链接失败:链接为空")
|
||||
}
|
||||
|
||||
return message.CustomMusic(
|
||||
fmt.Sprintf("https://www.kuwo.cn/play_detail/%s", song.ID),
|
||||
playURL,
|
||||
song.Name,
|
||||
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "kuwo"), nil
|
||||
}
|
||||
|
||||
func getKugouMusic(keyword string) (message.Segment, error) {
|
||||
songs, err := kugou.Search(keyword)
|
||||
if err != nil {
|
||||
return message.Segment{}, errors.Wrap(err, "酷狗音乐搜索失败")
|
||||
}
|
||||
if len(songs) == 0 {
|
||||
return message.Segment{}, errors.New("酷狗音乐未找到相关歌曲:" + keyword)
|
||||
}
|
||||
song := songs[0]
|
||||
|
||||
playURL, err := kugou.GetDownloadURL(&song)
|
||||
if err != nil {
|
||||
return message.Segment{}, errors.Wrap(err, "获取酷狗播放链接失败")
|
||||
}
|
||||
if playURL == "" {
|
||||
return message.Segment{}, errors.New("获取酷狗播放链接失败:链接为空")
|
||||
}
|
||||
|
||||
return message.CustomMusic(
|
||||
"https://www.kugou.com/",
|
||||
playURL,
|
||||
song.Name,
|
||||
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "kugou"), nil
|
||||
}
|
||||
|
||||
func getNeteaseMusic(keyword string) (message.Segment, error) {
|
||||
songs, err := netease.Search(keyword)
|
||||
if err != nil {
|
||||
return message.Segment{}, errors.Wrap(err, "网易云音乐搜索失败")
|
||||
}
|
||||
if len(songs) == 0 {
|
||||
return message.Segment{}, errors.New("网易云音乐未找到相关歌曲:" + keyword)
|
||||
}
|
||||
song := songs[0]
|
||||
|
||||
playURL, err := netease.GetDownloadURL(&song)
|
||||
if err != nil {
|
||||
return message.Segment{}, errors.Wrap(err, "获取网易云播放链接失败")
|
||||
}
|
||||
if playURL == "" {
|
||||
return message.Segment{}, errors.New("获取网易云播放链接失败:链接为空")
|
||||
}
|
||||
|
||||
return message.CustomMusic(
|
||||
fmt.Sprintf("https://music.163.com/#/song?id=%s", song.ID),
|
||||
playURL,
|
||||
song.Name,
|
||||
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "163"), nil
|
||||
}
|
||||
|
||||
func getQQMusic(keyword string) (message.Segment, error) {
|
||||
songs, err := qq.Search(keyword)
|
||||
if err != nil {
|
||||
return message.Segment{}, errors.Wrap(err, "QQ音乐搜索失败")
|
||||
}
|
||||
if len(songs) == 0 {
|
||||
return message.Segment{}, errors.New("QQ音乐未找到相关歌曲:" + keyword)
|
||||
}
|
||||
song := songs[0]
|
||||
|
||||
playURL, err := qq.GetDownloadURL(&song)
|
||||
if err != nil {
|
||||
return message.Segment{}, errors.Wrap(err, "获取QQ音乐播放链接失败")
|
||||
}
|
||||
if playURL == "" {
|
||||
return message.Segment{}, errors.New("获取QQ音乐播放链接失败:链接为空")
|
||||
}
|
||||
|
||||
return message.CustomMusic(
|
||||
fmt.Sprintf("https://y.qq.com/n/ryqq/songDetail/%s", song.ID),
|
||||
playURL,
|
||||
song.Name,
|
||||
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "qq"), nil
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func (repo *RssDomain) syncRss(ctx context.Context) (updated map[int64]*RssClien
|
||||
feed, err = repo.rssHubClient.FetchFeed(channel.RssHubFeedPath)
|
||||
// 如果获取失败,则跳过
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] fetch path(%+v) error: %v", channel.RssHubFeedPath, err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub syncRss] fetch path(%+v) error: %v", channel.RssHubFeedPath, err)
|
||||
continue
|
||||
}
|
||||
rv := convertFeedToRssView(0, channel.RssHubFeedPath, feed)
|
||||
@@ -42,27 +42,27 @@ func (repo *RssDomain) syncRss(ctx context.Context) (updated map[int64]*RssClien
|
||||
var needUpdate bool
|
||||
needUpdate, err = repo.checkSourceNeedUpdate(ctx, cv.Source)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] checkSourceNeedUpdate error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub syncRss] checkSourceNeedUpdate error: %v", err)
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
// 保存
|
||||
logrus.WithContext(ctx).Infof("[rsshub syncRss] cv %+v, need update(real): %v", cv.Source, needUpdate)
|
||||
logrus.WithContext(ctx).Debugf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[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)
|
||||
logrus.WithContext(ctx).Debugf("[rsshub syncRss] cv %s, no new content", cv.Source.RssHubFeedPath)
|
||||
continue
|
||||
}
|
||||
updateChannelView.Sort()
|
||||
@@ -80,7 +80,7 @@ func (repo *RssDomain) checkSourceNeedUpdate(ctx context.Context, source *RssSou
|
||||
return
|
||||
}
|
||||
if sourceInDB == nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] source not found: %v", source.RssHubFeedPath)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub syncRss] source not found: %v", source.RssHubFeedPath)
|
||||
return
|
||||
}
|
||||
source.ID = sourceInDB.ID
|
||||
@@ -102,13 +102,13 @@ func (repo *RssDomain) processContentsUpdate(ctx context.Context, cv *RssClientV
|
||||
var existed bool
|
||||
existed, err = repo.processContentItemUpdate(ctx, content)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] upsert content error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[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)
|
||||
logrus.WithContext(ctx).Debugf("[rsshub syncRss] cv %s, add new content: %v", cv.Source.RssHubFeedPath, content.Title)
|
||||
}
|
||||
}
|
||||
return err
|
||||
@@ -127,7 +127,7 @@ func (repo *RssDomain) processContentItemUpdate(ctx context.Context, content *Rs
|
||||
// 保存
|
||||
err = repo.storage.UpsertContent(ctx, content)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub syncRss] upsert content error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub syncRss] upsert content error: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
|
||||
@@ -36,11 +36,11 @@ func (c *RssHubClient) FetchFeed(path string) (feed *gofeed.Feed, err error) {
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Errorf("[rsshub FetchFeed] fetch feed error: %v", err)
|
||||
logrus.Warnf("[rsshub FetchFeed] fetch feed error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
if len(data) == 0 {
|
||||
logrus.Errorf("[rsshub FetchFeed] fetch feed error: data is empty")
|
||||
logrus.Warnf("[rsshub FetchFeed] fetch feed error: data is empty")
|
||||
return nil, errors.New("feed data is empty")
|
||||
}
|
||||
feed, err = gofeed.NewParser().Parse(bytes.NewBuffer(data))
|
||||
|
||||
@@ -33,7 +33,7 @@ func newRssDomain(dbPath string) (*RssDomain, error) {
|
||||
}
|
||||
orm, err := gorm.Open("sqlite3", dbPath)
|
||||
if err != nil {
|
||||
logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err)
|
||||
logrus.Warnf("[rsshub NewRssDomain] open db error: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
repo := &RssDomain{
|
||||
@@ -42,7 +42,7 @@ func newRssDomain(dbPath string) (*RssDomain, error) {
|
||||
}
|
||||
err = repo.storage.initDB()
|
||||
if err != nil {
|
||||
logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err)
|
||||
logrus.Warnf("[rsshub NewRssDomain] open db error: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
return repo, nil
|
||||
@@ -54,15 +54,15 @@ func (repo *RssDomain) Subscribe(ctx context.Context, gid int64, feedPath string
|
||||
// 验证
|
||||
feed, err := repo.rssHubClient.FetchFeed(feedPath)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] add source error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Subscribe] add source error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] try get source success: %v", len(feed.Title))
|
||||
logrus.WithContext(ctx).Debugf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Subscribe] query source by feedPath error: %v", err)
|
||||
return
|
||||
}
|
||||
// 如果已经存在
|
||||
@@ -76,30 +76,30 @@ func (repo *RssDomain) Subscribe(ctx context.Context, gid int64, feedPath string
|
||||
// 保存
|
||||
err = repo.storage.UpsertSource(ctx, rv.Source)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] save source error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Subscribe] save source error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.Infof("[rsshub Subscribe] save/update source success %v", rv.Source.ID)
|
||||
logrus.Debugf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Subscribe] query subscribe error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] query subscribe success: %v", subscribe)
|
||||
logrus.WithContext(ctx).Debugf("[rsshub Subscribe] query subscribe success: %v", subscribe)
|
||||
// 如果已经存在,直接返回
|
||||
if subscribe != nil {
|
||||
isSubExisted = true
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] subscribe existed: %v", subscribe)
|
||||
logrus.WithContext(ctx).Debugf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Subscribe] save subscribe error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] success: %v", len(rv.Contents))
|
||||
logrus.WithContext(ctx).Debugf("[rsshub Subscribe] success: %v", len(rv.Contents))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -107,31 +107,31 @@ func (repo *RssDomain) Subscribe(ctx context.Context, gid int64, feedPath string
|
||||
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)
|
||||
logrus.WithContext(ctx).Warnf("[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)
|
||||
logrus.WithContext(ctx).Debugf("[rsshub Subscribe] query source by route success: %v", existedSubscribes)
|
||||
// 如果不存在订阅关系,直接返回
|
||||
if !ifExisted || existedSubscribes == nil {
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] source existed: %v", ifExisted)
|
||||
logrus.WithContext(ctx).Debugf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Subscribe] delete source error: %v", err)
|
||||
return errors.New("清除频道信息失败")
|
||||
}
|
||||
}
|
||||
@@ -142,11 +142,11 @@ func (repo *RssDomain) Unsubscribe(ctx context.Context, gid int64, feedPath stri
|
||||
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)
|
||||
logrus.WithContext(ctx).Warnf("[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))
|
||||
logrus.WithContext(ctx).Debugf("[rsshub GetSubscribedChannelsByGroupID] query subscribe success: %v", len(channels))
|
||||
for i, cn := range channels {
|
||||
rv[i] = &RssClientView{
|
||||
Source: cn,
|
||||
@@ -162,13 +162,13 @@ func (repo *RssDomain) Sync(ctx context.Context) (groupView map[int64][]*RssClie
|
||||
// 获取所有频道
|
||||
updatedViews, err := repo.syncRss(ctx)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Sync] sync rss feed error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Sync] sync rss feed error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Sync] updated channels: %v", len(updatedViews))
|
||||
logrus.WithContext(ctx).Debugf("[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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub Sync] get subscribes error: %v", err)
|
||||
return
|
||||
}
|
||||
for _, subscribe := range subscribes {
|
||||
|
||||
@@ -19,7 +19,7 @@ type repoStorage struct {
|
||||
func (s *repoStorage) initDB() (err error) {
|
||||
err = s.orm.AutoMigrate(&RssSource{}, &RssContent{}, &RssSubscribe{}).Error
|
||||
if err != nil {
|
||||
logrus.Errorf("[rsshub initDB] error: %v", err)
|
||||
logrus.Warnf("[rsshub initDB] error: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -28,7 +28,7 @@ func (s *repoStorage) initDB() (err error) {
|
||||
|
||||
// GetSubscribesBySource Impl
|
||||
func (s *repoStorage) GetSubscribesBySource(ctx context.Context, feedPath string) ([]*RssSubscribe, error) {
|
||||
logrus.WithContext(ctx).Infof("[rsshub GetSubscribesBySource] feedPath: %s", feedPath)
|
||||
logrus.WithContext(ctx).Debugf("[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
|
||||
@@ -36,7 +36,7 @@ func (s *repoStorage) GetSubscribesBySource(ctx context.Context, feedPath string
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub GetSubscribesBySource] error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub GetSubscribesBySource] error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return rs, nil
|
||||
@@ -56,7 +56,7 @@ func (s *repoStorage) GetIfExistedSubscribe(ctx context.Context, gid int64, feed
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, false, nil
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub GetIfExistedSubscribe] error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub GetIfExistedSubscribe] error: %v", err)
|
||||
return nil, false, err
|
||||
}
|
||||
if rs.ID == 0 {
|
||||
@@ -76,14 +76,14 @@ func (s *repoStorage) UpsertSource(ctx context.Context, source *RssSource) (err
|
||||
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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] add source error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
source.ID = querySource.ID
|
||||
logrus.WithContext(ctx).Infof("[rsshub] update source: %+v", source.UpdatedParsed)
|
||||
logrus.WithContext(ctx).Debugf("[rsshub] update source: %+v", source.UpdatedParsed)
|
||||
err = s.orm.Model(&source).Where(&RssSource{ID: source.ID}).
|
||||
Updates(&RssSource{
|
||||
Title: source.Title,
|
||||
@@ -94,7 +94,7 @@ func (s *repoStorage) UpsertSource(ctx context.Context, source *RssSource) (err
|
||||
Mtime: time.Now(),
|
||||
}).Error
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] update source error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] update source error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.Println("[rsshub] add source success: ", source.ID)
|
||||
@@ -109,10 +109,10 @@ func (s *repoStorage) GetSources(ctx context.Context) (sources []RssSource, err
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("source not found")
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] get sources error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] get sources error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub] get sources success: %d", len(sources))
|
||||
logrus.WithContext(ctx).Debugf("[rsshub] get sources success: %d", len(sources))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func (s *repoStorage) GetSourceByRssHubFeedLink(ctx context.Context, rssHubFeedL
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] get source error: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] get source error: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -134,7 +134,7 @@ func (s *repoStorage) GetSourceByRssHubFeedLink(ctx context.Context, rssHubFeedL
|
||||
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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.DeleteSource: %v", err)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.New("source not found")
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (s *repoStorage) UpsertContent(ctx context.Context, content *RssContent) (e
|
||||
}
|
||||
err = s.orm.Create(content).Omit("id").Error
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.UpsertContent: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.UpsertContent: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -171,7 +171,7 @@ func (s *repoStorage) UpsertContent(ctx context.Context, content *RssContent) (e
|
||||
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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.DeleteSourceContents: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -185,7 +185,7 @@ func (s *repoStorage) IsContentHashIDExist(ctx context.Context, hashID string) (
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return false, nil
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.IsContentHashIDExist: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.IsContentHashIDExist: %v", err)
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
@@ -204,7 +204,7 @@ func (s *repoStorage) CreateSubscribe(ctx context.Context, gid, rssSourceID int6
|
||||
}
|
||||
err = s.orm.Create(&RssSubscribe{GroupID: gid, RssSourceID: rssSourceID}).Omit("id").Error
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.CreateSubscribe: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.CreateSubscribe: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -214,7 +214,7 @@ func (s *repoStorage) CreateSubscribe(ctx context.Context, gid, rssSourceID int6
|
||||
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)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.DeleteSubscribe error: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -228,7 +228,7 @@ func (s *repoStorage) GetSubscribeByID(ctx context.Context, gid int64, subscribe
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.GetSubscribeByID: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.GetSubscribeByID: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
@@ -247,7 +247,7 @@ func (s *repoStorage) GetSubscribedChannelsByGroupID(ctx context.Context, gid in
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.GetSubscribedChannelsByGroupID: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.GetSubscribedChannelsByGroupID: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -262,7 +262,7 @@ func (s *repoStorage) GetSubscribes(ctx context.Context) (res []*RssSubscribe, e
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Errorf("[rsshub] storage.GetSubscribes: %v", err)
|
||||
logrus.WithContext(ctx).Warnf("[rsshub] storage.GetSubscribes: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
|
||||
@@ -25,7 +25,7 @@ var (
|
||||
|
||||
var (
|
||||
// 注册插件
|
||||
engine = control.Register("rsshub", &ctrl.Options[*zero.Ctx]{
|
||||
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
// 默认不启动
|
||||
DisableOnDefault: false,
|
||||
Brief: "rsshub订阅姬",
|
||||
|
||||
@@ -4,7 +4,6 @@ package wife
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/color"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -15,7 +14,6 @@ import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
zbmath "github.com/FloatTech/floatbox/math"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
)
|
||||
|
||||
@@ -134,24 +132,8 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 马赛克生成
|
||||
// 高斯模糊生成
|
||||
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())
|
||||
blurRadius := float64(sizeList[level] * 3)
|
||||
return imgfactory.ToBytes(dst.Blur(blurRadius).Image())
|
||||
}
|
||||
|
||||
83
plugin/xhstext/xhstext.go
Normal file
83
plugin/xhstext/xhstext.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// Package xhstext 小红书文案
|
||||
package xhstext
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type xhstext struct {
|
||||
ID uint32 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
Label string `db:"label"`
|
||||
}
|
||||
|
||||
var db sql.Sqlite
|
||||
|
||||
func init() {
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "小红书文案",
|
||||
Help: "- 捧场\n- 有梗",
|
||||
PublicDataFolder: "Xhstext",
|
||||
})
|
||||
|
||||
// 初始化数据库
|
||||
initDB := fcext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
db = sql.New(en.DataFolder() + "xhstext.db")
|
||||
_, err := en.GetLazyData("xhstext.db", true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("all_texts", &xhstext{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
c, err := db.Count("all_texts")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
logrus.Infoln("[xhstext]加载", c, "条小红书文案")
|
||||
return true
|
||||
},
|
||||
)
|
||||
|
||||
// 捧场命令
|
||||
en.OnFullMatch("捧场", initDB).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
var x xhstext
|
||||
err := db.Find("all_texts", &x, "WHERE label = '捧场' ORDER BY RANDOM() LIMIT 1")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(x.Text))
|
||||
})
|
||||
|
||||
// 有梗命令
|
||||
en.OnFullMatch("有梗", initDB).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
var x xhstext
|
||||
err := db.Find("all_texts", &x, "WHERE label = '有梗' ORDER BY RANDOM() LIMIT 1")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(x.Text))
|
||||
})
|
||||
}
|
||||
3
run.bat
3
run.bat
@@ -3,5 +3,6 @@ go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go mod tidy
|
||||
::go build -ldflags="-s -w" -o ZeroBot-Plugin.exe
|
||||
go run main.go
|
||||
go generate main.go
|
||||
go run -ldflags "-s -w" main.go
|
||||
pause
|
||||
|
||||
3
run.sh
3
run.sh
@@ -3,4 +3,5 @@ go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go mod tidy
|
||||
#go build -ldflags="-s -w" -o ZeroBot-Plugin
|
||||
go run main.go
|
||||
go generate main.go
|
||||
go run -ldflags "-s -w" main.go
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
mkGoEnv ? pkgs.mkGoEnv,
|
||||
gomod2nix ? pkgs.gomod2nix,
|
||||
}: let
|
||||
goEnv = mkGoEnv { pwd = ./.; go = pkgs.go_1_20; };
|
||||
goEnv = mkGoEnv {
|
||||
pwd = ./.;
|
||||
go = pkgs.go_1_24;
|
||||
};
|
||||
in
|
||||
pkgs.mkShell {
|
||||
packages = [
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"0409": {
|
||||
"identity": {
|
||||
"name": "ZeroBot-Plugin",
|
||||
"version": "1.10.0.2279"
|
||||
"version": "1.10.18.2382"
|
||||
},
|
||||
"description": "",
|
||||
"minimum-os": "vista",
|
||||
@@ -36,23 +36,23 @@
|
||||
"#1": {
|
||||
"0000": {
|
||||
"fixed": {
|
||||
"file_version": "1.10.0.2279",
|
||||
"product_version": "v1.10.0",
|
||||
"timestamp": "2025-09-30T23:54:09+08:00"
|
||||
"file_version": "1.10.18.2382",
|
||||
"product_version": "v1.10.18",
|
||||
"timestamp": "2026-02-01T01:08:28+08:00"
|
||||
},
|
||||
"info": {
|
||||
"0409": {
|
||||
"Comments": "OneBot plugins based on ZeroBot",
|
||||
"CompanyName": "FloatTech",
|
||||
"FileDescription": "https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
"FileVersion": "1.10.0.2279",
|
||||
"FileVersion": "1.10.18.2382",
|
||||
"InternalName": "",
|
||||
"LegalCopyright": "© 2020 - 2025 FloatTech. All Rights Reserved.",
|
||||
"LegalCopyright": "© 2020 - 2026 FloatTech. All Rights Reserved.",
|
||||
"LegalTrademarks": "",
|
||||
"OriginalFilename": "ZBP.EXE",
|
||||
"PrivateBuild": "",
|
||||
"ProductName": "ZeroBot-Plugin",
|
||||
"ProductVersion": "v1.10.0",
|
||||
"ProductVersion": "v1.10.18",
|
||||
"SpecialBuild": ""
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user