mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-06 23:30:20 +00:00
Compare commits
300 Commits
v1.5.2-bet
...
v1.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
278d7e0cf9 | ||
|
|
821f8d4949 | ||
|
|
436838d2f8 | ||
|
|
30301f1aba | ||
|
|
df1d71b9b2 | ||
|
|
0315718ab7 | ||
|
|
971c179227 | ||
|
|
1c0270fda0 | ||
|
|
5463945b6c | ||
|
|
8eb058fb26 | ||
|
|
33e5b0286f | ||
|
|
296fd60cd7 | ||
|
|
667c9fbcca | ||
|
|
3d8d0ad107 | ||
|
|
f35a89e401 | ||
|
|
c5c63d0b64 | ||
|
|
3e15754031 | ||
|
|
c1e37b293c | ||
|
|
8edc3f6de6 | ||
|
|
416cb3f2b8 | ||
|
|
8050f12d51 | ||
|
|
292fc311d6 | ||
|
|
28cb0491f7 | ||
|
|
1bad611018 | ||
|
|
d49224fd50 | ||
|
|
2324837052 | ||
|
|
35f8458d67 | ||
|
|
8a6b7f65c7 | ||
|
|
7b1d2b7eaa | ||
|
|
7ced79c6bb | ||
|
|
e224bf9252 | ||
|
|
2b1caafa16 | ||
|
|
c1702c5d5e | ||
|
|
5c8ead8b1d | ||
|
|
635eb9832a | ||
|
|
f1e49dc02e | ||
|
|
573c942a9d | ||
|
|
e8b61b39f0 | ||
|
|
ed26d31326 | ||
|
|
76dbf5a4b6 | ||
|
|
f1ea658c7d | ||
|
|
2964986ee5 | ||
|
|
52ef28cd6a | ||
|
|
df4c0438a2 | ||
|
|
864f92a728 | ||
|
|
6ea50cf8b7 | ||
|
|
d66dd9b7fa | ||
|
|
4a15326977 | ||
|
|
b4a1f93993 | ||
|
|
0c8dfb3f9c | ||
|
|
1aa11879dc | ||
|
|
14c596be1f | ||
|
|
309afecadd | ||
|
|
f465e78460 | ||
|
|
aa5c324592 | ||
|
|
1a0575af64 | ||
|
|
587d3967ef | ||
|
|
d693f988bb | ||
|
|
500dcaa9ed | ||
|
|
1376803b07 | ||
|
|
68386910c4 | ||
|
|
1734f1f7d4 | ||
|
|
86b87c2b4e | ||
|
|
e9eb4c5602 | ||
|
|
6474b36ccd | ||
|
|
107149892c | ||
|
|
f1dba97922 | ||
|
|
bc3c4303be | ||
|
|
f7a61ed0ee | ||
|
|
107b38e2f5 | ||
|
|
0d85fa04e1 | ||
|
|
1d8f5a7869 | ||
|
|
5e93368e57 | ||
|
|
56e931665e | ||
|
|
e5b2b369e3 | ||
|
|
58cf08fc39 | ||
|
|
c18f9b8b72 | ||
|
|
0df465e1c6 | ||
|
|
8b010321d5 | ||
|
|
e1591c44b6 | ||
|
|
cc26eb1332 | ||
|
|
366c7acb90 | ||
|
|
d8cb5206e8 | ||
|
|
90efebf02f | ||
|
|
960cd3ad8b | ||
|
|
09a3e807c9 | ||
|
|
fb2718b495 | ||
|
|
1550cb7fcc | ||
|
|
7b27bc8f7a | ||
|
|
54598fbf54 | ||
|
|
bb844eaa40 | ||
|
|
4ef6f584c9 | ||
|
|
861b3cc82f | ||
|
|
5226548cec | ||
|
|
d41ae01f01 | ||
|
|
e294059de4 | ||
|
|
84bc79eaa6 | ||
|
|
8f9a396821 | ||
|
|
6f96c389c4 | ||
|
|
c55e31ed6f | ||
|
|
f3a0813fed | ||
|
|
c1602c323d | ||
|
|
1bceaa52ff | ||
|
|
86296a28df | ||
|
|
fe9b5023f6 | ||
|
|
d68223f63d | ||
|
|
1c274d6eb8 | ||
|
|
0e52bbe0f7 | ||
|
|
a177448315 | ||
|
|
ca3ff1b522 | ||
|
|
41f0b11469 | ||
|
|
ba0e471a19 | ||
|
|
84115a7316 | ||
|
|
4dc837854b | ||
|
|
64f9e309ef | ||
|
|
67a1050df6 | ||
|
|
d85865825e | ||
|
|
2704d3e7d4 | ||
|
|
0944fc7854 | ||
|
|
611c275092 | ||
|
|
e3e991e6ab | ||
|
|
f2cebcf95a | ||
|
|
4aca16a393 | ||
|
|
891bbb96aa | ||
|
|
d60acd3a47 | ||
|
|
7dc6499127 | ||
|
|
f28e746652 | ||
|
|
3c905d9061 | ||
|
|
091d3170fc | ||
|
|
bdc4138d78 | ||
|
|
e231235ed1 | ||
|
|
1795b9196b | ||
|
|
d5d0563544 | ||
|
|
723b7a9857 | ||
|
|
6a0a16662e | ||
|
|
f82ba852ba | ||
|
|
180945670b | ||
|
|
56984ef7fb | ||
|
|
ac4de84188 | ||
|
|
591ad79201 | ||
|
|
2e51c9e9c3 | ||
|
|
ca89f01f7d | ||
|
|
5dfc118f64 | ||
|
|
2410a7b3ed | ||
|
|
7e11924b3f | ||
|
|
4f65900688 | ||
|
|
20821827b3 | ||
|
|
3dd10169e3 | ||
|
|
8cd60a84d5 | ||
|
|
03a2f4c331 | ||
|
|
cfc9b55fce | ||
|
|
fc99eb3e22 | ||
|
|
93625f9c4f | ||
|
|
b6ce9f7b2e | ||
|
|
20642b3776 | ||
|
|
16ab7c08f6 | ||
|
|
7bce7f28dc | ||
|
|
8c695c96d7 | ||
|
|
d4a057e21a | ||
|
|
f18c809355 | ||
|
|
0d9c8d9a43 | ||
|
|
76e7f81a6c | ||
|
|
faf00dfea7 | ||
|
|
39af90e63d | ||
|
|
36b09b8e94 | ||
|
|
7ec2b46d75 | ||
|
|
7cc5771a9a | ||
|
|
f96b5f8965 | ||
|
|
07e6f33b04 | ||
|
|
f1a33a1845 | ||
|
|
0a72566378 | ||
|
|
a029add486 | ||
|
|
778b8749ea | ||
|
|
7d5944fccf | ||
|
|
3e16a24ab5 | ||
|
|
ff682da3fe | ||
|
|
a0120485de | ||
|
|
0c8e9198ee | ||
|
|
40da2481cc | ||
|
|
a7ae56481b | ||
|
|
f550d58ad7 | ||
|
|
f488b75ac6 | ||
|
|
4308e386b4 | ||
|
|
df1c207d77 | ||
|
|
8ca71967b6 | ||
|
|
c99d09ea63 | ||
|
|
9ce65de698 | ||
|
|
cc7953c486 | ||
|
|
d50f330ccf | ||
|
|
36f2a23aa1 | ||
|
|
14b98d4006 | ||
|
|
d401136966 | ||
|
|
d0610b152f | ||
|
|
fa8428ae8b | ||
|
|
7d1a4b4005 | ||
|
|
19e3688499 | ||
|
|
b8da6f8cfd | ||
|
|
58631c5b19 | ||
|
|
e994768318 | ||
|
|
c304d72d77 | ||
|
|
a1f1016fb9 | ||
|
|
913f01d69f | ||
|
|
f56929c852 | ||
|
|
e9e0498b34 | ||
|
|
b6026ee76a | ||
|
|
8fdc358cc5 | ||
|
|
fef0ac6049 | ||
|
|
e144db9205 | ||
|
|
825a5a0d43 | ||
|
|
6dccfc862c | ||
|
|
771f93f9af | ||
|
|
7893fc9ebe | ||
|
|
9b4363dda8 | ||
|
|
257263bfa2 | ||
|
|
8f009bb4ee | ||
|
|
34a3cf82e7 | ||
|
|
cd927ec2c4 | ||
|
|
1266b2378a | ||
|
|
575d158d5a | ||
|
|
a008faf805 | ||
|
|
9a2081de0a | ||
|
|
9550b817c5 | ||
|
|
ee895e7dc4 | ||
|
|
7aa2996540 | ||
|
|
725aa5b180 | ||
|
|
f96f14052e | ||
|
|
adfa9f9e0f | ||
|
|
d8bc336006 | ||
|
|
b69bd3d640 | ||
|
|
5d9ac50106 | ||
|
|
df83ffc8b0 | ||
|
|
e49b568d6d | ||
|
|
8399e49072 | ||
|
|
d76a65ec07 | ||
|
|
ed7cef7566 | ||
|
|
3349ec7694 | ||
|
|
11f358bcbf | ||
|
|
82608d01bb | ||
|
|
a93f4f68b4 | ||
|
|
6f8c576a44 | ||
|
|
e75fc83412 | ||
|
|
2e538e3905 | ||
|
|
a69399fa58 | ||
|
|
3e94d27e6a | ||
|
|
20293b35f8 | ||
|
|
b768e48a74 | ||
|
|
6a64c1ffd6 | ||
|
|
3b1ad2250f | ||
|
|
83778afd51 | ||
|
|
cbbae11fcd | ||
|
|
11c01af9da | ||
|
|
7547b33f65 | ||
|
|
4305f589df | ||
|
|
c8684f74a8 | ||
|
|
7cdc92c142 | ||
|
|
a7ccf302f2 | ||
|
|
f4b41efc75 | ||
|
|
ac18d3df96 | ||
|
|
daff47d912 | ||
|
|
27d04cbae2 | ||
|
|
8eef7718ee | ||
|
|
fb4259b696 | ||
|
|
eb378ea45a | ||
|
|
02992271a1 | ||
|
|
72b11c2717 | ||
|
|
a55f28c006 | ||
|
|
9f37962d22 | ||
|
|
8d001122e2 | ||
|
|
960aa2231c | ||
|
|
e55a133f00 | ||
|
|
4075c92e53 | ||
|
|
743e5509a2 | ||
|
|
1c93611a16 | ||
|
|
df8a320fbe | ||
|
|
8e8464d727 | ||
|
|
356d1dfe4d | ||
|
|
d185de0f3d | ||
|
|
644a6cdcc2 | ||
|
|
85f5fb2d87 | ||
|
|
8674c14754 | ||
|
|
6c2fc1b4c2 | ||
|
|
5d94980e7c | ||
|
|
9bed71a99f | ||
|
|
6faa2b65e2 | ||
|
|
98812b103e | ||
|
|
deb655de36 | ||
|
|
8d1c18cb4a | ||
|
|
88824126f7 | ||
|
|
68a9ecf995 | ||
|
|
57404b2dcd | ||
|
|
29705c63c9 | ||
|
|
5a854d9715 | ||
|
|
eb1cbeae3f | ||
|
|
b6246cfee6 | ||
|
|
0619000f9a | ||
|
|
01361781c8 | ||
|
|
3c03a308b3 | ||
|
|
7895e48420 | ||
|
|
ba15713b99 | ||
|
|
bd98fa3aed |
BIN
.github/hua_nobg_512.gif
vendored
Normal file
BIN
.github/hua_nobg_512.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 187 KiB |
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
- name: Setup Go environment
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
- name: Cache downloaded module
|
||||
uses: actions/cache@master
|
||||
with:
|
||||
|
||||
2
.github/workflows/pull.yml
vendored
2
.github/workflows/pull.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@master
|
||||
|
||||
16
.github/workflows/push.yml
vendored
16
.github/workflows/push.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@master
|
||||
@@ -17,3 +17,17 @@ jobs:
|
||||
uses: golangci/golangci-lint-action@master
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Commit back
|
||||
if: ${{ !github.head_ref }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
git config --local user.name 'github-actions[bot]'
|
||||
git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
||||
git add --all
|
||||
git commit -m "🎨 改进代码样式"
|
||||
|
||||
- name: Create Pull Request
|
||||
if: ${{ !github.head_ref }}
|
||||
continue-on-error: true
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -16,12 +16,12 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: '1.19'
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@master
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
args: release --clean
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
BIN
.github/黒金.jpg
vendored
BIN
.github/黒金.jpg
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 191 KiB |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ go-zero*
|
||||
nohup.out
|
||||
zerobot
|
||||
ZeroBot-Plugin*
|
||||
*.syso
|
||||
|
||||
@@ -18,7 +18,6 @@ linters:
|
||||
fast: false
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- dogsled
|
||||
- errcheck
|
||||
@@ -39,13 +38,11 @@ linters:
|
||||
- nolintlint
|
||||
- rowserrcheck
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- whitespace
|
||||
- prealloc
|
||||
- predeclared
|
||||
@@ -62,7 +59,7 @@ run:
|
||||
tests: false
|
||||
skip-dirs:
|
||||
- order
|
||||
go: '1.19'
|
||||
go: '1.20'
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
@@ -76,4 +73,5 @@ issues:
|
||||
fix: true
|
||||
exclude-use-default: false
|
||||
exclude:
|
||||
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Seek|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
||||
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Seek|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
||||
- 'identifier ".*" contain non-ASCII character: U\+.*'
|
||||
|
||||
@@ -4,6 +4,8 @@ env:
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
- go install github.com/tc-hib/go-winres@latest
|
||||
- go-winres make
|
||||
builds:
|
||||
- id: nowin
|
||||
env:
|
||||
|
||||
145
LICENSE
145
LICENSE
@@ -1,5 +1,5 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
@@ -7,17 +7,15 @@
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
@@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
@@ -72,7 +60,7 @@ modification follow.
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
@@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
@@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
577
README.md
577
README.md
@@ -1,13 +1,15 @@
|
||||
<div align="center">
|
||||
<a href="https://crypko.ai/crypko/5k8HyUVTq5421/">
|
||||
<img src=".github/黒金.jpg" alt="看板娘" width = "400">
|
||||
</a><br>
|
||||
<img src=".github/hua_nobg_512.gif" alt="椛" width = "400">
|
||||
<br>
|
||||
|
||||
<h1>ZeroBot-Plugin</h1>
|
||||
|
||||
“椛椛是[真寻](https://github.com/HibiKier/zhenxun_bot)的好朋友!”
|
||||
|
||||
ZeroBot-Plugin 是 ZeroBot 的 实用插件合集<br><br>
|
||||
|
||||
|
||||
<img src="http://cmoe.azurewebsites.net/cmoe?name=ZeroBot-Plugin&theme=r34" /><br>
|
||||
<img src="https://counter.seku.su/cmoe?name=ZeroBot-Plugin&theme=r34" /><br>
|
||||
|
||||
[](https://github.com/Mrs4s/MiraiGo)
|
||||
[](https://github.com/takayama-lily/oicq)
|
||||
@@ -15,7 +17,7 @@
|
||||
|
||||
[](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin)
|
||||
[](https://t.me/zerobotplugin)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
|
||||
[](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
|
||||
[](https://t.me/zerobotplugin)
|
||||
@@ -23,9 +25,11 @@
|
||||
本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
|
||||
| 项目地址 | 平台 | 核心作者 |
|
||||
| --- | --- | --- |
|
||||
| [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s |
|
||||
| [yyuueexxiinngg/cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg |
|
||||
| [takayama-lily/onebot](https://github.com/takayama-lily/onebot) | [OICQ](https://github.com/takayama-lily/oicq) | takayama |
|
||||
| [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s |
|
||||
| [onebot-kotlin](https://github.com/yyuueexxiinngg/onebot-kotlin) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg |
|
||||
| [oicq/http-api](https://github.com/takayama-lily/oicq/tree/master/http-api) | [OICQ](https://github.com/takayama-lily/oicq) | takayama |
|
||||
|
||||
[](https://seladb.github.io/StarTrack-js/#/preload?r=FloatTech,ZeroBot-Plugin)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -33,19 +37,25 @@
|
||||
|
||||
> 如果您对开发插件感兴趣,欢迎加入[ZeroBot-Plugin-Playground](https://github.com/FloatTech/ZeroBot-Plugin-Playground)
|
||||
|
||||
> webui持续开发中, 欢迎加入[ZeroBot-Plugin-Webui](https://github.com/FloatTech/ZeroBot-Plugin-Webui)
|
||||
|
||||
## 命令行参数
|
||||
> `[]`代表是可选参数
|
||||
```bash
|
||||
zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [qq1 qq2 qq3 ...] [&]
|
||||
zerobot [-h] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w] [-c|s config.json] [-l latency] [-r ringlen] [-x max process time] [qq1 qq2 qq3 ...] [&]
|
||||
```
|
||||
- **-c config.json**: 从`config.json`加载`bot`配置
|
||||
- **-h**: 显示帮助
|
||||
- **-s config.json**: 保存现在`bot`配置到`config.json`
|
||||
- **-n nickname**: 设置默认昵称,默认为`椛椛`
|
||||
- **-t token**: 设置`AccessToken`,默认为空
|
||||
- **-u url**: 设置`Url`,默认为`ws://127.0.0.1:6700`
|
||||
- **-n nickname**: 设置默认昵称,默认为`椛椛`
|
||||
- ~~**-g url**~~(默认禁用): 设置`webui url`,默认为`127.0.0.1:3000`
|
||||
- **-p prefix**: 设置命令前缀,默认为`/`
|
||||
- **-d|w**: 开启 debug | warning 级别及以上日志输出
|
||||
- **-c config.json**: 从`config.json`加载`bot`配置
|
||||
- **-s config.json**: 保存现在`bot`配置到`config.json`
|
||||
- **-l latency**: 全局处理延时 (ms)
|
||||
- **-r ringlen**: 接收消息环缓冲区大小,`0`为不设缓冲,并发处理
|
||||
- **-x max process time**: 最大处理时间 (min)
|
||||
- **qqs**: superusers 的 qq 号
|
||||
- **&**: 驻留在后台,必须放在最后,仅`Linux`下有效
|
||||
|
||||
@@ -61,21 +71,29 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
|
||||
"アトリ"
|
||||
],
|
||||
"command_prefix": "/",
|
||||
"super_users": []
|
||||
"super_users": [],
|
||||
"ring_len": 4096,
|
||||
"latency": 233000000,
|
||||
"max_process_time": 240000000000
|
||||
},
|
||||
"ws": [
|
||||
{
|
||||
"Url": "ws://127.0.0.1:6700",
|
||||
"AccessToken": ""
|
||||
}
|
||||
]
|
||||
],
|
||||
"wss": null
|
||||
}
|
||||
```
|
||||
|
||||
## 功能
|
||||
> 在编译时,以下功能除插件控制外,均可通过注释`main.go`中的相应`import`而物理禁用,减小插件体积。
|
||||
|
||||
> 通过插件控制,还可动态管理某个功能在某个群的打开/关闭。
|
||||
> 插件的优先级为`import`的先后顺序
|
||||
|
||||
> 插件的优先级为`import`的先后顺序。
|
||||
|
||||
> `webui`默认禁用不编译,打开后会增加程序体积。
|
||||
|
||||
<details>
|
||||
<summary>插件控制</summary>
|
||||
@@ -92,6 +110,10 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
|
||||
|
||||
- [x] /禁用 xxx (在发送的群/用户禁用xxx)
|
||||
|
||||
- [x] /此处启用所有插件
|
||||
|
||||
- [x] /此处禁用所有插件
|
||||
|
||||
- [x] /全局启用 xxx
|
||||
|
||||
- [x] /全局禁用 xxx
|
||||
@@ -114,7 +136,13 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
|
||||
|
||||
- [x] /服务列表
|
||||
|
||||
- [x] /服务详情
|
||||
- [x] /设置服务列表显示行数 xx (默认值为 9, 该设置仅运行时有效, zbp 重启后重置)
|
||||
|
||||
- [x] (默认禁用) /设置webui用户名 zerobot 密码 123456
|
||||
|
||||
- [x] (默认禁用) /webui启动
|
||||
|
||||
- [x] (默认禁用) /webui停止
|
||||
|
||||
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
|
||||
|
||||
@@ -220,9 +248,15 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
|
||||
|
||||
- [x] [开启 | 关闭]gist加群自动审批
|
||||
|
||||
- [x] 对信息回复:[设置 | 取消]精华
|
||||
|
||||
- [x] 取消精华 [信息ID]
|
||||
|
||||
- [x] /精华列表
|
||||
|
||||
- [ ] 同意好友请求
|
||||
|
||||
- [ ] 撤回[@xxx] [xxx]
|
||||
- [x] 对信息回复: 撤回
|
||||
|
||||
- [ ] 警告[@xxx]
|
||||
|
||||
@@ -230,14 +264,6 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
|
||||
|
||||
- 设置欢迎语可选添加参数说明:{at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>词典匹配回复</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
|
||||
|
||||
- [x] @Bot 关键词
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>定时指令触发器</summary>
|
||||
@@ -360,6 +386,10 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 设置ai绘图配置 [server] [token]
|
||||
|
||||
- [x] 设置ai绘图撤回时间90s
|
||||
|
||||
- [x] 查看ai绘图配置
|
||||
|
||||
例: 设置ai绘图配置 http://91.216.169.75:5010 abc
|
||||
|
||||
参考服务器 http://91.217.139.190:5010, http://91.216.169.75:5010, http://185.80.202.180:5010
|
||||
@@ -382,6 +412,14 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 支付宝到账 1
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>触发者撤回时也自动撤回</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/autowithdraw"`
|
||||
|
||||
- [x] 撤回一条消息
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>base16384加解密</summary>
|
||||
@@ -398,11 +436,11 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>百度一下</summary>
|
||||
<summary>百科</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu"`
|
||||
|
||||
- [x] 百度下[xxx]
|
||||
- [x] 百度/百科/维基/wiki[xxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -521,7 +559,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] b站推送列表
|
||||
|
||||
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 10s"触发的指令)
|
||||
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 5m"触发的指令)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -533,14 +571,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 随机书评
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>打断复读</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat"`
|
||||
|
||||
- [x] (打断三次以上的复读)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>藏头诗</summary>
|
||||
@@ -593,6 +623,14 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 磕cp大老师 雪乃
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>今日早报</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dailynews"`
|
||||
|
||||
- [x] 今日早报
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>DeepDanbooru二次元图标签识别</summary>
|
||||
@@ -613,6 +651,48 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 教你一篇小作文[作文]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>程序员做饭指南</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dish"`
|
||||
|
||||
- [x] 怎么做 | 烹饪[菜名]
|
||||
|
||||
- [x] 随机菜谱 | 随便做点菜
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>多功能抽签</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/drawlots"`
|
||||
|
||||
支持图包文件夹和gif抽签
|
||||
|
||||
- [x] (刷新)抽签列表
|
||||
|
||||
- [x] 抽[签名]签
|
||||
|
||||
- [x] 看签[gif签名]
|
||||
|
||||
- [x] 加签[签名][gif图片]
|
||||
|
||||
- [x] 删签[gif签名]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>女装</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dress"`
|
||||
|
||||
- [x] 女装
|
||||
|
||||
- [x] 男装
|
||||
|
||||
- [x] 随机女装
|
||||
|
||||
- [x] 随机男装
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>漂流瓶</summary>
|
||||
@@ -623,32 +703,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] @Bot throw xxx (投递内容xxx,支持图片文字,投递内容需要大于10个字符或者带有图片)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>一群一天一夫一妻制群老婆</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife"`
|
||||
|
||||
- 引入好感度系统,好感度越高,自由恋爱成功率越高
|
||||
|
||||
- [x] 设置CD为xx小时
|
||||
|
||||
- [x] 允许/禁止自由恋爱
|
||||
|
||||
- [x] 允许/禁止牛头人
|
||||
|
||||
- [x] 娶群友
|
||||
|
||||
- [x] (娶|嫁)[@对方QQ]
|
||||
|
||||
- [x] 当[对方Q号|@对方QQ]的小三
|
||||
|
||||
- [x] 做媒 @攻方QQ @受方QQ
|
||||
|
||||
- [x] 群老婆列表
|
||||
|
||||
- [x] 重置花名册
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>合成emoji</summary>
|
||||
@@ -657,14 +711,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] [emoji][emoji]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>城市疫情查询</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/epidemic"`
|
||||
|
||||
- [x] xxx疫情
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>好友申请及群聊邀请事件处理</summary>
|
||||
@@ -683,7 +729,8 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/font"`
|
||||
|
||||
- [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx
|
||||
- [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|粗苹方体|未来荧黑体|Gugi体|八丸体|Impact体|猫啃体|苹方体])渲染(抖动)文字xxx
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>每日运势</summary>
|
||||
@@ -692,7 +739,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 运势 | 抽签
|
||||
|
||||
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘 东方归言录 奇异恩典 夏日口袋 ASoul]
|
||||
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘 东方归言录 奇异恩典 夏日口袋 ASoul Hololive]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -742,37 +789,32 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/guessmusic"`
|
||||
|
||||
- 猜歌插件(该插件依赖ffmpeg)
|
||||
|
||||
- 因为API不可抗因素,更改为了本地猜歌,但仍支持歌曲下载(VIP歌曲无法下载,黑胶可以)
|
||||
|
||||
猜歌插件(该插件依赖ffmpeg)
|
||||
|
||||
---------主 人 指 令---------
|
||||
- [x] 设置猜歌歌库路径 [绝对路径]
|
||||
|
||||
- [x] 猜歌[开启/关闭][歌单/歌词]自动下载
|
||||
|
||||
- 现只有歌词指令有效
|
||||
|
||||
- [ ] 添加歌单 [网易云歌单链接/ID] [歌单名称]
|
||||
|
||||
- [x] 下载歌曲 [歌曲名称/网易云歌曲ID] [歌单名称]
|
||||
|
||||
- [x] 删除歌单 [网易云歌单ID/歌单名称]
|
||||
|
||||
- 注:删除网易云歌单ID仅只是解除绑定,删除歌单名称是将本地数据全部删除!
|
||||
|
||||
- [x] [创建/删除]歌单 [歌单名称]
|
||||
- [x] 下载歌曲[歌曲名称/网易云歌曲ID]到[歌单名称]
|
||||
|
||||
-------管 理 员 指 令--------
|
||||
- [x] 设置猜歌默认歌单 [歌单名称]
|
||||
|
||||
- [x] 上传歌曲[群文件的音乐名]到[歌单名称]
|
||||
|
||||
------公 用 指 令------
|
||||
- [x] 歌单列表
|
||||
|
||||
- [x] [个人/团队]猜歌
|
||||
|
||||
- 注:默认歌库为歌单列表第一个,如果设置了默认歌单变为指定的歌单
|
||||
|
||||
- 可在“[个人/团队]猜歌指令”后面添加[-歌单名称]进行指定歌单猜歌
|
||||
|
||||
- 猜歌内容必须以[-]开头才会识别
|
||||
|
||||
- 本地歌曲命名规则为:\n歌名 - 歌手 - 其他(歌曲出处之类)
|
||||
|
||||
------插 件 扩 展------
|
||||
|
||||
- 本插件内置了[NeteaseCloudMusicApi](https://binaryify.github.io/NeteaseCloudMusicApi/#/)框架的一些功能
|
||||
- [x] 设置猜歌API帮助
|
||||
- [x] 设置猜歌API [API首页网址]
|
||||
- [x] 猜歌[开启/关闭][歌单/歌词]自动下载
|
||||
- [ ] 登录网易云
|
||||
- [x] 歌单信息 [网易云歌单链接/ID]
|
||||
- [x] [歌单名称]绑定网易云[网易云歌单链接/ID]
|
||||
- [x] 下载歌单[网易云歌单链接/ID]到[歌单名称]
|
||||
- [x] 解除绑定 [歌单名称]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -782,6 +824,16 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 来点黑丝/白丝/jk/巨乳/足控/网红
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>一言</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hitokoto"`
|
||||
|
||||
- [x] 一言[xxx]
|
||||
|
||||
- [x] 系列一言
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>炉石</summary>
|
||||
@@ -830,6 +882,16 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 更新[屌|弔|吊]图
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>兽语加密(嗷呜~)</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/jiami"`
|
||||
|
||||
- [x] 兽语加密xxx
|
||||
|
||||
- [x] 兽语解密xxx
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>小鸡词典</summary>
|
||||
@@ -860,6 +922,26 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 喝奶茶绝绝子 | 绝绝子吃饭
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>疯狂星期四</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/kfccrazythursday"`
|
||||
|
||||
- [x] 疯狂星期四
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>kokomi原神面板</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/kokomi"`
|
||||
|
||||
- [x] kokomi菜单
|
||||
|
||||
- [x] XX面板
|
||||
|
||||
- 注:本插件未并入主仓库,需自行安装(须源码方式运行才能添加插件),安装地址[kokomi-原神面板查询插件](https://github.com/lianhong2758/kokomi-plugin)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>lolicon</summary>
|
||||
@@ -878,6 +960,14 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
来份萝莉
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>MagicPrompt-Stable-Diffusion吟唱提示</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/magicprompt"`
|
||||
|
||||
- [x] 吟唱提示[xxxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>简易midi音乐制作</summary>
|
||||
@@ -910,6 +1000,8 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 让[수아|미미르|아린|연화|유화|선배]说(韩语)
|
||||
|
||||
- [x] 让[派蒙|空|荧|阿贝多|枫原万叶|温迪|八重神子|纳西妲|钟离|诺艾尔|凝光|托马|北斗|莫娜|荒泷一斗|提纳里|芭芭拉|艾尔海森|雷电将军|赛诺|琴|班尼特|五郎|神里绫华|迪希雅|夜兰|辛焱|安柏|宵宫|云堇|妮露|烟绯|鹿野院平藏|凯亚|达达利亚|迪卢克|可莉|早柚|香菱|重云|刻晴|久岐忍|珊瑚宫心海|迪奥娜|戴因斯雷布|魈|神里绫人|丽莎|优菈|凯瑟琳|雷泽|菲谢尔|九条裟罗|甘雨|行秋|胡桃|迪娜泽黛|柯莱|申鹤|砂糖|萍姥姥|奥兹|罗莎莉亚|式大将|哲平|坎蒂丝|托克|留云借风真君|昆钧|塞琉斯|多莉|大肉丸|莱依拉|散兵|拉赫曼|杜拉夫|阿守|玛乔丽|纳比尔|海芭夏|九条镰治|阿娜耶|阿晃|阿扎尔|七七|博士|白术|埃洛伊|大慈树王|女士|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|芽衣|雷之律者|阿波尼亚]说(中文)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>摸鱼</summary>
|
||||
@@ -1014,6 +1106,12 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 小说[xxx]
|
||||
|
||||
- 设置小说配置 zerobot 123456
|
||||
|
||||
- 下载小说30298
|
||||
|
||||
- 注: 建议去https://www.23qb.com/ 注册一个账号, 小说下载有积分限制
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>nsfw图片识别</summary>
|
||||
@@ -1034,6 +1132,74 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 解签
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>一群一天一夫一妻制群老婆</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife"`
|
||||
|
||||
- 引入好感度系统,好感度越高,自由恋爱成功率越高
|
||||
|
||||
- [x] 设置CD为xx小时
|
||||
|
||||
- [x] [允许|禁止]自由恋爱
|
||||
|
||||
- [x] [允许|禁止]牛头人
|
||||
|
||||
- [x] 娶群友
|
||||
|
||||
- [x] [娶|嫁][@对方QQ]
|
||||
|
||||
- [x] 当[对方Q号|@对方QQ]的小三
|
||||
|
||||
- [x] 做媒 @攻方QQ @受方QQ
|
||||
|
||||
- [x] 买礼物给[对方Q号|@对方QQ]
|
||||
|
||||
- [x] 群老婆列表
|
||||
|
||||
- [x] 查好感度[对方Q号|@对方QQ]
|
||||
|
||||
- [x] 好感度列表
|
||||
|
||||
- [x] 重置花名册
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>权重查询</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/quan"`
|
||||
|
||||
- 来看看大家的账号分吧~据说越高越不容易封号哦
|
||||
|
||||
- [x] 权重查询+@xxx
|
||||
|
||||
- [x] 权重查询+QQ号(为空时匹配触发者QQ)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>qq空间表白墙</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/qzone"`
|
||||
|
||||
- [x] 登录QQ空间 (Cookie过期很快, 要经常登录)
|
||||
|
||||
- [x] 发说说[xxx]
|
||||
|
||||
- [x] (匿名)发表白墙[xxx]
|
||||
|
||||
- [x] [ 同意 | 拒绝 ]表白墙 1,2,3 (最后一个参数是表白墙的序号数组, 用英文逗号连接)
|
||||
|
||||
- [x] 查看[ 等待 | 同意 | 拒绝 | 所有 ]表白墙 0 (最后一个参数是页码, 建议私聊审稿)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Real-CUGAN清晰术</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan"`
|
||||
|
||||
- [x] 清晰术(双重吟唱|三重吟唱|四重吟唱)(强力术式|中等术式|弱术式|不变式|原式)[图片]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>投胎</summary>
|
||||
@@ -1084,6 +1250,12 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 签到
|
||||
- [x] 获得签到背景[@xxx] | 获得签到背景
|
||||
- [x] 设置签到预设(0~3)
|
||||
- [x] 查看等级排名
|
||||
- 注:跨群排行
|
||||
- [x] 查看我的钱包
|
||||
- [x] 查看钱包排名
|
||||
- 注:本群排行,若群人数太多不建议使用该功能!!!
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -1111,10 +1283,26 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 卖萌[@xxx]
|
||||
|
||||
- [x] 抽老婆[@xxx]
|
||||
- [x] 今日老婆[@xxx]
|
||||
|
||||
- [x] 黄油角色[@xxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>steam</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/steam"`
|
||||
|
||||
- [x] steam[添加|删除]订阅xxxxx
|
||||
|
||||
- [x] steam查看订阅
|
||||
|
||||
- [x] steam绑定 api key xxxxxxx
|
||||
|
||||
- [x] 查看apikey
|
||||
|
||||
- [x] 拉取steam订阅 (使用job执行定时任务------记录在"@every 1m"触发的指令)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>抽塔罗牌</summary>
|
||||
@@ -1126,6 +1314,14 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
- [x] 解塔罗牌[牌名]
|
||||
- [x] [塔罗|大阿卡纳|小阿卡纳|混合]牌阵[圣三角|时间之流|四要素|五牌阵|吉普赛十字|马蹄|六芒星]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>舔狗日记</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou"`
|
||||
|
||||
- [x] 舔狗日记
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>搜番</summary>
|
||||
@@ -1134,20 +1330,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 搜番 | 搜索番剧[图片]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>猜单词</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle"`
|
||||
|
||||
- [x] 个人猜单词
|
||||
|
||||
- [x] 团队猜单词
|
||||
|
||||
- [x] 团队六阶猜单词
|
||||
|
||||
- [x] 团队七阶猜单词
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>翻译</summary>
|
||||
@@ -1156,6 +1338,14 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] >TL 你好
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>vits猫雷</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/vitsnyaru"`
|
||||
|
||||
- [x] 让猫雷说[xxxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>vtb语录</summary>
|
||||
@@ -1168,6 +1358,26 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 更新vtb
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>vtb点歌</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbmusic"`
|
||||
|
||||
- [x] vtb点歌
|
||||
|
||||
- [x] vtb随机点歌
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>钱包</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet"`
|
||||
|
||||
- [x] 查看我的钱包
|
||||
|
||||
- [x] 查看钱包排名
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>网易云音乐热评</summary>
|
||||
@@ -1176,6 +1386,47 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 来份网易云热评
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>据意查句</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes"`
|
||||
|
||||
- [x] 据意查句 大海
|
||||
|
||||
- [x] 登录据意查句
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>星际战甲</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi"`
|
||||
|
||||
- [x] wf时间同步
|
||||
|
||||
- [x] [金星|地球|火卫二]平原状态
|
||||
|
||||
- [x] .wm [物品名称]
|
||||
|
||||
- [x] 仲裁
|
||||
|
||||
- [x] 警报
|
||||
|
||||
- [x] 每日特惠
|
||||
</details>
|
||||
<details>
|
||||
<summary>天气/拼音查询-名言</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenben"`
|
||||
|
||||
- [x] xx天气
|
||||
|
||||
- [x] xx拼音
|
||||
|
||||
- [x] 每日情话/一言/鸡汤
|
||||
|
||||
- [x] 绕口令
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>百度文心AI</summary>
|
||||
@@ -1220,6 +1471,59 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- 椛椛帮我画几张金凤凰,背景绚烂,高饱和,古风,仙境,高清,4K,古风的油画方图
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>抽老婆</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife"`
|
||||
|
||||
- [x] 抽老婆
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>聊天热词</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count"`
|
||||
|
||||
- [x] 热词 [群号] [消息数目]|热词 123456 1000
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>猜单词</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle"`
|
||||
|
||||
- [x] 个人猜单词
|
||||
|
||||
- [x] 团队猜单词
|
||||
|
||||
- [x] 团队六阶猜单词
|
||||
|
||||
- [x] 团队七阶猜单词
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>一些游戏王插件</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo"`
|
||||
|
||||
##### 白鸽API卡查
|
||||
|
||||
###### `"github.com/FloatTech/ZeroBot-Plugin/plugin/ygo/ygocdb.go"`
|
||||
- [x] /ydp [xxx]
|
||||
- [x] /yds [xxx]
|
||||
- [x] /ydb [xxx]
|
||||
- 注:[xxx]为搜索内容;p:返回一张图片;s:返回一张效果描述;b:高级搜索
|
||||
|
||||
##### 集换社卡价查询
|
||||
|
||||
###### `"github.com/FloatTech/ZeroBot-Plugin/plugin/ygo/ygotrade.go"`
|
||||
- [x] 查卡价 [卡名]
|
||||
- [x] 查卡价 [卡名] -r [稀有度 稀有度 ...]
|
||||
- [x] 查卡店 [卡名]
|
||||
- [x] 查卡店 [卡名] -r [稀有度]
|
||||
- 注:卡店只支持单个稀有度查询
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>月幕galgame图</summary>
|
||||
@@ -1236,22 +1540,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 更新gal
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>舔狗日记</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou"`
|
||||
|
||||
- [x] 舔狗日记
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>聊天热词</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count"`
|
||||
|
||||
- [x] 热词 [群号] [消息数目]|热词 123456 1000
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>鬼东西</summary>
|
||||
@@ -1285,8 +1573,29 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] @Bot 任意文本(任意一句话回复)
|
||||
|
||||
- [x] 设置回复模式[青云客 | 小爱]
|
||||
- [x] 设置回复模式[青云客 | 小爱 | ChatGPT]
|
||||
|
||||
- [x] 设置 ChatGPT api key xxx
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>词典匹配回复</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
|
||||
|
||||
- [x] 切换[kimo|傲娇|可爱]词库
|
||||
- [x] 设置词库触发概率0.x (0<x<9)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>打断复读</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat"`
|
||||
|
||||
- [x] (打断三次以上的复读)
|
||||
|
||||
</details>
|
||||
|
||||
## 三种使用方法,推荐第一种
|
||||
|
||||
### 1. 使用稳定版/测试版 (推荐)
|
||||
@@ -1349,3 +1658,9 @@ GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags "-s -w"
|
||||
|
||||
- [ZeroBot](https://github.com/wdvxdr1123/ZeroBot)
|
||||
- [ATRI](https://github.com/Kyomotoi/ATRI)
|
||||
|
||||
同时感谢以下开发者对 ZeroBot-Plugin 作出的贡献:
|
||||
|
||||
<a href="https://github.com/FloatTech/ZeroBot-Plugin/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=FloatTech/ZeroBot-Plugin&max=1000" />
|
||||
</a>
|
||||
|
||||
14
console/console_ansi.go
Normal file
14
console/console_ansi.go
Normal file
@@ -0,0 +1,14 @@
|
||||
//go:build !windows
|
||||
|
||||
// Package console sets console's behavior on init
|
||||
package console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fmt.Print("\033]0;ZeroBot-Blugin " + banner.Version + " " + banner.Copyright + "\007")
|
||||
}
|
||||
144
console/console_windows.go
Normal file
144
console/console_windows.go
Normal file
@@ -0,0 +1,144 @@
|
||||
// Package console sets console's behavior on init
|
||||
package console
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:linkname modkernel32 golang.org/x/sys/windows.modkernel32
|
||||
modkernel32 *windows.LazyDLL
|
||||
procSetConsoleTitle = modkernel32.NewProc("SetConsoleTitleW")
|
||||
)
|
||||
|
||||
//go:linkname errnoErr golang.org/x/sys/windows.errnoErr
|
||||
func errnoErr(e syscall.Errno) error
|
||||
|
||||
func setConsoleTitle(title string) (err error) {
|
||||
var p0 *uint16
|
||||
p0, err = syscall.UTF16PtrFromString(title)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall(procSetConsoleTitle.Addr(), 1, uintptr(unsafe.Pointer(p0)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func init() {
|
||||
stdin := windows.Handle(os.Stdin.Fd())
|
||||
|
||||
var mode uint32
|
||||
err := windows.GetConsoleMode(stdin, &mode)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode &^= windows.ENABLE_QUICK_EDIT_MODE // 禁用快速编辑模式
|
||||
mode |= windows.ENABLE_EXTENDED_FLAGS // 启用扩展标志
|
||||
|
||||
mode &^= windows.ENABLE_MOUSE_INPUT // 禁用鼠标输入
|
||||
mode |= windows.ENABLE_PROCESSED_INPUT // 启用控制输入
|
||||
|
||||
mode &^= windows.ENABLE_INSERT_MODE // 禁用插入模式
|
||||
mode |= windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT // 启用输入回显&逐行输入
|
||||
|
||||
mode &^= windows.ENABLE_WINDOW_INPUT // 禁用窗口输入
|
||||
mode &^= windows.ENABLE_VIRTUAL_TERMINAL_INPUT // 禁用虚拟终端输入
|
||||
|
||||
err = windows.SetConsoleMode(stdin, mode)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stdout := windows.Handle(os.Stdout.Fd())
|
||||
err = windows.GetConsoleMode(stdout, &mode)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING // 启用虚拟终端处理
|
||||
mode |= windows.ENABLE_PROCESSED_OUTPUT // 启用处理后的输出
|
||||
|
||||
err = windows.SetConsoleMode(stdout, mode)
|
||||
// windows 带颜色 log 自定义格式
|
||||
logrus.SetFormatter(&logFormat{hasColor: err == nil})
|
||||
if err != nil {
|
||||
logrus.Warnln("VT100设置失败, 将以无色模式输出")
|
||||
}
|
||||
|
||||
err = setConsoleTitle("ZeroBot-Blugin " + banner.Version + " " + banner.Copyright)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
colorCodePanic = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeFatal = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeError = "\x1b[31m" // color.Style{color.Red}.String()
|
||||
colorCodeWarn = "\x1b[33m" // color.Style{color.Yellow}.String()
|
||||
colorCodeInfo = "\x1b[37m" // color.Style{color.White}.String()
|
||||
colorCodeDebug = "\x1b[32m" // color.Style{color.Green}.String()
|
||||
colorCodeTrace = "\x1b[36m" // color.Style{color.Cyan}.String()
|
||||
colorReset = "\x1b[0m"
|
||||
)
|
||||
|
||||
// logFormat specialize for zbp
|
||||
type logFormat struct {
|
||||
hasColor bool
|
||||
}
|
||||
|
||||
// Format implements logrus.Formatter
|
||||
func (f logFormat) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
buf.WriteByte('[')
|
||||
if f.hasColor {
|
||||
buf.WriteString(getLogLevelColorCode(entry.Level))
|
||||
}
|
||||
buf.WriteString(strings.ToUpper(entry.Level.String()))
|
||||
if f.hasColor {
|
||||
buf.WriteString(colorReset)
|
||||
}
|
||||
buf.WriteString("] ")
|
||||
buf.WriteString(entry.Message)
|
||||
buf.WriteString(" \n")
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// getLogLevelColorCode 获取日志等级对应色彩code
|
||||
func getLogLevelColorCode(level logrus.Level) string {
|
||||
switch level {
|
||||
case logrus.PanicLevel:
|
||||
return colorCodePanic
|
||||
case logrus.FatalLevel:
|
||||
return colorCodeFatal
|
||||
case logrus.ErrorLevel:
|
||||
return colorCodeError
|
||||
case logrus.WarnLevel:
|
||||
return colorCodeWarn
|
||||
case logrus.InfoLevel:
|
||||
return colorCodeInfo
|
||||
case logrus.DebugLevel:
|
||||
return colorCodeDebug
|
||||
case logrus.TraceLevel:
|
||||
return colorCodeTrace
|
||||
|
||||
default:
|
||||
return colorCodeInfo
|
||||
}
|
||||
}
|
||||
2
data
2
data
Submodule data updated: 7bc1828db5...d0342c3806
94
go.mod
94
go.mod
@@ -1,88 +1,100 @@
|
||||
module github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
go 1.19
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/Baidu-AIP/golang-sdk v1.1.1
|
||||
github.com/Coloured-glaze/gg v1.3.4
|
||||
github.com/FloatTech/AnimeAPI v1.5.2-0.20221028033300-a9293e7eecb8
|
||||
github.com/FloatTech/floatbox v0.0.0-20221028033104-a243fca6f2a3
|
||||
github.com/FloatTech/sqlite v0.5.0
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230409024643-f25135dee0da
|
||||
github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944
|
||||
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9
|
||||
github.com/FloatTech/sqlite v1.6.2
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
|
||||
github.com/FloatTech/zbpctrl v1.5.2-0.20221011153929-4834c6911511
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20221028033223-1fdfaf978116
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230411055601-7cdff751dd67
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230411114057-4c71136244b2
|
||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
|
||||
github.com/antchfx/htmlquery v1.2.5
|
||||
github.com/corona10/goimagehash v1.1.0
|
||||
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/fumiama/ahsai v0.1.0
|
||||
github.com/fumiama/cron v1.3.0
|
||||
github.com/fumiama/go-base16384 v1.6.1
|
||||
github.com/fumiama/go-registry v0.2.1
|
||||
github.com/fumiama/go-base16384 v1.6.4
|
||||
github.com/fumiama/go-registry v0.2.6
|
||||
github.com/fumiama/gotracemoe v0.0.3
|
||||
github.com/fumiama/sqlite3 v1.14.6
|
||||
github.com/fumiama/unibase2n v0.0.0-20221003115227-e7db987de949
|
||||
github.com/fumiama/imgsz v0.0.2
|
||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565
|
||||
github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/jozsefsallai/gophersauce v1.0.1
|
||||
github.com/lucas-clemente/quic-go v0.29.0
|
||||
github.com/mroth/weightedrand v0.4.1
|
||||
github.com/lithammer/fuzzysearch v1.1.5
|
||||
github.com/mroth/weightedrand v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkumza/numcn v1.0.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.8
|
||||
github.com/quic-go/quic-go v0.32.0
|
||||
github.com/shirou/gopsutil/v3 v3.23.1
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/tidwall/gjson v1.14.3
|
||||
github.com/tidwall/gjson v1.14.4
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20221011153413-16c9a77ce4f0
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.11
|
||||
gitlab.com/gomidi/midi/v2 v2.0.25
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
|
||||
golang.org/x/image v0.3.0
|
||||
golang.org/x/sys v0.4.0
|
||||
golang.org/x/text v0.6.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
|
||||
github.com/antchfx/xpath v1.2.1 // indirect
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
||||
github.com/faiface/beep v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/fumiama/go-simple-protobuf v0.1.0 // indirect
|
||||
github.com/fumiama/gofastTEA v0.0.10 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hajimehoshi/oto v0.7.1 // indirect
|
||||
github.com/jfreymuth/oggvorbis v1.0.1 // indirect
|
||||
github.com/jfreymuth/vorbis v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // 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-18 v0.1.2 // indirect
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // 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/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pkumza/numcn v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 // 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.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741 // indirect
|
||||
golang.org/x/crypto v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 // indirect
|
||||
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
modernc.org/libc v1.19.0 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/net v0.4.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
modernc.org/libc v1.21.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.4.0 // indirect
|
||||
modernc.org/sqlite v1.20.0 // indirect
|
||||
)
|
||||
|
||||
replace modernc.org/sqlite => github.com/fumiama/sqlite3 v1.20.0-with-win386
|
||||
|
||||
replace github.com/remyoudompheng/bigfft => github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b
|
||||
|
||||
373
go.sum
373
go.sum
@@ -1,69 +1,81 @@
|
||||
github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhvrx4cw=
|
||||
github.com/Baidu-AIP/golang-sdk v1.1.1/go.mod h1:bXnGw7xPeKt8aF7UCELKrV6UZ/46spItONK1RQBQj1Y=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Coloured-glaze/gg v1.3.4 h1:l31zIF/HaVwkzjrj+A56RGQoSKyKuR1IWtIrqXGFStI=
|
||||
github.com/Coloured-glaze/gg v1.3.4/go.mod h1:Ih5NLNNDHOy3RJbB0EPqGTreIzq/H02TGThIagh8HJg=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/FloatTech/AnimeAPI v1.5.2-0.20221028033300-a9293e7eecb8 h1:W+Gb+NGv6RJZI4BSJHHADzYC9YeDfftFGphP8aMUvbg=
|
||||
github.com/FloatTech/AnimeAPI v1.5.2-0.20221028033300-a9293e7eecb8/go.mod h1:2RjLcJ67OxRebKTrxBKy4P/8wPdcVhci8a/HALVUAQQ=
|
||||
github.com/FloatTech/floatbox v0.0.0-20221028033104-a243fca6f2a3 h1:yiq5kEr51FTfz7xxDY+xjbcdgDWyvZ6U93cf1xSsGs4=
|
||||
github.com/FloatTech/floatbox v0.0.0-20221028033104-a243fca6f2a3/go.mod h1:GVbLqexg8XJGuZs2zBZHO7jswCAPkZ9M/IKBYD0I/L0=
|
||||
github.com/FloatTech/sqlite v0.5.0 h1:U7J5Omc534PqmH6csfu+ypCo3DS8L91l5lTsxUu3b/U=
|
||||
github.com/FloatTech/sqlite v0.5.0/go.mod h1:i33d92OtR8jcp5fBUvQtospf27+MkfUxnGwnZ95E/dA=
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230409024643-f25135dee0da h1:QyH0zpWt3YspNNfZ+5f8+QStvtmxrzld/DoocKjF+rc=
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230409024643-f25135dee0da/go.mod h1:UnCPjtpIzpNBZ02yeGYp+oYVxgoi5aF2yAK2bkOVxtI=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944 h1:/eQoMa6Aj3coF5F7yhzZe1+SzX6SItul7MW8//pl18o=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944/go.mod h1:FwQm6wk+b4wuW54KCKn3zccMX47Q5apnHD/Yakzv0fI=
|
||||
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08 h1:dPLeoiTVSBlgls+66EB/UJ2e38BaASmBN5nANaycSBU=
|
||||
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef h1:CJbK/2FRwPuZpeb6M4sWK2d7oXDnBEGhpkQuQrgc91A=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 h1:hffajvmQFfP68U6wUwHemPuuwCUoss+SEFfoLYwbGwE=
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9/go.mod h1:NBFPhWae4hqVMeG8ELBBnUQkKce3nDjkljVn6PdiUNs=
|
||||
github.com/FloatTech/sqlite v1.6.2 h1:FytbExjpvYalZxxITtmSenHiPGLPUvlz47LY/P0SCCw=
|
||||
github.com/FloatTech/sqlite v1.6.2/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||
github.com/FloatTech/zbpctrl v1.5.2-0.20221011153929-4834c6911511 h1:i2+JjTRR7gW8n1KivMKj3NEsCEEllYp8jneeOyg1Lz0=
|
||||
github.com/FloatTech/zbpctrl v1.5.2-0.20221011153929-4834c6911511/go.mod h1:TC5RkmSwKJvkDV+7vlTpcY+rnviB5gBq6JNOKnfZXHc=
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20221028033223-1fdfaf978116 h1:ZHAMbLbSkirxV3/Z7FKaiF9TiMRCavCYsIbYDIYbSGc=
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20221028033223-1fdfaf978116/go.mod h1:nxTBx0YX8Ewq8oef2em4aJ5RH/5ZiG4PizK8v/csm7w=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230411055601-7cdff751dd67 h1:KGfXWryE3VGFDC8Z6661d/7xm8oLNPpFB5ODb7DqYJc=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230411055601-7cdff751dd67/go.mod h1:gkGC1C1eEUd/Ld/ja68zas5j2ZktIZCdnj2FMaM+Au0=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230411114057-4c71136244b2 h1:Dx64RjcbxhsOHinykOPAlYqvPd9tE375IQrWqlNmDXs=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230411114057-4c71136244b2/go.mod h1:m3IW5z7vLMNgNtVNUfcYtOF1du6PnjckifdRK2hVjA0=
|
||||
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/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
|
||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5 h1:bBmmB7he0iVN4m5mcehfheeRUEer/Avo4ujnxI3uCqs=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5/go.mod h1:0UcFaCkhp6vZw6l5Dpq0Dp673CoF9GdvA8lTfst0GiU=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
|
||||
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3 h1:qshMBFxVjYjzI+kwvWvgoByF3uMCvnJiaK8KslWAbr8=
|
||||
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3/go.mod h1:M9fx6rAdHSYLKxXPgUXGgblb586CA7ceNrpu4DEc2No=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
|
||||
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/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/faiface/beep v1.1.0 h1:A2gWP6xf5Rh7RG/p9/VAW2jRSDEGQm5sbOb38sf5d4c=
|
||||
github.com/faiface/beep v1.1.0/go.mod h1:6I8p6kK2q4opL/eWb+kAkk38ehnTunWeToJB+s51sT4=
|
||||
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/ahsai v0.1.0 h1:LXD61Kaj6kJHa3AEGsLIfKNzcgaVxg7JB72OR4yNNZ4=
|
||||
github.com/fumiama/ahsai v0.1.0/go.mod h1:fFeNnqgo44i8FIaguK659aQryuZeFy+4klYLQu/rfdk=
|
||||
github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b h1:Zt3pFQditAdWTHCOVkiloc9ZauBoWrb37guFV4iIRvE=
|
||||
github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
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.6.1 h1:4yb4JgmBJDnQtq3XGXXdLrVwEnRpjhMUt4eAcsNeA30=
|
||||
github.com/fumiama/go-base16384 v1.6.1/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||
github.com/fumiama/go-registry v0.2.1 h1:PCu4d1OIYkLmoSufyxov3QXRul4lXrAfXfK1pVS2wrQ=
|
||||
github.com/fumiama/go-registry v0.2.1/go.mod h1:GP45kejHuDLFxcWdksrt75r5rHBqYwtfeUl3JzGWxfQ=
|
||||
github.com/fumiama/go-base16384 v1.6.4 h1:rYDRwD/th2cG4U7QLokpzmST1cCxZGXtHmolOUePt5o=
|
||||
github.com/fumiama/go-base16384 v1.6.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||
github.com/fumiama/go-registry v0.2.6 h1:+vEeBUwa1+GC87ujW3Km42fi8O/H7QcpVJWu1iuGNh0=
|
||||
github.com/fumiama/go-registry v0.2.6/go.mod h1:HjYagPZXzR2xCCxaSQerqX7JRzC0yiv2kslDdBiTq/g=
|
||||
github.com/fumiama/go-simple-protobuf v0.1.0 h1:rLzJgNqB6LHNDVMl81yyNt6ZKziWtVfu+ioF0edlEVw=
|
||||
github.com/fumiama/go-simple-protobuf v0.1.0/go.mod h1:5yYNapXq1tQMOZg9bOIVhQlZk9pQqpuFIO4DZLbsdy4=
|
||||
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/fumiama/sqlite3 v1.14.6 h1:+e+iygyiDXQJVi7xeXIviBvR7hAc5y20WA9hRwfKn10=
|
||||
github.com/fumiama/sqlite3 v1.14.6/go.mod h1:Xx9a2/OtHuy9pBjow0N+bE/RhNeZ7zZz5xh25vqbA5A=
|
||||
github.com/fumiama/unibase2n v0.0.0-20221003115227-e7db987de949 h1:VAzR8aoS2SCEBmRF9rqCPyXgXoP8mZ1viNL4mLWUg0Q=
|
||||
github.com/fumiama/unibase2n v0.0.0-20221003115227-e7db987de949/go.mod h1:lEaZsT4FRSqcjnQ5q8y+mkenkzR/r1D3BJmfdp0vqDg=
|
||||
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
|
||||
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
|
||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 h1:sQuR2+N5HurnvsZhiKdEg+Ig354TaqgCQRxd/0KgIOQ=
|
||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565/go.mod h1:UUEvyLTJ7yoOA/viKG4wEis4ERydM7+Ny6gZUWgkS80=
|
||||
github.com/fumiama/sqlite3 v1.20.0-with-win386 h1:ZR1AXGBEtkfq9GAXehOVcwn+aaCG8itrkgEsz4ggx5k=
|
||||
github.com/fumiama/sqlite3 v1.20.0-with-win386/go.mod h1:Os58MHwYCcYZCy2PGChBrQtBAw5/LS1ZZOkfc+C/I7s=
|
||||
github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430 h1:XL4SnagpaVHYybnnj6whQxmt8Ps9/kaG6sCNn4X1GGA=
|
||||
github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430/go.mod h1:lEaZsT4FRSqcjnQ5q8y+mkenkzR/r1D3BJmfdp0vqDg=
|
||||
github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8=
|
||||
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
@@ -82,32 +94,24 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZ
|
||||
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/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/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.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 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
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/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
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/hajimehoshi/go-mp3 v0.3.0/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||
github.com/hajimehoshi/oto v0.7.1 h1:I7maFPz5MBCwiutOrz++DLdbr4rTzBsbBuV2VpgU9kk=
|
||||
github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
|
||||
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
|
||||
github.com/jfreymuth/oggvorbis v1.0.1 h1:NT0eXBgE2WHzu6RT/6zcb2H10Kxj6Fm3PccT0LE6bqw=
|
||||
@@ -122,21 +126,20 @@ 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/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
|
||||
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
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/lucas-clemente/quic-go v0.29.0 h1:Vw0mGTfmWqGzh4jx/kMymsIkFK6rErFVmg+t9RLrnZE=
|
||||
github.com/lucas-clemente/quic-go v0.29.0/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE=
|
||||
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
|
||||
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
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/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-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
@@ -144,21 +147,16 @@ github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU=
|
||||
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA=
|
||||
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/mroth/weightedrand v1.0.0 h1:V8JeHChvl2MP1sAoXq4brElOcza+jxLkRuwvtQu8L3E=
|
||||
github.com/mroth/weightedrand v1.0.0/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||
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.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.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/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -168,35 +166,47 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/shirou/gopsutil/v3 v3.22.8 h1:a4s3hXogo5mE2PfdfJIonDbstO/P+9JszdfhAHSzD9Y=
|
||||
github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
|
||||
github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4=
|
||||
github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
|
||||
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
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/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
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.20221011153413-16c9a77ce4f0 h1:IKWX0c7b3URoFDt5ezD6wa0AZIQ0EY0GbPVhYfuzXug=
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20221011153413-16c9a77ce4f0/go.mod h1:shG/ruauisKaVcov4amrFJtkeDl7nl+Q00IXB2PqFsc=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.11 h1:44Wr6CsCtWlFensK5IhuVCWkosdRw0rA8SygVD8DgoI=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.11/go.mod h1:y29UIOy0RD3P+0meDNIWRhcJF3jtWPN9xP9hgt/AJAU=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
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.25 h1:dkzVBqbaFHjyWwP71MrQNX7IeRUIDonddmHbPpO/Ucg=
|
||||
@@ -206,22 +216,22 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||
golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741 h1:b7y8iQCnzOE0NhgpMj2yHw17Us+lhXxFbdzKlTpqm5I=
|
||||
golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 h1:tLxpBz7qD8qFkRDC159unetNbxKp4zeqsqw2rLwvdxc=
|
||||
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
|
||||
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/image v0.3.0 h1:HTDXbdK9bjfSWkPzDJIw89W8CAtfFGduujWs33NLLsg=
|
||||
golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f h1:kgfVkAEEQXXQ0qc6dH7n6y37NAYmTFmz0YRwrRjgxKw=
|
||||
@@ -229,12 +239,11 @@ golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -242,198 +251,64 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-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-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-20191204072324-ce4227a45e2e/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-20210510120138-977fb7262007/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-20220111092808-5a964db01320/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
|
||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/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.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf 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 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
lukechampine.com/uint128 v1.1.1/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=
|
||||
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
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/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
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=
|
||||
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
|
||||
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
|
||||
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
|
||||
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
|
||||
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
|
||||
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
|
||||
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
|
||||
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
|
||||
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
|
||||
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
|
||||
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
|
||||
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
|
||||
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
|
||||
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
|
||||
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
|
||||
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
|
||||
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
|
||||
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
|
||||
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
|
||||
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
|
||||
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
|
||||
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
|
||||
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
|
||||
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
|
||||
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
|
||||
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
|
||||
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
|
||||
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
|
||||
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
|
||||
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
|
||||
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
|
||||
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
|
||||
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.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/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
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=
|
||||
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
|
||||
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
|
||||
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
|
||||
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
|
||||
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
|
||||
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
|
||||
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
|
||||
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
|
||||
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
|
||||
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
|
||||
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
|
||||
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
|
||||
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
|
||||
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
|
||||
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
|
||||
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
|
||||
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
|
||||
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
|
||||
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
|
||||
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
|
||||
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
|
||||
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
|
||||
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
|
||||
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
|
||||
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
|
||||
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
|
||||
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
|
||||
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
|
||||
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
|
||||
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
|
||||
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
|
||||
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
|
||||
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
|
||||
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
|
||||
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/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
|
||||
modernc.org/libc v1.19.0 h1:bXyVhGQg6KIClTr8FMVIDPl7jtbcs7aS5WP7vLDaxPs=
|
||||
modernc.org/libc v1.19.0/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
|
||||
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/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/libc v1.21.5 h1:xBkU9fnHV+hvZuPSRszN0AXDG4M7nwPLwTWwkYcvLCI=
|
||||
modernc.org/libc v1.21.5/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
||||
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
|
||||
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package kanban
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fumiama/go-registry"
|
||||
)
|
||||
|
||||
var (
|
||||
// Banner ...
|
||||
Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||
"* Version 1.5.2-beta2 - 2022-10-28 12:49:51 +0800 CST\n" +
|
||||
"* Copyright © 2020 - 2022 FloatTech. All Rights Reserved.\n" +
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||
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
|
||||
}
|
||||
15
kanban/banner/banner.go
Normal file
15
kanban/banner/banner.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// Code generated by kanban/gen. DO NOT EDIT.
|
||||
|
||||
package banner
|
||||
|
||||
// Version ...
|
||||
var Version = "v1.7.1"
|
||||
|
||||
// Copyright ...
|
||||
var Copyright = "© 2020 - 2023 FloatTech"
|
||||
|
||||
// Banner ...
|
||||
var Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||
"* Version " + Version + " - 2023-04-30 13:51:47 +0800 CST\n" +
|
||||
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||
51
kanban/gen/banner.go
Normal file
51
kanban/gen/banner.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// Package main generates banner.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const banner = `// Code generated by kanban/gen. DO NOT EDIT.
|
||||
|
||||
package banner
|
||||
|
||||
// Version ...
|
||||
var Version = "%s"
|
||||
|
||||
// Copyright ...
|
||||
var Copyright = "© 2020 - %d FloatTech"
|
||||
|
||||
// Banner ...
|
||||
var Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||
"* Version " + Version + " - %s\n" +
|
||||
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||
`
|
||||
|
||||
const timeformat = `2006-01-02 15:04:05 +0800 CST`
|
||||
|
||||
func main() {
|
||||
f, err := os.Create("banner/banner.go")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
vartag := bytes.NewBuffer(nil)
|
||||
vartagcmd := exec.Command("git", "tag", "--sort=committerdate")
|
||||
vartagcmd.Stdout = vartag
|
||||
err = vartagcmd.Run()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
s := strings.Split(vartag.String(), "\n")
|
||||
now := time.Now()
|
||||
_, err = fmt.Fprintf(f, banner, s[len(s)-2], now.Year(), now.Format(timeformat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,43 @@
|
||||
package kanban
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"fmt"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/fumiama/go-registry"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
//go:generate go run github.com/FloatTech/ZeroBot-Plugin/kanban/gen
|
||||
|
||||
func init() {
|
||||
once.Do(PrintBanner)
|
||||
PrintBanner()
|
||||
}
|
||||
|
||||
var reg = registry.NewRegReader("reilia.fumiama.top:32664", control.Md5File, "fumiama")
|
||||
|
||||
// PrintBanner ...
|
||||
func PrintBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
"\n", banner.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
|
||||
}
|
||||
|
||||
227
main.go
227
main.go
@@ -7,10 +7,14 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 在最前打印 banner
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/console" // 更改控制台属性
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 打印 banner
|
||||
|
||||
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
|
||||
// ----------------------插件优先级按顺序从高到低---------------------- //
|
||||
@@ -36,8 +40,6 @@ import (
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager" // 群管
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
|
||||
|
||||
_ "github.com/FloatTech/zbputils/job" // 定时指令触发器
|
||||
|
||||
// ^^^^ //
|
||||
@@ -58,80 +60,99 @@ import (
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aipaint" // ai绘图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baiduaudit" // 百度内容审核
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/base64gua" // base64卦加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baseamasiro" // base天城文加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // 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/chrev" // 英文字符翻转
|
||||
_ "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/event" // 好友申请群聊邀请事件处理
|
||||
_ "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/heisi" // 黑丝
|
||||
_ "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/jikipedia" // 小鸡词典
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
|
||||
_ "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/moegoe" // 日韩 VITS 模型拟声
|
||||
_ "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/nihongo" // 日语语法学习
|
||||
_ "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/wenxinAI" // 百度文心AI画图
|
||||
_ "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/ahsai" // ahsai tts
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aipaint" // ai绘图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/autowithdraw" // 触发者撤回时也自动撤回
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baiduaudit" // 百度内容审核
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/base64gua" // base64卦加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baseamasiro" // base天城文加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // 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/chrev" // 英文字符翻转
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dailynews" // 今日早报
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dish" // 程序员做饭指南
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drawlots" // 多功能抽签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dress" // 女装
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle" // 漂流瓶
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/event" // 好友申请群聊邀请事件处理
|
||||
_ "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/heisi" // 黑丝
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hitokoto" // 一言
|
||||
_ "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/jiami" // 兽语加密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/kfccrazythursday" // 疯狂星期四
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/magicprompt" // magicprompt吟唱提示
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moegoe" // 日韩 VITS 模型拟声
|
||||
_ "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/nihongo" // 日语语法学习
|
||||
_ "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/quan" // QQ权重查询
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qzone" // qq空间表白墙
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan" // realcugan清晰术
|
||||
_ "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/steam" // steam相关
|
||||
_ "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/vitsnyaru" // vits猫雷
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbmusic" // vtb点歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet" // 钱包
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes" // 据意查句
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi" // warframeAPI插件
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenben" // 文本指令大全
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI" // 百度文心AI画图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife" // 抽老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo" // 游戏王相关插件
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
||||
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
@@ -155,6 +176,8 @@ import (
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat" // 打断复读
|
||||
|
||||
// ^^^^ //
|
||||
@@ -174,12 +197,17 @@ import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
// webctrl "github.com/FloatTech/zbputils/control/web"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
|
||||
// -----------------------以上为内置依赖,勿动------------------------ //
|
||||
)
|
||||
|
||||
type zbpcfg struct {
|
||||
Z zero.Config `json:"zero"`
|
||||
W []*driver.WSClient `json:"ws"`
|
||||
S []*driver.WSServer `json:"wss"`
|
||||
}
|
||||
|
||||
var config zbpcfg
|
||||
@@ -190,6 +218,7 @@ func init() {
|
||||
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 := flag.String("g", "127.0.0.1:3000", "Set webui url.")
|
||||
// 直接写死 AccessToken 时,请更改下面第二个参数
|
||||
token := flag.String("t", "", "Set AccessToken of WSClient.")
|
||||
// 直接写死 URL 时,请更改下面第二个参数
|
||||
@@ -199,6 +228,9 @@ func init() {
|
||||
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.")
|
||||
late := flag.Uint("l", 233, "Response latency (ms).")
|
||||
rsz := flag.Uint("r", 4096, "Receiving buffer ring size.")
|
||||
maxpt := flag.Uint("x", 4, "Max process time (min).")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
@@ -206,13 +238,12 @@ func init() {
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
} else {
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
}
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
|
||||
for _, s := range flag.Args() {
|
||||
@@ -227,6 +258,9 @@ func init() {
|
||||
// sus = append(sus, 12345678)
|
||||
// sus = append(sus, 87654321)
|
||||
|
||||
// 启用 webui
|
||||
// go webctrl.RunGui(*g)
|
||||
|
||||
if *runcfg != "" {
|
||||
f, err := os.Open(*runcfg)
|
||||
if err != nil {
|
||||
@@ -238,20 +272,25 @@ func init() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.Z.Driver = make([]zero.Driver, len(config.W))
|
||||
config.Z.Driver = make([]zero.Driver, len(config.W)+len(config.S))
|
||||
for i, w := range config.W {
|
||||
config.Z.Driver[i] = w
|
||||
}
|
||||
for i, s := range config.S {
|
||||
config.Z.Driver[i+len(config.W)] = s
|
||||
}
|
||||
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]},
|
||||
NickName: append([]string{*adana}, "ATRI", "atri", "亚托莉", "アトリ"),
|
||||
CommandPrefix: *prefix,
|
||||
SuperUsers: sus,
|
||||
RingLen: *rsz,
|
||||
Latency: time.Duration(*late) * time.Millisecond,
|
||||
MaxProcessTime: time.Duration(*maxpt) * time.Minute,
|
||||
Driver: []zero.Driver{config.W[0]},
|
||||
}
|
||||
|
||||
if *save != "" {
|
||||
@@ -270,15 +309,17 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano()) // 全局 seed,其他插件无需再 seed
|
||||
if !strings.Contains(runtime.Version(), "go1.2") { // go1.20之前版本需要全局 seed,其他插件无需再 seed
|
||||
rand.Seed(time.Now().UnixNano()) //nolint: staticcheck
|
||||
}
|
||||
// 帮助
|
||||
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(kanban.Banner, "\n可发送\"/服务列表\"查看 bot 功能"))
|
||||
ctx.SendChain(message.Text(banner.Banner, "\n管理发送\"/服务列表\"查看 bot 功能\n发送\"/用法name\"查看功能用法"))
|
||||
})
|
||||
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(kanban.Kanban()))
|
||||
ctx.SendChain(message.Text(strings.ReplaceAll(kanban.Kanban(), "\t", "")))
|
||||
})
|
||||
zero.RunAndBlock(config.Z, process.GlobalInitMutex.Unlock)
|
||||
zero.RunAndBlock(&config.Z, process.GlobalInitMutex.Unlock)
|
||||
}
|
||||
|
||||
70
main_win.go
70
main_win.go
@@ -1,70 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// windows 带颜色 log 自定义格式
|
||||
logrus.SetFormatter(&LogFormat{})
|
||||
}
|
||||
|
||||
const (
|
||||
colorCodePanic = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeFatal = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeError = "\x1b[31m" // color.Style{color.Red}.String()
|
||||
colorCodeWarn = "\x1b[33m" // color.Style{color.Yellow}.String()
|
||||
colorCodeInfo = "\x1b[37m" // color.Style{color.White}.String()
|
||||
colorCodeDebug = "\x1b[32m" // color.Style{color.Green}.String()
|
||||
colorCodeTrace = "\x1b[36m" // color.Style{color.Cyan}.String()
|
||||
colorReset = "\x1b[0m"
|
||||
)
|
||||
|
||||
// LogFormat specialize for zbp
|
||||
type LogFormat struct{}
|
||||
|
||||
// Format implements logrus.Formatter
|
||||
func (f LogFormat) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
buf.WriteString(getLogLevelColorCode(entry.Level))
|
||||
|
||||
buf.WriteByte('[')
|
||||
buf.WriteString(strings.ToUpper(entry.Level.String()))
|
||||
buf.WriteString("] ")
|
||||
buf.WriteString(entry.Message)
|
||||
buf.WriteString(" \n")
|
||||
|
||||
buf.WriteString(colorReset)
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// getLogLevelColorCode 获取日志等级对应色彩code
|
||||
func getLogLevelColorCode(level logrus.Level) string {
|
||||
switch level {
|
||||
case logrus.PanicLevel:
|
||||
return colorCodePanic
|
||||
case logrus.FatalLevel:
|
||||
return colorCodeFatal
|
||||
case logrus.ErrorLevel:
|
||||
return colorCodeError
|
||||
case logrus.WarnLevel:
|
||||
return colorCodeWarn
|
||||
case logrus.InfoLevel:
|
||||
return colorCodeInfo
|
||||
case logrus.DebugLevel:
|
||||
return colorCodeDebug
|
||||
case logrus.TraceLevel:
|
||||
return colorCodeTrace
|
||||
|
||||
default:
|
||||
return colorCodeInfo
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,8 @@ var (
|
||||
func init() {
|
||||
engine := control.Register("ahsai", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "ahsai tts\n- 使[伊織弓鶴|紲星あかり|結月ゆかり|京町セイカ|東北きりたん|東北イタコ|ついなちゃん標準語|ついなちゃん関西弁|音街ウナ|琴葉茜|吉田くん|民安ともえ|桜乃そら|月読アイ|琴葉葵|東北ずん子|月読ショウタ|水奈瀬コウ]说(日语)\n",
|
||||
Brief: "フリーテキスト音声合成",
|
||||
Help: "- 使[伊織弓鶴|紲星あかり|結月ゆかり|京町セイカ|東北きりたん|東北イタコ|ついなちゃん標準語|ついなちゃん関西弁|音街ウナ|琴葉茜|吉田くん|民安ともえ|桜乃そら|月読アイ|琴葉葵|東北ずん子|月読ショウタ|水奈瀬コウ]说(日语)",
|
||||
PrivateDataFolder: "ahsai",
|
||||
})
|
||||
cachePath := engine.DataFolder() + "cache/"
|
||||
|
||||
@@ -2,28 +2,59 @@
|
||||
package aifalse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"math"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/bilibili"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"github.com/FloatTech/rendercard"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
backgroundURL = "https://iw233.cn/api.php?sort=mp"
|
||||
referer = "https://weibo.com/"
|
||||
)
|
||||
|
||||
var (
|
||||
boottime = time.Now()
|
||||
bgdata *[]byte
|
||||
bgcount uintptr
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("aifalse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIfalse\n" +
|
||||
"- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
|
||||
Brief: "自检, 全局限速",
|
||||
Help: "- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
|
||||
"- 设置默认限速为每 m [分钟 | 秒] n 次触发",
|
||||
})
|
||||
c, ok := control.Lookup("aifalse")
|
||||
@@ -39,12 +70,19 @@ func init() { // 插件主体
|
||||
}
|
||||
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(
|
||||
"* CPU占用: ", cpuPercent(), "%\n",
|
||||
"* RAM占用: ", memPercent(), "%\n",
|
||||
"* 硬盘使用: ", diskPercent(),
|
||||
),
|
||||
)
|
||||
img, err := drawstatus(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.Event.SelfID, zero.BotConfig.NickName[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
sendimg, err := imgfactory.ToBytes(img)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.ImageBytes(sendimg)); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^设置默认限速为每\s*(\d+)\s*(分钟|秒)\s*(\d+)\s*次触发$`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
@@ -84,38 +122,493 @@ func init() { // 插件主体
|
||||
})
|
||||
}
|
||||
|
||||
func cpuPercent() float64 {
|
||||
func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg image.Image, err error) {
|
||||
diskstate, err := diskstate()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
diskcardh := 40 + (20+50)*len(diskstate) + 40 - 20
|
||||
|
||||
moreinfo, err := moreinfo(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
moreinfocardh := 30 + (20+32*72/96)*len(moreinfo) + 30 - 20
|
||||
|
||||
basicstate, err := basicstate()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dldata := (*[]byte)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&bgdata))))
|
||||
if dldata == (*[]byte)(nil) || uintptr(time.Since(boottime).Hours()/24) >= atomic.LoadUintptr(&bgcount) {
|
||||
url, err1 := bilibili.GetRealURL(backgroundURL)
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
data, err1 := web.RequestDataWith(web.NewDefaultClient(), url, "", referer, "", nil)
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
atomic.AddUintptr(&bgcount, 1)
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&bgdata)), unsafe.Pointer(&data))
|
||||
dldata = &data
|
||||
}
|
||||
data := *dldata
|
||||
|
||||
back, _, err := image.Decode(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data, err = web.GetData("http://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(uid, 10) + "&s=640")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
avatar, _, err := image.Decode(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
avatarf := imgfactory.Size(avatar, 200, 200)
|
||||
|
||||
fontbyte, err := file.GetLazyData(text.GlowSansFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
canvas := gg.NewContext(1280, 70+250+40+380+diskcardh+40+moreinfocardh+40+70)
|
||||
|
||||
bh, bw, ch, cw := float64(back.Bounds().Dy()), float64(back.Bounds().Dx()), float64(canvas.H()), float64(canvas.W())
|
||||
|
||||
if bh/bw < ch/cw {
|
||||
back = imgfactory.Size(back, int(bw*ch/bh), int(bh*ch/bh)).Image()
|
||||
canvas.DrawImageAnchored(back, canvas.W()/2, canvas.H()/2, 0.5, 0.5)
|
||||
} else {
|
||||
back = imgfactory.Size(back, int(bw*cw/bw), int(bh*cw/bw)).Image()
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
}
|
||||
var blurback image.Image
|
||||
bwg := &sync.WaitGroup{}
|
||||
bwg.Add(1)
|
||||
go func() {
|
||||
defer bwg.Done()
|
||||
blurback = imaging.Blur(canvas.Image(), 8)
|
||||
}()
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(5)
|
||||
|
||||
cardw := canvas.W() - 70 - 70
|
||||
|
||||
titlecardh := 250
|
||||
basiccardh := 380
|
||||
|
||||
var titleimg, basicimg, diskimg, moreinfoimg, shadowimg image.Image
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
titlecard := gg.NewContext(cardw, titlecardh)
|
||||
bwg.Wait()
|
||||
titlecard.DrawImage(blurback, -70, -70)
|
||||
|
||||
titlecard.DrawRoundedRectangle(1, 1, float64(titlecard.W()-1*2), float64(titlecardh-1*2), 16)
|
||||
titlecard.SetLineWidth(3)
|
||||
titlecard.SetRGBA255(255, 255, 255, 100)
|
||||
titlecard.StrokePreserve()
|
||||
titlecard.SetRGBA255(255, 255, 255, 140)
|
||||
titlecard.Fill()
|
||||
|
||||
titlecard.DrawImage(avatarf.Circle(0).Image(), (titlecardh-avatarf.H())/2, (titlecardh-avatarf.H())/2)
|
||||
|
||||
err = titlecard.ParseFontFace(fontbyte, 72)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fw, _ := titlecard.MeasureString(botname)
|
||||
|
||||
titlecard.SetRGBA255(30, 30, 30, 255)
|
||||
|
||||
titlecard.DrawStringAnchored(botname, float64(titlecardh)+fw/2, float64(titlecardh)*0.5/2, 0.5, 0.5)
|
||||
|
||||
err = titlecard.ParseFontFace(fontbyte, 24)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
titlecard.SetRGBA255(30, 30, 30, 180)
|
||||
|
||||
titlecard.NewSubPath()
|
||||
titlecard.MoveTo(float64(titlecardh), float64(titlecardh)/2)
|
||||
titlecard.LineTo(float64(titlecard.W()-titlecardh), float64(titlecardh)/2)
|
||||
titlecard.Stroke()
|
||||
|
||||
brt, err := botruntime()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fw, _ = titlecard.MeasureString(brt)
|
||||
|
||||
titlecard.DrawStringAnchored(brt, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.25/2), 0.5, 0.5)
|
||||
|
||||
bs, err := botstatus()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fw, _ = titlecard.MeasureString(bs)
|
||||
|
||||
titlecard.DrawStringAnchored(bs, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.5/2), 0.5, 0.5)
|
||||
titleimg = rendercard.Fillet(titlecard.Image(), 16)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
basiccard := gg.NewContext(cardw, basiccardh)
|
||||
bwg.Wait()
|
||||
basiccard.DrawImage(blurback, -70, -70-titlecardh-40)
|
||||
|
||||
basiccard.DrawRoundedRectangle(1, 1, float64(basiccard.W()-1*2), float64(basiccardh-1*2), 16)
|
||||
basiccard.SetLineWidth(3)
|
||||
basiccard.SetRGBA255(255, 255, 255, 100)
|
||||
basiccard.StrokePreserve()
|
||||
basiccard.SetRGBA255(255, 255, 255, 140)
|
||||
basiccard.Fill()
|
||||
|
||||
bslen := len(basicstate)
|
||||
for i, v := range basicstate {
|
||||
offset := float64(i) * ((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1) + 200)
|
||||
|
||||
basiccard.SetRGBA255(235, 235, 235, 255)
|
||||
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100)
|
||||
basiccard.Fill()
|
||||
|
||||
switch {
|
||||
case v.precent > 90:
|
||||
basiccard.SetRGBA255(255, 70, 0, 255)
|
||||
case v.precent > 70:
|
||||
basiccard.SetRGBA255(255, 165, 0, 255)
|
||||
default:
|
||||
basiccard.SetRGBA255(145, 240, 145, 255)
|
||||
}
|
||||
|
||||
basiccard.NewSubPath()
|
||||
basiccard.MoveTo((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2)
|
||||
basiccard.DrawEllipticalArc((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100, 100, -0.5*math.Pi, -0.5*math.Pi+2*v.precent*0.01*math.Pi)
|
||||
basiccard.Fill()
|
||||
|
||||
basiccard.SetRGBA255(255, 255, 255, 255)
|
||||
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 80)
|
||||
basiccard.Fill()
|
||||
|
||||
err = basiccard.ParseFontFace(fontbyte, 42)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
basiccard.SetRGBA255(213, 213, 213, 255)
|
||||
basiccard.DrawStringAnchored(strconv.FormatFloat(v.precent, 'f', 0, 64)+"%", (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 0.5, 0.5)
|
||||
|
||||
basiccard.SetRGBA255(30, 30, 30, 255)
|
||||
_, fw := basiccard.MeasureString(v.name)
|
||||
basiccard.DrawStringAnchored(v.name, (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200+15+basiccard.FontHeight()/2, 0.5, 0.5)
|
||||
|
||||
err = basiccard.ParseFontFace(fontbyte, 20)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
basiccard.SetRGBA255(30, 30, 30, 180)
|
||||
|
||||
textoffsety := basiccard.FontHeight() + 10
|
||||
for k, s := range v.text {
|
||||
basiccard.DrawStringAnchored(s, (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200+15+fw+15+basiccard.FontHeight()/2+float64(k)*textoffsety, 0.5, 0.5)
|
||||
}
|
||||
}
|
||||
basicimg = rendercard.Fillet(basiccard.Image(), 16)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
diskcard := gg.NewContext(cardw, diskcardh)
|
||||
bwg.Wait()
|
||||
diskcard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40)
|
||||
|
||||
diskcard.DrawRoundedRectangle(1, 1, float64(diskcard.W()-1*2), float64(diskcardh-1*2), 16)
|
||||
diskcard.SetLineWidth(3)
|
||||
diskcard.SetRGBA255(255, 255, 255, 100)
|
||||
diskcard.StrokePreserve()
|
||||
diskcard.SetRGBA255(255, 255, 255, 140)
|
||||
diskcard.Fill()
|
||||
|
||||
err = diskcard.ParseFontFace(fontbyte, 32)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dslen := len(diskstate)
|
||||
if dslen == 1 {
|
||||
diskcard.SetRGBA255(192, 192, 192, 255)
|
||||
diskcard.DrawRoundedRectangle(40, 40, float64(diskcard.W())-40-100, 50, 12)
|
||||
diskcard.ClipPreserve()
|
||||
diskcard.Fill()
|
||||
|
||||
switch {
|
||||
case diskstate[0].precent > 90:
|
||||
diskcard.SetRGBA255(255, 70, 0, 255)
|
||||
case diskstate[0].precent > 70:
|
||||
diskcard.SetRGBA255(255, 165, 0, 255)
|
||||
default:
|
||||
diskcard.SetRGBA255(145, 240, 145, 255)
|
||||
}
|
||||
|
||||
diskcard.DrawRoundedRectangle(40, 40, (float64(diskcard.W())-40-100)*diskstate[0].precent*0.01, 50, 12)
|
||||
diskcard.Fill()
|
||||
diskcard.ResetClip()
|
||||
diskcard.SetRGBA255(30, 30, 30, 255)
|
||||
|
||||
fw, _ := diskcard.MeasureString(diskstate[0].name)
|
||||
fw1, _ := diskcard.MeasureString(diskstate[0].text[0])
|
||||
|
||||
diskcard.DrawStringAnchored(diskstate[0].name, 40+10+fw/2, 40+50/2, 0.5, 0.5)
|
||||
diskcard.DrawStringAnchored(diskstate[0].text[0], (float64(diskcard.W())-100-10)-fw1/2, 40+50/2, 0.5, 0.5)
|
||||
diskcard.DrawStringAnchored(strconv.FormatFloat(diskstate[0].precent, 'f', 0, 64)+"%", float64(diskcard.W())-100/2, 40+50/2, 0.5, 0.5)
|
||||
} else {
|
||||
for i, v := range diskstate {
|
||||
offset := float64(i)*(50+20) - 20
|
||||
|
||||
diskcard.SetRGBA255(192, 192, 192, 255)
|
||||
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, float64(diskcard.W())-40-100, 50, 12)
|
||||
diskcard.Fill()
|
||||
|
||||
switch {
|
||||
case v.precent > 90:
|
||||
diskcard.SetRGBA255(255, 70, 0, 255)
|
||||
case v.precent > 70:
|
||||
diskcard.SetRGBA255(255, 165, 0, 255)
|
||||
default:
|
||||
diskcard.SetRGBA255(145, 240, 145, 255)
|
||||
}
|
||||
|
||||
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, (float64(diskcard.W())-40-100)*v.precent*0.01, 50, 12)
|
||||
diskcard.Fill()
|
||||
|
||||
diskcard.SetRGBA255(30, 30, 30, 255)
|
||||
|
||||
fw, _ := diskcard.MeasureString(v.name)
|
||||
fw1, _ := diskcard.MeasureString(v.text[0])
|
||||
|
||||
diskcard.DrawStringAnchored(v.name, 40+10+fw/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
|
||||
diskcard.DrawStringAnchored(v.text[0], (float64(diskcard.W())-100-10)-fw1/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
|
||||
diskcard.DrawStringAnchored(strconv.FormatFloat(v.precent, 'f', 0, 64)+"%", float64(diskcard.W())-100/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
|
||||
}
|
||||
}
|
||||
diskimg = rendercard.Fillet(diskcard.Image(), 16)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
moreinfocard := gg.NewContext(cardw, moreinfocardh)
|
||||
bwg.Wait()
|
||||
moreinfocard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
|
||||
|
||||
moreinfocard.DrawRoundedRectangle(1, 1, float64(moreinfocard.W()-1*2), float64(moreinfocard.H()-1*2), 16)
|
||||
moreinfocard.SetLineWidth(3)
|
||||
moreinfocard.SetRGBA255(255, 255, 255, 100)
|
||||
moreinfocard.StrokePreserve()
|
||||
moreinfocard.SetRGBA255(255, 255, 255, 140)
|
||||
moreinfocard.Fill()
|
||||
|
||||
err = moreinfocard.ParseFontFace(fontbyte, 32)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
milen := len(moreinfo)
|
||||
for i, v := range moreinfo {
|
||||
offset := float64(i)*(20+moreinfocard.FontHeight()) - 20
|
||||
|
||||
moreinfocard.SetRGBA255(30, 30, 30, 255)
|
||||
|
||||
fw, _ := moreinfocard.MeasureString(v.name)
|
||||
fw1, _ := moreinfocard.MeasureString(v.text[0])
|
||||
|
||||
moreinfocard.DrawStringAnchored(v.name, 20+fw/2, 30+(float64(moreinfocardh-30*2)-moreinfocard.FontHeight()*float64(milen))/float64(milen-1)+moreinfocard.FontHeight()/2+offset, 0.5, 0.5)
|
||||
moreinfocard.DrawStringAnchored(v.text[0], float64(moreinfocard.W())-20-fw1/2, 30+(float64(moreinfocardh-30*2)-moreinfocard.FontHeight()*float64(milen))/float64(milen-1)+moreinfocard.FontHeight()/2+offset, 0.5, 0.5)
|
||||
}
|
||||
moreinfoimg = rendercard.Fillet(moreinfocard.Image(), 16)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
shadow := gg.NewContext(canvas.W(), canvas.H())
|
||||
shadow.SetRGBA255(0, 0, 0, 100)
|
||||
shadow.SetLineWidth(12)
|
||||
shadow.DrawRoundedRectangle(70, 70, float64(cardw), float64(titlecardh), 16)
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40), float64(cardw), float64(basiccardh), 16)
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40), float64(cardw), float64(diskcardh), 16)
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40+diskcardh+40), float64(cardw), float64(moreinfocardh), 16)
|
||||
shadow.Stroke()
|
||||
shadowimg = imaging.Blur(shadow.Image(), 24)
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
if shadowimg == nil || titleimg == nil || basicimg == nil || diskimg == nil || moreinfoimg == nil {
|
||||
err = errors.New("图片渲染失败")
|
||||
return
|
||||
}
|
||||
canvas.DrawImage(shadowimg, 0, 0)
|
||||
canvas.DrawImage(titleimg, 70, 70)
|
||||
canvas.DrawImage(basicimg, 70, 70+titlecardh+40)
|
||||
canvas.DrawImage(diskimg, 70, 70+titlecardh+40+basiccardh+40)
|
||||
canvas.DrawImage(moreinfoimg, 70, 70+titlecardh+40+basiccardh+40+diskcardh+40)
|
||||
|
||||
err = canvas.ParseFontFace(fontbyte, 28)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.DrawStringAnchored("Created By ZeroBot-Plugin "+banner.Version, float64(canvas.W())/2+3, float64(canvas.H())-70/2+3, 0.5, 0.5)
|
||||
canvas.SetRGBA255(255, 255, 255, 255)
|
||||
canvas.DrawStringAnchored("Created By ZeroBot-Plugin "+banner.Version, float64(canvas.W())/2, float64(canvas.H())-70/2, 0.5, 0.5)
|
||||
|
||||
sendimg = canvas.Image()
|
||||
return
|
||||
}
|
||||
|
||||
func botruntime() (string, error) {
|
||||
hostinfo, err := host.Info()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
t := &strings.Builder{}
|
||||
t.WriteString("ZeroBot-Plugin 已运行 ")
|
||||
t.WriteString(strconv.FormatInt((time.Now().Unix()-boottime.Unix())/86400, 10))
|
||||
t.WriteString(" 天 ")
|
||||
t.WriteString(time.Unix(time.Now().Unix()-boottime.Unix(), 0).UTC().Format("15:04:05"))
|
||||
t.WriteString(" | 系统运行 ")
|
||||
t.WriteString(strconv.FormatInt(int64(hostinfo.Uptime)/86400, 10))
|
||||
t.WriteString(" 天 ")
|
||||
t.WriteString(time.Unix(int64(hostinfo.Uptime), 0).UTC().Format("15:04:05"))
|
||||
return t.String(), nil
|
||||
}
|
||||
|
||||
func botstatus() (string, error) {
|
||||
hostinfo, err := host.Info()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
t := &strings.Builder{}
|
||||
t.WriteString(time.Now().Format("2006-01-02 15:04:05"))
|
||||
t.WriteString(" | Compiled by ")
|
||||
t.WriteString(runtime.Version())
|
||||
t.WriteString(" | ")
|
||||
t.WriteString(cases.Title(language.English).String(hostinfo.OS))
|
||||
return t.String(), nil
|
||||
}
|
||||
|
||||
type status struct {
|
||||
precent float64
|
||||
name string
|
||||
text []string
|
||||
}
|
||||
|
||||
func basicstate() (stateinfo [3]*status, err error) {
|
||||
percent, err := cpu.Percent(time.Second, false)
|
||||
if err != nil {
|
||||
return -1
|
||||
return
|
||||
}
|
||||
return math.Round(percent[0])
|
||||
cpuinfo, err := cpu.Info()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cores := strconv.Itoa(int(cpuinfo[0].Cores)) + " Core"
|
||||
times := "最大 " + strconv.FormatFloat(cpuinfo[0].Mhz/1000, 'f', 1, 64) + "Ghz"
|
||||
|
||||
stateinfo[0] = &status{
|
||||
precent: math.Round(percent[0]),
|
||||
name: "CPU",
|
||||
text: []string{cores, times},
|
||||
}
|
||||
|
||||
raminfo, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total := "总共 " + storagefmt(float64(raminfo.Total))
|
||||
used := "已用 " + storagefmt(float64(raminfo.Used))
|
||||
free := "剩余 " + storagefmt(float64(raminfo.Free))
|
||||
|
||||
stateinfo[1] = &status{
|
||||
precent: math.Round(raminfo.UsedPercent),
|
||||
name: "RAM",
|
||||
text: []string{total, used, free},
|
||||
}
|
||||
|
||||
swapinfo, err := mem.SwapMemory()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total = "总共 " + storagefmt(float64(swapinfo.Total))
|
||||
used = "已用 " + storagefmt(float64(swapinfo.Used))
|
||||
free = "剩余 " + storagefmt(float64(swapinfo.Free))
|
||||
|
||||
stateinfo[2] = &status{
|
||||
precent: math.Round(swapinfo.UsedPercent),
|
||||
name: "SWAP",
|
||||
text: []string{total, used, free},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func memPercent() float64 {
|
||||
memInfo, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return -1
|
||||
func storagefmt(num float64) string {
|
||||
if num /= 1024; num < 1 {
|
||||
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "B"
|
||||
}
|
||||
return math.Round(memInfo.UsedPercent)
|
||||
if num /= 1024; num < 1 {
|
||||
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "KB"
|
||||
}
|
||||
if num /= 1024; num < 1 {
|
||||
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "MB"
|
||||
}
|
||||
if num /= 1024; num < 1 {
|
||||
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "GB"
|
||||
}
|
||||
return strconv.FormatFloat(num, 'f', 2, 64) + "TB"
|
||||
}
|
||||
|
||||
func diskPercent() string {
|
||||
parts, err := disk.Partitions(true)
|
||||
func diskstate() (stateinfo []*status, err error) {
|
||||
parts, err := disk.Partitions(false)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
return
|
||||
}
|
||||
msg := ""
|
||||
for _, p := range parts {
|
||||
diskInfo, err := disk.Usage(p.Mountpoint)
|
||||
if err != nil {
|
||||
msg += "\n - " + err.Error()
|
||||
stateinfo = make([]*status, 0, len(parts))
|
||||
for _, v := range parts {
|
||||
mp := v.Mountpoint
|
||||
if strings.HasPrefix(mp, "/snap/") || strings.HasPrefix(mp, "/apex/") {
|
||||
continue
|
||||
}
|
||||
pc := uint(math.Round(diskInfo.UsedPercent))
|
||||
if pc > 0 {
|
||||
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, pc)
|
||||
diskusage, err := disk.Usage(mp)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
stateinfo = append(stateinfo, &status{
|
||||
precent: math.Round(diskusage.UsedPercent),
|
||||
name: mp,
|
||||
text: []string{storagefmt(float64(diskusage.Used)) + " / " + storagefmt(float64(diskusage.Total))},
|
||||
})
|
||||
}
|
||||
return msg
|
||||
return stateinfo, nil
|
||||
}
|
||||
|
||||
func moreinfo(m *ctrl.Control[*zero.Ctx]) (stateinfo []*status, err error) {
|
||||
hostinfo, err := host.Info()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cpuinfo, err := cpu.Info()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count := len(m.Manager.M)
|
||||
stateinfo = []*status{
|
||||
{name: "OS", text: []string{hostinfo.Platform}},
|
||||
{name: "CPU", text: []string{cpuinfo[0].ModelName}},
|
||||
{name: "Version", text: []string{hostinfo.PlatformVersion}},
|
||||
{name: "Plugin", text: []string{"共 " + strconv.Itoa(count) + " 个"}},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,100 +2,75 @@ package aireply
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"sync"
|
||||
"strings"
|
||||
|
||||
"github.com/RomiChan/syncx"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
"github.com/FloatTech/AnimeAPI/tts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/baidutts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/genshin"
|
||||
"github.com/FloatTech/AnimeAPI/tts/ttscn"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
)
|
||||
|
||||
// 数据结构: [4 bits] [4 bits] [8 bits] [8 bits]
|
||||
// [ttscn模式] [百度模式] [tts模式] [回复模式]
|
||||
|
||||
// defaultttsindexkey
|
||||
// 数据结构: [4 bits] [4 bits] [8 bits]
|
||||
// [ttscn模式] [百度模式] [tts模式]
|
||||
|
||||
// [tts模式]: 0~63 genshin 64 baidu 65 ttscn
|
||||
|
||||
const (
|
||||
cnapi = "https://genshin.azurewebsites.net/api/speak?format=mp3&id=%d&text=%s"
|
||||
lastgsttsindex = 63 + iota
|
||||
baiduttsindex
|
||||
ttscnttsindex
|
||||
)
|
||||
|
||||
// 每个角色的测试文案
|
||||
var testRecord = map[string]string{
|
||||
"派蒙": "哎,又是看不懂的东西。我完全不知道这些奇怪的问题和实验,能得到什么结果…",
|
||||
"凯亚": "真是个急性子啊你。",
|
||||
"安柏": "最初的鸟儿是不会飞翔的,飞翔是它们勇敢跃入峡谷的奖励。",
|
||||
"丽莎": "嗨,小可爱,你是新来的助理吗?",
|
||||
"琴": "蒲公英骑士,琴,申请入队。",
|
||||
"香菱": "我是来自璃月的厨师香菱,最擅长的是做各种捞…捞,料理…哎呀,练了那么多次,还是会紧张,嘿。",
|
||||
"枫原万叶": "飘摇风雨中,带刀归来赤脚行。",
|
||||
"迪卢克": "在黎明来临之前,总要有人照亮黑暗。",
|
||||
"温迪": "若你困于无风之地,我将为你奏响高天之歌。",
|
||||
"可莉": "西风骑士团,火花骑士,可莉,前来报到!…呃—后面该说什么词来着?可莉背不下来啦...",
|
||||
"早柚": "终末番,早柚,参上。 呼——",
|
||||
"托马": "初次见面,异乡的旅人,你的名字我可是早就听说了。只要你不嫌弃,我托马,从今天起就是你的朋友了。",
|
||||
"芭芭拉": "芭芭拉,闪耀登场~治疗就交给我吧,不会让你失望的!",
|
||||
"优菈": "沉沦是很容易的一件事,但我仍想冻住这股潮流。",
|
||||
"云堇": "曲高未必人不识,自有知音和清词。",
|
||||
"钟离": "人间归离复归离,借一浮生逃浮生。",
|
||||
"魈": "三眼五显仙人,魈,听召,前来守护",
|
||||
"凝光": "就算古玩价值连城,给人的快乐,也只有刚拥有的一瞬",
|
||||
"雷电将军": "浮世千百年来风景依旧,人之在世却如白露与泡影。",
|
||||
"北斗": "不知道如何向前的话,总之先迈出第一步,后面的道路就会自然而然地展开了。",
|
||||
"甘雨": "这项工作,该划掉了。",
|
||||
"七七": "椰羊的奶,好喝!比一般的羊奶,好喝!",
|
||||
"刻晴": "劳逸结合是不错,但也别放松过头。",
|
||||
"神里绫华": "若知是梦何须醒,不比真如一相会。",
|
||||
"雷泽": "你是朋友。我和你一起狩猎。",
|
||||
"神里绫人": "此前听绫华屡次提起阁下,不料公务繁忙,直至今日才有机会相见。",
|
||||
"罗莎莉亚": "哪怕如今你已经走上截然不同的道路,也不要否认从前的自己,从前的每一个你都是你脚下的基石,不要害怕过去,不要畏惧与它抗衡。",
|
||||
"阿贝多": "用自己的双脚丈量土地,将未知变为知识。",
|
||||
"八重神子": "我的神明,就托付给你了。",
|
||||
"宵宫": "即使只是片刻的火花,也能在仰望黑夜的人心中留下久久不灭的美丽光芒。",
|
||||
"荒泷一斗": "更好地活下去,绝不该靠牺牲同类换取,应该是,一起更好地活着,才对。",
|
||||
"九条裟罗": "想要留住雪花。但在手心里,它只会融化的更快。",
|
||||
"夜兰": "线人来信了,嗯,看来又出现了新的变数。",
|
||||
"珊瑚宫心海": "成为了现任人神巫女之后,我也慢慢习惯了这样的生活,更重要的是我也因此和你相遇了,不是吗?",
|
||||
"五郎": "海祇岛反抗军大将,五郎,前来助阵!",
|
||||
"达达利亚": "许下的诺言就好好遵守,做错了事情就承担责任,这才是家人应有的样子吧。",
|
||||
"莫娜": "正是因为无法更改,无可违逆,只能接受,命运才会被称之为命运。",
|
||||
"班尼特": "只要有大家在,伤口就不会痛!",
|
||||
"申鹤": "不知道你是喜欢人间的灯火,还是山林的月光?",
|
||||
"行秋": "有时明月无人夜,独向昭潭制恶龙。",
|
||||
"烟绯": "律法即是约束,也是工具。",
|
||||
"久岐忍": "有麻烦事要处理的话,直接告诉我就好,我来摆平。",
|
||||
"辛焱": "马上就要演出了,你也一起来嗨吗?",
|
||||
"砂糖": "我是砂糖,炼金术的…研究员。",
|
||||
"胡桃": "阴阳有序,命运无常,死亡难以预测,却也有它的规矩。",
|
||||
"重云": "我名重云,家族久居璃月,世代以驱邪除魔为业。",
|
||||
"菲谢尔": "我即断罪之皇女,真名为菲谢尔。应命运的召唤降临在此间——哎?你也是,异世界的旅人吗…?",
|
||||
"诺艾尔": "我是诺艾尔,西风骑士团的女仆,从今天起会陪你一起去冒险。",
|
||||
"迪奥娜": "猫尾酒馆的招牌调酒师,迪奥娜,我的出场费可是很贵的。",
|
||||
"鹿野院平藏": "我叫鹿野院平藏,是天领奉行里破案最多最快的侦探……",
|
||||
// extrattsname is the tts other than genshin vits
|
||||
var extrattsname = []string{"百度", "TTSCN"}
|
||||
|
||||
var ttscnspeakers = [...]string{
|
||||
"晓晓(女 - 年轻人)",
|
||||
"云扬(男 - 年轻人)",
|
||||
"晓辰(女 - 年轻人 - 抖音热门)",
|
||||
"晓涵(女 - 年轻人)",
|
||||
"晓墨(女 - 年轻人)",
|
||||
"晓秋(女 - 中年人)",
|
||||
"晓睿(女 - 老年)",
|
||||
"晓双(女 - 儿童)",
|
||||
"晓萱(女 - 年轻人)",
|
||||
"晓颜(女 - 年轻人)",
|
||||
"晓悠(女 - 儿童)",
|
||||
"云希(男 - 年轻人 - 抖音热门)",
|
||||
"云野(男 - 中年人)",
|
||||
"晓梦(女 - 年轻人)",
|
||||
"晓伊(女 - 儿童)",
|
||||
"晓甄(女 - 年轻人)",
|
||||
}
|
||||
|
||||
const defaultttsindexkey = -2905
|
||||
|
||||
var (
|
||||
re = regexp.MustCompile(`(\-|\+)?\d+(\.\d+)?`)
|
||||
soundList = [...]string{
|
||||
"派蒙", "凯亚", "安柏", "丽莎", "琴",
|
||||
"香菱", "枫原万叶", "迪卢克", "温迪", "可莉",
|
||||
"早柚", "托马", "芭芭拉", "优菈", "云堇",
|
||||
"钟离", "魈", "凝光", "雷电将军", "北斗",
|
||||
"甘雨", "七七", "刻晴", "神里绫华", "雷泽",
|
||||
"神里绫人", "罗莎莉亚", "阿贝多", "八重神子", "宵宫",
|
||||
"荒泷一斗", "九条裟罗", "夜兰", "珊瑚宫心海", "五郎",
|
||||
"达达利亚", "莫娜", "班尼特", "申鹤", "行秋",
|
||||
"烟绯", "久岐忍", "辛焱", "砂糖", "胡桃",
|
||||
"重云", "菲谢尔", "诺艾尔", "迪奥娜", "鹿野院平藏",
|
||||
}
|
||||
原 = newapikeystore("./data/tts/o.txt")
|
||||
ཆཏ = newapikeystore("./data/tts/c.txt")
|
||||
百 = newapikeystore("./data/tts/b.txt")
|
||||
)
|
||||
|
||||
/*************************************************************
|
||||
*******************************AIreply************************
|
||||
*************************************************************/
|
||||
func setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
type replymode []string
|
||||
|
||||
func (r replymode) setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
var ok bool
|
||||
var index int64
|
||||
for i, s := range replyModes {
|
||||
for i, s := range r {
|
||||
if s == name {
|
||||
ok = true
|
||||
index = int64(i)
|
||||
@@ -109,31 +84,47 @@ func setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
if !ok {
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
return m.SetData(gid, index)
|
||||
return m.SetData(gid, (m.GetData(index)&^0xff)|(index&0xff))
|
||||
}
|
||||
|
||||
func getReplyMode(ctx *zero.Ctx) (name string) {
|
||||
func (r replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
|
||||
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)
|
||||
if int(index) < len(replyModes) {
|
||||
return replyModes[index]
|
||||
switch m.GetData(gid) & 0xff {
|
||||
case 0:
|
||||
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
|
||||
case 1:
|
||||
return aireply.NewXiaoAi(aireply.XiaoAiURL, aireply.XiaoAiBotName)
|
||||
case 2:
|
||||
k := ཆཏ.k
|
||||
if k != "" {
|
||||
return aireply.NewChatGPT(aireply.ChatGPTURL, k)
|
||||
}
|
||||
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
|
||||
}
|
||||
}
|
||||
return "青云客"
|
||||
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
***********************tts************************************
|
||||
*************************************************************/
|
||||
type ttsmode struct {
|
||||
sync.RWMutex
|
||||
mode map[int64]int64
|
||||
}
|
||||
var ttsins = func() map[string]tts.TTS {
|
||||
m := make(map[string]tts.TTS, 128)
|
||||
for _, mode := range append(genshin.SoundList[:], extrattsname...) {
|
||||
m[mode] = nil
|
||||
}
|
||||
return m
|
||||
}()
|
||||
|
||||
var ttsModes = func() []string {
|
||||
s := append(genshin.SoundList[:], make([]string, 64-len(genshin.SoundList))...) // 0-63
|
||||
s = append(s, extrattsname...) // 64 65 ...
|
||||
return s
|
||||
}()
|
||||
|
||||
type ttsmode syncx.Map[int64, int64]
|
||||
|
||||
func list(list []string, num int) string {
|
||||
s := ""
|
||||
@@ -149,90 +140,127 @@ func list(list []string, num int) string {
|
||||
}
|
||||
|
||||
func newttsmode() *ttsmode {
|
||||
tts := &ttsmode{}
|
||||
tts.Lock()
|
||||
defer tts.Unlock()
|
||||
m, ok := control.Lookup(ttsServiceName)
|
||||
tts.mode = make(map[int64]int64, 2*len(soundList))
|
||||
tts.mode[-2905] = 1
|
||||
t := &ttsmode{}
|
||||
m, ok := control.Lookup("tts")
|
||||
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, 0)
|
||||
if ok {
|
||||
index := m.GetData(-2905)
|
||||
if index > 0 && index < int64(len(soundList)) {
|
||||
tts.mode[-2905] = index
|
||||
index := m.GetData(defaultttsindexkey)
|
||||
msk := index & 0xff
|
||||
if msk >= 0 && (msk < int64(len(genshin.SoundList)) || msk == baiduttsindex || msk == ttscnttsindex) {
|
||||
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, index)
|
||||
}
|
||||
}
|
||||
return tts
|
||||
return t
|
||||
}
|
||||
|
||||
func (tts *ttsmode) setSoundMode(ctx *zero.Ctx, name string) error {
|
||||
func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt int) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
var index int64
|
||||
for i, s := range soundList {
|
||||
_, ok := ttsins[name]
|
||||
if !ok {
|
||||
return errors.New("不支持设置语音人物" + name)
|
||||
}
|
||||
var index = int64(-1)
|
||||
for i, s := range genshin.SoundList {
|
||||
if s == name {
|
||||
index = int64(i + 1)
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if index == 0 {
|
||||
return errors.New("不支持设置语音人物" + name)
|
||||
if index == -1 {
|
||||
switch name {
|
||||
case extrattsname[0]:
|
||||
index = baiduttsindex
|
||||
case extrattsname[1]:
|
||||
index = ttscnttsindex
|
||||
default:
|
||||
return errors.New("语音人物" + name + "未注册index")
|
||||
}
|
||||
}
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
tts.Lock()
|
||||
defer tts.Unlock()
|
||||
tts.mode[gid] = index
|
||||
return m.SetData(gid, index)
|
||||
(*syncx.Map[int64, int64])(t).Store(gid, index)
|
||||
return m.SetData(gid, (m.GetData(gid)&^0xffff00)|((index<<8)&0xff00)|((int64(baiduper)<<16)&0x0f0000)|((int64(mockingsynt)<<20)&0xf00000))
|
||||
}
|
||||
|
||||
func (tts *ttsmode) getSoundMode(ctx *zero.Ctx) int64 {
|
||||
func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
tts.Lock()
|
||||
defer tts.Unlock()
|
||||
i, ok := tts.mode[gid]
|
||||
i, ok := (*syncx.Map[int64, int64])(t).Load(gid)
|
||||
if !ok {
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
i = m.GetData(gid)
|
||||
i = m.GetData(gid) >> 8
|
||||
}
|
||||
if i <= 0 || i >= int64(len(soundList)) {
|
||||
i = tts.mode[-2905]
|
||||
m := i & 0xff
|
||||
if m < 0 || (m >= int64(len(genshin.SoundList)) && m != baiduttsindex && m != ttscnttsindex) {
|
||||
i, _ = (*syncx.Map[int64, int64])(t).Load(defaultttsindexkey)
|
||||
m = i & 0xff
|
||||
}
|
||||
return i - 1
|
||||
mode := ttsModes[m]
|
||||
ins, ok := ttsins[mode]
|
||||
if !ok || ins == nil {
|
||||
switch mode {
|
||||
case extrattsname[0]:
|
||||
id, sec, _ := strings.Cut(百.k, ",")
|
||||
ins = baidutts.NewBaiduTTS(int(i&0x0f00)>>8, id, sec)
|
||||
case extrattsname[1]:
|
||||
var err error
|
||||
ins, err = ttscn.NewTTSCN("中文(普通话,简体)", ttscnspeakers[int(i&0xf000)>>12], ttscn.KBRates[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default: // 原神
|
||||
k := 原.k
|
||||
if k != "" {
|
||||
ins = genshin.NewGenshin(int(m), 原.k)
|
||||
ttsins[mode] = ins
|
||||
} else {
|
||||
return nil, errors.New("no valid speaker")
|
||||
}
|
||||
}
|
||||
}
|
||||
return ins, nil
|
||||
}
|
||||
|
||||
func (tts *ttsmode) resetSoundMode(ctx *zero.Ctx) error {
|
||||
func (t *ttsmode) resetSoundMode(ctx *zero.Ctx) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
tts.Lock()
|
||||
defer tts.Unlock()
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
tts.mode[gid] = 0
|
||||
return m.SetData(gid, 0) // 重置数据
|
||||
index := m.GetData(defaultttsindexkey)
|
||||
return m.SetData(gid, (m.GetData(gid)&0xff)|((index&^0xff)<<8)) // 重置数据
|
||||
}
|
||||
|
||||
func (tts *ttsmode) setDefaultSoundMode(name string) error {
|
||||
var index int64
|
||||
for i, s := range soundList {
|
||||
func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) error {
|
||||
_, ok := ttsins[name]
|
||||
if !ok {
|
||||
return errors.New("不支持设置语音人物" + name)
|
||||
}
|
||||
index := int64(-1)
|
||||
for i, s := range genshin.SoundList {
|
||||
if s == name {
|
||||
index = int64(i + 1)
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if index == 0 {
|
||||
return errors.New("不支持设置语音人物" + name)
|
||||
if index == -1 {
|
||||
switch name {
|
||||
case extrattsname[0]:
|
||||
index = baiduttsindex
|
||||
case extrattsname[1]:
|
||||
index = ttscnttsindex
|
||||
default:
|
||||
return errors.New("语音人物" + name + "未注册index")
|
||||
}
|
||||
}
|
||||
tts.Lock()
|
||||
defer tts.Unlock()
|
||||
m, ok := control.Lookup(ttsServiceName)
|
||||
m, ok := control.Lookup("tts")
|
||||
if !ok {
|
||||
return errors.New("[tts] service not found")
|
||||
}
|
||||
tts.mode[-2905] = index
|
||||
return m.SetData(-2905, index)
|
||||
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, index)
|
||||
return m.SetData(defaultttsindexkey, (index&0xff)|((int64(baiduper)<<8)&0x0f00)|((int64(mockingsynt)<<12)&0xf000))
|
||||
}
|
||||
|
||||
@@ -2,51 +2,49 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
"github.com/FloatTech/AnimeAPI/tts/genshin"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/pkumza/numcn"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
replyServiceName = "aireply"
|
||||
ttsServiceName = "tts"
|
||||
)
|
||||
var replmd = replymode([]string{"青云客", "小爱", "ChatGPT"})
|
||||
|
||||
var replyModes = [...]string{"青云客", "小爱"}
|
||||
var ttsmd = newttsmode()
|
||||
|
||||
func init() { // 插件主体
|
||||
enOftts := control.Register(ttsServiceName, &ctrl.Options[*zero.Ctx]{
|
||||
ent := control.Register("tts", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "语音回复(大家一起来炼丹)\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n" +
|
||||
"- 设置语音模式[原神人物]\n" +
|
||||
"- 设置默认语音模式[原神人物]\n" +
|
||||
Brief: "人工智能语音回复",
|
||||
Help: "- @Bot 任意文本(任意一句话回复)\n" +
|
||||
"- 设置语音模式[原神人物/百度/TTSCN] 数字(百度/TTSCN说话人)\n" +
|
||||
"- 设置默认语音模式[原神人物/百度/TTSCN] 数字(百度/TTSCN说话人)\n" +
|
||||
"- 恢复成默认语音模式\n" +
|
||||
"当前适用的原神人物含有以下:\n" + list(soundList[:], 5),
|
||||
"- 设置原神语音 api key xxxxxx (key请加开发群获得)\n" +
|
||||
"- 设置百度语音 api id xxxxxx secret xxxxxx (请自行获得)\n" +
|
||||
"当前适用的原神人物含有以下: \n" + list(genshin.SoundList[:], 5) +
|
||||
"\n当前适用的TTSCN人物含有以下(以数字顺序代表): \n" + list(ttscnspeakers[:], 5),
|
||||
PrivateDataFolder: "tts",
|
||||
})
|
||||
tts := newttsmode()
|
||||
enOfreply := control.Register(replyServiceName, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "人工智能回复\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客|小爱]",
|
||||
|
||||
enr := control.Register("aireply", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "人工智能回复",
|
||||
Help: "- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客|小爱|ChatGPT]\n- 设置 ChatGPT api key xxx",
|
||||
PrivateDataFolder: "aireply",
|
||||
})
|
||||
/*************************************************************
|
||||
*******************************AIreply************************
|
||||
*************************************************************/
|
||||
enOfreply.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
|
||||
enr.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
aireply := aireply.NewAIReply(getReplyMode(ctx))
|
||||
reply := message.ParseMessageFromString(aireply.Talk(ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
|
||||
aireply := replmd.getReplyMode(ctx)
|
||||
reply := message.ParseMessageFromString(aireply.Talk(ctx.Event.UserID, ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
|
||||
// 回复
|
||||
time.Sleep(time.Second * 1)
|
||||
if zero.OnlyPublic(ctx) {
|
||||
@@ -56,95 +54,150 @@ func init() { // 插件主体
|
||||
}
|
||||
ctx.Send(reply)
|
||||
})
|
||||
enOfreply.OnPrefix("设置回复模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
enr.OnPrefix("设置回复模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["args"].(string)
|
||||
err := setReplyMode(ctx, param)
|
||||
err := replmd.setReplyMode(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("成功"))
|
||||
})
|
||||
/*************************************************************
|
||||
***********************tts************************************
|
||||
*************************************************************/
|
||||
enOftts.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
|
||||
enr.OnRegex(`^设置\s*ChatGPT\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := ཆཏ.set(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置成功"))
|
||||
})
|
||||
|
||||
endpre := regexp.MustCompile(`\pP$`)
|
||||
ent.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := ctx.ExtractPlainText()
|
||||
// 获取回复模式
|
||||
r := aireply.NewAIReply(getReplyMode(ctx))
|
||||
r := replmd.getReplyMode(ctx)
|
||||
// 获取回复的文本
|
||||
reply := r.TalkPlain(msg, zero.BotConfig.NickName[0])
|
||||
reply := r.TalkPlain(ctx.Event.UserID, msg, zero.BotConfig.NickName[0])
|
||||
// 获取语音
|
||||
index := tts.getSoundMode(ctx)
|
||||
record := message.Record(fmt.Sprintf(cnapi, index, url.QueryEscape(
|
||||
// 将数字转文字
|
||||
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)
|
||||
}),
|
||||
))).Add("cache", 0)
|
||||
speaker, err := ttsmd.getSoundMode(ctx)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
rec, err := speaker.Speak(ctx.Event.UserID, func() string {
|
||||
if !endpre.MatchString(reply) {
|
||||
return reply + "。"
|
||||
}
|
||||
return reply
|
||||
})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
|
||||
return
|
||||
}
|
||||
// 发送语音
|
||||
if ID := ctx.SendChain(record); ID.ID() == 0 {
|
||||
if id := ctx.SendChain(message.Record(rec)); id.ID() == 0 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
|
||||
}
|
||||
})
|
||||
enOftts.OnRegex(`^设置语音模式(.*)$`, zero.AdminPermission, func(ctx *zero.Ctx) bool {
|
||||
|
||||
ent.OnRegex(`^设置语音模式\s*([\S\D]*)\s+(\d*)$`, zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
if _, ok := testRecord[param]; !ok {
|
||||
return false
|
||||
num := ctx.State["regex_matched"].([]string)[2]
|
||||
n := 0
|
||||
var err error
|
||||
if num != "" {
|
||||
n, err = strconv.Atoi(num)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
return true
|
||||
}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
// 保存设置
|
||||
err := tts.setSoundMode(ctx, param)
|
||||
logrus.Debugln("[tts] t.setSoundMode( ctx", param, n, n, ")")
|
||||
err = ttsmd.setSoundMode(ctx, param, n, n)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
// 设置验证
|
||||
i := tts.getSoundMode(ctx)
|
||||
if _, ok := testRecord[soundList[i]]; !ok {
|
||||
ctx.SendChain(message.Text("配置的语音人物数据丢失!请重新设置语音人物。"))
|
||||
return
|
||||
if banner, ok := genshin.TestRecord[param]; ok {
|
||||
logrus.Debugln("[tts] banner:", banner, "get sound mode...")
|
||||
// 设置验证
|
||||
speaker, err := ttsmd.getSoundMode(ctx)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[tts] got sound mode, speaking...")
|
||||
rec, err := speaker.Speak(ctx.Event.UserID, func() string { return banner })
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[tts] sending...")
|
||||
if id := ctx.SendChain(message.Record(rec).Add("cache", 0)); id.ID() == 0 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
}
|
||||
record := message.Record(fmt.Sprintf(cnapi, i, url.QueryEscape(testRecord[soundList[i]]))).Add("cache", 0)
|
||||
if ID := ctx.SendChain(record); ID.ID() == 0 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置失败!无法发送测试语音,请重试。"))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功"))
|
||||
})
|
||||
enOftts.OnRegex(`^设置默认语音模式(.*)$`, zero.SuperUserPermission, func(ctx *zero.Ctx) bool {
|
||||
|
||||
ent.OnRegex(`^设置默认语音模式\s*([\S\D]*)\s+(\d*)$`, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
if _, ok := testRecord[param]; !ok {
|
||||
return false
|
||||
num := ctx.State["regex_matched"].([]string)[2]
|
||||
n := 0
|
||||
var err error
|
||||
if num != "" {
|
||||
n, err = strconv.Atoi(num)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
return true
|
||||
}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
// 保存设置
|
||||
err := tts.setDefaultSoundMode(param)
|
||||
err = ttsmd.setDefaultSoundMode(param, n, n)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功"))
|
||||
})
|
||||
enOftts.OnFullMatch("恢复成默认语音模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := tts.resetSoundMode(ctx)
|
||||
|
||||
ent.OnFullMatch("恢复成默认语音模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := ttsmd.resetSoundMode(ctx)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
// 设置验证
|
||||
index := tts.getSoundMode(ctx)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前为", soundList[index]))
|
||||
speaker, err := ttsmd.getSoundMode(ctx)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前为", speaker))
|
||||
})
|
||||
|
||||
ent.OnRegex(`^设置原神语音\s*api\s*key\s*([0-9a-zA-Z-_]{54}==)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := 原.set(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置成功"))
|
||||
})
|
||||
|
||||
ent.OnRegex(`^设置百度语音\s*api\s*id\s*(.*)\s*secret\s*(.*)\s*$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := 百.set(ctx.State["regex_matched"].([]string)[1] + "," + ctx.State["regex_matched"].([]string)[2])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置成功"))
|
||||
})
|
||||
}
|
||||
|
||||
29
plugin/ai_reply/model.go
Normal file
29
plugin/ai_reply/model.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
)
|
||||
|
||||
type apikeystore struct {
|
||||
k string
|
||||
p string
|
||||
}
|
||||
|
||||
func newapikeystore(p string) (s apikeystore) {
|
||||
s.p = p
|
||||
if file.IsExist(p) {
|
||||
data, err := os.ReadFile(p)
|
||||
if err == nil {
|
||||
s.k = binary.BytesToString(data)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *apikeystore) set(k string) error {
|
||||
s.k = k
|
||||
return os.WriteFile(s.p, binary.StringToBytes(k), 0644)
|
||||
}
|
||||
@@ -2,11 +2,9 @@
|
||||
package aipaint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"image"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
@@ -16,7 +14,6 @@ import (
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/img/writer"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
@@ -51,96 +48,51 @@ func (r *result) String() string {
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("aipaint", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "ai绘图\n" +
|
||||
"- [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx\n" +
|
||||
Brief: "ai绘图",
|
||||
Help: "- [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx\n" +
|
||||
"- [ ai高级绘图 | 高级生成色图 | 高级生成涩图 | ai高级画图 ] [prompt]\n" +
|
||||
"- [ 以图绘图 | 以图生图 | 以图画图 ] xxx [图片]|@xxx|[qq号]\n" +
|
||||
"- 设置ai绘图配置 [server] [token]\n" +
|
||||
"例: 设置ai绘图配置 http://91.217.139.190:5010 abc\n" +
|
||||
"- 设置ai绘图撤回时间90s\n" +
|
||||
"- 查看ai绘图配置\n" +
|
||||
"Tips: 使用前请先前往 http://91.217.139.190:5010/token 按提示获取token" +
|
||||
"设置token示例(请确保是主人并且响应): 设置ai绘图配置 http://91.217.139.190:5010 [token] (中括号无需输入)\n" +
|
||||
"参考服务器 http://91.217.139.190:5010, http://91.216.169.75:5010, http://185.80.202.180:5010\n" +
|
||||
"通过 http://91.217.139.190:5010/token 获取token\n" +
|
||||
"[prompt]参数如下\n" +
|
||||
"tags:tag词条\nntags:ntag词条\nshape:[Portrait|Landscape|Square]\nscale:[6:20]\nseed:种子\n" +
|
||||
"参数与参数内容用:连接,每个参数之间用回车或者&分割",
|
||||
"tags:tag词条\nntags:ntag词条\nshape:[Portrait|Landscape|Square]\nscale:[6:20]\nseed:种子\nstrength:[0-1] 建议0-0.7\nnoise:[0-1] 建议0-0.15" +
|
||||
"参数与参数内容用:连接,每个参数之间用回车分割",
|
||||
PrivateDataFolder: "aipaint",
|
||||
})
|
||||
datapath = file.BOTPATH + "/" + engine.DataFolder()
|
||||
if file.IsNotExist(cfg.file) {
|
||||
s := serverConfig{}
|
||||
data, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = os.WriteFile(cfg.file, data, 0666)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
engine.OnPrefixGroup([]string{`ai绘图`, `生成色图`, `生成涩图`, `ai画图`}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
server, token, err := cfg.load()
|
||||
err := cfg.load()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
args := ctx.State["args"].(string)
|
||||
data, err := web.GetData(server + fmt.Sprintf(aipaintTxt2ImgURL, token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20")))))
|
||||
data, err := web.GetData(cfg.BaseURL + fmt.Sprintf(aipaintTxt2ImgURL, cfg.Token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20")))))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
sendAiImg(ctx, data)
|
||||
})
|
||||
engine.OnRegex(`^(以图绘图|以图生图|以图画图)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
server, token, err := cfg.load()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
||||
args := strings.TrimSuffix(strings.TrimPrefix(list[0], list[1]), list[2])
|
||||
if args == "" {
|
||||
ctx.SendChain(message.Text("ERROR: 以图绘图必须添加tag"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
postURL := server + fmt.Sprintf(aipaintImg2ImgURL, token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20"))))
|
||||
|
||||
f, err := os.Open(c.headimgsdir[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
img, _, err := image.Decode(f)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
imageShape := ""
|
||||
switch {
|
||||
case img.Bounds().Dx() > img.Bounds().Dy():
|
||||
imageShape = "Landscape"
|
||||
case img.Bounds().Dx() == img.Bounds().Dy():
|
||||
imageShape = "Square"
|
||||
default:
|
||||
imageShape = "Portrait"
|
||||
}
|
||||
|
||||
// 图片转base64
|
||||
base64Bytes, err := writer.ToBase64(img)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
data, err := web.PostData(postURL+"&shape="+imageShape, "text/plain", bytes.NewReader(base64Bytes))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
sendAiImg(ctx, data)
|
||||
sendAiImg(ctx, data, cfg.Interval)
|
||||
})
|
||||
engine.OnPrefixGroup([]string{`ai高级绘图`, `高级生成色图`, `高级生成涩图`, `ai高级画图`}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
server, token, err := cfg.load()
|
||||
err := cfg.load()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -156,13 +108,13 @@ func init() { // 插件主体
|
||||
if len(value) > 1 {
|
||||
if value[0] == "R18" && value[1] == "1" {
|
||||
value[1] = "0"
|
||||
ctx.SendChain(message.Text("不准涩涩!已将R18设置为0。"))
|
||||
ctx.SendChain(message.Text("不准涩涩! 已将R18设置为0. "))
|
||||
}
|
||||
tags[value[0]] = strings.Join(value[1:], ":")
|
||||
}
|
||||
}
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
apiurl := "/got_image?token=" + token
|
||||
apiurl := "/got_image?token=" + cfg.Token
|
||||
if _, ok := tags["tags"]; ok {
|
||||
apiurl += "&tags=" + url.QueryEscape(strings.ReplaceAll(strings.TrimSpace(tags["tags"]), " ", "%20"))
|
||||
}
|
||||
@@ -181,26 +133,66 @@ func init() { // 插件主体
|
||||
if _, ok := tags["seed"]; ok {
|
||||
apiurl += "&seed=" + url.QueryEscape(strings.TrimSpace(tags["seed"]))
|
||||
}
|
||||
data, err := web.GetData(server + apiurl)
|
||||
if _, ok := tags["strength"]; ok {
|
||||
apiurl += "&strength=" + url.QueryEscape(strings.TrimSpace(tags["strength"]))
|
||||
}
|
||||
if _, ok := tags["noise"]; ok {
|
||||
apiurl += "&noise=" + url.QueryEscape(strings.TrimSpace(tags["noise"]))
|
||||
}
|
||||
data, err := web.GetData(cfg.BaseURL + apiurl)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
sendAiImg(ctx, data)
|
||||
sendAiImg(ctx, data, cfg.Interval)
|
||||
})
|
||||
engine.OnRegex(`^设置ai绘图配置\s(.*[^\s$])\s(.+)$`, zero.SuperUserPermission).SetBlock(true).
|
||||
engine.OnRegex(`^设置ai绘图配置\s(.*[^\s$])\s(.+)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
regexMatched := ctx.State["regex_matched"].([]string)
|
||||
err := cfg.save(regexMatched[1], regexMatched[2])
|
||||
err := cfg.load()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功设置server为", regexMatched[1], ", token为", regexMatched[2]))
|
||||
err = cfg.update(regexMatched[1], regexMatched[2], cfg.Interval)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功设置\nbase_url: ", cfg.BaseURL, "\ntoken: ", cfg.Token, "\ninterval: ", cfg.Interval))
|
||||
})
|
||||
engine.OnRegex(`^设置ai绘图撤回时间(\d{1,3})s$`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
regexMatched := ctx.State["regex_matched"].([]string)
|
||||
interval, err := strconv.Atoi(regexMatched[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
err = cfg.load()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
err = cfg.update(cfg.BaseURL, cfg.Token, interval)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功设置撤回时间为", cfg.Interval, "s"))
|
||||
})
|
||||
engine.OnFullMatch(`查看ai绘图配置`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := cfg.load()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("base_url: ", cfg.BaseURL, "\ntoken: ", cfg.Token, "\ninterval: ", cfg.Interval))
|
||||
})
|
||||
}
|
||||
|
||||
func sendAiImg(ctx *zero.Ctx, data []byte) {
|
||||
func sendAiImg(ctx *zero.Ctx, data []byte, interval int) {
|
||||
var loadData string
|
||||
if predictRe.MatchString(binary.BytesToString(data)) {
|
||||
loadData = predictRe.FindStringSubmatch(binary.BytesToString(data))[0]
|
||||
@@ -223,11 +215,10 @@ func sendAiImg(ctx *zero.Ctx, data []byte) {
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(r.String())))
|
||||
if mid := ctx.Send(m); mid.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
} else {
|
||||
} else if interval > 0 {
|
||||
go func(i message.MessageID) {
|
||||
time.Sleep(90 * time.Second)
|
||||
time.Sleep(time.Duration(interval) * time.Second)
|
||||
ctx.DeleteMessage(i)
|
||||
}(mid)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import (
|
||||
|
||||
// 配置结构体
|
||||
type serverConfig struct {
|
||||
BaseURL string `json:"base_url"`
|
||||
Token string `json:"token"`
|
||||
file string
|
||||
BaseURL string `json:"base_url"`
|
||||
Token string `json:"token"`
|
||||
Interval int `json:"interval"`
|
||||
file string
|
||||
}
|
||||
|
||||
func newServerConfig(file string) *serverConfig {
|
||||
@@ -21,9 +22,14 @@ func newServerConfig(file string) *serverConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *serverConfig) save(baseURL, token string) (err error) {
|
||||
cfg.BaseURL = baseURL
|
||||
cfg.Token = token
|
||||
func (cfg *serverConfig) update(baseURL, token string, interval int) (err error) {
|
||||
if baseURL != "" {
|
||||
cfg.BaseURL = baseURL
|
||||
}
|
||||
if token != "" {
|
||||
cfg.Token = token
|
||||
}
|
||||
cfg.Interval = interval
|
||||
reader, err := os.Create(cfg.file)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -32,10 +38,8 @@ func (cfg *serverConfig) save(baseURL, token string) (err error) {
|
||||
return json.NewEncoder(reader).Encode(cfg)
|
||||
}
|
||||
|
||||
func (cfg *serverConfig) load() (aipaintServer, token string, err error) {
|
||||
if cfg.BaseURL != "" && cfg.Token != "" {
|
||||
aipaintServer = cfg.BaseURL
|
||||
token = cfg.Token
|
||||
func (cfg *serverConfig) load() (err error) {
|
||||
if cfg.BaseURL != "" && cfg.Token != "" && cfg.Interval != 0 {
|
||||
return
|
||||
}
|
||||
if file.IsNotExist(cfg.file) {
|
||||
@@ -48,7 +52,5 @@ func (cfg *serverConfig) load() (aipaintServer, token string, err error) {
|
||||
}
|
||||
defer reader.Close()
|
||||
err = json.NewDecoder(reader).Decode(cfg)
|
||||
aipaintServer = cfg.BaseURL
|
||||
token = cfg.Token
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/process"
|
||||
)
|
||||
|
||||
type context struct {
|
||||
@@ -27,13 +28,14 @@ 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)
|
||||
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif")
|
||||
} else {
|
||||
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
88
plugin/aipaint/img2img.go
Normal file
88
plugin/aipaint/img2img.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Package aipaint ai绘图
|
||||
package aipaint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("img2img", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Brief: "以图绘图",
|
||||
Help: "- [ 以图绘图 | 以图生图 | 以图画图 ] xxx [图片]|@xxx|[qq号]\n" +
|
||||
"- 官方以图绘图api已失效 需要自建api 其他配置参数同ai绘图",
|
||||
PrivateDataFolder: "img2img",
|
||||
})
|
||||
datapath = file.BOTPATH + "/" + engine.DataFolder()
|
||||
engine.OnRegex(`^(以图绘图|以图生图|以图画图)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := cfg.load()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
||||
args := strings.TrimSuffix(strings.TrimPrefix(list[0], list[1]), list[2])
|
||||
if args == "" {
|
||||
ctx.SendChain(message.Text("ERROR: 以图绘图必须添加tag"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
postURL := cfg.BaseURL + fmt.Sprintf(aipaintImg2ImgURL, cfg.Token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20"))))
|
||||
|
||||
f, err := os.Open(c.headimgsdir[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
img, _, err := image.Decode(f)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
imageShape := ""
|
||||
switch {
|
||||
case img.Bounds().Dx() > img.Bounds().Dy():
|
||||
imageShape = "Landscape"
|
||||
case img.Bounds().Dx() == img.Bounds().Dy():
|
||||
imageShape = "Square"
|
||||
default:
|
||||
imageShape = "Portrait"
|
||||
}
|
||||
|
||||
// 图片转base64
|
||||
base64Bytes, err := imgfactory.ToBase64(img)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
data, err := web.PostData(postURL+"&shape="+imageShape, "text/plain", bytes.NewReader(base64Bytes))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
sendAiImg(ctx, data, cfg.Interval)
|
||||
})
|
||||
}
|
||||
@@ -19,8 +19,8 @@ const (
|
||||
func init() { // 插件主体
|
||||
control.Register("aiwife", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIWife\n" +
|
||||
"- waifu | 随机waifu",
|
||||
Brief: "ai随机生成老婆",
|
||||
Help: "- waifu | 随机waifu",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatchGroup([]string{"waifu", "随机waifu"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
miku := rand.Intn(100000) + 1
|
||||
|
||||
@@ -17,9 +17,9 @@ const (
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("alipayvoice", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "支付宝到账语音\n" +
|
||||
"- 支付宝到账 1",
|
||||
DisableOnDefault: false,
|
||||
Brief: "支付宝到账语音",
|
||||
Help: "- 支付宝到账 1",
|
||||
PrivateDataFolder: "alipayvoice",
|
||||
})
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ func onDel(uid int64, _ struct{}) {
|
||||
func init() {
|
||||
engine := control.Register("antiabuse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "违禁词检测\n- /[添加|删除|查看]违禁词",
|
||||
Brief: "违禁词检测",
|
||||
Help: "- /[添加|删除|查看]违禁词",
|
||||
PrivateDataFolder: "anti_abuse",
|
||||
})
|
||||
|
||||
|
||||
@@ -6,66 +6,87 @@ Package atri 本文件基于 https://github.com/Kyomotoi/ATRI
|
||||
package atri
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/floatbox/process"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
)
|
||||
|
||||
const (
|
||||
// 服务名
|
||||
servicename = "atri"
|
||||
// ATRI 表情的 codechina 镜像
|
||||
res = "https://gitcode.net/u011570312/zbpdata/-/raw/main/Atri/"
|
||||
)
|
||||
type datagetter func(string, bool) ([]byte, error)
|
||||
|
||||
func (dgtr datagetter) randImage(file ...string) message.MessageSegment {
|
||||
data, err := dgtr(file[rand.Intn(len(file))], true)
|
||||
if err != nil {
|
||||
return message.Text("ERROR: ", err)
|
||||
}
|
||||
return message.ImageBytes(data)
|
||||
}
|
||||
|
||||
func (dgtr datagetter) randRecord(file ...string) message.MessageSegment {
|
||||
data, err := dgtr(file[rand.Intn(len(file))], true)
|
||||
if err != nil {
|
||||
return message.Text("ERROR: ", err)
|
||||
}
|
||||
return message.Record("base64://" + base64.StdEncoding.EncodeToString(data))
|
||||
}
|
||||
|
||||
func randText(text ...string) message.MessageSegment {
|
||||
return message.Text(text[rand.Intn(len(text))])
|
||||
}
|
||||
|
||||
// isAtriSleeping 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func isAtriSleeping(*zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register(servicename, &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.Register("atri", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "atri人格文本回复",
|
||||
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
|
||||
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢 | 爱你 | 爱 | suki | daisuki | すき | 好き | 贴贴 | 老婆 | 亲一个 | mua\n" +
|
||||
"- 草你妈 | 操你妈 | 脑瘫 | 废柴 | fw | 废物 | 战斗 | 爬 | 爪巴 | sb | SB | 傻B\n- 早安 | 早哇 | 早上好 | ohayo | 哦哈哟 | お早う | 早好 | 早 | 早早早\n" +
|
||||
"- 中午好 | 午安 | 午好\n- 晚安 | oyasuminasai | おやすみなさい | 晚好 | 晚上好\n- 高性能 | 太棒了 | すごい | sugoi | 斯国一 | よかった\n" +
|
||||
"- 没事 | 没关系 | 大丈夫 | 还好 | 不要紧 | 没出大问题 | 没伤到哪\n- 好吗 | 是吗 | 行不行 | 能不能 | 可不可以\n- 啊这\n- 我好了\n- ? | ? | ¿\n" +
|
||||
"- 离谱\n- 答应我",
|
||||
PublicDataFolder: "Atri",
|
||||
OnEnable: func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
|
||||
},
|
||||
OnDisable: func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("Zzz……Zzz……"))
|
||||
},
|
||||
})
|
||||
engine.OnFullMatch("萝卜子", isAtriSleeping).SetBlock(true).
|
||||
engine.UsePreHandler(isAtriSleeping)
|
||||
var dgtr datagetter = engine.GetLazyData
|
||||
engine.OnFullMatch("萝卜子").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("萝卜子是对机器人的蔑称!", "是亚托莉......萝卜子可是对机器人的蔑称"))
|
||||
case 1:
|
||||
ctx.SendChain(randRecord("RocketPunch.amr"))
|
||||
ctx.SendChain(dgtr.randRecord("RocketPunch.amr"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
|
||||
ctx.SendChain(dgtr.randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
|
||||
ctx.SendChain(dgtr.randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
process.SleepAbout1sTo2s()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
@@ -106,7 +127,6 @@ func init() { // 插件主体
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
if now > 11 && now < 15 { // 中午
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"午安w",
|
||||
"午觉要好好睡哦,ATRI会陪伴在你身旁的w",
|
||||
@@ -118,7 +138,6 @@ func init() { // 插件主体
|
||||
engine.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい", "晚好", "晚上好"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
process.SleepAbout1sTo2s()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
@@ -158,9 +177,8 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
"当然,我是高性能的嘛~!",
|
||||
"小事一桩,我是高性能的嘛",
|
||||
@@ -179,9 +197,8 @@ func init() { // 插件主体
|
||||
"呣......我的高性能,毫无遗憾地施展出来了......",
|
||||
))
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
"当然,我是高性能的嘛~!",
|
||||
"没事没事,因为我是高性能的嘛!嗯哼!",
|
||||
@@ -194,67 +211,42 @@ func init() { // 插件主体
|
||||
))
|
||||
})
|
||||
|
||||
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, isAtriSleeping).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("YES.png", "NO.jpg"))
|
||||
ctx.SendChain(dgtr.randImage("YES.png", "NO.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"啊这"}, isAtriSleeping).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"啊这"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
|
||||
ctx.SendChain(dgtr.randImage("AZ.jpg", "AZ1.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"我好了"}, isAtriSleeping).SetBlock(true).
|
||||
engine.OnKeywordGroup([]string{"我好了"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText("不许好!", "憋回去!"))
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"?", "?", "¿"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("?", "?", "嗯?", "(。´・ω・)ん?", "ん?"))
|
||||
case 1, 2:
|
||||
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeyword("离谱", isAtriSleeping).SetBlock(true).
|
||||
engine.OnFullMatchGroup([]string{"?", "?", "¿"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("?", "?", "嗯?", "(。´・ω・)ん?", "ん?"))
|
||||
case 1, 2:
|
||||
ctx.SendChain(randImage("WH.jpg"))
|
||||
ctx.SendChain(dgtr.randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeyword("答应我", isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
engine.OnKeyword("离谱").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("?", "?", "嗯?", "(。´・ω・)ん?", "ん?"))
|
||||
case 1, 2:
|
||||
ctx.SendChain(dgtr.randImage("WH.jpg"))
|
||||
}
|
||||
})
|
||||
engine.OnKeyword("答应我", zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText("我无法回应你的请求"))
|
||||
})
|
||||
}
|
||||
|
||||
func randText(text ...string) message.MessageSegment {
|
||||
return message.Text(text[rand.Intn(len(text))])
|
||||
}
|
||||
|
||||
func randImage(file ...string) message.MessageSegment {
|
||||
return message.Image(res + file[rand.Intn(len(file))])
|
||||
}
|
||||
|
||||
func randRecord(file ...string) message.MessageSegment {
|
||||
return message.Record(res + file[rand.Intn(len(file))])
|
||||
}
|
||||
|
||||
// isAtriSleeping 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func isAtriSleeping(ctx *zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
29
plugin/autowithdraw/main.go
Normal file
29
plugin/autowithdraw/main.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package autowithdraw 触发者撤回时也自动撤回
|
||||
package autowithdraw
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/floatbox/process"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("autowithdraw", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "触发者撤回时也自动撤回",
|
||||
Help: "- 撤回一条消息\n",
|
||||
}).OnNotice(func(ctx *zero.Ctx) bool {
|
||||
return ctx.Event.NoticeType == "group_recall" || ctx.Event.NoticeType == "friend_recall"
|
||||
}).SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
||||
id, ok := ctx.Event.MessageID.(int64)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for _, msg := range zero.GetTriggeredMessages(message.NewMessageIDFromInteger(id)) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.DeleteMessage(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
func init() {
|
||||
en := control.Register("base16384", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "base16384加解密\n" +
|
||||
"- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
|
||||
Brief: "base16384加解密",
|
||||
Help: "- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
|
||||
})
|
||||
en.OnRegex(`^加密\s*(.+)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
@@ -1,27 +1,60 @@
|
||||
// Package baidu 百度一下
|
||||
// Package baidu 百度百科
|
||||
package baidu
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
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"
|
||||
)
|
||||
|
||||
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)))
|
||||
}
|
||||
})
|
||||
const (
|
||||
duURL = "https://api.a20safe.com/api.php?api=21&key=%s&text=%s" // api地址
|
||||
wikiURL = "https://api.a20safe.com/api.php?api=23&key=%s&text=%s"
|
||||
key = "7d06a110e9e20a684e02934549db1d3d"
|
||||
)
|
||||
|
||||
type result struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data []struct {
|
||||
Content string `json:"content"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func init() { // 主函数
|
||||
en := control.Register("baidu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "百科\n" +
|
||||
"- 百度/百科/维基/wiki[关键字]",
|
||||
})
|
||||
en.OnRegex(`^(百度|维基|百科|wiki)\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
var es []byte
|
||||
var err error
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "百度", "百科":
|
||||
es, err = web.GetData(fmt.Sprintf(duURL, key, ctx.State["regex_matched"].([]string)[2])) // 将网站返回结果赋值
|
||||
case "wiki", "维基":
|
||||
es, err = web.GetData(fmt.Sprintf(wikiURL, key, ctx.State["regex_matched"].([]string)[2])) // 将网站返回结果赋值
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
var r result // r数组
|
||||
err = json.Unmarshal(es, &r) // 填api返回结果,struct地址
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
if r.Code == 0 && len(r.Data) > 0 {
|
||||
ctx.SendChain(message.Text(r.Data[0].Content)) // 输出提取后的结果
|
||||
} else {
|
||||
ctx.SendChain(message.Text("API访问错误"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,113 +4,51 @@ package baiduaudit
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Baidu-AIP/golang-sdk/aip/censor"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 服务网址:https://console.bce.baidu.com/ai/?_=1665977657185#/ai/antiporn/overview/index
|
||||
// 返回参数说明:https://cloud.baidu.com/doc/ANTIPORN/s/Nk3h6xbb2
|
||||
type baiduRes struct {
|
||||
LogID int `json:"log_id"` // 请求唯一id
|
||||
Conclusion string `json:"conclusion"` // 审核结果,可取值:合规、不合规、疑似、审核失败
|
||||
ConclusionType int `json:"conclusionType"` // 审核结果类型,可取值1.合规,2.不合规,3.疑似,4.审核失败
|
||||
Data []auditData `json:"data"`
|
||||
ErrorCode int `json:"error_code"` // 错误提示码,失败才返回,成功不返回
|
||||
ErrorMsg string `json:"error_msg"` // 错误提示信息,失败才返回,成功不返回
|
||||
}
|
||||
|
||||
type auditData struct {
|
||||
Type int `json:"type"` // 审核主类型,11:百度官方违禁词库、12:文本反作弊、13:自定义文本黑名单、14:自定义文本白名单
|
||||
SubType int `json:"subType"` // 审核子类型,0:含多种类型,具体看官方链接,1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
|
||||
Conclusion string `json:"conclusion"` // 审核结果,可取值:合规、不合规、疑似、审核失败
|
||||
ConclusionType int `json:"conclusionType"` // 审核结果类型,可取值1.合规,2.不合规,3.疑似,4.审核失败
|
||||
Msg string `json:"msg"` // 不合规项描述信息
|
||||
Hits []hit `json:"hits"`
|
||||
} // 不合规/疑似/命中白名单项详细信息。响应成功并且conclusion为疑似或不合规或命中白名单时才返回,响应失败或conclusion为合规且未命中白名单时不返回。
|
||||
|
||||
type hit struct {
|
||||
DatasetName string `json:"datasetName"` // 违规项目所属数据集名称
|
||||
Words []string `json:"words"` // 送检文本命中词库的关键词(备注:建议参考新字段“wordHitPositions”,包含信息更丰富:关键词以及对应的位置及标签信息)
|
||||
Probability float64 `json:"probability,omitempty"` // 不合规项置信度
|
||||
} // 送检文本违规原因的详细信息
|
||||
type keyConfig struct {
|
||||
Key1 string `json:"key1"` // 百度云服务内容审核key存储
|
||||
Key2 string `json:"key2"` // 百度云服务内容审核key存储
|
||||
Groups map[int64]group `json:"groups"` // 群配置存储
|
||||
}
|
||||
|
||||
type group struct {
|
||||
Enable EnableMark // 是否启用内容审核
|
||||
TextAudit EnableMark // 文本检测
|
||||
ImageAudit EnableMark // 图像检测
|
||||
DMRemind EnableMark // 撤回提示
|
||||
MoreRemind EnableMark // 详细违规提示
|
||||
DMBAN EnableMark // 撤回后禁言
|
||||
BANTimeAddEnable EnableMark // 禁言累加
|
||||
BANTime int64 // 标准禁言时间,禁用累加,但开启禁言的的情况下采用该值
|
||||
MaxBANTimeAddRange int64 // 最大禁言时间累加范围,最高禁言时间
|
||||
BANTimeAddTime int64 // 禁言累加时间,该值是开启禁累加功能后,再次触发时,根据被禁次数X该值计算出的禁言时间
|
||||
WhiteListType [8]bool // 类型白名单,处于白名单类型的违规,不会被触发 0:含多种类型,具体看官方链接,1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
|
||||
AuditHistory map[int64]auditHistory // 被封禁用户列表
|
||||
}
|
||||
|
||||
// EnableMark 启用:●,禁用:○
|
||||
type EnableMark bool
|
||||
|
||||
// String 打印启用状态
|
||||
func (em EnableMark) String() string {
|
||||
if em {
|
||||
return "开启"
|
||||
}
|
||||
return "关闭"
|
||||
}
|
||||
|
||||
type auditHistory struct {
|
||||
Count int64 `json:"key2"` // 被禁次数
|
||||
ResList []baiduRes `json:"reslist"` // 禁言原因
|
||||
}
|
||||
|
||||
var bdcli *censor.ContentCensorClient // 百度云审核服务Client
|
||||
var typetext = [8]string{
|
||||
0: "默认违禁词库",
|
||||
1: "违禁违规",
|
||||
2: "文本色情",
|
||||
3: "敏感信息",
|
||||
4: "恶意推广",
|
||||
5: "低俗辱骂",
|
||||
6: "恶意推广-联系方式",
|
||||
7: "恶意推广-软文推广",
|
||||
} // 文本类型
|
||||
|
||||
var (
|
||||
config keyConfig // 插件配置
|
||||
configinit bool // 配置初始化
|
||||
configpath string // 配置路径
|
||||
bdcli *censor.ContentCensorClient // 百度云审核服务Client
|
||||
txttyp = [...]string{
|
||||
0: "默认违禁词库",
|
||||
1: "违禁违规",
|
||||
2: "文本色情",
|
||||
3: "敏感信息",
|
||||
4: "恶意推广",
|
||||
5: "低俗辱骂",
|
||||
6: "恶意推广-联系方式",
|
||||
7: "恶意推广-软文推广",
|
||||
} // 文本类型
|
||||
config = newconfig() // 插件配置
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("baiduaudit", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "##该功能来自百度内容审核,需购买相关服务,并创建app##\n" +
|
||||
Brief: "百度内容审核",
|
||||
Help: "##该功能来自百度内容审核, 需购买相关服务, 并创建app##\n" +
|
||||
"- 获取BDAKey\n" +
|
||||
"- 配置BDAKey [API key] [Secret Key]\n" +
|
||||
"- 开启/关闭内容审核\n" +
|
||||
"- 开启/关闭撤回提示\n" +
|
||||
"- 开启/关闭详细提示\n" +
|
||||
"- 开启/关闭撤回禁言\n" +
|
||||
"##禁言时间设置## 禁言时间计算方式为:禁言次数*每次禁言累加时间,当达到最大禁言时间时,再次触发按最大禁言时间计算\n" +
|
||||
"##禁言时间设置## 禁言时间计算方式为:禁言次数*每次禁言累加时间,当达到最大禁言时间时, 再次触发按最大禁言时间计算\n" +
|
||||
"- 开启/关闭禁言累加\n" +
|
||||
"- 设置撤回禁言时间[分钟,默认:1]\n" +
|
||||
"- 设置最大禁言时间[分钟,默认:60,最大43200]\n" +
|
||||
"- 设置每次累加时间[分钟,默认:1]\n" +
|
||||
"- 设置撤回禁言时间[分钟, 默认:1]\n" +
|
||||
"- 设置最大禁言时间[分钟, 默认:60,最大43200]\n" +
|
||||
"- 设置每次累加时间[分钟, 默认:1]\n" +
|
||||
"##检测类型设置## 类型编号列表:[1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广]\n" +
|
||||
"- 查看检测类型\n" +
|
||||
"- 查看检测配置\n" +
|
||||
@@ -119,15 +57,19 @@ func init() {
|
||||
"- 开启/关闭文本检测\n" +
|
||||
"- 开启/关闭图像检测\n" +
|
||||
"##测试功能##\n" +
|
||||
"- 测试文本检测[文本内容]\n" +
|
||||
"- 测试图像检测[图片]\n",
|
||||
"- ^文本检测[文本内容]\n" +
|
||||
"- ^图像检测[图片]\n",
|
||||
PrivateDataFolder: "baiduaudit",
|
||||
})
|
||||
configpath = engine.DataFolder() + "config.json"
|
||||
loadConfig()
|
||||
if configinit {
|
||||
|
||||
configpath := engine.DataFolder() + "config.json"
|
||||
err := config.load(configpath)
|
||||
if err != nil {
|
||||
logrus.Warnln("[baiduaudit] 加载配置错误:", err)
|
||||
} else if config.Key1 != "" && config.Key2 != "" {
|
||||
bdcli = censor.NewClient(config.Key1, config.Key2)
|
||||
}
|
||||
|
||||
engine.OnFullMatch("获取BDAKey", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("接口key创建网址:\n" +
|
||||
@@ -136,29 +78,33 @@ func init() {
|
||||
"https://console.bce.baidu.com/ai/?_=1665977657185#/ai/antiporn/overview/resource/getFree"))
|
||||
})
|
||||
|
||||
engine.OnRegex("^查看检测(类型|配置)$", zero.AdminPermission, clientCheck).SetBlock(true).
|
||||
engine.OnRegex("^查看检测(类型|配置)$", zero.AdminPermission, hasinit).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 获取群配置
|
||||
group := getGroup(ctx.Event.GroupID)
|
||||
var msgs string
|
||||
group := config.groupof(ctx.Event.GroupID)
|
||||
msg := ""
|
||||
k1 := ctx.State["regex_matched"].([]string)[1]
|
||||
if k1 == "类型" {
|
||||
msgs += "本群检测类型:"
|
||||
find := false
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString("本群检测类型:")
|
||||
found := false
|
||||
// 遍历群检测类型名单
|
||||
for i, v := range group.WhiteListType {
|
||||
for i, v := range group.copyWhiteListType() {
|
||||
if !v {
|
||||
find = true
|
||||
msgs += fmt.Sprint("\n", i, ".", typetext[i])
|
||||
found = true
|
||||
sb.WriteByte('\n')
|
||||
sb.WriteString(strconv.Itoa(i))
|
||||
sb.WriteByte('.')
|
||||
sb.WriteString(txttyp[i])
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
msgs += "无"
|
||||
if !found {
|
||||
sb.WriteString("无")
|
||||
}
|
||||
|
||||
msg = sb.String()
|
||||
} else {
|
||||
// 生成配置文本
|
||||
msgs = fmt.Sprintf("本群配置:\n"+
|
||||
msg = fmt.Sprintf("本群配置:\n"+
|
||||
"内容审核:%s\n"+
|
||||
"-文本:%s\n"+
|
||||
"-图像:%s\n"+
|
||||
@@ -170,138 +116,145 @@ func init() {
|
||||
"-每次累加时间:%v分钟\n"+
|
||||
"-最大禁言时间:%v分钟", group.Enable, group.TextAudit, group.ImageAudit, group.DMRemind, group.MoreRemind, group.DMBAN, group.BANTimeAddEnable, group.BANTime, group.BANTimeAddTime, group.MaxBANTimeAddRange)
|
||||
}
|
||||
b, err := text.RenderToBase64(msgs, text.FontFile, 300, 20)
|
||||
b, err := text.RenderToBase64(msg, text.FontFile, 300, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
|
||||
})
|
||||
engine.OnRegex("^设置(不)?检测类型([01234567])$", zero.AdminPermission, clientCheck).SetBlock(true).
|
||||
|
||||
engine.OnRegex("^设置(不)?检测类型([0-7])$", zero.AdminPermission, hasinit).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
defer jsonSave(config, configpath)
|
||||
k1 := ctx.State["regex_matched"].([]string)[1]
|
||||
k2 := ctx.State["regex_matched"].([]string)[2]
|
||||
group := getGroup(ctx.Event.GroupID)
|
||||
group := config.groupof(ctx.Event.GroupID)
|
||||
inputType, _ := strconv.Atoi(k2)
|
||||
if k1 == "不" {
|
||||
group.WhiteListType[inputType] = true //不检测:则进入类型白名单
|
||||
} else {
|
||||
group.WhiteListType[inputType] = false //检测:则退出白名单
|
||||
group.setWhiteListType(inputType, k1 == "不")
|
||||
err := config.saveto(configpath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
config.Groups[ctx.Event.GroupID] = group
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群将%s检测%s类型内容", k1, typetext[inputType])))
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群将%s检测%s类型内容", k1, txttyp[inputType])))
|
||||
})
|
||||
engine.OnRegex("^设置(最大|每次|撤回)(累加|禁言)时间(\\d{1,5})$", zero.AdminPermission, clientCheck).SetBlock(true).
|
||||
|
||||
engine.OnRegex("^设置(最大|每次|撤回)(累加|禁言)时间(\\d{1,5})$", zero.AdminPermission, hasinit).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
defer jsonSave(config, configpath)
|
||||
k1 := ctx.State["regex_matched"].([]string)[1]
|
||||
k3 := ctx.State["regex_matched"].([]string)[3]
|
||||
group := getGroup(ctx.Event.GroupID)
|
||||
time, _ := strconv.ParseInt(k1, 10, 64)
|
||||
switch k1 {
|
||||
case "最大":
|
||||
group.MaxBANTimeAddRange = time
|
||||
case "每次":
|
||||
group.BANTimeAddTime = time
|
||||
case "撤回":
|
||||
group.BANTime = time
|
||||
config.groupof(ctx.Event.GroupID).set(func(g *group) {
|
||||
switch k1 {
|
||||
case "最大":
|
||||
g.MaxBANTimeAddRange = time
|
||||
case "每次":
|
||||
g.BANTimeAddTime = time
|
||||
case "撤回":
|
||||
g.BANTime = time
|
||||
}
|
||||
})
|
||||
err := config.saveto(configpath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
config.Groups[ctx.Event.GroupID] = group
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群%s禁言累加时间已设置为%s", k3, k1)))
|
||||
})
|
||||
engine.OnRegex("^(开启|关闭)(内容审核|撤回提示|撤回禁言|禁言累加|详细提示|文本检测|图像检测)$", zero.AdminPermission, clientCheck).SetBlock(true).
|
||||
|
||||
engine.OnRegex("^(开启|关闭)(内容审核|撤回提示|撤回禁言|禁言累加|详细提示|文本检测|图像检测)$", zero.AdminPermission, hasinit).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
defer jsonSave(config, configpath)
|
||||
k1 := ctx.State["regex_matched"].([]string)[1]
|
||||
k2 := ctx.State["regex_matched"].([]string)[2]
|
||||
isEnable := EnableMark(false)
|
||||
group := getGroup(ctx.Event.GroupID)
|
||||
if k1 == "开启" {
|
||||
isEnable = true
|
||||
isEnable := mark(k1 == "开启")
|
||||
config.groupof(ctx.Event.GroupID).set(func(g *group) {
|
||||
switch k2 {
|
||||
case "内容审核":
|
||||
g.Enable = isEnable
|
||||
case "撤回提示":
|
||||
g.DMRemind = isEnable
|
||||
case "撤回禁言":
|
||||
g.DMBAN = isEnable
|
||||
case "禁言累加":
|
||||
g.BANTimeAddEnable = isEnable
|
||||
case "详细提示":
|
||||
g.MoreRemind = isEnable
|
||||
case "文本检测":
|
||||
g.TextAudit = isEnable
|
||||
case "图像检测":
|
||||
g.ImageAudit = isEnable
|
||||
}
|
||||
})
|
||||
err := config.saveto(configpath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
switch k2 {
|
||||
case "内容审核":
|
||||
group.Enable = isEnable
|
||||
case "撤回提示":
|
||||
group.DMRemind = isEnable
|
||||
case "撤回禁言":
|
||||
group.DMBAN = isEnable
|
||||
case "禁言累加":
|
||||
group.BANTimeAddEnable = isEnable
|
||||
case "详细提示":
|
||||
group.MoreRemind = isEnable
|
||||
case "文本检测":
|
||||
group.TextAudit = isEnable
|
||||
case "图像检测":
|
||||
group.ImageAudit = isEnable
|
||||
}
|
||||
config.Groups[ctx.Event.GroupID] = group
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群%s已%s", k2, k1)))
|
||||
})
|
||||
engine.OnRegex(`^配置BDAKey\s*(.*)\s*(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
||||
|
||||
engine.OnRegex(`^配置BDAKey\s(.*)\s(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
k1 := ctx.State["regex_matched"].([]string)[1]
|
||||
k2 := ctx.State["regex_matched"].([]string)[2]
|
||||
bdcli = censor.NewClient(k1, k2)
|
||||
config.Key1 = k1
|
||||
config.Key2 = k2
|
||||
config.setkey(k1, k2)
|
||||
if bdcli != nil {
|
||||
jsonSave(config, configpath)
|
||||
err := config.saveto(configpath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("配置成功"))
|
||||
}
|
||||
})
|
||||
engine.OnMessage().SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
||||
group, ok := config.Groups[ctx.Event.GroupID]
|
||||
// 如果没该配置,或者审核功能未开启直接跳过
|
||||
if !ok || !bool(group.Enable) {
|
||||
|
||||
engine.OnMessage(config.isgroupexist).SetBlock(false).Handle(func(ctx *zero.Ctx) {
|
||||
group := config.groupof(ctx.Event.GroupID)
|
||||
if !bool(group.Enable) {
|
||||
return
|
||||
}
|
||||
var bdres baiduRes
|
||||
var err error
|
||||
for _, elem := range ctx.Event.Message {
|
||||
switch elem.Type {
|
||||
case "image":
|
||||
if !group.ImageAudit {
|
||||
return
|
||||
if !group.ImageAudit || elem.Data["url"] == "" {
|
||||
continue
|
||||
}
|
||||
res := bdcli.ImgCensorUrl(elem.Data["url"], nil)
|
||||
bdres, err := jsonToBaiduRes(res)
|
||||
bdres, err = parse2BaiduRes(res)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
|
||||
return
|
||||
continue
|
||||
}
|
||||
banCheck(ctx, bdres)
|
||||
|
||||
case "text":
|
||||
if !group.TextAudit {
|
||||
return
|
||||
if !group.TextAudit || elem.Data["text"] == "" {
|
||||
continue
|
||||
}
|
||||
res := bdcli.TextCensor(elem.Data["text"])
|
||||
bdres, err := jsonToBaiduRes(res)
|
||||
bdres, err = parse2BaiduRes(bdcli.TextCensor(elem.Data["text"]))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
|
||||
return
|
||||
continue
|
||||
}
|
||||
banCheck(ctx, bdres)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
bdres.audit(ctx, configpath)
|
||||
})
|
||||
engine.OnPrefix("文本检测", clientCheck).SetBlock(false).
|
||||
|
||||
engine.OnPrefix("^文本检测", hasinit).SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if bdcli == nil {
|
||||
ctx.SendChain(message.Text("Key未配置"))
|
||||
return
|
||||
}
|
||||
args := ctx.ExtractPlainText()
|
||||
res := bdcli.TextCensor(args)
|
||||
bdres, err := jsonToBaiduRes(res)
|
||||
bdres, err := parse2BaiduRes(res)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
|
||||
ctx.SendChain(message.Text("ERROR: ", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
|
||||
return
|
||||
}
|
||||
group := getGroup(ctx.Event.GroupID)
|
||||
ctx.SendChain(buildResp(bdres, group)...)
|
||||
ctx.Send(config.groupof(ctx.Event.GroupID).reply(&bdres))
|
||||
})
|
||||
engine.OnPrefix("^图像检测", clientCheck).SetBlock(false).
|
||||
|
||||
engine.OnPrefix("^图像检测", hasinit).SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var urls []string
|
||||
for _, elem := range ctx.Event.Message {
|
||||
@@ -315,106 +268,17 @@ func init() {
|
||||
return
|
||||
}
|
||||
res := bdcli.ImgCensorUrl(urls[0], nil)
|
||||
bdres, err := jsonToBaiduRes(res)
|
||||
bdres, err := parse2BaiduRes(res)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
|
||||
ctx.SendChain(message.Text("ERROR: ", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
|
||||
return
|
||||
}
|
||||
group := getGroup(ctx.Event.GroupID)
|
||||
ctx.SendChain(buildResp(bdres, group)...)
|
||||
|
||||
ctx.Send(config.groupof(ctx.Event.GroupID).reply(&bdres))
|
||||
})
|
||||
}
|
||||
|
||||
// 禁言检测
|
||||
func banCheck(ctx *zero.Ctx, bdres baiduRes) {
|
||||
// 如果返回类型为2(不合规),0为合规,3为疑似
|
||||
if bdres.ConclusionType == 2 {
|
||||
// 创建消息ID
|
||||
mid := message.NewMessageIDFromInteger(ctx.Event.MessageID.(int64))
|
||||
// 获取群配置
|
||||
group := getGroup(ctx.Event.GroupID)
|
||||
// 检测群配置里的不检测类型白名单,忽略掉不检测的违规类型
|
||||
for i, b := range group.WhiteListType {
|
||||
if i == bdres.Data[0].SubType && b {
|
||||
return
|
||||
}
|
||||
}
|
||||
// 生成回复文本
|
||||
res := buildResp(bdres, group)
|
||||
// 撤回消息
|
||||
ctx.DeleteMessage(mid)
|
||||
// 查看是否启用撤回后禁言
|
||||
if group.DMBAN {
|
||||
// 从历史违规记录中获取指定用户
|
||||
user := group.getUser(ctx.Event.UserID)
|
||||
// 用户违规次数自增
|
||||
user.Count++
|
||||
// 用户违规原因记录
|
||||
user.ResList = append(user.ResList, bdres)
|
||||
// 覆写该用户到群违规记录中
|
||||
group.AuditHistory[ctx.Event.UserID] = user
|
||||
// 覆写该群信息
|
||||
config.Groups[ctx.Event.GroupID] = group
|
||||
// 保存到json
|
||||
jsonSave(config, configpath)
|
||||
var bantime int64
|
||||
// 查看是否开启禁言累加功能,并计算禁言时间
|
||||
if group.BANTimeAddEnable {
|
||||
bantime = user.Count * group.BANTimeAddTime * 60
|
||||
} else {
|
||||
bantime = group.BANTime * 60
|
||||
}
|
||||
//执行禁言
|
||||
ctx.SetGroupBan(ctx.Event.GroupID, ctx.Event.UserID, bantime)
|
||||
}
|
||||
//查看是否开启撤回提示
|
||||
if group.DMRemind {
|
||||
res = append(res, message.At(ctx.Event.Sender.ID))
|
||||
ctx.SendChain(res...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取群配置
|
||||
func getGroup(groupID int64) group {
|
||||
g, ok := config.Groups[groupID]
|
||||
if ok {
|
||||
return g
|
||||
}
|
||||
if config.Groups == nil {
|
||||
config.Groups = make(map[int64]group)
|
||||
}
|
||||
g = group{
|
||||
TextAudit: true,
|
||||
ImageAudit: true,
|
||||
BANTime: 1,
|
||||
MaxBANTimeAddRange: 60,
|
||||
BANTimeAddTime: 1,
|
||||
WhiteListType: [8]bool{},
|
||||
AuditHistory: map[int64]auditHistory{},
|
||||
}
|
||||
config.Groups[groupID] = g
|
||||
return g
|
||||
}
|
||||
|
||||
// 从群历史违规记录中获取用户
|
||||
func (group *group) getUser(userID int64) auditHistory {
|
||||
audit, ok := group.AuditHistory[userID]
|
||||
if ok {
|
||||
return audit
|
||||
}
|
||||
// 如果没有用户,则创建一个并返回
|
||||
if group.AuditHistory == nil {
|
||||
group.AuditHistory = make(map[int64]auditHistory)
|
||||
}
|
||||
audit = auditHistory{0, []baiduRes{}}
|
||||
group.AuditHistory[userID] = audit
|
||||
return audit
|
||||
}
|
||||
|
||||
// 客户端是否初始化检测
|
||||
func clientCheck(ctx *zero.Ctx) bool {
|
||||
func hasinit(ctx *zero.Ctx) bool {
|
||||
if bdcli == nil {
|
||||
ctx.SendChain(message.Text("Key未配置"))
|
||||
return false
|
||||
@@ -422,79 +286,7 @@ func clientCheck(ctx *zero.Ctx) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// 加载JSON配置文件
|
||||
func loadConfig() {
|
||||
if file.IsExist(configpath) {
|
||||
data, err := os.OpenFile(configpath, os.O_RDONLY, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = json.NewDecoder(data).Decode(&config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
configinit = true
|
||||
} else {
|
||||
config = keyConfig{}
|
||||
configinit = false
|
||||
}
|
||||
}
|
||||
|
||||
// 保存配置文件
|
||||
func jsonSave(v keyConfig, path string) {
|
||||
jsf, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
defer func(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}(jsf) // 结束时关闭句柄,释放资源
|
||||
err := json.NewEncoder(jsf).Encode(v)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// JSON反序列化
|
||||
func jsonToBaiduRes(resjson string) (baiduRes, error) {
|
||||
var bdres baiduRes
|
||||
err := json.Unmarshal(binary.StringToBytes(resjson), &bdres)
|
||||
return bdres, err
|
||||
}
|
||||
|
||||
// 生成回复文本
|
||||
func buildResp(bdres baiduRes, group group) []message.MessageSegment {
|
||||
// 建立消息段
|
||||
msgs := make([]message.MessageSegment, 0, 8)
|
||||
// 生成简略审核结果回复
|
||||
msgs = append(msgs, message.Text(bdres.Conclusion, "\n"))
|
||||
// 查看是否开启详细审核内容提示,并确定审核内容值为疑似,或者不合规
|
||||
if !group.MoreRemind {
|
||||
return msgs
|
||||
}
|
||||
// 遍历返回的不合规数据,生成详细违规内容
|
||||
for i, datum := range bdres.Data {
|
||||
msgs = append(msgs, message.Text("[", i, "]:", datum.Msg, "\n"))
|
||||
// 检查命中词条是否大于0
|
||||
if len(datum.Hits) == 0 {
|
||||
return msgs
|
||||
}
|
||||
// 遍历打印命中的违规词条
|
||||
for _, hit := range datum.Hits {
|
||||
if len(datum.Hits) == 0 {
|
||||
return msgs
|
||||
}
|
||||
msgs = append(msgs, message.Text("("))
|
||||
for i4, i3 := range hit.Words {
|
||||
// 检查是否是最后一个要打印的词条,如果是则不加上逗号
|
||||
if i4 != len(hit.Words)-1 {
|
||||
msgs = append(msgs, message.Text(i3, ","))
|
||||
} else {
|
||||
msgs = append(msgs, message.Text(i3))
|
||||
}
|
||||
}
|
||||
msgs = append(msgs, message.Text(")"))
|
||||
}
|
||||
}
|
||||
return msgs
|
||||
func parse2BaiduRes(resjson string) (bdres baiduRes, err error) {
|
||||
err = json.Unmarshal(binary.StringToBytes(resjson), &bdres)
|
||||
return
|
||||
}
|
||||
|
||||
271
plugin/baiduaudit/model.go
Normal file
271
plugin/baiduaudit/model.go
Normal file
@@ -0,0 +1,271 @@
|
||||
package baiduaudit
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
// 服务网址:https://console.bce.baidu.com/ai/?_=1665977657185#/ai/antiporn/overview/index
|
||||
// 返回参数说明:https://cloud.baidu.com/doc/ANTIPORN/s/Nk3h6xbb2
|
||||
type baiduRes struct {
|
||||
mu sync.Mutex `json:"-"`
|
||||
// LogID int `json:"log_id"` // 请求唯一id
|
||||
Conclusion string `json:"conclusion"` // 审核结果, 可取值:合规、不合规、疑似、审核失败
|
||||
ConclusionType int `json:"conclusionType"` // 审核结果类型, 可取值1.合规, 2.不合规, 3.疑似, 4.审核失败
|
||||
Data []*auditData `json:"data"`
|
||||
ErrorCode int `json:"error_code"` // 错误提示码, 失败才返回, 成功不返回
|
||||
ErrorMsg string `json:"error_msg"` // 错误提示信息, 失败才返回, 成功不返回
|
||||
}
|
||||
|
||||
// 禁言检测
|
||||
func (bdres *baiduRes) audit(ctx *zero.Ctx, configpath string) {
|
||||
bdres.mu.Lock()
|
||||
defer bdres.mu.Unlock()
|
||||
// 如果返回类型为2(不合规), 0为合规, 3为疑似
|
||||
if bdres.ConclusionType != 2 {
|
||||
return
|
||||
}
|
||||
// 创建消息ID
|
||||
mid := message.NewMessageIDFromInteger(ctx.Event.MessageID.(int64))
|
||||
// 获取群配置
|
||||
group := config.groupof(ctx.Event.GroupID)
|
||||
// 检测群配置里的不检测类型白名单, 忽略掉不检测的违规类型
|
||||
for i, b := range group.copyWhiteListType() {
|
||||
if i == bdres.Data[0].SubType && b {
|
||||
return
|
||||
}
|
||||
}
|
||||
// 生成回复文本
|
||||
res := group.reply(bdres)
|
||||
// 撤回消息
|
||||
ctx.DeleteMessage(mid)
|
||||
// 查看是否启用撤回后禁言
|
||||
if group.DMBAN {
|
||||
// 从历史违规记录中获取指定用户
|
||||
user := group.historyof(ctx.Event.UserID)
|
||||
// 用户违规次数自增
|
||||
atomic.AddInt64(&user.Count, 1)
|
||||
user.mu.Lock()
|
||||
// 用户违规原因记录
|
||||
user.ResList = append(user.ResList, bdres)
|
||||
user.mu.Unlock()
|
||||
// 保存到json
|
||||
err := config.saveto(configpath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
var bantime int64
|
||||
// 查看是否开启禁言累加功能, 并计算禁言时间
|
||||
if group.BANTimeAddEnable {
|
||||
bantime = atomic.LoadInt64(&user.Count) * group.BANTimeAddTime * 60
|
||||
} else {
|
||||
bantime = group.BANTime * 60
|
||||
}
|
||||
// 执行禁言
|
||||
ctx.SetGroupBan(ctx.Event.GroupID, ctx.Event.UserID, bantime)
|
||||
}
|
||||
// 查看是否开启撤回提示
|
||||
if group.DMRemind {
|
||||
res = append(res, message.At(ctx.Event.Sender.ID))
|
||||
ctx.Send(res)
|
||||
}
|
||||
}
|
||||
|
||||
type auditData struct {
|
||||
// Type int `json:"type"` // 审核主类型, 11:百度官方违禁词库、12:文本反作弊、13:自定义文本黑名单、14:自定义文本白名单
|
||||
SubType int `json:"subType"` // 审核子类型, 0:含多种类型, 具体看官方链接, 1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
|
||||
// Conclusion string `json:"conclusion"` // 审核结果, 可取值:合规、不合规、疑似、审核失败
|
||||
// ConclusionType int `json:"conclusionType"` // 审核结果类型, 可取值1.合规, 2.不合规, 3.疑似, 4.审核失败
|
||||
Msg string `json:"msg"` // 不合规项描述信息
|
||||
Hits []*hit `json:"hits"`
|
||||
} // 不合规/疑似/命中白名单项详细信息.响应成功并且conclusion为疑似或不合规或命中白名单时才返回, 响应失败或conclusion为合规且未命中白名单时不返回.
|
||||
|
||||
type auditHistory struct {
|
||||
mu sync.Mutex `json:"-"`
|
||||
Count int64 `json:"key2"` // 被禁次数
|
||||
ResList []*baiduRes `json:"reslist"` // 禁言原因
|
||||
}
|
||||
|
||||
type hit struct {
|
||||
// DatasetName string `json:"datasetName"` // 违规项目所属数据集名称
|
||||
Words []string `json:"words"` // 送检文本命中词库的关键词(备注:建议参考新字段“wordHitPositions”, 包含信息更丰富:关键词以及对应的位置及标签信息)
|
||||
// Probability float64 `json:"probability,omitempty"` // 不合规项置信度
|
||||
} // 送检文本违规原因的详细信息
|
||||
|
||||
type keyConfig struct {
|
||||
mu sync.Mutex `json:"-"`
|
||||
Key1 string `json:"key1"` // 百度云服务内容审核key存储
|
||||
Key2 string `json:"key2"` // 百度云服务内容审核key存储
|
||||
Groups map[int64]*group `json:"groups"` // 群配置存储
|
||||
}
|
||||
|
||||
func newconfig() (kc keyConfig) {
|
||||
kc.Groups = make(map[int64]*group, 64)
|
||||
return
|
||||
}
|
||||
|
||||
func (kc *keyConfig) setkey(k1, k2 string) {
|
||||
kc.mu.Lock()
|
||||
defer kc.mu.Unlock()
|
||||
kc.Key1 = k1
|
||||
kc.Key2 = k2
|
||||
}
|
||||
|
||||
// 加载JSON配置文件
|
||||
func (kc *keyConfig) load(filename string) error {
|
||||
if file.IsNotExist(filename) {
|
||||
return nil
|
||||
}
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kc.mu.Lock()
|
||||
defer kc.mu.Unlock()
|
||||
return json.NewDecoder(f).Decode(kc)
|
||||
}
|
||||
|
||||
func (kc *keyConfig) isgroupexist(ctx *zero.Ctx) (ok bool) {
|
||||
kc.mu.Lock()
|
||||
defer kc.mu.Unlock()
|
||||
_, ok = kc.Groups[ctx.Event.GroupID]
|
||||
return
|
||||
}
|
||||
|
||||
// 获取群配置
|
||||
func (kc *keyConfig) groupof(groupID int64) *group {
|
||||
kc.mu.Lock()
|
||||
defer kc.mu.Unlock()
|
||||
g, ok := kc.Groups[groupID]
|
||||
if ok {
|
||||
return g
|
||||
}
|
||||
g = &group{
|
||||
TextAudit: true,
|
||||
ImageAudit: true,
|
||||
BANTime: 1,
|
||||
MaxBANTimeAddRange: 60,
|
||||
BANTimeAddTime: 1,
|
||||
AuditHistory: map[int64]*auditHistory{},
|
||||
}
|
||||
kc.Groups[groupID] = g
|
||||
return g
|
||||
}
|
||||
|
||||
// 保存配置文件
|
||||
func (kc *keyConfig) saveto(filename string) error {
|
||||
kc.mu.Lock()
|
||||
defer kc.mu.Unlock()
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return json.NewEncoder(f).Encode(kc)
|
||||
}
|
||||
|
||||
type group struct {
|
||||
mu sync.Mutex
|
||||
Enable mark // 是否启用内容审核
|
||||
TextAudit mark // 文本检测
|
||||
ImageAudit mark // 图像检测
|
||||
DMRemind mark // 撤回提示
|
||||
MoreRemind mark // 详细违规提示
|
||||
DMBAN mark // 撤回后禁言
|
||||
BANTimeAddEnable mark // 禁言累加
|
||||
BANTime int64 // 标准禁言时间, 禁用累加, 但开启禁言的的情况下采用该值
|
||||
MaxBANTimeAddRange int64 // 最大禁言时间累加范围, 最高禁言时间
|
||||
BANTimeAddTime int64 // 禁言累加时间, 该值是开启禁累加功能后, 再次触发时, 根据被禁次数X该值计算出的禁言时间
|
||||
WhiteListType [8]bool // 类型白名单, 处于白名单类型的违规, 不会被触发 0:含多种类型, 具体看官方链接, 1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
|
||||
AuditHistory map[int64]*auditHistory // 被封禁用户列表
|
||||
}
|
||||
|
||||
func (g *group) set(f func(g *group)) {
|
||||
g.mu.Lock()
|
||||
f(g)
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
||||
func (g *group) setWhiteListType(typ int, ok bool) {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
g.WhiteListType[typ] = ok
|
||||
}
|
||||
|
||||
func (g *group) copyWhiteListType() [8]bool {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.WhiteListType
|
||||
}
|
||||
|
||||
// 从群历史违规记录中获取用户
|
||||
func (g *group) historyof(userID int64) *auditHistory {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
audit, ok := g.AuditHistory[userID]
|
||||
if ok {
|
||||
return audit
|
||||
}
|
||||
// 如果没有用户, 则创建一个并返回
|
||||
if g.AuditHistory == nil {
|
||||
g.AuditHistory = make(map[int64]*auditHistory)
|
||||
}
|
||||
audit = &auditHistory{}
|
||||
g.AuditHistory[userID] = audit
|
||||
return audit
|
||||
}
|
||||
|
||||
// 生成回复文本
|
||||
func (g *group) reply(bdres *baiduRes) message.Message {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
// 建立消息段
|
||||
msgs := make([]message.MessageSegment, 0, 8)
|
||||
// 生成简略审核结果回复
|
||||
msgs = append(msgs, message.Text(bdres.Conclusion, "\n"))
|
||||
// 查看是否开启详细审核内容提示, 并确定审核内容值为疑似, 或者不合规
|
||||
if !g.MoreRemind {
|
||||
return msgs
|
||||
}
|
||||
// 遍历返回的不合规数据, 生成详细违规内容
|
||||
for i, datum := range bdres.Data {
|
||||
msgs = append(msgs, message.Text("[", i, "]:", datum.Msg, "\n"))
|
||||
// 检查命中词条是否大于0
|
||||
if len(datum.Hits) == 0 {
|
||||
return msgs
|
||||
}
|
||||
// 遍历打印命中的违规词条
|
||||
for _, hit := range datum.Hits {
|
||||
if len(datum.Hits) == 0 {
|
||||
return msgs
|
||||
}
|
||||
msgs = append(msgs, message.Text("("))
|
||||
for i4, i3 := range hit.Words {
|
||||
// 检查是否是最后一个要打印的词条, 如果是则不加上逗号
|
||||
if i4 != len(hit.Words)-1 {
|
||||
msgs = append(msgs, message.Text(i3, ","))
|
||||
} else {
|
||||
msgs = append(msgs, message.Text(i3))
|
||||
}
|
||||
}
|
||||
msgs = append(msgs, message.Text(")"))
|
||||
}
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
type mark bool
|
||||
|
||||
// String 打印启用状态
|
||||
func (em mark) String() string {
|
||||
if em {
|
||||
return "开启"
|
||||
}
|
||||
return "关闭"
|
||||
}
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
func init() {
|
||||
en := control.Register("base64gua", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "base64gua加解密\n" +
|
||||
"- 六十四卦加密xxx\n- 六十四卦解密xxx\n- 六十四卦用yyy加密xxx\n- 六十四卦用yyy解密xxx",
|
||||
Brief: "六十四卦加解密",
|
||||
Help: "- 六十四卦加密xxx\n- 六十四卦解密xxx\n- 六十四卦用yyy加密xxx\n- 六十四卦用yyy解密xxx",
|
||||
})
|
||||
en.OnRegex(`^六十四卦加密\s*(.+)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
func init() {
|
||||
en := control.Register("baseamasiro", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "base天城文加解密\n" +
|
||||
"- 天城文加密xxx\n- 天城文解密xxx\n- 天城文用yyy加密xxx\n- 天城文用yyy解密xxx",
|
||||
Brief: "天城文加解密",
|
||||
Help: "- 天城文加密xxx\n- 天城文解密xxx\n- 天城文用yyy加密xxx\n- 天城文用yyy解密xxx",
|
||||
})
|
||||
en.OnRegex(`^天城文加密\s*(.+)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
@@ -16,15 +16,14 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/Coloured-glaze/gg"
|
||||
bz "github.com/FloatTech/AnimeAPI/bilibili"
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/img/writer"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
@@ -40,6 +39,9 @@ var (
|
||||
3: "Superchat",
|
||||
4: "进入直播间",
|
||||
5: "标题变动",
|
||||
6: "分区变动",
|
||||
7: "直播中止",
|
||||
8: "直播继续",
|
||||
}
|
||||
cfg = bz.NewCookieConfig("data/Bilibili/config.json")
|
||||
)
|
||||
@@ -48,13 +50,14 @@ var (
|
||||
func init() {
|
||||
engine := control.Register("bilibili", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibili (412就是拦截的意思,建议私聊把cookie设全)\n" +
|
||||
"- >vup info [xxx]\n" +
|
||||
Brief: "b站查成分查弹幕",
|
||||
Help: "- >vup info [xxx]\n" +
|
||||
"- >user info [xxx]\n" +
|
||||
"- 查成分 [xxx]\n" +
|
||||
"- 查弹幕 [xxx]\n" +
|
||||
"- 设置b站cookie b_ut=7;buvid3=0;i-wanna-go-back=-1;innersign=0;\n" +
|
||||
"- 更新vup",
|
||||
"- 更新vup\n" +
|
||||
"Tips: (412就是拦截的意思,建议私聊把cookie设全)\n",
|
||||
PublicDataFolder: "Bilibili",
|
||||
})
|
||||
cachePath := engine.DataFolder() + "cache/"
|
||||
@@ -170,7 +173,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
back = img.Size(back, backX, backY).Im
|
||||
back = imgfactory.Size(back, backX, backY).Image()
|
||||
}
|
||||
if len(vups) > 50 {
|
||||
ctx.SendChain(message.Text(u.Name + "关注的up主太多了, 只展示前50个up"))
|
||||
@@ -184,11 +187,11 @@ func init() {
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
|
||||
if err = canvas.ParseFontFace(data, fontSize); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
@@ -255,12 +258,15 @@ func init() {
|
||||
f, err := os.Create(drawedFile)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibili]", err)
|
||||
data, cl := writer.ToBytes(canvas.Image())
|
||||
data, err := imgfactory.ToBytes(canvas.Image())
|
||||
if err != nil {
|
||||
log.Errorln("[bilibili]", err)
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.ImageBytes(data))
|
||||
cl()
|
||||
return
|
||||
}
|
||||
_, err = writer.WriteTo(canvas.Image(), f)
|
||||
_, err = imgfactory.WriteTo(canvas.Image(), f)
|
||||
_ = f.Close()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
@@ -287,7 +293,7 @@ func init() {
|
||||
}
|
||||
|
||||
client := &http.Client{Transport: tr}
|
||||
data, err := web.RequestDataWith(client, fmt.Sprintf(bz.DanmakuAPI, id, pagenum), "GET", "", web.RandUA())
|
||||
data, err := web.RequestDataWith(client, fmt.Sprintf(bz.DanmakuAPI, id, pagenum), "GET", "", web.RandUA(), nil)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -314,15 +320,15 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
back = img.Size(back, backX, backY).Im
|
||||
back = imgfactory.Size(back, backX, backY).Image()
|
||||
}
|
||||
canvas := gg.NewContext(100, 100)
|
||||
fontSize := 50.0
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
|
||||
if err = canvas.ParseFontFace(data, fontSize); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
@@ -334,14 +340,14 @@ func init() {
|
||||
for i := 0; i < len(danmaku.Data.Data); i++ {
|
||||
totalDanmuku += len(danmaku.Data.Data[i].Danmakus) + 1
|
||||
}
|
||||
cw := 10000
|
||||
cw := 3000
|
||||
mcw := float64(2000)
|
||||
ch := 550 + len(danmaku.Data.Data)*int(faceH) + totalDanmuku*int(danmuH)
|
||||
canvas = gg.NewContext(cw, ch)
|
||||
canvas.SetColor(color.White)
|
||||
canvas.Clear()
|
||||
canvas.SetColor(color.Black)
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
|
||||
if err = canvas.ParseFontFace(data, fontSize); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
@@ -380,7 +386,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
back = img.Size(back, backX, backY).Im
|
||||
back = imgfactory.Size(back, backX, backY).Image()
|
||||
}
|
||||
if back != nil {
|
||||
canvas.DrawImage(back, facestart, int(channelStart))
|
||||
@@ -491,13 +497,19 @@ func init() {
|
||||
canvas.DrawString(t, moveW, danmuNow)
|
||||
canvas.SetColor(color.Black)
|
||||
moveW += l + dz
|
||||
case 4, 5:
|
||||
case 4, 5, 6, 7, 8:
|
||||
t = danmakuTypeMap[danItem.Type]
|
||||
canvas.SetRGB255(0, 128, 0)
|
||||
l, _ = canvas.MeasureString(t)
|
||||
canvas.DrawString(t, moveW, danmuNow)
|
||||
canvas.SetColor(color.Black)
|
||||
moveW += l + dz
|
||||
default:
|
||||
canvas.SetRGB255(0, 128, 0)
|
||||
l, _ = canvas.MeasureString("未知类型" + strconv.Itoa(int(danItem.Type)))
|
||||
canvas.DrawString(t, moveW, danmuNow)
|
||||
canvas.SetColor(color.Black)
|
||||
moveW += l + dz
|
||||
}
|
||||
if moveW > mcw {
|
||||
mcw = moveW
|
||||
@@ -510,12 +522,15 @@ func init() {
|
||||
f, err := os.Create(drawedFile)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibili]", err)
|
||||
data, cl := writer.ToBytes(nim)
|
||||
data, err := imgfactory.ToBytes(nim)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibili]", err)
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.ImageBytes(data))
|
||||
cl()
|
||||
return
|
||||
}
|
||||
_, err = writer.WriteTo(nim, f)
|
||||
_, err = imgfactory.WriteTo(nim, f)
|
||||
_ = f.Close()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
|
||||
@@ -29,13 +29,13 @@ var (
|
||||
func init() {
|
||||
en := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "b站动态、专栏、视频、直播解析\n" +
|
||||
"- t.bilibili.com/642277677329285174 | bilibili.com/read/cv17134450 | bilibili.com/video/BV13B4y1x7pS | live.bilibili.com/22603245 ",
|
||||
Brief: "b站链接解析",
|
||||
Help: "例:- t.bilibili.com/642277677329285174\n- bilibili.com/read/cv17134450\n- bilibili.com/video/BV13B4y1x7pS\n- live.bilibili.com/22603245 ",
|
||||
})
|
||||
en.OnRegex(`((b23|acg).tv|bili2233.cn)/[0-9a-zA-Z]+`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["regex_matched"].([]string)[0]
|
||||
realurl, err := bz.GetRealUrl("https://" + url)
|
||||
realurl, err := bz.GetRealURL("https://" + url)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
_ "github.com/fumiama/sqlite3" // use sql
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -22,10 +23,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
|
||||
referer = "https://www.bilibili.com/"
|
||||
infoURL = "https://api.bilibili.com/x/space/acc/info?mid=%v"
|
||||
serviceName = "bilibilipush"
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
|
||||
referer = "https://www.bilibili.com/"
|
||||
infoURL = "https://api.bilibili.com/x/space/acc/info?mid=%v"
|
||||
)
|
||||
|
||||
// bdb bilibili推送数据库
|
||||
@@ -38,16 +38,18 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register(serviceName, &ctrl.Options[*zero.Ctx]{
|
||||
en := control.Register("bilibilipush", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibilipush,需要配合job一起使用\n" +
|
||||
"- 添加b站订阅[uid|name]\n" +
|
||||
Brief: "b站推送",
|
||||
Help: "- 添加b站订阅[uid|name]\n" +
|
||||
"- 取消b站订阅[uid|name]\n" +
|
||||
"- 取消b站动态订阅[uid|name]\n" +
|
||||
"- 取消b站直播订阅[uid|name]\n" +
|
||||
"- b站推送列表\n" +
|
||||
"- 拉取b站推送 (使用job执行定时任务------记录在\"@every 10s\"触发的指令)",
|
||||
PrivateDataFolder: serviceName,
|
||||
"Tips: 需要配合job一起使用, 全局只需要设置一个, 无视响应状态推送, 下为例子\n" +
|
||||
"记录在\"@every 5m\"触发的指令)\n" +
|
||||
"拉取b站推送",
|
||||
PrivateDataFolder: "bilibilipush",
|
||||
})
|
||||
|
||||
// 加载bilibili推送数据库
|
||||
@@ -55,7 +57,7 @@ func init() {
|
||||
dbfile := dbpath + "push.db"
|
||||
bdb = initializePush(dbfile)
|
||||
|
||||
en.OnRegex(`^添加b站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^添加[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||
name, err := getName(buid)
|
||||
if err != nil {
|
||||
@@ -72,7 +74,7 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
|
||||
})
|
||||
en.OnRegex(`^取消b站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^取消[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||
name, err := getName(buid)
|
||||
if err != nil {
|
||||
@@ -89,7 +91,7 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("已取消" + name + "的订阅"))
|
||||
})
|
||||
en.OnRegex(`^取消b站动态订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^取消[B|b]站动态订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||
name, err := getName(buid)
|
||||
if err != nil {
|
||||
@@ -106,7 +108,7 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("已取消" + name + "的动态订阅"))
|
||||
})
|
||||
en.OnRegex(`^取消b站直播订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^取消[B|b]站直播订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
@@ -123,13 +125,13 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("已取消" + name + "的直播订阅"))
|
||||
})
|
||||
en.OnFullMatch("b站推送列表", zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^[B|b]站推送列表$`, zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
bpl := bdb.getAllPushByGroup(gid)
|
||||
msg := "--------b站推送列表--------"
|
||||
msg := "--------B站推送列表--------"
|
||||
for _, v := range bpl {
|
||||
if _, ok := upMap[v.BilibiliUID]; !ok {
|
||||
bdb.updateAllUp()
|
||||
@@ -157,7 +159,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
en.OnFullMatch("拉取b站推送").SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`拉取[B|b]站推送$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := sendDynamic(ctx)
|
||||
if err != nil {
|
||||
ctx.SendPrivateMessage(ctx.Event.UserID, message.Text("Error: bilibilipush,", err))
|
||||
@@ -174,7 +176,19 @@ func getName(buid int64) (name string, err error) {
|
||||
var ok bool
|
||||
if name, ok = upMap[buid]; !ok {
|
||||
var data []byte
|
||||
data, err = web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(infoURL, buid), "GET", referer, ua)
|
||||
data, err = web.RequestDataWithHeaders(web.NewDefaultClient(), fmt.Sprintf(infoURL, buid), "GET", func(r *http.Request) error {
|
||||
r.Header.Set("refer", referer)
|
||||
r.Header.Set("user-agent", ua)
|
||||
cookie := ""
|
||||
if cfg != nil {
|
||||
cookie, err = cfg.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
r.Header.Set("cookie", cookie)
|
||||
return nil
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -231,7 +245,7 @@ func unsubscribeLive(buid, groupid int64) (err error) {
|
||||
}
|
||||
|
||||
func getUserDynamicCard(buid int64) (cardList []gjson.Result, err error) {
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(bz.SpaceHistoryURL, buid, 0), "GET", referer, ua)
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(bz.SpaceHistoryURL, buid, 0), "GET", referer, ua, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -274,7 +288,7 @@ func sendDynamic(ctx *zero.Ctx) error {
|
||||
ct := cardList[i].Get("desc.timestamp").Int()
|
||||
if ct > t && ct > time.Now().Unix()-600 {
|
||||
lastTime[buid] = ct
|
||||
m, ok := control.Lookup(serviceName)
|
||||
m, ok := control.Lookup("bilibilipush")
|
||||
if ok {
|
||||
groupList := bdb.getAllGroupByBuidAndDynamic(buid)
|
||||
dc, err := bz.LoadDynamicDetail(cardList[i].Raw)
|
||||
@@ -323,7 +337,7 @@ func sendLive(ctx *zero.Ctx) error {
|
||||
oldStatus := liveStatus[key.Int()]
|
||||
if newStatus != oldStatus && newStatus == 1 {
|
||||
liveStatus[key.Int()] = newStatus
|
||||
m, ok := control.Lookup(serviceName)
|
||||
m, ok := control.Lookup("bilibilipush")
|
||||
if ok {
|
||||
groupList := bdb.getAllGroupByBuidAndLive(key.Int())
|
||||
roomID := value.Get("short_id").Int()
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
_ "github.com/fumiama/sqlite3" // import sql
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
func init() {
|
||||
engine := control.Register("bookreview", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "哀伤雪刃推书记录\n- 书评[xxx]\n- 随机书评",
|
||||
Brief: "哀伤雪刃推书书评",
|
||||
Help: "- 书评[xxx]\n- 随机书评",
|
||||
PublicDataFolder: "BookReview",
|
||||
})
|
||||
|
||||
@@ -26,7 +27,7 @@ func init() {
|
||||
db.DBPath = engine.DataFolder() + "bookreview.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("bookreview.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -18,7 +18,8 @@ var sm syncx.Map[int64, string]
|
||||
func init() {
|
||||
engine := control.Register("breakrepeat", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "打断复读\n- 打断" + strconv.Itoa(throttle) + "次以上复读\n",
|
||||
Brief: "打断复读",
|
||||
Help: "- 打断" + strconv.Itoa(throttle) + "次以上复读\n",
|
||||
})
|
||||
engine.On("message/group", zero.OnlyGroup, func(ctx *zero.Ctx) bool {
|
||||
return !zero.HasPicture(ctx)
|
||||
|
||||
@@ -32,8 +32,8 @@ var (
|
||||
func init() {
|
||||
engine := control.Register("cangtoushi", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "藏头诗\n" +
|
||||
"- 藏头诗[xxx]\n- 藏尾诗[xxx]",
|
||||
Brief: "藏头诗, 藏尾诗",
|
||||
Help: "- 藏头诗[xxx]\n- 藏尾诗[xxx]",
|
||||
})
|
||||
engine.OnRegex(`藏头诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
kw := ctx.State["regex_matched"].([]string)[1]
|
||||
|
||||
@@ -17,6 +17,7 @@ var (
|
||||
poke = rate.NewManager[int64](time.Minute*5, 8) // 戳一戳
|
||||
engine = control.Register("chat", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "基础反应, 群空调",
|
||||
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
|
||||
})
|
||||
)
|
||||
|
||||
@@ -15,9 +15,9 @@ import (
|
||||
func init() {
|
||||
engine := control.Register("choose", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "choose\n" +
|
||||
"- 选择可口可乐还是百事可乐\n" +
|
||||
"- 选择肯德基还是麦当劳还是必胜客",
|
||||
Brief: "选择困难症帮手",
|
||||
Help: "例: 选择可口可乐还是百事可乐\n" +
|
||||
"选择肯德基还是麦当劳还是必胜客",
|
||||
})
|
||||
engine.OnPrefix("选择").SetBlock(true).Handle(handle)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ import (
|
||||
func init() {
|
||||
en := control.Register("chouxianghua", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "抽象话\n- 抽象翻译xxx",
|
||||
Brief: "翻译为抽象话",
|
||||
Help: "- 抽象翻译xxx",
|
||||
PublicDataFolder: "ChouXiangHua",
|
||||
})
|
||||
|
||||
@@ -25,7 +26,7 @@ func init() {
|
||||
db.DBPath = en.DataFolder() + "cxh.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = en.GetLazyData("cxh.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -14,7 +14,8 @@ func init() {
|
||||
// 初始化engine
|
||||
engine := control.Register("chrev", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "字符翻转\n- 翻转 I love you",
|
||||
Brief: "英文字符翻转",
|
||||
Help: "例: 翻转 I love you",
|
||||
})
|
||||
// 处理字符翻转指令
|
||||
engine.OnRegex(`^翻转\s*([A-Za-z\s]*)$`).SetBlock(true).
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
package coser
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
@@ -10,6 +13,8 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/setu"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
@@ -19,34 +24,47 @@ import (
|
||||
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() {
|
||||
p, err := setu.NewPool(setu.DefaultPoolDir,
|
||||
func(s string) (string, error) {
|
||||
if s != "coser" {
|
||||
return "", errors.New("invalid call")
|
||||
}
|
||||
typ := setu.DefaultPoolDir + "/" + "coser"
|
||||
if file.IsNotExist(typ) {
|
||||
err := os.MkdirAll(typ, 0755)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), coserURL, "GET", "", ua, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
arr := gjson.Get(helper.BytesToString(data), "data.data").Array()
|
||||
if len(arr) == 0 {
|
||||
return "", errors.New("data is empty")
|
||||
}
|
||||
pic := arr[rand.Intn(len(arr))]
|
||||
return pic.String(), nil
|
||||
}, web.GetData, time.Minute)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
control.Register("coser", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "三次元小姐姐\n- coser",
|
||||
Brief: "三次元coser",
|
||||
Help: "- coser",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), coserURL, "GET", "", ua)
|
||||
pic, err := p.Roll("coser")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
text := gjson.Get(helper.BytesToString(data), "data.Title").String()
|
||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(text))}
|
||||
ds := ""
|
||||
gjson.Get(helper.BytesToString(data), "data.data").ForEach(func(_, value gjson.Result) bool {
|
||||
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.Send(m).ID(); id == 0 {
|
||||
if id := ctx.Send(message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+file.BOTPATH+"/"+pic))}).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
func init() {
|
||||
engine := control.Register("cpstory", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "cp短打\n- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
|
||||
Brief: "cp短打", // 这里也许有更好的名字
|
||||
Help: "- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
|
||||
PublicDataFolder: "CpStory",
|
||||
})
|
||||
|
||||
@@ -26,7 +27,7 @@ func init() {
|
||||
db.DBPath = engine.DataFolder() + "cp.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("cp.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
@@ -52,7 +53,7 @@ func init() {
|
||||
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)
|
||||
text = strings.ReplaceAll(text, cs.Shou, shou)
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
engine.OnPrefix("磕cp", getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
@@ -23,7 +23,8 @@ const (
|
||||
func init() {
|
||||
engine := control.Register("curse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "骂人(求骂,自卫)\n- 骂我\n- 大力骂我",
|
||||
Brief: "骂人反击",
|
||||
Help: "- 骂我\n- 大力骂我",
|
||||
PublicDataFolder: "Curse",
|
||||
})
|
||||
|
||||
@@ -34,7 +35,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
37
plugin/dailynews/dailynews.go
Normal file
37
plugin/dailynews/dailynews.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Package dailynews 今日早报
|
||||
package dailynews
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const api = "http://dwz.2xb.cn/zaob"
|
||||
|
||||
func init() {
|
||||
engine := control.Register("dailynews", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "今日早报",
|
||||
Help: "- 今日早报",
|
||||
PrivateDataFolder: "dailynews",
|
||||
})
|
||||
|
||||
engine.OnFullMatch(`今日早报`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
data, err := web.GetData(api)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
picURL := gjson.Get(binary.BytesToString(data), "imageUrl").String()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(picURL))
|
||||
})
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/img/writer"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("danbooru", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "二次元图片标签识别\n" +
|
||||
"- 鉴赏图片[图片]",
|
||||
DisableOnDefault: false,
|
||||
Brief: "二次元图片标签识别",
|
||||
Help: "- 鉴赏图片[图片]",
|
||||
PrivateDataFolder: "danbooru",
|
||||
})
|
||||
|
||||
@@ -39,7 +39,7 @@ func init() { // 插件主体
|
||||
digest := md5.Sum(helper.StringToBytes(url))
|
||||
f := cachefolder + hex.EncodeToString(digest[:])
|
||||
if file.IsNotExist(f) {
|
||||
_ = writer.SavePNG2Path(f, t)
|
||||
_ = imgfactory.SavePNG2Path(f, t)
|
||||
}
|
||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+file.BOTPATH+"/"+f))}
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text("tags: ", strings.Join(st.tseq, ","))))
|
||||
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
"net/url"
|
||||
"sort"
|
||||
|
||||
"github.com/Coloured-glaze/gg"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
imgutils "github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img/text" // jpg png gif
|
||||
_ "golang.org/x/image/webp" // webp
|
||||
)
|
||||
@@ -75,11 +76,11 @@ func tagurl(name, u string) (im image.Image, st *sorttags, err error) {
|
||||
st = newsorttags(tags)
|
||||
sort.Sort(st)
|
||||
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
boldfd, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = file.GetLazyData(text.ConsolasFontFile, true)
|
||||
consfd, err := file.GetLazyData(text.ConsolasFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -93,19 +94,19 @@ func tagurl(name, u string) (im image.Image, st *sorttags, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
img = imgutils.Limit(img, 1280, 720)
|
||||
img = imgfactory.Limit(img, 1280, 720)
|
||||
|
||||
canvas := gg.NewContext(img.Bounds().Size().X, img.Bounds().Size().Y+int(float64(img.Bounds().Size().X)*0.2)+len(tags)*img.Bounds().Size().X/25)
|
||||
canvas.SetRGB(1, 1, 1)
|
||||
canvas.Clear()
|
||||
canvas.DrawImage(img, 0, 0)
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, float64(img.Bounds().Size().X)*0.1); err != nil {
|
||||
if err = canvas.ParseFontFace(boldfd, float64(img.Bounds().Size().X)*0.1); err != nil {
|
||||
return
|
||||
}
|
||||
canvas.SetRGB(0, 0, 0)
|
||||
canvas.DrawString(name, float64(img.Bounds().Size().X)*0.02, float64(img.Bounds().Size().Y)+float64(img.Bounds().Size().X)*0.1)
|
||||
i := float64(img.Bounds().Size().Y) + float64(img.Bounds().Size().X)*0.2
|
||||
if err = canvas.LoadFontFace(text.ConsolasFontFile, float64(img.Bounds().Size().X)*0.04); err != nil {
|
||||
if err = canvas.ParseFontFace(consfd, float64(img.Bounds().Size().X)*0.04); err != nil {
|
||||
return
|
||||
}
|
||||
rate := float64(img.Bounds().Size().X) * 0.04
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
|
||||
var engine = control.Register("diana", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "嘉然\n" +
|
||||
"- 小作文\n" +
|
||||
Brief: "嘉然相关", // 也许使用常用功能当Brief更好
|
||||
Help: "- 小作文\n" +
|
||||
"- 发大病\n" +
|
||||
"- 教你一篇小作文[作文]",
|
||||
PublicDataFolder: "Diana",
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
binutils "github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -21,12 +22,12 @@ type text struct {
|
||||
|
||||
// LoadText 加载小作文
|
||||
func LoadText(dbfile string) error {
|
||||
_, err := file.GetLazyData(dbfile, false)
|
||||
_, err := file.GetLazyData(dbfile, control.Md5File, false)
|
||||
db.DBPath = dbfile
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
115
plugin/dish/dish.go
Normal file
115
plugin/dish/dish.go
Normal file
@@ -0,0 +1,115 @@
|
||||
// Package dish 程序员做饭指南zbp版,数据来源Anduin2017/HowToCook
|
||||
package dish
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type dish struct {
|
||||
ID uint32 `db:"id"`
|
||||
Name string `db:"name"`
|
||||
Materials string `db:"materials"`
|
||||
Steps string `db:"steps"`
|
||||
}
|
||||
|
||||
var (
|
||||
db = &sql.Sqlite{}
|
||||
initialized = false
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("dish", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "程序员做饭指南",
|
||||
Help: "-怎么做[xxx]|烹饪[xxx]|随机菜谱|随便做点菜",
|
||||
PublicDataFolder: "Dish",
|
||||
})
|
||||
|
||||
db.DBPath = en.DataFolder() + "dishes.db"
|
||||
|
||||
if _, err := en.GetLazyData("dishes.db", true); err != nil {
|
||||
logrus.Warnln("[dish]获取菜谱数据库文件失败")
|
||||
} else if err = db.Open(time.Hour); err != nil {
|
||||
logrus.Warnln("[dish]连接菜谱数据库失败")
|
||||
} else if err = db.Create("dish", &dish{}); err != nil {
|
||||
logrus.Warnln("[dish]同步菜谱数据表失败")
|
||||
} else if count, err := db.Count("dish"); err != nil {
|
||||
logrus.Warnln("[dish]统计菜谱数据失败")
|
||||
} else {
|
||||
logrus.Infoln("[dish]加载", count, "条菜谱")
|
||||
initialized = true
|
||||
}
|
||||
|
||||
if !initialized {
|
||||
logrus.Warnln("[dish]插件未能成功初始化")
|
||||
}
|
||||
|
||||
en.OnPrefixGroup([]string{"怎么做", "烹饪"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
if !initialized {
|
||||
ctx.SendChain(message.Text("客官,本店暂未开业"))
|
||||
return
|
||||
}
|
||||
|
||||
name := ctx.NickName()
|
||||
dishName := ctx.State["args"].(string)
|
||||
|
||||
if dishName == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(dishName, "'") ||
|
||||
strings.Contains(dishName, "\"") ||
|
||||
strings.Contains(dishName, "\\") ||
|
||||
strings.Contains(dishName, ";") {
|
||||
return
|
||||
}
|
||||
|
||||
var d dish
|
||||
if err := db.Find("dish", &d, fmt.Sprintf("WHERE name like %%%s%%", dishName)); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.SendChain(message.Text(fmt.Sprintf(
|
||||
"已为客官%s找到%s的做法辣!\n"+
|
||||
"原材料:%s\n"+
|
||||
"步骤:\n"+
|
||||
"%s",
|
||||
name, dishName, d.Materials, d.Steps),
|
||||
))
|
||||
})
|
||||
|
||||
en.OnPrefixGroup([]string{"随机菜谱", "随便做点菜"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
if !initialized {
|
||||
ctx.SendChain(message.Text("客官,本店暂未开业"))
|
||||
return
|
||||
}
|
||||
|
||||
name := ctx.NickName()
|
||||
var d dish
|
||||
if err := db.Pick("dish", &d); err != nil {
|
||||
ctx.SendChain(message.Text("小店好像出错了,暂时端不出菜来惹"))
|
||||
logrus.Warnln("[dish]随机菜谱请求出错:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx.SendChain(message.Text(fmt.Sprintf(
|
||||
"已为客官%s送上%s的做法:\n"+
|
||||
"原材料:%s\n"+
|
||||
"步骤:\n"+
|
||||
"%s",
|
||||
name, d.Name, d.Materials, d.Steps),
|
||||
))
|
||||
})
|
||||
}
|
||||
253
plugin/drawlots/main.go
Normal file
253
plugin/drawlots/main.go
Normal file
@@ -0,0 +1,253 @@
|
||||
// Package drawlots 多功能抽签插件
|
||||
package drawlots
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/fumiama/jieba/util/helper"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type info struct {
|
||||
lotsType string // 文件后缀
|
||||
quantity int // 签数
|
||||
}
|
||||
|
||||
var (
|
||||
lotsList = func() map[string]info {
|
||||
lotsList, err := getList()
|
||||
if err != nil {
|
||||
logrus.Infoln("[drawlots]加载失败:", err)
|
||||
} else {
|
||||
logrus.Infoln("[drawlots]加载", len(lotsList), "个抽签")
|
||||
}
|
||||
return lotsList
|
||||
}()
|
||||
en = control.Register("drawlots", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "多功能抽签",
|
||||
Help: "支持图包文件夹和gif抽签\n" +
|
||||
"-------------\n" +
|
||||
"- (刷新)抽签列表\n- 抽[签名]签\n- 看[gif签名]签\n- 加[签名]签[gif图片]\n- 删[gif签名]签",
|
||||
PrivateDataFolder: "drawlots",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
datapath = file.BOTPATH + "/" + en.DataFolder()
|
||||
)
|
||||
|
||||
func init() {
|
||||
en.OnFullMatchGroup([]string{"抽签列表", "刷新抽签列表"}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
lotsList, err := getList() // 刷新列表
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
messageText := &strings.Builder{}
|
||||
messageText.WriteString(" 签 名 [ 类 型 ]----签数\n")
|
||||
messageText.WriteString("———————————\n")
|
||||
for name, fileInfo := range lotsList {
|
||||
messageText.WriteString(name + "[" + fileInfo.lotsType + "]----" + strconv.Itoa(fileInfo.quantity) + "\n")
|
||||
messageText.WriteString("----------\n")
|
||||
}
|
||||
textPic, err := text.RenderToBase64(messageText.String(), text.BoldFontFile, 400, 50)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + helper.BytesToString(textPic)))
|
||||
})
|
||||
en.OnRegex(`^抽(.+)签$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
lotsType := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsType]
|
||||
if !ok {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("才...才没有", lotsType, "签这种东西啦")))
|
||||
return
|
||||
}
|
||||
if fileInfo.lotsType == "folder" {
|
||||
picPath, err := randFile(lotsType, 3)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("file:///"+picPath))
|
||||
return
|
||||
}
|
||||
lotsImg, err := randGif(lotsType + "." + fileInfo.lotsType)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 生成图片
|
||||
data, err := imgfactory.ToBytes(lotsImg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.ImageBytes(data))
|
||||
})
|
||||
en.OnRegex(`^看(.+)签$`, zero.UserOrGrpAdmin).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsName]
|
||||
if !ok {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
|
||||
return
|
||||
}
|
||||
if fileInfo.lotsType == "folder" {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("只能查看gif签哦~")))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Image("file:///"+datapath+lotsName+"."+fileInfo.lotsType)))
|
||||
})
|
||||
en.OnRegex(`^加(.+)签.*`, zero.SuperUserPermission, zero.MustProvidePicture).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
if lotsName == "" {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("请使用正确的指令形式哦~")))
|
||||
return
|
||||
}
|
||||
picURL := ctx.State["image_url"].([]string)[0]
|
||||
gifdata, err := web.GetData(picURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
im, err := gif.DecodeAll(bytes.NewReader(gifdata))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
fileName := datapath + "/" + lotsName + ".gif"
|
||||
err = file.DownloadTo(picURL, fileName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
lotsList[lotsName] = info{
|
||||
lotsType: "gif",
|
||||
quantity: len(im.Image),
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("成功!")))
|
||||
})
|
||||
en.OnRegex(`^删(.+)签$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsName]
|
||||
if !ok {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
|
||||
return
|
||||
}
|
||||
if fileInfo.lotsType == "folder" {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("为了防止误删图源,图包请手动移除哦~")))
|
||||
return
|
||||
}
|
||||
err := os.Remove(datapath + lotsName + "." + fileInfo.lotsType)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
delete(lotsList, lotsName)
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("成功!")))
|
||||
})
|
||||
}
|
||||
|
||||
func getList() (list map[string]info, err error) {
|
||||
list = make(map[string]info, 100)
|
||||
files, err := os.ReadDir(datapath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(files) == 0 {
|
||||
err = errors.New("什么签也没有哦~")
|
||||
return
|
||||
}
|
||||
for _, lots := range files {
|
||||
if lots.IsDir() {
|
||||
files, _ := os.ReadDir(datapath + "/" + lots.Name())
|
||||
list[lots.Name()] = info{
|
||||
lotsType: "folder",
|
||||
quantity: len(files),
|
||||
}
|
||||
continue
|
||||
}
|
||||
before, after, ok := strings.Cut(lots.Name(), ".")
|
||||
if !ok || before == "" {
|
||||
continue
|
||||
}
|
||||
file, err := os.Open(datapath + "/" + lots.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
im, err := gif.DecodeAll(file)
|
||||
_ = file.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list[before] = info{
|
||||
lotsType: after,
|
||||
quantity: len(im.Image),
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func randFile(path string, indexMax int) (string, error) {
|
||||
picPath := datapath + path
|
||||
files, err := os.ReadDir(picPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(files) > 0 {
|
||||
drawFile := files[rand.Intn(len(files))]
|
||||
// 如果是文件夹就递归
|
||||
if drawFile.IsDir() {
|
||||
indexMax--
|
||||
if indexMax <= 0 {
|
||||
return "", errors.New("图包[" + path + "]存在太多非图片文件,请清理~")
|
||||
}
|
||||
return randFile(path, indexMax)
|
||||
}
|
||||
return picPath + "/" + drawFile.Name(), err
|
||||
}
|
||||
return "", errors.New("图包[" + path + "]不存在签内容!")
|
||||
}
|
||||
|
||||
func randGif(gifName string) (image.Image, error) {
|
||||
name := datapath + gifName
|
||||
file, err := os.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
im, err := gif.DecodeAll(file)
|
||||
_ = file.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
/*
|
||||
firstImg, err := imgfactory.Load(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v := im.Image[rand.Intn(len(im.Image))]
|
||||
return imgfactory.Size(firstImg, firstImg.Bounds().Dx(), firstImg.Bounds().Dy()).InsertUpC(v, 0, 0, firstImg.Bounds().Dx()/2, firstImg.Bounds().Dy()/2).Clone().Image(),err
|
||||
/*/
|
||||
// 如果gif图片出现信息缺失请使用上面注释掉的代码,把下面注释了(上面代码部分图存在bug)
|
||||
v := im.Image[rand.Intn(len(im.Image))]
|
||||
return imgfactory.NewFactoryBG(v.Rect.Dx(), v.Rect.Dy(), color.NRGBA{0, 0, 0, 255}).InsertUp(v, 0, 0, 0, 0).Clone().Image(), err
|
||||
// */
|
||||
}
|
||||
39
plugin/dress/api.go
Normal file
39
plugin/dress/api.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package dress
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
const (
|
||||
dressURL = "http://www.yoooooooooo.com/gitdress"
|
||||
male = "dress"
|
||||
female = "girldress"
|
||||
dressListURL = dressURL + "/%v/album/list.json"
|
||||
dressDetailURL = dressURL + "/%v/album/%v/info.json"
|
||||
dressImageURL = dressURL + "/%v/album/%v/%v-m.webp"
|
||||
)
|
||||
|
||||
func dressList(sex string) (dressList []string, err error) {
|
||||
data, err := web.GetData(fmt.Sprintf(dressListURL, sex))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
arr := gjson.ParseBytes(data).Get("@this").Array()
|
||||
dressList = make([]string, len(arr))
|
||||
for i, v := range arr {
|
||||
dressList[i] = v.String()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func detail(sex, name string) (count int, err error) {
|
||||
data, err := web.GetData(fmt.Sprintf(dressDetailURL, sex, name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = int(gjson.ParseBytes(data).Get("@this.#").Int())
|
||||
return
|
||||
}
|
||||
113
plugin/dress/dress.go
Normal file
113
plugin/dress/dress.go
Normal file
@@ -0,0 +1,113 @@
|
||||
// Package dress 女装
|
||||
package dress
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"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() { // 插件主体
|
||||
engine := control.Register("dress", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "女装",
|
||||
Help: "女装\n" +
|
||||
"- 女装\n" +
|
||||
"- 男装\n" +
|
||||
"- 随机女装\n" +
|
||||
"- 随机男装",
|
||||
PrivateDataFolder: "dress",
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"女装", "男装"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
matched := ctx.State["matched"].(string)
|
||||
sex := male
|
||||
if matched == "男装" {
|
||||
sex = female
|
||||
}
|
||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
nameList, err := dressList(sex)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
tex := "请输入" + matched + "序号\n"
|
||||
for i, v := range nameList {
|
||||
tex += fmt.Sprintf("%d. %s\n", i, v)
|
||||
}
|
||||
base64Str, err := text.RenderToBase64(tex, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(base64Str)))
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.SendChain(message.Text(matched, "指令过期"))
|
||||
return
|
||||
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 >= len(nameList) {
|
||||
ctx.SendChain(message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
name := nameList[num]
|
||||
sendImage(ctx, sex, matched, name)
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"随机女装", "随机男装"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
matched := strings.TrimPrefix(ctx.State["matched"].(string), "随机")
|
||||
sex := male
|
||||
if matched == "男装" {
|
||||
sex = female
|
||||
}
|
||||
nameList, err := dressList(sex)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
name := nameList[rand.Intn(len(nameList))]
|
||||
sendImage(ctx, sex, matched, name)
|
||||
})
|
||||
}
|
||||
|
||||
func sendImage(ctx *zero.Ctx, sex, matched, name string) {
|
||||
ctx.SendChain(message.Text("请欣赏", matched, ": ", name))
|
||||
count, err := detail(sex, name)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
imageList := make([]string, count)
|
||||
for i := range imageList {
|
||||
imageList[i] = fmt.Sprintf(dressImageURL, sex, name, i+1)
|
||||
}
|
||||
m := message.Message{}
|
||||
for _, v := range imageList {
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(v)))
|
||||
}
|
||||
if id := ctx.Send(m).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
}
|
||||
@@ -35,11 +35,12 @@ var seaLocker sync.RWMutex
|
||||
func init() {
|
||||
en := control.Register("driftbottle", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "简单的漂流瓶\n" + "- @bot pick" + "- @bot throw xxx (xxx为投递内容)",
|
||||
Brief: "漂流瓶",
|
||||
Help: "- @bot pick" + "- @bot throw xxx (xxx为投递内容)",
|
||||
PrivateDataFolder: "driftbottle",
|
||||
})
|
||||
seaSide.DBPath = en.DataFolder() + "sea.db"
|
||||
err := seaSide.Open(time.Hour * 24)
|
||||
err := seaSide.Open(time.Hour)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%
|
||||
func init() {
|
||||
control.Register("emojimix", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "合成emoji\n" +
|
||||
"- [emoji][emoji]",
|
||||
Brief: "合成emoji",
|
||||
Help: "- [emoji][emoji]",
|
||||
}).OnMessage(match).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
r := ctx.State["emojimix"].([]rune)
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
// Package epidemic 城市疫情查询
|
||||
package epidemic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
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 any `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
|
||||
}
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
func init() {
|
||||
engine := control.Register("event", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "好友申请以及群聊邀请事件处理,默认发送给主人列表第一位\n" +
|
||||
"- [开启|关闭]自动同意[申请|邀请|主人]\n" +
|
||||
Brief: "好友申请和群聊邀请事件处理",
|
||||
Help: "- [开启|关闭]自动同意[申请|邀请|主人]\n" +
|
||||
"- [同意|拒绝][申请|邀请][flag]\n" +
|
||||
"flag跟随事件一起发送, 默认同意主人的事件",
|
||||
"Tips: 信息默认发送给主人列表第一位, 默认同意所有主人的事件, flag跟随事件一起发送",
|
||||
})
|
||||
engine.On("request/group/invite").SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
@@ -2,7 +2,17 @@
|
||||
package font
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
@@ -14,10 +24,11 @@ import (
|
||||
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) {
|
||||
Brief: "渲染任意文字到图片",
|
||||
Help: "- (用[字体])渲染(抖动)文字xxx\n可选字体: [终末体|终末变体|紫罗兰体|樱酥体|Consolas体|粗苹方体|未来荧黑体|Gugi体|八丸体|Impact体|猫啃体|苹方体]",
|
||||
}).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]
|
||||
txt := ctx.State["regex_matched"].([]string)[3]
|
||||
switch fnt {
|
||||
case "用终末体":
|
||||
fnt = text.SyumatuFontFile
|
||||
@@ -29,16 +40,73 @@ func init() {
|
||||
fnt = text.SakuraFontFile
|
||||
case "用Consolas体":
|
||||
fnt = text.ConsolasFontFile
|
||||
case "用粗苹方体":
|
||||
fnt = text.BoldFontFile
|
||||
case "用未来荧黑体":
|
||||
fnt = text.GlowSansFontFile
|
||||
case "用Gugi体":
|
||||
fnt = text.GugiRegularFontFile
|
||||
case "用八丸体":
|
||||
fnt = text.HachiMaruPopRegularFontFile
|
||||
case "用Impact体":
|
||||
fnt = text.ImpactFontFile
|
||||
case "用猫啃体":
|
||||
fnt = text.MaokenFontFile
|
||||
case "用苹方体":
|
||||
fallthrough
|
||||
default:
|
||||
fnt = text.FontFile
|
||||
}
|
||||
b, err := text.RenderToBase64(txt, fnt, 400, 20)
|
||||
if ctx.State["regex_matched"].([]string)[2] == "" {
|
||||
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)))
|
||||
return
|
||||
}
|
||||
nilx, nily := 1.0, 8.0
|
||||
s := []*image.NRGBA{}
|
||||
strlist := strings.Split(txt, "\n")
|
||||
data, err := file.GetLazyData(fnt, control.Md5File, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
|
||||
// 获得画布预计
|
||||
testcov := gg.NewContext(1, 1)
|
||||
if err = testcov.ParseFontFace(data, 30); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 取最长段
|
||||
txt = ""
|
||||
for _, v := range strlist {
|
||||
if len([]rune(v)) > len([]rune(txt)) {
|
||||
txt = v
|
||||
}
|
||||
}
|
||||
w, h := testcov.MeasureString(txt)
|
||||
for i := 0; i < 10; i++ {
|
||||
cov := gg.NewContext(int(w+float64(len([]rune(txt)))*nilx)+40, int(h+nily)*len(strlist)+30)
|
||||
cov.SetRGB(1, 1, 1)
|
||||
cov.Clear()
|
||||
if err = cov.ParseFontFace(data, 30); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
cov.SetColor(color.NRGBA{R: 0, G: 0, B: 0, A: 127})
|
||||
for k, v := range strlist {
|
||||
for kk, vv := range []rune(v) {
|
||||
x, y := cov.MeasureString(string([]rune(v)[:kk]))
|
||||
cov.DrawString(string(vv), x+float64(rand.Intn(5))+10+nilx, y+float64(rand.Intn(5))+15+float64(k)*(y+nily))
|
||||
}
|
||||
}
|
||||
s = append(s, imgfactory.Size(cov.Image(), 0, 0).Image())
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
_ = gif.EncodeAll(&buf, imgfactory.MergeGif(5, s))
|
||||
ctx.SendChain(message.ImageBytes(buf.Bytes()))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/Coloured-glaze/gg" // 注册了 jpg png gif
|
||||
"github.com/FloatTech/gg" // 注册了 jpg png gif
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
@@ -19,7 +20,6 @@ import (
|
||||
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/img/writer"
|
||||
"github.com/FloatTech/floatbox/math"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
@@ -32,28 +32,27 @@ const (
|
||||
images = "data/Fortune/"
|
||||
// 基础文件位置
|
||||
omikujson = "data/Fortune/text.json"
|
||||
// 字体文件位置
|
||||
font = "data/Font/sakura.ttf"
|
||||
// 生成图缓存位置
|
||||
cache = images + "cache/"
|
||||
)
|
||||
|
||||
var (
|
||||
// 底图类型列表
|
||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录", "奇异恩典", "夏日口袋", "ASoul"}
|
||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录", "奇异恩典", "夏日口袋", "ASoul", "Hololive"}
|
||||
// 映射底图与 index
|
||||
index = make(map[string]uint8)
|
||||
// 签文
|
||||
omikujis []map[string]string
|
||||
fontdata []byte
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 插件主体
|
||||
en := control.Register("fortune", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "每日运势: \n" +
|
||||
"- 运势 | 抽签\n" +
|
||||
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录 | 奇异恩典 | 夏日口袋 | ASoul]",
|
||||
Brief: "每日运势",
|
||||
Help: "- 运势 | 抽签\n" +
|
||||
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录 | 奇异恩典 | 夏日口袋 | ASoul | Hololive]",
|
||||
PublicDataFolder: "Fortune",
|
||||
})
|
||||
_ = os.RemoveAll(cache)
|
||||
@@ -90,7 +89,7 @@ func init() {
|
||||
})
|
||||
en.OnFullMatchGroup([]string{"运势", "抽签"}, fcext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
data, err := file.GetLazyData(omikujson, false)
|
||||
data, err := file.GetLazyData(omikujson, control.Md5File, false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
@@ -100,10 +99,12 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
_, err = file.GetLazyData(font, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
if fontdata == nil {
|
||||
fontdata, err = file.GetLazyData("data/Font/sakura.ttf", control.Md5File, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
@@ -126,7 +127,7 @@ func init() {
|
||||
}
|
||||
// 检查背景图片是否存在
|
||||
zipfile := images + kind + ".zip"
|
||||
_, err := file.GetLazyData(zipfile, false)
|
||||
_, err := file.GetLazyData(zipfile, control.Md5File, false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -150,7 +151,7 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = draw(background, title, text, f)
|
||||
_, err = draw(background, fontdata, title, text, f)
|
||||
_ = f.Close()
|
||||
return err
|
||||
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
|
||||
@@ -189,19 +190,19 @@ func randimage(path string, ctx *zero.Ctx) (im image.Image, index int, err error
|
||||
// @param title 签名
|
||||
// @param text 签文
|
||||
// @return 错误信息
|
||||
func draw(back image.Image, title, txt string, f io.Writer) (int64, error) {
|
||||
func draw(back image.Image, fontdata []byte, title, txt string, f io.Writer) (int64, error) {
|
||||
canvas := gg.NewContext(back.Bounds().Size().Y, back.Bounds().Size().X)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
// 写标题
|
||||
canvas.SetRGB(1, 1, 1)
|
||||
if err := canvas.LoadFontFace(font, 45); err != nil {
|
||||
if err := canvas.ParseFontFace(fontdata, 45); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
sw, _ := canvas.MeasureString(title)
|
||||
canvas.DrawString(title, 140-sw/2, 112)
|
||||
// 写正文
|
||||
canvas.SetRGB(0, 0, 0)
|
||||
if err := canvas.LoadFontFace(font, 23); err != nil {
|
||||
if err := canvas.ParseFontFace(fontdata, 23); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
tw, th := canvas.MeasureString("测")
|
||||
@@ -230,7 +231,7 @@ func draw(back image.Image, title, txt string, f io.Writer) (int64, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return writer.WriteTo(canvas.Image(), f)
|
||||
return imgfactory.WriteTo(canvas.Image(), f)
|
||||
}
|
||||
|
||||
func offest(total, now int, distance float64) float64 {
|
||||
|
||||
@@ -26,8 +26,8 @@ var db = &sql.Sqlite{}
|
||||
func init() {
|
||||
en := control.Register("funny", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "讲个笑话\n" +
|
||||
"- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
|
||||
Brief: "讲个笑话",
|
||||
Help: "- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
|
||||
PublicDataFolder: "Funny",
|
||||
})
|
||||
|
||||
@@ -38,7 +38,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
"github.com/FloatTech/floatbox/img/writer"
|
||||
"github.com/FloatTech/floatbox/process"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
@@ -37,7 +37,8 @@ var (
|
||||
func init() {
|
||||
engine := control.Register("genshin", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "原神抽卡\n- 原神十连\n- 切换原神卡池",
|
||||
Brief: "原神模拟抽卡",
|
||||
Help: "- 原神十连\n- 切换原神卡池",
|
||||
PublicDataFolder: "Genshin",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
|
||||
@@ -99,7 +100,11 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
b, cl := writer.ToBytes(img)
|
||||
b, err := imgfactory.ToBytes(img)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if mode {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("恭喜你抽到了: \n", str), message.ImageBytes(b)))
|
||||
@@ -107,7 +112,6 @@ func init() {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("十连成功~"), message.ImageBytes(b)))
|
||||
}
|
||||
cl()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
|
||||
defer wg.Done()
|
||||
target := datapath + `materials/` + name
|
||||
if file.IsNotExist(target) {
|
||||
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA())
|
||||
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA(), nil)
|
||||
if err != nil {
|
||||
_ = os.Remove(target)
|
||||
exit(err)
|
||||
@@ -48,7 +48,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
|
||||
func dlblock(name string) (string, error) {
|
||||
target := datapath + `materials/` + name
|
||||
if file.IsNotExist(target) {
|
||||
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA())
|
||||
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA(), nil)
|
||||
if err != nil {
|
||||
_ = os.Remove(target)
|
||||
return "", err
|
||||
@@ -97,10 +97,10 @@ func newContext(user int64) *context {
|
||||
return c
|
||||
}
|
||||
|
||||
func loadFirstFrames(paths []string, size int) (imgs []*img.Factory, err error) {
|
||||
imgs = make([]*img.Factory, size)
|
||||
func loadFirstFrames(paths []string, size int) (imgs []*imgfactory.Factory, err error) {
|
||||
imgs = make([]*imgfactory.Factory, size)
|
||||
for i := range imgs {
|
||||
imgs[i], err = img.LoadFirstFrame(paths[i], 0, 0)
|
||||
imgs[i], err = imgfactory.LoadFirstFrame(paths[i], 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,36 +6,38 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/floatbox/process"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
)
|
||||
|
||||
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)
|
||||
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif")
|
||||
} else {
|
||||
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[0], w, h)
|
||||
frame, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
return frame.Circle(0).Image(), nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo2(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[1], w, h)
|
||||
frame, err := imgfactory.LoadFirstFrame(cc.headimgsdir[1], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
return frame.Circle(0).Image(), nil
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/Coloured-glaze/gg"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/img/writer"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
)
|
||||
|
||||
@@ -35,11 +35,11 @@ func pa(cc *context, args ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgf, err := img.LoadFirstFrame(f, 0, 0)
|
||||
imgf, err := imgfactory.LoadFirstFrame(f, 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertUp(tou, 100, 100, 0, 400).Im)
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgf.InsertUp(tou, 100, 100, 0, 400).Image())
|
||||
}
|
||||
|
||||
// si 撕
|
||||
@@ -50,8 +50,8 @@ func si(cc *context, args ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
im1 := img.Rotate(tou, 20, 380, 380)
|
||||
im2 := img.Rotate(tou, -12, 380, 380)
|
||||
im1 := imgfactory.Rotate(tou, 20, 380, 380)
|
||||
im2 := imgfactory.Rotate(tou, -12, 380, 380)
|
||||
if file.IsNotExist(datapath + "materials/si") {
|
||||
err = os.MkdirAll(datapath+"materials/si", 0755)
|
||||
if err != nil {
|
||||
@@ -62,11 +62,11 @@ func si(cc *context, args ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgf, err := img.LoadFirstFrame(f, 0, 0)
|
||||
imgf, err := imgfactory.LoadFirstFrame(f, 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertBottom(im1.Im, im1.W, im1.H, -3, 370).InsertBottom(im2.Im, im2.W, im2.H, 653, 310).Im)
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgf.InsertBottom(im1.Image(), im1.W(), im1.H(), -3, 370).InsertBottom(im2.Image(), im2.W(), im2.H(), 653, 310).Image())
|
||||
}
|
||||
|
||||
// flipV 上翻,下翻
|
||||
@@ -74,12 +74,12 @@ func flipV(cc *context, args ...string) (string, error) {
|
||||
_ = args
|
||||
name := cc.usrdir + "FlipV.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.FlipV().Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.FlipV().Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// flipH 左翻,右翻
|
||||
@@ -87,12 +87,12 @@ func flipH(cc *context, args ...string) (string, error) {
|
||||
_ = args
|
||||
name := cc.usrdir + "FlipH.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.FlipH().Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.FlipH().Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// invert 反色
|
||||
@@ -100,12 +100,12 @@ func invert(cc *context, args ...string) (string, error) {
|
||||
_ = args
|
||||
name := cc.usrdir + "Invert.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.Invert().Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.Invert().Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// blur 反色
|
||||
@@ -113,12 +113,12 @@ func blur(cc *context, args ...string) (string, error) {
|
||||
_ = args
|
||||
name := cc.usrdir + "Blur.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.Blur(10).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.Blur(10).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// grayscale 灰度
|
||||
@@ -126,12 +126,12 @@ func grayscale(cc *context, args ...string) (string, error) {
|
||||
_ = args
|
||||
name := cc.usrdir + "Grayscale.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.Grayscale().Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.Grayscale().Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// invertAndGrayscale 负片
|
||||
@@ -139,12 +139,12 @@ func invertAndGrayscale(cc *context, args ...string) (string, error) {
|
||||
_ = args
|
||||
name := cc.usrdir + "InvertAndGrayscale.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.Invert().Grayscale().Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.Invert().Grayscale().Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// convolve3x3 浮雕
|
||||
@@ -152,32 +152,32 @@ func convolve3x3(cc *context, args ...string) (string, error) {
|
||||
_ = args
|
||||
name := cc.usrdir + "Convolve3x3.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.Convolve3x3().Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.Relief().Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// rotate 旋转
|
||||
func rotate(cc *context, args ...string) (string, error) {
|
||||
name := cc.usrdir + "Rotate.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
r, _ := strconv.ParseFloat(args[0], 64)
|
||||
imgnrgba := img.Rotate(im.Im, r, 0, 0).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgfactory.Rotate(im.Image(), r, 0, 0).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// deformation 变形
|
||||
func deformation(cc *context, args ...string) (string, error) {
|
||||
name := cc.usrdir + "Deformation.png"
|
||||
// 加载图片
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -189,8 +189,8 @@ func deformation(cc *context, args ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := img.Size(im.Im, w, h).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgfactory.Size(im.Image(), w, h).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// alike 你像个xxx一样
|
||||
@@ -213,12 +213,12 @@ func alike(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Anyasuki.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 82, 69)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 82, 69)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertUp(im.Im, 0, 0, 136, 21).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertUp(im.Image(), 0, 0, 136, 21).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// marriage
|
||||
@@ -241,12 +241,12 @@ func marriage(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Marriage.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 1080, 1080)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 1080, 1080)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).InsertUp(imgs[1].Im, 0, 0, 800, 0).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 0, 0).InsertUp(imgs[1].Image(), 0, 0, 800, 0).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// anyasuki 阿尼亚喜欢
|
||||
@@ -274,14 +274,14 @@ func anyasuki(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
canvas := gg.NewContext(475, 540)
|
||||
canvas.DrawImage(img.Size(face, 347, 267).Im, 82, 53)
|
||||
canvas.DrawImage(imgfactory.Size(face, 347, 267).Image(), 82, 53)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 30); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -321,13 +321,13 @@ func alwaysLike(cc *context, args ...string) (string, error) {
|
||||
}
|
||||
canvas := gg.NewContext(830, 599)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.DrawImage(img.Size(face, 380, 380).Im, 44, 74)
|
||||
canvas.DrawImage(imgfactory.Size(face, 380, 380).Image(), 44, 74)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 56); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 56); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -362,12 +362,12 @@ func decentKiss(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "DecentKiss.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 589, 577)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 589, 577)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 0, 0).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// chinaFlag 国旗
|
||||
@@ -390,12 +390,12 @@ func chinaFlag(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "ChinaFlag.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 0, 0).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// dontTouch 不要靠近
|
||||
@@ -418,12 +418,12 @@ func dontTouch(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "DontTouch.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertUp(im.Im, 148, 148, 46, 238).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertUp(im.Image(), 148, 148, 46, 238).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// universal 万能表情 空白表情
|
||||
@@ -435,13 +435,13 @@ func universal(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
canvas := gg.NewContext(500, 550)
|
||||
canvas.DrawImage(img.Size(face, 500, 500).Im, 0, 0)
|
||||
canvas.DrawImage(imgfactory.Size(face, 500, 500).Image(), 0, 0)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 40); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -484,15 +484,15 @@ func interview(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
canvas := gg.NewContext(600, 300)
|
||||
canvas.DrawImage(img.Size(face, 124, 124).Im, 100, 50)
|
||||
canvas.DrawImage(imgfactory.Size(face, 124, 124).Image(), 100, 50)
|
||||
canvas.DrawImage(huaji, 376, 50)
|
||||
canvas.DrawImage(microphone, 300, 50)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 40); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -526,12 +526,12 @@ func need(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Need.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 114, 114)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 114, 114)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 327, 232).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 327, 232).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// paint 这像画吗
|
||||
@@ -554,12 +554,12 @@ func paint(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Paint.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 117, 135)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 117, 135)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 4, 0, 0).Im, 0, 0, 95, 107).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 4, 0, 0).Image(), 0, 0, 95, 107).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// painter 小画家
|
||||
@@ -582,12 +582,12 @@ func painter(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Painter.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 240, 345)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 240, 345)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 125, 91).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 125, 91).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// perfect 完美
|
||||
@@ -610,12 +610,12 @@ func perfect(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Perfect.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 310, 460)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 310, 460)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertUp(im.Im, 0, 0, 313, 64).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertUp(im.Image(), 0, 0, 313, 64).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// playGame 玩游戏
|
||||
@@ -643,14 +643,14 @@ func playGame(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
canvas := gg.NewContext(526, 503)
|
||||
canvas.DrawImage(img.Rotate(face, 10, 225, 160).Im, 161, 117)
|
||||
canvas.DrawImage(imgfactory.Rotate(face, 10, 225, 160).Image(), 161, 117)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 40); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -684,12 +684,12 @@ func police(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Police.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 245, 245)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 245, 245)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 224, 46).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 224, 46).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// police1 警察
|
||||
@@ -712,12 +712,12 @@ func police1(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Police1.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 60, 75)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 60, 75)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[1].InsertBottom(img.Rotate(im.Im, 16, 0, 0).Im, 0, 0, 37, 291).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[1].InsertBottom(imgfactory.Rotate(im.Image(), 16, 0, 0).Image(), 0, 0, 37, 291).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// prpr 舔 舔屏 prpr
|
||||
@@ -740,12 +740,12 @@ func prpr(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Prpr.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 330, 330)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 330, 330)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 8, 0, 0).Im, 0, 0, 46, 264).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 8, 0, 0).Image(), 0, 0, 46, 264).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// safeSense 安全感
|
||||
@@ -774,13 +774,13 @@ func safeSense(cc *context, args ...string) (string, error) {
|
||||
}
|
||||
canvas := gg.NewContext(430, 478)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.DrawImage(img.Size(face, 215, 343).Im, 215, 135)
|
||||
canvas.DrawImage(imgfactory.Size(face, 215, 343).Image(), 215, 135)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 30); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -816,12 +816,12 @@ func support(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Support.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 815, 815)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 815, 815)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 23, 0, 0).Im, 0, 0, -172, -17).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 23, 0, 0).Image(), 0, 0, -172, -17).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// thinkwhat 想什么
|
||||
@@ -844,12 +844,12 @@ func thinkwhat(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Thinkwhat.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 530, 0).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 530, 0).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// wallpaper 墙纸
|
||||
@@ -872,12 +872,12 @@ func wallpaper(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Wallpaper.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 775, 496)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 775, 496)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 260, 580).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 260, 580).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// whyatme 为什么at我
|
||||
@@ -900,12 +900,12 @@ func whyatme(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Whyatme.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 265, 265)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 265, 265)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 42, 13).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 42, 13).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// makeFriend 交个朋友
|
||||
@@ -933,16 +933,16 @@ func makeFriend(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
canvas := gg.NewContext(1000, 1000)
|
||||
canvas.DrawImage(img.Size(face, 1000, 1000).Im, 0, 0)
|
||||
canvas.DrawImage(img.Rotate(face, 9, 250, 250).Im, 743, 845)
|
||||
canvas.DrawImage(img.Rotate(face, 9, 55, 55).Im, 836, 722)
|
||||
canvas.DrawImage(imgfactory.Size(face, 1000, 1000).Image(), 0, 0)
|
||||
canvas.DrawImage(imgfactory.Rotate(face, 9, 250, 250).Image(), 743, 845)
|
||||
canvas.DrawImage(imgfactory.Rotate(face, 9, 55, 55).Image(), 836, 722)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.SetColor(color.White)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 20); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 20); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -977,12 +977,12 @@ func backToWork(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "BackToWork.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 220, 310)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 220, 310)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 25, 0, 0).Im, 0, 0, 56, 32).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 25, 0, 0).Image(), 0, 0, 56, 32).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// coupon 兑换券
|
||||
@@ -1015,13 +1015,13 @@ func coupon(cc *context, args ...string) (string, error) {
|
||||
canvas := gg.NewContext(500, 355)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.Rotate(gg.Radians(-22))
|
||||
canvas.DrawImage(img.Size(face, 60, 60).Im, 100, 163)
|
||||
canvas.DrawImage(imgfactory.Size(face, 60, 60).Image(), 100, 163)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 30); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -1056,12 +1056,12 @@ func distracted(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "Distracted.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 500, 500)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 500, 500)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 140, 320).InsertUp(imgs[1].Im, 0, 0, 0, 0).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 140, 320).InsertUp(imgs[1].Image(), 0, 0, 0, 0).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// throw 扔
|
||||
@@ -1088,8 +1088,8 @@ func throw(cc *context, args ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertUpC(img.Rotate(face, float64(rand.Intn(360)), 143, 143).Im, 0, 0, 86, 249).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertUpC(imgfactory.Rotate(face, float64(rand.Intn(360)), 143, 143).Image(), 0, 0, 86, 249).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// 远离
|
||||
@@ -1112,12 +1112,12 @@ func yuanli(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "yuanli.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 420, 420, 45, 90).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 420, 420, 45, 90).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// 不是你老婆
|
||||
@@ -1140,12 +1140,12 @@ func nowife(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "nowife.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 400, 400, 112, 81).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 400, 400, 112, 81).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// youer 你老婆
|
||||
@@ -1174,13 +1174,13 @@ func youer(cc *context, args ...string) (string, error) {
|
||||
}
|
||||
canvas := gg.NewContext(690, 690)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.DrawImage(img.Size(tou, 350, 350).Im, 55, 165)
|
||||
canvas.DrawImage(imgfactory.Size(tou, 350, 350).Image(), 55, 165)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 56); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 56); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -1221,13 +1221,13 @@ func xiaotianshi(cc *context, args ...string) (string, error) {
|
||||
}
|
||||
canvas := gg.NewContext(522, 665)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.DrawImage(img.Size(face, 480, 480).Im, 20, 80)
|
||||
canvas.DrawImage(imgfactory.Size(face, 480, 480).Image(), 20, 80)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 35); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 35); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -1262,12 +1262,12 @@ func neko(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "neko.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 712, 949)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 712, 949)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 0, 0, 0).Im, 450, 450, 0, 170).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 0, 0, 0).Image(), 450, 450, 0, 170).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// 给我变
|
||||
@@ -1291,12 +1291,12 @@ func bian(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "bian.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 640, 550)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 640, 550)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 0, 0, 0).Im, 380, 380, 225, -20).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 0, 0, 0).Image(), 380, 380, 225, -20).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// van 玩一下
|
||||
@@ -1325,13 +1325,13 @@ func van(cc *context, args ...string) (string, error) {
|
||||
}
|
||||
canvas := gg.NewContext(522, 665)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.DrawImage(img.Size(face, 480, 480).Im, 20, 80)
|
||||
canvas.DrawImage(imgfactory.Size(face, 480, 480).Image(), 20, 80)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 35); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 35); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
@@ -1366,12 +1366,12 @@ func eihei(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "eihei.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 690, 690)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 690, 690)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 450, 450, 121, 162).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 450, 450, 121, 162).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// fanfa 犯法
|
||||
@@ -1398,9 +1398,9 @@ func fanfa(cc *context, args ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
m1 := img.Rotate(face, 45, 110, 110)
|
||||
imgnrgba := imgs[0].InsertUp(m1.Im, 0, 0, 125, 360).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
m1 := imgfactory.Rotate(face, 45, 110, 110)
|
||||
imgnrgba := imgs[0].InsertUp(m1.Image(), 0, 0, 125, 360).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// huai 怀
|
||||
@@ -1423,12 +1423,12 @@ func huai(cc *context, args ...string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
name := cc.usrdir + "huai.png"
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 640, 640)
|
||||
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 640, 640)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(im.Im, 640, 640, 0, 0).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(im.Image(), 640, 640, 0, 0).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// haowan 好玩
|
||||
@@ -1455,8 +1455,8 @@ func haowan(cc *context, args ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgnrgba := imgs[0].InsertBottom(face, 90, 90, 321, 172).Im
|
||||
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
|
||||
imgnrgba := imgs[0].InsertBottom(face, 90, 90, 321, 172).Image()
|
||||
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
|
||||
}
|
||||
|
||||
// mengbi 蒙蔽
|
||||
@@ -1485,14 +1485,14 @@ func mengbi(cc *context, args ...string) (string, error) {
|
||||
}
|
||||
canvas := gg.NewContext(1080, 1080)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
canvas.DrawImage(img.Size(face, 100, 100).Im, 392, 460)
|
||||
canvas.DrawImage(img.Size(face, 100, 100).Im, 606, 443)
|
||||
canvas.DrawImage(imgfactory.Size(face, 100, 100).Image(), 392, 460)
|
||||
canvas.DrawImage(imgfactory.Size(face, 100, 100).Image(), 606, 443)
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, 80); err != nil {
|
||||
if err = canvas.ParseFontFace(data, 80); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args[0] == "" {
|
||||
|
||||
@@ -128,20 +128,25 @@ func init() { // 插件主体
|
||||
}
|
||||
en := control.Register("gif", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "GIF制图,命令后艾特群友/QQ号/一张图方可触发命令\n其中XXX可以为任何文字,可以不写\n对机器人操作请先艾特机器人再执行命令\n" +
|
||||
"- 搓|-冲|-摸|-拍|-丢|-吃|-敲|-啃|-蹭|-爬|-撕|-灰度|-上翻|-下翻\n" +
|
||||
"- 左翻|-右翻|-反色|-浮雕|- 打码|- 负片|- 旋转|- 变形|- 亲\n" +
|
||||
"- 结婚申请|结婚登记|- 阿尼亚喜欢XXX|- 像只|- 我永远喜欢XXX\n" +
|
||||
"- 像样的亲亲|- 国旗|- 不要靠近|- 万能表情|-空白表情|- 采访\n" +
|
||||
"- 需要|-你可能需要|- 这像画吗|- 小画家|- 完美|- 玩游戏|- 出警\n" +
|
||||
"- 警察|- 舔|舔屏|prpr|- 安全感|- 精神支柱|- 想什么|- 墙纸\n" +
|
||||
"- 为什么at我|- 交个朋友|- 打工人|-继续干活|- 兑换券|- 炖\n" +
|
||||
"- 垃圾桶|- 垃圾|- 捶|- 啾啾|- 2敲|- 听音乐|- 永远爱你|- 2拍\n" +
|
||||
"- 顶|- 捣|- 打拳|- 滚|- 吸|- 嗦|- 扔|- 锤|- 紧贴|紧紧贴着|- 转\n" +
|
||||
"- 抬棺|- 远离|- 我老婆|- 小天使XXX|- 你的XXX|- 不要看\n" +
|
||||
"- 玩一下XXX|- 给我变|- 揍|- 吞|- 膜拜|- 诶嘿|- 2蹭|- 你犯法了\n" +
|
||||
"- 砰|- 注意力涣散|- 蒙蔽|- 踩|- 好玩|- 2转|- 踢球|- 2舔|\n" +
|
||||
"- 可莉吃|- 胡桃啃|- 怀|- 一直(支持动图)",
|
||||
Brief: "制图",
|
||||
Help: "下为制图命令:\n" +
|
||||
"- 搓|- 冲|- 摸|-拍|- 丢|- 吃|- 敲|- 啃|- 蹭|- 爬|- 撕\n" +
|
||||
"- 吸|- 嗦|- 扔|- 锤|- 紧贴|紧紧贴着|- 转|- 抬棺|- 远离\n" +
|
||||
"- 揍|- 吞|- 膜拜|- 诶嘿|- 2蹭|- 你犯法了|- 砰|- 注意力涣散\n" +
|
||||
"- 2敲|- 听音乐|- 永远爱你|- 2拍|- 顶|- 捣|- 打拳|- 滚\n" +
|
||||
"- 灰度|- 上翻|- 下翻|- 左翻|- 右翻|- 反色|- 浮雕|- 打码\n" +
|
||||
"- 负片|- 旋转|- 变形|- 亲|- 结婚申请|结婚登记|- 阿尼亚喜欢XXX\n" +
|
||||
"- 像只|- 我永远喜欢XXX|- 像样的亲亲|- 国旗|- 不要靠近\n" +
|
||||
"- 蒙蔽|- 踩|- 好玩|- 2转|- 踢球|- 2舔|- 可莉吃|- 胡桃啃|- 怀\n" +
|
||||
"- 小画家|- 完美|- 玩游戏|- 出警|- 警察|- 舔|舔屏|prpr\n" +
|
||||
"- 安全感|- 精神支柱|- 想什么|- 墙纸|- 为什么at我|- 交个朋友\n" +
|
||||
"- 打工人|- 继续干活|- 兑换券|- 炖|- 垃圾桶|- 垃圾|- 捶|- 啾啾\n" +
|
||||
"- 我老婆|- 小天使XXX|- 你的XXX|- 不要看|- 玩一下XXX|- 给我变\n" +
|
||||
"- 万能表情|- 空白表情|- 采访|- 需要|- 你可能需要|- 这像画吗\n" +
|
||||
"- 一直(支持动图)\n" +
|
||||
"例: 制图命令XXX[@用户|QQ号|图片]\n" +
|
||||
"Tips: XXX可以为限制长度的任何文字\n" +
|
||||
"对Bot使用为 @Bot制图命令[XXX]@Bot",
|
||||
PrivateDataFolder: "gif",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
datapath = file.BOTPATH + "/" + en.DataFolder()
|
||||
|
||||
@@ -20,8 +20,8 @@ import (
|
||||
func init() { // 插件主体
|
||||
control.Register("github", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "GitHub仓库搜索\n" +
|
||||
"- >github [xxx]\n" +
|
||||
Brief: "GitHub仓库搜索",
|
||||
Help: "- >github [xxx]\n" +
|
||||
"- >github -p [xxx]",
|
||||
}).OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
473
plugin/guessmusic/apiservice.go
Normal file
473
plugin/guessmusic/apiservice.go
Normal file
@@ -0,0 +1,473 @@
|
||||
package guessmusic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
wyy "github.com/FloatTech/AnimeAPI/neteasemusic"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/pkg/errors"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// API配置
|
||||
engine.OnPrefix("设置猜歌API", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
option := ctx.State["args"].(string)
|
||||
if option == "帮助" {
|
||||
ctx.SendChain(message.Text(
|
||||
"项目地址:binaryify.github.io/NeteaseCloudMusicApi" +
|
||||
"\n网上有基于该框架的API,可以自行搜索白嫖。\n" +
|
||||
"添加API指令:\n设置猜歌API [API首页网址]"))
|
||||
return
|
||||
}
|
||||
if !strings.HasSuffix(option, "/") {
|
||||
option += "/"
|
||||
}
|
||||
cfg.APIURL = option
|
||||
err := saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
}
|
||||
})
|
||||
// API配置
|
||||
engine.OnRegex(`^猜歌(开启|关闭)(歌单|歌词)自动下载`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
swtich := ctx.State["regex_matched"].([]string)[1]
|
||||
option := ctx.State["regex_matched"].([]string)[2]
|
||||
chose := true
|
||||
if swtich == "关闭" {
|
||||
chose = false
|
||||
}
|
||||
if option == "歌单" {
|
||||
cfg.API = chose
|
||||
} else {
|
||||
cfg.Local = chose
|
||||
}
|
||||
err := saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("登录网易云", zero.SuperUserPermission, func(ctx *zero.Ctx) bool {
|
||||
if !zero.OnlyPrivate(ctx) {
|
||||
ctx.SendChain(message.Text("为了保护登录过程,请bot主人私聊。"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyURL := cfg.APIURL + "login/qr/key"
|
||||
data, err := web.GetData(keyURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, "获取网易云key失败,", err))
|
||||
return
|
||||
}
|
||||
var keyInfo keyInfo
|
||||
err = json.Unmarshal(data, &keyInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, "解析网易云key失败,", err))
|
||||
return
|
||||
}
|
||||
qrURL := cfg.APIURL + "login/qr/create?key=" + keyInfo.Data.Unikey + "&qrimg=1"
|
||||
data, err = web.GetData(qrURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, "获取网易云二维码失败,", err))
|
||||
return
|
||||
}
|
||||
var qrInfo qrInfo
|
||||
err = json.Unmarshal(data, &qrInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, "解析网易云二维码失败,", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("[请使用手机APP扫描二维码或者进入网页扫码登录]\n", qrInfo.Data.Qrurl),
|
||||
message.Image("base64://"+strings.ReplaceAll(qrInfo.Data.Qrimg, "data:image/png;base64,", "")),
|
||||
message.Text("二维码有效时间为6分钟,登陆后请耐心等待结果,获取cookie过程有些漫长。"))
|
||||
i := 0
|
||||
for range time.NewTicker(10 * time.Second).C {
|
||||
APIURL := cfg.APIURL + "login/qr/check?key=" + url.QueryEscape(keyInfo.Data.Unikey)
|
||||
data, err := web.GetData(APIURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, "无法获取登录状态,", err))
|
||||
return
|
||||
}
|
||||
var cookiesInfo cookyInfo
|
||||
err = json.Unmarshal(data, &cookiesInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, "解析登录状态失败,", err))
|
||||
return
|
||||
}
|
||||
switch cookiesInfo.Code {
|
||||
case 803:
|
||||
cfg.Cookie = cookiesInfo.Cookie
|
||||
err = saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
}
|
||||
return
|
||||
case 801:
|
||||
i++
|
||||
if i%6 == 0 { // 每1分钟才提醒一次,减少提示(380/60=6次)
|
||||
ctx.SendChain(message.Text("状态:", cookiesInfo.Message))
|
||||
}
|
||||
continue
|
||||
case 800:
|
||||
ctx.SendChain(message.Text("状态:", cookiesInfo.Message))
|
||||
return
|
||||
default:
|
||||
ctx.SendChain(message.Text("状态:", cookiesInfo.Message))
|
||||
continue
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^歌单信息\s*((https:\/\/music\.163\.com\/#\/playlist\?id=)?(\d+)|http:\/\/music\.163\.com\/playlist\/(\d+).*)$`).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
listID := ctx.State["regex_matched"].([]string)[3] + ctx.State["regex_matched"].([]string)[4]
|
||||
_, err := strconv.ParseInt(listID, 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("请输入正确的歌单ID或者歌单连接"))
|
||||
return
|
||||
}
|
||||
APIURL := cfg.APIURL + "playlist/detail?id=" + listID
|
||||
data, err := web.GetData(APIURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("无法连接歌单,", err))
|
||||
return
|
||||
}
|
||||
var parsed listInfoOfAPI
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("无法解析歌单ID内容,", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Image(parsed.Playlist.CoverImgURL),
|
||||
message.Text(
|
||||
"歌单名称:", parsed.Playlist.Name,
|
||||
"\n歌单ID:", parsed.Playlist.ID,
|
||||
"\n创建人:", parsed.Playlist.Creator.Nickname,
|
||||
"\n创建时间:", time.Unix(parsed.Playlist.CreateTime/1000, 0).Format("2006-01-02"),
|
||||
"\n标签:", strings.Join(parsed.Playlist.Tags, ";"),
|
||||
"\n歌曲数量:", parsed.Playlist.TrackCount,
|
||||
"\n歌单简介:\n", parsed.Playlist.Description,
|
||||
"\n更新时间:", time.Unix(parsed.Playlist.UpdateTime/1000, 0).Format("2006-01-02"),
|
||||
))
|
||||
})
|
||||
// 本地绑定网易云歌单ID
|
||||
engine.OnRegex(`^(.*)绑定网易云\s*((https:\/\/music\.163\.com\/#\/playlist\?id=)?(\d+)|http:\/\/music\.163\.com\/playlist\/(\d+).*)$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
listName := ctx.State["regex_matched"].([]string)[1]
|
||||
listID := ctx.State["regex_matched"].([]string)[4] + ctx.State["regex_matched"].([]string)[5]
|
||||
ctx.SendChain(message.Text("正在校验歌单信息,请稍等"))
|
||||
pathOfMusic := cfg.MusicPath + listName + "/"
|
||||
if file.IsNotExist(pathOfMusic) {
|
||||
ctx.SendChain(message.Text(serviceErr, "歌单不存在于本地"))
|
||||
return
|
||||
}
|
||||
// 是否存在该歌单
|
||||
APIURL := cfg.APIURL + "playlist/track/all?id=" + listID
|
||||
data, err := web.GetData(APIURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
return
|
||||
}
|
||||
var parsed musicListOfApI
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, "无法解析歌单ID内容,", err))
|
||||
return
|
||||
}
|
||||
if parsed.Code != 200 {
|
||||
ctx.SendChain(message.Text(serviceErr, parsed.Code))
|
||||
return
|
||||
}
|
||||
mid, _ := strconv.ParseInt(listID, 10, 64)
|
||||
cfg.Playlist = append(cfg.Playlist, listRaw{
|
||||
Name: listName,
|
||||
ID: mid,
|
||||
})
|
||||
err = saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
}
|
||||
})
|
||||
engine.OnPrefix("解除绑定", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
delList := ctx.State["args"].(string)
|
||||
filelist, err := getlist(cfg.MusicPath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
return
|
||||
}
|
||||
var playID int64
|
||||
for _, listinfo := range filelist {
|
||||
if delList == listinfo.Name {
|
||||
playID = listinfo.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
// 删除ID
|
||||
if playID == 0 { // 如果ID没有且没删除文件
|
||||
ctx.SendChain(message.Text("歌单名称错误或者该歌单并没有绑定网易云,可以发送“歌单列表”获取歌单名称"))
|
||||
return
|
||||
}
|
||||
index := -1
|
||||
for i, list := range cfg.Playlist {
|
||||
if playID == list.ID {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if index == -1 {
|
||||
ctx.SendChain(message.Text("歌单名称错误或者该歌单并没有绑定网易云,可以发送“歌单列表”获取歌单名称"))
|
||||
return
|
||||
}
|
||||
cfg.Playlist = append(cfg.Playlist[:index], cfg.Playlist[index+1:]...)
|
||||
err = saveConfig(cfgFile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
}
|
||||
})
|
||||
// 下载歌曲到对应的歌单里面
|
||||
engine.OnRegex(`^下载歌单\s*((https:\/\/music\.163\.com\/#\/playlist\?id=)?(\d+)|http:\/\/music\.163\.com\/playlist\/(\d+).*[^\s$])\s*到\s*(.*)$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[3] + ctx.State["regex_matched"].([]string)[4]
|
||||
listName := ctx.State["regex_matched"].([]string)[5]
|
||||
ctx.SendChain(message.Text("正在校验歌单信息,请稍等"))
|
||||
// 是否存在该歌单
|
||||
if file.IsNotExist(cfg.MusicPath + listName) {
|
||||
ctx.SendChain(message.Text("歌单不存在,是否创建?(是/否)"))
|
||||
next := zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`(是|否)`), ctx.CheckSession())
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
wait := time.NewTimer(120 * time.Second)
|
||||
answer := ""
|
||||
for {
|
||||
select {
|
||||
case <-wait.C:
|
||||
wait.Stop()
|
||||
ctx.SendChain(message.Text("等待超时,取消下载"))
|
||||
return
|
||||
case c := <-recv:
|
||||
wait.Stop()
|
||||
answer = c.Event.Message.String()
|
||||
}
|
||||
if answer == "否" {
|
||||
ctx.SendChain(message.Text("下载已经取消"))
|
||||
return
|
||||
}
|
||||
if answer != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
err := os.MkdirAll(cfg.MusicPath+listName, 0755)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.SendChain(message.Text("开始下载歌曲,需要一定时间下载,请稍等"))
|
||||
listID, err := strconv.ParseInt(keyword, 10, 64)
|
||||
if err == nil {
|
||||
err = downloadlist(listID, cfg.MusicPath+listName+"/")
|
||||
}
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 随机从歌单下载歌曲(歌单ID, 音乐保存路径)
|
||||
func drawByAPI(playlistID int64, musicPath string) (musicName string, err error) {
|
||||
APIURL := cfg.APIURL + "playlist/track/all?id=" + strconv.FormatInt(playlistID, 10)
|
||||
data, err := web.GetData(APIURL)
|
||||
if err != nil {
|
||||
err = errors.Errorf("无法获取歌单列表\n%s", err)
|
||||
return
|
||||
}
|
||||
var parsed musicListOfApI
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
err = errors.Errorf("无法读取歌单列表\n%s", err)
|
||||
return
|
||||
}
|
||||
listlen := len(parsed.Songs)
|
||||
randidx := rand.Intn(listlen)
|
||||
// 将"/"符号去除,不然无法生成文件
|
||||
name := strings.ReplaceAll(parsed.Songs[randidx].Name, "/", "·")
|
||||
musicID := parsed.Songs[randidx].ID
|
||||
artistName := ""
|
||||
for i, ARInfo := range parsed.Songs[randidx].Ar {
|
||||
if i != 0 {
|
||||
artistName += "&" + ARInfo.Name
|
||||
} else {
|
||||
artistName += ARInfo.Name
|
||||
}
|
||||
}
|
||||
cource := ""
|
||||
if parsed.Songs[randidx].Alia != nil {
|
||||
cource = strings.Join(parsed.Songs[randidx].Alia, "&")
|
||||
// 将"/"符号去除,不然无法下载
|
||||
cource = strings.ReplaceAll(cource, "/", "&")
|
||||
}
|
||||
if name == "" || musicID == 0 {
|
||||
err = errors.New("无法获API取歌曲信息")
|
||||
return
|
||||
}
|
||||
if cource != "" {
|
||||
name += " - " + artistName + " - " + cource
|
||||
} else {
|
||||
name += " - " + artistName
|
||||
}
|
||||
// 下载歌曲
|
||||
err = wyy.DownloadMusic(musicID, name, musicPath)
|
||||
if err == nil {
|
||||
musicName = name + ".mp3"
|
||||
if cfg.Local {
|
||||
// 下载歌词
|
||||
_ = wyy.DownloadLrc(musicID, name, musicPath+"歌词/")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 下载歌单歌曲(歌单ID, 音乐保存路径)
|
||||
func downloadlist(playlistID int64, musicPath string) error {
|
||||
APIURL := cfg.APIURL + "playlist/track/all?id=" + strconv.FormatInt(playlistID, 10)
|
||||
data, err := web.GetData(APIURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var parsed musicListOfApI
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if parsed.Code != 200 {
|
||||
err = errors.Errorf("requset code : %d", parsed.Code)
|
||||
return err
|
||||
}
|
||||
for _, info := range parsed.Songs {
|
||||
// 将"/"符号去除,不然无法生成文件
|
||||
musicName := strings.ReplaceAll(info.Name, "/", "·")
|
||||
musicID := info.ID
|
||||
artistName := ""
|
||||
for i, ARInfo := range info.Ar {
|
||||
if i != 0 {
|
||||
artistName += "&" + ARInfo.Name
|
||||
} else {
|
||||
artistName += ARInfo.Name
|
||||
}
|
||||
}
|
||||
cource := ""
|
||||
if info.Alia != nil {
|
||||
cource = strings.Join(info.Alia, "&")
|
||||
// 将"/"符号去除,不然无法下载
|
||||
cource = strings.ReplaceAll(cource, "/", "&")
|
||||
}
|
||||
if musicName == "" || musicID == 0 {
|
||||
err = errors.New("无法获API取歌曲信息")
|
||||
return err
|
||||
}
|
||||
if cource != "" {
|
||||
musicName += " - " + artistName + " - " + cource
|
||||
} else {
|
||||
musicName += " - " + artistName
|
||||
}
|
||||
// 下载歌曲
|
||||
err = wyy.DownloadMusic(musicID, musicName, musicPath)
|
||||
if err == nil {
|
||||
if cfg.Local {
|
||||
// 下载歌词
|
||||
_ = wyy.DownloadLrc(musicID, musicName, musicPath+"歌词/")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**************************独角兽API*******************************/
|
||||
/*****************************************************************/
|
||||
// 下载从独角兽抽到的歌曲ID(歌单ID, 音乐保存路径, 歌词保存路径)
|
||||
func downloadByOvooa(playlistID int64, musicPath string) (musicName string, err error) {
|
||||
// 抽取歌曲
|
||||
mid, err := drawByOvooa(playlistID)
|
||||
if err != nil {
|
||||
err = errors.Errorf("API%s", err)
|
||||
return
|
||||
}
|
||||
// 获取完成的歌名
|
||||
musiclist, err := wyy.SearchMusic(strconv.Itoa(mid), 1)
|
||||
if err != nil {
|
||||
err = errors.Errorf("API歌曲下载ERROR: %s", err)
|
||||
return
|
||||
}
|
||||
// 歌曲ID理论是唯一的
|
||||
mun := len(musiclist)
|
||||
if mun == 1 {
|
||||
// 拉取歌名
|
||||
musicList := make([]string, mun)
|
||||
i := 0
|
||||
for musicName := range musiclist {
|
||||
musicList[i] = musicName
|
||||
}
|
||||
name := musicList[0]
|
||||
// 下载歌曲
|
||||
err = wyy.DownloadMusic(mid, name, musicPath)
|
||||
if err == nil {
|
||||
musicName = name + ".mp3"
|
||||
if cfg.Local {
|
||||
// 下载歌词
|
||||
_ = wyy.DownloadLrc(mid, name, musicPath+"歌词/")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = errors.Errorf("music IDThis music ID sreached munber is %d", mun)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 通过独角兽API随机抽取歌单歌曲ID(参数:歌单ID)
|
||||
func drawByOvooa(playlistID int64) (musicID int, err error) {
|
||||
APIURL := "https://ovooa.com/API/163_Music_Rand/api.php?id=" + strconv.FormatInt(playlistID, 10)
|
||||
data, err := web.GetData(APIURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var parsed ovooaData
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if parsed.Code != 1 {
|
||||
return
|
||||
}
|
||||
return parsed.Data.ID, nil
|
||||
}
|
||||
316
plugin/guessmusic/guessmusic.go
Normal file
316
plugin/guessmusic/guessmusic.go
Normal file
@@ -0,0 +1,316 @@
|
||||
package guessmusic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/fs"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/pkg/errors"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
|
||||
|
||||
func init() {
|
||||
engine.OnRegex(`^(个人|团队)猜歌(-(.*))?$`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
mode := ctx.State["regex_matched"].([]string)[3]
|
||||
gid := ctx.Event.GroupID
|
||||
// 获取本地列表
|
||||
filelist, err := getlist(cfg.MusicPath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
return
|
||||
}
|
||||
// 加载默认歌单
|
||||
if mode == "" {
|
||||
index := -1
|
||||
for i, dlist := range cfg.Defaultlist {
|
||||
if dlist.GroupID == gid {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if index == -1 {
|
||||
// 如果没有设置就默认第一个文件夹
|
||||
mode = filelist[0].Name
|
||||
} else {
|
||||
mode = cfg.Defaultlist[index].Name
|
||||
ok := true
|
||||
for _, listinfo := range filelist {
|
||||
if mode == listinfo.Name {
|
||||
ok = false
|
||||
break
|
||||
}
|
||||
}
|
||||
// 如果默认的歌单不存在了清空设置
|
||||
if ok {
|
||||
cfg.Defaultlist = append(cfg.Defaultlist[:index], cfg.Defaultlist[index+1:]...)
|
||||
_ = saveConfig(cfgFile)
|
||||
mode = filelist[0].Name
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲信息(歌名歌手等)|提示|取消]”\n一共3段语音,6次机会"))
|
||||
// 随机抽歌
|
||||
pathOfMusic, musicName, err := musicLottery(cfg.MusicPath, mode)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(serviceErr, err))
|
||||
return
|
||||
}
|
||||
// 解析歌曲信息
|
||||
music := strings.Split(musicName, ".")
|
||||
// 获取音乐后缀
|
||||
musictype := music[len(music)-1]
|
||||
if !strings.Contains(musictypelist, musictype) {
|
||||
ctx.SendChain(message.Text("抽取到了歌曲:\n",
|
||||
musicName, "\n该歌曲不是音乐后缀,请联系bot主人修改"))
|
||||
return
|
||||
}
|
||||
// 获取音乐信息
|
||||
musicInfo := strings.Split(strings.ReplaceAll(musicName, "."+musictype, ""), " - ")
|
||||
infoNum := len(musicInfo)
|
||||
if infoNum == 1 {
|
||||
ctx.SendChain(message.Text("抽取到了歌曲:\n",
|
||||
musicName, "\n该歌曲命名不符合命名规则,请联系bot主人修改"))
|
||||
return
|
||||
}
|
||||
answerString := "歌名:" + musicInfo[0] + "\n歌手:" + musicInfo[1]
|
||||
if infoNum > 2 {
|
||||
musicInfo[2] = strings.ReplaceAll(musicInfo[2], "&", "\n")
|
||||
answerString += "\n其他信息:\n" + musicInfo[2]
|
||||
}
|
||||
musicInfo = append(musicInfo, answerString)
|
||||
// 切割音频,生成3个10秒的音频
|
||||
outputPath := cachePath + strconv.FormatInt(gid, 10) + "/"
|
||||
err = cutMusic(musicName, pathOfMusic, outputPath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
return
|
||||
}
|
||||
// 进行猜歌环节
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav"))
|
||||
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))
|
||||
}
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
wait := time.NewTimer(40 * time.Second)
|
||||
tick := time.NewTimer(105 * time.Second)
|
||||
after := time.NewTimer(120 * time.Second)
|
||||
wg := sync.WaitGroup{}
|
||||
var (
|
||||
messageStr message.MessageSegment // 文本信息
|
||||
tickCount = 0 // 音频数量
|
||||
answerCount = 0 // 问答次数
|
||||
win bool // 是否赢得游戏
|
||||
)
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
ctx.SendChain(message.Text("猜歌游戏,你还有15s作答时间"))
|
||||
case <-after.C:
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("时间超时,猜歌结束,公布答案:\n", answerString)))
|
||||
return
|
||||
case <-wait.C:
|
||||
wait.Reset(40 * time.Second)
|
||||
tickCount++
|
||||
if tickCount > 2 {
|
||||
wait.Stop()
|
||||
continue
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Text("好像有些难度呢,再听这段音频,要仔细听哦"),
|
||||
)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(tickCount) + ".wav"))
|
||||
case c := <-recv:
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
messageStr, answerCount, tickCount, win = gameMatch(c, ctx.Event.UserID, musicInfo, answerCount, tickCount)
|
||||
if win { // 游戏结束的话
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), messageStr)
|
||||
ctx.SendChain(message.Record("file:///" + pathOfMusic + musicName))
|
||||
} else {
|
||||
wait.Reset(40 * time.Second)
|
||||
tick.Reset(105 * time.Second)
|
||||
after.Reset(120 * time.Second)
|
||||
if tickCount > 2 || messageStr.Data["text"] == "你无权限取消" {
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), messageStr)
|
||||
} else {
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), messageStr)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(tickCount) + ".wav"))
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Wait()
|
||||
if win {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 随机抽取音乐
|
||||
func musicLottery(musicPath, listName string) (pathOfMusic, musicName string, err error) {
|
||||
// 读取歌单文件
|
||||
pathOfMusic = musicPath + listName + "/"
|
||||
if file.IsNotExist(pathOfMusic) {
|
||||
err = errors.New("指定的歌单不存在,可发送“歌单列表”查看歌单列表")
|
||||
return
|
||||
}
|
||||
files, err := os.ReadDir(pathOfMusic)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 获取绑定的网易云
|
||||
var playlistID int64
|
||||
for _, listinfo := range cfg.Playlist {
|
||||
if listinfo.Name == listName {
|
||||
playlistID = listinfo.ID
|
||||
}
|
||||
}
|
||||
// 如果本地列表为空
|
||||
if len(files) == 0 {
|
||||
if playlistID == 0 || !cfg.API {
|
||||
err = errors.New("本地歌单数据为0")
|
||||
return
|
||||
}
|
||||
// 如果绑定了歌单ID
|
||||
if cfg.APIURL == "" {
|
||||
// 如果没有配置过API地址,尝试连接独角兽
|
||||
musicName, err = downloadByOvooa(playlistID, pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("本地歌单数据为0,API下载歌曲失败\n%s", err)
|
||||
}
|
||||
} else {
|
||||
// 从API中抽取歌曲
|
||||
musicName, err = drawByAPI(playlistID, pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("本地歌单数据为0,API下载歌曲失败\n%s", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// 进行随机抽取
|
||||
if playlistID == 0 || !cfg.API {
|
||||
musicName = getLocalMusic(files, 10)
|
||||
} else {
|
||||
switch rand.Intn(3) { // 三分二概率抽取API的
|
||||
case 1:
|
||||
musicName = getLocalMusic(files, 10)
|
||||
default:
|
||||
if cfg.APIURL == "" {
|
||||
// 如果没有配置过API地址,尝试连接独角兽
|
||||
musicName, err = downloadByOvooa(playlistID, pathOfMusic)
|
||||
} else {
|
||||
// 从API中抽取歌曲
|
||||
musicName, err = drawByAPI(playlistID, pathOfMusic)
|
||||
}
|
||||
if err != nil {
|
||||
musicName = getLocalMusic(files, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
if musicName == "" {
|
||||
err = errors.New("抽取歌曲轮空了,请重试")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 从本地列表中随机抽取一首( indexMax : 最大递归次数 )
|
||||
func getLocalMusic(files []fs.DirEntry, indexMax int) (musicName string) {
|
||||
if len(files) > 1 {
|
||||
music := files[rand.Intn(len(files))]
|
||||
// 如果是文件夹就递归
|
||||
if music.IsDir() {
|
||||
indexMax--
|
||||
if indexMax <= 0 {
|
||||
return
|
||||
}
|
||||
musicName = getLocalMusic(files, indexMax)
|
||||
} else {
|
||||
musicName = music.Name()
|
||||
}
|
||||
} else {
|
||||
music := files[0]
|
||||
if !music.IsDir() {
|
||||
musicName = files[0].Name()
|
||||
}
|
||||
}
|
||||
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,
|
||||
"-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
|
||||
}
|
||||
|
||||
// 数据匹配(结果信息,答题次数,提示次数,是否结束游戏)
|
||||
func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tickTimes int) (message.MessageSegment, int, int, bool) {
|
||||
answer := strings.Replace(c.Event.Message.String(), "-", "", 1)
|
||||
switch {
|
||||
case answer == "取消":
|
||||
if c.Event.UserID == beginner {
|
||||
return message.Text("游戏已取消,猜歌答案是\n", musicInfo[len(musicInfo)-1], "\n\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
|
||||
}
|
||||
return message.Text("你无权限取消"), answerTimes, tickTimes, false
|
||||
case answer == "提示":
|
||||
tickTimes++
|
||||
if tickTimes > 2 {
|
||||
return message.Text("已经没有提示了哦"), answerTimes, tickTimes, false
|
||||
}
|
||||
return message.Text("再听这段音频,要仔细听哦"), answerTimes, tickTimes, false
|
||||
case strings.Contains(musicInfo[0], answer) || strings.EqualFold(musicInfo[0], answer):
|
||||
return message.Text("太棒了,你猜对歌曲名了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
|
||||
case strings.Contains(musicInfo[1], answer) || strings.EqualFold(musicInfo[1], answer):
|
||||
return message.Text("太棒了,你猜对歌手名了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
|
||||
case len(musicInfo) == 4 && (strings.Contains(musicInfo[2], answer) || strings.EqualFold(musicInfo[2], answer)):
|
||||
return message.Text("太棒了,你猜对相关信息了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
|
||||
default:
|
||||
answerTimes++
|
||||
tickTimes++
|
||||
switch {
|
||||
case tickTimes > 2 && answerTimes < 6:
|
||||
return message.Text("答案不对哦,还有", 6-answerTimes, "次答题,加油啊~"), answerTimes, tickTimes, false
|
||||
case tickTimes > 2:
|
||||
return message.Text("次数到了,没能猜出来。答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
|
||||
default:
|
||||
return message.Text("答案不对,再听这段音频,要仔细听哦"), answerTimes, tickTimes, false
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,11 +3,12 @@ package guessmusic
|
||||
// config内容
|
||||
type config struct {
|
||||
MusicPath string `json:"musicPath"`
|
||||
APIURL string `json:"apiURL"`
|
||||
Playlist []listRaw `json:"playlist"`
|
||||
Defaultlist []dlist `json:"defaultlist"`
|
||||
Local bool `json:"local"`
|
||||
API bool `json:"api"`
|
||||
Cookie string `json:"cookie"`
|
||||
Playlist []listRaw `json:"playlist"`
|
||||
Defaultlist []dlist `json:"defaultlist"`
|
||||
}
|
||||
|
||||
// 记录歌单绑定的网易云歌单ID
|
||||
@@ -29,6 +30,408 @@ type listinfo struct {
|
||||
ID int64 // 歌单绑定的歌曲ID
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/***************NeteaseCloudMusicApi框架API************************/
|
||||
/*****************************************************************/
|
||||
// 获取登陆信息
|
||||
type keyInfo struct {
|
||||
Data struct {
|
||||
Code int `json:"code"`
|
||||
Unikey string `json:"unikey"`
|
||||
} `json:"data"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
type cookyInfo struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Cookie string `json:"cookie"`
|
||||
}
|
||||
type qrInfo struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
Qrurl string `json:"qrurl"`
|
||||
Qrimg string `json:"qrimg"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// 获取歌单信息
|
||||
type listInfoOfAPI struct {
|
||||
Code int `json:"code"`
|
||||
RelatedVideos interface{} `json:"relatedVideos"`
|
||||
Playlist struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CoverImgID int64 `json:"coverImgId"`
|
||||
CoverImgURL string `json:"coverImgUrl"`
|
||||
CoverImgIDStr string `json:"coverImgId_str"`
|
||||
AdType int `json:"adType"`
|
||||
UserID int `json:"userId"`
|
||||
CreateTime int64 `json:"createTime"`
|
||||
Status int `json:"status"`
|
||||
OpRecommend bool `json:"opRecommend"`
|
||||
HighQuality bool `json:"highQuality"`
|
||||
NewImported bool `json:"newImported"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
TrackCount int `json:"trackCount"`
|
||||
SpecialType int `json:"specialType"`
|
||||
Privacy int `json:"privacy"`
|
||||
TrackUpdateTime int64 `json:"trackUpdateTime"`
|
||||
CommentThreadID string `json:"commentThreadId"`
|
||||
PlayCount int `json:"playCount"`
|
||||
TrackNumberUpdateTime int64 `json:"trackNumberUpdateTime"`
|
||||
SubscribedCount int `json:"subscribedCount"`
|
||||
CloudTrackCount int `json:"cloudTrackCount"`
|
||||
Ordered bool `json:"ordered"`
|
||||
Description string `json:"description"`
|
||||
Tags []string `json:"tags"`
|
||||
UpdateFrequency interface{} `json:"updateFrequency"`
|
||||
BackgroundCoverID int `json:"backgroundCoverId"`
|
||||
BackgroundCoverURL interface{} `json:"backgroundCoverUrl"`
|
||||
TitleImage int `json:"titleImage"`
|
||||
TitleImageURL interface{} `json:"titleImageUrl"`
|
||||
EnglishTitle interface{} `json:"englishTitle"`
|
||||
OfficialPlaylistType interface{} `json:"officialPlaylistType"`
|
||||
Subscribers []struct {
|
||||
DefaultAvatar bool `json:"defaultAvatar"`
|
||||
Province int `json:"province"`
|
||||
AuthStatus int `json:"authStatus"`
|
||||
Followed bool `json:"followed"`
|
||||
AvatarURL string `json:"avatarUrl"`
|
||||
AccountStatus int `json:"accountStatus"`
|
||||
Gender int `json:"gender"`
|
||||
City int `json:"city"`
|
||||
Birthday int `json:"birthday"`
|
||||
UserID int `json:"userId"`
|
||||
UserType int `json:"userType"`
|
||||
Nickname string `json:"nickname"`
|
||||
Signature string `json:"signature"`
|
||||
Description string `json:"description"`
|
||||
DetailDescription string `json:"detailDescription"`
|
||||
AvatarImgID int64 `json:"avatarImgId"`
|
||||
BackgroundImgID int64 `json:"backgroundImgId"`
|
||||
BackgroundURL string `json:"backgroundUrl"`
|
||||
Authority int `json:"authority"`
|
||||
Mutual bool `json:"mutual"`
|
||||
ExpertTags interface{} `json:"expertTags"`
|
||||
Experts interface{} `json:"experts"`
|
||||
DjStatus int `json:"djStatus"`
|
||||
VipType int `json:"vipType"`
|
||||
RemarkName interface{} `json:"remarkName"`
|
||||
AuthenticationTypes int `json:"authenticationTypes"`
|
||||
AvatarDetail interface{} `json:"avatarDetail"`
|
||||
Anchor bool `json:"anchor"`
|
||||
BackgroundImgIDStr string `json:"backgroundImgIdStr"`
|
||||
AvatarImgIDStr string `json:"avatarImgIdStr"`
|
||||
AvatarImgIDString string `json:"AvatarImgIDString"`
|
||||
} `json:"subscribers"`
|
||||
Subscribed interface{} `json:"subscribed"`
|
||||
Creator struct {
|
||||
DefaultAvatar bool `json:"defaultAvatar"`
|
||||
Province int `json:"province"`
|
||||
AuthStatus int `json:"authStatus"`
|
||||
Followed bool `json:"followed"`
|
||||
AvatarURL string `json:"avatarUrl"`
|
||||
AccountStatus int `json:"accountStatus"`
|
||||
Gender int `json:"gender"`
|
||||
City int `json:"city"`
|
||||
Birthday int `json:"birthday"`
|
||||
UserID int `json:"userId"`
|
||||
UserType int `json:"userType"`
|
||||
Nickname string `json:"nickname"`
|
||||
Signature string `json:"signature"`
|
||||
Description string `json:"description"`
|
||||
DetailDescription string `json:"detailDescription"`
|
||||
AvatarImgID int64 `json:"avatarImgId"`
|
||||
BackgroundImgID int64 `json:"backgroundImgId"`
|
||||
BackgroundURL string `json:"backgroundUrl"`
|
||||
Authority int `json:"authority"`
|
||||
Mutual bool `json:"mutual"`
|
||||
ExpertTags interface{} `json:"expertTags"`
|
||||
Experts interface{} `json:"experts"`
|
||||
DjStatus int `json:"djStatus"`
|
||||
VipType int `json:"vipType"`
|
||||
RemarkName interface{} `json:"remarkName"`
|
||||
AuthenticationTypes int `json:"authenticationTypes"`
|
||||
AvatarDetail struct {
|
||||
UserType int `json:"userType"`
|
||||
IdentityLevel int `json:"identityLevel"`
|
||||
IdentityIconURL string `json:"identityIconUrl"`
|
||||
} `json:"avatarDetail"`
|
||||
Anchor bool `json:"anchor"`
|
||||
BackgroundImgIDStr string `json:"backgroundImgIdStr"`
|
||||
AvatarImgIDStr string `json:"avatarImgIdStr"`
|
||||
AvatarImgIDString string `json:"AvatarImgIDString"`
|
||||
} `json:"creator"`
|
||||
Tracks []struct {
|
||||
Name string `json:"name"`
|
||||
ID int `json:"id"`
|
||||
Pst int `json:"pst"`
|
||||
T int `json:"t"`
|
||||
Ar []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
Alias []interface{} `json:"alias"`
|
||||
} `json:"ar"`
|
||||
Alia []string `json:"alia"`
|
||||
Pop int `json:"pop"`
|
||||
St int `json:"st"`
|
||||
Rt string `json:"rt"`
|
||||
Fee int `json:"fee"`
|
||||
V int `json:"v"`
|
||||
Crbt interface{} `json:"crbt"`
|
||||
Cf string `json:"cf"`
|
||||
Al struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PicURL string `json:"picUrl"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
PicStr string `json:"pic_str"`
|
||||
Pic int64 `json:"pic"`
|
||||
} `json:"al"`
|
||||
Dt int `json:"dt"`
|
||||
H struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float64 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"h"`
|
||||
M struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float64 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"m"`
|
||||
L struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float64 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"l"`
|
||||
Sq interface{} `json:"sq"`
|
||||
Hr interface{} `json:"hr"`
|
||||
A interface{} `json:"a"`
|
||||
Cd string `json:"cd"`
|
||||
No int `json:"no"`
|
||||
RtURL interface{} `json:"rtUrl"`
|
||||
Ftype int `json:"ftype"`
|
||||
RtUrls []interface{} `json:"rtUrls"`
|
||||
DjID int `json:"djId"`
|
||||
Copyright int `json:"copyright"`
|
||||
SID int `json:"s_id"`
|
||||
Mark int `json:"mark"`
|
||||
OriginCoverType int `json:"originCoverType"`
|
||||
OriginSongSimpleData interface{} `json:"originSongSimpleData"`
|
||||
TagPicList interface{} `json:"tagPicList"`
|
||||
ResourceState bool `json:"resourceState"`
|
||||
Version int `json:"version"`
|
||||
SongJumpInfo interface{} `json:"songJumpInfo"`
|
||||
EntertainmentTags interface{} `json:"entertainmentTags"`
|
||||
Single int `json:"single"`
|
||||
NoCopyrightRcmd interface{} `json:"noCopyrightRcmd"`
|
||||
Alg interface{} `json:"alg"`
|
||||
Rtype int `json:"rtype"`
|
||||
Rurl interface{} `json:"rurl"`
|
||||
Mst int `json:"mst"`
|
||||
Cp int `json:"cp"`
|
||||
Mv int `json:"mv"`
|
||||
PublishTime int64 `json:"publishTime"`
|
||||
Tns []string `json:"tns,omitempty"`
|
||||
} `json:"tracks"`
|
||||
VideoIds interface{} `json:"videoIds"`
|
||||
Videos interface{} `json:"videos"`
|
||||
TrackIds []struct {
|
||||
ID int `json:"id"`
|
||||
V int `json:"v"`
|
||||
T int `json:"t"`
|
||||
At int64 `json:"at"`
|
||||
Alg interface{} `json:"alg"`
|
||||
UID int `json:"uid"`
|
||||
RcmdReason string `json:"rcmdReason"`
|
||||
Sc interface{} `json:"sc"`
|
||||
Lr int `json:"lr,omitempty"`
|
||||
} `json:"trackIds"`
|
||||
ShareCount int `json:"shareCount"`
|
||||
CommentCount int `json:"commentCount"`
|
||||
RemixVideo interface{} `json:"remixVideo"`
|
||||
SharedUsers interface{} `json:"sharedUsers"`
|
||||
HistorySharedUsers interface{} `json:"historySharedUsers"`
|
||||
GradeStatus string `json:"gradeStatus"`
|
||||
Score interface{} `json:"score"`
|
||||
AlgTags interface{} `json:"algTags"`
|
||||
} `json:"playlist"`
|
||||
Urls interface{} `json:"urls"`
|
||||
Privileges []struct {
|
||||
ID int `json:"id"`
|
||||
Fee int `json:"fee"`
|
||||
Payed int `json:"payed"`
|
||||
RealPayed int `json:"realPayed"`
|
||||
St int `json:"st"`
|
||||
Pl int `json:"pl"`
|
||||
Dl int `json:"dl"`
|
||||
Sp int `json:"sp"`
|
||||
Cp int `json:"cp"`
|
||||
Subp int `json:"subp"`
|
||||
Cs bool `json:"cs"`
|
||||
Maxbr int `json:"maxbr"`
|
||||
Fl int `json:"fl"`
|
||||
Pc interface{} `json:"pc"`
|
||||
Toast bool `json:"toast"`
|
||||
Flag int `json:"flag"`
|
||||
PaidBigBang bool `json:"paidBigBang"`
|
||||
PreSell bool `json:"preSell"`
|
||||
PlayMaxbr int `json:"playMaxbr"`
|
||||
DownloadMaxbr int `json:"downloadMaxbr"`
|
||||
MaxBrLevel string `json:"maxBrLevel"`
|
||||
PlayMaxBrLevel string `json:"playMaxBrLevel"`
|
||||
DownloadMaxBrLevel string `json:"downloadMaxBrLevel"`
|
||||
PlLevel string `json:"plLevel"`
|
||||
DlLevel string `json:"dlLevel"`
|
||||
FlLevel string `json:"flLevel"`
|
||||
Rscl int `json:"rscl"`
|
||||
FreeTrialPrivilege struct {
|
||||
ResConsumable bool `json:"resConsumable"`
|
||||
UserConsumable bool `json:"userConsumable"`
|
||||
ListenType interface{} `json:"listenType"`
|
||||
} `json:"freeTrialPrivilege"`
|
||||
ChargeInfoList []struct {
|
||||
Rate int `json:"rate"`
|
||||
ChargeURL interface{} `json:"chargeUrl"`
|
||||
ChargeMessage interface{} `json:"chargeMessage"`
|
||||
ChargeType int `json:"chargeType"`
|
||||
} `json:"chargeInfoList"`
|
||||
} `json:"privileges"`
|
||||
SharedPrivilege interface{} `json:"sharedPrivilege"`
|
||||
ResEntrance interface{} `json:"resEntrance"`
|
||||
}
|
||||
|
||||
// 获取歌单列表
|
||||
type musicListOfApI struct {
|
||||
Songs []struct {
|
||||
Name string `json:"name"`
|
||||
ID int `json:"id"`
|
||||
Pst int `json:"pst"`
|
||||
T int `json:"t"`
|
||||
Ar []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
Alias []interface{} `json:"alias"`
|
||||
} `json:"ar"`
|
||||
Alia []string `json:"alia"`
|
||||
Pop int `json:"pop"`
|
||||
St int `json:"st"`
|
||||
Rt string `json:"rt"`
|
||||
Fee int `json:"fee"`
|
||||
V int `json:"v"`
|
||||
Crbt interface{} `json:"crbt"`
|
||||
Cf string `json:"cf"`
|
||||
Al struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PicURL string `json:"picUrl"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
PicStr string `json:"pic_str"`
|
||||
Pic int64 `json:"pic"`
|
||||
} `json:"al"`
|
||||
Dt int `json:"dt"`
|
||||
H struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float32 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"h"`
|
||||
M struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float32 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"m"`
|
||||
L struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float32 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"l"`
|
||||
Sq interface{} `json:"sq"`
|
||||
Hr interface{} `json:"hr"`
|
||||
A interface{} `json:"a"`
|
||||
Cd string `json:"cd"`
|
||||
No int `json:"no"`
|
||||
RtURL interface{} `json:"rtUrl"`
|
||||
Ftype int `json:"ftype"`
|
||||
RtUrls []interface{} `json:"rtUrls"`
|
||||
DjID int `json:"djId"`
|
||||
Copyright int `json:"copyright"`
|
||||
SID int `json:"s_id"`
|
||||
Mark int `json:"mark"`
|
||||
OriginCoverType int `json:"originCoverType"`
|
||||
OriginSongSimpleData interface{} `json:"originSongSimpleData"`
|
||||
TagPicList interface{} `json:"tagPicList"`
|
||||
ResourceState bool `json:"resourceState"`
|
||||
Version int `json:"version"`
|
||||
SongJumpInfo interface{} `json:"songJumpInfo"`
|
||||
EntertainmentTags interface{} `json:"entertainmentTags"`
|
||||
AwardTags interface{} `json:"awardTags"`
|
||||
Single int `json:"single"`
|
||||
NoCopyrightRcmd interface{} `json:"noCopyrightRcmd"`
|
||||
Rtype int `json:"rtype"`
|
||||
Rurl interface{} `json:"rurl"`
|
||||
Mst int `json:"mst"`
|
||||
Cp int `json:"cp"`
|
||||
Mv int `json:"mv"`
|
||||
PublishTime int64 `json:"publishTime"`
|
||||
Tns []string `json:"tns,omitempty"`
|
||||
} `json:"songs"`
|
||||
Privileges []struct {
|
||||
ID int `json:"id"`
|
||||
Fee int `json:"fee"`
|
||||
Payed int `json:"payed"`
|
||||
St int `json:"st"`
|
||||
Pl int `json:"pl"`
|
||||
Dl int `json:"dl"`
|
||||
Sp int `json:"sp"`
|
||||
Cp int `json:"cp"`
|
||||
Subp int `json:"subp"`
|
||||
Cs bool `json:"cs"`
|
||||
Maxbr int `json:"maxbr"`
|
||||
Fl int `json:"fl"`
|
||||
Toast bool `json:"toast"`
|
||||
Flag int `json:"flag"`
|
||||
PreSell bool `json:"preSell"`
|
||||
PlayMaxbr int `json:"playMaxbr"`
|
||||
DownloadMaxbr int `json:"downloadMaxbr"`
|
||||
MaxBrLevel string `json:"maxBrLevel"`
|
||||
PlayMaxBrLevel string `json:"playMaxBrLevel"`
|
||||
DownloadMaxBrLevel string `json:"downloadMaxBrLevel"`
|
||||
PlLevel string `json:"plLevel"`
|
||||
DlLevel string `json:"dlLevel"`
|
||||
FlLevel string `json:"flLevel"`
|
||||
Rscl int `json:"rscl"`
|
||||
FreeTrialPrivilege struct {
|
||||
ResConsumable bool `json:"resConsumable"`
|
||||
UserConsumable bool `json:"userConsumable"`
|
||||
ListenType interface{} `json:"listenType"`
|
||||
} `json:"freeTrialPrivilege"`
|
||||
ChargeInfoList []struct {
|
||||
Rate int `json:"rate"`
|
||||
ChargeURL interface{} `json:"chargeUrl"`
|
||||
ChargeMessage interface{} `json:"chargeMessage"`
|
||||
ChargeType int `json:"chargeType"`
|
||||
} `json:"chargeInfoList"`
|
||||
} `json:"privileges"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/*********************独角兽API随机抽歌信息**************************/
|
||||
/*****************************************************************/
|
||||
// 独角兽API随机抽歌信息
|
||||
type ovooaData struct {
|
||||
Code int `json:"code"`
|
||||
|
||||
@@ -2,11 +2,17 @@
|
||||
package heisi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/setu"
|
||||
fbctxext "github.com/FloatTech/floatbox/ctxext"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
@@ -25,10 +31,45 @@ var (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
p, err := setu.NewPool(setu.DefaultPoolDir,
|
||||
func(s string) (string, error) {
|
||||
if s != "黑丝" && s != "白丝" && s != "jk" && s != "巨乳" && s != "足控" && s != "网红" {
|
||||
return "", errors.New("invalid call")
|
||||
}
|
||||
typ := setu.DefaultPoolDir + "/" + s
|
||||
if file.IsNotExist(typ) {
|
||||
err := os.MkdirAll(typ, 0755)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
var pic item
|
||||
switch s {
|
||||
case "黑丝":
|
||||
pic = heisiPic[rand.Intn(len(heisiPic))]
|
||||
case "白丝":
|
||||
pic = baisiPic[rand.Intn(len(baisiPic))]
|
||||
case "jk":
|
||||
pic = jkPic[rand.Intn(len(jkPic))]
|
||||
case "巨乳":
|
||||
pic = jurPic[rand.Intn(len(jurPic))]
|
||||
case "足控":
|
||||
pic = zukPic[rand.Intn(len(zukPic))]
|
||||
case "网红":
|
||||
pic = mcnPic[rand.Intn(len(mcnPic))]
|
||||
}
|
||||
return pic.String(), nil
|
||||
}, func(s string) ([]byte, error) {
|
||||
return web.RequestDataWith(web.NewTLS12Client(), s, "GET", "http://hs.heisiwu.com/", web.RandUA(), nil)
|
||||
}, time.Minute)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
engine := control.Register("heisi", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "黑丝\n" +
|
||||
"- 来点黑丝\n- 来点白丝\n- 来点jk\n- 来点巨乳\n- 来点足控\n- 来点网红",
|
||||
Brief: "黑丝",
|
||||
Help: "- 来点黑丝\n- 来点白丝\n- 来点jk\n- 来点巨乳\n- 来点足控\n- 来点网红",
|
||||
PublicDataFolder: "Heisi",
|
||||
})
|
||||
|
||||
@@ -65,22 +106,12 @@ func init() { // 插件主体
|
||||
})).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
matched := ctx.State["matched"].(string)
|
||||
var pic item
|
||||
switch matched {
|
||||
case "来点黑丝":
|
||||
pic = heisiPic[rand.Intn(len(heisiPic))]
|
||||
case "来点白丝":
|
||||
pic = baisiPic[rand.Intn(len(baisiPic))]
|
||||
case "来点jk":
|
||||
pic = jkPic[rand.Intn(len(jkPic))]
|
||||
case "来点巨乳":
|
||||
pic = jurPic[rand.Intn(len(jurPic))]
|
||||
case "来点足控":
|
||||
pic = zukPic[rand.Intn(len(zukPic))]
|
||||
case "来点网红":
|
||||
pic = mcnPic[rand.Intn(len(mcnPic))]
|
||||
pic, err := p.Roll(matched[3*2:])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image(pic.String()))}
|
||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+file.BOTPATH+"/"+pic))}
|
||||
if id := ctx.Send(m).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
|
||||
174
plugin/hitokoto/hitokoto.go
Normal file
174
plugin/hitokoto/hitokoto.go
Normal file
@@ -0,0 +1,174 @@
|
||||
// Package hitokoto 一言
|
||||
package hitokoto
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"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() { // 插件主体
|
||||
engine := control.Register("hitokoto", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "一言",
|
||||
Help: "- 一言[xxx]\n" +
|
||||
"- 系列一言",
|
||||
PublicDataFolder: "Hitokoto",
|
||||
})
|
||||
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
dbfile := engine.DataFolder() + "hitokoto.db"
|
||||
_, err := engine.GetLazyData("hitokoto.db", false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
hdb, err = initialize(dbfile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
engine.OnPrefix(`一言`, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
args := ctx.State["args"].(string)
|
||||
blist, err := hdb.getByKey(strings.TrimSpace(args))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(blist) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: hitokoto empty"))
|
||||
return
|
||||
}
|
||||
m := make(message.Message, 0, 10)
|
||||
text := strings.Builder{}
|
||||
if len(blist) <= 10 {
|
||||
for _, b := range blist {
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
} else {
|
||||
indexes := map[int]struct{}{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ind := rand.Intn(len(blist))
|
||||
if _, ok := indexes[ind]; ok {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
indexes[ind] = struct{}{}
|
||||
}
|
||||
for k := range indexes {
|
||||
b := blist[k]
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
}
|
||||
if id := ctx.Send(m).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch(`系列一言`, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
results, err := hdb.getAllCategory()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
tex := strings.Builder{}
|
||||
tex.WriteString("请输入系列一言序号\n")
|
||||
for i, v := range results {
|
||||
tex.WriteString(strconv.Itoa(i))
|
||||
tex.WriteString(". ")
|
||||
tex.WriteString(v.Category)
|
||||
tex.WriteString("\n")
|
||||
}
|
||||
base64Str, err := text.RenderToBase64(tex.String(), text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(base64Str)))
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.SendChain(message.Text("系列一言指令过期"))
|
||||
return
|
||||
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 >= len(results) {
|
||||
ctx.SendChain(message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
ctx.SendChain(message.Text("请欣赏系列一言: ", results[num].Category))
|
||||
hlist, err := hdb.getByCategory(results[num].Category)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(hlist) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: hitokoto empty"))
|
||||
return
|
||||
}
|
||||
m := make(message.Message, 0, 10)
|
||||
text := strings.Builder{}
|
||||
if len(hlist) <= 10 {
|
||||
for _, b := range hlist {
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
} else {
|
||||
indexes := map[int]struct{}{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ind := rand.Intn(len(hlist))
|
||||
if _, ok := indexes[ind]; ok {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
indexes[ind] = struct{}{}
|
||||
}
|
||||
for k := range indexes {
|
||||
b := hlist[k]
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
}
|
||||
if id := ctx.Send(m).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
73
plugin/hitokoto/model.go
Normal file
73
plugin/hitokoto/model.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package hitokoto
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// hdb 表情包数据库全局变量
|
||||
var hdb *hitokotodb
|
||||
|
||||
// hitokotodb 表情包数据库
|
||||
type hitokotodb gorm.DB
|
||||
|
||||
// initialize 初始化
|
||||
func initialize(dbpath string) (db *hitokotodb, err error) {
|
||||
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
|
||||
// 生成文件
|
||||
f, err := os.Create(dbpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = f.Close()
|
||||
}
|
||||
gdb, err := gorm.Open("sqlite3", dbpath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gdb.AutoMigrate(&hitokoto{})
|
||||
return (*hitokotodb)(gdb), nil
|
||||
}
|
||||
|
||||
type hitokoto struct {
|
||||
ID int `json:"id" gorm:"column:id;primary_key"`
|
||||
Hitokoto string `json:"hitokoto" gorm:"column:hitokoto"`
|
||||
Type string `json:"type" gorm:"column:type"`
|
||||
From string `json:"from" gorm:"column:from"`
|
||||
FromWho string `json:"from_who" gorm:"column:from_who"`
|
||||
Creator string `json:"creator" gorm:"column:creator"`
|
||||
CreatorUID int `json:"creator_uid" gorm:"column:creator_uid"`
|
||||
Reviewer int `json:"reviewer" gorm:"column:reviewer"`
|
||||
UUID string `json:"uuid" gorm:"column:uuid"`
|
||||
CreatedAt string `json:"created_at" gorm:"column:created_at"`
|
||||
Category string `json:"catogory" gorm:"column:category"`
|
||||
}
|
||||
|
||||
// TableName 表名
|
||||
func (hitokoto) TableName() string {
|
||||
return "hitokoto"
|
||||
}
|
||||
|
||||
func (hdb *hitokotodb) getByKey(key string) (b []hitokoto, err error) {
|
||||
db := (*gorm.DB)(hdb)
|
||||
err = db.Where("hitokoto like ?", "%"+key+"%").Find(&b).Error
|
||||
return
|
||||
}
|
||||
|
||||
type result struct {
|
||||
Category string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (hdb *hitokotodb) getAllCategory() (results []result, err error) {
|
||||
db := (*gorm.DB)(hdb)
|
||||
err = db.Table("hitokoto").Select("category, count(1) as count").Group("category").Scan(&results).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (hdb *hitokotodb) getByCategory(category string) (h []hitokoto, err error) {
|
||||
db := (*gorm.DB)(hdb)
|
||||
err = db.Where("category = ?", category).Find(&h).Error
|
||||
return
|
||||
}
|
||||
@@ -43,8 +43,8 @@ const (
|
||||
func init() {
|
||||
engine := control.Register("hs", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "炉石\n" +
|
||||
"- 搜卡[xxxx]\n" +
|
||||
Brief: "炉石搜卡",
|
||||
Help: "- 搜卡[xxxx]\n" +
|
||||
"- [卡组代码xxx]\n" +
|
||||
"- 更多搜卡指令参数:https://hs.fbigame.com/misc/searchhelp",
|
||||
PrivateDataFolder: "hs",
|
||||
@@ -67,7 +67,7 @@ func init() {
|
||||
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])
|
||||
reqconf[0], reqconf[1], reqconf[2], nil)
|
||||
if err == nil {
|
||||
err = os.WriteFile(cachefile, data, 0644)
|
||||
}
|
||||
@@ -95,10 +95,10 @@ func init() {
|
||||
}
|
||||
|
||||
func sh(s string) string {
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), "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], nil)
|
||||
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.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2], nil)
|
||||
if err == nil {
|
||||
return helper.BytesToString(r)
|
||||
}
|
||||
@@ -107,10 +107,10 @@ func sh(s string) string {
|
||||
}
|
||||
|
||||
func kz(s string) string {
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), "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], nil)
|
||||
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.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2], nil)
|
||||
if err == nil {
|
||||
return "base64://" + gjson.Get(helper.BytesToString(r), "img").String()
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
package hyaku
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
@@ -23,7 +21,6 @@ import (
|
||||
|
||||
const bed = "https://gitcode.net/u011570312/OguraHyakuninIsshu/-/raw/master/"
|
||||
|
||||
//nolint: asciicheck
|
||||
type line struct {
|
||||
番号, 歌人, 上の句, 下の句, 上の句ひらがな, 下の句ひらがな string
|
||||
}
|
||||
@@ -56,61 +53,41 @@ var lines [100]*line
|
||||
func init() {
|
||||
engine := control.Register("hyaku", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "百人一首\n" +
|
||||
"- 百人一首(随机发一首)\n" +
|
||||
Brief: "百人一首",
|
||||
Help: "- 百人一首(随机发一首)\n" +
|
||||
"- 百人一首之n",
|
||||
PrivateDataFolder: "hyaku",
|
||||
})
|
||||
csvfile := engine.DataFolder() + "hyaku.csv"
|
||||
err := os.MkdirAll(engine.DataFolder()+"img", 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go func() {
|
||||
var f *os.File
|
||||
if file.IsNotExist(csvfile) {
|
||||
data, err := web.RequestDataWith(web.NewTLS12Client(), bed+"小倉百人一首.csv", "GET", "gitcode.net", web.RandUA())
|
||||
if err != nil {
|
||||
_ = os.Remove(csvfile)
|
||||
panic(err)
|
||||
}
|
||||
f, err = os.Create(csvfile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, _ = f.Write(data)
|
||||
_, _ = f.Seek(0, io.SeekStart)
|
||||
} else {
|
||||
var err error
|
||||
f, err = os.Open(csvfile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data, err := engine.GetCustomLazyData(bed, "小倉百人一首.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
records, err := csv.NewReader(bytes.NewReader(data)).ReadAll()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
records = records[1:] // skip title
|
||||
if len(records) != 100 {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
for j, r := range records {
|
||||
if len(r) != 6 {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
records, err := csv.NewReader(f).ReadAll()
|
||||
i, err := strconv.Atoi(r[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = f.Close()
|
||||
records = records[1:] // skip title
|
||||
if len(records) != 100 {
|
||||
i--
|
||||
if j != i {
|
||||
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)))
|
||||
}
|
||||
}()
|
||||
lines[i] = (*line)(*(*unsafe.Pointer)(unsafe.Pointer(&r)))
|
||||
}
|
||||
engine.OnFullMatch("百人一首").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
i := rand.Intn(100)
|
||||
img0, err := engine.GetCustomLazyData(bed, fmt.Sprintf("img/%03d.jpg", i+1))
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/http3"
|
||||
"github.com/quic-go/quic-go/http3"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
@@ -64,8 +64,8 @@ var hrefre = regexp.MustCompile(`<a href=".*">`)
|
||||
func init() {
|
||||
control.Register("imgfinder", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "关键字搜图\n" +
|
||||
"- 来张 [xxx]",
|
||||
Brief: "关键字搜图",
|
||||
Help: "- 来张 [xxx]",
|
||||
}).OnRegex(`^来张\s?(.*)$`, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
@@ -81,6 +81,10 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(illust.ImageUrls) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: nil image url"))
|
||||
return
|
||||
}
|
||||
u := illust.ImageUrls[0]
|
||||
n := u[strings.LastIndex(u, "/")+1 : len(u)-4]
|
||||
f := illust.Path(0)
|
||||
@@ -94,7 +98,7 @@ func init() {
|
||||
"标题: ", il.Title, "\n",
|
||||
"副标题: ", il.AltTitle, "\n",
|
||||
"ID: ", il.ID, "\n",
|
||||
"画师: ", illust.UserName, " (", illust.UserId, ")", "\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)),
|
||||
@@ -115,6 +119,7 @@ func soutuapi(keyword string) (r resultjson, err error) {
|
||||
"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",
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
func init() {
|
||||
en := control.Register("inject", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "注入指令\n" +
|
||||
"- run[CQ码]",
|
||||
Brief: "注入指令",
|
||||
Help: "- run[CQ码]",
|
||||
})
|
||||
// 运行 CQ 码
|
||||
en.OnPrefix("run", zero.SuperUserPermission).SetBlock(true).
|
||||
|
||||
@@ -25,14 +25,15 @@ const (
|
||||
func init() {
|
||||
engine := control.Register("jandan", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "煎蛋网无聊图\n- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
|
||||
Brief: "煎蛋网无聊图",
|
||||
Help: "- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
|
||||
PublicDataFolder: "Jandan",
|
||||
})
|
||||
|
||||
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "pics.db"
|
||||
_, _ = engine.GetLazyData("pics.db", false)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
65
plugin/jiami/jiami.go
Normal file
65
plugin/jiami/jiami.go
Normal file
@@ -0,0 +1,65 @@
|
||||
// Package jiami 兽语加密与解密
|
||||
package jiami
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
jiami1 = "http://ovooa.caonm.net/API/sho_u/?msg=%v" // 加密api地址
|
||||
jiami2 = "http://ovooa.caonm.net/API/sho_u/?format=1&msg=%v" // 解密api地址
|
||||
|
||||
)
|
||||
|
||||
type nmd struct { // struct解析格式大概是
|
||||
Data struct {
|
||||
Message string
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func init() { // 主函数
|
||||
en := control.Register("jiami", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "兽语加解密",
|
||||
Help: "兽语加解密\n" +
|
||||
"- 兽语加密xxx\n- 兽语解密xxx",
|
||||
})
|
||||
en.OnRegex(`^兽语加密\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es, err := web.GetData(fmt.Sprintf(jiami1, str)) // 将网站返回结果赋值
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
var r nmd // r数组
|
||||
err = json.Unmarshal(es, &r) // 填api返回结果,struct地址
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(r.Data.Message)) // 输出提取后的结果
|
||||
})
|
||||
|
||||
en.OnRegex(`^兽语解密\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es, err := web.GetData(fmt.Sprintf(jiami2, str)) // 将网站返回结果赋值
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
var n nmd // r数组
|
||||
err = json.Unmarshal(es, &n) // 填api返回结果,struct地址
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(n.Data.Message)) // 输出提取后的结果
|
||||
})
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
// Package jikipedia 小鸡词典
|
||||
// 修改自https://github.com/TeamPGM/PagerMaid_Plugins_Pyro ,非常感谢!!
|
||||
package jikipedia
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
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"
|
||||
)
|
||||
|
||||
const (
|
||||
url = "https://api.jikipedia.com/go/search_entities"
|
||||
)
|
||||
|
||||
type value struct {
|
||||
Phrase string `json:"phrase"`
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 初始化engine
|
||||
engine := control.Register(
|
||||
"jikipedia",
|
||||
&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "小鸡词典\n -[查梗|小鸡词典][梗]",
|
||||
},
|
||||
)
|
||||
engine.OnPrefixGroup([]string{"小鸡词典", "查梗"}).Limit(ctxext.LimitByGroup).SetBlock(true).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
keyWord := strings.Trim(ctx.State["args"].(string), " ")
|
||||
|
||||
definition, err := parseKeyword(keyWord)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if definition.String() == "" {
|
||||
ctx.SendChain(message.Text("好像什么都没查到,换个关键词试一试?"))
|
||||
return
|
||||
}
|
||||
imgURL := definition.Get("images.0.scaled.path").String()
|
||||
ctx.SendChain(message.Text("【标题】:", definition.Get("term.title"),
|
||||
"\n【释义】:", definition.Get("plaintext"),
|
||||
"\n【原文】:https://jikipedia.com/definition/", definition.Get("id")),
|
||||
message.Image(imgURL))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func parseKeyword(keyWord string) (definition gjson.Result, err error) {
|
||||
client := &http.Client{}
|
||||
|
||||
values := value{Phrase: keyWord, Page: 1, Size: 10}
|
||||
jsonData, err := json.Marshal(values)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var request *http.Request
|
||||
request, err = http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
request.Header = http.Header{
|
||||
"Accept": {"application/json, text/plain, */*"},
|
||||
"Accept-Encoding": {"gzip, deflate, br"},
|
||||
"Accept-Language": {"zh-CN,zh-TW;q=0.9,zh;q=0.8"},
|
||||
"Client": {"web"},
|
||||
"Client-Version": {"2.7.2g"},
|
||||
"Connection": {"keep-alive"},
|
||||
"Host": {"api.jikipedia.com"},
|
||||
"Origin": {"https://jikipedia.com"},
|
||||
"Referer": {"https://jikipedia.com/"},
|
||||
"Sec-Fetch-Dest": {"empty"},
|
||||
"Sec-Fetch-Mode": {"cors"},
|
||||
"Sec-Fetch-Site": {"same-site"},
|
||||
"Token": {""},
|
||||
"User-Agent": {"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36"},
|
||||
"XID": {"uNo5bL1nyNCp/Gm7lJAHQ91220HLbMT8jqk9IJYhtHA4ofP+zgxwM6lSDIKiYoppP2k1IW/1Vxc2vOVGxOOVReebsLmWPHhTs7NCRygfDkE="},
|
||||
"sec-ch-ua": {`" Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"`},
|
||||
"sec-ch-ua-mobile": {"?1"},
|
||||
"sec-ch-ua-platform": {`"Android"`},
|
||||
}
|
||||
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||||
var response *http.Response
|
||||
response, err = client.Do(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != http.StatusOK {
|
||||
extraInfo := ""
|
||||
if response.StatusCode == 423 {
|
||||
extraInfo = "\n调用过多被网站暂时封禁,请等待数个小时后使用该功能~"
|
||||
}
|
||||
s := fmt.Sprintf("status code: %d%s", response.StatusCode, extraInfo)
|
||||
err = errors.New(s)
|
||||
return
|
||||
}
|
||||
data, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gjson.Get(binary.BytesToString(data), "data").ForEach(func(key, value gjson.Result) bool {
|
||||
definition = value.Get("definitions.0")
|
||||
return definition.String() == ""
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("jptingroom", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "日语听力学习材料\n" +
|
||||
"- 随机日语听力\n" +
|
||||
Brief: "日语听力学习材料",
|
||||
Help: "- 随机日语听力\n" +
|
||||
"- 随机日语歌曲\n" +
|
||||
"- 日语听力 xxx\n" +
|
||||
"- 日语歌曲 xxx\n",
|
||||
@@ -32,7 +32,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -25,8 +25,8 @@ const (
|
||||
func init() {
|
||||
control.Register("juejuezi", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "绝绝子生成器\n" +
|
||||
"- 喝奶茶绝绝子 | 绝绝子吃饭",
|
||||
Brief: "绝绝子生成器",
|
||||
Help: "例: 喝奶茶绝绝子\n绝绝子吃饭",
|
||||
}).OnRegex("[\u4E00-\u9FA5]{0,10}绝绝子[\u4E00-\u9FA5]{0,10}").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
toDealStr := []rune(strings.ReplaceAll(ctx.ExtractPlainText(), "绝绝子", ""))
|
||||
switch len(toDealStr) {
|
||||
|
||||
31
plugin/kfccrazythursday/kfccrazythursday.go
Normal file
31
plugin/kfccrazythursday/kfccrazythursday.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Package kfccrazythursday 疯狂星期四
|
||||
package kfccrazythursday
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
crazyURL = "https://www.iculture.cc/demo/CrazyThursday/api/kfc.php"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("kfccrazythursday", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "疯狂星期四",
|
||||
Help: "疯狂星期四\n",
|
||||
})
|
||||
engine.OnFullMatch("疯狂星期四").SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
data, err := web.GetData(crazyURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.ParseBytes(data).Get("@this.0.content").String()))
|
||||
})
|
||||
}
|
||||
@@ -34,8 +34,8 @@ var (
|
||||
func init() {
|
||||
en := control.Register("lolicon", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "lolicon\n" +
|
||||
"- 随机图片\n" +
|
||||
Brief: "随机图片",
|
||||
Help: "- 随机图片\n" +
|
||||
"- 随机图片 萝莉|少女\n" +
|
||||
"- 设置随机图片地址[http...]",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
|
||||
91
plugin/magicprompt/magicprompt.go
Normal file
91
plugin/magicprompt/magicprompt.go
Normal file
@@ -0,0 +1,91 @@
|
||||
// Package magicprompt MagicPrompt-Stable-Diffusion吟唱提示
|
||||
package magicprompt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
hf "github.com/FloatTech/AnimeAPI/huggingface"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/RomiChan/websocket"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
magicpromptRepo = "Gustavosta/MagicPrompt-Stable-Diffusion"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("magicprompt", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "MagicPrompt-Stable-Diffusion吟唱提示",
|
||||
Help: "- 吟唱提示 xxx",
|
||||
PrivateDataFolder: "magicprompt",
|
||||
})
|
||||
|
||||
// 开启
|
||||
engine.OnPrefixGroup([]string{`吟唱提示`, "吟唱补全"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
_ctx, _cancel := context.WithTimeout(context.Background(), hf.TimeoutMax*time.Second)
|
||||
defer _cancel()
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
|
||||
magicpromptURL := fmt.Sprintf(hf.WssJoinPath, magicpromptRepo)
|
||||
args := ctx.State["args"].(string)
|
||||
c, _, err := websocket.DefaultDialer.Dial(magicpromptURL, nil)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
r := hf.PushRequest{
|
||||
FnIndex: 0,
|
||||
Data: []interface{}{args},
|
||||
}
|
||||
b, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = c.WriteMessage(websocket.TextMessage, b)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
t := time.NewTicker(time.Second * 1)
|
||||
defer t.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
_, data, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
j := gjson.ParseBytes(data)
|
||||
if j.Get("msg").String() == hf.WssCompleteStatus {
|
||||
m := message.Message{}
|
||||
for _, v := range strings.Split(j.Get("output.data.0").String(), "\n\n") {
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(v)))
|
||||
}
|
||||
if id := ctx.Send(m).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
return
|
||||
}
|
||||
case <-_ctx.Done():
|
||||
ctx.SendChain(message.Text("ERROR: 吟唱提示指令超时"))
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -47,11 +47,15 @@ const (
|
||||
"- 取消在\"cron\"的提醒\n" +
|
||||
"- 列出所有提醒\n" +
|
||||
"- 翻牌\n" +
|
||||
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}] {at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名\n" +
|
||||
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}]\n" +
|
||||
"- 测试欢迎语\n" +
|
||||
"- 设置告别辞 参数同设置欢迎语\n" +
|
||||
"- 测试告别辞\n" +
|
||||
"- [开启 | 关闭]入群验证"
|
||||
"- [开启 | 关闭]入群验证\n" +
|
||||
"- 对信息回复:[设置 | 取消]精华\n" +
|
||||
"- 取消精华 [信息ID]\n" +
|
||||
"- /精华列表\n" +
|
||||
"Tips: {at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -62,13 +66,14 @@ var (
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("manager", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "群管插件",
|
||||
Help: hint,
|
||||
PrivateDataFolder: "manager",
|
||||
})
|
||||
|
||||
go func() {
|
||||
db.DBPath = engine.DataFolder() + "config.db"
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -217,7 +222,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("那我就不手下留情了~"))
|
||||
})
|
||||
// 修改名片
|
||||
engine.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
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("名字太长啦!"))
|
||||
@@ -231,33 +236,51 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
})
|
||||
// 修改头衔
|
||||
engine.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
engine.OnRegex(`^修改头衔.*?(\d+).+?\s*(.*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
|
||||
sptitle := ctx.State["regex_matched"].([]string)[2]
|
||||
if sptitle == "" {
|
||||
ctx.SendChain(message.Text("头衔不能为空!"))
|
||||
return
|
||||
} else if len(sptitle) > 18 {
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
|
||||
ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
|
||||
sptitle, // 修改成的群头衔
|
||||
)
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
})
|
||||
// 申请头衔
|
||||
engine.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).
|
||||
engine.OnRegex(`^申请头衔\s*(.*)$`, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
|
||||
sptitle := ctx.State["regex_matched"].([]string)[1]
|
||||
if sptitle == "" {
|
||||
ctx.SendChain(message.Text("头衔不能为空!"))
|
||||
return
|
||||
} else if len(sptitle) > 18 {
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
ctx.Event.UserID, // 被修改群头衔的人
|
||||
ctx.State["regex_matched"].([]string)[1], // 修改成的群头衔
|
||||
ctx.Event.UserID, // 被修改群头衔的人
|
||||
sptitle, // 修改成的群头衔
|
||||
)
|
||||
ctx.SendChain(message.Text("嗯!不错的头衔呢~"))
|
||||
})
|
||||
// 撤回
|
||||
// 群聊中直接回复消息结尾带上撤回
|
||||
// 权限够的话,可以把请求撤回的消息也一并撤回
|
||||
engine.OnRegex(`^\[CQ:reply,id=(-?\d+)\].*撤回$`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 删除需要撤回的消息ID
|
||||
ctx.DeleteMessage(message.NewMessageIDFromString(ctx.State["regex_matched"].([]string)[1]))
|
||||
// 删除请求撤回的消息ID
|
||||
// ctx.DeleteMessage(message.NewMessageIDFromInteger(ctx.Event.MessageID.(int64)))
|
||||
})
|
||||
// 群聊转发
|
||||
engine.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
@@ -577,6 +600,72 @@ func init() { // 插件主体
|
||||
}
|
||||
}
|
||||
})
|
||||
// 设精
|
||||
engine.OnRegex(`^\[CQ:reply,id=(-?\d+)\][\s\S]*(设置|取消)精华$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
essenceID, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
option := ctx.State["regex_matched"].([]string)[2]
|
||||
var rsp zero.APIResponse
|
||||
switch option {
|
||||
case "设置":
|
||||
rsp = ctx.SetGroupEssenceMessage(essenceID)
|
||||
case "取消":
|
||||
rsp = ctx.DeleteGroupEssenceMessage(essenceID)
|
||||
}
|
||||
if rsp.RetCode == 0 {
|
||||
ctx.SendChain(message.Text(option, "成功"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(option, "失败, 信息: ", rsp.Msg, "解释: ", rsp.Wording))
|
||||
}
|
||||
})
|
||||
engine.OnCommand("精华列表", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
list := ctx.GetGroupEssenceMessageList(ctx.Event.GroupID).Array()
|
||||
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("本群精华列表:"))}
|
||||
n := len(list)
|
||||
if n > 30 {
|
||||
ctx.SendChain(message.Text("精华内容太多,仅显示前30个"))
|
||||
n = 30
|
||||
}
|
||||
for _, info := range list[:n] {
|
||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx,
|
||||
message.Text(fmt.Sprintf(
|
||||
"信息ID: %d\n发送者昵称: %s\n发送者QQ 号: %d\n消息发送时间: %s\n操作者昵称: %s\n操作者QQ 号: %d\n精华设置时间: %s",
|
||||
info.Get("message_id").Int(),
|
||||
info.Get("sender_nick").String(),
|
||||
info.Get("sender_id").Int(),
|
||||
time.Unix(info.Get("sender_time").Int(), 0).Format("2006/01/02 15:04:05"),
|
||||
info.Get("operator_nick").String(),
|
||||
info.Get("operator_id").Int(),
|
||||
time.Unix(info.Get("operator_time").Int(), 0).Format("2006/01/02 15:04:05"),
|
||||
))),
|
||||
)
|
||||
msgData := ctx.GetMessage(message.NewMessageIDFromInteger(info.Get("message_id").Int())).Elements
|
||||
if msgData != nil {
|
||||
msg = append(msg,
|
||||
message.CustomNode(info.Get("sender_nick").String(), info.Get("sender_id").Int(), msgData),
|
||||
)
|
||||
} else {
|
||||
msg = append(msg,
|
||||
message.CustomNode(info.Get("sender_nick").String(), info.Get("sender_id").Int(), "[error]信息久远,无法获取,如需查看原始内容请在“精华信息”中查看"),
|
||||
)
|
||||
}
|
||||
}
|
||||
if id := ctx.Send(msg).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
engine.OnPrefix("取消精华", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
essenceID, err := strconv.ParseInt(strings.TrimSpace(ctx.State["args"].(string)), 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: 请输入正确的设精ID"))
|
||||
return
|
||||
}
|
||||
rsp := ctx.DeleteGroupEssenceMessage(essenceID)
|
||||
if rsp.RetCode == 0 {
|
||||
ctx.SendChain(message.Text("取消成功"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("取消失败, 信息: ", rsp.Msg, "解释: ", rsp.Wording))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 传入 ctx 和 welcome格式string 返回cq格式string 使用方法:welcometocq(ctx,w.Msg)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user