mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-06 23:30:20 +00:00
Compare commits
408 Commits
v1.2.5
...
v1.5.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45e3383031 | ||
|
|
fc91b69b55 | ||
|
|
13b6614dc2 | ||
|
|
fec5e4d73f | ||
|
|
585add29fc | ||
|
|
1e48e59cb7 | ||
|
|
41911af09a | ||
|
|
37b95e9559 | ||
|
|
a7901745e8 | ||
|
|
da9f085a50 | ||
|
|
192c2a8bd6 | ||
|
|
e6c00e9b68 | ||
|
|
1faa5aa5d8 | ||
|
|
7e7191536a | ||
|
|
16ff1975ff | ||
|
|
b32c86863e | ||
|
|
d9b361f765 | ||
|
|
5b2810e6c5 | ||
|
|
15a5b347e8 | ||
|
|
477ffa825b | ||
|
|
84363b1513 | ||
|
|
01bf6f049b | ||
|
|
a8d93de000 | ||
|
|
2da5de3743 | ||
|
|
bf6bac7be6 | ||
|
|
394d2e4a08 | ||
|
|
0dd447e270 | ||
|
|
92c913e3eb | ||
|
|
5dea461963 | ||
|
|
f768081849 | ||
|
|
668418c48a | ||
|
|
2bf387a57c | ||
|
|
42a4726985 | ||
|
|
5c4b5359e0 | ||
|
|
8e3f56a3a2 | ||
|
|
91a837477a | ||
|
|
a2dfc54068 | ||
|
|
7ded2fe13a | ||
|
|
b6f1b27a81 | ||
|
|
621fd614ea | ||
|
|
be3e7c892c | ||
|
|
1f640b7644 | ||
|
|
987b505d32 | ||
|
|
4b2f23f093 | ||
|
|
1d52d0bafc | ||
|
|
e73db14976 | ||
|
|
fe8a677541 | ||
|
|
926cba8197 | ||
|
|
ee6e5db0a6 | ||
|
|
0c62d8dd07 | ||
|
|
d6e352b3b4 | ||
|
|
59e46be262 | ||
|
|
746c048550 | ||
|
|
a92c584997 | ||
|
|
7f4c6eb4ac | ||
|
|
fbeb048c44 | ||
|
|
9f748a8119 | ||
|
|
b9fd590095 | ||
|
|
430e210b3c | ||
|
|
706d54db76 | ||
|
|
9ac276767d | ||
|
|
29144348b3 | ||
|
|
2f91b11672 | ||
|
|
caf0ef88ac | ||
|
|
c8154db108 | ||
|
|
7ce6b5592a | ||
|
|
e1bc4fdf36 | ||
|
|
fd7f5f719f | ||
|
|
6678ca6c93 | ||
|
|
180e03e249 | ||
|
|
357f15eb01 | ||
|
|
a08704b60f | ||
|
|
03ba81a9c5 | ||
|
|
2933962df8 | ||
|
|
4f248c4dc7 | ||
|
|
14096f24ba | ||
|
|
c0b75accf4 | ||
|
|
cb1b7d5da7 | ||
|
|
c8072171f0 | ||
|
|
485f6d4cef | ||
|
|
2b85097e30 | ||
|
|
0904789291 | ||
|
|
fda69793a5 | ||
|
|
3c22aaf99d | ||
|
|
151a5d480f | ||
|
|
88d136626d | ||
|
|
170f5bba79 | ||
|
|
c4cbb0cd59 | ||
|
|
0fa04070f1 | ||
|
|
f8bea241a2 | ||
|
|
bb6b2e4b29 | ||
|
|
557251a679 | ||
|
|
696783b0fe | ||
|
|
6eb29d2cc9 | ||
|
|
4b4cafcda8 | ||
|
|
ed2ed8d968 | ||
|
|
fbb387bd9f | ||
|
|
0db2db482f | ||
|
|
af2fe727fc | ||
|
|
a7387dcf22 | ||
|
|
5ce44fb161 | ||
|
|
9086b9c3ca | ||
|
|
4837c5387a | ||
|
|
5d73216238 | ||
|
|
5053091e44 | ||
|
|
6319ed0473 | ||
|
|
c67c109af6 | ||
|
|
b3cdb1464b | ||
|
|
3c01c3f0ba | ||
|
|
07d541be20 | ||
|
|
4a0dc59585 | ||
|
|
b1dd8f52e8 | ||
|
|
6907fe230f | ||
|
|
f2e4071b90 | ||
|
|
452f5e5f83 | ||
|
|
c94b9f54ce | ||
|
|
e993f93cf4 | ||
|
|
e9fac38c1b | ||
|
|
31a49b8ff9 | ||
|
|
7831cdf10c | ||
|
|
c0f176f0af | ||
|
|
dc96a557eb | ||
|
|
7a8c915e62 | ||
|
|
dec42cc72b | ||
|
|
92c9d1d2ce | ||
|
|
de017fcd27 | ||
|
|
1229f62abd | ||
|
|
512852b817 | ||
|
|
5a087000a9 | ||
|
|
6b56d6649e | ||
|
|
5081aab497 | ||
|
|
bbb4afde53 | ||
|
|
d28495c3eb | ||
|
|
1785e0c4a3 | ||
|
|
1e93e75aac | ||
|
|
a3ed7eeee2 | ||
|
|
c3582637df | ||
|
|
3b277b0eb0 | ||
|
|
5e0991681f | ||
|
|
354fbb7cdd | ||
|
|
a166d06096 | ||
|
|
b8a6e07095 | ||
|
|
a8fba6e7b5 | ||
|
|
17a8c10f8c | ||
|
|
7ccd29faac | ||
|
|
d432e48cce | ||
|
|
19091319cc | ||
|
|
d29e12a92c | ||
|
|
5db03b0441 | ||
|
|
f8c7e2bf6d | ||
|
|
a7fdc6a88f | ||
|
|
4aaf5b0779 | ||
|
|
6150e4c736 | ||
|
|
9a3b4b3ecb | ||
|
|
cbaeb4d5f2 | ||
|
|
592c306aa0 | ||
|
|
136e6bddf4 | ||
|
|
0e8bef0541 | ||
|
|
9d8c52303e | ||
|
|
e6ae7df546 | ||
|
|
5b57a759be | ||
|
|
cc96eeae32 | ||
|
|
484fef1228 | ||
|
|
ba4ca11c83 | ||
|
|
9372902348 | ||
|
|
0cc9420570 | ||
|
|
18fa48d283 | ||
|
|
9034fedbd0 | ||
|
|
ec3b6ec5fa | ||
|
|
8cc2a4174e | ||
|
|
8a0014928d | ||
|
|
228ca7f9c0 | ||
|
|
c0fa7efb27 | ||
|
|
3553683bb1 | ||
|
|
ccb58e0a6c | ||
|
|
93253e2188 | ||
|
|
e34bcc9bbd | ||
|
|
72169e3a4d | ||
|
|
41c499840f | ||
|
|
f5cef170f0 | ||
|
|
d7922a7c9b | ||
|
|
23fc77e8e1 | ||
|
|
51f3eda09a | ||
|
|
6ec08a5227 | ||
|
|
4855f694cb | ||
|
|
eaef37a831 | ||
|
|
b182ff36bb | ||
|
|
c4e543449c | ||
|
|
c76d9d4461 | ||
|
|
dfd184724b | ||
|
|
fef254031e | ||
|
|
89c4e59bf1 | ||
|
|
2e9acd3276 | ||
|
|
5cab59c93f | ||
|
|
ebfb5878a1 | ||
|
|
de6b11aa22 | ||
|
|
9e7e7159e8 | ||
|
|
00c909271b | ||
|
|
7401a0cbec | ||
|
|
a9327d1774 | ||
|
|
9e99ef1348 | ||
|
|
5b4b9fdb01 | ||
|
|
d2998c4908 | ||
|
|
4ab968d563 | ||
|
|
9b26eea754 | ||
|
|
a6bd717971 | ||
|
|
f2914adb65 | ||
|
|
aa5a426aac | ||
|
|
fef8144187 | ||
|
|
d8a429d3b3 | ||
|
|
56e53b75a5 | ||
|
|
f89b6f5feb | ||
|
|
ec513e8893 | ||
|
|
35d6792d2e | ||
|
|
74387aae2d | ||
|
|
959043962d | ||
|
|
4efb71bafb | ||
|
|
6fd0bc0445 | ||
|
|
176a2eb392 | ||
|
|
1a85deb36e | ||
|
|
5b409ff3de | ||
|
|
a9e13d3a92 | ||
|
|
0698d8e3b1 | ||
|
|
8e4c496b54 | ||
|
|
27054b9722 | ||
|
|
bcad2c4998 | ||
|
|
aae2bd4884 | ||
|
|
006ef6f672 | ||
|
|
7be1a61347 | ||
|
|
1ef48f6cd6 | ||
|
|
a9a061a4bb | ||
|
|
14ed8b7af7 | ||
|
|
d17b8fa720 | ||
|
|
68980a69b5 | ||
|
|
636f14c450 | ||
|
|
b066bc37b3 | ||
|
|
9ac43fecf8 | ||
|
|
d6ff14167d | ||
|
|
5837a765f1 | ||
|
|
1bfb76a4b3 | ||
|
|
2a78a602e2 | ||
|
|
884b0e4226 | ||
|
|
4e819eb5d9 | ||
|
|
e3a50cc014 | ||
|
|
25ab8c9234 | ||
|
|
901e680fa4 | ||
|
|
82768fff59 | ||
|
|
87e3297904 | ||
|
|
81a4297eb1 | ||
|
|
17f5b52931 | ||
|
|
2250adf854 | ||
|
|
5cd46b3926 | ||
|
|
6e2b10b788 | ||
|
|
5e301ccaaf | ||
|
|
206a38efab | ||
|
|
cdf844be52 | ||
|
|
70cc28c191 | ||
|
|
35282fba6c | ||
|
|
e43f8e594d | ||
|
|
21988fab76 | ||
|
|
2f3823abe2 | ||
|
|
2c545e7b7f | ||
|
|
22f2200778 | ||
|
|
2f63253ec0 | ||
|
|
be7e8134f9 | ||
|
|
b85408e3e5 | ||
|
|
4828451f9e | ||
|
|
b3b50e1353 | ||
|
|
95e8bf2f55 | ||
|
|
cde7669c0b | ||
|
|
ff4a33c51c | ||
|
|
06cf6f84aa | ||
|
|
556f6f134f | ||
|
|
b1ab7ef118 | ||
|
|
e5fd108a9c | ||
|
|
5a67bf2417 | ||
|
|
cb020c1bbd | ||
|
|
bf75b29e33 | ||
|
|
d730fd9cab | ||
|
|
a862e5be7c | ||
|
|
ebca124c86 | ||
|
|
3b7803a81b | ||
|
|
b7b9d92148 | ||
|
|
44575fb19e | ||
|
|
f181a4b9cd | ||
|
|
77e5d8b0c2 | ||
|
|
edd9feb8f8 | ||
|
|
81d6a06dbe | ||
|
|
8afbc67bf7 | ||
|
|
a27132f907 | ||
|
|
183be05d82 | ||
|
|
bccf789714 | ||
|
|
55944dddb3 | ||
|
|
f67932cc56 | ||
|
|
6d633fac6a | ||
|
|
86fc5c51c8 | ||
|
|
156e9f07ad | ||
|
|
1ba4722fc7 | ||
|
|
54c9857219 | ||
|
|
ea56c7d0d2 | ||
|
|
0cbe43df97 | ||
|
|
1f941d883a | ||
|
|
f5b3e423fb | ||
|
|
6c7f81ca55 | ||
|
|
3911b5ed82 | ||
|
|
f38f3ab69c | ||
|
|
846db6f063 | ||
|
|
ff068a05b0 | ||
|
|
051b7dd182 | ||
|
|
11870aeed6 | ||
|
|
9bcff82d9c | ||
|
|
309efe8cd8 | ||
|
|
bf54789f0f | ||
|
|
01e527abdb | ||
|
|
db6b558c75 | ||
|
|
9a792eb144 | ||
|
|
44e99664a3 | ||
|
|
9f3dd37bf0 | ||
|
|
f5936d9cb7 | ||
|
|
27e69ef022 | ||
|
|
6262aab6bd | ||
|
|
4781bc8eb7 | ||
|
|
b233c4b638 | ||
|
|
0a0cc807dc | ||
|
|
feeeb63e52 | ||
|
|
5c620d6268 | ||
|
|
a469000d7a | ||
|
|
0e15ac78b2 | ||
|
|
d9e195ccd0 | ||
|
|
cf52997279 | ||
|
|
88318a7151 | ||
|
|
91f522b666 | ||
|
|
1895f8815e | ||
|
|
7be5f52be4 | ||
|
|
0cfb2e4e06 | ||
|
|
5ccf753af3 | ||
|
|
bfcf3cac91 | ||
|
|
bc3d7bc278 | ||
|
|
7cf767f344 | ||
|
|
7aed9a2c89 | ||
|
|
454196a462 | ||
|
|
1597ba7128 | ||
|
|
480523ff27 | ||
|
|
7ec7ab8682 | ||
|
|
ba2d011d48 | ||
|
|
504e6cd1cc | ||
|
|
b8f3700fe4 | ||
|
|
b2cff862bb | ||
|
|
dc348f8500 | ||
|
|
8c40293fed | ||
|
|
48deaf3aca | ||
|
|
6932643788 | ||
|
|
7f972e3d68 | ||
|
|
edb0880999 | ||
|
|
45f0f5cd6c | ||
|
|
e468ac1933 | ||
|
|
55b6b40acf | ||
|
|
5f1190f72e | ||
|
|
b0fbd6507d | ||
|
|
598a664d30 | ||
|
|
211f0a667d | ||
|
|
28fb788778 | ||
|
|
628830fbf5 | ||
|
|
7d235d0077 | ||
|
|
861b0b6cef | ||
|
|
9986c57727 | ||
|
|
f1c9e2331c | ||
|
|
7c1ddc6ab1 | ||
|
|
44ad78761b | ||
|
|
bd6925f2f1 | ||
|
|
3838d74cb8 | ||
|
|
eaad8beb7b | ||
|
|
14acdfdbc3 | ||
|
|
a5fe7a5b40 | ||
|
|
61df3c55b5 | ||
|
|
eb0059c1a3 | ||
|
|
4ca5038ae9 | ||
|
|
121403231a | ||
|
|
b945338a8d | ||
|
|
ae5ea542a0 | ||
|
|
fe95dc8201 | ||
|
|
1eefb4e610 | ||
|
|
8660d8d990 | ||
|
|
37033fe48d | ||
|
|
30665ad8c6 | ||
|
|
f9e4b8db76 | ||
|
|
c486a210e4 | ||
|
|
0cd01959a0 | ||
|
|
d5ac9f7920 | ||
|
|
6b2dd112a6 | ||
|
|
01abfab133 | ||
|
|
e2a56872dc | ||
|
|
6f22a9c4bc | ||
|
|
a2426de70c | ||
|
|
ed7bbf54a7 | ||
|
|
69394377d0 | ||
|
|
8f20487a15 | ||
|
|
fae24db2df | ||
|
|
f8fb791d8f | ||
|
|
f320d9e1e5 | ||
|
|
18bd34fad2 | ||
|
|
cf72d0b36a | ||
|
|
c3722b0a6c | ||
|
|
3af701e803 | ||
|
|
bc4b2e89db | ||
|
|
3cbb589d2c | ||
|
|
63ef93a9f9 | ||
|
|
8c943d2c01 |
10
.github/workflows/nightly.yml
vendored
10
.github/workflows/nightly.yml
vendored
@@ -24,13 +24,13 @@ jobs:
|
||||
goarch: arm64
|
||||
fail-fast: true
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@master
|
||||
- name: Setup Go environment
|
||||
uses: actions/setup-go@v2.1.3
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
- name: Cache downloaded module
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@master
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
export CGO_ENABLED=0
|
||||
go build -o "output/$BINARY_NAME" -trimpath -ldflags "$LD_FLAGS" .
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@master
|
||||
if: ${{ !github.head_ref }}
|
||||
with:
|
||||
name: ${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
|
||||
9
.github/workflows/pull.yml
vendored
9
.github/workflows/pull.yml
vendored
@@ -6,12 +6,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@master
|
||||
@@ -28,9 +28,6 @@ jobs:
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
# only-new-issues: true
|
||||
|
||||
# Optional: if set to true then the action will use pre-installed Go.
|
||||
skip-go-installation: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
||||
# skip-pkg-cache: true
|
||||
|
||||
|
||||
7
.github/workflows/push.yml
vendored
7
.github/workflows/push.yml
vendored
@@ -6,19 +6,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@master
|
||||
with:
|
||||
version: latest
|
||||
args: --issues-exit-code=0
|
||||
skip-go-installation: true
|
||||
- name: Commit back
|
||||
continue-on-error: true
|
||||
run: |
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -9,17 +9,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: '1.17'
|
||||
go-version: '1.18'
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
uses: goreleaser/goreleaser-action@master
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
|
||||
BIN
.github/yaya.jpg
vendored
BIN
.github/yaya.jpg
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB |
BIN
.github/黒金.jpg
vendored
Normal file
BIN
.github/黒金.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 191 KiB |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,4 +5,5 @@ plugins/*.dll
|
||||
.vscode
|
||||
go-zero*
|
||||
nohup.out
|
||||
zerobot
|
||||
zerobot
|
||||
ZeroBot-Plugin*
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
linters-settings:
|
||||
errcheck:
|
||||
ignore: fmt:.*,io/ioutil:^Read.*
|
||||
ignore: fmt:.*
|
||||
ignoretests: true
|
||||
|
||||
goimports:
|
||||
local-prefixes: github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- exitAfterDefer
|
||||
|
||||
forbidigo:
|
||||
# Forbid the following identifiers
|
||||
forbid:
|
||||
@@ -66,6 +62,7 @@ run:
|
||||
tests: false
|
||||
skip-dirs:
|
||||
- order
|
||||
go: '1.18'
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
|
||||
13
config.go
Normal file
13
config.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
)
|
||||
|
||||
type zbpcfg struct {
|
||||
Z zero.Config `json:"zero"`
|
||||
W []*driver.WSClient `json:"ws"`
|
||||
}
|
||||
|
||||
var config zbpcfg
|
||||
2
data
2
data
Submodule data updated: 0090d93bda...5ce4b48c12
74
go.mod
74
go.mod
@@ -1,64 +1,76 @@
|
||||
module github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
go 1.17
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/FloatTech/AnimeAPI v1.2.5
|
||||
github.com/FloatTech/sqlite v0.1.0
|
||||
github.com/FloatTech/zbputils v1.2.5
|
||||
github.com/antchfx/htmlquery v1.2.4
|
||||
github.com/FloatTech/AnimeAPI v1.4.1-0.20220613042537-0adf8c5616ec
|
||||
github.com/FloatTech/sqlite v0.3.2
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220708120020-996c0e071fca
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220708133204-3fa802132b81
|
||||
github.com/antchfx/htmlquery v1.2.5
|
||||
github.com/corona10/goimagehash v1.0.3
|
||||
github.com/fogleman/gg v1.3.0
|
||||
github.com/fumiama/cron v1.3.0
|
||||
github.com/fumiama/go-base16384 v1.2.1
|
||||
github.com/fumiama/go-registry v0.0.2
|
||||
github.com/fumiama/gofastTEA v0.0.6
|
||||
github.com/fumiama/go-base16384 v1.5.4
|
||||
github.com/fumiama/go-registry v0.1.6
|
||||
github.com/fumiama/gofastTEA v0.0.10
|
||||
github.com/fumiama/gotracemoe v0.0.3
|
||||
github.com/fumiama/sqlite3 v1.14.6
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/logoove/sqlite v1.13.0
|
||||
github.com/jozsefsallai/gophersauce v1.0.1
|
||||
github.com/lucas-clemente/quic-go v0.27.2
|
||||
github.com/mroth/weightedrand v0.4.1
|
||||
github.com/shirou/gopsutil/v3 v3.21.12
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pkumza/numcn v1.0.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.3
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/tidwall/gjson v1.13.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220208041536-d463c1c92bb4
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
github.com/tidwall/gjson v1.14.1
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220610070647-9eeffcb277ee
|
||||
gitlab.com/gomidi/midi/v2 v2.0.17
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c // indirect
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
|
||||
github.com/antchfx/xpath v1.2.0 // indirect
|
||||
github.com/antchfx/xpath v1.2.1 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/marten-seemann/qpack v0.2.1 // indirect
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 // indirect
|
||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.9 // indirect
|
||||
golang.org/x/tools v0.1.1 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.35.22 // indirect
|
||||
modernc.org/ccgo/v3 v3.15.13 // indirect
|
||||
modernc.org/libc v1.14.5 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
modernc.org/libc v1.16.8 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.0.5 // indirect
|
||||
modernc.org/opt v0.1.1 // indirect
|
||||
modernc.org/sqlite v1.14.6 // indirect
|
||||
modernc.org/strutil v1.1.1 // indirect
|
||||
modernc.org/token v1.0.0 // indirect
|
||||
modernc.org/memory v1.1.1 // indirect
|
||||
)
|
||||
|
||||
421
go.sum
421
go.sum
@@ -1,23 +1,43 @@
|
||||
github.com/FloatTech/AnimeAPI v1.2.5 h1:X0NLJSl9o63vRwGRPn/XiojOOBqZRbY94TxPEvhiVRo=
|
||||
github.com/FloatTech/AnimeAPI v1.2.5/go.mod h1:nJpebBjTNUpr4cV0bR0Xu54/SP78+iN7hJ2EfQWbM7M=
|
||||
github.com/FloatTech/bot-manager v1.0.0/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
|
||||
github.com/FloatTech/sqlite v0.1.0 h1:Geh6Z+DWZXmyXVOhM0U2oXT7b1Ob6sQtuyjInk+MCUk=
|
||||
github.com/FloatTech/sqlite v0.1.0/go.mod h1:XS0oeSqtH6lFzpPRiDE9fV6+zMcuUF5/6o+tQVO1QZE=
|
||||
github.com/FloatTech/zbputils v1.2.5 h1:/JyN6ear5PPpBjrjQEQT0/8mPBMJYBswLiNIzfmGYU8=
|
||||
github.com/FloatTech/zbputils v1.2.5/go.mod h1:e9e8998yQkzS24IqZ8jLUssTk607hD/Tj3zGyBikIIc=
|
||||
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb h1:Rkj28fqIwGx/EgBzRYtpmJRfH6wqVn7cNdc7aJ0QE4M=
|
||||
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqeit+C/eaWGb4MKQ3z3gN6pRpBU5RMtp5so=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/FloatTech/AnimeAPI v1.4.1-0.20220613042537-0adf8c5616ec h1:Hl/BxaQoQFEJUIGmdhR0NyBvZChb7qkfCrF916bNxnI=
|
||||
github.com/FloatTech/AnimeAPI v1.4.1-0.20220613042537-0adf8c5616ec/go.mod h1:MrCZ7P6WvF0JWHMeedAx6fVm5BP1s6/RUy0r0Jvqrds=
|
||||
github.com/FloatTech/sqlite v0.3.2 h1:iTg2ZKnzjjZAdlSN3hXmpCBn15odc4Ud484OoM3yXGA=
|
||||
github.com/FloatTech/sqlite v0.3.2/go.mod h1:VFtLofV5qxw5eBneZRbWwD451SLSm50o9J3J43iB1iw=
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220708120020-996c0e071fca h1:uLeGuRiNI7ikVBi8FqKvYVgpDOwrE3XVNKDENERkN64=
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220708120020-996c0e071fca/go.mod h1:5FDkrlVaQCxUfeqH7XJPTfej0q+y9fzImhvZI4ofu9Y=
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220708131751-1c1d07981dd7 h1:0GsqNdhqa8ovJsfwY75bYM+w2p0L9AcuR7v7J9RxygY=
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220708131751-1c1d07981dd7/go.mod h1:sae5x2kfCC6bcJy8hb0mgcJzB/27YALgsDlrrB2ifso=
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220708133204-3fa802132b81 h1:SaSp9E3zX4cKp2H1/G3qPvLAMTELmtP5fnm/tW3YeI8=
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220708133204-3fa802132b81/go.mod h1:sae5x2kfCC6bcJy8hb0mgcJzB/27YALgsDlrrB2ifso=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c h1:cNPOdTNiVwxLpROLjXCgbIPvdkE+BwvxDvgmdYmWx6Q=
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c/go.mod h1:KqZzu7slNKROh3TSYEH/IUMG6f4M+1qubZ5e52QypsE=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc/go.mod h1:OMmITAib6POA37xCichWM0aRnoVpSMZO1rB/G01wrr0=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/antchfx/htmlquery v1.2.4 h1:qLteofCMe/KGovBI6SQgmou2QNyedFUW+pE+BpeZ494=
|
||||
github.com/antchfx/htmlquery v1.2.4/go.mod h1:2xO6iu3EVWs7R2JYqBbp8YzG50gj/ofqs5/0VZoDZLc=
|
||||
github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
|
||||
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antchfx/htmlquery v1.2.5 h1:1lXnx46/1wtv1E/kzmH8vrfMuUKYgkdDBA9pIdMJnk4=
|
||||
github.com/antchfx/htmlquery v1.2.5/go.mod h1:2MCVBzYVafPBmKbrmwB9F5xdd+IEgRY61ci2oOsOQVw=
|
||||
github.com/antchfx/xpath v1.2.1 h1:qhp4EW6aCOVr5XIkT+l6LJ9ck/JsUH/yyauNgTQkBF8=
|
||||
github.com/antchfx/xpath v1.2.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
|
||||
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -25,246 +45,383 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6RO
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
|
||||
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
|
||||
github.com/fumiama/go-base16384 v1.2.1 h1:6OGprW8g/95m2ocmryHi8mipZ7bx9StFMZDKEqLvMiA=
|
||||
github.com/fumiama/go-base16384 v1.2.1/go.mod h1:1HTC0QFL7BjS0DuO5Qm+fBYKQkHqmAapLbRpCxrhPXQ=
|
||||
github.com/fumiama/go-registry v0.0.2 h1:2EoZwZpqI7YhkQ1FnuAPvALYPpvUtbsCqk879+r7ehs=
|
||||
github.com/fumiama/go-registry v0.0.2/go.mod h1:QkcmmHuw1y6y/w7/HiH1c9yjBw5Zt+6EER6YJKl9xh8=
|
||||
github.com/fumiama/gofastTEA v0.0.6 h1:Yni3MXDbJVa/c4CecgdZDgCJK+fLdvGph+OBqY2mtiI=
|
||||
github.com/fumiama/gofastTEA v0.0.6/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
|
||||
github.com/fumiama/go-base16384 v1.5.4 h1:UKx925X7cTsqsVWBlBLBs1v38epFT/q3AGjvyP5E0PM=
|
||||
github.com/fumiama/go-base16384 v1.5.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||
github.com/fumiama/go-registry v0.1.6 h1:Ee/tXCCIR/xt8celhbbw0W/xDMdhAXLwy2YFBB/LWFk=
|
||||
github.com/fumiama/go-registry v0.1.6/go.mod h1:dIUVbiOgfk9oZcsgwDvNLC72i+ctibVukSXR/9bLviI=
|
||||
github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoGhhQ=
|
||||
github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
|
||||
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
|
||||
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/fumiama/sqlite3 v1.14.6 h1:+e+iygyiDXQJVi7xeXIviBvR7hAc5y20WA9hRwfKn10=
|
||||
github.com/fumiama/sqlite3 v1.14.6/go.mod h1:Xx9a2/OtHuy9pBjow0N+bE/RhNeZ7zZz5xh25vqbA5A=
|
||||
github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8=
|
||||
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
|
||||
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/logoove/sqlite v1.13.0 h1:XM7QKK9R3tm8o7bI75R3zmwYBFQ5S3Jqg+XCaqsAMQQ=
|
||||
github.com/logoove/sqlite v1.13.0/go.mod h1:MRpE/o3qQhT7AgfIdnBue5c63+//xT+KXV0gHeVAUAg=
|
||||
github.com/lucas-clemente/quic-go v0.27.2 h1:zsMwwniyybb8B/UDNXRSYee7WpQJVOcjQEGgpw2ikXs=
|
||||
github.com/lucas-clemente/quic-go v0.27.2/go.mod h1:vXgO/11FBSKM+js1NxoaQ/bPtVFYfB7uxhfHXyMhl1A=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
|
||||
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ=
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
|
||||
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
|
||||
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA=
|
||||
github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil/v3 v3.22.3 h1:UebRzEomgMpv61e3hgD1tGooqX5trFbdU/ehphbHd00=
|
||||
github.com/shirou/gopsutil/v3 v3.22.3/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
||||
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
||||
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
||||
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
||||
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
||||
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
||||
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
||||
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
||||
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
|
||||
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M=
|
||||
github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
|
||||
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||
github.com/wdvxdr1123/ZeroBot v1.3.2/go.mod h1:i2DIqQjtjE+3gvVi9r9sc+QpNaUuyTXx/HNXXayIpwI=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.1/go.mod h1:7t9m4vDZPwWAmzKlhP6IvUoisOIiqNdm/3AJgiY3+ew=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220208041536-d463c1c92bb4 h1:T/m7vDUFKdLd0xfSZHVPQGaRZ73nwPzidLW7hTn25mg=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220208041536-d463c1c92bb4/go.mod h1:NwXIp7PgjV+kUALMXJ4v4/3QcsRSOodtjhLekuPXFog=
|
||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220610070647-9eeffcb277ee h1:b2f+KLhZv+BCMQZuwMJvhKQOrz5YXzOduHC3G1DjQR0=
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220610070647-9eeffcb277ee/go.mod h1:LJ+VOf523i3IrykuLK53UEeWqnAclRL5d2wGT4sS4Zk=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
gitlab.com/gomidi/midi/v2 v2.0.17 h1:kf16wNwFFOskl0trvarOwMuZUQICdIGn37LP9QqIRuo=
|
||||
gitlab.com/gomidi/midi/v2 v2.0.17/go.mod h1:quTyMKSQ4Klevxu6gY4gy2USbeZra0fV5SalndmPfsY=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 h1:kACShD3qhmr/3rLmg1yXyt+N4HcwutKyPRB93s54TIU=
|
||||
golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd h1:9NbNcTg//wfC5JskFW4Z3sqwVnjmJKHxLAol1bW2qgw=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 h1:0FB83qp0AzVJm+0wcIlauAjJ+tNdh7jLuacRYCIVv7s=
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc=
|
||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
|
||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
@@ -280,8 +437,10 @@ modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g
|
||||
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.22 h1:BzShpwCAP7TWzFppM4k2t03RhXhgYqaibROWkrWq7lE=
|
||||
modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
|
||||
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
|
||||
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
|
||||
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
|
||||
@@ -320,17 +479,14 @@ modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTS
|
||||
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
|
||||
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
|
||||
modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4=
|
||||
modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
|
||||
modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
|
||||
modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8=
|
||||
modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I=
|
||||
modernc.org/ccgo/v3 v3.15.13 h1:hqlCzNJTXLrhS70y1PqWckrF9x1btSQRC7JFuQcBg5c=
|
||||
modernc.org/ccgo/v3 v3.15.13/go.mod h1:QHtvdpeODlXjdK3tsbpyK+7U9JV4PQsrPGIbtmc0KfY=
|
||||
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
|
||||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/ccorpus v1.11.4 h1:YOmQBBzE8GC/puUx76D5j/gJYIZQsydrh6VMJVfXF0M=
|
||||
modernc.org/ccorpus v1.11.4/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
|
||||
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
|
||||
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
|
||||
@@ -372,23 +528,22 @@ modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
|
||||
modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
|
||||
modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34=
|
||||
modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
|
||||
modernc.org/libc v1.14.5 h1:DAHvwGoVRDZs5iJXnX9RJrgXSsorupCWmJ2ac964Owk=
|
||||
modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
|
||||
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
|
||||
modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
|
||||
modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o=
|
||||
modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
|
||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
|
||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
|
||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
|
||||
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.14.6 h1:Jt5P3k80EtDBWaq1beAxnWW+5MdHXbZITujnRS7+zWg=
|
||||
modernc.org/sqlite v1.14.6/go.mod h1:yiCvMv3HblGmzENNIaNtFhfaNIwcla4u2JQEwJPzfEc=
|
||||
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/tcl v1.11.0/go.mod h1:zsTUpbQ+NxQEjOjCUlImDLPv1sG8Ww0qp66ZvyOxCgw=
|
||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.3.0/go.mod h1:+mvgLH814oDjtATDdT3rs84JnUIpkvAF5B8AVkNlE2g=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
|
||||
45
kanban/banner.go
Normal file
45
kanban/banner.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package kanban
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fumiama/go-registry"
|
||||
)
|
||||
|
||||
var (
|
||||
info = [...]string{
|
||||
"* OneBot + ZeroBot + Golang",
|
||||
"* Version 1.5.0-beta4 - 2022-07-13 12:24:13 +0800 CST",
|
||||
"* Copyright © 2020 - 2022 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
// Banner ...
|
||||
Banner = strings.Join(info[:], "\n")
|
||||
reg = registry.NewRegReader("reilia.fumiama.top:32664", "fumiama")
|
||||
)
|
||||
|
||||
// PrintBanner ...
|
||||
func PrintBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
"\n", Banner, "\n",
|
||||
"----------------------[ZeroBot-公告栏]----------------------",
|
||||
"\n", Kanban(), "\n",
|
||||
"============================================================\n\n",
|
||||
)
|
||||
}
|
||||
|
||||
// Kanban ...
|
||||
func Kanban() string {
|
||||
err := reg.Connect()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
defer reg.Close()
|
||||
text, err := reg.Get("ZeroBot-Plugin/kanban")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return text
|
||||
}
|
||||
6
kanban/init.go
Normal file
6
kanban/init.go
Normal file
@@ -0,0 +1,6 @@
|
||||
// Package kanban 打印版本信息
|
||||
package kanban
|
||||
|
||||
func init() {
|
||||
PrintBanner()
|
||||
}
|
||||
330
main.go
330
main.go
@@ -1,125 +1,184 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
|
||||
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 在最前打印 banner
|
||||
|
||||
// 插件控制
|
||||
// webctrl "github.com/FloatTech/zbputils/control/web" // web 后端控制
|
||||
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
|
||||
// ----------------------插件优先级按顺序从高到低---------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------高优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv高优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv高优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv高优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
// 词库类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_reply" // 人工智能回复
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri" // ATRI词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat" // 基础词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
|
||||
|
||||
// 实用类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_b14" // base16384加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager" // 群管
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh" // 拼音首字母缩写释义工具
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_runcode" // 在线运行代码
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage" // 统计睡眠时间
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation" // 翻译
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage" // 统计睡眠时间
|
||||
|
||||
// 娱乐类
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf" // 鬼东西
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review" // 哀伤雪刃吧推书记录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_cangtoushi" // 藏头诗
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_chouxianghua" // 说抽象话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_cpstory" // cp短打
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_curse" // 骂人
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_funny" // 笑话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_gif" // 制图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_hs" // 炉石
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_jandan" // 煎蛋网无聊图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_juejuezi" // 绝绝子生成器
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft" // MCSManager
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_moyu" // 摸鱼
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_music" // 点歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_novel" // 铅笔小说网搜索
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_score" // 分数
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shadiao" // 沙雕app
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_wangyiyun" // 网易云音乐热评
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
|
||||
|
||||
// b站相关
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili" // 查询b站用户信息
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili_parse" // b站视频链接解析
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager" // 群管
|
||||
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili_push" // b站推送
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_diana" // 嘉心糖发病
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
|
||||
|
||||
// 二次元图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_acgimage" // 随机图片与AI点评
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_aiwife" // 随机老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_coser" // 三次元小姐姐
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_danbooru" // DeepDanbooru二次元图标签识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder" // 关键字搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_lolicon" // lolicon 随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativesetu" // 本地涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativewife" // 本地老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nsfw" // nsfw图片识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao" // 以图搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_scale" // 叔叔的AI二次元图片放大
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_setutime" // 来份涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_tracemoe" // 搜番
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation" // vtb语录
|
||||
_ "github.com/FloatTech/zbputils/job" // 定时指令触发器
|
||||
|
||||
// 以下为内置依赖,勿动
|
||||
"github.com/fumiama/go-registry"
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^高优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^高优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^高优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------高优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------中优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv中优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv中优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv中优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // 查询b站用户信息
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_parse" // b站视频链接解析
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/book_review" // 哀伤雪刃吧推书记录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi" // 藏头诗
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chouxianghua" // 说抽象话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle" // 漂流瓶
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/epidemic" // 城市疫情查询
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/font" // 渲染任意文字到图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/fortune" // 运势
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/funny" // 笑话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/genshin" // 原神抽卡
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif" // 制图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/guessmusic" // 猜歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu" // 摸鱼
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu_calendar" // 摸鱼人日历
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/music" // 点歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativesetu" // 本地涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativewife" // 本地老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nbnhhsh" // 拼音首字母缩写释义工具
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/novel" // 铅笔小说网搜索
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale" // 叔叔的AI二次元图片放大
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/setutime" // 来份涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao" // 沙雕app
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tarot" // 抽塔罗牌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou" // 舔狗日记
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe" // 搜番
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation" // 翻译
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
||||
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^中优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^中优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^中优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------中优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------低优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv低优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv低优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv低优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse" // 骂人
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^低优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^低优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^低优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------低优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// -----------------------以下为内置依赖,勿动------------------------ //
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
var (
|
||||
contents = []string{
|
||||
"* OneBot + ZeroBot + Golang",
|
||||
"* Version 1.2.5 - 2022-01-30 20:06:00 +0800 CST",
|
||||
"* Copyright © 2020 - 2021 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
nicks = []string{"ATRI", "atri", "亚托莉", "アトリ"}
|
||||
banner = strings.Join(contents, "\n")
|
||||
token *string
|
||||
url *string
|
||||
adana *string
|
||||
prefix *string
|
||||
reg = registry.NewRegReader("reilia.fumiama.top:32664", "fumiama")
|
||||
// -----------------------以上为内置依赖,勿动------------------------ //
|
||||
)
|
||||
|
||||
func init() {
|
||||
sus := make([]int64, 0, 16)
|
||||
// 解析命令行参数
|
||||
d := flag.Bool("d", false, "Enable debug level log and higher.")
|
||||
w := flag.Bool("w", false, "Enable warning level log and higher.")
|
||||
h := flag.Bool("h", false, "Display this help.")
|
||||
// 解析命令行参数,输入 `-g 监听地址:端口` 指定 gui 访问地址,默认 127.0.0.1:3000
|
||||
// g := flag.String("g", "127.0.0.1:3000", "Set web gui listening address.")
|
||||
|
||||
// 直接写死 AccessToken 时,请更改下面第二个参数
|
||||
token = flag.String("t", "", "Set AccessToken of WSClient.")
|
||||
token := flag.String("t", "", "Set AccessToken of WSClient.")
|
||||
// 直接写死 URL 时,请更改下面第二个参数
|
||||
url = flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
|
||||
url := flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
|
||||
// 默认昵称
|
||||
adana = flag.String("n", "椛椛", "Set default nickname.")
|
||||
prefix = flag.String("p", "/", "Set command prefix.")
|
||||
adana := flag.String("n", "椛椛", "Set default nickname.")
|
||||
prefix := flag.String("p", "/", "Set command prefix.")
|
||||
runcfg := flag.String("c", "", "Run from config file.")
|
||||
save := flag.String("s", "", "Save default config to file and exit.")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *h {
|
||||
printBanner()
|
||||
kanban.PrintBanner()
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
@@ -132,53 +191,70 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// 启用 gui
|
||||
// webctrl.InitGui(*g)
|
||||
}
|
||||
|
||||
func printBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
"\n", banner, "\n",
|
||||
"----------------------[ZeroBot-公告栏]----------------------",
|
||||
"\n", getKanban(), "\n",
|
||||
"============================================================\n",
|
||||
)
|
||||
}
|
||||
|
||||
func getKanban() string {
|
||||
err := reg.Connect()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
for _, s := range flag.Args() {
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
sus = append(sus, i)
|
||||
}
|
||||
defer reg.Close()
|
||||
text, err := reg.Get("ZeroBot-Plugin/kanban")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
|
||||
// 通过代码写死的方式添加主人账号
|
||||
// sus = append(sus, 12345678)
|
||||
// sus = append(sus, 87654321)
|
||||
|
||||
if *runcfg != "" {
|
||||
f, err := os.Open(*runcfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.W = make([]*driver.WSClient, 0, 2)
|
||||
err = json.NewDecoder(f).Decode(&config)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.Z.Driver = make([]zero.Driver, len(config.W))
|
||||
for i, w := range config.W {
|
||||
config.Z.Driver[i] = w
|
||||
}
|
||||
logrus.Infoln("[main] 从", *runcfg, "读取配置文件")
|
||||
return
|
||||
}
|
||||
|
||||
config.W = []*driver.WSClient{driver.NewWebSocketClient(*url, *token)}
|
||||
config.Z = zero.Config{
|
||||
NickName: append([]string{*adana}, "ATRI", "atri", "亚托莉", "アトリ"),
|
||||
CommandPrefix: *prefix,
|
||||
SuperUsers: sus,
|
||||
Driver: []zero.Driver{config.W[0]},
|
||||
}
|
||||
|
||||
if *save != "" {
|
||||
f, err := os.Create(*save)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = json.NewEncoder(f).Encode(&config)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Infoln("[main] 配置文件已保存到", *save)
|
||||
os.Exit(0)
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
func main() {
|
||||
order.Wait()
|
||||
printBanner()
|
||||
rand.Seed(time.Now().UnixNano()) // 全局 seed,其他插件无需再 seed
|
||||
// 帮助
|
||||
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(banner, "\n可发送\"/服务列表\"查看 bot 功能"))
|
||||
ctx.SendChain(message.Text(kanban.Banner, "\n可发送\"/服务列表\"查看 bot 功能"))
|
||||
})
|
||||
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(getKanban()))
|
||||
ctx.SendChain(message.Text(kanban.Kanban()))
|
||||
})
|
||||
zero.RunAndBlock(
|
||||
zero.Config{
|
||||
NickName: append([]string{*adana}, nicks...),
|
||||
CommandPrefix: *prefix,
|
||||
// SuperUsers 某些功能需要主人权限,可通过以下两种方式修改
|
||||
// SuperUsers: []string{"12345678", "87654321"}, // 通过代码写死的方式添加主人账号
|
||||
SuperUsers: flag.Args(), // 通过命令行参数的方式添加主人账号
|
||||
Driver: []zero.Driver{driver.NewWebSocketClient(*url, *token)},
|
||||
},
|
||||
)
|
||||
zero.RunAndBlock(config.Z, process.GlobalInitMutex.Unlock)
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package order
|
||||
|
||||
import "sync"
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// DoneOnExit 在退出时执行 Done
|
||||
func DoneOnExit() func() {
|
||||
wg.Add(1)
|
||||
return wg.Done
|
||||
}
|
||||
|
||||
// Wait 等待
|
||||
var Wait = wg.Wait
|
||||
@@ -1,62 +0,0 @@
|
||||
// Package order 各个插件的优先级
|
||||
package order
|
||||
|
||||
const (
|
||||
PrioChat = iota * 10
|
||||
PrioSleepManage
|
||||
PrioAtri
|
||||
PrioManager
|
||||
|
||||
PrioACGImage
|
||||
PrioAIFalse
|
||||
PrioAIWife
|
||||
PrioBase14
|
||||
PrioBilibili
|
||||
PrioBiliBiliParse
|
||||
PrioBilibiliPush
|
||||
PrioBookReview
|
||||
PrioCangTouShi
|
||||
PrioChoose
|
||||
PrioChouXiangHua
|
||||
PrioCoser
|
||||
PrioCPStory
|
||||
PrioDanbooru
|
||||
PrioDiana
|
||||
PrioFansDaily
|
||||
PrioFortune
|
||||
PrioFunny
|
||||
PrioGIF
|
||||
PrioGithub
|
||||
PrioHS
|
||||
PrioImageFinder
|
||||
PrioJandan
|
||||
PrioJueJueZi
|
||||
PrioLolicon
|
||||
PrioMinecraft
|
||||
PrioMoyu
|
||||
PrioMusic
|
||||
PrioNativeSetu
|
||||
PrioNativeWife
|
||||
PrioNBNHHSH
|
||||
PrioNovel
|
||||
PrioNSFW
|
||||
PrioNSFWAuto
|
||||
PrioOmikuji
|
||||
PrioReborn
|
||||
PrioRuncode
|
||||
PrioSauceNao
|
||||
PrioScale
|
||||
PrioScore
|
||||
PrioSetuTime
|
||||
PrioShaDiao
|
||||
PrioShinDan
|
||||
PrioTraceMoe
|
||||
PrioTranslation
|
||||
PrioVtbQuotation
|
||||
PrioWangYiYun
|
||||
PrioWtf
|
||||
|
||||
PrioCurse
|
||||
PrioMockingBird
|
||||
PrioAIReply
|
||||
)
|
||||
121
plugin/ai_false/ai_false.go
Normal file
121
plugin/ai_false/ai_false.go
Normal file
@@ -0,0 +1,121 @@
|
||||
// Package aifalse 暂时只有服务器监控
|
||||
package aifalse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("aifalse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIfalse\n" +
|
||||
"- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
|
||||
"- 设置默认限速为每 m [分钟 | 秒] n 次触发",
|
||||
})
|
||||
c, ok := control.Lookup("aifalse")
|
||||
if !ok {
|
||||
panic("register aifalse error")
|
||||
}
|
||||
m := c.GetData(0)
|
||||
n := (m >> 16) & 0xffff
|
||||
m &= 0xffff
|
||||
if m != 0 || n != 0 {
|
||||
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
|
||||
logrus.Infoln("设置默认限速为每", m, "秒触发", n, "次")
|
||||
}
|
||||
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(
|
||||
"* CPU占用: ", cpuPercent(), "%\n",
|
||||
"* RAM占用: ", memPercent(), "%\n",
|
||||
"* 硬盘使用: ", diskPercent(),
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnRegex(`^设置默认限速为每\s*(\d+)\s*(分钟|秒)\s*(\d+)\s*次触发$`, 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
|
||||
}
|
||||
m, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if ctx.State["regex_matched"].([]string)[2] == "分钟" {
|
||||
m *= 60
|
||||
}
|
||||
if m >= 65536 || m <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:interval too big"))
|
||||
return
|
||||
}
|
||||
n, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[3], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if n >= 65536 || n <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:burst too big"))
|
||||
return
|
||||
}
|
||||
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
|
||||
err = c.SetData(0, (m&0xffff)|((n<<16)&0xffff0000))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置默认限速为每", m, "秒触发", n, "次"))
|
||||
})
|
||||
}
|
||||
|
||||
func cpuPercent() float64 {
|
||||
percent, err := cpu.Percent(time.Second, false)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return math.Round(percent[0])
|
||||
}
|
||||
|
||||
func memPercent() float64 {
|
||||
memInfo, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return math.Round(memInfo.UsedPercent)
|
||||
}
|
||||
|
||||
func diskPercent() string {
|
||||
parts, err := disk.Partitions(true)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
msg := ""
|
||||
for _, p := range parts {
|
||||
diskInfo, err := disk.Usage(p.Mountpoint)
|
||||
if err != nil {
|
||||
msg += "\n - " + err.Error()
|
||||
continue
|
||||
}
|
||||
pc := uint(math.Round(diskInfo.UsedPercent))
|
||||
if pc > 0 {
|
||||
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, pc)
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
181
plugin/ai_reply/ai_tts.go
Normal file
181
plugin/ai_reply/ai_tts.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/pkumza/numcn"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
"github.com/FloatTech/AnimeAPI/tts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/baidutts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/mockingbird"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
const ttsServiceName = "tts"
|
||||
|
||||
var re = regexp.MustCompile(`(\-|\+)?\d+(\.\d+)?`)
|
||||
|
||||
type ttsInstances struct {
|
||||
sync.RWMutex
|
||||
m map[string]tts.TTS
|
||||
l []string
|
||||
}
|
||||
|
||||
func (t *ttsInstances) List() []string {
|
||||
t.RLock()
|
||||
cl := make([]string, len(t.l))
|
||||
_ = copy(cl, t.l)
|
||||
t.RUnlock()
|
||||
return cl
|
||||
}
|
||||
|
||||
func init() {
|
||||
t := &ttsInstances{
|
||||
m: map[string]tts.TTS{
|
||||
"百度女声": baidutts.NewBaiduTTS(0),
|
||||
"百度男声": baidutts.NewBaiduTTS(1),
|
||||
"百度度逍遥": baidutts.NewBaiduTTS(3),
|
||||
"百度度丫丫": baidutts.NewBaiduTTS(4),
|
||||
"拟声鸟阿梓": nil,
|
||||
"拟声鸟文静": nil,
|
||||
"拟声鸟药水哥": nil,
|
||||
},
|
||||
l: []string{"拟声鸟阿梓", "拟声鸟文静", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"},
|
||||
}
|
||||
engine := control.Register(ttsServiceName, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "语音回复(包括拟声鸟和百度)\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n" +
|
||||
"- 设置语音模式[拟声鸟阿梓 | 拟声鸟文静 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n" +
|
||||
"- 设置默认语音模式[拟声鸟阿梓 | 拟声鸟文静 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n",
|
||||
})
|
||||
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := ctx.ExtractPlainText()
|
||||
r := aireply.NewAIReply(getReplyMode(ctx))
|
||||
tts, err := t.new(t.getSoundMode(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
var reply string
|
||||
if tts != nil {
|
||||
rec, err := tts.Speak(ctx.Event.UserID, func() string {
|
||||
reply = r.TalkPlain(msg, zero.BotConfig.NickName[0])
|
||||
reply = re.ReplaceAllStringFunc(reply, func(s string) string {
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
log.Errorln("[tts]:", err)
|
||||
return s
|
||||
}
|
||||
return numcn.EncodeFromFloat64(f)
|
||||
})
|
||||
log.Debugln("[tts]:", reply)
|
||||
return reply
|
||||
})
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Record(rec))
|
||||
} else {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^设置语音模式(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, t)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
err := t.setSoundMode(ctx, param)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前模式为", param))
|
||||
})
|
||||
engine.OnRegex(`^设置默认语音模式(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, t)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
t.setDefaultSoundMode(param)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,默认模式为", param))
|
||||
})
|
||||
}
|
||||
|
||||
// new 语音简单工厂
|
||||
func (t *ttsInstances) new(name string) (ts tts.TTS, err error) {
|
||||
t.RLock()
|
||||
ts = t.m[name]
|
||||
t.RUnlock()
|
||||
if ts == nil {
|
||||
switch name {
|
||||
case "拟声鸟阿梓":
|
||||
t.Lock()
|
||||
ts, err = mockingbird.NewMockingBirdTTS(0)
|
||||
t.Unlock()
|
||||
case "拟声鸟文静":
|
||||
t.Lock()
|
||||
ts, err = mockingbird.NewMockingBirdTTS(1)
|
||||
t.Unlock()
|
||||
case "拟声鸟药水哥":
|
||||
t.Lock()
|
||||
ts, err = mockingbird.NewMockingBirdTTS(2)
|
||||
t.Unlock()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *ttsInstances) setSoundMode(ctx *zero.Ctx, name string) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
var index int64
|
||||
t.RLock()
|
||||
for i, s := range t.l {
|
||||
if s == name {
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
t.RUnlock()
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
return m.SetData(gid, index)
|
||||
}
|
||||
|
||||
func (t *ttsInstances) getSoundMode(ctx *zero.Ctx) (name string) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
index := m.GetData(gid)
|
||||
if int(index) < len(t.l) {
|
||||
return t.l[index]
|
||||
}
|
||||
}
|
||||
return "拟声鸟阿梓"
|
||||
}
|
||||
|
||||
func (t *ttsInstances) setDefaultSoundMode(name string) {
|
||||
var index int
|
||||
t.RLock()
|
||||
for _, s := range t.l {
|
||||
if s == name {
|
||||
break
|
||||
}
|
||||
index++
|
||||
}
|
||||
t.RUnlock()
|
||||
t.Lock()
|
||||
t.l[0], t.l[index] = t.l[index], t.l[0]
|
||||
t.Unlock()
|
||||
}
|
||||
@@ -6,22 +6,21 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
serviceName = "aireply"
|
||||
replyServiceName = "aireply"
|
||||
)
|
||||
|
||||
var modes = [...]string{"青云客", "小爱"}
|
||||
var replyModes = [...]string{"青云客", "小爱"}
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register(serviceName, order.PrioAIReply, &control.Options{
|
||||
engine := control.Register(replyServiceName, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "人工智能回复\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客 | 小爱]\n- ",
|
||||
@@ -59,7 +58,7 @@ func setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
}
|
||||
var ok bool
|
||||
var index int64
|
||||
for i, s := range modes {
|
||||
for i, s := range replyModes {
|
||||
if s == name {
|
||||
ok = true
|
||||
index = int64(i)
|
||||
@@ -69,7 +68,7 @@ func setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
if !ok {
|
||||
return errors.New("no such mode")
|
||||
}
|
||||
m, ok := control.Lookup(serviceName)
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
@@ -81,11 +80,11 @@ func getReplyMode(ctx *zero.Ctx) (name string) {
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := control.Lookup(serviceName)
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
index := m.GetData(gid)
|
||||
if int(index) < len(modes) {
|
||||
return modes[index]
|
||||
if int(index) < len(replyModes) {
|
||||
return replyModes[index]
|
||||
}
|
||||
}
|
||||
return "青云客"
|
||||
@@ -4,14 +4,12 @@ package aiwife
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -19,8 +17,7 @@ const (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
control.Register("aiwife", order.PrioAIWife, &control.Options{
|
||||
control.Register("aiwife", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIWife\n" +
|
||||
"- waifu | 随机waifu",
|
||||
@@ -12,10 +12,9 @@ import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register(servicename, order.PrioAtri, &control.Options{
|
||||
engine := control.Register(servicename, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
|
||||
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢 | 爱你 | 爱 | suki | daisuki | すき | 好き | 贴贴 | 老婆 | 亲一个 | mua\n" +
|
||||
@@ -34,26 +33,16 @@ func init() { // 插件主体
|
||||
"- 中午好 | 午安 | 午好\n- 晚安 | oyasuminasai | おやすみなさい | 晚好 | 晚上好\n- 高性能 | 太棒了 | すごい | sugoi | 斯国一 | よかった\n" +
|
||||
"- 没事 | 没关系 | 大丈夫 | 还好 | 不要紧 | 没出大问题 | 没伤到哪\n- 好吗 | 是吗 | 行不行 | 能不能 | 可不可以\n- 啊这\n- 我好了\n- ? | ? | ¿\n" +
|
||||
"- 离谱\n- 答应我",
|
||||
OnEnable: func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
|
||||
},
|
||||
OnDisable: func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("Zzz……Zzz……"))
|
||||
},
|
||||
})
|
||||
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := control.Lookup(servicename)
|
||||
if ok && !c.IsEnabledIn(ctx.Event.GroupID) {
|
||||
c.Enable(ctx.Event.GroupID)
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := control.Lookup(servicename)
|
||||
if ok && c.IsEnabledIn(ctx.Event.GroupID) {
|
||||
c.Disable(ctx.Event.GroupID)
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("Zzz……Zzz……"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("萝卜子", atriSleep).SetBlock(true).
|
||||
engine.OnFullMatch("萝卜子", isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(2) {
|
||||
@@ -63,12 +52,12 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randRecord("RocketPunch.amr"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
|
||||
@@ -169,7 +158,7 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
@@ -190,7 +179,7 @@ func init() { // 插件主体
|
||||
"呣......我的高性能,毫无遗憾地施展出来了......",
|
||||
))
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
@@ -205,26 +194,26 @@ func init() { // 插件主体
|
||||
))
|
||||
})
|
||||
|
||||
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, atriSleep).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("YES.png", "NO.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"啊这"}, atriSleep).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"啊这"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"我好了"}, atriSleep).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"我好了"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText("不许好!", "憋回去!"))
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"?", "?", "¿"}, atriSleep).SetBlock(true).
|
||||
engine.OnFullMatchGroup([]string{"?", "?", "¿"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(5) {
|
||||
@@ -234,7 +223,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeyword("离谱", atriSleep).SetBlock(true).
|
||||
engine.OnKeyword("离谱", isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
@@ -243,7 +232,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randImage("WH.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeyword("答应我", atriSleep, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeyword("答应我", isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText("我无法回应你的请求"))
|
||||
@@ -262,8 +251,8 @@ func randRecord(file ...string) message.MessageSegment {
|
||||
return message.Record(res + file[rand.Intn(len(file))])
|
||||
}
|
||||
|
||||
// atriSleep 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func atriSleep(ctx *zero.Ctx) bool {
|
||||
// isAtriSleeping 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func isAtriSleeping(ctx *zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
@@ -4,58 +4,57 @@ package b14coder
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
base14 "github.com/fumiama/go-base16384"
|
||||
tea "github.com/fumiama/gofastTEA"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("base16384", order.PrioBase14, &control.Options{
|
||||
en := control.Register("base16384", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "base16384加解密\n" +
|
||||
"- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
|
||||
})
|
||||
en.OnRegex(`^加密\s?(.*)`).SetBlock(true).
|
||||
en.OnRegex(`^加密\s*(.+)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es, err := base14.UTF16be2utf8(base14.EncodeString(str))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(helper.BytesToString(es)))
|
||||
es := base14.EncodeString(str)
|
||||
if es != "" {
|
||||
ctx.SendChain(message.Text(es))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("加密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^解密\s?([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
|
||||
en.OnRegex(`^解密\s*([一-踀]+[㴁-㴆]?)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es, err := base14.UTF82utf16be(helper.StringToBytes(str))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(base14.DecodeString(es)))
|
||||
es := base14.DecodeString(str)
|
||||
if es != "" {
|
||||
ctx.SendChain(message.Text(es))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("解密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^用(.*)加密\s?(.*)`).SetBlock(true).
|
||||
en.OnRegex(`^用(.+)加密\s*(.+)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
|
||||
t := getea(key)
|
||||
es, err := base14.UTF16be2utf8(base14.Encode(t.Encrypt(helper.StringToBytes(str))))
|
||||
es, err := base14.UTF16BE2UTF8(base14.Encode(t.Encrypt(helper.StringToBytes(str))))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(helper.BytesToString(es)))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("加密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^用(.*)解密\s?([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
|
||||
en.OnRegex(`^用(.+)解密\s*([一-踀]+[㴁-㴆]?)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
|
||||
t := getea(key)
|
||||
es, err := base14.UTF82utf16be(helper.StringToBytes(str))
|
||||
es, err := base14.UTF82UTF16BE(helper.StringToBytes(str))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(helper.BytesToString(t.Decrypt(base14.Decode(es)))))
|
||||
} else {
|
||||
27
plugin/baidu/search.go
Normal file
27
plugin/baidu/search.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Package baidu 百度一下
|
||||
package baidu
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("baidu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "baidu\n" +
|
||||
"- 百度下[xxx]",
|
||||
}).OnPrefix("百度下").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
txt := ctx.State["args"].(string)
|
||||
if txt != "" {
|
||||
ctx.SendChain(message.Text("https://buhuibaidu.me/?s=" + url.QueryEscape(txt)))
|
||||
}
|
||||
})
|
||||
}
|
||||
179
plugin/bilibili/api.go
Normal file
179
plugin/bilibili/api.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var (
|
||||
errNeedCookie = errors.New("该api需要设置b站cookie,请发送命令设置cookie,例如\"设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\"")
|
||||
)
|
||||
|
||||
type searchResult struct {
|
||||
Mid int64 `json:"mid"`
|
||||
Uname string `json:"uname"`
|
||||
Gender int64 `json:"gender"`
|
||||
Usign string `json:"usign"`
|
||||
Level int64 `json:"level"`
|
||||
}
|
||||
|
||||
// 搜索api:通过把触发指令传入的昵称找出uid返回
|
||||
func search(keyword string) (r []searchResult, err error) {
|
||||
searchURL := "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&keyword=" + keyword
|
||||
data, err := web.GetData(searchURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
j := gjson.ParseBytes(data)
|
||||
if j.Get("data.numResults").Int() == 0 {
|
||||
err = errors.New("查无此人")
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(j.Get("data.result").Raw), &r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type follower struct {
|
||||
Mid int `json:"mid"`
|
||||
Uname string `json:"uname"`
|
||||
Video int `json:"video"`
|
||||
Roomid int `json:"roomid"`
|
||||
Rise int `json:"rise"`
|
||||
Follower int `json:"follower"`
|
||||
GuardNum int `json:"guardNum"`
|
||||
AreaRank int `json:"areaRank"`
|
||||
}
|
||||
|
||||
// 请求api
|
||||
func fansapi(uid string) (result follower, err error) {
|
||||
fanURL := "https://api.vtbs.moe/v1/detail/" + uid
|
||||
data, err := web.GetData(fanURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(data, &result); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func followings(uid string) (s string, err error) {
|
||||
followingURL := "https://api.bilibili.com/x/relation/same/followings?vmid=" + uid
|
||||
method := "GET"
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest(method, followingURL, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c := vdb.getBilibiliCookie()
|
||||
req.Header.Add("cookie", c.Value)
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
j := gjson.ParseBytes(body)
|
||||
s = j.Get("data.list.#.uname").Raw
|
||||
if j.Get("code").Int() == -101 {
|
||||
err = errNeedCookie
|
||||
return
|
||||
}
|
||||
if j.Get("code").Int() != 0 {
|
||||
err = errors.New(j.Get("message").String())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type userinfo struct {
|
||||
Name string `json:"name"`
|
||||
Mid string `json:"mid"`
|
||||
Face string `json:"face"`
|
||||
Fans int64 `json:"fans"`
|
||||
Regtime int64 `json:"regtime"`
|
||||
Attentions []int64 `json:"attentions"`
|
||||
}
|
||||
|
||||
type medalInfo struct {
|
||||
Mid int64 `json:"target_id"`
|
||||
MedalName string `json:"medal_name"`
|
||||
Level int64 `json:"level"`
|
||||
MedalColorStart int64 `json:"medal_color_start"`
|
||||
MedalColorEnd int64 `json:"medal_color_end"`
|
||||
MedalColorBorder int64 `json:"medal_color_border"`
|
||||
}
|
||||
type medal struct {
|
||||
Uname string `json:"target_name"`
|
||||
medalInfo `json:"medal_info"`
|
||||
}
|
||||
|
||||
type medalSlice []medal
|
||||
|
||||
func (m medalSlice) Len() int {
|
||||
return len(m)
|
||||
}
|
||||
func (m medalSlice) Swap(i, j int) {
|
||||
m[i], m[j] = m[j], m[i]
|
||||
}
|
||||
func (m medalSlice) Less(i, j int) bool {
|
||||
return m[i].Level > m[j].Level
|
||||
}
|
||||
|
||||
// 获取详情
|
||||
func card(uid string) (result userinfo, err error) {
|
||||
cardURL := "https://account.bilibili.com/api/member/getCardByMid?mid=" + uid
|
||||
data, err := web.GetData(cardURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("card").Raw), &result)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 获得牌子
|
||||
func medalwall(uid string) (result []medal, err error) {
|
||||
medalwallURL := "https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id=" + uid
|
||||
method := "GET"
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest(method, medalwallURL, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c := vdb.getBilibiliCookie()
|
||||
req.Header.Add("cookie", c.Value)
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
data, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
j := gjson.ParseBytes(data)
|
||||
if j.Get("code").Int() == -101 {
|
||||
err = errNeedCookie
|
||||
return
|
||||
}
|
||||
if j.Get("code").Int() != 0 {
|
||||
err = errors.New(j.Get("message").String())
|
||||
}
|
||||
_ = json.Unmarshal(binary.StringToBytes(j.Get("data.list").Raw), &result)
|
||||
return
|
||||
}
|
||||
358
plugin/bilibili/info.go
Normal file
358
plugin/bilibili/info.go
Normal file
@@ -0,0 +1,358 @@
|
||||
// Package bilibili 查询b站用户信息
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/fogleman/gg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var engine = control.Register("bilibili", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibili\n" +
|
||||
"- >vup info [xxx]\n" +
|
||||
"- >user info [xxx]\n" +
|
||||
"- 查成分 [xxx]\n" +
|
||||
"- 设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\n" +
|
||||
"- 更新vup",
|
||||
PublicDataFolder: "Bilibili",
|
||||
})
|
||||
var re = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
// 查成分的
|
||||
func init() {
|
||||
cachePath := engine.DataFolder() + "cache/"
|
||||
_ = os.RemoveAll(cachePath)
|
||||
_ = os.MkdirAll(cachePath, 0755)
|
||||
var getdb = ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
var err error
|
||||
_, _ = engine.GetLazyData("bilibili.db", false)
|
||||
vdb, err = initialize(engine.DataFolder() + "bilibili.db")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnRegex(`^>user info\s?(.{1,25})$`, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
uidRes, err := search(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
id := strconv.FormatInt(uidRes[0].Mid, 10)
|
||||
follwings, err := followings(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
ctx.SendChain(message.Text(
|
||||
"search: ", uidRes[0].Mid, "\n",
|
||||
"name: ", uidRes[0].Uname, "\n",
|
||||
"sex: ", []string{"", "男", "女", "未知"}[uidRes[0].Gender], "\n",
|
||||
"sign: ", uidRes[0].Usign, "\n",
|
||||
"level: ", uidRes[0].Level, "\n",
|
||||
"follow: ", follwings,
|
||||
))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^>vup info\s?(.{1,25})$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
res, err := search(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
id := strconv.FormatInt(res[0].Mid, 10)
|
||||
// 获取详情
|
||||
fo, err := fansapi(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(
|
||||
"search: ", fo.Mid, "\n",
|
||||
"名字: ", fo.Uname, "\n",
|
||||
"当前粉丝数: ", fo.Follower, "\n",
|
||||
"24h涨粉数: ", fo.Rise, "\n",
|
||||
"视频投稿数: ", fo.Video, "\n",
|
||||
"直播间id: ", fo.Roomid, "\n",
|
||||
"舰队: ", fo.GuardNum, "\n",
|
||||
"直播总排名: ", fo.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", fo.Mid, "\n",
|
||||
"数据获取时间: ", time.Now().Format("2006-01-02 15:04:05"),
|
||||
))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^查成分\s?(.{1,25})$`, getdb, getPara).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.State["uid"].(string)
|
||||
today := time.Now().Format("20060102")
|
||||
drawedFile := cachePath + id + today + "vupLike.png"
|
||||
if file.IsExist(drawedFile) {
|
||||
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
|
||||
return
|
||||
}
|
||||
u, err := card(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
vups, err := vdb.filterVup(u.Attentions)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
vupLen := len(vups)
|
||||
medals, err := medalwall(id)
|
||||
sort.Sort(medalSlice(medals))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
frontVups := make([]vup, 0)
|
||||
medalMap := make(map[int64]medal)
|
||||
for _, v := range medals {
|
||||
up := vup{
|
||||
Mid: v.Mid,
|
||||
Uname: v.Uname,
|
||||
}
|
||||
frontVups = append(frontVups, up)
|
||||
medalMap[v.Mid] = v
|
||||
}
|
||||
vups = append(vups, frontVups...)
|
||||
copy(vups[len(frontVups):], vups)
|
||||
copy(vups, frontVups)
|
||||
for i := len(frontVups); i < len(vups); i++ {
|
||||
if _, ok := medalMap[vups[i].Mid]; ok {
|
||||
vups = append(vups[:i], vups[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
facePath := cachePath + id + "vupFace" + path.Ext(u.Face)
|
||||
backX := 500
|
||||
backY := 500
|
||||
var back image.Image
|
||||
if path.Ext(u.Face) != ".webp" {
|
||||
err = initFacePic(facePath, u.Face)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
back, err = gg.LoadImage(facePath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
back = img.Size(back, backX, backY).Im
|
||||
}
|
||||
if len(vups) > 50 {
|
||||
ctx.SendChain(message.Text(u.Name + "关注的up主太多了,只展示前50个up"))
|
||||
vups = vups[:50]
|
||||
}
|
||||
canvas := gg.NewContext(1500, int(500*(1.1+float64(len(vups))/3)))
|
||||
fontSize := 50.0
|
||||
canvas.SetColor(color.White)
|
||||
canvas.Clear()
|
||||
if back != nil {
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
sl, _ := canvas.MeasureString("好")
|
||||
length, h := canvas.MeasureString(u.Mid)
|
||||
n, _ := canvas.MeasureString(u.Name)
|
||||
canvas.DrawString(u.Name, 550, 160-h)
|
||||
canvas.DrawRoundedRectangle(600+n-length*0.1, 160-h*2.5, length*1.2, h*2, fontSize*0.2)
|
||||
canvas.SetRGB255(221, 221, 221)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawString(u.Mid, 600+n, 160-h)
|
||||
canvas.DrawString(fmt.Sprintf("粉丝:%d", u.Fans), 550, 240-h)
|
||||
canvas.DrawString(fmt.Sprintf("关注:%d", len(u.Attentions)), 1000, 240-h)
|
||||
canvas.DrawString(fmt.Sprintf("管人痴成分:%.2f%%(%d/%d)", float64(vupLen)/float64(len(u.Attentions))*100, vupLen, len(u.Attentions)), 550, 320-h)
|
||||
regtime := time.Unix(u.Regtime, 0).Format("2006-01-02 15:04:05")
|
||||
canvas.DrawString("注册日期:"+regtime, 550, 400-h)
|
||||
canvas.DrawString("查询日期:"+time.Now().Format("2006-01-02"), 550, 480-h)
|
||||
for i, v := range vups {
|
||||
if i%2 == 1 {
|
||||
canvas.SetRGB255(245, 245, 245)
|
||||
canvas.DrawRectangle(0, float64(backY)*1.1+float64(i)*float64(backY)/3, float64(backX*3), float64(backY)/3)
|
||||
canvas.Fill()
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
nl, _ := canvas.MeasureString(v.Uname)
|
||||
canvas.DrawString(v.Uname, float64(backX)*0.1, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
ml, _ := canvas.MeasureString(strconv.FormatInt(v.Mid, 10))
|
||||
canvas.DrawRoundedRectangle(nl-0.1*ml+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-h*3.5, ml*1.2, h*2, fontSize*0.2)
|
||||
canvas.SetRGB255(221, 221, 221)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawString(strconv.FormatInt(v.Mid, 10), nl+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
if m, ok := medalMap[v.Mid]; ok {
|
||||
mnl, _ := canvas.MeasureString(m.MedalName)
|
||||
grad := gg.NewLinearGradient(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h, nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
r, g, b := int2rbg(m.MedalColorStart)
|
||||
grad.AddColorStop(0, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: 255})
|
||||
r, g, b = int2rbg(m.MedalColorEnd)
|
||||
grad.AddColorStop(1, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: 255})
|
||||
canvas.SetFillStyle(grad)
|
||||
canvas.SetLineWidth(4)
|
||||
canvas.MoveTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.ClosePath()
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.White)
|
||||
canvas.DrawString(m.MedalName, nl+ml+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
r, g, b = int2rbg(m.MedalColorBorder)
|
||||
canvas.SetRGB255(int(r), int(g), int(b))
|
||||
canvas.DrawString(strconv.FormatInt(m.Level, 10), nl+ml+mnl+sl+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
mll, _ := canvas.MeasureString(strconv.FormatInt(m.Level, 10))
|
||||
canvas.SetLineWidth(4)
|
||||
canvas.MoveTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.ClosePath()
|
||||
canvas.Stroke()
|
||||
}
|
||||
}
|
||||
f, err := os.Create(drawedFile)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibili]", err)
|
||||
data, cl := writer.ToBytes(canvas.Image())
|
||||
ctx.SendChain(message.ImageBytes(data))
|
||||
cl()
|
||||
return
|
||||
}
|
||||
_, err = writer.WriteTo(canvas.Image(), f)
|
||||
_ = f.Close()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^设置b站cookie?\s+(.{1,100})$`, zero.SuperUserPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
cookie := ctx.State["regex_matched"].([]string)[1]
|
||||
err := vdb.setBilibiliCookie(cookie)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功设置b站cookie为" + cookie))
|
||||
})
|
||||
|
||||
engine.OnFullMatch("更新vup", zero.SuperUserPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
err := updateVup()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("vup已更新"))
|
||||
})
|
||||
}
|
||||
|
||||
func initFacePic(filename, faceURL string) error {
|
||||
if file.IsNotExist(filename) {
|
||||
data, err := web.GetData(faceURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(filename, data, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func int2rbg(t int64) (int64, int64, int64) {
|
||||
var buf [8]byte
|
||||
binary.LittleEndian.PutUint64(buf[:], uint64(t))
|
||||
b, g, r := int64(buf[0]), int64(buf[1]), int64(buf[2])
|
||||
return r, g, b
|
||||
}
|
||||
|
||||
func getPara(ctx *zero.Ctx) bool {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
if !re.MatchString(keyword) {
|
||||
searchRes, err := search(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
|
||||
return true
|
||||
}
|
||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
ctx.SendChain(message.Text("输入为纯数字,请选择查询uid还是用户名,输入对应序号:\n0. 查询uid\n1. 查询用户名"))
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 10):
|
||||
ctx.SendChain(message.Text("时间太久啦!", zero.BotConfig.NickName[0], "帮你选择查询uid"))
|
||||
ctx.State["uid"] = keyword
|
||||
return true
|
||||
case c := <-recv:
|
||||
msg := c.Event.Message.ExtractPlainText()
|
||||
num, err := strconv.Atoi(msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("请输入数字!"))
|
||||
continue
|
||||
}
|
||||
if num < 0 || num > 1 {
|
||||
ctx.SendChain(message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
if num == 0 {
|
||||
ctx.State["uid"] = keyword
|
||||
return true
|
||||
} else if num == 1 {
|
||||
searchRes, err := search(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
130
plugin/bilibili/model.go
Normal file
130
plugin/bilibili/model.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
_ "github.com/fumiama/sqlite3" // use sql
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
const (
|
||||
bilibiliCookie = "bilbili_cookie"
|
||||
)
|
||||
|
||||
var (
|
||||
vtbURLs = [...]string{"https://api.vtbs.moe/v1/short", "https://api.tokyo.vtbs.moe/v1/short", "https://vtbs.musedash.moe/v1/short"}
|
||||
vdb *vupdb
|
||||
)
|
||||
|
||||
// vupdb 分数数据库
|
||||
type vupdb gorm.DB
|
||||
|
||||
type vup struct {
|
||||
Mid int64 `gorm:"column:mid;primary_key"`
|
||||
Uname string `gorm:"column:uname"`
|
||||
Roomid int64 `gorm:"column:roomid"`
|
||||
}
|
||||
|
||||
func (vup) TableName() string {
|
||||
return "vup"
|
||||
}
|
||||
|
||||
type config struct {
|
||||
Key string `gorm:"column:key;primary_key"`
|
||||
Value string `gorm:"column:value"`
|
||||
}
|
||||
|
||||
func (config) TableName() string {
|
||||
return "config"
|
||||
}
|
||||
|
||||
// initialize 初始化vtb数据库
|
||||
func initialize(dbpath string) (*vupdb, error) {
|
||||
if _, err := os.Stat(dbpath); err != nil || os.IsNotExist(err) {
|
||||
// 生成文件
|
||||
f, err := os.Create(dbpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
gdb, err := gorm.Open("sqlite3", dbpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gdb.AutoMigrate(&vup{}).AutoMigrate(&config{})
|
||||
return (*vupdb)(gdb), nil
|
||||
}
|
||||
|
||||
func (vdb *vupdb) insertVupByMid(mid int64, uname string, roomid int64) (err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
v := vup{
|
||||
Mid: mid,
|
||||
Uname: uname,
|
||||
Roomid: roomid,
|
||||
}
|
||||
if err = db.Model(&vup{}).First(&v, "mid = ? ", mid).Error; err != nil {
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
err = db.Model(&vup{}).Create(&v).Error
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// filterVup 筛选vup
|
||||
func (vdb *vupdb) filterVup(ids []int64) (vups []vup, err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
if err = db.Model(&vup{}).Find(&vups, "mid in (?)", ids).Error; err != nil {
|
||||
return vups, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func updateVup() error {
|
||||
for _, v := range vtbURLs {
|
||||
data, err := web.GetData(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(key, value gjson.Result) bool {
|
||||
mid := value.Get("mid").Int()
|
||||
uname := value.Get("uname").String()
|
||||
roomid := value.Get("roomid").Int()
|
||||
err = vdb.insertVupByMid(mid, uname, roomid)
|
||||
return err == nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vdb *vupdb) setBilibiliCookie(cookie string) (err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
c := config{
|
||||
Key: bilibiliCookie,
|
||||
Value: cookie,
|
||||
}
|
||||
if err = db.Model(&config{}).First(&c, "key = ? ", bilibiliCookie).Error; err != nil {
|
||||
// error handling...
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
err = db.Model(&config{}).Create(&c).Error
|
||||
}
|
||||
} else {
|
||||
err = db.Model(&config{}).Where("key = ? ", bilibiliCookie).Update(
|
||||
map[string]interface{}{
|
||||
"value": cookie,
|
||||
}).Error
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (vdb *vupdb) getBilibiliCookie() (c config) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
db.Model(&config{}).First(&c, "key = ?", bilibiliCookie)
|
||||
return
|
||||
}
|
||||
190
plugin/bilibili_parse/bilibili_parse.go
Normal file
190
plugin/bilibili_parse/bilibili_parse.go
Normal file
@@ -0,0 +1,190 @@
|
||||
// Package bilibiliparse b站视频链接解析
|
||||
package bilibiliparse
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type result struct {
|
||||
Data struct {
|
||||
Bvid string `json:"bvid"`
|
||||
Aid int `json:"aid"`
|
||||
Copyright int `json:"copyright"`
|
||||
Pic string `json:"pic"`
|
||||
Title string `json:"title"`
|
||||
Pubdate int `json:"pubdate"`
|
||||
Ctime int `json:"ctime"`
|
||||
Rights struct {
|
||||
IsCooperation int `json:"is_cooperation"`
|
||||
} `json:"rights"`
|
||||
Owner struct {
|
||||
Mid int `json:"mid"`
|
||||
Name string `json:"name"`
|
||||
} `json:"owner"`
|
||||
Stat struct {
|
||||
Aid int `json:"aid"`
|
||||
View int `json:"view"`
|
||||
Danmaku int `json:"danmaku"`
|
||||
Reply int `json:"reply"`
|
||||
Favorite int `json:"favorite"`
|
||||
Coin int `json:"coin"`
|
||||
Share int `json:"share"`
|
||||
Like int `json:"like"`
|
||||
} `json:"stat"`
|
||||
Staff []struct {
|
||||
Title string `json:"title"`
|
||||
Name string `json:"name"`
|
||||
Follower int `json:"follower"`
|
||||
} `json:"staff"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type owner struct {
|
||||
Data struct {
|
||||
Card struct {
|
||||
Fans int `json:"fans"`
|
||||
} `json:"card"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
const (
|
||||
videoapi = "https://api.bilibili.com/x/web-interface/view?"
|
||||
cardapi = "http://api.bilibili.com/x/web-interface/card?"
|
||||
origin = "https://www.bilibili.com/video/"
|
||||
)
|
||||
|
||||
var (
|
||||
reg = regexp.MustCompile(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`)
|
||||
limit = ctxext.NewLimiterManager(time.Second*10, 1)
|
||||
)
|
||||
|
||||
// 插件主体
|
||||
func init() {
|
||||
en := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "b站视频链接解析\n" +
|
||||
"- https://www.bilibili.com/video/BV1xx411c7BF | https://www.bilibili.com/video/av1605 | https://b23.tv/I8uzWCA | https://www.bilibili.com/video/bv1xx411c7BF",
|
||||
})
|
||||
en.OnRegex(`(av[0-9]+|BV[0-9a-zA-Z]{10}){1}`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if strings.Contains(ctx.MessageString(), "[CQ:forward") {
|
||||
return
|
||||
}
|
||||
id := ctx.State["regex_matched"].([]string)[1]
|
||||
m, err := parse(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(m)
|
||||
})
|
||||
en.OnRegex(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.State["regex_matched"].([]string)[1]
|
||||
m, err := parse(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(m)
|
||||
})
|
||||
en.OnRegex(`(https://b23.tv/[0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["regex_matched"].([]string)[1]
|
||||
realurl, err := getrealurl(url)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
m, err := parse(cuturl(realurl))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(m)
|
||||
})
|
||||
}
|
||||
|
||||
// parse 解析视频数据
|
||||
func parse(id string) (m message.Message, err error) {
|
||||
var vid string
|
||||
switch id[:2] {
|
||||
case "av":
|
||||
vid = "aid=" + id[2:]
|
||||
case "BV":
|
||||
vid = "bvid=" + id
|
||||
}
|
||||
data, err := web.GetData(videoapi + vid)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var r result
|
||||
err = json.Unmarshal(data, &r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m = make(message.Message, 0, 16)
|
||||
m = append(m, message.Text("标题: ", r.Data.Title, "\n"))
|
||||
if r.Data.Rights.IsCooperation == 1 {
|
||||
for i := 0; i < len(r.Data.Staff); i++ {
|
||||
m = append(m, message.Text(r.Data.Staff[i].Title, ": ", r.Data.Staff[i].Name, ", 粉丝: ", row(r.Data.Staff[i].Follower), "\n"))
|
||||
}
|
||||
} else {
|
||||
o, err := getcard(r.Data.Owner.Mid)
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
m = append(m, message.Text("UP主: ", r.Data.Owner.Name, ", 粉丝: ", row(o.Data.Card.Fans), "\n"))
|
||||
}
|
||||
m = append(m, message.Text("播放: ", row(r.Data.Stat.View), ", 弹幕: ", row(r.Data.Stat.Danmaku), "\n"),
|
||||
message.Image(r.Data.Pic),
|
||||
message.Text("\n点赞: ", row(r.Data.Stat.Like), ", 投币: ", row(r.Data.Stat.Coin), "\n收藏: ", row(r.Data.Stat.Favorite), ", 分享: ", row(r.Data.Stat.Share), "\n", origin, id))
|
||||
return
|
||||
}
|
||||
|
||||
// getrealurl 获取跳转后的链接
|
||||
func getrealurl(url string) (realurl string, err error) {
|
||||
data, err := http.Head(url)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
realurl = data.Request.URL.String()
|
||||
return
|
||||
}
|
||||
|
||||
// cuturl 获取aid或者bvid
|
||||
func cuturl(url string) (id string) {
|
||||
if !reg.MatchString(url) {
|
||||
return
|
||||
}
|
||||
return reg.FindStringSubmatch(url)[1]
|
||||
}
|
||||
|
||||
// getcard 获取个人信息
|
||||
func getcard(mid int) (o owner, err error) {
|
||||
data, err := web.GetData(cardapi + "mid=" + strconv.Itoa(mid))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &o)
|
||||
return
|
||||
}
|
||||
|
||||
func row(res int) string {
|
||||
if res/10000 != 0 {
|
||||
return strconv.FormatFloat(float64(res)/10000, 'f', 2, 64) + "万"
|
||||
}
|
||||
return strconv.Itoa(res)
|
||||
}
|
||||
74
plugin/book_review/book_review.go
Normal file
74
plugin/book_review/book_review.go
Normal file
@@ -0,0 +1,74 @@
|
||||
// Package bookreview 书评
|
||||
package bookreview
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("bookreview", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "哀伤雪刃推书记录\n- 书评[xxx]\n- 随机书评",
|
||||
PublicDataFolder: "BookReview",
|
||||
})
|
||||
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "bookreview.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("bookreview.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("bookreview", &book{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("bookreview")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
log.Infof("[bookreview]读取%d条书评", n)
|
||||
return true
|
||||
})
|
||||
|
||||
// 中文、英文、数字但不包括下划线等符号
|
||||
engine.OnRegex("^书评([\u4E00-\u9FA5A-Za-z0-9]{1,25})$", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
b := getBookReviewByKeyword(ctx.State["regex_matched"].([]string)[1])
|
||||
data, err := text.RenderToBase64(b.BookReview, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnFullMatch("随机书评", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
br := getRandomBookReview()
|
||||
data, err := text.RenderToBase64(br.BookReview, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
package bookreview
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type book struct {
|
||||
ID uint64 `db:"id"`
|
||||
BookReview string `db:"bookreview"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
// 暂时随机选择一个书评
|
||||
func getBookReviewByKeyword(keyword string) (b book) {
|
||||
_ = db.Find("bookreview", &b, "where bookreview LIKE '%"+keyword+"%'")
|
||||
@@ -9,14 +9,12 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/antchfx/htmlquery"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -32,92 +30,110 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cangtoushi", order.PrioCangTouShi, &control.Options{
|
||||
engine := control.Register("cangtoushi", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "藏头诗\n" +
|
||||
"- 藏头诗[xxx]\n- 藏尾诗[xxx]",
|
||||
})
|
||||
engine.OnRegex(`藏头诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
kw := ctx.State["regex_matched"].([]string)[1]
|
||||
login()
|
||||
err := login()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
data, err := search(kw, "7", "0")
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
text, err := dealHTML(helper.BytesToString(data))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
text := dealHTML(helper.BytesToString(data))
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnRegex(`藏尾诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
kw := ctx.State["regex_matched"].([]string)[1]
|
||||
login()
|
||||
err := login()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
data, err := search(kw, "7", "2")
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
text, err := dealHTML(helper.BytesToString(data))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
text := dealHTML(helper.BytesToString(data))
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
}
|
||||
|
||||
func login() {
|
||||
func login() error {
|
||||
gCurCookieJar, _ = cookiejar.New(nil)
|
||||
client := &http.Client{
|
||||
Jar: gCurCookieJar,
|
||||
}
|
||||
request, err := http.NewRequest("GET", loginURL, nil)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return err
|
||||
}
|
||||
request.Header.Add("User-Agent", ua)
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return err
|
||||
}
|
||||
data, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return err
|
||||
}
|
||||
response.Body.Close()
|
||||
doc, err := htmlquery.Parse(strings.NewReader(helper.BytesToString(data)))
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return err
|
||||
}
|
||||
csrf = htmlquery.SelectAttr(htmlquery.FindOne(doc, "//input[@name='_csrf']"), "value")
|
||||
return nil
|
||||
}
|
||||
|
||||
func search(kw, zishu, position string) (data []byte, err error) {
|
||||
postStr := fmt.Sprintf("_csrf=%s&kw=%s&zishu=%s&position=%s", url.QueryEscape(csrf), url.QueryEscape(kw), zishu, position)
|
||||
log.Println("postStr:", postStr)
|
||||
client := &http.Client{
|
||||
Jar: gCurCookieJar,
|
||||
}
|
||||
request, err := http.NewRequest("POST", searchURL, strings.NewReader(postStr))
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return nil, err
|
||||
}
|
||||
request.Header.Add("Referer", referer)
|
||||
request.Header.Add("User-Agent", ua)
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return nil, err
|
||||
}
|
||||
data, err = io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return nil, err
|
||||
}
|
||||
response.Body.Close()
|
||||
return
|
||||
}
|
||||
|
||||
func dealHTML(data string) (text string) {
|
||||
func dealHTML(data string) (text string, err error) {
|
||||
doc, err := htmlquery.Parse(strings.NewReader(data))
|
||||
if err != nil {
|
||||
log.Errorln("[cangtoushi]:", err)
|
||||
return "", err
|
||||
}
|
||||
text = htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@class='card']/div[@class='card']"))
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.Replace(text, "\n", "", 1)
|
||||
return text
|
||||
return text, nil
|
||||
}
|
||||
@@ -6,27 +6,19 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
dbpath = "data/Chat/"
|
||||
dbfile = dbpath + "kimoi.json"
|
||||
)
|
||||
|
||||
var (
|
||||
poke = rate.NewManager(time.Minute*5, 8) // 戳一戳
|
||||
engine = control.Register("chat", order.PrioChat, &control.Options{
|
||||
poke = rate.NewManager[int64](time.Minute*5, 8) // 戳一戳
|
||||
engine = control.Register("chat", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]\n- mua | 啾咪 | 摸 | 上你 | 傻 | 裸 | 贴 | 老婆 | 抱 | 亲 | 一下 | 咬 | 操 | 123 | 进去 | 调教 | 搓 | 让 | 捏 | 挤 | 略 | 呐 | 原味 | 胖次 | 内裤 | 内衣 | 衣服 | ghs | 批 | 憨批 | kkp | 咕 | 骚 | 喜欢 | suki | 好き | 看 | 不能 | 砸了 | 透 | 口我 | 草我 | 自慰 | onani | オナニー | 炸了 | 色图 | 涩图 | 告白 | 对不起 | 回来 | 吻 | 软 | 壁咚 | 掰开 | 女友 | 是 | 喵 | 嗷呜 | 叫 | 拜 | 佬 | awsl | 臭 | 香 | 腿 | 张开 | 脚 | 脸 | 头发 | 手 | pr | 舔 | 小穴 | 腰 | 诶嘿嘿 | 可爱 | 扭蛋 | 鼻 | 眼 | 色气 | 推 | 床 | 举 | 手冲 | 饿 | 变 | 敲 | 爬 | 怕 | 冲 | 射 | 不穿 | 迫害 | 猫粮 | 揪尾巴 | 薄荷 | 早 | 晚安 | 揉 | 榨 | 掐 | 胸 | 奶子 | 欧派 | 嫩 | 蹭 | 牵手 | 握手 | 拍照 | w | 睡不着 | 欧尼酱 | 哥 | 爱你 | 过来 | 自闭 | 打不过 | 么么哒 | 很懂 | 膝枕 | 累了 | 安慰 | 洗澡 | 一起睡觉 | 一起 | 多大 | 姐姐 | 糖 | 嗦 | 牛子 | 🐂子 | 🐮子 | 嫌弃 | 紧 | baka | 笨蛋 | 插 | 插进来 | 屁股 | 翘 | 翘起来 | 抬 | 抬起 | 爸 | 傲娇 | rua | 咕噜咕噜 | 咕噜 | 上床 | 做爱 | 吃掉 | 吃 | 揪 | 种草莓 | 种草 | 掀 | 妹 | 病娇 | 嘻",
|
||||
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
|
||||
})
|
||||
kimomap = make(kimo, 256)
|
||||
chatList = make([]string, 0, 256)
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
@@ -111,13 +103,4 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
initChatList(func() {
|
||||
engine.OnFullMatchGroup(chatList, zero.OnlyToMe).SetBlock(true).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
key := ctx.MessageString()
|
||||
val := *kimomap[key]
|
||||
text := val[rand.Intn(len(val))]
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -6,15 +6,14 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("choose", order.PrioChoose, &control.Options{
|
||||
engine := control.Register("choose", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "choose\n" +
|
||||
"- 选择可口可乐还是百事可乐\n" +
|
||||
72
plugin/chouxianghua/chouxianghua.go
Normal file
72
plugin/chouxianghua/chouxianghua.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Package chouxianghua 抽象话转化
|
||||
package chouxianghua
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("chouxianghua", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "抽象话\n- 抽象翻译xxx",
|
||||
PublicDataFolder: "ChouXiangHua",
|
||||
})
|
||||
|
||||
en.OnRegex("^抽象翻译((\\s|[\\r\\n]|[\\p{Han}\\p{P}A-Za-z0-9])+)$",
|
||||
ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = en.DataFolder() + "cxh.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = en.GetLazyData("cxh.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("pinyin", &pinyin{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("pinyin")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Printf("[chouxianghua]读取%d条拼音", n)
|
||||
return true
|
||||
}),
|
||||
).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
r := cx(ctx.State["regex_matched"].([]string)[1])
|
||||
ctx.SendChain(message.Text(r))
|
||||
})
|
||||
}
|
||||
|
||||
func cx(s string) (r string) {
|
||||
h := []rune(s)
|
||||
for i := 0; i < len(h); i++ {
|
||||
if i < len(h)-1 {
|
||||
e := getEmojiByPronun(getPronunByDWord(h[i], h[i+1]))
|
||||
if e != "" {
|
||||
r += e
|
||||
i++
|
||||
continue
|
||||
}
|
||||
}
|
||||
e := getEmojiByPronun(getPinyinByWord(string(h[i])))
|
||||
if e != "" {
|
||||
r += e
|
||||
continue
|
||||
}
|
||||
r += string(h[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package chouxianghua
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type pinyin struct {
|
||||
Word string `db:"word"`
|
||||
Pronun string `db:"pronunciation"`
|
||||
@@ -9,6 +11,8 @@ type emoji struct {
|
||||
Emoji string `db:"emoji"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getPinyinByWord(word string) string {
|
||||
var p pinyin
|
||||
_ = db.Find("pinyin", &p, "where word = '"+word+"'")
|
||||
@@ -2,60 +2,55 @@
|
||||
package coser
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
var (
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36"
|
||||
coserURL = "http://ovooa.com/API/cosplay/api.php"
|
||||
datestr = regexp.MustCompile(`/\d{4}-\d{2}-\d{2}/`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("coser", order.PrioCoser, &control.Options{
|
||||
control.Register("coser", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "三次元小姐姐\n- coser",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
data, err := web.ReqWith(coserURL, "GET", "", ua)
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), coserURL, "GET", "", ua)
|
||||
if err != nil {
|
||||
log.Println("err为:", err)
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
var m message.Message
|
||||
text := gjson.Get(helper.BytesToString(data), "data.Title").String()
|
||||
m = append(m,
|
||||
message.CustomNode(
|
||||
ctx.Event.Sender.NickName,
|
||||
ctx.Event.UserID,
|
||||
text,
|
||||
))
|
||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(text))}
|
||||
ds := ""
|
||||
gjson.Get(helper.BytesToString(data), "data.data").ForEach(func(_, value gjson.Result) bool {
|
||||
m = append(m,
|
||||
message.CustomNode(
|
||||
ctx.Event.Sender.NickName,
|
||||
ctx.Event.UserID,
|
||||
[]message.MessageSegment{
|
||||
message.Image(value.String()),
|
||||
}),
|
||||
)
|
||||
if ds == "" {
|
||||
ds = datestr.FindString(value.String())
|
||||
} else if ds != datestr.FindString(value.String()) {
|
||||
return false
|
||||
}
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(value.String())))
|
||||
return true
|
||||
})
|
||||
|
||||
if id := ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
m).Get("message_id").Int(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
})
|
||||
}
|
||||
73
plugin/cpstory/cpstory.go
Normal file
73
plugin/cpstory/cpstory.go
Normal file
@@ -0,0 +1,73 @@
|
||||
// Package cpstory cp短打
|
||||
package cpstory
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cpstory", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "cp短打\n- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
|
||||
PublicDataFolder: "CpStory",
|
||||
})
|
||||
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "cp.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("cp.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("cp_story", &cpstory{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("cp_story")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Printf("[cpstory]读取%d条故事", n)
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnRegex("^组cp.*?(\\d+).*?(\\d+)", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cs := getRandomCpStory()
|
||||
gong := ctx.CardOrNickName(math.Str2Int64(ctx.State["regex_matched"].([]string)[1]))
|
||||
shou := ctx.CardOrNickName(math.Str2Int64(ctx.State["regex_matched"].([]string)[2]))
|
||||
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
|
||||
text = strings.ReplaceAll(text, "<受>", shou)
|
||||
text = strings.ReplaceAll(text, cs.Gong, gong)
|
||||
text = strings.ReplaceAll(text, cs.Shou, gong)
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
engine.OnPrefix("磕cp", getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cs := getRandomCpStory()
|
||||
params := strings.Split(ctx.State["args"].(string), " ")
|
||||
if len(params) < 2 {
|
||||
ctx.SendChain(message.Text(ctx.Event.MessageID), message.Text("请用空格分开两个人名"))
|
||||
} else {
|
||||
gong := params[0]
|
||||
shou := params[1]
|
||||
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
|
||||
text = strings.ReplaceAll(text, "<受>", shou)
|
||||
text = strings.ReplaceAll(text, cs.Gong, gong)
|
||||
text = strings.ReplaceAll(text, cs.Shou, gong)
|
||||
ctx.SendChain(message.Text(text))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package cpstory
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type cpstory struct {
|
||||
ID int64 `db:"id"`
|
||||
Gong string `db:"gong"`
|
||||
@@ -7,6 +9,8 @@ type cpstory struct {
|
||||
Story string `db:"story"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getRandomCpStory() (cs cpstory) {
|
||||
_ = db.Pick("cp_story", &cs)
|
||||
return
|
||||
72
plugin/curse/curse.go
Normal file
72
plugin/curse/curse.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Package curse 骂人插件(求骂,自卫)
|
||||
package curse
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
)
|
||||
|
||||
const (
|
||||
minLevel = "min"
|
||||
maxLevel = "max"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("curse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "骂人(求骂,自卫)\n- 骂我\n- 大力骂我",
|
||||
PublicDataFolder: "Curse",
|
||||
})
|
||||
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "curse.db"
|
||||
_, err := engine.GetLazyData("curse.db", true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("curse", &curse{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
c, err := db.Count("curse")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Infoln("[curse]加载", c, "条骂人语录")
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnFullMatch("骂我", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
text := getRandomCurseByLevel(minLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnFullMatch("大力骂我", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
text := getRandomCurseByLevel(maxLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnKeywordGroup([]string{"他妈", "公交车", "你妈", "操", "屎", "去死", "快死", "我日", "逼", "尼玛", "艾滋", "癌症", "有病", "烦你", "你爹", "屮", "cnm"}, zero.OnlyToMe, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
text := getRandomCurseByLevel(maxLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
package curse
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type curse struct {
|
||||
ID uint32 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
Level string `db:"level"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getRandomCurseByLevel(level string) (c curse) {
|
||||
_ = db.Find("curse", &c, "where level = '"+level+"' ORDER BY RANDOM() limit 1")
|
||||
return
|
||||
@@ -4,53 +4,39 @@ package deepdanbooru
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/danbooru"
|
||||
"github.com/FloatTech/AnimeAPI/saucenao"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const cachefile = "data/danbooru/"
|
||||
|
||||
func init() { // 插件主体
|
||||
_ = os.RemoveAll(cachefile)
|
||||
err := os.MkdirAll(cachefile, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
engine := control.Register("danbooru", order.PrioDanbooru, &control.Options{
|
||||
engine := control.Register("danbooru", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "二次元图片标签识别\n" +
|
||||
"- 鉴赏图片[图片]",
|
||||
PrivateDataFolder: "danbooru",
|
||||
})
|
||||
|
||||
cachefolder := engine.DataFolder()
|
||||
|
||||
// 上传一张图进行评价
|
||||
engine.OnKeywordGroup([]string{"鉴赏图片"}, zero.OnlyGroup, ctxext.CmdMatch, ctxext.MustGiven).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"鉴赏图片"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
for _, url := range ctx.State["image_url"].([]string) {
|
||||
name := ""
|
||||
r, err := saucenao.SauceNAO(url)
|
||||
if err != nil {
|
||||
name = "未知图片"
|
||||
} else {
|
||||
name = r[0].Title
|
||||
}
|
||||
t, err := danbooru.TagURL(name, url)
|
||||
t, err := danbooru.TagURL("", url)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
digest := md5.Sum(helper.StringToBytes(url))
|
||||
f := cachefile + hex.EncodeToString(digest[:])
|
||||
f := cachefolder + hex.EncodeToString(digest[:])
|
||||
if file.IsNotExist(f) {
|
||||
_ = writer.SavePNG2Path(f, t)
|
||||
}
|
||||
@@ -2,47 +2,54 @@
|
||||
package diana
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin_diana/data"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/diana/data"
|
||||
)
|
||||
|
||||
var engine = control.Register("diana", order.PrioDiana, &control.Options{
|
||||
var engine = control.Register("diana", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "嘉然\n" +
|
||||
"- 小作文\n" +
|
||||
"- 发大病\n" +
|
||||
"- 教你一篇小作文[作文]\n" +
|
||||
"- [回复]查重",
|
||||
PublicDataFolder: "Diana",
|
||||
})
|
||||
|
||||
func init() {
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
err := data.LoadText(engine.DataFolder() + "text.db")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// 随机发送一篇上面的小作文
|
||||
engine.OnFullMatch("小作文").SetBlock(true).
|
||||
engine.OnFullMatch("小作文", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
// 绕过第一行发病
|
||||
ctx.SendChain(message.Text(data.RandText()))
|
||||
})
|
||||
// 逆天
|
||||
engine.OnFullMatch("发大病").SetBlock(true).
|
||||
engine.OnFullMatch("发大病", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 第一行是发病
|
||||
ctx.SendChain(message.Text(data.HentaiText()))
|
||||
})
|
||||
// 增加小作文
|
||||
engine.OnRegex(`^教你一篇小作文(.*)$`, zero.AdminPermission).SetBlock(true).
|
||||
engine.OnRegex(`^教你一篇小作文(.*)$`, zero.AdminPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := data.AddText(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("记住啦!"))
|
||||
}
|
||||
70
plugin/diana/data/text.go
Normal file
70
plugin/diana/data/text.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Package data 加载位于 datapath 的小作文
|
||||
package data
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
binutils "github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var db = sql.Sqlite{}
|
||||
|
||||
type text struct {
|
||||
ID int64 `db:"id"`
|
||||
Data string `db:"data"`
|
||||
}
|
||||
|
||||
// LoadText 加载小作文
|
||||
func LoadText(dbfile string) error {
|
||||
_, err := file.GetLazyData(dbfile, false)
|
||||
db.DBPath = dbfile
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Create("text", &text{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := db.Count("text")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Printf("[Diana]读取%d条小作文", c)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddText 添加小作文
|
||||
func AddText(txt string) error {
|
||||
s := md5.Sum(binutils.StringToBytes(txt))
|
||||
i := binary.LittleEndian.Uint64(s[:8])
|
||||
return db.Insert("text", &text{ID: int64(i), Data: txt})
|
||||
}
|
||||
|
||||
// RandText 随机小作文
|
||||
func RandText() string {
|
||||
var t text
|
||||
err := db.Pick("text", &t)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return t.Data
|
||||
}
|
||||
|
||||
// HentaiText 发大病
|
||||
func HentaiText() string {
|
||||
var t text
|
||||
err := db.Find("text", &t, "where id = -3802576048116006195")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return t.Data
|
||||
}
|
||||
89
plugin/diana/zhiwang.go
Normal file
89
plugin/diana/zhiwang.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// Package diana 嘉然相关
|
||||
package diana
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
)
|
||||
|
||||
// 小作文查重: 回复要查的消息 查重
|
||||
func init() {
|
||||
engine.OnMessage(func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
if msg[0].Type != "reply" {
|
||||
return false
|
||||
}
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "text" {
|
||||
text := elem.Data["text"]
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.ReplaceAll(text, "\r", "")
|
||||
text = strings.ReplaceAll(text, "\n", "")
|
||||
if text == "查重" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
msg := ctx.GetMessage(message.NewMessageIDFromString(ctx.Event.Message[0].Data["id"])).Elements[0].Data["text"]
|
||||
result, err := zhiwangapi(msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if result.Get("code").Int() != 0 {
|
||||
ctx.SendChain(message.Text("api返回错误:", result.Get("code").Int()))
|
||||
return
|
||||
}
|
||||
if result.Get("data.related.#").Int() == 0 {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("枝网没搜到,查重率为0%,鉴定为原创")))
|
||||
return
|
||||
}
|
||||
related := result.Get("data.related.0.reply").Map()
|
||||
rate := result.Get("data.related.0.rate").Float()
|
||||
relatedcontent := related["content"].String()
|
||||
if len(relatedcontent) > 102 {
|
||||
relatedcontent = relatedcontent[:102] + "....."
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(
|
||||
"枝网文本复制检测报告(简洁)", "\n",
|
||||
"查重时间: ", time.Now().Format("2006-01-02 15:04:05"), "\n",
|
||||
"总文字复制比: ", math.Floor(rate*100), "%", "\n",
|
||||
"相似小作文:", "\n", relatedcontent, "\n",
|
||||
"获赞数:", related["like_num"].String(), "\n",
|
||||
result.Get("data.related.0.reply_url").String(), "\n",
|
||||
"作者: ", related["m_name"].String(), "\n",
|
||||
"发表时间: ", time.Unix(int64(related["ctime"].Float()), 0).Format("2006-01-02 15:04:05"), "\n",
|
||||
"查重结果仅作参考,请注意辨别是否为原创", "\n",
|
||||
"数据来源: https://asoulcnki.asia/",
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
||||
func zhiwangapi(text string) (*gjson.Result, error) {
|
||||
b, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
w.WriteString("{\n\"text\":\"")
|
||||
w.WriteString(text)
|
||||
w.WriteString("\"\n}")
|
||||
})
|
||||
|
||||
data, err := web.PostData("https://asoulcnki.asia/v1/api/check", "application/json", bytes.NewReader(b))
|
||||
cl()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := gjson.ParseBytes(data)
|
||||
return &result, nil
|
||||
}
|
||||
53
plugin/drift_bottle/data.go
Normal file
53
plugin/drift_bottle/data.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package driftbottle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc64"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
)
|
||||
|
||||
type bottle struct {
|
||||
ID int64 `db:"id"` // ID qq_grp_name_msg 的 crc64
|
||||
QQ int64 `db:"qq"` // QQ 发送者 qq
|
||||
Grp int64 `db:"grp"` // Grp 限制抽出的群 / 人(负数)
|
||||
Name string `db:"name"` // Name 发送者 昵称
|
||||
Msg string `db:"msg"` // Msg 消息,纯文本
|
||||
}
|
||||
|
||||
var sea = &sql.Sqlite{}
|
||||
var seamu sync.RWMutex
|
||||
|
||||
func newBottle(qq, grp int64, name, msg string) *bottle {
|
||||
id := int64(crc64.Checksum(binary.StringToBytes(fmt.Sprintf("%d_%d_%s_%s", qq, grp, name, msg)), crc64.MakeTable(crc64.ISO)))
|
||||
return &bottle{ID: id, QQ: qq, Grp: grp, Name: name, Msg: msg}
|
||||
}
|
||||
|
||||
func (b *bottle) throw(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Insert(channel, b)
|
||||
}
|
||||
|
||||
func (b *bottle) destroy(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Del(channel, "WHERE id="+strconv.FormatInt(b.ID, 10))
|
||||
}
|
||||
|
||||
// fetchBottle grp != 0
|
||||
func fetchBottle(db *sql.Sqlite, channel string, grp int64) (*bottle, error) {
|
||||
seamu.RLock()
|
||||
defer seamu.RUnlock()
|
||||
b := new(bottle)
|
||||
return b, db.Find(channel, b, "WHERE grp=0 or grp="+strconv.FormatInt(grp, 10)+" ORDER BY RANDOM() limit 1")
|
||||
}
|
||||
|
||||
func createChannel(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Create(channel, &bottle{})
|
||||
}
|
||||
133
plugin/drift_bottle/main.go
Normal file
133
plugin/drift_bottle/main.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// Package driftbottle 漂流瓶
|
||||
package driftbottle
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("driftbottle", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "漂流瓶\n- (在群xxx)丢漂流瓶(到频道xxx) [消息]\n- (从频道xxx)捡漂流瓶\n- @BOT 创建频道 xxx\n- 跳入(频道)海中\n- 注:不显式限制时,私聊发送可在所有群抽到,群聊发送仅可在本群抽到,默认频道为 global",
|
||||
PrivateDataFolder: "driftbottle",
|
||||
})
|
||||
sea.DBPath = en.DataFolder() + "sea.db"
|
||||
err := sea.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = createChannel(sea, "global")
|
||||
en.OnRegex(`^(在群\d+)?丢漂流瓶(到频道\w+)?\s+(.*)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
grp := ctx.Event.GroupID
|
||||
channel := "global"
|
||||
msg := msgs[3]
|
||||
var err error
|
||||
if msgs[1] != "" {
|
||||
grp, err = strconv.ParseInt(msgs[1][6:], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("群号非法!"))
|
||||
return
|
||||
}
|
||||
}
|
||||
if msgs[2] != "" {
|
||||
channel = msgs[2][9:]
|
||||
}
|
||||
if msg == "" {
|
||||
ctx.SendChain(message.Text("消息为空!"))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[driftbottle]", grp, channel, msg)
|
||||
err = newBottle(
|
||||
ctx.Event.UserID,
|
||||
grp,
|
||||
ctx.CardOrNickName(ctx.Event.UserID),
|
||||
msg,
|
||||
).throw(sea, channel)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你将它扔进大海,希望有人捞到吧~")))
|
||||
})
|
||||
en.OnRegex(`^(从频道\w+)?捡漂流瓶$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
grp = -ctx.Event.UserID
|
||||
}
|
||||
if grp == 0 {
|
||||
ctx.SendChain(message.Text("找不到对象!"))
|
||||
return
|
||||
}
|
||||
channel := "global"
|
||||
if msgs[1] != "" {
|
||||
channel = msgs[1][9:]
|
||||
}
|
||||
logrus.Debugln("[driftbottle]", grp, channel)
|
||||
b, err := fetchBottle(sea, channel, grp)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err = b.destroy(sea, channel)
|
||||
wg.Done()
|
||||
}()
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(
|
||||
ctx.Event.MessageID,
|
||||
message.Text("你在海边捡到了一个来自 ", b.Name, " 的漂流瓶,打开瓶子,里面有一张纸条,写着:"),
|
||||
message.Text(b.Msg),
|
||||
),
|
||||
)
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
en.OnPrefix("创建频道", zero.SuperUserPermission, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
channel := strings.TrimRight(ctx.State["args"].(string), " ")
|
||||
if channel == "" {
|
||||
ctx.SendChain(message.Text("频道名为空!"))
|
||||
return
|
||||
}
|
||||
err := createChannel(sea, channel)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("成功~")))
|
||||
})
|
||||
en.OnRegex(`^跳入(\w+)?海中$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
channel := "global"
|
||||
if msgs[1] != "" {
|
||||
channel = msgs[1]
|
||||
}
|
||||
seamu.RLock()
|
||||
c, err := sea.Count(channel)
|
||||
seamu.RUnlock()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你缓缓走入大海,感受着海浪轻柔地拍打着你的小腿,膝盖……\n波浪卷着你的腰腹,你感觉有些把握不住平衡了……\n……\n你沉入海中,", c, " 个物体与你一同沉浮。\n不知何处涌来一股暗流,你失去了意识。")))
|
||||
})
|
||||
}
|
||||
249
plugin/emojimix/emoji.go
Normal file
249
plugin/emojimix/emoji.go
Normal file
@@ -0,0 +1,249 @@
|
||||
// Package emojimix 合成emoji
|
||||
package emojimix
|
||||
|
||||
var emojis = map[rune]int64{
|
||||
128516: 20201001, // 😄 grinning face with smiling eyes
|
||||
128512: 20201001, // 😀 grinning face
|
||||
128578: 20201001, // 🙂 slightly smiling face
|
||||
128579: 20201001, // 🙃 upside-down face
|
||||
128521: 20201001, // 😉 winking face
|
||||
128522: 20201001, // 😊 smiling face with smiling eyes
|
||||
128518: 20201001, // 😆 grinning squinting face
|
||||
128515: 20201001, // 😃 grinning face with big eyes
|
||||
128513: 20201001, // 😁 beaming face with smiling eyes
|
||||
129315: 20201001, // 🤣 rolling on the floor laughing
|
||||
128517: 20201001, // 😅 grinning face with sweat
|
||||
128514: 20201001, // 😂 face with tears of joy
|
||||
128519: 20201001, // 😇 smiling face with halo
|
||||
129392: 20201001, // 🥰 smiling face with hearts
|
||||
128525: 20201001, // 😍 smiling face with heart-eyes
|
||||
128536: 20201001, // 😘 face blowing a kiss
|
||||
129321: 20201001, // 🤩 star-struck
|
||||
128535: 20201001, // 😗 kissing face
|
||||
128538: 20201001, // 😚 kissing face with closed eyes
|
||||
128537: 20201001, // 😙 kissing face with smiling eyes
|
||||
128539: 20201001, // 😛 face with tongue
|
||||
128541: 20201001, // 😝 squinting face with tongue
|
||||
128523: 20201001, // 😋 face savoring food
|
||||
129394: 20201001, // 🥲 smiling face with tear
|
||||
129297: 20201001, // 🤑 money-mouth face
|
||||
128540: 20201001, // 😜 winking face with tongue
|
||||
129303: 20201001, // 🤗 smiling face with open hands hugs
|
||||
129323: 20201001, // 🤫 shushing face quiet whisper
|
||||
129300: 20201001, // 🤔 thinking face question hmmm
|
||||
129325: 20201001, // 🤭 face with hand over mouth embarrassed
|
||||
129320: 20201001, // 🤨 face with raised eyebrow question
|
||||
129296: 20201001, // 🤐 zipper-mouth face
|
||||
128528: 20201001, // 😐 neutral face
|
||||
128529: 20201001, // 😑 expressionless face
|
||||
128566: 20201001, // 😶 face without mouth
|
||||
129322: 20201001, // 🤪 zany face
|
||||
128527: 20201001, // 😏 smirking face suspicious
|
||||
128530: 20201001, // 😒 unamused face
|
||||
128580: 20201001, // 🙄 face with rolling eyes
|
||||
128556: 20201001, // 😬 grimacing face
|
||||
128558: 20210218, // 😮 face exhaling
|
||||
129317: 20201001, // 🤥 lying face
|
||||
128524: 20201001, // 😌 relieved face
|
||||
128532: 20201001, // 😔 pensive face
|
||||
128554: 20201001, // 😪 sleepy face
|
||||
129316: 20201001, // 🤤 drooling face
|
||||
128564: 20201001, // 😴 sleeping face
|
||||
128567: 20201001, // 😷 face with medical mask
|
||||
129298: 20201001, // 🤒 face with thermometer
|
||||
129301: 20201001, // 🤕 face with head-bandage
|
||||
129314: 20201001, // 🤢 nauseated face
|
||||
129326: 20201001, // 🤮 face vomiting throw
|
||||
129319: 20201001, // 🤧 sneezing face
|
||||
129397: 20201001, // 🥵 hot face warm
|
||||
129398: 20201001, // 🥶 cold face freezing ice
|
||||
128565: 20201001, // 😵 face with crossed-out eyes
|
||||
129396: 20201001, // 🥴 woozy face drunk tipsy drug high
|
||||
129327: 20201001, // 🤯 exploding head mindblow
|
||||
129312: 20201001, // 🤠 cowboy hat face
|
||||
129395: 20201001, // 🥳 partying face
|
||||
129400: 20201001, // 🥸 disguised face
|
||||
129488: 20201001, // 🧐 face with monocle glasses
|
||||
128526: 20201001, // 😎 smiling face with sunglasses
|
||||
128533: 20201001, // 😕 confused face
|
||||
128543: 20201001, // 😟 worried face
|
||||
128577: 20201001, // 🙁 slightly frowning face
|
||||
128559: 20201001, // 😯 hushed face
|
||||
128562: 20201001, // 😲 astonished face
|
||||
129299: 20201001, // 🤓 nerd face glasses
|
||||
128563: 20201001, // 😳 flushed face
|
||||
129402: 20201001, // 🥺 pleading face
|
||||
128551: 20201001, // 😧 anguished face
|
||||
128552: 20201001, // 😨 fearful face
|
||||
128550: 20201001, // 😦 frowning face with open mouth
|
||||
128560: 20201001, // 😰 anxious face with sweat
|
||||
128549: 20201001, // 😥 sad but relieved face
|
||||
128557: 20201001, // 😭 loudly crying face
|
||||
128553: 20201001, // 😩 weary face
|
||||
128546: 20201001, // 😢 crying face
|
||||
128547: 20201001, // 😣 persevering face
|
||||
128544: 20201001, // 😠 angry face
|
||||
128531: 20201001, // 😓 downcast face with sweat
|
||||
128534: 20201001, // 😖 confounded face
|
||||
129324: 20201001, // 🤬 face with symbols on mouth
|
||||
128542: 20201001, // 😞 disappointed face
|
||||
128555: 20201001, // 😫 tired face
|
||||
128548: 20201001, // 😤 face with steam from nose
|
||||
129393: 20201001, // 🥱 yawning face
|
||||
128169: 20201001, // 💩 pile of poo
|
||||
128545: 20201001, // 😡 pouting face
|
||||
128561: 20201001, // 😱 face screaming in fear
|
||||
128127: 20201001, // 👿 angry face with horns
|
||||
128128: 20201001, // 💀 skull
|
||||
128125: 20201001, // 👽 alien
|
||||
128520: 20201001, // 😈 smiling face with horns devil
|
||||
129313: 20201001, // 🤡 clown face
|
||||
128123: 20201001, // 👻 ghost
|
||||
129302: 20201001, // 🤖 robot
|
||||
128175: 20201001, // 💯 hundred points percent
|
||||
128064: 20201001, // 👀 eyes
|
||||
127801: 20201001, // 🌹 rose flower
|
||||
127804: 20201001, // 🌼 blossom flower
|
||||
127799: 20201001, // 🌷 tulip flower
|
||||
127797: 20201001, // 🌵 cactus
|
||||
127821: 20201001, // 🍍 pineapple
|
||||
127874: 20201001, // 🎂 birthday cake
|
||||
127751: 20210831, // 🌇 sunset
|
||||
129473: 20201001, // 🧁 cupcake muffin
|
||||
127911: 20210521, // 🎧 headphone earphone
|
||||
127800: 20210218, // 🌸 cherry blossom flower
|
||||
129440: 20201001, // 🦠 microbe germ bacteria virus covid corona
|
||||
128144: 20201001, // 💐 bouquet flowers
|
||||
127789: 20201001, // 🌭 hot dog food
|
||||
128139: 20201001, // 💋 kiss mark lips
|
||||
127875: 20201001, // 🎃 jack-o-lantern pumpkin
|
||||
129472: 20201001, // 🧀 cheese wedge
|
||||
9749: 20201001, // ☕ hot beverage coffee cup tea
|
||||
127882: 20201001, // 🎊 confetti ball
|
||||
127880: 20201001, // 🎈 balloon
|
||||
9924: 20201001, // ⛄ snowman without snow
|
||||
128142: 20201001, // 💎 gem stone crystal diamond
|
||||
127794: 20201001, // 🌲 evergreen tree
|
||||
129410: 20210218, // 🦂 scorpion
|
||||
128584: 20201001, // 🙈 see-no-evil monkey
|
||||
128148: 20201001, // 💔 broken heart
|
||||
128140: 20201001, // 💌 love letter heart
|
||||
128152: 20201001, // 💘 heart with arrow
|
||||
128159: 20201001, // 💟 heart decoration
|
||||
128158: 20201001, // 💞 revolving hearts
|
||||
128147: 20201001, // 💓 beating heart
|
||||
128149: 20201001, // 💕 two hearts
|
||||
128151: 20201001, // 💗 growing heart
|
||||
129505: 20201001, // 🧡 orange heart
|
||||
128155: 20201001, // 💛 yellow heart
|
||||
10084: 20210218, // ❤ mending heart
|
||||
128156: 20201001, // 💜 purple heart
|
||||
128154: 20201001, // 💚 green heart
|
||||
128153: 20201001, // 💙 blue heart
|
||||
129294: 20201001, // 🤎 brown heart
|
||||
129293: 20201001, // 🤍 white heart
|
||||
128420: 20201001, // 🖤 black heart
|
||||
128150: 20201001, // 💖 sparkling heart
|
||||
128157: 20201001, // 💝 heart with ribbon
|
||||
127873: 20211115, // 🎁 wrapped-gift
|
||||
129717: 20211115, // 🪵 wood
|
||||
127942: 20211115, // 🏆 trophy
|
||||
127838: 20210831, // 🍞 bread
|
||||
128240: 20201001, // 📰 newspaper
|
||||
128302: 20201001, // 🔮 crystal ball
|
||||
128081: 20201001, // 👑 crown
|
||||
128055: 20201001, // 🐷 pig face
|
||||
129412: 20210831, // 🦄 unicorn
|
||||
127771: 20201001, // 🌛 first quarter moon face
|
||||
129420: 20201001, // 🦌 deer
|
||||
129668: 20210521, // 🪄 magic wand
|
||||
128171: 20201001, // 💫 dizzy
|
||||
128049: 20201001, // 🐱 meow cat face
|
||||
129409: 20201001, // 🦁 lion
|
||||
128293: 20201001, // 🔥 fire
|
||||
128038: 20210831, // 🐦 bird
|
||||
129415: 20201001, // 🦇 bat
|
||||
129417: 20210831, // 🦉 owl
|
||||
127752: 20201001, // 🌈 rainbow
|
||||
128053: 20201001, // 🐵 monkey face
|
||||
128029: 20201001, // 🐝 honeybee bumblebee wasp
|
||||
128034: 20201001, // 🐢 turtle
|
||||
128025: 20201001, // 🐙 octopus
|
||||
129433: 20201001, // 🦙 llama alpaca
|
||||
128016: 20210831, // 🐐 goat
|
||||
128060: 20201001, // 🐼 panda
|
||||
128040: 20201001, // 🐨 koala
|
||||
129445: 20201001, // 🦥 sloth
|
||||
128059: 20210831, // 🐻 bear
|
||||
128048: 20201001, // 🐰 rabbit face
|
||||
129428: 20201001, // 🦔 hedgehog
|
||||
128054: 20211115, // 🐶 dog puppy
|
||||
128041: 20211115, // 🐩 poodle dog
|
||||
129437: 20211115, // 🦝 raccoon
|
||||
128039: 20211115, // 🐧 penguin
|
||||
128012: 20210218, // 🐌 snail
|
||||
128045: 20201001, // 🐭 mouse face rat
|
||||
128031: 20210831, // 🐟 fish
|
||||
127757: 20201001, // 🌍 globe showing Europe-Africa
|
||||
127774: 20201001, // 🌞 sun with face
|
||||
127775: 20201001, // 🌟 glowing star
|
||||
11088: 20201001, // ⭐ star
|
||||
127772: 20201001, // 🌜 last quarter moon face
|
||||
129361: 20201001, // 🥑 avocado
|
||||
127820: 20211115, // 🍌 banana
|
||||
127827: 20210831, // 🍓 strawberry
|
||||
127819: 20210521, // 🍋 lemon
|
||||
127818: 20211115, // 🍊 tangerine orange
|
||||
}
|
||||
|
||||
var qqface = map[int]rune{
|
||||
0: 128558, // 😮 face exhaling
|
||||
1: 128556, // 😬 grimacing face
|
||||
2: 128525, // 😍 smiling face with heart-eyes
|
||||
4: 128526, // 😎 smiling face with sunglasses
|
||||
5: 128557, // 😭 loudly crying face
|
||||
6: 129402, // 🥺 pleading face
|
||||
7: 129296, // 🤐 zipper-mouth face
|
||||
8: 128554, // 😪 sleepy face
|
||||
11: 128545, // 😡 pouting face
|
||||
12: 128539, // 😛 face with tongue
|
||||
13: 128513, // 😁 beaming face with smiling eyes
|
||||
14: 128578, // 🙂 slightly smiling face
|
||||
15: 128577, // 🙁 slightly frowning face
|
||||
16: 128526, // 😎 smiling face with sunglasses
|
||||
19: 129326, // 🤮 face vomiting throw
|
||||
20: 129325, // 🤭 face with hand over mouth embarrassed
|
||||
21: 128522, // 😊 smiling face with smiling eyes
|
||||
23: 128533, // 😕 confused face
|
||||
24: 128523, // 😋 face savoring food
|
||||
27: 128531, // 😓 downcast face with sweat
|
||||
28: 128516, // 😄 grinning face with smiling eyes
|
||||
31: 129324, // 🤬 face with symbols on mouth
|
||||
32: 129300, // 🤔 thinking face question hmmm
|
||||
33: 129323, // 🤫 shushing face quiet whisper
|
||||
34: 128565, // 😵 face with crossed-out eyes
|
||||
35: 128547, // 😣 persevering face
|
||||
37: 128128, // 💀 skull
|
||||
46: 128055, // 🐷 pig face
|
||||
53: 127874, // 🎂 birthday cake
|
||||
59: 128169, // 💩 pile of poo
|
||||
60: 9749, // ☕ hot beverage coffee cup tea
|
||||
63: 127801, // 🌹 rose flower
|
||||
66: 10084, // ❤ mending heart
|
||||
67: 128148, // 💔 broken heart
|
||||
69: 127873, // 🎁 wrapped-gift
|
||||
74: 127774, // 🌞 sun with face
|
||||
75: 127772, // 🌜 last quarter moon face
|
||||
96: 128517, // 😅 grinning face with sweat
|
||||
104: 129393, // 🥱 yawning face
|
||||
109: 128535, // 😗 kissing face
|
||||
110: 128562, // 😲 astonished face
|
||||
111: 129402, // 🥺 pleading face
|
||||
172: 128539, // 😛 face with tongue
|
||||
182: 128514, // 😂 face with tears of joy
|
||||
187: 128123, // 👻 ghost
|
||||
247: 128567, // 😷 face with medical mask
|
||||
272: 128579, // 🙃 upside-down face
|
||||
320: 129395, // 🥳 partying face
|
||||
325: 128561, // 😱 face screaming in fear
|
||||
}
|
||||
101
plugin/emojimix/mix.go
Normal file
101
plugin/emojimix/mix.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Package emojimix 合成emoji
|
||||
package emojimix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%x.png"
|
||||
|
||||
func init() {
|
||||
control.Register("emojimix", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "合成emoji\n" +
|
||||
"- [emoji][emoji]",
|
||||
}).OnMessage(match).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
r := ctx.State["emojimix"].([]rune)
|
||||
logrus.Debugln("[emojimix] match:", r)
|
||||
r1, r2 := r[0], r[1]
|
||||
u1 := fmt.Sprintf(bed, emojis[r1], r1, r1, r2)
|
||||
u2 := fmt.Sprintf(bed, emojis[r2], r2, r2, r1)
|
||||
logrus.Debugln("[emojimix] u1:", u1)
|
||||
logrus.Debugln("[emojimix] u2:", u2)
|
||||
resp1, err := http.Head(u1)
|
||||
if err == nil {
|
||||
resp1.Body.Close()
|
||||
if resp1.StatusCode == http.StatusOK {
|
||||
ctx.SendChain(message.Image(u1))
|
||||
return
|
||||
}
|
||||
}
|
||||
resp2, err := http.Head(u2)
|
||||
if err == nil {
|
||||
resp2.Body.Close()
|
||||
if resp2.StatusCode == http.StatusOK {
|
||||
ctx.SendChain(message.Image(u2))
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func match(ctx *zero.Ctx) bool {
|
||||
logrus.Debugln("[emojimix] msg:", ctx.Event.Message)
|
||||
if len(ctx.Event.Message) == 2 {
|
||||
r1 := face2emoji(ctx.Event.Message[0])
|
||||
if _, ok := emojis[r1]; !ok {
|
||||
return false
|
||||
}
|
||||
r2 := face2emoji(ctx.Event.Message[1])
|
||||
if _, ok := emojis[r2]; !ok {
|
||||
return false
|
||||
}
|
||||
ctx.State["emojimix"] = []rune{r1, r2}
|
||||
return true
|
||||
}
|
||||
|
||||
r := []rune(ctx.Event.RawMessage)
|
||||
logrus.Debugln("[emojimix] raw msg:", ctx.Event.RawMessage)
|
||||
if len(r) == 2 {
|
||||
if _, ok := emojis[r[0]]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := emojis[r[1]]; !ok {
|
||||
return false
|
||||
}
|
||||
ctx.State["emojimix"] = r
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func face2emoji(face message.MessageSegment) rune {
|
||||
if face.Type == "text" {
|
||||
r := []rune(face.Data["text"])
|
||||
if len(r) != 1 {
|
||||
return 0
|
||||
}
|
||||
return r[0]
|
||||
}
|
||||
if face.Type != "face" {
|
||||
return 0
|
||||
}
|
||||
id, err := strconv.Atoi(face.Data["id"])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if r, ok := qqface[id]; ok {
|
||||
return r
|
||||
}
|
||||
return 0
|
||||
}
|
||||
123
plugin/epidemic/epidemic.go
Normal file
123
plugin/epidemic/epidemic.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Package epidemic 城市疫情查询
|
||||
package epidemic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
const (
|
||||
servicename = "epidemic"
|
||||
txurl = "https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=statisGradeCityDetail,diseaseh5Shelf"
|
||||
)
|
||||
|
||||
// result 疫情查询结果
|
||||
type result struct {
|
||||
Data struct {
|
||||
Epidemic epidemic `json:"diseaseh5Shelf"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// epidemic 疫情数据
|
||||
type epidemic struct {
|
||||
LastUpdateTime string `json:"lastUpdateTime"`
|
||||
AreaTree []*area `json:"areaTree"`
|
||||
}
|
||||
|
||||
// area 城市疫情数据
|
||||
type area struct {
|
||||
Name string `json:"name"`
|
||||
Today struct {
|
||||
Confirm int `json:"confirm"`
|
||||
Wzzadd interface{} `json:"wzz_add"`
|
||||
} `json:"today"`
|
||||
Total struct {
|
||||
NowConfirm int `json:"nowConfirm"`
|
||||
Confirm int `json:"confirm"`
|
||||
Dead int `json:"dead"`
|
||||
Heal int `json:"heal"`
|
||||
Grade string `json:"grade"`
|
||||
Wzz int `json:"wzz"`
|
||||
} `json:"total"`
|
||||
Children []*area `json:"children"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
engine := control.Register(servicename, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "城市疫情查询\n" +
|
||||
"- xxx疫情\n",
|
||||
})
|
||||
engine.OnSuffix("疫情").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
city := ctx.State["args"].(string)
|
||||
if city == "" {
|
||||
ctx.SendChain(message.Text("你还没有输入城市名字呢!"))
|
||||
return
|
||||
}
|
||||
data, time, err := queryEpidemic(city)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if data == nil {
|
||||
ctx.SendChain(message.Text("没有找到【", city, "】城市的疫情数据."))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
"【", data.Name, "】疫情数据\n",
|
||||
"新增人数:", data.Today.Confirm, "\n",
|
||||
"现有确诊:", data.Total.NowConfirm, "\n",
|
||||
"累计确诊:", data.Total.Confirm, "\n",
|
||||
"治愈人数:", data.Total.Heal, "\n",
|
||||
"死亡人数:", data.Total.Dead, "\n",
|
||||
"无症状人数:", data.Total.Wzz, "\n",
|
||||
"新增无症状:", data.Today.Wzzadd, "\n",
|
||||
"更新时间:\n『", time, "』",
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// rcity 查找城市
|
||||
func rcity(a *area, cityName string) *area {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
if a.Name == cityName {
|
||||
return a
|
||||
}
|
||||
for _, v := range a.Children {
|
||||
if v.Name == cityName {
|
||||
return v
|
||||
}
|
||||
c := rcity(v, cityName)
|
||||
if c != nil {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryEpidemic 查询城市疫情
|
||||
func queryEpidemic(findCityName string) (citydata *area, times string, err error) {
|
||||
data, err := web.GetData(txurl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var r result
|
||||
err = json.Unmarshal(data, &r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
citydata = rcity(r.Data.Epidemic.AreaTree[0], findCityName)
|
||||
return citydata, r.Data.Epidemic.LastUpdateTime, nil
|
||||
}
|
||||
44
plugin/font/main.go
Normal file
44
plugin/font/main.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Package font 渲染任意文字到图片
|
||||
package font
|
||||
|
||||
import (
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("font", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "渲染任意文字到图片\n- (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx",
|
||||
}).OnRegex(`^(用.+)?渲染文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
fnt := ctx.State["regex_matched"].([]string)[1]
|
||||
txt := ctx.State["regex_matched"].([]string)[2]
|
||||
switch fnt {
|
||||
case "用终末体":
|
||||
fnt = text.SyumatuFontFile
|
||||
case "用终末变体":
|
||||
fnt = text.NisiFontFile
|
||||
case "用紫罗兰体":
|
||||
fnt = text.VioletEvergardenFontFile
|
||||
case "用樱酥体":
|
||||
fnt = text.SakuraFontFile
|
||||
case "用Consolas体":
|
||||
fnt = text.ConsolasFontFile
|
||||
case "用苹方体":
|
||||
fallthrough
|
||||
default:
|
||||
fnt = text.FontFile
|
||||
}
|
||||
b, err := text.RenderToBase64(txt, fnt, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
|
||||
})
|
||||
}
|
||||
@@ -8,10 +8,8 @@ import (
|
||||
"encoding/json"
|
||||
"image"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fogleman/gg" // 注册了 jpg png gif
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -19,14 +17,13 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/FloatTech/zbputils/imgpool"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,9 +38,8 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌
|
||||
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘
|
||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘"}
|
||||
// 底图类型列表
|
||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录", "奇异恩典", "夏日口袋", "ASoul"}
|
||||
// 映射底图与 index
|
||||
index = make(map[string]uint8)
|
||||
// 签文
|
||||
@@ -51,37 +47,22 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
for i, s := range table {
|
||||
index[s] = uint8(i)
|
||||
}
|
||||
err := os.MkdirAll(images, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = os.RemoveAll(cache)
|
||||
err = os.MkdirAll(cache, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data, err := file.GetLazyData(omikujson, true, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = json.Unmarshal(data, &omikujis)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = file.GetLazyData(font, false, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// 插件主体
|
||||
en := control.Register("fortune", order.PrioFortune, &control.Options{
|
||||
en := control.Register("fortune", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "每日运势: \n" +
|
||||
"- 运势 | 抽签\n" +
|
||||
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘]",
|
||||
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录 | 奇异恩典 | 夏日口袋 | ASoul]",
|
||||
PublicDataFolder: "Fortune",
|
||||
})
|
||||
_ = os.RemoveAll(cache)
|
||||
err := os.MkdirAll(cache, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i, s := range table {
|
||||
index[s] = uint8(i)
|
||||
}
|
||||
en.OnRegex(`^设置底图\s?(.*)`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
@@ -91,9 +72,9 @@ func init() {
|
||||
}
|
||||
i, ok := index[ctx.State["regex_matched"].([]string)[1]]
|
||||
if ok {
|
||||
c, ok := control.Lookup("fortune")
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
err = c.SetData(gid, int64(i)&0xff)
|
||||
err := c.SetData(gid, int64(i)&0xff)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("设置失败:", err))
|
||||
return
|
||||
@@ -106,7 +87,26 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("没有这个底图哦~"))
|
||||
})
|
||||
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).
|
||||
en.OnFullMatchGroup([]string{"运势", "抽签"}, ctxext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
data, err := file.GetLazyData(omikujson, false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = json.Unmarshal(data, &omikujis)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
_, err = file.GetLazyData(font, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
)).Limit(ctxext.LimitByGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 获取该群背景类型,默认车万
|
||||
kind := "车万"
|
||||
@@ -116,7 +116,7 @@ func init() {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
logrus.Debugln("[fortune]gid:", ctx.Event.GroupID, "uid:", ctx.Event.UserID)
|
||||
c, ok := control.Lookup("fortune")
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
v := uint8(c.GetData(gid) & 0xff)
|
||||
if int(v) < len(table) {
|
||||
@@ -125,73 +125,53 @@ func init() {
|
||||
}
|
||||
// 检查背景图片是否存在
|
||||
zipfile := images + kind + ".zip"
|
||||
_, err = file.GetLazyData(zipfile, false, false)
|
||||
_, err := file.GetLazyData(zipfile, false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
|
||||
// 生成种子
|
||||
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
|
||||
seed := ctx.Event.UserID + t
|
||||
|
||||
// 随机获取背景
|
||||
background, index, err := randimage(zipfile, seed)
|
||||
background, index, err := randimage(zipfile, ctx)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
|
||||
// 随机获取签文
|
||||
title, text := randtext(seed)
|
||||
randtextindex := ctxext.RandSenderPerDayN(ctx.Event.UserID, len(omikujis))
|
||||
title, text := omikujis[randtextindex]["title"], omikujis[randtextindex]["content"]
|
||||
digest := md5.Sum(helper.StringToBytes(zipfile + strconv.Itoa(index) + title + text))
|
||||
cachefile := cache + hex.EncodeToString(digest[:])
|
||||
|
||||
m, err := imgpool.GetImage(cachefile)
|
||||
if err != nil {
|
||||
logrus.Debugln("[fortune]", err)
|
||||
if file.IsNotExist(cachefile) {
|
||||
f, err := os.Create(cachefile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
_, err = draw(background, title, text, f)
|
||||
_ = f.Close()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
m.SetFile(file.BOTPATH + "/" + cachefile)
|
||||
hassent, err := m.Push(ctxext.Send(ctx), ctxext.GetMessage(ctx))
|
||||
err = pool.SendImageFromPool(cachefile, cachefile, func() error {
|
||||
f, err := os.Create(cachefile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if hassent {
|
||||
return
|
||||
return err
|
||||
}
|
||||
_, err = draw(background, title, text, f)
|
||||
_ = f.Close()
|
||||
return err
|
||||
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
// 发送图片
|
||||
ctx.SendChain(message.Image(m.String()))
|
||||
})
|
||||
}
|
||||
|
||||
// @function randimage 随机选取zip内的文件
|
||||
// @param path zip路径
|
||||
// @param seed 随机数种子
|
||||
// @param ctx *zero.Ctx
|
||||
// @return 文件路径 & 错误信息
|
||||
func randimage(path string, seed int64) (im image.Image, index int, err error) {
|
||||
func randimage(path string, ctx *zero.Ctx) (im image.Image, index int, err error) {
|
||||
reader, err := zip.OpenReader(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
rand.Seed(seed)
|
||||
index = rand.Intn(len(reader.File))
|
||||
file := reader.File[index]
|
||||
file := reader.File[ctxext.RandSenderPerDayN(ctx.Event.UserID, len(reader.File))]
|
||||
f, err := file.Open()
|
||||
if err != nil {
|
||||
return
|
||||
@@ -202,16 +182,6 @@ func randimage(path string, seed int64) (im image.Image, index int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// @function randtext 随机选取签文
|
||||
// @param file 文件路径
|
||||
// @param seed 随机数种子
|
||||
// @return 签名 & 签文 & 错误信息
|
||||
func randtext(seed int64) (string, string) {
|
||||
rand.Seed(seed)
|
||||
r := rand.Intn(len(omikujis))
|
||||
return omikujis[r]["title"], omikujis[r]["content"]
|
||||
}
|
||||
|
||||
// @function draw 绘制运势图
|
||||
// @param background 背景图片路径
|
||||
// @param seed 随机数种子
|
||||
68
plugin/funny/laugh.go
Normal file
68
plugin/funny/laugh.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// Package funny 冷笑话
|
||||
package funny
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
type joke struct {
|
||||
ID uint32 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func init() {
|
||||
en := control.Register("funny", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "讲个笑话\n" +
|
||||
"- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
|
||||
PublicDataFolder: "Funny",
|
||||
})
|
||||
|
||||
en.OnPrefixGroup([]string{"讲个笑话", "夸夸"}, ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = en.DataFolder() + "jokes.db"
|
||||
_, err := en.GetLazyData("jokes.db", true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("jokes", &joke{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
c, err := db.Count("jokes")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Infoln("[funny]加载", c, "个笑话")
|
||||
return true
|
||||
})).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
// 获取名字
|
||||
name := ctx.NickName()
|
||||
var j joke
|
||||
err := db.Pick("jokes", &j)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(strings.ReplaceAll(j.Text, "%name", name)))
|
||||
})
|
||||
}
|
||||
16
plugin/genshin/data.go
Normal file
16
plugin/genshin/data.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package genshin
|
||||
|
||||
type storage uint64
|
||||
|
||||
func (s *storage) is5starsmode() bool {
|
||||
return *s&1 == 1
|
||||
}
|
||||
|
||||
func (s *storage) setmode(is5stars bool) bool {
|
||||
if is5stars {
|
||||
*s |= 1
|
||||
} else {
|
||||
*s &= 0xffffffff_fffffffe
|
||||
}
|
||||
return is5stars
|
||||
}
|
||||
375
plugin/genshin/ys.go
Normal file
375
plugin/genshin/ys.go
Normal file
@@ -0,0 +1,375 @@
|
||||
// Package genshin 原神抽卡
|
||||
package genshin
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/golang/freetype"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type zipfilestructure map[string][]*zip.File
|
||||
|
||||
var (
|
||||
totl uint64 // 累计抽奖次数
|
||||
filetree = make(zipfilestructure, 32)
|
||||
starN3, starN4, starN5 *zip.File
|
||||
namereg = regexp.MustCompile(`_(.*)\.png`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("genshin", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "原神抽卡\n- 原神十连\n- 切换原神卡池",
|
||||
PublicDataFolder: "Genshin",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
|
||||
engine.OnFullMatch("切换原神卡池").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
return
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
store := (storage)(c.GetData(gid))
|
||||
if store.setmode(!store.is5starsmode()) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("切换到五星卡池~"))
|
||||
} else {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("切换到普通卡池~"))
|
||||
}
|
||||
err := c.SetData(gid, int64(store))
|
||||
if err != nil {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnFullMatch("原神十连", ctxext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
zipfile := engine.DataFolder() + "Genshin.zip"
|
||||
_, err := engine.GetLazyData("Genshin.zip", false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = parsezip(zipfile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
)).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
return
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
store := (storage)(c.GetData(gid))
|
||||
img, str, mode, err := randnums(10, store)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
b, cl := writer.ToBytes(img)
|
||||
if mode {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("恭喜你抽到了: \n", str), message.ImageBytes(b)))
|
||||
} else {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("十连成功~"), message.ImageBytes(b)))
|
||||
}
|
||||
cl()
|
||||
})
|
||||
}
|
||||
|
||||
func randnums(nums int, store storage) (rgba *image.RGBA, str string, replyMode bool, err error) {
|
||||
var (
|
||||
fours, fives = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 四, 五星角色
|
||||
threeArms, fourArms, fiveArms = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 三 , 四, 五星武器
|
||||
fourN, fiveN = 0, 0 // 抽到 四, 五星角色的数量
|
||||
bgs = make([]*zip.File, 0, 10) // 背景图片名
|
||||
threeN2, fourN2, fiveN2 = 0, 0, 0 // 抽到 三 , 四, 五星武器的数量
|
||||
hero, stars = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 角色武器名, 储存星级图标
|
||||
|
||||
cicon = make([]*zip.File, 0, 10) // 元素图标
|
||||
fivebg, fourbg, threebg = filetree["five_bg.jpg"][0], filetree["four_bg.jpg"][0], filetree["three_bg.jpg"][0] // 背景图片名
|
||||
fivelen = len(filetree["five"])
|
||||
five2len = len(filetree["five2"])
|
||||
threelen = len(filetree["Three"])
|
||||
fourlen = len(filetree["four"])
|
||||
four2len = len(filetree["four2"])
|
||||
)
|
||||
|
||||
if totl%9 == 0 { // 累计9次加入一个五星
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
fiveN++
|
||||
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
|
||||
case 1:
|
||||
fiveN2++
|
||||
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
|
||||
}
|
||||
nums--
|
||||
}
|
||||
|
||||
if store.is5starsmode() { // 5星模式
|
||||
for i := 0; i < nums; i++ {
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
fiveN++
|
||||
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
|
||||
case 1:
|
||||
fiveN2++
|
||||
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
|
||||
}
|
||||
}
|
||||
} else { // 默认模式
|
||||
for i := 0; i < nums; i++ {
|
||||
a := rand.Intn(1000) // 抽卡几率 三星80% 四星17% 五星3%
|
||||
switch {
|
||||
case a >= 0 && a <= 800:
|
||||
threeN2++
|
||||
threeArms = append(threeArms, filetree["Three"][rand.Intn(threelen)])
|
||||
case a > 800 && a <= 885:
|
||||
fourN++
|
||||
fours = append(fours, filetree["four"][rand.Intn(fourlen)]) // 随机角色
|
||||
case a > 885 && a <= 970:
|
||||
fourN2++
|
||||
fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) // 随机武器
|
||||
case a > 970 && a <= 985:
|
||||
fiveN++
|
||||
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
|
||||
default:
|
||||
fiveN2++
|
||||
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
|
||||
}
|
||||
}
|
||||
if fourN+fourN2 == 0 && threeN2 > 0 { // 没有四星时自动加入
|
||||
threeN2--
|
||||
threeArms = threeArms[:len(threeArms)-1]
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
fourN++
|
||||
fours = append(fours, filetree["four"][rand.Intn(fourlen)]) // 随机角色
|
||||
case 1:
|
||||
fourN2++
|
||||
fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) // 随机武器
|
||||
}
|
||||
}
|
||||
_ = atomic.AddUint64(&totl, 1)
|
||||
}
|
||||
|
||||
icon := func(f *zip.File) *zip.File {
|
||||
name := f.Name
|
||||
name = name[strings.LastIndex(name, "/")+1:strings.Index(name, "_")] + ".png"
|
||||
logrus.Debugln("[genshin]get named file", name)
|
||||
return filetree[name][0]
|
||||
}
|
||||
|
||||
he := func(cnt int, id int, f *zip.File, bg *zip.File) {
|
||||
var hen *[]*zip.File
|
||||
for i := 0; i < cnt; i++ {
|
||||
switch id {
|
||||
case 1:
|
||||
hen = &threeArms
|
||||
case 2:
|
||||
hen = &fourArms
|
||||
case 3:
|
||||
hen = &fours
|
||||
case 4:
|
||||
hen = &fiveArms
|
||||
case 5:
|
||||
hen = &fives
|
||||
}
|
||||
bgs = append(bgs, bg) // 加入颜色背景
|
||||
hero = append(hero, (*hen)[i])
|
||||
stars = append(stars, f) // 加入星级图标
|
||||
cicon = append(cicon, icon((*hen)[i])) // 加入元素图标
|
||||
}
|
||||
}
|
||||
|
||||
if fiveN > 0 { // 按顺序加入
|
||||
he(fiveN, 5, starN5, fivebg) // 五星角色
|
||||
str += reply(fives, 1, str)
|
||||
replyMode = true
|
||||
}
|
||||
if fourN > 0 {
|
||||
he(fourN, 3, starN4, fourbg) // 四星角色
|
||||
}
|
||||
if fiveN2 > 0 {
|
||||
he(fiveN2, 4, starN5, fivebg) // 五星武器
|
||||
str += reply(fiveArms, 2, str)
|
||||
replyMode = true
|
||||
}
|
||||
if fourN2 > 0 {
|
||||
he(fourN2, 2, starN4, fourbg) // 四星武器
|
||||
}
|
||||
if threeN2 > 0 {
|
||||
he(threeN2, 1, starN3, threebg) // 三星武器
|
||||
}
|
||||
|
||||
var c1, c2, c3 uint8 = 50, 50, 50 // 背景颜色
|
||||
|
||||
img00, err := filetree["bg0.jpg"][0].Open() // 打开背景图片
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rectangle := image.Rect(0, 0, 1920, 1080) // 图片宽度, 图片高度
|
||||
rgba = image.NewRGBA(rectangle)
|
||||
draw.Draw(rgba, rgba.Bounds(), image.NewUniform(color.RGBA{c1, c2, c3, 255}), image.Point{}, draw.Over)
|
||||
context := freetype.NewContext() // 创建一个新的上下文
|
||||
context.SetDPI(72) // 每英寸 dpi
|
||||
context.SetClip(rgba.Bounds())
|
||||
context.SetDst(rgba)
|
||||
|
||||
defer img00.Close()
|
||||
img0, err := jpeg.Decode(img00) // 读取一个本地图像
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
offset := image.Pt(0, 0) // 图片在背景上的位置
|
||||
draw.Draw(rgba, img0.Bounds().Add(offset), img0, image.Point{}, draw.Over)
|
||||
|
||||
w1, h1 := 230, 0
|
||||
for i := 0; i < len(hero); i++ {
|
||||
if i > 0 {
|
||||
w1 += 146 // 图片宽度
|
||||
}
|
||||
|
||||
imgs, err := bgs[i].Open() // 取出背景图片
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs.Close()
|
||||
|
||||
img, _ := jpeg.Decode(imgs)
|
||||
offset := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img.Bounds().Add(offset), img, image.Point{}, draw.Over)
|
||||
|
||||
imgs1, err := hero[i].Open() // 取出图片名
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs1.Close()
|
||||
|
||||
img1, _ := png.Decode(imgs1)
|
||||
offset1 := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img1.Bounds().Add(offset1), img1, image.Point{}, draw.Over)
|
||||
|
||||
imgs2, err := stars[i].Open() // 取出星级图标
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs2.Close()
|
||||
|
||||
img2, _ := png.Decode(imgs2)
|
||||
offset2 := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img2.Bounds().Add(offset2), img2, image.Point{}, draw.Over)
|
||||
|
||||
imgs3, err := cicon[i].Open() // 取出类型图标
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs3.Close()
|
||||
|
||||
img3, _ := png.Decode(imgs3)
|
||||
offset3 := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img3.Bounds().Add(offset3), img3, image.Point{}, draw.Over)
|
||||
}
|
||||
imgs4, err := filetree["Reply.png"][0].Open() // "分享" 图标
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs4.Close()
|
||||
img4, err := png.Decode(imgs4)
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
offset4 := image.Pt(1270, 945) // 宽, 高
|
||||
draw.Draw(rgba, img4.Bounds().Add(offset4), img4, image.Point{}, draw.Over)
|
||||
return
|
||||
}
|
||||
|
||||
func parsezip(zipFile string) error {
|
||||
zipReader, err := zip.OpenReader(zipFile) // will not close
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range zipReader.File {
|
||||
if f.FileInfo().IsDir() {
|
||||
filetree[f.Name] = make([]*zip.File, 0, 32)
|
||||
continue
|
||||
}
|
||||
f.Name = f.Name[8:]
|
||||
i := strings.LastIndex(f.Name, "/")
|
||||
if i < 0 {
|
||||
filetree[f.Name] = []*zip.File{f}
|
||||
logrus.Debugln("[genshin]insert file", f.Name)
|
||||
continue
|
||||
}
|
||||
folder := f.Name[:i]
|
||||
if folder != "" {
|
||||
filetree[folder] = append(filetree[folder], f)
|
||||
logrus.Debugln("[genshin]insert file into", folder)
|
||||
if folder == "gacha" {
|
||||
switch f.Name[i+1:] {
|
||||
case "ThreeStar.png":
|
||||
starN3 = f
|
||||
case "FourStar.png":
|
||||
starN4 = f
|
||||
case "FiveStar.png":
|
||||
starN5 = f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 取出角色武器名
|
||||
func reply(z []*zip.File, num int, nameStr string) string {
|
||||
var tmp strings.Builder
|
||||
tmp.Grow(128)
|
||||
switch {
|
||||
case num == 1:
|
||||
tmp.WriteString("★五星角色★\n")
|
||||
case num == 2 && len(nameStr) > 0:
|
||||
tmp.WriteString("\n★五星武器★\n")
|
||||
default:
|
||||
tmp.WriteString("★五星武器★\n")
|
||||
}
|
||||
for i := range z {
|
||||
tmp.WriteString(namereg.FindStringSubmatch(z[i].Name)[1] + " * ")
|
||||
}
|
||||
return tmp.String()
|
||||
}
|
||||
90
plugin/gif/README.md
Normal file
90
plugin/gif/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# ZeroBot-Plugin-Gif
|
||||
[ZeroBot QQ机器人](https://github.com/wdvxdr1123/ZeroBot)插件,可以制作各种沙雕gif图
|
||||
> 素材包地址: https://gitcode.net/anto_july/imagematerials
|
||||
|
||||
## 触发方式
|
||||
1. [指令词]+[qq号] 如:爬123456
|
||||
2. [指令词]+[图片] 如:爬[图片]
|
||||
3. [指令词]+[艾特] 如:爬@小H
|
||||
|
||||
## 指令列表
|
||||
- [x] 爬
|
||||
- [x] 冲
|
||||
- [x] 摸
|
||||
- [x] 搓
|
||||
- [x] 拍
|
||||
- [x] 丢
|
||||
- [x] 敲
|
||||
- [x] 吃
|
||||
- [x] 啃
|
||||
- [x] 撕
|
||||
- [x] 蹭
|
||||
- [x] 灰度
|
||||
- [x] 上翻
|
||||
- [x] 下翻
|
||||
- [x] 左翻
|
||||
- [x] 右翻
|
||||
- [x] 反色
|
||||
- [x] 倒放
|
||||
- [x] 浮雕
|
||||
- [x] 打码
|
||||
- [x] 负片
|
||||
- [x] 旋转45
|
||||
- [x] 变形100 100
|
||||
- [x] 亲
|
||||
- [x] 娶|结婚申请|结婚登记
|
||||
- [x] 像只
|
||||
- [x] 阿尼亚喜欢
|
||||
- [x] 我永远喜欢|永远喜欢
|
||||
- [x] 像样的亲亲
|
||||
- [x] 国旗
|
||||
- [x] 不要靠近
|
||||
- [x] 万能表情|空白表情
|
||||
- [x] 采访
|
||||
- [x] 需要|你可能需要
|
||||
- [x] 这像画吗
|
||||
- [x] 小画家
|
||||
- [x] 完美
|
||||
- [x] 玩游戏 (应该使用透视变换)
|
||||
- [x] 出警
|
||||
- [x] 警察
|
||||
- [x] 舔|舔屏|prpr (应该使用透视变换)
|
||||
- [x] 安全感
|
||||
- [x] 精神支柱
|
||||
- [x] 想什么
|
||||
- [x] 墙纸
|
||||
- [x] 为什么at我
|
||||
- [x] 交个朋友
|
||||
- [x] 打工人|继续干活
|
||||
- [x] 兑换券
|
||||
- [ ] 捂脸 (使用了透视变换, 需要研究矩阵变换)
|
||||
- [x] 注意力涣散
|
||||
- [x] 垃圾桶|垃圾
|
||||
- [x] 锤
|
||||
- [x] 啾啾
|
||||
- [x] 2敲
|
||||
- [x] 听音乐
|
||||
- [ ] 群青 (需要mask)
|
||||
- [ ] 加载中 (需要mask)
|
||||
- [x] 永远爱你 (未加闪光)
|
||||
- [ ] 关注 (处理文字麻烦)
|
||||
- [x] 2拍
|
||||
- [x] 顶
|
||||
- [x] 捣
|
||||
- [x] 打拳 (未加闪光)
|
||||
- [ ] 复读 (处理文字麻烦)
|
||||
- [x] 滚
|
||||
- [x] 吸
|
||||
- [x] 扔
|
||||
- [x] 捶
|
||||
- [x] 紧贴
|
||||
- [ ] 膜拜 (使用了透视变换, 需要研究矩阵变换)
|
||||
- [ ] 小天使 (摆)
|
||||
- [ ] 一直 (摆)
|
||||
- [x] 转
|
||||
- [ ] 问问 (摆)
|
||||
- [ ] 典中典 (摆)
|
||||
- [ ] 震惊 (摆)
|
||||
- [ ] 哈哈镜 (摆)
|
||||
- [ ] 对称 (猎奇, 不整)
|
||||
- [ ] 远离 (摆)
|
||||
85
plugin/gif/context.go
Normal file
85
plugin/gif/context.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type context struct {
|
||||
usrdir string
|
||||
headimgsdir []string
|
||||
}
|
||||
|
||||
func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
|
||||
defer wg.Done()
|
||||
target := datapath + `materials/` + name
|
||||
var err error
|
||||
if file.IsNotExist(target) {
|
||||
err = file.DownloadTo(`https://gitcode.net/anto_july/imagematerials/-/raw/main/`+name, target, true)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
|
||||
} else {
|
||||
logrus.Debugln("[gif] dl", name, "exists at", target)
|
||||
}
|
||||
*s = target
|
||||
}
|
||||
|
||||
func dlblock(name string) (string, error) {
|
||||
target := datapath + `materials/` + name
|
||||
if file.IsNotExist(target) {
|
||||
err := file.DownloadTo(`https://gitcode.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
|
||||
} else {
|
||||
logrus.Debugln("[gif] dl", name, "exists at", target)
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func dlrange(prefix string, end int, wg *sync.WaitGroup, exit func(error)) []string {
|
||||
if file.IsNotExist(datapath + `materials/` + prefix) {
|
||||
err := os.MkdirAll(datapath+`materials/`+prefix, 0755)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
c := make([]string, end)
|
||||
for i := range c {
|
||||
wg.Add(1)
|
||||
go dlchan(prefix+"/"+strconv.Itoa(i)+".png", &c[i], wg, exit)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// 新的上下文
|
||||
func newContext(user int64) *context {
|
||||
c := new(context)
|
||||
c.usrdir = datapath + "users/" + strconv.FormatInt(user, 10) + `/`
|
||||
_ = os.MkdirAll(c.usrdir, 0755)
|
||||
c.headimgsdir = make([]string, 2)
|
||||
c.headimgsdir[0] = c.usrdir + "0.gif"
|
||||
c.headimgsdir[1] = c.usrdir + "1.gif"
|
||||
return c
|
||||
}
|
||||
|
||||
func loadFirstFrames(paths []string, size int) (imgs []*img.ImgFactory, err error) {
|
||||
imgs = make([]*img.ImgFactory, size)
|
||||
for i := range imgs {
|
||||
imgs[i], err = img.LoadFirstFrame(paths[i], 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return imgs, nil
|
||||
}
|
||||
868
plugin/gif/gif.go
Normal file
868
plugin/gif/gif.go
Normal file
@@ -0,0 +1,868 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/fogleman/gg"
|
||||
)
|
||||
|
||||
// mo 摸
|
||||
func mo(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "摸.gif"
|
||||
c := dlrange("mo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 5)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
mo := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 80, 80, 32, 32).Im,
|
||||
imgs[1].InsertBottom(tou, 70, 90, 42, 22).Im,
|
||||
imgs[2].InsertBottom(tou, 75, 85, 37, 27).Im,
|
||||
imgs[3].InsertBottom(tou, 85, 75, 27, 37).Im,
|
||||
imgs[4].InsertBottom(tou, 90, 70, 22, 42).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, mo))
|
||||
}
|
||||
|
||||
// cuo 搓
|
||||
func cuo(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "搓.gif"
|
||||
c := dlrange("cuo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(110, 110)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
m1 := img.Rotate(tou, 72, 0, 0)
|
||||
m2 := img.Rotate(tou, 144, 0, 0)
|
||||
m3 := img.Rotate(tou, 216, 0, 0)
|
||||
m4 := img.Rotate(tou, 288, 0, 0)
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 5)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cuo := []*image.NRGBA{
|
||||
imgs[0].InsertBottomC(tou, 0, 0, 75, 130).Im,
|
||||
imgs[1].InsertBottomC(m1.Im, 0, 0, 75, 130).Im,
|
||||
imgs[2].InsertBottomC(m2.Im, 0, 0, 75, 130).Im,
|
||||
imgs[3].InsertBottomC(m3.Im, 0, 0, 75, 130).Im,
|
||||
imgs[4].InsertBottomC(m4.Im, 0, 0, 75, 130).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(5, cuo))
|
||||
}
|
||||
|
||||
// qiao 敲
|
||||
func qiao(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "敲.gif"
|
||||
c := dlrange("qiao", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(40, 40)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
qiao := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 40, 33, 57, 52).Im,
|
||||
imgs[1].InsertUp(tou, 38, 36, 58, 50).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, qiao))
|
||||
}
|
||||
|
||||
// chi 吃
|
||||
func chi(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "吃.gif"
|
||||
c := dlrange("chi", 3, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(32, 32)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 3)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
chi := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
imgs[1].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
imgs[2].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chi))
|
||||
}
|
||||
|
||||
// ceng 蹭
|
||||
func ceng(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "蹭.gif"
|
||||
c := dlrange("ceng", 6, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou2, err := cc.getLogo2(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ceng := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 75, 77, 40, 88).InsertUp(tou2, 77, 103, 102, 81).Im,
|
||||
imgs[1].InsertUp(tou, 75, 77, 46, 100).InsertUp(img.Rotate(tou2, 10, 62, 127).Im, 0, 0, 92, 40).Im,
|
||||
imgs[2].InsertUp(tou, 75, 77, 67, 99).InsertUp(tou2, 76, 117, 90, 8).Im,
|
||||
imgs[3].InsertUp(tou, 75, 77, 52, 83).InsertUp(img.Rotate(tou2, -40, 94, 94).Im, 0, 0, 53, -20).Im,
|
||||
imgs[4].InsertUp(tou, 75, 77, 56, 110).InsertUp(img.Rotate(tou2, -66, 132, 80).Im, 0, 0, 78, 40).Im,
|
||||
imgs[5].InsertUp(tou, 75, 77, 62, 102).InsertUp(tou2, 71, 100, 110, 94).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(8, ceng))
|
||||
}
|
||||
|
||||
// ken 啃
|
||||
func ken(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "啃.gif"
|
||||
c := dlrange("ken", 16, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 16)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ken := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 90, 90, 105, 150).Im,
|
||||
imgs[1].InsertBottom(tou, 90, 83, 96, 172).Im,
|
||||
imgs[2].InsertBottom(tou, 90, 90, 106, 148).Im,
|
||||
imgs[3].InsertBottom(tou, 88, 88, 97, 167).Im,
|
||||
imgs[4].InsertBottom(tou, 90, 85, 89, 179).Im,
|
||||
imgs[5].InsertBottom(tou, 90, 90, 106, 151).Im,
|
||||
imgs[6].Im,
|
||||
imgs[7].Im,
|
||||
imgs[8].Im,
|
||||
imgs[9].Im,
|
||||
imgs[10].Im,
|
||||
imgs[11].Im,
|
||||
imgs[12].Im,
|
||||
imgs[13].Im,
|
||||
imgs[14].Im,
|
||||
imgs[15].Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, ken))
|
||||
}
|
||||
|
||||
// pai 拍
|
||||
func pai(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "拍.gif"
|
||||
c := dlrange("pai", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(30, 30)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pai := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 0, 0, 1, 47).Im,
|
||||
imgs[1].InsertUp(tou, 0, 0, 1, 67).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, pai))
|
||||
}
|
||||
|
||||
// xqe 冲
|
||||
func xqe(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "冲.gif"
|
||||
c := dlrange("xqe", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
chong := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 30, 30, 15, 53).Im,
|
||||
imgs[1].InsertUp(tou, 30, 30, 40, 53).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chong))
|
||||
}
|
||||
|
||||
// diu 丢
|
||||
func diu(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "丢.gif"
|
||||
c := dlrange("diu", 8, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 8)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
diu := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 32, 32, 108, 36).Im,
|
||||
imgs[1].InsertUp(tou, 32, 32, 122, 36).Im,
|
||||
imgs[2].Im,
|
||||
imgs[3].InsertUp(tou, 123, 123, 19, 129).Im,
|
||||
imgs[4].InsertUp(tou, 185, 185, -50, 200).InsertUp(tou, 33, 33, 289, 70).Im,
|
||||
imgs[5].InsertUp(tou, 32, 32, 280, 73).Im,
|
||||
imgs[6].InsertUp(tou, 35, 35, 259, 31).Im,
|
||||
imgs[7].InsertUp(tou, 175, 175, -50, 220).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, diu))
|
||||
}
|
||||
|
||||
// kiss 亲
|
||||
func kiss(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 13
|
||||
name := cc.usrdir + "Kiss.gif"
|
||||
c := dlrange("kiss", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou2, err := cc.getLogo2(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
userLocs := [][]int{{58, 90}, {62, 95}, {42, 100}, {50, 100}, {56, 100}, {18, 120}, {28, 110}, {54, 100}, {46, 100}, {60, 100}, {35, 115}, {20, 120}, {40, 96}}
|
||||
selfLocs := [][]int{{92, 64}, {135, 40}, {84, 105}, {80, 110}, {155, 82}, {60, 96}, {50, 80}, {98, 55}, {35, 65}, {38, 100}, {70, 80}, {84, 65}, {75, 65}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
kiss := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
kiss[i] = imgs[i].InsertUp(tou, 50, 50, userLocs[i][0], userLocs[i][1]).
|
||||
InsertUp(tou2, 40, 40, selfLocs[i][0], selfLocs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, kiss))
|
||||
}
|
||||
|
||||
// garbage 垃圾 垃圾桶
|
||||
func garbage(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 25
|
||||
name := cc.usrdir + "Garbage.gif"
|
||||
c := dlrange("garbage", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 79, 79)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{39, 40}, {39, 40}, {39, 40}, {39, 30}, {39, 30}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 30}, {39, 27}, {39, 32}, {37, 49}, {37, 64}, {37, 67}, {37, 67}, {39, 69}, {37, 70}, {37, 70}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
garbage := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
garbage[i] = imgs[i].InsertBottom(im.Im, 0, 0, locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, garbage))
|
||||
}
|
||||
|
||||
// thump 捶
|
||||
func thump(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 4
|
||||
name := cc.usrdir + "Thump.gif"
|
||||
c := dlrange("thump", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{65, 128, 77, 72}, {67, 128, 73, 72}, {54, 139, 94, 61}, {57, 135, 86, 65}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
thump := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
thump[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, thump))
|
||||
}
|
||||
|
||||
// jiujiu 啾啾
|
||||
func jiujiu(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Jiujiu.gif"
|
||||
c := dlrange("jiujiu", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 75, 51)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
jiujiu := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
jiujiu[i] = imgs[i].InsertBottom(im.Im, 0, 0, 0, 0).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, jiujiu))
|
||||
}
|
||||
|
||||
// knock 2敲
|
||||
func knock(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Knock.gif"
|
||||
c := dlrange("knock", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{60, 308, 210, 195}, {60, 308, 210, 198}, {45, 330, 250, 172}, {58, 320, 218, 180}, {60, 310, 215, 193}, {40, 320, 250, 285}, {48, 308, 226, 192}, {51, 301, 223, 200}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
knock := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
knock[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, knock))
|
||||
}
|
||||
|
||||
// 听音乐 listenMusic
|
||||
func listenMusic(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 1
|
||||
name := cc.usrdir + "ListenMusic.gif"
|
||||
c := dlrange("listen_music", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
face, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
listenmusic := make([]*image.NRGBA, 36)
|
||||
for i := 0; i < 36; i++ {
|
||||
listenmusic[i] = imgs[0].InsertBottomC(img.Rotate(face, float64(-i*10), 215, 215).Im, 0, 0, 207, 207).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, listenmusic))
|
||||
}
|
||||
|
||||
// loveYou 永远爱你
|
||||
func loveYou(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 2
|
||||
name := cc.usrdir + "LoveYou.gif"
|
||||
c := dlrange("love_you", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{68, 65, 70, 70}, {63, 59, 80, 80}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
loveyou := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
loveyou[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, loveyou))
|
||||
}
|
||||
|
||||
// pat 2拍
|
||||
func pat(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 10
|
||||
name := cc.usrdir + "Pat.gif"
|
||||
c := dlrange("pat", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{11, 73, 106, 100}, {8, 79, 112, 96}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
p := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
if i == 2 {
|
||||
p[i] = imgs[i].InsertBottom(im.Im, locs[1][2], locs[1][3], locs[1][0], locs[1][1]).Im
|
||||
} else {
|
||||
p[i] = imgs[i].InsertBottom(im.Im, locs[0][2], locs[0][3], locs[0][0], locs[0][1]).Im
|
||||
}
|
||||
}
|
||||
seq := []int{0, 1, 2, 3, 1, 2, 3, 0, 1, 2, 3, 0, 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 5, 5, 6, 7, 8, 9}
|
||||
pat := make([]*image.NRGBA, len(seq))
|
||||
for i := 0; i < len(pat); i++ {
|
||||
pat[i] = p[seq[i]]
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, pat))
|
||||
}
|
||||
|
||||
// jackUp 顶
|
||||
func jackUp(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 23
|
||||
name := cc.usrdir + "JackUp.gif"
|
||||
c := dlrange("play", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{180, 60, 100, 100}, {184, 75, 100, 100}, {183, 98, 100, 100}, {179, 118, 110, 100}, {156, 194, 150, 48}, {178, 136, 122, 69}, {175, 66, 122, 85}, {170, 42, 130, 96}, {175, 34, 118, 95}, {179, 35, 110, 93}, {180, 54, 102, 93}, {183, 58, 97, 92}, {174, 35, 120, 94}, {179, 35, 109, 93}, {181, 54, 101, 92}, {182, 59, 98, 92}, {183, 71, 90, 96}, {180, 131, 92, 101}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
p := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
if i < len(locs) {
|
||||
p[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
} else {
|
||||
p[i] = imgs[i].Im
|
||||
}
|
||||
}
|
||||
play := make([]*image.NRGBA, 0, 16)
|
||||
play = append(play, p[0:12]...)
|
||||
play = append(play, p[0:12]...)
|
||||
play = append(play, p[0:8]...)
|
||||
play = append(play, p[12:18]...)
|
||||
play = append(play, p[18:23]...)
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, play))
|
||||
}
|
||||
|
||||
// pound 捣
|
||||
func pound(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Pound.gif"
|
||||
c := dlrange("pound", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{135, 240, 138, 47}, {135, 240, 138, 47}, {150, 190, 105, 95}, {150, 190, 105, 95}, {148, 188, 106, 98}, {146, 196, 110, 88}, {145, 223, 112, 61}, {145, 223, 112, 61}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pound := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
pound[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, pound))
|
||||
}
|
||||
|
||||
// punch 打拳
|
||||
func punch(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 13
|
||||
name := cc.usrdir + "Punch.gif"
|
||||
c := dlrange("punch", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 260, 260)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{-50, 20}, {-40, 10}, {-30, 0}, {-20, -10}, {-10, -10}, {0, 0}, {10, 10}, {20, 20}, {10, 10}, {0, 0}, {-10, -10}, {10, 0}, {-30, 10}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
punch := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
punch[i] = imgs[i].InsertBottom(im.Im, 0, 0, locs[i][0], locs[i][1]-15).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, punch))
|
||||
}
|
||||
|
||||
// roll 滚
|
||||
func roll(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "roll.gif"
|
||||
c := dlrange("roll", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 210, 210)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{87, 77, 0}, {96, 85, -45}, {92, 79, -90}, {92, 78, -135}, {92, 75, -180}, {92, 75, -225}, {93, 76, -270}, {90, 80, -315}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
roll := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
roll[i] = imgs[i].InsertBottomC(img.Rotate(im.Im, float64(locs[i][2]), 0, 0).Im, 0, 0, locs[i][0]+105, locs[i][1]+105).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, roll))
|
||||
}
|
||||
|
||||
// suck 吸 嗦
|
||||
func suck(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 12
|
||||
name := cc.usrdir + "Suck.gif"
|
||||
c := dlrange("suck", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{82, 100, 130, 119}, {82, 94, 126, 125}, {82, 120, 128, 99}, {81, 164, 132, 55}, {79, 163, 132, 55}, {82, 140, 127, 79}, {83, 152, 125, 67}, {75, 157, 140, 62}, {72, 165, 144, 54}, {80, 132, 128, 87}, {81, 127, 127, 92}, {79, 111, 132, 108}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
suck := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
suck[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, suck))
|
||||
}
|
||||
|
||||
// hammer 锤
|
||||
func hammer(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 7
|
||||
name := cc.usrdir + "Hammer.gif"
|
||||
c := dlrange("hammer", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{62, 143, 158, 113}, {52, 177, 173, 105}, {42, 192, 192, 92}, {46, 182, 184, 100}, {54, 169, 174, 110}, {69, 128, 144, 135}, {65, 130, 152, 124}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hammer := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
hammer[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, hammer))
|
||||
}
|
||||
|
||||
// tightly 紧贴 紧紧贴着
|
||||
func tightly(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 20
|
||||
name := cc.usrdir + "Tightly.gif"
|
||||
c := dlrange("tightly", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{39, 169, 267, 141}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {28, 176, 293, 134}, {5, 215, 333, 96}, {10, 210, 321, 102}, {3, 210, 330, 104}, {4, 210, 328, 102}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {29, 195, 285, 120}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tightly := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
tightly[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, tightly))
|
||||
}
|
||||
|
||||
// turn 转
|
||||
func turn(cc *context, value ...string) (string, error) {
|
||||
name := cc.usrdir + "Turn.gif"
|
||||
face, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
canvas := gg.NewContext(250, 250)
|
||||
canvas.SetColor(color.White)
|
||||
canvas.DrawRectangle(0, 0, 250, 250)
|
||||
canvas.Fill()
|
||||
turn := make([]*image.NRGBA, 36)
|
||||
for i := 0; i < 36; i++ {
|
||||
turn[i] = img.Size(canvas.Image(), 0, 0).InsertUpC(img.Rotate(face, float64(10*i), 250, 250).Im, 0, 0, 125, 125).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, turn))
|
||||
}
|
||||
41
plugin/gif/logo.go
Normal file
41
plugin/gif/logo.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"image"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
)
|
||||
|
||||
func (cc *context) prepareLogos(s ...string) error {
|
||||
for i, v := range s {
|
||||
_, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
} else {
|
||||
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[0], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo2(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[1], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
}
|
||||
1057
plugin/gif/png.go
Normal file
1057
plugin/gif/png.go
Normal file
File diff suppressed because it is too large
Load Diff
130
plugin/gif/run.go
Normal file
130
plugin/gif/run.go
Normal file
@@ -0,0 +1,130 @@
|
||||
// Package gif 制图
|
||||
package gif
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
cmd = make([]string, 0)
|
||||
datapath string
|
||||
cmdMap = map[string]func(cc *context, args ...string) (string, error){
|
||||
"搓": cuo,
|
||||
"冲": xqe,
|
||||
"摸": mo,
|
||||
"拍": pai,
|
||||
"丢": diu,
|
||||
"吃": chi,
|
||||
"敲": qiao,
|
||||
"啃": ken,
|
||||
"蹭": ceng,
|
||||
"爬": pa,
|
||||
"撕": si,
|
||||
"灰度": grayscale,
|
||||
"上翻": flipV,
|
||||
"下翻": flipV,
|
||||
"左翻": flipH,
|
||||
"右翻": flipH,
|
||||
"反色": invert,
|
||||
"浮雕": convolve3x3,
|
||||
"打码": blur,
|
||||
"负片": invertAndGrayscale,
|
||||
"旋转": rotate,
|
||||
"变形": deformation,
|
||||
"亲": kiss,
|
||||
"结婚申请": marriage,
|
||||
"结婚登记": marriage,
|
||||
"阿尼亚喜欢": anyasuki,
|
||||
"像只": alike,
|
||||
"我永远喜欢": alwaysLike,
|
||||
"永远喜欢": alwaysLike,
|
||||
"像样的亲亲": decentKiss,
|
||||
"国旗": chinaFlag,
|
||||
"不要靠近": dontTouch,
|
||||
"万能表情": universal,
|
||||
"空白表情": universal,
|
||||
"采访": interview,
|
||||
"需要": need,
|
||||
"你可能需要": need,
|
||||
"这像画吗": paint,
|
||||
"小画家": painter,
|
||||
"完美": perfect,
|
||||
"玩游戏": playGame,
|
||||
"出警": police,
|
||||
"警察": police1,
|
||||
"舔": prpr,
|
||||
"舔屏": prpr,
|
||||
"prpr": prpr,
|
||||
"安全感": safeSense,
|
||||
"精神支柱": support,
|
||||
"想什么": thinkwhat,
|
||||
"墙纸": wallpaper,
|
||||
"为什么at我": whyatme,
|
||||
"交个朋友": makeFriend,
|
||||
"打工人": backToWork,
|
||||
"继续干活": backToWork,
|
||||
"兑换券": coupon,
|
||||
"注意力涣散": distracted,
|
||||
"垃圾桶": garbage,
|
||||
"垃圾": garbage,
|
||||
"捶": thump,
|
||||
"啾啾": jiujiu,
|
||||
"2敲": knock,
|
||||
"听音乐": listenMusic,
|
||||
"永远爱你": loveYou,
|
||||
"2拍": pat,
|
||||
"顶": jackUp,
|
||||
"捣": pound,
|
||||
"打拳": punch,
|
||||
"滚": roll,
|
||||
"吸": suck,
|
||||
"嗦": suck,
|
||||
"扔": throw,
|
||||
"锤": hammer,
|
||||
"紧贴": tightly,
|
||||
"紧紧贴着": tightly,
|
||||
"转": turn,
|
||||
}
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
for k := range cmdMap {
|
||||
cmd = append(cmd, k)
|
||||
}
|
||||
en := control.Register("gif", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "制图\n- 搓\n- 冲\n- 摸\n- 拍\n- 丢\n- 吃\n- 敲\n- 啃\n- 蹭\n- 爬\n- 撕\n- 灰度\n- 上翻|下翻\n" +
|
||||
"- 左翻|右翻\n- 反色\n- 浮雕\n- 打码\n- 负片\n- 旋转 45\n- 变形 100 100\n- 亲\n- 结婚申请|结婚登记\n- 阿尼亚喜欢\n- 像只\n" +
|
||||
"- 我永远喜欢|永远喜欢\n- 像样的亲亲\n- 国旗\n- 不要靠近\n- 万能表情|空白表情\n- 采访\n- 需要|你可能需要\n- 这像画吗\n- 小画家\n" +
|
||||
"- 完美\n- 玩游戏\n- 出警\n- 警察\n- 舔|舔屏|prpr\n- 安全感\n- 精神支柱\n- 想什么\n- 墙纸\n- 为什么at我\n- 交个朋友\n- 打工人|继续干活\n" +
|
||||
"- 兑换券\n- 注意力涣散\n- 垃圾桶|垃圾\n- 捶\n- 啾啾\n- 2敲\n- 听音乐\n- 永远爱你\n- 2拍\n- 顶\n- 捣\n- 打拳\n- 滚\n- 吸|嗦\n- 扔\n" +
|
||||
"- 锤\n- 紧贴|紧紧贴着\n- 转\n",
|
||||
PrivateDataFolder: "gif",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
datapath = file.BOTPATH + "/" + en.DataFolder()
|
||||
en.OnRegex(`^(` + strings.Join(cmd, "|") + `)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := newContext(ctx.Event.UserID)
|
||||
list := ctx.State["regex_matched"].([]string)
|
||||
err := c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
argslist := strings.Split(strings.TrimSuffix(strings.TrimPrefix(list[0], list[1]), list[2]), " ")
|
||||
picurl, err := cmdMap[list[1]](c, argslist...)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(picurl))
|
||||
})
|
||||
}
|
||||
@@ -4,22 +4,21 @@ package github
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("github", order.PrioGithub, &control.Options{
|
||||
control.Register("github", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "GitHub仓库搜索\n" +
|
||||
"- >github [xxx]\n" +
|
||||
@@ -36,12 +35,12 @@ func init() { // 插件主体
|
||||
}.Encode()
|
||||
body, err := netGet(api.String(), header)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
// 解析请求
|
||||
info := gjson.ParseBytes(body)
|
||||
if info.Get("total_count").Int() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 没有找到这样的仓库"))
|
||||
ctx.SendChain(message.Text("ERROR:没有找到这样的仓库"))
|
||||
return
|
||||
}
|
||||
repo := info.Get("items.0")
|
||||
@@ -97,7 +96,7 @@ func init() { // 插件主体
|
||||
}
|
||||
|
||||
// notnull 如果传入文本为空,则返回默认值
|
||||
//nolint: unparam
|
||||
|
||||
func notnull(text, defstr string) string {
|
||||
if text == "" {
|
||||
return defstr
|
||||
@@ -119,7 +118,7 @@ func netGet(dest string, header http.Header) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
594
plugin/guessmusic/main.go
Normal file
594
plugin/guessmusic/main.go
Normal file
@@ -0,0 +1,594 @@
|
||||
// Package guessmusic 基于zbp的猜歌插件
|
||||
package guessmusic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||
)
|
||||
|
||||
const (
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"
|
||||
)
|
||||
|
||||
var (
|
||||
cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
|
||||
cfg = config{ // 默认 config
|
||||
MusicPath: file.BOTPATH + "/data/guessmusic/music/", // 绝对路径,歌库根目录,通过指令进行更改
|
||||
Local: true, // 是否使用本地音乐库
|
||||
API: true, // 是否使用 Api
|
||||
}
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("guessmusic", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "猜歌插件(该插件依赖ffmpeg)\n" +
|
||||
"- 个人猜歌\n" +
|
||||
"- 团队猜歌\n" +
|
||||
"- 设置猜歌缓存歌库路径 [绝对路径]\n" +
|
||||
"- 设置猜歌本地 [true/false]\n" +
|
||||
"- 设置猜歌Api [true/false]\n" +
|
||||
"注:默认歌库为网易云热歌榜\n- 本地歌榜歌库歌曲命名规格“歌名 - 歌手”\n" +
|
||||
"1.可在后面添加“-动漫”进行动漫歌猜歌\n- 这个只能猜歌名和歌手\n- 本地动漫歌库歌曲命名规格“歌名 - 歌手”\n" +
|
||||
"2.可在后面添加“-动漫2”进行动漫歌猜歌\n- 这个可以猜番名,但歌手经常“未知”\n- 本地动漫2歌库歌曲命名规格“歌名 - 歌手 - 番名”",
|
||||
PrivateDataFolder: "guessmusic",
|
||||
}).ApplySingle(single.New(
|
||||
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("已经有正在进行的游戏..."),
|
||||
),
|
||||
)
|
||||
}),
|
||||
))
|
||||
cachePath := engine.DataFolder() + "cache/"
|
||||
err := os.MkdirAll(cachePath, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cfgFile := engine.DataFolder() + "config.json"
|
||||
if file.IsExist(cfgFile) {
|
||||
reader, err := os.Open(cfgFile)
|
||||
if err == nil {
|
||||
err = json.NewDecoder(reader).Decode(&cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
err = reader.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
err = saveConfig(cfgFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
engine.OnRegex(`^设置猜歌(缓存歌库路径|本地|Api)\s*(.*)$`, func(ctx *zero.Ctx) bool {
|
||||
if !zero.SuperUserPermission(ctx) {
|
||||
ctx.SendChain(message.Text("只有bot主人可以设置!"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
option := ctx.State["regex_matched"].([]string)[1]
|
||||
value := ctx.State["regex_matched"].([]string)[2]
|
||||
switch option {
|
||||
case "缓存歌库路径":
|
||||
if value == "" {
|
||||
ctx.SendChain(message.Text("请输入正确的路径!"))
|
||||
return
|
||||
}
|
||||
musicPath := strings.ReplaceAll(value, "\\", "/")
|
||||
if !strings.HasSuffix(musicPath, "/") {
|
||||
musicPath += "/"
|
||||
}
|
||||
cfg.MusicPath = musicPath
|
||||
case "本地":
|
||||
choice, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
cfg.Local = choice
|
||||
case "Api":
|
||||
choice, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
cfg.API = choice
|
||||
}
|
||||
err = saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^(个人|团队)猜歌(-动漫|-动漫2)?$`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
mode := ctx.State["regex_matched"].([]string)[2]
|
||||
gid := strconv.FormatInt(ctx.Event.GroupID, 10)
|
||||
if mode == "-动漫2" {
|
||||
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲名称|歌手|番剧|提示|取消]”\n一共3段语音,6次机会"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲名称|歌手|提示|取消]”\n一共3段语音,6次机会"))
|
||||
}
|
||||
// 随机抽歌
|
||||
musicName, pathOfMusic, err := musicLottery(mode, cfg.MusicPath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
return
|
||||
}
|
||||
// 切割音频,生成3个10秒的音频
|
||||
outputPath := cachePath + gid + "/"
|
||||
err = cutMusic(musicName, pathOfMusic, outputPath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
return
|
||||
}
|
||||
// 进行猜歌环节
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav"))
|
||||
answerString := strings.Split(musicName, " - ")
|
||||
var next *zero.FutureEvent
|
||||
if ctx.State["regex_matched"].([]string)[1] == "个人" {
|
||||
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), ctx.CheckSession())
|
||||
} else {
|
||||
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), zero.CheckGroup(ctx.Event.GroupID))
|
||||
}
|
||||
var musicCount = 0 // 音频数量
|
||||
var answerCount = 0 // 问答次数
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
wait := time.NewTimer(40 * time.Second)
|
||||
tick := time.NewTimer(105 * time.Second)
|
||||
after := time.NewTimer(120 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
ctx.SendChain(message.Text("猜歌游戏,你还有15s作答时间"))
|
||||
case <-after.C:
|
||||
msg := make(message.Message, 0, 3)
|
||||
msg = append(msg, message.Reply(ctx.Event.MessageID))
|
||||
msg = append(msg, message.Text("猜歌超时,游戏结束\n答案是:",
|
||||
"\n歌名:", answerString[0],
|
||||
"\n歌手:", answerString[1]))
|
||||
if mode == "-动漫2" {
|
||||
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||
}
|
||||
ctx.Send(msg)
|
||||
return
|
||||
case <-wait.C:
|
||||
wait.Reset(40 * time.Second)
|
||||
musicCount++
|
||||
if musicCount > 2 {
|
||||
wait.Stop()
|
||||
continue
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Text("好像有些难度呢,再听这段音频,要仔细听哦"),
|
||||
)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||
case c := <-recv:
|
||||
wait.Reset(40 * time.Second)
|
||||
tick.Reset(105 * time.Second)
|
||||
after.Reset(120 * time.Second)
|
||||
answer := strings.Replace(c.Event.Message.String(), "-", "", 1)
|
||||
switch {
|
||||
case answer == "取消":
|
||||
if c.Event.UserID == ctx.Event.UserID {
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
msg := make(message.Message, 0, 3)
|
||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||
msg = append(msg, message.Text("游戏已取消,猜歌答案是",
|
||||
"\n歌名:", answerString[0],
|
||||
"\n歌手:", answerString[1]))
|
||||
if mode == "-动漫2" {
|
||||
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||
}
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("你无权限取消"),
|
||||
),
|
||||
)
|
||||
case answer == "提示":
|
||||
musicCount++
|
||||
if musicCount > 2 {
|
||||
wait.Stop()
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("已经没有提示了哦"),
|
||||
),
|
||||
)
|
||||
continue
|
||||
}
|
||||
wait.Reset(40 * time.Second)
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("再听这段音频,要仔细听哦"),
|
||||
),
|
||||
)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||
case strings.Contains(answerString[0], answer) || strings.EqualFold(answerString[0], answer):
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
msg := make(message.Message, 0, 3)
|
||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||
msg = append(msg, message.Text("太棒了,你猜对歌曲名了!答案是",
|
||||
"\n歌名:", answerString[0],
|
||||
"\n歌手:", answerString[1]))
|
||||
if mode == "-动漫2" {
|
||||
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||
}
|
||||
ctx.Send(msg)
|
||||
return
|
||||
case answerString[1] == "未知" && answer == "未知":
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("该模式禁止回答“未知”"),
|
||||
),
|
||||
)
|
||||
case strings.Contains(answerString[1], answer) || strings.EqualFold(answerString[1], answer):
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
msg := make(message.Message, 0, 3)
|
||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||
msg = append(msg, message.Text("太棒了,你猜对歌手名了!答案是",
|
||||
"\n歌名:", answerString[0],
|
||||
"\n歌手:", answerString[1]))
|
||||
if mode == "-动漫2" {
|
||||
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||
}
|
||||
ctx.Send(msg)
|
||||
return
|
||||
default:
|
||||
if mode == "-动漫2" && (strings.Contains(answerString[2], answer) || strings.EqualFold(answerString[2], answer)) {
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("太棒了,你猜对番剧名了!答案是:",
|
||||
"\n歌名:", answerString[0],
|
||||
"\n歌手:", answerString[1],
|
||||
"\n歌曲出自:", answerString[2]),
|
||||
))
|
||||
return
|
||||
}
|
||||
musicCount++
|
||||
switch {
|
||||
case musicCount > 2 && answerCount < 6:
|
||||
wait.Stop()
|
||||
answerCount++
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("答案不对哦,加油啊~"),
|
||||
),
|
||||
)
|
||||
case musicCount > 2:
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
msg := make(message.Message, 0, 3)
|
||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||
msg = append(msg, message.Text("次数到了,你没能猜出来。\n答案是:",
|
||||
"\n歌名:", answerString[0],
|
||||
"\n歌手:", answerString[1]))
|
||||
if mode == "-动漫2" {
|
||||
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||
}
|
||||
ctx.Send(msg)
|
||||
return
|
||||
default:
|
||||
wait.Reset(40 * time.Second)
|
||||
answerCount++
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("答案不对,再听这段音频,要仔细听哦"),
|
||||
),
|
||||
)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func saveConfig(cfgFile string) (err error) {
|
||||
if reader, err := os.Create(cfgFile); err == nil {
|
||||
err = json.NewEncoder(reader).Encode(&cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 随机抽取音乐
|
||||
func musicLottery(mode, musicPath string) (musicName, pathOfMusic string, err error) {
|
||||
switch mode {
|
||||
case "-动漫":
|
||||
pathOfMusic = musicPath + "动漫/"
|
||||
case "-动漫2":
|
||||
pathOfMusic = musicPath + "动漫2/"
|
||||
default:
|
||||
pathOfMusic = musicPath + "歌榜/"
|
||||
}
|
||||
err = os.MkdirAll(pathOfMusic, 0755)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[生成文件夹错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
files, err := ioutil.ReadDir(pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[读取本地列表错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.Local && cfg.API {
|
||||
switch {
|
||||
case len(files) == 0:
|
||||
// 如果没有任何本地就下载歌曲
|
||||
musicName, err = getAPIMusic(mode, pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[本地数据为0,歌曲下载错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
case rand.Intn(2) == 0:
|
||||
// [0,1)只会取到0,rand不允许的
|
||||
musicName = getLocalMusic(files)
|
||||
default:
|
||||
musicName, err = getAPIMusic(mode, pathOfMusic)
|
||||
if err != nil {
|
||||
// 如果下载失败就从本地抽一个歌曲
|
||||
musicName = getLocalMusic(files)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if cfg.Local {
|
||||
if len(files) == 0 {
|
||||
err = errors.New("[本地数据为0,未开启API数据]")
|
||||
return
|
||||
}
|
||||
musicName = getLocalMusic(files)
|
||||
return
|
||||
}
|
||||
if cfg.API {
|
||||
musicName, err = getAPIMusic(mode, pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[获取API失败,未开启本地数据] ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errors.New("[未开启API以及本地数据]")
|
||||
return
|
||||
}
|
||||
|
||||
func getAPIMusic(mode string, musicPath string) (musicName string, err error) {
|
||||
switch mode {
|
||||
case "-动漫":
|
||||
musicName, err = getPaugramData(musicPath)
|
||||
case "-动漫2":
|
||||
musicName, err = getAnimeData(musicPath)
|
||||
default:
|
||||
musicName, err = getNetEaseData(musicPath)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getLocalMusic(files []fs.FileInfo) (musicName string) {
|
||||
if len(files) > 1 {
|
||||
musicName = strings.Replace(files[rand.Intn(len(files))].Name(), ".mp3", "", 1)
|
||||
} else {
|
||||
musicName = strings.Replace(files[0].Name(), ".mp3", "", 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 下载保罗API的歌曲
|
||||
func getPaugramData(musicPath string) (musicName string, err error) {
|
||||
api := "https://api.paugram.com/acgm/?list=1"
|
||||
referer := "https://api.paugram.com/"
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var parsed paugramData
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
name := parsed.Title
|
||||
artistsName := parsed.Artist
|
||||
musicURL := parsed.Link
|
||||
if name == "" || artistsName == "" {
|
||||
err = errors.New("无法获API取歌曲信息")
|
||||
return
|
||||
}
|
||||
musicName = name + " - " + artistsName
|
||||
downMusic := musicPath + "/" + musicName + ".mp3"
|
||||
response, err := http.Head(musicURL)
|
||||
if err != nil {
|
||||
err = errors.Errorf("下载音乐失败, ERROR: %s", err)
|
||||
return
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
err = errors.Errorf("下载音乐失败, Status Code: %d", response.StatusCode)
|
||||
return
|
||||
}
|
||||
if file.IsNotExist(downMusic) {
|
||||
data, err = web.GetData(musicURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(downMusic, data, 0666)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 下载animeMusic API的歌曲
|
||||
func getAnimeData(musicPath string) (musicName string, err error) {
|
||||
api := "https://anime-music.jijidown.com/api/v2/music"
|
||||
referer := "https://anime-music.jijidown.com/"
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var parsed animeData
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
name := parsed.Res.Title
|
||||
artistName := parsed.Res.Author
|
||||
acgName := parsed.Res.AnimeInfo.Title
|
||||
//musicURL := parsed.Res.PlayURL
|
||||
if name == "" || artistName == "" {
|
||||
err = errors.New("无法获API取歌曲信息")
|
||||
return
|
||||
}
|
||||
requestURL := "https://music.cyrilstudio.top/search?keywords=" + url.QueryEscape(name+" "+artistName) + "&limit=1"
|
||||
if artistName == "未知" {
|
||||
requestURL = "https://music.cyrilstudio.top/search?keywords=" + url.QueryEscape(acgName+" "+name) + "&limit=1"
|
||||
}
|
||||
data, err = web.GetData(requestURL)
|
||||
if err != nil {
|
||||
err = errors.Errorf("API歌曲查询失败, ERROR: %s", err)
|
||||
return
|
||||
}
|
||||
var autumnfish autumnfishData
|
||||
err = json.Unmarshal(data, &autumnfish)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if autumnfish.Code != 200 {
|
||||
err = errors.Errorf("下载音乐失败, Status Code: %d", autumnfish.Code)
|
||||
return
|
||||
}
|
||||
musicID := strconv.Itoa(autumnfish.Result.Songs[0].ID)
|
||||
if artistName == "未知" {
|
||||
artistName = strings.ReplaceAll(autumnfish.Result.Songs[0].Artists[0].Name, " - ", "-")
|
||||
}
|
||||
musicName = name + " - " + artistName + " - " + acgName
|
||||
downMusic := musicPath + "/" + musicName + ".mp3"
|
||||
musicURL := "http://music.163.com/song/media/outer/url?id=" + musicID
|
||||
response, err := http.Head(musicURL)
|
||||
if err != nil {
|
||||
err = errors.Errorf("下载音乐失败, ERROR: %s", err)
|
||||
return
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
err = errors.Errorf("下载音乐失败, Status Code: %d", response.StatusCode)
|
||||
return
|
||||
}
|
||||
if file.IsNotExist(downMusic) {
|
||||
data, err = web.GetData(musicURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(downMusic, data, 0666)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 下载网易云热歌榜音乐
|
||||
func getNetEaseData(musicPath string) (musicName string, err error) {
|
||||
api := "https://api.uomg.com/api/rand.music?sort=%E7%83%AD%E6%AD%8C%E6%A6%9C&format=json"
|
||||
referer := "https://api.uomg.com/api/rand.music"
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var parsed netEaseData
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
name := parsed.Data.Name
|
||||
musicURL := parsed.Data.URL
|
||||
artistsName := parsed.Data.Artistsname
|
||||
if name == "" || artistsName == "" {
|
||||
err = errors.New("无法获API取歌曲信息")
|
||||
return
|
||||
}
|
||||
musicName = name + " - " + artistsName
|
||||
downMusic := musicPath + "/" + musicName + ".mp3"
|
||||
if file.IsNotExist(downMusic) {
|
||||
data, err = web.GetData(musicURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(downMusic, data, 0666)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 切割音乐成三个10s音频
|
||||
func cutMusic(musicName, pathOfMusic, outputPath string) (err error) {
|
||||
err = os.MkdirAll(outputPath, 0755)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[生成歌曲目录错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
var stderr bytes.Buffer
|
||||
cmdArguments := []string{"-y", "-i", pathOfMusic + musicName + ".mp3",
|
||||
"-ss", cuttime[0], "-t", "10", file.BOTPATH + "/" + outputPath + "0.wav",
|
||||
"-ss", cuttime[1], "-t", "10", file.BOTPATH + "/" + outputPath + "1.wav",
|
||||
"-ss", cuttime[2], "-t", "10", file.BOTPATH + "/" + outputPath + "2.wav", "-hide_banner"}
|
||||
cmd := exec.Command("ffmpeg", cmdArguments...)
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
err = errors.Errorf("[生成歌曲错误]ERROR:%s", stderr.String())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
108
plugin/guessmusic/struct.go
Normal file
108
plugin/guessmusic/struct.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package guessmusic
|
||||
|
||||
type config struct {
|
||||
MusicPath string `json:"musicPath"`
|
||||
Local bool `json:"local"`
|
||||
API bool `json:"api"`
|
||||
}
|
||||
|
||||
type paugramData struct {
|
||||
ID int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Artist string `json:"artist"`
|
||||
Album string `json:"album"`
|
||||
Cover string `json:"cover"`
|
||||
Lyric string `json:"lyric"`
|
||||
SubLyric string `json:"sub_lyric"`
|
||||
Link string `json:"link"`
|
||||
Cached bool `json:"cached"`
|
||||
}
|
||||
|
||||
type animeData struct {
|
||||
Msg string `json:"msg"`
|
||||
Res struct {
|
||||
ID string `json:"id"`
|
||||
AnimeInfo struct {
|
||||
Desc string `json:"desc"`
|
||||
ID string `json:"id"`
|
||||
Atime int `json:"atime"`
|
||||
Logo string `json:"logo"`
|
||||
Year int `json:"year"`
|
||||
Bg string `json:"bg"`
|
||||
Title string `json:"title"`
|
||||
Month int `json:"month"`
|
||||
} `json:"anime_info"`
|
||||
PlayURL string `json:"play_url"`
|
||||
Atime int `json:"atime"`
|
||||
Title string `json:"title"`
|
||||
Author string `json:"author"`
|
||||
Type string `json:"type"`
|
||||
Recommend bool `json:"recommend"`
|
||||
} `json:"res"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
|
||||
type netEaseData struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Picurl string `json:"picurl"`
|
||||
Artistsname string `json:"artistsname"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type autumnfishData struct {
|
||||
Result struct {
|
||||
Songs []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Artists []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PicURL interface{} `json:"picUrl"`
|
||||
Alias []interface{} `json:"alias"`
|
||||
AlbumSize int `json:"albumSize"`
|
||||
PicID int `json:"picId"`
|
||||
Img1V1URL string `json:"img1v1Url"`
|
||||
Img1V1 int `json:"img1v1"`
|
||||
Trans interface{} `json:"trans"`
|
||||
} `json:"artists"`
|
||||
Album struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Artist struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PicURL interface{} `json:"picUrl"`
|
||||
Alias []interface{} `json:"alias"`
|
||||
AlbumSize int `json:"albumSize"`
|
||||
PicID int `json:"picId"`
|
||||
Img1V1URL string `json:"img1v1Url"`
|
||||
Img1V1 int `json:"img1v1"`
|
||||
Trans interface{} `json:"trans"`
|
||||
} `json:"artist"`
|
||||
PublishTime int64 `json:"publishTime"`
|
||||
Size int `json:"size"`
|
||||
CopyrightID int `json:"copyrightId"`
|
||||
Status int `json:"status"`
|
||||
PicID int64 `json:"picId"`
|
||||
Mark int `json:"mark"`
|
||||
} `json:"album"`
|
||||
Duration int `json:"duration"`
|
||||
CopyrightID int `json:"copyrightId"`
|
||||
Status int `json:"status"`
|
||||
Alias []interface{} `json:"alias"`
|
||||
Rtype int `json:"rtype"`
|
||||
Ftype int `json:"ftype"`
|
||||
TransNames []string `json:"transNames"`
|
||||
Mvid int `json:"mvid"`
|
||||
Fee int `json:"fee"`
|
||||
RURL interface{} `json:"rUrl"`
|
||||
Mark int `json:"mark"`
|
||||
} `json:"songs"`
|
||||
HasMore bool `json:"hasMore"`
|
||||
SongCount int `json:"songCount"`
|
||||
} `json:"result"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
package hs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -12,19 +11,15 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
var (
|
||||
cachedir = file.BOTPATH + "/data/hs/"
|
||||
reqconf = [...]string{"GET", "https://hs.fbigame.com",
|
||||
"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}
|
||||
)
|
||||
var reqconf = [...]string{"GET", "https://hs.fbigame.com",
|
||||
"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}
|
||||
|
||||
const (
|
||||
hs = `https://hs.fbigame.com/ajax.php?`
|
||||
@@ -46,19 +41,15 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
os.RemoveAll(cachedir)
|
||||
err := os.MkdirAll(cachedir, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
engine := control.Register("hs", order.PrioHS, &control.Options{
|
||||
engine := control.Register("hs", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "炉石\n" +
|
||||
"- 搜卡[xxxx]\n" +
|
||||
"- [卡组代码xxx]\n" +
|
||||
"- 更多搜卡指令参数:https://hs.fbigame.com/misc/searchhelp",
|
||||
PrivateDataFolder: "hs",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
cachedir := file.BOTPATH + "/" + engine.DataFolder()
|
||||
engine.OnRegex(`^搜卡(.+)$`).
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
List := ctx.State["regex_matched"].([]string)[1]
|
||||
@@ -73,7 +64,7 @@ func init() {
|
||||
cid := gjson.Get(g, `list.`+strconv.Itoa(i)+`.CardID`).String()
|
||||
cachefile := cachedir + cid
|
||||
if file.IsNotExist(cachefile) {
|
||||
data, err := web.ReqWith(
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(),
|
||||
`https://res.fbigame.com/hs/v13/`+cid+`.png?auth_key=`+
|
||||
gjson.Get(g, `list.`+strconv.Itoa(i)+`.auth_key`).String(),
|
||||
reqconf[0], reqconf[1], reqconf[2])
|
||||
@@ -84,26 +75,18 @@ func init() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
sk = append(
|
||||
sk,
|
||||
message.CustomNode(
|
||||
zero.BotConfig.NickName[0],
|
||||
ctx.Event.SelfID,
|
||||
[]message.MessageSegment{message.Image("file:///" + cachefile)}, // 图片
|
||||
),
|
||||
)
|
||||
sk = append(sk, ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+cachefile)))
|
||||
}
|
||||
if id := ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
sk,
|
||||
).Get("message_id").Int(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
})
|
||||
// 卡组
|
||||
engine.OnRegex(`^[\s\S]*?(AAE[a-zA-Z0-9/\+=]{70,})[\s\S]*$`).
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
fmt.Print("成功")
|
||||
List := ctx.State["regex_matched"].([]string)[1]
|
||||
ctx.SendChain(
|
||||
message.Image(kz(List)),
|
||||
@@ -112,10 +95,10 @@ func init() {
|
||||
}
|
||||
|
||||
func sh(s string) string {
|
||||
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), "https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
url := hs + para + "&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
|
||||
r, err := web.ReqWith(url, reqconf[0], reqconf[1], reqconf[2])
|
||||
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
return helper.BytesToString(r)
|
||||
}
|
||||
@@ -124,10 +107,10 @@ func sh(s string) string {
|
||||
}
|
||||
|
||||
func kz(s string) string {
|
||||
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), "https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
url := hs + para + "mod=general_deck_image&deck_code=" + s + "&deck_text=&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
|
||||
r, err := web.ReqWith(url, reqconf[0], reqconf[1], reqconf[2])
|
||||
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
return "base64://" + gjson.Get(helper.BytesToString(r), "img").String()
|
||||
}
|
||||
123
plugin/hyaku/main.go
Normal file
123
plugin/hyaku/main.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Package hyaku 百人一首
|
||||
package hyaku
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const bed = "https://gitcode.net/u011570312/OguraHyakuninIsshu/-/raw/master/"
|
||||
|
||||
//nolint: asciicheck
|
||||
type line struct {
|
||||
番号, 歌人, 上の句, 下の句, 上の句ひらがな, 下の句ひらがな string
|
||||
}
|
||||
|
||||
func (l *line) String() string {
|
||||
b := binary.NewWriterF(func(w *binary.Writer) {
|
||||
r := reflect.ValueOf(l).Elem().Type()
|
||||
for i := 0; i < r.NumField(); i++ {
|
||||
switch i {
|
||||
case 0:
|
||||
w.WriteString("●")
|
||||
case 1:
|
||||
w.WriteString("◉")
|
||||
case 2, 3:
|
||||
w.WriteString("○")
|
||||
case 4, 5:
|
||||
w.WriteString("◎")
|
||||
}
|
||||
w.WriteString(r.Field(i).Name)
|
||||
w.WriteString(":")
|
||||
w.WriteString((*[6]string)(unsafe.Pointer(l))[i])
|
||||
w.WriteString("\n")
|
||||
}
|
||||
})
|
||||
return binary.BytesToString(b)
|
||||
}
|
||||
|
||||
var lines [100]*line
|
||||
|
||||
func init() {
|
||||
engine := control.Register("hyaku", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "百人一首\n" +
|
||||
"- 百人一首(随机发一首)\n" +
|
||||
"- 百人一首之n",
|
||||
PrivateDataFolder: "hyaku",
|
||||
})
|
||||
csvfile := engine.DataFolder() + "hyaku.csv"
|
||||
go func() {
|
||||
if file.IsNotExist(csvfile) {
|
||||
err := file.DownloadTo(bed+"小倉百人一首.csv", csvfile, true)
|
||||
if err != nil {
|
||||
_ = os.Remove(csvfile)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
f, err := os.Open(csvfile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
records, err := csv.NewReader(f).ReadAll()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = f.Close()
|
||||
records = records[1:] // skip title
|
||||
if len(records) != 100 {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
for j, r := range records {
|
||||
if len(r) != 6 {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
i, err := strconv.Atoi(r[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
i--
|
||||
if j != i {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
lines[i] = (*line)(*(*unsafe.Pointer)(unsafe.Pointer(&r)))
|
||||
}
|
||||
}()
|
||||
engine.OnFullMatch("百人一首").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
i := rand.Intn(100)
|
||||
ctx.SendChain(
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i+1)),
|
||||
message.Text("\n", lines[i]),
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.png", i+1)),
|
||||
)
|
||||
})
|
||||
engine.OnRegex(`^百人一首之\s?(\d+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
i, err := strconv.Atoi(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if i > 100 || i < 1 {
|
||||
ctx.SendChain(message.Text("ERROR:超出范围"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i)),
|
||||
message.Text("\n", lines[i-1]),
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.png", i)),
|
||||
)
|
||||
})
|
||||
}
|
||||
145
plugin/image_finder/keyword.go
Normal file
145
plugin/image_finder/keyword.go
Normal file
@@ -0,0 +1,145 @@
|
||||
// Package imagefinder 关键字搜图
|
||||
package imagefinder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/http3"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
type resultjson struct {
|
||||
Error bool `json:"error"`
|
||||
Message string `json:"message"`
|
||||
Data struct {
|
||||
Illusts []struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
AltTitle string `json:"altTitle"`
|
||||
Description string `json:"description"`
|
||||
Type int64 `json:"type"`
|
||||
CreateDate string `json:"createDate"`
|
||||
UploadDate string `json:"uploadDate"`
|
||||
Sanity int64 `json:"sanity"`
|
||||
Width int64 `json:"width"`
|
||||
Height int64 `json:"height"`
|
||||
PageCount int64 `json:"pageCount"`
|
||||
Tags []struct {
|
||||
Name string `json:"name"`
|
||||
Translation string `json:"translation"`
|
||||
} `json:"tags"`
|
||||
Statistic struct {
|
||||
Bookmarks int64 `json:"bookmarks"`
|
||||
Likes int64 `json:"likes"`
|
||||
Comments int64 `json:"comments"`
|
||||
Views int64 `json:"views"`
|
||||
} `json:"statistic"`
|
||||
Image string `json:"image"`
|
||||
} `json:"illusts"`
|
||||
Scores []float64 `json:"scores"`
|
||||
HasNext bool `json:"has_next"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
var hrefre = regexp.MustCompile(`<a href=".*">`)
|
||||
|
||||
func init() {
|
||||
control.Register("imgfinder", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "关键字搜图\n" +
|
||||
"- 来张 [xxx]",
|
||||
}).OnRegex(`^来张\s?(.*)$`, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
soutujson, err := soutuapi(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
rannum := rand.Intn(len(soutujson.Data.Illusts))
|
||||
il := soutujson.Data.Illusts[rannum]
|
||||
illust, err := pixiv.Works(il.ID)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
u := illust.ImageUrls[0]
|
||||
n := u[strings.LastIndex(u, "/")+1 : len(u)-4]
|
||||
f := illust.Path(0)
|
||||
|
||||
err = pool.SendImageFromPool(n, f, func() error {
|
||||
// 下载图片
|
||||
return illust.DownloadToCache(0)
|
||||
}, ctxext.SendFakeForwardToGroup(ctx,
|
||||
message.Text(
|
||||
il.Width, "x", il.Height, "\n",
|
||||
"标题: ", il.Title, "\n",
|
||||
"副标题: ", il.AltTitle, "\n",
|
||||
"ID: ", il.ID, "\n",
|
||||
"画师: ", illust.UserName, " (", illust.UserId, ")", "\n",
|
||||
"分级:", il.Sanity, "\n",
|
||||
hrefre.ReplaceAllString(strings.ReplaceAll(strings.ReplaceAll(il.Description, "<br />", "\n"), "</a>", ""), ""),
|
||||
printtags(reflect.ValueOf(&il.Tags)),
|
||||
),
|
||||
), ctxext.GetFirstMessageInForward(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// soutuapi 请求api
|
||||
func soutuapi(keyword string) (r resultjson, err error) {
|
||||
var data []byte
|
||||
data, err = web.RequestDataWith(&http.Client{Transport: &http3.RoundTripper{}},
|
||||
"https://api.pixivel.moe/v2/pixiv/illust/search/"+url.QueryEscape(keyword)+"?page=0",
|
||||
"GET",
|
||||
"https://pixivel.moe/",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36",
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &r)
|
||||
if err == nil && r.Error {
|
||||
err = errors.New(r.Message)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func printtags(r reflect.Value) string {
|
||||
tags := r.Elem()
|
||||
s := binary.BytesToString(binary.NewWriterF(func(w *binary.Writer) {
|
||||
for i := 0; i < tags.Len(); i++ {
|
||||
_ = w.WriteByte('\n')
|
||||
tag := tags.Index(i)
|
||||
_ = w.WriteByte('#')
|
||||
w.WriteString(tag.Field(0).String())
|
||||
if !tag.Field(1).IsZero() {
|
||||
w.WriteString(" (")
|
||||
w.WriteString(tag.Field(1).String())
|
||||
w.WriteString(")")
|
||||
}
|
||||
}
|
||||
}))
|
||||
return s
|
||||
}
|
||||
23
plugin/inject/main.go
Normal file
23
plugin/inject/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Package inject 注入指令
|
||||
package inject
|
||||
|
||||
import (
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("inject", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "注入指令\n" +
|
||||
"- run[CQ码]",
|
||||
})
|
||||
// 运行 CQ 码
|
||||
en.OnPrefix("run", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(message.UnescapeCQCodeText(ctx.State["args"].(string)))
|
||||
})
|
||||
}
|
||||
24
plugin/jandan/data.go
Normal file
24
plugin/jandan/data.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package jandan
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
)
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
var mu sync.RWMutex
|
||||
|
||||
type picture struct {
|
||||
ID uint64 `db:"id"`
|
||||
URL string `db:"url"`
|
||||
}
|
||||
|
||||
func getRandomPicture() (u string, err error) {
|
||||
var p picture
|
||||
mu.RLock()
|
||||
err = db.Pick("picture", &p)
|
||||
mu.RUnlock()
|
||||
u = p.URL
|
||||
return
|
||||
}
|
||||
@@ -6,15 +6,16 @@ import (
|
||||
"hash/crc64"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/antchfx/htmlquery"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -22,12 +23,35 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("jandan", order.PrioJandan, &control.Options{
|
||||
engine := control.Register("jandan", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "煎蛋网无聊图\n- 来份屌图\n- 更新屌图\n",
|
||||
Help: "煎蛋网无聊图\n- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
|
||||
PublicDataFolder: "Jandan",
|
||||
})
|
||||
|
||||
engine.OnFullMatch("来份屌图").SetBlock(true).
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "pics.db"
|
||||
_, _ = engine.GetLazyData("pics.db", false)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("picture", &picture{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("picture")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Printf("[jandan]读取%d张图片", n)
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnRegex(`来份[屌|弔|吊]图`, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
u, err := getRandomPicture()
|
||||
if err != nil {
|
||||
@@ -37,7 +61,7 @@ func init() {
|
||||
ctx.SendChain(message.Image(u))
|
||||
})
|
||||
|
||||
engine.OnFullMatch("更新屌图", zero.SuperUserPermission).SetBlock(true).
|
||||
engine.OnRegex(`更新[屌|弔|吊]图`, zero.SuperUserPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send("少女更新中...")
|
||||
webpageURL := api
|
||||
@@ -54,7 +78,7 @@ func init() {
|
||||
}
|
||||
LOOP:
|
||||
for i := 0; i < pageTotal; i++ {
|
||||
logrus.Infoln("[jandan]", fmt.Sprintf("处理第%d/%d页...", i, pageTotal))
|
||||
logrus.Debugln("[jandan]", fmt.Sprintf("处理第%d/%d页...", i, pageTotal))
|
||||
doc, err = htmlquery.LoadURL(webpageURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
@@ -74,7 +98,7 @@ func init() {
|
||||
mu.RUnlock()
|
||||
if !ok {
|
||||
mu.Lock()
|
||||
db.Insert("picture", &picture{ID: i, URL: u})
|
||||
_ = db.Insert("picture", &picture{ID: i, URL: u})
|
||||
mu.Unlock()
|
||||
} else {
|
||||
// 开始重复,说明之后都是重复
|
||||
@@ -7,15 +7,13 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("juejuezi", order.PrioJueJueZi, &control.Options{
|
||||
control.Register("juejuezi", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "绝绝子生成器\n" +
|
||||
"- 喝奶茶绝绝子 | 绝绝子吃饭",
|
||||
@@ -37,14 +35,16 @@ func init() {
|
||||
case 2:
|
||||
data, err := juejuezi(string(toDealStr[0]), string(toDealStr[1]))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
|
||||
default:
|
||||
params := ctx.GetWordSlices(string(toDealStr)).Get("slices").Array()
|
||||
data, err := juejuezi(params[0].String(), params[1].String())
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
|
||||
}
|
||||
@@ -57,13 +57,13 @@ func juejuezi(verb, noun string) (data []byte, err error) {
|
||||
// 提交请求
|
||||
request, err := http.NewRequest("POST", juejueziURL, strings.NewReader(juejueziStr))
|
||||
if err != nil {
|
||||
log.Errorln("[juejuezi]:", err)
|
||||
return nil, err
|
||||
}
|
||||
request.Header.Add("Referer", referer)
|
||||
request.Header.Add("User-Agent", ua)
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Errorln("[juejuezi]:", err)
|
||||
return nil, err
|
||||
}
|
||||
data, err = io.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
101
plugin/lolicon/lolicon.go
Normal file
101
plugin/lolicon/lolicon.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Package lolicon 基于 https://api.lolicon.app 随机图片
|
||||
package lolicon
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
const (
|
||||
api = "https://api.lolicon.app/setu/v2"
|
||||
capacity = 10
|
||||
)
|
||||
|
||||
var (
|
||||
queue = make(chan string, capacity)
|
||||
custapi = ""
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("lolicon", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "lolicon\n" +
|
||||
"- 来份萝莉\n" +
|
||||
"- 设置随机图片地址[http...]",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
en.OnFullMatch("来份萝莉").Limit(ctxext.LimitByGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
go func() {
|
||||
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
|
||||
if custapi != "" {
|
||||
data, err := web.GetData(custapi)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
continue
|
||||
}
|
||||
queue <- "base64://" + base64.StdEncoding.EncodeToString(data)
|
||||
continue
|
||||
}
|
||||
data, err := web.GetData(api)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
continue
|
||||
}
|
||||
json := gjson.ParseBytes(data)
|
||||
if e := json.Get("error").Str; e != "" {
|
||||
ctx.SendChain(message.Text("ERROR:", e))
|
||||
continue
|
||||
}
|
||||
url := json.Get("data.0.urls.original").Str
|
||||
url = strings.ReplaceAll(url, "i.pixiv.cat", "i.pixiv.re")
|
||||
name := url[strings.LastIndex(url, "/")+1 : len(url)-4]
|
||||
m, err := pool.GetImage(name)
|
||||
if err != nil {
|
||||
m.SetFile(url)
|
||||
_, err = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
if err == nil {
|
||||
queue <- m.String()
|
||||
} else {
|
||||
queue <- url
|
||||
}
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case <-time.After(time.Minute):
|
||||
ctx.SendChain(message.Text("ERROR:等待填充,请稍后再试......"))
|
||||
case img := <-queue:
|
||||
id := ctx.SendChain(message.Image(img))
|
||||
if id.ID() == 0 {
|
||||
process.SleepAbout1sTo2s()
|
||||
id = ctx.SendChain(message.Image(img).Add("cache", "0"))
|
||||
if id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:图片发送失败,可能被风控了~"))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
en.OnPrefix("设置随机图片地址", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
u := strings.TrimSpace(ctx.State["args"].(string))
|
||||
if !strings.HasPrefix(u, "http") {
|
||||
ctx.SendChain(message.Text("ERROR:url非法!"))
|
||||
return
|
||||
}
|
||||
custapi = u
|
||||
})
|
||||
}
|
||||
@@ -4,7 +4,6 @@ package manager
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -15,19 +14,17 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin_manager/timer"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/manager/timer"
|
||||
)
|
||||
|
||||
const (
|
||||
datapath = "data/manager/"
|
||||
confile = datapath + "config.db"
|
||||
hint = "====群管====\n" +
|
||||
hint = "====群管====\n" +
|
||||
"- 禁言@QQ 1分钟\n" +
|
||||
"- 解除禁言 @QQ\n" +
|
||||
"- 我要自闭 1分钟\n" +
|
||||
@@ -50,27 +47,33 @@ const (
|
||||
"- 取消在\"cron\"的提醒\n" +
|
||||
"- 列出所有提醒\n" +
|
||||
"- 翻牌\n" +
|
||||
"- 设置欢迎语XXX\n" +
|
||||
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}] {at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名\n" +
|
||||
"- 测试欢迎语\n" +
|
||||
"- 设置告别辞 参数同设置欢迎语\n" +
|
||||
"- 测试告别辞\n" +
|
||||
"- [开启 | 关闭]入群验证"
|
||||
)
|
||||
|
||||
var (
|
||||
db = &sql.Sqlite{DBPath: confile}
|
||||
db = &sql.Sqlite{}
|
||||
clock timer.Clock
|
||||
)
|
||||
|
||||
var engine = control.Register("manager", order.PrioManager, &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: hint,
|
||||
})
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("manager", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: hint,
|
||||
PrivateDataFolder: "manager",
|
||||
})
|
||||
|
||||
go func() {
|
||||
defer order.DoneOnExit()()
|
||||
process.SleepAbout1sTo2s()
|
||||
_ = os.MkdirAll(datapath, 0755)
|
||||
db.DBPath = engine.DataFolder() + "config.db"
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
clock = timer.NewClock(db)
|
||||
err := db.Create("welcome", &welcome{})
|
||||
err = db.Create("welcome", &welcome{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -78,7 +81,12 @@ func init() { // 插件主体
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = db.Create("farewell", &welcome{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// 升为管理
|
||||
engine.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
@@ -211,6 +219,10 @@ func init() { // 插件主体
|
||||
// 修改名片
|
||||
engine.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[2]) > 60 {
|
||||
ctx.SendChain(message.Text("名字太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupCard(
|
||||
ctx.Event.GroupID,
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
|
||||
@@ -221,6 +233,10 @@ func init() { // 插件主体
|
||||
// 修改头衔
|
||||
engine.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
|
||||
@@ -231,6 +247,10 @@ func init() { // 插件主体
|
||||
// 申请头衔
|
||||
engine.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
ctx.Event.UserID, // 被修改群头衔的人
|
||||
@@ -270,7 +290,7 @@ func init() { // 插件主体
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, ctx.Event.GroupID, false)
|
||||
if ts.En() {
|
||||
go clock.RegisterTimer(ts, true)
|
||||
go clock.RegisterTimer(ts, true, false)
|
||||
ctx.SendChain(message.Text("记住了~"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("参数非法:" + ts.Alert))
|
||||
@@ -283,7 +303,7 @@ func init() { // 插件主体
|
||||
var url, alert string
|
||||
switch len(dateStrs) {
|
||||
case 4:
|
||||
url = dateStrs[2]
|
||||
url = strings.TrimPrefix(dateStrs[2], "用")
|
||||
alert = dateStrs[3]
|
||||
case 3:
|
||||
alert = dateStrs[2]
|
||||
@@ -293,7 +313,7 @@ func init() { // 插件主体
|
||||
}
|
||||
logrus.Debugln("[manager] cron:", dateStrs[1])
|
||||
ts := timer.GetFilledCronTimer(dateStrs[1], alert, url, ctx.Event.SelfID, ctx.Event.GroupID)
|
||||
if clock.RegisterTimer(ts, true) {
|
||||
if clock.RegisterTimer(ts, true, false) {
|
||||
ctx.SendChain(message.Text("记住了~"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("参数非法:" + ts.Alert))
|
||||
@@ -334,16 +354,11 @@ func init() { // 插件主体
|
||||
engine.OnFullMatchGroup([]string{"翻牌"}, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 无缓存获取群员列表
|
||||
list := ctx.CallAction("get_group_member_list", zero.Params{
|
||||
"group_id": ctx.Event.GroupID,
|
||||
"no_cache": true,
|
||||
}).Data
|
||||
temp := list.Array()
|
||||
temp := ctx.GetThisGroupMemberListNoCache().Array()
|
||||
sort.SliceStable(temp, func(i, j int) bool {
|
||||
return temp[i].Get("last_sent_time").Int() < temp[j].Get("last_sent_time").Int()
|
||||
})
|
||||
temp = temp[math.Max(0, len(temp)-10):]
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
who := temp[rand.Intn(len(temp))]
|
||||
if who.Get("user_id").Int() == ctx.Event.SelfID {
|
||||
ctx.SendChain(message.Text("幸运儿居然是我自己"))
|
||||
@@ -371,11 +386,11 @@ func init() { // 插件主体
|
||||
var w welcome
|
||||
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(w.Msg))
|
||||
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("欢迎~"))
|
||||
}
|
||||
c, ok := control.Lookup("manager")
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
enable := c.GetData(ctx.Event.GroupID)&1 == 1
|
||||
if enable {
|
||||
@@ -401,13 +416,13 @@ func init() { // 插件主体
|
||||
}
|
||||
return false
|
||||
}
|
||||
next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID), rule)
|
||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession(), rule)
|
||||
recv, cancel := next.Repeat()
|
||||
select {
|
||||
case <-time.After(time.Minute):
|
||||
cancel()
|
||||
ctx.SendChain(message.Text("拜拜啦~"))
|
||||
ctx.SetGroupKick(ctx.Event.GroupID, uid, false)
|
||||
cancel()
|
||||
case <-recv:
|
||||
cancel()
|
||||
ctx.SendChain(message.Text("答对啦~"))
|
||||
@@ -420,16 +435,24 @@ func init() { // 插件主体
|
||||
engine.OnNotice().SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.NoticeType == "group_decrease" {
|
||||
userid := ctx.Event.UserID
|
||||
ctx.SendChain(message.Text(ctxext.CardOrNickName(ctx, userid), "(", userid, ")", "离开了我们..."))
|
||||
var w welcome
|
||||
err := db.Find("farewell", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
|
||||
if err == nil {
|
||||
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
|
||||
} else {
|
||||
userid := ctx.Event.UserID
|
||||
ctx.SendChain(message.Text(ctx.CardOrNickName(userid), "(", userid, ")", "离开了我们..."))
|
||||
}
|
||||
}
|
||||
})
|
||||
// 设置欢迎语
|
||||
engine.OnRegex(`^设置欢迎语([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
welcomestring := ctx.State["regex_matched"].([]string)[1]
|
||||
welcomestring = message.UnescapeCQCodeText(welcomestring)
|
||||
w := &welcome{
|
||||
GrpID: ctx.Event.GroupID,
|
||||
Msg: ctx.State["regex_matched"].([]string)[1],
|
||||
Msg: welcomestring,
|
||||
}
|
||||
err := db.Insert("welcome", w)
|
||||
if err == nil {
|
||||
@@ -438,11 +461,50 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("出错啦: ", err))
|
||||
}
|
||||
})
|
||||
// 测试欢迎语
|
||||
engine.OnFullMatch("测试欢迎语", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var w welcome
|
||||
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
|
||||
if err == nil {
|
||||
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("欢迎~"))
|
||||
}
|
||||
})
|
||||
// 设置告别辞
|
||||
engine.OnRegex(`^设置告别辞([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
farewellstring := ctx.State["regex_matched"].([]string)[1]
|
||||
farewellstring = message.UnescapeCQCodeText(farewellstring)
|
||||
w := &welcome{
|
||||
GrpID: ctx.Event.GroupID,
|
||||
Msg: farewellstring,
|
||||
}
|
||||
err := db.Insert("farewell", w)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("记住啦!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("出错啦: ", err))
|
||||
}
|
||||
})
|
||||
// 测试告别辞
|
||||
engine.OnFullMatch("测试告别辞", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var w welcome
|
||||
err := db.Find("farewell", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
|
||||
if err == nil {
|
||||
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
|
||||
} else {
|
||||
userid := ctx.Event.UserID
|
||||
ctx.SendChain(message.Text(ctx.CardOrNickName(userid), "(", userid, ")", "离开了我们..."))
|
||||
}
|
||||
})
|
||||
// 入群后验证开关
|
||||
engine.OnRegex(`^(.*)入群验证$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
option := ctx.State["regex_matched"].([]string)[1]
|
||||
c, ok := control.Lookup("manager")
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
data := c.GetData(ctx.Event.GroupID)
|
||||
switch option {
|
||||
@@ -467,7 +529,7 @@ func init() { // 插件主体
|
||||
engine.OnRegex(`^(.*)gist加群自动审批$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
option := ctx.State["regex_matched"].([]string)[1]
|
||||
c, ok := control.Lookup("manager")
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
data := c.GetData(ctx.Event.GroupID)
|
||||
switch option {
|
||||
@@ -488,15 +550,6 @@ func init() { // 插件主体
|
||||
}
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
})
|
||||
// 运行 CQ 码
|
||||
engine.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var cmd = ctx.State["regex_matched"].([]string)[1]
|
||||
cmd = strings.ReplaceAll(cmd, "[", "[")
|
||||
cmd = strings.ReplaceAll(cmd, "]", "]")
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(cmd)
|
||||
})
|
||||
// 根据 gist 自动同意加群
|
||||
// 加群请在github新建一个gist,其文件名为本群群号的字符串的md5(小写),内容为一行,是当前unix时间戳(10分钟内有效)。
|
||||
// 然后请将您的用户名和gist哈希(小写)按照username/gisthash的格式填写到回答即可。
|
||||
@@ -504,7 +557,7 @@ func init() { // 插件主体
|
||||
/*if ctx.Event.RequestType == "friend" {
|
||||
ctx.SetFriendAddRequest(ctx.Event.Flag, true, "")
|
||||
}*/
|
||||
c, ok := control.Lookup("manager")
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok && c.GetData(ctx.Event.GroupID)&0x10 == 0x10 && ctx.Event.RequestType == "group" && ctx.Event.SubType == "add" {
|
||||
// gist 文件名是群号的 ascii 编码的 md5
|
||||
// gist 内容是当前 uinx 时间戳,在 10 分钟内视为有效
|
||||
@@ -516,7 +569,7 @@ func init() { // 插件主体
|
||||
}
|
||||
ghun := ans[:divi]
|
||||
hash := ans[divi+1:]
|
||||
logrus.Infoln("[manager]收到加群申请, 用户:", ghun, ", hash:", hash)
|
||||
logrus.Debugln("[manager]收到加群申请, 用户:", ghun, ", hash:", hash)
|
||||
ok, reason := checkNewUser(ctx.Event.UserID, ctx.Event.GroupID, ghun, hash)
|
||||
if ok {
|
||||
ctx.SetGroupAddRequest(ctx.Event.Flag, "add", true, "")
|
||||
@@ -528,3 +581,20 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 传入 ctx 和 welcome格式string 返回cq格式string 使用方法:welcometocq(ctx,w.Msg)
|
||||
func welcometocq(ctx *zero.Ctx, welcome string) string {
|
||||
uid := strconv.FormatInt(ctx.Event.UserID, 10) // 用户id
|
||||
nickname := ctx.CardOrNickName(ctx.Event.UserID) // 用户昵称
|
||||
at := "[CQ:at,qq=" + uid + "]" // at用户
|
||||
avatar := "[CQ:image,file=" + "http://q4.qlogo.cn/g?b=qq&nk=" + uid + "&s=640]" // 用户头像
|
||||
gid := strconv.FormatInt(ctx.Event.GroupID, 10) // 群id
|
||||
groupname := ctx.GetGroupInfo(ctx.Event.GroupID, true).Name // 群名
|
||||
cqstring := strings.ReplaceAll(welcome, "{at}", at)
|
||||
cqstring = strings.ReplaceAll(cqstring, "{nickname}", nickname)
|
||||
cqstring = strings.ReplaceAll(cqstring, "{avatar}", avatar)
|
||||
cqstring = strings.ReplaceAll(cqstring, "{uid}", uid)
|
||||
cqstring = strings.ReplaceAll(cqstring, "{gid}", gid)
|
||||
cqstring = strings.ReplaceAll(cqstring, "{groupname}", groupname)
|
||||
return cqstring
|
||||
}
|
||||
@@ -106,10 +106,10 @@ func GetFilledTimer(dateStrs []string, botqq, grp int64, matchDateOnly bool) *Ti
|
||||
urlStr := dateStrs[5]
|
||||
if urlStr != "" { // 是图片url
|
||||
t.URL = urlStr[3:] // utf-8下用为3字节
|
||||
logrus.Println("[群管]" + t.URL)
|
||||
logrus.Debugln("[群管]" + t.URL)
|
||||
if !strings.HasPrefix(t.URL, "http") {
|
||||
t.URL = "illegal"
|
||||
logrus.Println("[群管]url非法!")
|
||||
logrus.Debugln("[群管]url非法!")
|
||||
return &t
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/fumiama/cron"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
@@ -47,7 +48,7 @@ func NewClock(db *sql.Sqlite) (c Clock) {
|
||||
}
|
||||
|
||||
// RegisterTimer 注册计时器
|
||||
func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
|
||||
func (c *Clock) RegisterTimer(ts *Timer, save, isinit bool) bool {
|
||||
var key uint32
|
||||
if save {
|
||||
key = ts.GetTimerID()
|
||||
@@ -59,9 +60,12 @@ func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
|
||||
if t != ts && ok { // 避免重复注册定时器
|
||||
t.SetEn(false)
|
||||
}
|
||||
logrus.Println("[群管]注册计时器", key)
|
||||
logrus.Infoln("[群管]注册计时器", key)
|
||||
if ts.Cron != "" {
|
||||
var ctx *zero.Ctx
|
||||
if isinit {
|
||||
process.GlobalInitMutex.Lock()
|
||||
}
|
||||
if ts.SelfID != 0 {
|
||||
ctx = zero.GetBot(ts.SelfID)
|
||||
} else {
|
||||
@@ -71,6 +75,9 @@ func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
|
||||
return false
|
||||
})
|
||||
}
|
||||
if isinit {
|
||||
process.GlobalInitMutex.Unlock()
|
||||
}
|
||||
eid, err := c.cron.AddFunc(ts.Cron, func() { ts.sendmsg(ts.GrpID, ctx) })
|
||||
if err == nil {
|
||||
c.entmu.Lock()
|
||||
@@ -187,7 +194,7 @@ func (c *Clock) loadTimers(db *sql.Sqlite) {
|
||||
var t Timer
|
||||
_ = c.db.FindFor("timer", &t, "", func() error {
|
||||
tescape := t
|
||||
go c.RegisterTimer(&tescape, false)
|
||||
go c.RegisterTimer(&tescape, false, true)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
539
plugin/midicreate/midicreate.go
Normal file
539
plugin/midicreate/midicreate.go
Normal file
@@ -0,0 +1,539 @@
|
||||
// Package midicreate 简易midi音乐制作
|
||||
package midicreate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/pkg/errors"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"gitlab.com/gomidi/midi/v2"
|
||||
"gitlab.com/gomidi/midi/v2/smf"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("midicreate", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "midi音乐制作,该插件需要安装timidity,linux安装脚本可参考https://gitcode.net/anto_july/midi/-/raw/master/timidity.sh,windows安装脚本可参考https://gitcode.net/anto_july/midi/-/raw/master/timidity.bat,windows需要管理员模式运行\n" +
|
||||
"- midi制作 CCGGAAGR FFEEDDCR GGFFEEDR GGFFEEDR CCGGAAGR FFEEDDCR\n" +
|
||||
"- 个人听音练习\n" +
|
||||
"- 团队听音练习\n" +
|
||||
"- *.mid (midi 转 txt)\n" +
|
||||
"- midi制作*.txt (txt 转 midi)\n" +
|
||||
"- 设置音色40 (0~127)",
|
||||
PrivateDataFolder: "midicreate",
|
||||
})
|
||||
cachePath := engine.DataFolder() + "cache/"
|
||||
_ = os.RemoveAll(cachePath)
|
||||
err := os.MkdirAll(cachePath, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
engine.OnPrefix("midi制作").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
input := ctx.State["args"].(string)
|
||||
midiFile := cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
|
||||
cmidiFile, err := str2music(ctx, input, midiFile)
|
||||
if err != nil {
|
||||
if file.IsExist(midiFile) {
|
||||
ctx.UploadThisGroupFile(file.BOTPATH+"/"+midiFile, filepath.Base(midiFile), "")
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("ERROR:无法转换midi文件,", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
|
||||
})
|
||||
engine.OnRegex("^(个人|团队)听音练习$", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
ctx.SendChain(message.Text("欢迎来到听音练习, 一共有5个问题, 每个问题1分"))
|
||||
var mode int
|
||||
var next *zero.FutureEvent
|
||||
var maxErrorCount int
|
||||
if ctx.State["regex_matched"].([]string)[1] == "个人" {
|
||||
mode = 0
|
||||
next = zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^[A-G][b|#]?\d{0,2}$`),
|
||||
zero.OnlyGroup, ctx.CheckSession())
|
||||
maxErrorCount = 3
|
||||
} else {
|
||||
mode = 1
|
||||
next = zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^[A-G][b|#]?\d{0,2}$`),
|
||||
zero.OnlyGroup, zero.CheckGroup(ctx.Event.GroupID))
|
||||
maxErrorCount = 10
|
||||
}
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
|
||||
score := make(map[int64]float64)
|
||||
round := 1
|
||||
maxRound := 6
|
||||
errorCount := 0
|
||||
target := uint8(55 + rand.Intn(34))
|
||||
answer := name(target) + strconv.Itoa(int(target/12))
|
||||
midiFile := cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
|
||||
cmidiFile, err := str2music(ctx, answer, midiFile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:听音练习结束, 无法转换midi文件, ", err))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("判断上面的音频, 输入音符, 例如C#6"),
|
||||
),
|
||||
)
|
||||
tick := time.NewTimer(45 * time.Second)
|
||||
after := time.NewTimer(60 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
ctx.SendChain(message.Text("听音练习, 你还有15s作答时间"))
|
||||
case <-after.C:
|
||||
var text string
|
||||
for k, v := range score {
|
||||
text += fmt.Sprintf("%s: %.1f\n", ctx.CardOrNickName(k), v)
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("听音练习超时, 练习结束...答案是: ", answer, "\n所得分数如下:\n", text),
|
||||
),
|
||||
)
|
||||
return
|
||||
case c := <-recv:
|
||||
tick.Reset(45 * time.Second)
|
||||
after.Reset(60 * time.Second)
|
||||
n := processOne(c.Event.Message.String())
|
||||
if n != target {
|
||||
errorCount++
|
||||
}
|
||||
if errorCount == maxErrorCount || n == target {
|
||||
if n == target {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("恭喜你回答正确, 答案是: ", answer),
|
||||
),
|
||||
)
|
||||
} else if errorCount == maxErrorCount {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("你的回答是: "),
|
||||
),
|
||||
)
|
||||
midiFile = cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
|
||||
cmidiFile, err = str2music(ctx, c.Event.Message.String(), midiFile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: can't convert midi file,", err))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("回答错误, 答案是: ", answer, ", 错误次数已达3次, 进入下一关"),
|
||||
),
|
||||
)
|
||||
}
|
||||
// 统计分数
|
||||
if mode == 0 {
|
||||
switch errorCount {
|
||||
case 0:
|
||||
score[c.Event.UserID] += 1.0
|
||||
case 1:
|
||||
score[c.Event.UserID] += 0.5
|
||||
case 2:
|
||||
score[c.Event.UserID] += 0.2
|
||||
}
|
||||
} else if mode == 1 {
|
||||
if errorCount != maxErrorCount {
|
||||
score[c.Event.UserID] += 1.0
|
||||
}
|
||||
}
|
||||
// 下一关
|
||||
round++
|
||||
if round != maxRound {
|
||||
errorCount = 0
|
||||
target = uint8(55 + rand.Intn(34))
|
||||
answer = name(target) + strconv.Itoa(int(target/12))
|
||||
midiFile = cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
|
||||
cmidiFile, err = str2music(ctx, answer, midiFile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:听音练习结束, 无法转换midi文件, ", err))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("判断上面的音频, 输入音符, 例如C#6"),
|
||||
),
|
||||
)
|
||||
}
|
||||
} else if n != target {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("你的回答是: "),
|
||||
),
|
||||
)
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
midiFile = cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
|
||||
cmidiFile, err = str2music(ctx, c.Event.Message.String(), midiFile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: can't convert midi file,", err))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("回答错误, 错误次数为", errorCount, ", 请继续回答"),
|
||||
),
|
||||
)
|
||||
}
|
||||
if round == maxRound {
|
||||
var text string
|
||||
for k, v := range score {
|
||||
text += fmt.Sprintf("%s: %.1f\n", ctx.CardOrNickName(k), v)
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("回答完毕, 所得分数如下:\n", text),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.On("notice/group_upload", func(ctx *zero.Ctx) bool {
|
||||
return path.Ext(ctx.Event.File.Name) == ".mid"
|
||||
}).SetBlock(false).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
fileURL := ctx.GetThisGroupFileUrl(ctx.Event.File.BusID, ctx.Event.File.ID)
|
||||
data, err := web.GetData(fileURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
s, err := smf.ReadFrom(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
for i := 0; i < int(s.NumTracks()); i++ {
|
||||
midStr := mid2txt(data, i)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
fileName := strings.ReplaceAll(cachePath+"/"+ctx.Event.File.Name, ".mid", fmt.Sprintf("-%d.txt", i))
|
||||
_ = os.WriteFile(fileName, binary.StringToBytes(midStr), 0666)
|
||||
ctx.UploadThisGroupFile(file.BOTPATH+"/"+fileName, filepath.Base(fileName), "")
|
||||
}
|
||||
})
|
||||
engine.On("notice/group_upload", func(ctx *zero.Ctx) bool {
|
||||
return path.Ext(ctx.Event.File.Name) == ".txt" && strings.Contains(ctx.Event.File.Name, "midi制作")
|
||||
}).SetBlock(false).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
fileURL := ctx.GetThisGroupFileUrl(ctx.Event.File.BusID, ctx.Event.File.ID)
|
||||
data, err := web.GetData(fileURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
uid := ctx.Event.UserID
|
||||
midiFile := cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
|
||||
cmidiFile, err := str2music(ctx, binary.BytesToString(data), midiFile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:无法转换midi文件,", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
|
||||
})
|
||||
engine.OnPrefix("设置音色").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["args"].(string)
|
||||
timbre, err := strconv.Atoi(param)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
err = setTimbreMode(ctx, int64(timbre))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功"))
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
noteMap = map[string]uint8{
|
||||
"C": 60,
|
||||
"Db": 61,
|
||||
"D": 62,
|
||||
"Eb": 63,
|
||||
"E": 64,
|
||||
"F": 65,
|
||||
"Gb": 66,
|
||||
"G": 67,
|
||||
"Ab": 68,
|
||||
"A": 69,
|
||||
"Bb": 70,
|
||||
"B": 71,
|
||||
}
|
||||
)
|
||||
|
||||
func str2music(ctx *zero.Ctx, input, midiFile string) (cmidiFile string, err error) {
|
||||
err = mkMidi(ctx, midiFile, input)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cmidiFile = strings.ReplaceAll(midiFile, ".mid", ".wav")
|
||||
cmd := exec.Command("timidity", file.BOTPATH+"/"+midiFile, "-Ow", "-o", file.BOTPATH+"/"+cmidiFile)
|
||||
err = cmd.Run()
|
||||
return
|
||||
}
|
||||
|
||||
func mkMidi(ctx *zero.Ctx, filePath, input string) error {
|
||||
if file.IsExist(filePath) {
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
clock smf.MetricTicks
|
||||
tr smf.Track
|
||||
)
|
||||
|
||||
tr.Add(0, smf.MetaMeter(4, 4))
|
||||
tr.Add(0, smf.MetaTempo(72))
|
||||
tr.Add(0, smf.MetaInstrument("Violin"))
|
||||
timbre := getTimbreMode(ctx)
|
||||
tr.Add(0, midi.ProgramChange(0, uint8(timbre)))
|
||||
|
||||
k := strings.ReplaceAll(input, " ", "")
|
||||
|
||||
var (
|
||||
base uint8
|
||||
level uint8
|
||||
delay uint32
|
||||
sleepFlag bool
|
||||
lengthBytes = make([]byte, 0)
|
||||
)
|
||||
|
||||
for i := 0; i < len(k); {
|
||||
base = 0
|
||||
level = 0
|
||||
sleepFlag = false
|
||||
lengthBytes = lengthBytes[:0]
|
||||
for {
|
||||
switch {
|
||||
case k[i] == 'R':
|
||||
sleepFlag = true
|
||||
i++
|
||||
case k[i] >= 'A' && k[i] <= 'G':
|
||||
base = noteMap[k[i:i+1]] % 12
|
||||
i++
|
||||
case k[i] == 'b':
|
||||
base--
|
||||
i++
|
||||
case k[i] == '#':
|
||||
base++
|
||||
i++
|
||||
case k[i] >= '0' && k[i] <= '9':
|
||||
level = level*10 + k[i] - '0'
|
||||
i++
|
||||
case k[i] == '<':
|
||||
i++
|
||||
for i < len(k) && (k[i] == '-' || (k[i] >= '0' && k[i] <= '9')) {
|
||||
lengthBytes = append(lengthBytes, k[i])
|
||||
i++
|
||||
}
|
||||
default:
|
||||
return errors.Errorf("无法解析第%d个位置的%c字符", i, k[i])
|
||||
}
|
||||
if i >= len(k) || (k[i] >= 'A' && k[i] <= 'G') || k[i] == 'R' {
|
||||
break
|
||||
}
|
||||
}
|
||||
length, _ := strconv.Atoi(string(lengthBytes))
|
||||
if sleepFlag {
|
||||
if length >= 0 {
|
||||
delay = clock.Ticks4th() * (1 << length)
|
||||
} else {
|
||||
delay = clock.Ticks4th() / (1 << -length)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if level == 0 {
|
||||
level = 5
|
||||
}
|
||||
tr.Add(delay, midi.NoteOn(0, o(base, level), 120))
|
||||
if length >= 0 {
|
||||
tr.Add(clock.Ticks4th()*(1<<length), midi.NoteOff(0, o(base, level)))
|
||||
} else {
|
||||
tr.Add(clock.Ticks4th()/(1<<-length), midi.NoteOff(0, o(base, level)))
|
||||
}
|
||||
delay = 0
|
||||
}
|
||||
tr.Close(0)
|
||||
|
||||
s := smf.New()
|
||||
s.TimeFormat = clock
|
||||
err := s.Add(tr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.WriteTo(f)
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func o(base uint8, oct uint8) uint8 {
|
||||
if oct > 10 {
|
||||
oct = 10
|
||||
}
|
||||
|
||||
if oct == 0 {
|
||||
return base
|
||||
}
|
||||
|
||||
res := base + 12*oct
|
||||
if res > 127 {
|
||||
res -= 12
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func name(n uint8) string {
|
||||
for k, v := range noteMap {
|
||||
if v%12 == n%12 {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func processOne(note string) uint8 {
|
||||
k := strings.ReplaceAll(note, " ", "")
|
||||
var (
|
||||
base uint8
|
||||
level uint8
|
||||
)
|
||||
for i := 0; i < len(k); i++ {
|
||||
switch {
|
||||
case k[i] >= 'A' && k[i] <= 'G':
|
||||
base = noteMap[k[i:i+1]] % 12
|
||||
case k[i] == 'b':
|
||||
base--
|
||||
case k[i] == '#':
|
||||
base++
|
||||
case k[i] >= '0' && k[i] <= '9':
|
||||
level = level*10 + k[i] - '0'
|
||||
}
|
||||
}
|
||||
if level == 0 {
|
||||
level = 5
|
||||
}
|
||||
return o(base, level)
|
||||
}
|
||||
|
||||
func mid2txt(midBytes []byte, trackNo int) (midStr string) {
|
||||
var (
|
||||
absTicksStart float64
|
||||
absTicksEnd float64
|
||||
startNote byte
|
||||
endNote byte
|
||||
defaultMetric = 960.0
|
||||
)
|
||||
_ = smf.ReadTracksFrom(bytes.NewReader(midBytes), trackNo).
|
||||
Do(
|
||||
func(te smf.TrackEvent) {
|
||||
if !te.Message.IsMeta() {
|
||||
b := te.Message.Bytes()
|
||||
if te.Message.Is(midi.NoteOnMsg) && b[2] > 0 {
|
||||
absTicksStart = float64(te.AbsTicks)
|
||||
startNote = b[1]
|
||||
}
|
||||
if te.Message.Is(midi.NoteOffMsg) || (te.Message.Is(midi.NoteOnMsg) && b[2] == 0x00) {
|
||||
absTicksEnd = float64(te.AbsTicks)
|
||||
endNote = b[1]
|
||||
if startNote == endNote {
|
||||
sign := name(b[1])
|
||||
level := b[1] / 12
|
||||
length := (absTicksEnd - absTicksStart) / defaultMetric
|
||||
midStr += sign
|
||||
if level != 5 {
|
||||
midStr += strconv.Itoa(int(level))
|
||||
}
|
||||
pow := int(math.Round(math.Log2(length)))
|
||||
if pow >= -4 && pow != 0 {
|
||||
midStr += "<" + strconv.Itoa(pow)
|
||||
}
|
||||
startNote = 0
|
||||
endNote = 0
|
||||
}
|
||||
}
|
||||
if (te.Message.Is(midi.NoteOnMsg) && b[2] > 0) && absTicksStart > absTicksEnd {
|
||||
length := (absTicksStart - absTicksEnd) / defaultMetric
|
||||
pow := int(math.Round(math.Log2(length)))
|
||||
if pow == 0 {
|
||||
midStr += "R"
|
||||
} else if pow >= -4 {
|
||||
midStr += "R<" + strconv.Itoa(pow)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func setTimbreMode(ctx *zero.Ctx, timbre int64) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
if timbre < 0 || timbre > 127 {
|
||||
return errors.New("音色应该在0~127之间")
|
||||
}
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
return m.SetData(gid, timbre)
|
||||
}
|
||||
|
||||
func getTimbreMode(ctx *zero.Ctx) (index int64) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
index := m.GetData(gid)
|
||||
return index
|
||||
}
|
||||
return 40
|
||||
}
|
||||
@@ -12,7 +12,6 @@ var sr = reg.NewRegedit("reilia.fumiama.top:32664", "fumiama", "--")
|
||||
|
||||
func TestGetHoliday(t *testing.T) {
|
||||
registry.Connect()
|
||||
holidaymap = make(map[string]*Holiday)
|
||||
h := GetHoliday("元旦")
|
||||
registry.Close()
|
||||
t.Fatal(h)
|
||||
@@ -28,19 +27,19 @@ func TestSetHoliday(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = SetHoliday("春节", 7, 2022, 1, 31)
|
||||
err = SetHoliday("春节", 7, 2023, 1, 21)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = SetHoliday("清明节", 1, 2022, 4, 3)
|
||||
err = SetHoliday("清明节", 1, 2023, 4, 5)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = SetHoliday("劳动节", 1, 2022, 4, 30)
|
||||
err = SetHoliday("劳动节", 1, 2023, 5, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = SetHoliday("端午节", 1, 2022, 6, 3)
|
||||
err = SetHoliday("端午节", 1, 2023, 6, 22)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -21,29 +21,20 @@ func NewHoliday(name string, dur, year int, month time.Month, day int) *Holiday
|
||||
return &Holiday{name: name, date: time.Date(year, month, day, 0, 0, 0, 0, time.Local), dur: time.Duration(dur) * time.Hour * 24}
|
||||
}
|
||||
|
||||
var (
|
||||
registry = reg.NewRegReader("reilia.fumiama.top:32664", "fumiama")
|
||||
holidaymap map[string]*Holiday
|
||||
)
|
||||
var registry = reg.NewRegReader("reilia.fumiama.top:32664", "fumiama")
|
||||
|
||||
// GetHoliday 从 reg 服务器获取节日
|
||||
func GetHoliday(name string) *Holiday {
|
||||
var dur, year int
|
||||
var month time.Month
|
||||
var day int
|
||||
h, ok := holidaymap[name]
|
||||
if ok {
|
||||
return h
|
||||
}
|
||||
ret, err := registry.Get("holiday/" + name)
|
||||
if err != nil {
|
||||
return NewHoliday(name+err.Error(), 0, 0, 0, 0)
|
||||
}
|
||||
fmt.Sscanf(ret, "%d_%d_%d_%d", &dur, &year, &month, &day)
|
||||
logrus.Debugln("[moyu]获取节日:", name, dur, year, month, day)
|
||||
h = NewHoliday(name, dur, year, month, day)
|
||||
holidaymap[name] = h
|
||||
return h
|
||||
return NewHoliday(name, dur, year, month, day)
|
||||
}
|
||||
|
||||
// String 获取两个时间相差
|
||||
62
plugin/moyu/run.go
Normal file
62
plugin/moyu/run.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Package moyu 摸鱼
|
||||
package moyu
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
msg message.Message
|
||||
mu sync.Mutex
|
||||
lastupdate time.Time
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("moyu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "moyu\n" +
|
||||
"- /启用 moyu\n" +
|
||||
"- /禁用 moyu\n" +
|
||||
"- 记录在\"0 10 * * *\"触发的指令\n" +
|
||||
" - 摸鱼提醒",
|
||||
}).OnFullMatch("摸鱼提醒").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if msg == nil || time.Since(lastupdate) > time.Hour*20 {
|
||||
if registry.Connect() != nil {
|
||||
return
|
||||
}
|
||||
msg = message.Message{
|
||||
message.Text(time.Now().Format("2006-01-02")),
|
||||
message.Text("上午好,摸鱼人!\n工作再累,一定不要忘记摸鱼哦!有事没事起身去茶水间,去厕所,去廊道走走别老在工位上坐着,钱是老板的,但命是自己的。\n"),
|
||||
message.Text(weekend()),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("元旦")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("春节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("清明节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("劳动节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("端午节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("中秋节")),
|
||||
message.Text("\n"),
|
||||
message.Text(GetHoliday("国庆节")),
|
||||
message.Text("\n"),
|
||||
message.Text("上班是帮老板赚钱,摸鱼是赚老板的钱!最后,祝愿天下所有摸鱼人,都能愉快的渡过每一天…"),
|
||||
}
|
||||
_ = registry.Close()
|
||||
lastupdate = time.Now()
|
||||
}
|
||||
ctx.Send(msg)
|
||||
})
|
||||
}
|
||||
29
plugin/moyu_calendar/calendar.go
Normal file
29
plugin/moyu_calendar/calendar.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package moyucalendar 摸鱼人日历
|
||||
package moyucalendar
|
||||
|
||||
import (
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("moyucalendar", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "摸鱼人日历\n" +
|
||||
"- /启用 moyucalendar\n" +
|
||||
"- /禁用 moyucalendar\n" +
|
||||
"- 记录在\"30 8 * * *\"触发的指令\n" +
|
||||
" - 摸鱼人日历",
|
||||
}).OnFullMatch("摸鱼人日历").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
data, err := web.GetData("https://api.vvhan.com/api/moyu")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.ImageBytes(data))
|
||||
})
|
||||
}
|
||||
@@ -5,23 +5,24 @@ import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("music", order.PrioMusic, &control.Options{
|
||||
control.Register("music", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "点歌\n" +
|
||||
"- 点歌[xxx]\n" +
|
||||
@@ -136,81 +137,28 @@ func kugou(keyword string) message.MessageSegment {
|
||||
}
|
||||
|
||||
// cloud163 返回网易云音乐卡片
|
||||
func cloud163(keyword string) message.MessageSegment {
|
||||
headers := http.Header{
|
||||
"Content-Type": []string{"application/x-www-form-urlencoded"},
|
||||
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
|
||||
func cloud163(keyword string) (msg message.MessageSegment) {
|
||||
requestURL := "https://music.cyrilstudio.top/search?keywords=" + url.QueryEscape(keyword)
|
||||
data, err := web.GetData(requestURL)
|
||||
if err != nil {
|
||||
msg = message.Text("ERROR:", err)
|
||||
return
|
||||
}
|
||||
data := url.Values{
|
||||
"offset": []string{"0"},
|
||||
"total": []string{"true"},
|
||||
"limit": []string{"9"},
|
||||
"type": []string{"1"},
|
||||
"s": []string{keyword},
|
||||
}
|
||||
// 搜索音乐信息 第一首歌
|
||||
info := gjson.ParseBytes(netPost("http://music.163.com/api/search/pc", data, headers)).Get("result.songs.0")
|
||||
// 返回音乐卡片
|
||||
return message.CustomMusic(
|
||||
fmt.Sprintf("http://y.music.163.com/m/song?id=%d", info.Get("id").Int()),
|
||||
fmt.Sprintf("http://music.163.com/song/media/outer/url?id=%d.mp3", info.Get("id").Int()),
|
||||
info.Get("name").Str,
|
||||
).Add("content", info.Get("artists.0.name").Str).Add("image", info.Get("album.blurPicUrl").Str)
|
||||
msg = message.Music("163", gjson.ParseBytes(data).Get("result.songs.0.id").Int())
|
||||
return
|
||||
}
|
||||
|
||||
// qqmusic 返回QQ音乐卡片
|
||||
func qqmusic(keyword string) message.MessageSegment {
|
||||
// 搜索音乐信息 第一首歌
|
||||
h1 := http.Header{
|
||||
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
|
||||
func qqmusic(keyword string) (msg message.MessageSegment) {
|
||||
requestURL := "https://c.y.qq.com/soso/fcgi-bin/client_search_cp?w=" + url.QueryEscape(keyword)
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), requestURL, "GET", "", web.RandUA())
|
||||
if err != nil {
|
||||
msg = message.Text("ERROR:", err)
|
||||
return
|
||||
}
|
||||
search, _ := url.Parse("https://c.y.qq.com/soso/fcgi-bin/client_search_cp")
|
||||
search.RawQuery = url.Values{
|
||||
"w": []string{keyword},
|
||||
}.Encode()
|
||||
res := netGet(search.String(), h1)
|
||||
info := gjson.ParseBytes(res[9 : len(res)-1]).Get("data.song.list.0")
|
||||
// 获得音乐直链
|
||||
h2 := http.Header{
|
||||
"User-Agent": []string{"Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"},
|
||||
"referer": []string{"http://y.qq.com"},
|
||||
}
|
||||
music, _ := url.Parse("https://u.y.qq.com/cgi-bin/musicu.fcg")
|
||||
music.RawQuery = url.Values{
|
||||
"data": []string{`{"req": {"module": "CDN.SrfCdnDispatchServer", "method": "GetCdnDispatch", "param": {"guid": "3982823384", "calltype": 0, "userip": ""}}, "req_0": {"module": "vkey.GetVkeyServer", "method": "CgiGetVkey", "param": {"guid": "3982823384", "songmid": ["` + info.Get("songmid").Str + `"], "songtype": [0], "uin": "0", "loginflag": 1, "platform": "20"}}, "comm": {"uin": 0, "format": "json", "ct": 24, "cv": 0}}`},
|
||||
}.Encode()
|
||||
audio := gjson.ParseBytes(netGet(music.String(), h2))
|
||||
// 获得音乐封面
|
||||
image := "https://y.gtimg.cn/music/photo_new/" +
|
||||
find(
|
||||
`photo_new\u002F`,
|
||||
"?max_age",
|
||||
string(
|
||||
netGet("https://y.qq.com/n/yqq/song/"+info.Get("songmid").Str+".html", nil),
|
||||
),
|
||||
)
|
||||
// 返回音乐卡片
|
||||
return message.CustomMusic(
|
||||
"https://y.qq.com/n/yqq/song/"+info.Get("songmid").Str+".html",
|
||||
"https://isure.stream.qqmusic.qq.com/"+audio.Get("req_0.data.midurlinfo.0.purl").Str,
|
||||
info.Get("songname").Str,
|
||||
).Add("content", info.Get("singer.0.name").Str).Add("image", image)
|
||||
}
|
||||
|
||||
// find 返回 pre 到 suf 之间的文本
|
||||
func find(pre string, suf string, str string) string {
|
||||
n := strings.Index(str, pre)
|
||||
if n == -1 {
|
||||
n = 0
|
||||
} else {
|
||||
n += len(pre)
|
||||
}
|
||||
str = str[n:]
|
||||
m := strings.Index(str, suf)
|
||||
if m == -1 {
|
||||
m = len(str)
|
||||
}
|
||||
return str[:m]
|
||||
info := gjson.ParseBytes(data[9 : len(data)-1]).Get("data.song.list.0")
|
||||
msg = message.Music("qq", info.Get("songid").Int())
|
||||
return
|
||||
}
|
||||
|
||||
// md5str 返回字符串 MD5
|
||||
@@ -231,20 +179,6 @@ func netGet(url string, header http.Header) []byte {
|
||||
return nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
result, _ := ioutil.ReadAll(res.Body)
|
||||
return result
|
||||
}
|
||||
|
||||
// netPost 返回请求数据
|
||||
func netPost(url string, data url.Values, header http.Header) []byte {
|
||||
client := &http.Client{}
|
||||
request, _ := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
|
||||
request.Header = header
|
||||
res, err := client.Do(request)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
result, _ := ioutil.ReadAll(res.Body)
|
||||
result, _ := io.ReadAll(res.Body)
|
||||
return result
|
||||
}
|
||||
@@ -7,17 +7,14 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/corona10/goimagehash"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
_ "golang.org/x/image/webp" // import webp decoding
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
// setuclass holds setus in a folder, which is the class name.
|
||||
@@ -27,25 +24,7 @@ type setuclass struct {
|
||||
Path string `db:"path"` // Path 图片路径
|
||||
}
|
||||
|
||||
var ns = &nsetu{db: &sql.Sqlite{DBPath: dbfile}}
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
defer order.DoneOnExit()()
|
||||
process.SleepAbout1sTo2s()
|
||||
err := os.MkdirAll(datapath, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if file.IsExist(cfgfile) {
|
||||
b, err := os.ReadFile(cfgfile)
|
||||
if err == nil {
|
||||
setupath = helper.BytesToString(b)
|
||||
logrus.Println("[nsetu] set setu dir to", setupath)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
var ns = &nsetu{db: &sql.Sqlite{}}
|
||||
|
||||
type nsetu struct {
|
||||
db *sql.Sqlite
|
||||
@@ -54,7 +33,7 @@ type nsetu struct {
|
||||
|
||||
func (n *nsetu) List() (l []string) {
|
||||
if file.IsExist(n.db.DBPath) {
|
||||
err := n.db.Open()
|
||||
err := n.db.Open(time.Hour * 24)
|
||||
if err == nil {
|
||||
l, err = n.db.ListTables()
|
||||
}
|
||||
@@ -99,7 +78,8 @@ func (n *nsetu) scanclass(root fs.FS, path, clsn string) error {
|
||||
return err
|
||||
}
|
||||
n.mu.Lock()
|
||||
_ = n.db.Truncate(clsn)
|
||||
_ = n.db.Drop(clsn)
|
||||
_ = n.db.Create(clsn, &setuclass{})
|
||||
n.mu.Unlock()
|
||||
for _, d := range ds {
|
||||
nm := d.Name()
|
||||
@@ -10,16 +10,10 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/rule"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
datapath = "data/nsetu"
|
||||
dbfile = datapath + "/data.db"
|
||||
cfgfile = datapath + "/setupath.txt"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -27,7 +21,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("nativesetu", order.PrioNativeSetu, &control.Options{
|
||||
engine := control.Register("nativesetu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "本地涩图\n" +
|
||||
"- 本地[xxx]\n" +
|
||||
@@ -35,8 +29,20 @@ func init() {
|
||||
"- 设置本地setu绝对路径[xxx]\n" +
|
||||
"- 刷新所有本地setu\n" +
|
||||
"- 所有本地setu分类",
|
||||
PrivateDataFolder: "nsetu",
|
||||
})
|
||||
engine.OnRegex(`^本地(.*)$`, rule.FirstValueInList(ns)).SetBlock(true).
|
||||
|
||||
ns.db.DBPath = engine.DataFolder() + "data.db"
|
||||
cfgfile := engine.DataFolder() + "setupath.txt"
|
||||
if file.IsExist(cfgfile) {
|
||||
b, err := os.ReadFile(cfgfile)
|
||||
if err == nil {
|
||||
setupath = helper.BytesToString(b)
|
||||
logrus.Infoln("[nsetu] set setu dir to", setupath)
|
||||
}
|
||||
}
|
||||
|
||||
engine.OnRegex(`^本地(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, ns)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
imgtype := ctx.State["regex_matched"].([]string)[1]
|
||||
sc := new(setuclass)
|
||||
@@ -44,20 +50,27 @@ func init() {
|
||||
err := ns.db.Pick(imgtype, sc)
|
||||
ns.mu.RUnlock()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
} else {
|
||||
p := "file:///" + setupath + "/" + sc.Path
|
||||
if ctx.Event.GroupID != 0 {
|
||||
ctx.SendGroupForwardMessage(ctx.Event.GroupID, message.Message{
|
||||
ctxext.FakeSenderForwardNode(ctx,
|
||||
message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p),
|
||||
)})
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^刷新本地(.*)$`, rule.FirstValueInList(ns), zero.SuperUserPermission).SetBlock(true).
|
||||
engine.OnRegex(`^刷新本地(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, ns), zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
imgtype := ctx.State["regex_matched"].([]string)[1]
|
||||
err := ns.scanclass(os.DirFS(setupath), imgtype, imgtype)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^设置本地setu绝对路径(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
||||
@@ -67,7 +80,7 @@ func init() {
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("刷新所有本地setu", zero.SuperUserPermission).SetBlock(true).
|
||||
@@ -76,7 +89,7 @@ func init() {
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("所有本地setu分类").SetBlock(true).
|
||||
@@ -16,26 +16,19 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
)
|
||||
|
||||
const base = "data/nwife"
|
||||
|
||||
var baseuri = "file:///" + file.BOTPATH + "/" + base
|
||||
|
||||
func init() {
|
||||
err := os.MkdirAll(base, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
engine := control.Register("nwife", order.PrioNativeWife, &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "nativewife\n- 抽wife[@xxx]\n- 添加wife[名字][图片]\n- 删除wife[名字]\n- [让 | 不让]所有人均可添加wife",
|
||||
engine := control.Register("nwife", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "nativewife\n- 抽wife[@xxx]\n- 添加wife[名字][图片]\n- 删除wife[名字]\n- [让 | 不让]所有人均可添加wife",
|
||||
PrivateDataFolder: "nwife",
|
||||
})
|
||||
base := engine.DataFolder()
|
||||
baseuri := "file:///" + file.BOTPATH + "/" + base
|
||||
engine.OnPrefix("抽wife", zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
grpf := strconv.FormatInt(ctx.Event.GroupID, 36)
|
||||
@@ -52,7 +45,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("大家的wife都是", wn, "\n"), message.Image(baseuri+"/"+grpf+"/"+wn), message.Text("\n哦~"))
|
||||
default:
|
||||
// 获取名字
|
||||
name := ctxext.NickName(ctx)
|
||||
name := ctx.NickName()
|
||||
now := time.Now()
|
||||
s := md5.Sum(helper.StringToBytes(fmt.Sprintf("%s%d%d%d", name, now.Year(), now.Month(), now.Day())))
|
||||
r := rand.New(rand.NewSource(int64(binary.LittleEndian.Uint64(s[:]))))
|
||||
@@ -62,7 +55,7 @@ func init() {
|
||||
}
|
||||
})
|
||||
// 上传一张图
|
||||
engine.OnPrefix("添加wife", zero.OnlyGroup, chkAddWifePermission, ctxext.MustGiven).SetBlock(true).
|
||||
engine.OnPrefix("添加wife", zero.OnlyGroup, chkAddWifePermission, zero.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
name := ""
|
||||
for _, elem := range ctx.Event.Message {
|
||||
@@ -78,13 +71,13 @@ func init() {
|
||||
url := ctx.State["image_url"].([]string)[0]
|
||||
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
|
||||
if file.IsNotExist(grpfolder) {
|
||||
err = os.Mkdir(grpfolder, 0755)
|
||||
err := os.Mkdir(grpfolder, 0755)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("错误:", err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
err = file.DownloadTo(url, grpfolder+"/"+name, true)
|
||||
err := file.DownloadTo(url, grpfolder+"/"+name, true)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
|
||||
} else {
|
||||
@@ -108,7 +101,7 @@ func init() {
|
||||
}
|
||||
if name != "" {
|
||||
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
|
||||
err = os.Remove(grpfolder + "/" + name)
|
||||
err := os.Remove(grpfolder + "/" + name)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
|
||||
} else {
|
||||
@@ -131,9 +124,9 @@ func init() {
|
||||
var err error
|
||||
switch text {
|
||||
case "设置", "授予", "让":
|
||||
err = setEveryoneCanAddWife(ctx.Event.GroupID, true)
|
||||
err = setEveryoneCanAddWife(ctx, true)
|
||||
case "取消", "撤销", "不让":
|
||||
err = setEveryoneCanAddWife(ctx.Event.GroupID, false)
|
||||
err = setEveryoneCanAddWife(ctx, false)
|
||||
}
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
|
||||
@@ -146,7 +139,7 @@ func init() {
|
||||
func chkAddWifePermission(ctx *zero.Ctx) bool {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid > 0 {
|
||||
m, ok := control.Lookup("nwife")
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
data := m.GetData(gid)
|
||||
if data&1 == 1 {
|
||||
@@ -158,13 +151,13 @@ func chkAddWifePermission(ctx *zero.Ctx) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func setEveryoneCanAddWife(gid int64, canadd bool) error {
|
||||
m, ok := control.Lookup("nwife")
|
||||
func setEveryoneCanAddWife(ctx *zero.Ctx, canadd bool) error {
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
if canadd {
|
||||
return m.SetData(gid, 1)
|
||||
return m.SetData(ctx.Event.GroupID, 1)
|
||||
}
|
||||
return m.SetData(gid, 0)
|
||||
return m.SetData(ctx.Event.GroupID, 0)
|
||||
}
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
@@ -2,21 +2,20 @@
|
||||
package nbnhhsh
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("nbnhhsh", order.PrioNBNHHSH, &control.Options{
|
||||
control.Register("nbnhhsh", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "拼音首字母释义工具\n- ?? [缩写]",
|
||||
}).OnRegex(`^[??]{1,2} ?([a-z0-9]+)$`).SetBlock(false).
|
||||
@@ -31,7 +30,7 @@ func getValue(text string) []string {
|
||||
urlValues.Add("text", text)
|
||||
resp, err := http.PostForm("https://lab.magiconch.com/api/nbnhhsh/guess", urlValues)
|
||||
if err == nil {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err == nil {
|
||||
resp.Body.Close()
|
||||
json := gjson.ParseBytes(body)
|
||||
@@ -3,7 +3,7 @@ package novel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
@@ -11,57 +11,62 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/antchfx/htmlquery"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
ub "github.com/FloatTech/zbputils/binary"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const (
|
||||
websiteURL = "https://www.23qb.net"
|
||||
websiteURL = "https://www.23qb.com"
|
||||
websiteTitle = "铅笔小说"
|
||||
errorTitle = "出现错误!"
|
||||
username = "zerobot"
|
||||
password = "123456"
|
||||
submit = "%26%23160%3B%B5%C7%26%23160%3B%26%23160%3B%C2%BC%26%23160%3B"
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
|
||||
loginURL = websiteURL + "/login.php?do=submit&jumpurl=https%3A%2F%2Fwww.23qb.net%2F"
|
||||
loginURL = websiteURL + "/login.php?do=submit&jumpurl=https%3A%2F%2Fwww.23qb.com%2F"
|
||||
searchURL = websiteURL + "/saerch.php"
|
||||
idReg = `/(\d+)/`
|
||||
)
|
||||
|
||||
var (
|
||||
gCurCookieJar *cookiejar.Jar
|
||||
engine = control.Register("novel", order.PrioNovel, &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "铅笔小说网搜索\n- 小说[xxx]",
|
||||
})
|
||||
)
|
||||
var gCurCookieJar *cookiejar.Jar
|
||||
|
||||
func init() {
|
||||
engine.OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
control.Register("novel", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "铅笔小说网搜索\n- 小说[xxx]",
|
||||
}).OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
login(username, password)
|
||||
err := login(username, password)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
searchKey := ctx.State["regex_matched"].([]string)[1]
|
||||
searchHTML := search(searchKey)
|
||||
searchHTML, err := search(searchKey)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
doc, err := htmlquery.Parse(strings.NewReader(searchHTML))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
htmlTitle := htmlquery.InnerText(htmlquery.FindOne(doc, "/html/head/title"))
|
||||
switch htmlTitle {
|
||||
case websiteTitle:
|
||||
list, err := htmlquery.QueryAll(doc, "//dl[@id='nr']")
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if len(list) != 0 {
|
||||
txt := ""
|
||||
@@ -84,10 +89,11 @@ func init() {
|
||||
}
|
||||
data, err := text.RenderToBase64(txt, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
log.Println("err:", err)
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + helper.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
} else {
|
||||
text := htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@id='tipss']"))
|
||||
@@ -119,38 +125,39 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
func login(username, password string) {
|
||||
func login(username, password string) (err error) {
|
||||
gCurCookieJar, _ = cookiejar.New(nil)
|
||||
client := &http.Client{
|
||||
Jar: gCurCookieJar,
|
||||
}
|
||||
usernameData, err := ub.UTF82GBK(helper.StringToBytes(username))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
usernameGbk := helper.BytesToString(usernameData)
|
||||
passwordData, err := ub.UTF82GBK(helper.StringToBytes(password))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
passwordGbk := helper.BytesToString(passwordData)
|
||||
loginReq, err := http.NewRequest("POST", loginURL, strings.NewReader(fmt.Sprintf("username=%s&password=%s&usecookie=315360000&action=login&submit=%s", url.QueryEscape(usernameGbk), url.QueryEscape(passwordGbk), submit)))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
loginReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
loginReq.Header.Set("User-Agent", ua)
|
||||
loginResp, err := client.Do(loginReq)
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
defer loginResp.Body.Close()
|
||||
_ = loginResp.Body.Close()
|
||||
return
|
||||
}
|
||||
|
||||
func search(searchKey string) (searchHTML string) {
|
||||
func search(searchKey string) (searchHTML string, err error) {
|
||||
searchKeyData, err := ub.UTF82GBK(helper.StringToBytes(searchKey))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
searchKeyGbk := helper.BytesToString(searchKeyData)
|
||||
client := &http.Client{
|
||||
@@ -158,23 +165,23 @@ func search(searchKey string) (searchHTML string) {
|
||||
}
|
||||
searchReq, err := http.NewRequest("POST", searchURL, strings.NewReader(fmt.Sprintf("searchkey=%s&searchtype=all", url.QueryEscape(searchKeyGbk))))
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
searchReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
searchReq.Header.Set("User-Agent", ua)
|
||||
searchResp, err := client.Do(searchReq)
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
defer searchResp.Body.Close()
|
||||
searchData, err := ioutil.ReadAll(searchResp.Body)
|
||||
searchData, err := io.ReadAll(searchResp.Body)
|
||||
_ = searchResp.Body.Close()
|
||||
if err != nil {
|
||||
log.Errorf("[novel] get response for url=%s got error=%s\n", searchURL, err.Error())
|
||||
return
|
||||
}
|
||||
searchData, err = ub.GBK2UTF8(searchData)
|
||||
if err != nil {
|
||||
log.Errorln("[novel]", err)
|
||||
return
|
||||
}
|
||||
searchHTML = helper.BytesToString(searchData)
|
||||
return searchHTML
|
||||
return searchHTML, nil
|
||||
}
|
||||
@@ -3,54 +3,54 @@ package nsfw
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/AnimeAPI/nsfw"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/order"
|
||||
)
|
||||
|
||||
const hso = "https://gchat.qpic.cn/gchatpic_new//--4234EDEC5F147A4C319A41149D7E0EA9/0"
|
||||
|
||||
func init() {
|
||||
engine := control.Register("nsfw", order.PrioNSFW, &control.Options{
|
||||
engine := control.Register("nsfw", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "nsfw图片识别\n- nsfw打分[图片]",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
// 上传一张图进行评价
|
||||
engine.OnKeywordGroup([]string{"nsfw打分"}, zero.OnlyGroup, ctxext.CmdMatch, ctxext.MustGiven).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"nsfw打分"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["image_url"].([]string)
|
||||
if len(url) > 0 {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
p, err := nsfw.Classify(url...)
|
||||
p, err := nsfw.Classify(url[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(judge(p[0]))))
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(judge(p))))
|
||||
}
|
||||
})
|
||||
en := control.Register("nsfwauto", order.PrioNSFWAuto, &control.Options{
|
||||
control.Register("nsfwauto", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "nsfw图片自动识别\n- 当图片属于非 neutral 类别时自动发送评价",
|
||||
})
|
||||
en.OnMessage(ctxext.Exists).SetBlock(false).
|
||||
}).OnMessage(zero.HasPicture).SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["image_url"].([]string)
|
||||
if len(url) > 0 {
|
||||
process.SleepAbout1sTo2s()
|
||||
p, err := nsfw.Classify(url...)
|
||||
p, err := nsfw.Classify(url[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
process.SleepAbout1sTo2s()
|
||||
autojudge(ctx, p[0])
|
||||
autojudge(ctx, p)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func judge(p nsfw.Picture) string {
|
||||
func judge(p *nsfw.Picture) string {
|
||||
if p.Neutral > 0.3 {
|
||||
return "普通哦"
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func judge(p nsfw.Picture) string {
|
||||
return c
|
||||
}
|
||||
|
||||
func autojudge(ctx *zero.Ctx, p nsfw.Picture) {
|
||||
func autojudge(ctx *zero.Ctx, p *nsfw.Picture) {
|
||||
if p.Neutral > 0.3 {
|
||||
return
|
||||
}
|
||||
@@ -96,6 +96,6 @@ func autojudge(ctx *zero.Ctx, p nsfw.Picture) {
|
||||
i++
|
||||
}
|
||||
if i > 0 {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(c)))
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(c, "\n"), message.Image(hso)))
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
package omikuji
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
)
|
||||
|
||||
type kuji struct {
|
||||
ID uint8 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
// 返回一个解签
|
||||
func getKujiByBango(id uint8) string {
|
||||
var s kuji
|
||||
80
plugin/omikuji/sensou.go
Normal file
80
plugin/omikuji/sensou.go
Normal file
@@ -0,0 +1,80 @@
|
||||
// Package omikuji 浅草寺求签
|
||||
package omikuji
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
)
|
||||
|
||||
const bed = "https://gitcode.net/u011570312/senso-ji-omikuji/-/raw/main/%d_%d.jpg"
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("omikuji", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "浅草寺求签\n" +
|
||||
"- 求签 | 占卜\n- 解签",
|
||||
PublicDataFolder: "Omikuji",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
|
||||
engine.OnFullMatchGroup([]string{"求签", "占卜"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
i := ctxext.RandSenderPerDayN(ctx.Event.UserID, 100) + 1
|
||||
ctx.SendChain(
|
||||
message.At(ctx.Event.UserID),
|
||||
message.Image(fmt.Sprintf(bed, i, 0)),
|
||||
message.Image(fmt.Sprintf(bed, i, 1)),
|
||||
)
|
||||
})
|
||||
engine.OnFullMatch("解签", ctxext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "kuji.db"
|
||||
_, err := engine.GetLazyData("kuji.db", true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("kuji", &kuji{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("kuji")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Infof("[kuji]读取%d条签文", n)
|
||||
return true
|
||||
},
|
||||
)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
kujiBytes, err := text.RenderToBase64(
|
||||
getKujiByBango(
|
||||
uint8(ctxext.RandSenderPerDayN(ctx.Event.UserID, 100)+1),
|
||||
),
|
||||
text.FontFile, 400, 20,
|
||||
)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.At(ctx.Event.UserID), message.Image("base64://"+helper.BytesToString(kujiBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
})
|
||||
}
|
||||
798
plugin/qqwife/qqmapwife.go
Normal file
798
plugin/qqwife/qqmapwife.go
Normal file
@@ -0,0 +1,798 @@
|
||||
// Package qqwife 娶群友 基于“翻牌”和江林大佬的“群老婆”插件魔改作品,文案采用了Hana的zbp娶群友文案
|
||||
package qqwife
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
|
||||
// 数据库
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
// 定时器
|
||||
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
|
||||
// 画图
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/fogleman/gg"
|
||||
)
|
||||
|
||||
//nolint: asciicheck
|
||||
type 婚姻登记 struct {
|
||||
db *sql.Sqlite
|
||||
dbmu sync.RWMutex
|
||||
}
|
||||
|
||||
// 结婚证信息
|
||||
type userinfo struct {
|
||||
User int64 // 用户身份证
|
||||
Target int64 // 对象身份证号
|
||||
Username string // 户主名称
|
||||
Targetname string // 对象名称
|
||||
Updatetime string // 登记时间
|
||||
|
||||
}
|
||||
|
||||
// 民政局的当前时间
|
||||
type updateinfo struct {
|
||||
GID int64
|
||||
Updatetime string // 登记时间
|
||||
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) checkupdate(gid int64) (updatetime string, err error) {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
err = sql.db.Create("updateinfo", &updateinfo{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gidstr := strconv.FormatInt(gid, 10)
|
||||
dbinfo := updateinfo{}
|
||||
err = sql.db.Find("updateinfo", &dbinfo, "where gid is "+gidstr) // 获取表格更新的时间
|
||||
if err != nil {
|
||||
updatetime = time.Now().Format("2006/01/02")
|
||||
err = sql.db.Insert("updateinfo", &updateinfo{GID: gid, Updatetime: updatetime})
|
||||
return
|
||||
}
|
||||
updatetime = dbinfo.Updatetime
|
||||
return
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) 重置(gid string) error {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
if gid != "ALL" {
|
||||
err := sql.db.Drop(gid)
|
||||
if err != nil {
|
||||
err = sql.db.Create(gid, &userinfo{})
|
||||
return err
|
||||
}
|
||||
gidint, _ := strconv.ParseInt(gid, 10, 64)
|
||||
updateinfo := updateinfo{
|
||||
GID: gidint,
|
||||
Updatetime: time.Now().Format("2006/01/02"),
|
||||
}
|
||||
err = sql.db.Insert("updateinfo", &updateinfo)
|
||||
return err
|
||||
}
|
||||
grouplist, err := sql.db.ListTables()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, gid := range grouplist {
|
||||
err = sql.db.Drop(gid)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
gidint, _ := strconv.ParseInt(gid, 10, 64)
|
||||
updateinfo := updateinfo{
|
||||
GID: gidint,
|
||||
Updatetime: time.Now().Format("2006/01/02"),
|
||||
}
|
||||
err = sql.db.Insert("updateinfo", &updateinfo)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) 离婚休妻(gid, wife int64) error {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
gidstr := strconv.FormatInt(gid, 10)
|
||||
wifestr := strconv.FormatInt(wife, 10)
|
||||
// 先判断用户是否存在
|
||||
err := sql.db.Del(gidstr, "where target = "+wifestr)
|
||||
return err
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) 离婚休夫(gid, husband int64) error {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
gidstr := strconv.FormatInt(gid, 10)
|
||||
husbandstr := strconv.FormatInt(husband, 10)
|
||||
// 先判断用户是否存在
|
||||
err := sql.db.Del(gidstr, "where target = "+husbandstr)
|
||||
return err
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) 复婚(gid, uid, target int64, username, targetname string) error {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
gidstr := strconv.FormatInt(gid, 10)
|
||||
uidstr := strconv.FormatInt(uid, 10)
|
||||
tagstr := strconv.FormatInt(target, 10)
|
||||
var info userinfo
|
||||
err := sql.db.Find(gidstr, &info, "where user = "+uidstr)
|
||||
if err == nil {
|
||||
err = sql.db.Find(gidstr, &info, "where user = "+tagstr)
|
||||
}
|
||||
if err == nil {
|
||||
return err
|
||||
}
|
||||
updatetime := time.Now().Format("2006/01/02")
|
||||
// 更改夫妻信息
|
||||
info.User = uid
|
||||
info.Username = username
|
||||
info.Target = target
|
||||
info.Targetname = targetname
|
||||
info.Updatetime = updatetime
|
||||
// 民政局登记数据
|
||||
err = sql.db.Insert(gidstr, &info)
|
||||
return err
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) 花名册(gid int64) (list [][4]string, number int, err error) {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
gidstr := strconv.FormatInt(gid, 10)
|
||||
err = sql.db.Create(gidstr, &userinfo{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
number, err = sql.db.Count(gidstr)
|
||||
if err != nil || number <= 0 {
|
||||
return
|
||||
}
|
||||
var info userinfo
|
||||
list = make([][4]string, 0, number)
|
||||
err = sql.db.FindFor(gidstr, &info, "GROUP BY user", func() error {
|
||||
if info.Target == 0 {
|
||||
return nil
|
||||
}
|
||||
dbinfo := [4]string{
|
||||
info.Username,
|
||||
strconv.FormatInt(info.User, 10),
|
||||
info.Targetname,
|
||||
strconv.FormatInt(info.Target, 10),
|
||||
}
|
||||
list = append(list, dbinfo)
|
||||
return nil
|
||||
})
|
||||
if len(list) == 0 {
|
||||
number = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func slicename(name string, canvas *gg.Context) (resultname string) {
|
||||
usermane := []rune(name) // 将每个字符单独放置
|
||||
widthlen := 0
|
||||
numberlen := 0
|
||||
for i, v := range usermane {
|
||||
width, _ := canvas.MeasureString(string(v)) // 获取单个字符的宽度
|
||||
widthlen += int(width)
|
||||
if widthlen > 350 {
|
||||
break // 总宽度不能超过350
|
||||
}
|
||||
numberlen = i
|
||||
}
|
||||
if widthlen > 350 {
|
||||
resultname = string(usermane[:numberlen-1]) + "......" // 名字切片
|
||||
} else {
|
||||
resultname = name
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) 查户口(gid, uid int64) (info userinfo, status int, err error) {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
gidstr := strconv.FormatInt(gid, 10)
|
||||
uidstr := strconv.FormatInt(uid, 10)
|
||||
status = 3
|
||||
if err = sql.db.Create(gidstr, &userinfo{}); err != nil {
|
||||
status = 2
|
||||
return
|
||||
}
|
||||
err = sql.db.Find(gidstr, &info, "where user = "+uidstr)
|
||||
if err == nil {
|
||||
status = 1
|
||||
return
|
||||
}
|
||||
err = sql.db.Find(gidstr, &info, "where target = "+uidstr)
|
||||
if err == nil {
|
||||
status = 0
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sql *婚姻登记) 登记(gid, uid, target int64, username, targetname string) error {
|
||||
sql.dbmu.Lock()
|
||||
defer sql.dbmu.Unlock()
|
||||
gidstr := strconv.FormatInt(gid, 10)
|
||||
err := sql.db.Create(gidstr, &userinfo{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updatetime := time.Now().Format("2006/01/02")
|
||||
// 填写夫妻信息
|
||||
uidinfo := userinfo{
|
||||
User: uid,
|
||||
Username: username,
|
||||
Target: target,
|
||||
Targetname: targetname,
|
||||
Updatetime: updatetime,
|
||||
}
|
||||
// 民政局登记数据
|
||||
err = sql.db.Insert(gidstr, &uidinfo)
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
//nolint: asciicheck
|
||||
民政局 = &婚姻登记{
|
||||
db: &sql.Sqlite{},
|
||||
}
|
||||
skillCD = rate.NewManager[string](time.Hour*12, 1)
|
||||
sendtext = [...][]string{
|
||||
{ // 表白成功
|
||||
"是个勇敢的孩子(*/ω\*) 今天的运气都降临在你的身边~\n\n",
|
||||
"(´・ω・`)对方答应了你 并表示愿意当今天的CP\n\n",
|
||||
},
|
||||
{ // 表白失败
|
||||
"今天的运气有一点背哦~明天再试试叭",
|
||||
"_(:з」∠)_下次还有机会 咱抱抱你w",
|
||||
"今天失败了惹. 摸摸头~咱明天还有机会",
|
||||
},
|
||||
{ // ntr成功
|
||||
"因为你的个人魅力~~今天他就是你的了w\n\n",
|
||||
},
|
||||
{ // 离婚失败
|
||||
"打是情,骂是爱,,不打不亲不相爱。答应我不要分手。",
|
||||
"床头打架床尾和,夫妻没有隔夜仇。安啦安啦,不要闹变扭。",
|
||||
},
|
||||
{ // 离婚成功
|
||||
"离婚成功力\n天涯何处无芳草,何必单恋一枝花?不如再摘一支(bushi",
|
||||
"离婚成功力\n话说你不考虑当个1?",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("qqwife", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
PrivateDataFolder: "qqwife",
|
||||
Help: "一群一天一夫一妻制群老婆\n(每天凌晨刷新CP)\n" +
|
||||
"- 娶群友\n- 群老婆列表\n" +
|
||||
"--------------------------------\n以下技能每人只能三选一\n CD12H,不跨天刷新\n--------------------------------\n" +
|
||||
"- (娶|嫁)@对方QQ\n- 当[对方Q号|@对方QQ]的小三\n- 闹离婚",
|
||||
})
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
民政局.db.DBPath = engine.DataFolder() + "结婚登记表.db"
|
||||
// 如果数据库不存在则下载
|
||||
// _, _ = engine.GetLazyData("结婚登记表.db", false)
|
||||
|
||||
err := 民政局.db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
engine.OnFullMatch("娶群友", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
updatetime, err := 民政局.checkupdate(gid)
|
||||
switch {
|
||||
case err != nil:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
case time.Now().Format("2006/01/02") != updatetime:
|
||||
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
uid := ctx.Event.UserID
|
||||
targetinfo, status, err := 民政局.查户口(gid, uid)
|
||||
switch {
|
||||
case status == 2:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
case status != 3 && targetinfo.Target == 0: // 如果为单身贵族
|
||||
ctx.SendChain(message.Text("今天你是单身贵族噢"))
|
||||
return
|
||||
case status == 1: // 娶过别人
|
||||
ctx.SendChain(
|
||||
message.At(uid),
|
||||
message.Text("\n今天你已经娶过了,群老婆是"),
|
||||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(targetinfo.Target, 10)+"&s=640").Add("cache", 0),
|
||||
message.Text(
|
||||
"\n",
|
||||
"[", targetinfo.Targetname, "]",
|
||||
"(", targetinfo.Target, ")哒",
|
||||
),
|
||||
)
|
||||
return
|
||||
case status == 0: // 嫁给别人
|
||||
ctx.SendChain(
|
||||
message.At(uid),
|
||||
message.Text("\n今天你被娶了,群老公是"),
|
||||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(targetinfo.User, 10)+"&s=640").Add("cache", 0),
|
||||
message.Text(
|
||||
"\n",
|
||||
"[", targetinfo.Username, "]",
|
||||
"(", targetinfo.User, ")哒",
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
// 无缓存获取群员列表
|
||||
temp := ctx.GetThisGroupMemberListNoCache().Array()
|
||||
sort.SliceStable(temp, func(i, j int) bool {
|
||||
return temp[i].Get("last_sent_time").Int() < temp[j].Get("last_sent_time").Int()
|
||||
})
|
||||
temp = temp[math.Max(0, len(temp)-30):]
|
||||
// 将已经娶过的人剔除
|
||||
qqgrouplist := make([]int64, 0, len(temp))
|
||||
for k := 0; k < len(temp); k++ {
|
||||
usr := temp[k].Get("user_id").Int()
|
||||
_, status, _ := 民政局.查户口(gid, usr)
|
||||
if status != 3 {
|
||||
continue
|
||||
}
|
||||
qqgrouplist = append(qqgrouplist, usr)
|
||||
}
|
||||
// 没有人(只剩自己)的时候
|
||||
if len(qqgrouplist) == 1 {
|
||||
ctx.SendChain(message.Text("~群里没有ta人是单身了哦 明天再试试叭"))
|
||||
return
|
||||
}
|
||||
// 随机抽娶
|
||||
fiancee := qqgrouplist[rand.Intn(len(qqgrouplist))]
|
||||
if fiancee == uid { // 如果是自己
|
||||
ctx.SendChain(message.Text("呜...没娶到,你可以再尝试一次"))
|
||||
return
|
||||
}
|
||||
// 去民政局办证
|
||||
err = 民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
// 请大家吃席
|
||||
ctx.SendChain(
|
||||
message.At(uid),
|
||||
message.Text("今天你的群老婆是"),
|
||||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(fiancee, 10)+"&s=640").Add("cache", 0),
|
||||
message.Text(
|
||||
"\n",
|
||||
"[", ctx.CardOrNickName(fiancee), "]",
|
||||
"(", fiancee, ")哒",
|
||||
),
|
||||
)
|
||||
})
|
||||
// 单身技能
|
||||
engine.OnRegex(`^(娶|嫁)\[CQ:at,qq=(\d+)\]`, zero.OnlyGroup, getdb, checkdog).SetBlock(true).Limit(cdcheck, iscding).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
choice := ctx.State["regex_matched"].([]string)[1]
|
||||
fiancee, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
|
||||
uid := ctx.Event.UserID
|
||||
gid := ctx.Event.GroupID
|
||||
if uid == fiancee { // 如果是自己
|
||||
switch rand.Intn(3) {
|
||||
case 1:
|
||||
err := 民政局.登记(gid, uid, 0, "", "")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("今日获得成就:单身贵族"))
|
||||
default:
|
||||
ctx.SendChain(message.Text("今日获得成就:自恋狂"))
|
||||
}
|
||||
return
|
||||
}
|
||||
if rand.Intn(2) == 0 { // 二分之一的概率表白成功
|
||||
ctx.SendChain(message.Text(sendtext[1][rand.Intn(len(sendtext[1]))]))
|
||||
return
|
||||
}
|
||||
// 去民政局登记
|
||||
var choicetext string
|
||||
switch choice {
|
||||
case "娶":
|
||||
err := 民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
choicetext = "\n今天你的群老婆是"
|
||||
default:
|
||||
err := 民政局.登记(gid, fiancee, uid, ctx.CardOrNickName(fiancee), ctx.CardOrNickName(uid))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
choicetext = "\n今天你的群老公是"
|
||||
}
|
||||
// 请大家吃席
|
||||
ctx.SendChain(
|
||||
message.Text(sendtext[0][rand.Intn(len(sendtext[0]))]),
|
||||
message.At(uid),
|
||||
message.Text(choicetext),
|
||||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(fiancee, 10)+"&s=640").Add("cache", 0),
|
||||
message.Text(
|
||||
"\n",
|
||||
"[", ctx.CardOrNickName(fiancee), "]",
|
||||
"(", fiancee, ")哒",
|
||||
),
|
||||
)
|
||||
})
|
||||
// NTR技能
|
||||
engine.OnRegex(`^当(\[CQ:at,qq=(\d+)\]\s?|(\d+))的小三`, zero.OnlyGroup, getdb, checkcp).SetBlock(true).Limit(cdcheck, iscding).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
fid := ctx.State["regex_matched"].([]string)
|
||||
fiancee, _ := strconv.ParseInt(fid[2]+fid[3], 10, 64)
|
||||
uid := ctx.Event.UserID
|
||||
if fiancee == uid {
|
||||
ctx.SendChain(message.Text("今日获得成就:自我攻略"))
|
||||
return
|
||||
}
|
||||
if rand.Intn(10)/4 != 0 { // 十分之三的概率NTR成功
|
||||
ctx.SendChain(message.Text("失败了!可惜"))
|
||||
return
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
// 判断target是老公还是老婆
|
||||
var choicetext string
|
||||
_, gender, err := 民政局.查户口(gid, fiancee)
|
||||
switch gender {
|
||||
case 3:
|
||||
ctx.SendChain(message.Text("ta现在还是单身哦,快向ta表白吧!"))
|
||||
return
|
||||
case 2:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
case 1:
|
||||
// 和对象结婚登记
|
||||
err = 民政局.复婚(gid, fiancee, uid, ctx.CardOrNickName(fiancee), ctx.CardOrNickName(uid))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
choicetext = "老公"
|
||||
case 0:
|
||||
// 和对象结婚登记
|
||||
err = 民政局.复婚(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
choicetext = "老婆"
|
||||
default:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员"))
|
||||
return
|
||||
}
|
||||
// 输出结果
|
||||
ctx.SendChain(
|
||||
message.Text(sendtext[2][rand.Intn(len(sendtext[2]))]),
|
||||
message.At(uid),
|
||||
message.Text("今天你的群"+choicetext+"是"),
|
||||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(fiancee, 10)+"&s=640").Add("cache", 0),
|
||||
message.Text(
|
||||
"\n",
|
||||
"[", ctx.CardOrNickName(fiancee), "]",
|
||||
"(", fiancee, ")哒",
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnFullMatch("群老婆列表", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
updatetime, err := 民政局.checkupdate(gid)
|
||||
switch {
|
||||
case err != nil:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
case time.Now().Format("2006/01/02") != updatetime:
|
||||
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("今天还没有人结婚哦"))
|
||||
return
|
||||
}
|
||||
list, number, err := 民政局.花名册(gid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
if number <= 0 {
|
||||
ctx.SendChain(message.Text("今天还没有人结婚哦"))
|
||||
return
|
||||
}
|
||||
/***********设置图片的大小和底色***********/
|
||||
fontSize := 50.0
|
||||
if number < 10 {
|
||||
number = 10
|
||||
}
|
||||
canvas := gg.NewContext(1500, int(250+fontSize*float64(number)))
|
||||
canvas.SetRGB(1, 1, 1) // 白色
|
||||
canvas.Clear()
|
||||
/***********下载字体,可以注销掉***********/
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
/***********设置字体颜色为黑色***********/
|
||||
canvas.SetRGB(0, 0, 0)
|
||||
/***********设置字体大小,并获取字体高度用来定位***********/
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize*2); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
sl, h := canvas.MeasureString("群老婆列表")
|
||||
/***********绘制标题***********/
|
||||
canvas.DrawString("群老婆列表", (1500-sl)/2, 160-h) // 放置在中间位置
|
||||
canvas.DrawString("————————————————————", 0, 250-h)
|
||||
/***********设置字体大小,并获取字体高度用来定位***********/
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
_, h = canvas.MeasureString("焯")
|
||||
for i, info := range list {
|
||||
canvas.DrawString(slicename(info[0], canvas), 0, float64(260+50*i)-h)
|
||||
canvas.DrawString("("+info[1]+")", 350, float64(260+50*i)-h)
|
||||
canvas.DrawString("←→", 700, float64(260+50*i)-h)
|
||||
canvas.DrawString(slicename(info[2], canvas), 800, float64(260+50*i)-h)
|
||||
canvas.DrawString("("+info[3]+")", 1150, float64(260+50*i)-h)
|
||||
}
|
||||
data, cl := writer.ToBytes(canvas.Image())
|
||||
ctx.SendChain(message.ImageBytes(data))
|
||||
cl()
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"闹离婚", "办离婚"}, zero.OnlyGroup, getdb, checkfiancee).SetBlock(true).Limit(cdcheck, iscding2).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
uid := ctx.Event.UserID
|
||||
info, uidstatus, err := 民政局.查户口(gid, uid)
|
||||
switch uidstatus {
|
||||
case 2:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
case 1:
|
||||
if rand.Intn(10) != 1 { // 十分之一的概率成功
|
||||
ctx.SendChain(message.Text(sendtext[3][rand.Intn(len(sendtext[3]))]))
|
||||
return
|
||||
}
|
||||
err := 民政局.离婚休妻(gid, info.Target)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(sendtext[4][0]))
|
||||
case 0:
|
||||
if rand.Intn(10) != 0 { // 十分之一的概率成功
|
||||
ctx.SendChain(message.Text(sendtext[3][rand.Intn(len(sendtext[3]))]))
|
||||
return
|
||||
}
|
||||
err := 民政局.离婚休夫(gid, info.User)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(sendtext[4][1]))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^重置(所有|本群|/d+)?花名册$`, zero.SuperUserPermission, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
cmd := "ALL"
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "":
|
||||
if ctx.Event.GroupID == 0 {
|
||||
ctx.SendChain(message.Text("该功能只能在群组使用或者指定群组"))
|
||||
return
|
||||
}
|
||||
cmd = strconv.FormatInt(ctx.Event.GroupID, 10)
|
||||
case "所有":
|
||||
break
|
||||
case "本群":
|
||||
if ctx.Event.GroupID == 0 {
|
||||
ctx.SendChain(message.Text("该功能只能在群组使用或者指定群组"))
|
||||
return
|
||||
}
|
||||
cmd = strconv.FormatInt(ctx.Event.GroupID, 10)
|
||||
default:
|
||||
cmd = ctx.State["regex_matched"].([]string)[1]
|
||||
}
|
||||
err := 民政局.重置(cmd)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("重置成功"))
|
||||
})
|
||||
}
|
||||
|
||||
// 以群号和昵称为限制
|
||||
func cdcheck(ctx *zero.Ctx) *rate.Limiter {
|
||||
limitID := strconv.FormatInt(ctx.Event.GroupID, 10) + strconv.FormatInt(ctx.Event.UserID, 10)
|
||||
return skillCD.Load(limitID)
|
||||
}
|
||||
func iscding(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("你的技能现在正在CD中"))
|
||||
}
|
||||
|
||||
// 注入判断 是否为单身
|
||||
func checkdog(ctx *zero.Ctx) bool {
|
||||
// 得先判断用户是否存在才行在,再重置
|
||||
fiancee, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("额,你的target好像不存在?"))
|
||||
return false
|
||||
}
|
||||
// 判断是否需要重置
|
||||
gid := ctx.Event.GroupID
|
||||
updatetime, err := 民政局.checkupdate(gid)
|
||||
switch {
|
||||
case err != nil:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
case time.Now().Format("2006/01/02") != updatetime:
|
||||
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
}
|
||||
return true // 重置后也全是单身
|
||||
}
|
||||
uid := ctx.Event.UserID
|
||||
// 获取用户信息
|
||||
uidtarget, uidstatus, err1 := 民政局.查户口(gid, uid)
|
||||
fianceeinfo, fianceestatus, err2 := 民政局.查户口(gid, fiancee)
|
||||
switch {
|
||||
case uidstatus == 2 || fianceestatus == 2:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err1, "\n", err2))
|
||||
return false
|
||||
case uidstatus == 3 && fianceestatus == 3: // 必须是两个单身
|
||||
return true
|
||||
case uidtarget.Target == fiancee: // 如果本就是一块
|
||||
ctx.SendChain(message.Text("笨蛋~你们明明已经在一起了啊w"))
|
||||
return false
|
||||
case uidstatus != 3 && uidtarget.Target == 0: // 如果是单身贵族
|
||||
ctx.SendChain(message.Text("今天的你是单身贵族噢"))
|
||||
return false
|
||||
case uidstatus == 1: // 如果如为攻
|
||||
ctx.SendChain(message.Text("笨蛋~你家里还有个吃白饭的w"))
|
||||
return false
|
||||
case uidstatus == 0: // 如果为受
|
||||
ctx.SendChain(message.Text("该是0就是0,当0有什么不好"))
|
||||
return false
|
||||
case fianceestatus != 3 && fianceeinfo.Target == 0:
|
||||
ctx.SendChain(message.Text("今天的ta是单身贵族噢"))
|
||||
return false
|
||||
case fianceestatus == 1: // 如果如为攻
|
||||
ctx.SendChain(message.Text("他有别的女人了,你该放下了"))
|
||||
return false
|
||||
case fianceestatus == 0: // 如果为受
|
||||
ctx.SendChain(message.Text("这是一个纯爱的世界,拒绝NTR"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 注入判断 是否满足小三要求
|
||||
func checkcp(ctx *zero.Ctx) bool {
|
||||
gid := ctx.Event.GroupID
|
||||
updatetime, err := 民政局.checkupdate(gid)
|
||||
switch {
|
||||
case err != nil:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
case time.Now().Format("2006/01/02") != updatetime:
|
||||
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ta现在还是单身哦,快向ta表白吧!"))
|
||||
}
|
||||
return false // 重置后全是单身
|
||||
}
|
||||
// 检查target
|
||||
fid := ctx.State["regex_matched"].([]string)
|
||||
fiancee, err := strconv.ParseInt(fid[2]+fid[3], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("额,你的对象好像不存在?"))
|
||||
return false
|
||||
}
|
||||
// 检查用户是否登记过
|
||||
uid := ctx.Event.UserID
|
||||
userinfo, uidstatus, err := 民政局.查户口(gid, uid)
|
||||
switch {
|
||||
case uidstatus == 2:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
case userinfo.Target == fiancee: // 如果本就是一块
|
||||
ctx.SendChain(message.Text("笨蛋~你们明明已经在一起了啊w"))
|
||||
return false
|
||||
case uidstatus != 3 && userinfo.Target == 0: // 如果是单身贵族
|
||||
ctx.SendChain(message.Text("今天的你是单身贵族哦"))
|
||||
return false
|
||||
case fiancee == uid: // 自我攻略
|
||||
return true
|
||||
case uidstatus == 1: // 如果如为攻
|
||||
ctx.SendChain(message.Text("打灭,不给纳小妾!"))
|
||||
return false
|
||||
case uidstatus == 0: // 如果为受
|
||||
ctx.SendChain(message.Text("该是0就是0,当0有什么不好"))
|
||||
return false
|
||||
}
|
||||
fianceeinfo, fianceestatus, err := 民政局.查户口(gid, fiancee)
|
||||
switch {
|
||||
case fianceestatus == 2:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
case fianceestatus == 3:
|
||||
ctx.SendChain(message.Text("ta现在还是单身哦,快向ta表白吧!"))
|
||||
return false
|
||||
case fianceeinfo.Target == 0:
|
||||
ctx.SendChain(message.Text("今天的ta是单身贵族哦"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func checkfiancee(ctx *zero.Ctx) bool {
|
||||
gid := ctx.Event.GroupID
|
||||
updatetime, err := 民政局.checkupdate(gid)
|
||||
switch {
|
||||
case err != nil:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
case time.Now().Format("2006/01/02") != updatetime:
|
||||
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
}
|
||||
ctx.SendChain(message.Text("今天你还没有结婚哦"))
|
||||
return false
|
||||
}
|
||||
// 获取用户信息
|
||||
uid := ctx.Event.UserID
|
||||
_, uidstatus, err := 民政局.查户口(gid, uid)
|
||||
switch uidstatus {
|
||||
case 2:
|
||||
ctx.SendChain(message.Text("数据库发生问题力,请联系bot管理员\n[error]", err))
|
||||
return false
|
||||
case 3: // 如果是单身
|
||||
ctx.SendChain(message.Text("今天你还没有结婚哦"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func iscding2(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("打灭,禁止离婚 (你的技能正在CD中)"))
|
||||
}
|
||||
@@ -4,7 +4,13 @@ import (
|
||||
wr "github.com/mroth/weightedrand"
|
||||
)
|
||||
|
||||
type rate []struct {
|
||||
Name string `json:"name"`
|
||||
Weight float64 `json:"weight"`
|
||||
}
|
||||
|
||||
var (
|
||||
areac *wr.Chooser
|
||||
gender, _ = wr.NewChooser(
|
||||
wr.Choice{Item: "男孩子", Weight: 50707},
|
||||
wr.Choice{Item: "女孩子", Weight: 48292},
|
||||
16
plugin/reborn/load.go
Normal file
16
plugin/reborn/load.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package reborn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
)
|
||||
|
||||
// load 加载rate数据
|
||||
func load(area *rate, jsonfile string) error {
|
||||
data, err := file.GetLazyData(jsonfile, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, area)
|
||||
}
|
||||
55
plugin/reborn/main.go
Normal file
55
plugin/reborn/main.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Package reborn 投胎 来自 https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py
|
||||
package reborn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
wr "github.com/mroth/weightedrand"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("reborn", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "投胎\n- reborn",
|
||||
PublicDataFolder: "Reborn",
|
||||
})
|
||||
|
||||
en.OnFullMatch("reborn", ctxext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
datapath := en.DataFolder()
|
||||
jsonfile := datapath + "rate.json"
|
||||
area := make(rate, 226)
|
||||
err := load(&area, jsonfile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
choices := make([]wr.Choice, len(area))
|
||||
for i, a := range area {
|
||||
choices[i].Item = a.Name
|
||||
choices[i].Weight = uint(a.Weight * 1e9)
|
||||
}
|
||||
areac, err = wr.NewChooser(choices...)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Printf("[Reborn]读取%d个国家/地区", len(area))
|
||||
return true
|
||||
},
|
||||
)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if rand.Int31() > 1<<27 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("投胎成功!\n您出生在 %s, 是 %s。", randcoun(), randgen())))
|
||||
} else {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("投胎失败!\n您没能活到出生,祝您下次好运!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user