Compare commits
129 Commits
create-pul
...
backup
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40544b0c4d | ||
|
|
4b95225355 | ||
|
|
7c523be12d | ||
|
|
6da2044be5 | ||
|
|
0ebc54a17b | ||
|
|
31d29e7fa5 | ||
|
|
21e3659ed3 | ||
|
|
9a611e9eca | ||
|
|
7ca9f2158b | ||
|
|
0fe0a5e4e8 | ||
|
|
8b7749168a | ||
|
|
3fc165d636 | ||
|
|
48632e25b8 | ||
|
|
16901e33a6 | ||
|
|
85b6276b25 | ||
|
|
725f1bcee3 | ||
|
|
1353335bc9 | ||
|
|
3a867bc20e | ||
|
|
b6bada7b83 | ||
|
|
3238205765 | ||
|
|
e60280722f | ||
|
|
8ec4b5251b | ||
|
|
8be003500c | ||
|
|
2f360d1d8a | ||
|
|
91d13c12b2 | ||
|
|
61858a8cf9 | ||
|
|
425e605ab2 | ||
|
|
48cd620fc1 | ||
|
|
940b70f61a | ||
|
|
d6b4289918 | ||
|
|
811fe358b2 | ||
|
|
bb581ab60d | ||
|
|
29be1bd5ec | ||
|
|
64302d3181 | ||
|
|
b4173ecab9 | ||
|
|
9aa1275275 | ||
|
|
ce326ce977 | ||
|
|
77cad0915c | ||
|
|
a382dea51f | ||
|
|
5cc7c40417 | ||
|
|
77aeb38927 | ||
|
|
d7ce199bf7 | ||
|
|
18781e3e64 | ||
|
|
0595fb223a | ||
|
|
b7620460d3 | ||
|
|
bf6180a0ac | ||
|
|
f201eb6497 | ||
|
|
f126d44764 | ||
|
|
33dc16956d | ||
|
|
6e3f395f07 | ||
|
|
da44b02b43 | ||
|
|
c742ab43a3 | ||
|
|
b1b831ff87 | ||
|
|
b82e0aeb2e | ||
|
|
17ab5f1c37 | ||
|
|
b1f4d6fb93 | ||
|
|
710a46f674 | ||
|
|
71b2df2d9f | ||
|
|
734d838182 | ||
|
|
17c60ce961 | ||
|
|
fd3e4ba7f5 | ||
|
|
ec21395606 | ||
|
|
333cfdcb04 | ||
|
|
12ca43a5d4 | ||
|
|
32eed9a4d8 | ||
|
|
8801b8659b | ||
|
|
807752b07d | ||
|
|
a1a6770fdc | ||
|
|
e9da9be361 | ||
|
|
eda51bd549 | ||
|
|
34b82f8cb9 | ||
|
|
dcc31ecaa1 | ||
|
|
dbe30433a1 | ||
|
|
6e24552be8 | ||
|
|
2c8812f45e | ||
|
|
3a293f5e2d | ||
|
|
a4592465dc | ||
|
|
a0c39a7464 | ||
|
|
f4af5bea99 | ||
|
|
3bec61fb78 | ||
|
|
d75494a418 | ||
|
|
c5268d2981 | ||
|
|
65beaa5a41 | ||
|
|
55e5f645fa | ||
|
|
e22b534ed9 | ||
|
|
6cac126ad8 | ||
|
|
38bb4722b9 | ||
|
|
0adaac13c4 | ||
|
|
283e559344 | ||
|
|
6a46db14e1 | ||
|
|
117df2dbe1 | ||
|
|
c9560cd635 | ||
|
|
79b0d31df9 | ||
|
|
355690e4e6 | ||
|
|
189e5e7eba | ||
|
|
d1dd04a973 | ||
|
|
0ea1f68bbe | ||
|
|
9992e351b4 | ||
|
|
b0bf100096 | ||
|
|
766f4e3953 | ||
|
|
dcd0ce1194 | ||
|
|
b9e7122b29 | ||
|
|
0e4f1dfaa6 | ||
|
|
f6213798ba | ||
|
|
8411ed5e3e | ||
|
|
6706adf586 | ||
|
|
3a11769b11 | ||
|
|
d680fbaa4f | ||
|
|
c208e1b120 | ||
|
|
1e7decc966 | ||
|
|
ae9b0c2756 | ||
|
|
763060c42b | ||
|
|
e53eacd908 | ||
|
|
c199d1dd8c | ||
|
|
d7e3709b76 | ||
|
|
acc9d1473d | ||
|
|
db331c6a87 | ||
|
|
3a35fdb4d9 | ||
|
|
27c3095e5d | ||
|
|
b8e84b4049 | ||
|
|
ac0526a03e | ||
|
|
4a4aa5620d | ||
|
|
d092e06fdb | ||
|
|
a960b7c732 | ||
|
|
4a00a5e2fb | ||
|
|
d250f2e9b1 | ||
|
|
8acda6b28b | ||
|
|
5ffd5065ff | ||
|
|
5833e7dd42 |
24
.github/workflows/golint.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Lint
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint_golangci-lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2.5.2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Commit back
|
||||
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 "🎨 改进代码样式"
|
||||
git push
|
||||
4
.github/workflows/linux.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.15
|
||||
go-version: 1.16
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
@@ -39,4 +39,4 @@ jobs:
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ZeroBot-Plugin-linux
|
||||
path: ./artifacts
|
||||
path: ./artifacts
|
||||
|
||||
20
.github/workflows/suggester.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Suggester
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2.5.2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Suggester
|
||||
uses: reviewdog/action-suggester@v1.0.1
|
||||
with:
|
||||
tool_name: golangci-lint
|
||||
2
.github/workflows/windows.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.15
|
||||
go-version: 1.16
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
5
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
data/*
|
||||
main.exe
|
||||
data/SetuTime/cache
|
||||
data/SetuTime/search
|
||||
data/manager
|
||||
94
.golangci.yml
Normal file
@@ -0,0 +1,94 @@
|
||||
linters-settings:
|
||||
errcheck:
|
||||
ignore: fmt:.*,io/ioutil:^Read.*
|
||||
ignoretests: true
|
||||
|
||||
goimports:
|
||||
local-prefixes: github.com/Yiwen-Chan/ZeroBot-Plugin
|
||||
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- exitAfterDefer
|
||||
|
||||
forbidigo:
|
||||
# Forbid the following identifiers
|
||||
forbid:
|
||||
- ^fmt\.Errorf$ # consider errors.Errorf in github.com/pkg/errors
|
||||
|
||||
linters:
|
||||
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||
fast: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- exportloopref
|
||||
- exhaustive
|
||||
#- funlen
|
||||
#- goconst
|
||||
- gocritic
|
||||
#- gocyclo
|
||||
- gofmt
|
||||
- goimports
|
||||
- goprintffuncname
|
||||
#- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- nolintlint
|
||||
- rowserrcheck
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- whitespace
|
||||
- prealloc
|
||||
- predeclared
|
||||
- asciicheck
|
||||
- forbidigo
|
||||
- makezero
|
||||
- revive
|
||||
#- interfacer
|
||||
|
||||
# don't enable:
|
||||
# - scopelint
|
||||
# - gochecknoglobals
|
||||
# - gocognit
|
||||
# - godot
|
||||
# - godox
|
||||
# - goerr113
|
||||
# - interfacer
|
||||
# - maligned
|
||||
# - nestif
|
||||
# - testpackage
|
||||
# - wsl
|
||||
|
||||
run:
|
||||
# default concurrency is a available CPU number.
|
||||
# concurrency: 4 # explicitly omit this value to fully utilize available resources.
|
||||
deadline: 5m
|
||||
issues-exit-code: 1
|
||||
tests: false
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
format: "colored-line-number"
|
||||
print-issued-lines: true
|
||||
print-linter-name: true
|
||||
uniq-by-line: true
|
||||
|
||||
issues:
|
||||
# Fix found issues (if it's supported by the linter)
|
||||
fix: true
|
||||
exclude-use-default: false
|
||||
exclude:
|
||||
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
||||
143
LICENSE
@@ -1,5 +1,5 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
@@ -7,15 +7,17 @@
|
||||
|
||||
Preamble
|
||||
|
||||
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 GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
the GNU General Public License is 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.
|
||||
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.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
@@ -24,34 +26,44 @@ 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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
@@ -60,7 +72,7 @@ modification follow.
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
@@ -537,45 +549,35 @@ 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. 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.
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
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 General Public License into a single
|
||||
under version 3 of the GNU Affero 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 work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
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.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
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
|
||||
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
|
||||
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 Affero General
|
||||
Program specifies that a certain numbered version of the GNU 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 Affero General Public License, you may choose any version ever published
|
||||
GNU 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 Affero General Public License can be used, that proxy's
|
||||
versions of the GNU 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.
|
||||
|
||||
@@ -633,29 +635,40 @@ 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 Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
it under the terms of the GNU 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 Affero General Public License for more details.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
You should have received a copy of the GNU 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 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.
|
||||
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".
|
||||
|
||||
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 AGPL, see
|
||||
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>.
|
||||
|
||||
83
README.md
@@ -10,15 +10,25 @@
|
||||
|
||||
[](https://goreportcard.com/report/github.com/github.com/Yiwen-Chan/ZeroBot-Plugin)
|
||||
[](https://github.com/howmanybots/onebot)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://raw.githubusercontent.com/Yiwen-Chan/ZeroBot-Plugin/master/LICENSE)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
|
||||
[](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### 功能
|
||||
- 群管
|
||||
- 聊天 `import _ "github.com/FloatTech/ZeroBot-Plugin/chat"`
|
||||
- [x] [BOT名字]
|
||||
- [x] [戳一戳BOT]
|
||||
- [x] 空调开
|
||||
- [x] 空调关
|
||||
- [x] 群温度
|
||||
- [x] 设置温度[正整数]
|
||||
- ATRI `import _ "github.com/FloatTech/ZeroBot-Plugin/atri"`
|
||||
- [x] 具体指令看代码
|
||||
- 注:本插件基于 [ATRI](https://github.com/Kyomotoi/ATRI) ,为 Golang 移植版
|
||||
- 群管 `import _ "github.com/FloatTech/ZeroBot-Plugin/manager"`
|
||||
- [x] 禁言[@xxx][分钟]
|
||||
- [x] 解除禁言[@xxx]
|
||||
- [x] 我要自闭 [分钟]
|
||||
@@ -33,20 +43,46 @@
|
||||
- [x] 退出群聊[群号]
|
||||
- [x] *入群欢迎
|
||||
- [x] *退群通知
|
||||
- [x] 在[月份]月[日期]日的[小时]点[分钟]分时(用[url])提醒大家[消息]
|
||||
- [x] 在[月份]月[每周or周几]的[小时]点[分钟]分时(用[url])提醒大家[消息]
|
||||
- [x] 取消在[月份]月[日期]日的[小时]点[分钟]分的提醒
|
||||
- [x] 取消在[月份]月[每周or周几]的[小时]点[分钟]分的提醒
|
||||
- [x] 翻牌
|
||||
- [ ] 同意入群请求
|
||||
- [ ] 同意好友请求
|
||||
- [ ] 撤回[@xxx] [xxx]
|
||||
- [ ] 警告[@xxx]
|
||||
- [x] run[xxx]
|
||||
- 涩图
|
||||
- [x] 来份[涩图/二次元/风景]
|
||||
- [x] 添加[涩图/二次元/风景][P站图片ID]
|
||||
- [x] 删除[涩图/二次元/风景][P站图片ID]
|
||||
- [x] setu -s
|
||||
- [x] setu -x
|
||||
- [x] setu -p
|
||||
- 点歌
|
||||
- 涩图 `import _ "github.com/FloatTech/ZeroBot-Plugin/setutime"`
|
||||
- [x] 来份[涩图/二次元/风景/车万]
|
||||
- [x] 添加[涩图/二次元/风景/车万][P站图片ID]
|
||||
- [x] 删除[涩图/二次元/风景/车万][P站图片ID]
|
||||
- [x] >setu status
|
||||
- 搜图 `import _ "github.com/FloatTech/ZeroBot-Plugin/picsearcher"`
|
||||
- [x] 以图搜图|搜索图片|以图识图[图片]
|
||||
- [x] 搜图[P站图片ID]
|
||||
- 简易随机图片(调用url) `import _ "github.com/FloatTech/ZeroBot-Plugin/randimg"`
|
||||
- [x] 随机图片
|
||||
- [x] 直接随机(无r18检测,后果自负)
|
||||
- [x] 设置随机图片网址[url]
|
||||
- [x] 太涩了(撤回最近发的图)
|
||||
- [x] 评价图片:发送一张图片进行评分
|
||||
- 点歌 `import _ "github.com/FloatTech/ZeroBot-Plugin/music"`
|
||||
- [x] 点歌[xxx]
|
||||
- [x] 网易点歌[xxx]
|
||||
- [x] 酷我点歌[xxx]
|
||||
- [x] 酷狗点歌[xxx]
|
||||
- shindan `import _ "github.com/FloatTech/ZeroBot-Plugin/shindan"`
|
||||
- [x] 今天是什么少女[@xxx]
|
||||
- [x] 异世界转生[@xxx]
|
||||
- [x] 卖萌[@xxx]
|
||||
- GitHub仓库搜索 `import _ "github.com/FloatTech/ZeroBot-Plugin/github"`
|
||||
- [x] >github [xxx]
|
||||
- [x] >github -p [xxx]
|
||||
- 在线代码运行 `import _ "github.com/FloatTech/ZeroBot-Plugin/runcode"`
|
||||
- [x] >runcode help
|
||||
- [x] >runcode [on/off]
|
||||
- [x] >runcode [language] [code block]
|
||||
- TODO...
|
||||
|
||||
### 使用方法
|
||||
@@ -60,18 +96,25 @@
|
||||
| [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 | |
|
||||
|
||||
#### 本地编译
|
||||
#### 本地运行
|
||||
1. 下载安装 [Go](https://studygolang.com/dl/golang/go1.16.2.windows-amd64.msi) 环境
|
||||
2. 下载安装 [TDM-GCC](https://github.com/jmeubank/tdm-gcc/releases),并添加到环境变量
|
||||
3. [clone](https://github.com/Yiwen-Chan/ZeroBot-Plugin/archive/master.zip) 本项目,本地解压
|
||||
4. 编辑 main.go 文件,内容按需修改
|
||||
5. 双击点击 build.bat 文件
|
||||
6. 运行框架,并同时运行本插件
|
||||
2. [clone](https://github.com/Yiwen-Chan/ZeroBot-Plugin/archive/master.zip) 本项目,本地解压
|
||||
3. 编辑 main.go 文件,内容按需修改
|
||||
4. 双击 build.bat 文件 或 直接双击 run.bat 文件
|
||||
5. 运行 OneBot 框架,并同时运行本插件
|
||||
|
||||
#### 利用 Actions 编译 (推荐)
|
||||
#### 利用 Actions 在线编译 (推荐)
|
||||
1. 点击右上角 Fork 本项目,并转跳到自己 Fork 的仓库
|
||||
2. 点击仓库上方的 Actions 按钮,确认使用 Actions
|
||||
3. 编辑 main.go 文件,内容按需修改,返回仓库
|
||||
3. 编辑 main.go 文件,内容按需修改,提交修改后 Actions 自动执行
|
||||
4. 点击 Actions 按钮,等待编译完成,在 Actions 里下载编译好的文件
|
||||
5. 运行框架,并同时运行本插件
|
||||
5. 运行 OneBot 框架,并同时运行本插件
|
||||
6. 啾咪~
|
||||
|
||||
### 特别感谢
|
||||
- [ZeroBot](https://github.com/wdvxdr1123/ZeroBot)
|
||||
- [ATRI](https://github.com/Kyomotoi/ATRI)
|
||||
|
||||
|
||||
## License
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FYiwen-Chan%2FZeroBot-Plugin?ref=badge_large)
|
||||
|
||||
BIN
atri/AZ.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
atri/AZ1.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
atri/FN.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
atri/NO.jpg
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
atri/RocketPunch.amr
Normal file
BIN
atri/SUKI.jpg
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
atri/SUKI1.jpg
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
atri/SUKI2.png
Normal file
|
After Width: | Height: | Size: 693 KiB |
BIN
atri/WH.jpg
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
atri/WH1.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
atri/WH2.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
atri/WH3.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
atri/WQ.jpg
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
atri/WQ1.jpg
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
atri/YES.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
248
atri/atri.go
Normal file
@@ -0,0 +1,248 @@
|
||||
// 本文件基于 https://github.com/Kyomotoi/ATRI
|
||||
// 为 Golang 移植版,语料、素材均来自上述项目
|
||||
// 本项目遵守 AGPL v3 协议进行开源
|
||||
package atri
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
PRIO = -1
|
||||
RES = "https://raw.dihe.moe/Yiwen-Chan/ZeroBot-Plugin/master/atri/"
|
||||
ENABLE = true
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ENABLE = true
|
||||
ctx.SendChain(randText("嗯呜呜……夏生先生……?"))
|
||||
})
|
||||
zero.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ENABLE = false
|
||||
ctx.SendChain(randText("Zzz……Zzz……"))
|
||||
})
|
||||
zero.OnFullMatch("萝卜子", AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("萝卜子是对机器人的蔑称!", "是亚托莉......萝卜子可是对机器人的蔑称"))
|
||||
case 1:
|
||||
ctx.SendChain(randRecord("RocketPunch.amr"))
|
||||
}
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if rand.Intn(10) == 0 {
|
||||
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
|
||||
}
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO - 1).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(randText(
|
||||
"zzzz......",
|
||||
"zzzzzzzz......",
|
||||
"zzz...好涩哦..zzz....",
|
||||
"别...不要..zzz..那..zzz..",
|
||||
"嘻嘻..zzz..呐~..zzzz..",
|
||||
"...zzz....哧溜哧溜....",
|
||||
))
|
||||
case now >= 6 && now < 9:
|
||||
ctx.SendChain(randText(
|
||||
"啊......早上好...(哈欠)",
|
||||
"唔......吧唧...早上...哈啊啊~~~\n早上好......",
|
||||
"早上好......",
|
||||
"早上好呜......呼啊啊~~~~",
|
||||
"啊......早上好。\n昨晚也很激情呢!",
|
||||
"吧唧吧唧......怎么了...已经早上了么...",
|
||||
"早上好!",
|
||||
"......看起来像是傍晚,其实已经早上了吗?",
|
||||
"早上好......欸~~~脸好近呢",
|
||||
))
|
||||
case now >= 9 && now < 18:
|
||||
ctx.SendChain(randText(
|
||||
"哼!这个点还早啥,昨晚干啥去了!?",
|
||||
"熬夜了对吧熬夜了对吧熬夜了对吧???!",
|
||||
"是不是熬夜是不是熬夜是不是熬夜?!",
|
||||
))
|
||||
case now >= 18 && now < 24:
|
||||
ctx.SendChain(randText(
|
||||
"早个啥?哼唧!我都准备洗洗睡了!",
|
||||
"不是...你看看几点了,哼!",
|
||||
"晚上好哇",
|
||||
))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"中午好", "午安"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(randText(
|
||||
"午安w",
|
||||
"午觉要好好睡哦,ATRI会陪伴在你身旁的w",
|
||||
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
|
||||
"睡你午觉去!哼唧!!",
|
||||
))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(randText(
|
||||
"zzzz......",
|
||||
"zzzzzzzz......",
|
||||
"zzz...好涩哦..zzz....",
|
||||
"别...不要..zzz..那..zzz..",
|
||||
"嘻嘻..zzz..呐~..zzzz..",
|
||||
"...zzz....哧溜哧溜....",
|
||||
))
|
||||
case now >= 6 && now < 11:
|
||||
ctx.SendChain(randText(
|
||||
"你可猝死算了吧!",
|
||||
"?啊这",
|
||||
"亲,这边建议赶快去睡觉呢~~~",
|
||||
"不可忍不可忍不可忍!!为何这还不猝死!!",
|
||||
))
|
||||
case now >= 11 && now < 15:
|
||||
ctx.SendChain(randText(
|
||||
"午安w",
|
||||
"午觉要好好睡哦,ATRI会陪伴在你身旁的w",
|
||||
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
|
||||
"睡你午觉去!哼唧!!",
|
||||
))
|
||||
case now >= 15 && now < 19:
|
||||
ctx.SendChain(randText(
|
||||
"难不成??晚上不想睡觉??现在休息",
|
||||
"就......挺离谱的...现在睡觉",
|
||||
"现在还是白天哦,睡觉还太早了",
|
||||
))
|
||||
case now >= 19 && now < 24:
|
||||
ctx.SendChain(randText(
|
||||
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
|
||||
"......(打瞌睡)",
|
||||
"呼...呼...已经睡着了哦~...呼......",
|
||||
"......我、我会在这守着你的,请务必好好睡着",
|
||||
))
|
||||
}
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText(
|
||||
"当然,我是高性能的嘛~!",
|
||||
"小事一桩,我是高性能的嘛",
|
||||
"怎么样?还是我比较高性能吧?",
|
||||
"哼哼!我果然是高性能的呢!",
|
||||
"因为我是高性能的嘛!嗯哼!",
|
||||
"因为我是高性能的呢!",
|
||||
"哎呀~,我可真是太高性能了",
|
||||
"正是,因为我是高性能的",
|
||||
"是的。我是高性能的嘛♪",
|
||||
"毕竟我可是高性能的!",
|
||||
"嘿嘿,我的高性能发挥出来啦♪",
|
||||
"我果然是很高性能的机器人吧!",
|
||||
"是吧!谁叫我这么高性能呢!哼哼!",
|
||||
"交给我吧,有高性能的我陪着呢",
|
||||
"呣......我的高性能,毫无遗憾地施展出来了......",
|
||||
))
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText(
|
||||
"当然,我是高性能的嘛~!",
|
||||
"没事没事,因为我是高性能的嘛!嗯哼!",
|
||||
"没事的,因为我是高性能的呢!",
|
||||
"正是,因为我是高性能的",
|
||||
"是的。我是高性能的嘛♪",
|
||||
"毕竟我可是高性能的!",
|
||||
"那种程度的事不算什么的。\n别看我这样,我可是高性能的",
|
||||
"没问题的,我可是高性能的",
|
||||
))
|
||||
})
|
||||
|
||||
zero.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("YES.png", "NO.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"啊这"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"我好了"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("不许好!", "憋回去!"))
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"?", "?", "¿"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("?", "?", "嗯?", "(。´・ω・)ん?", "ん?"))
|
||||
case 1, 2:
|
||||
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnKeyword("离谱", AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("?", "?", "嗯?", "(。´・ω・)ん?", "ん?"))
|
||||
case 1, 2:
|
||||
ctx.SendChain(randImage("WH.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnKeyword("答应我", AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("我无法回应你的请求"))
|
||||
})
|
||||
}
|
||||
|
||||
func randText(text ...string) message.MessageSegment {
|
||||
length := len(text)
|
||||
return message.Text(text[rand.Intn(length)])
|
||||
}
|
||||
|
||||
func randImage(file ...string) message.MessageSegment {
|
||||
length := len(file)
|
||||
return message.Image(RES + file[rand.Intn(length)])
|
||||
}
|
||||
|
||||
func randRecord(file ...string) message.MessageSegment {
|
||||
length := len(file)
|
||||
return message.Record(RES + file[rand.Intn(length)])
|
||||
}
|
||||
|
||||
// AtriSwitch 控制 ATRI 的开关
|
||||
func AtriSwitch() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
return ENABLE
|
||||
}
|
||||
}
|
||||
|
||||
// AtriSleep 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func AtriSleep() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
55
chat/chat.go
@@ -2,6 +2,7 @@ package chat
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
@@ -44,4 +45,58 @@ func init() { // 插件主体
|
||||
}
|
||||
return
|
||||
})
|
||||
// 群空调
|
||||
var AirConditTemp = map[int64]int{}
|
||||
var AirConditSwitch = map[int64]bool{}
|
||||
zero.OnFullMatch("空调开").SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
AirConditSwitch[ctx.Event.GroupID] = true
|
||||
ctx.SendChain(message.Text("❄️哔~"))
|
||||
})
|
||||
zero.OnFullMatch("空调关").SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
AirConditSwitch[ctx.Event.GroupID] = false
|
||||
delete(AirConditTemp, ctx.Event.GroupID)
|
||||
ctx.SendChain(message.Text("💤哔~"))
|
||||
})
|
||||
zero.OnRegex(`设置温度(\d+)`).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
|
||||
AirConditTemp[ctx.Event.GroupID] = 26
|
||||
}
|
||||
if AirConditSwitch[ctx.Event.GroupID] {
|
||||
temp := ctx.State["regex_matched"].([]string)[1]
|
||||
AirConditTemp[ctx.Event.GroupID], _ = strconv.Atoi(temp)
|
||||
ctx.SendChain(message.Text(
|
||||
"❄️风速中", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
} else {
|
||||
ctx.SendChain(message.Text(
|
||||
"💤", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
}
|
||||
})
|
||||
zero.OnFullMatch(`群温度`).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
|
||||
AirConditTemp[ctx.Event.GroupID] = 26
|
||||
}
|
||||
if AirConditSwitch[ctx.Event.GroupID] {
|
||||
ctx.SendChain(message.Text(
|
||||
"❄️风速中", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
} else {
|
||||
ctx.SendChain(message.Text(
|
||||
"💤", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
BIN
data/SetuTime/SetuTime.db
Normal file
@@ -8,13 +8,14 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
zero.OnRegex(`>G\s(.*)`).SetBlock(true).FirstPriority().
|
||||
zero.OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 发送请求
|
||||
header := http.Header{
|
||||
@@ -22,7 +23,7 @@ func init() { // 插件主体
|
||||
}
|
||||
api, _ := url.Parse("https://api.github.com/search/repositories")
|
||||
api.RawQuery = url.Values{
|
||||
"q": []string{ctx.State["regex_matched"].([]string)[1]},
|
||||
"q": []string{ctx.State["regex_matched"].([]string)[2]},
|
||||
}.Encode()
|
||||
body, err := netGet(api.String(), header)
|
||||
if err != nil {
|
||||
@@ -36,8 +37,13 @@ func init() { // 插件主体
|
||||
}
|
||||
repo := info.Get("items.0")
|
||||
// 发送结果
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "-p ": // 图片模式
|
||||
ctx.SendChain(message.Image(
|
||||
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
|
||||
).Add("cache", 0))
|
||||
default:
|
||||
ctx.SendChain(message.Text(
|
||||
repo.Get("full_name").Str, "\n",
|
||||
"Description: ",
|
||||
repo.Get("description").Str, "\n",
|
||||
@@ -51,8 +57,8 @@ func init() { // 插件主体
|
||||
repo.Get("pushed_at").Str, "\n",
|
||||
"Jump: ",
|
||||
repo.Get("html_url").Str, "\n",
|
||||
),
|
||||
)
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
19
go.mod
@@ -1,12 +1,19 @@
|
||||
module github.com/Yiwen-Chan/ZeroBot-Plugin
|
||||
module github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
go 1.15
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/antchfx/htmlquery v1.2.3
|
||||
github.com/mattn/go-sqlite3 v1.14.6
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2
|
||||
github.com/antchfx/xpath v1.2.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
|
||||
github.com/tidwall/gjson v1.7.4
|
||||
github.com/wdvxdr1123/ZeroBot v1.1.2
|
||||
github.com/tidwall/gjson v1.8.0
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.1
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect
|
||||
modernc.org/sqlite v1.10.8
|
||||
)
|
||||
|
||||
118
go.sum
@@ -1,34 +1,55 @@
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07 h1:7fBPLLoZysaa9PI9ApgzyVMrMLMWBam273YgKwy7Ddg=
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07/go.mod h1:GYrQD70HvBzry1XiZ1tHFNOsOqRkR+ao4XGYZqV4I9c=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2 h1:I7RSCsJVT6elehdaSiWB4n96y06fQxMsvAG494S5Od0=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2/go.mod h1:femu/wVuqVSN/rg209qksMx8/2OKUF8l1PZCNg4RwVA=
|
||||
github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz6M=
|
||||
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
|
||||
github.com/antchfx/xpath v1.1.6 h1:6sVh6hB5T6phw1pFpHRQ+C4bd8sNI+O58flqtg7h0R0=
|
||||
github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||
github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
|
||||
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
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/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
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/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b h1:6Xjqolv/0DDdUqlpnsTomXQvjvvkz7Ux7TcMALvozEw=
|
||||
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
@@ -41,31 +62,96 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
|
||||
github.com/tidwall/gjson v1.7.4 h1:19cchw8FOxkG5mdLRkGf9jqIqEyqdZhPqW60XfyFxk8=
|
||||
github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
|
||||
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/wdvxdr1123/ZeroBot v1.1.2 h1:SGl7lSdFatdSCcVPXTIC56xoMUtXwyz1xWBSkPOAgEU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.1.2/go.mod h1:N4bGSEHCKOrplRHNM8XJFXcXFsK0OUSvmTVakomS+k8=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.1 h1:ougeP+VOAGlQWCAUSB7fjA5trzEvPepU7pujsoYTCq8=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.1/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
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 v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
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/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
|
||||
modernc.org/cc/v3 v3.33.5 h1:gfsIOmcv80EelyQyOHn/Xhlzex8xunhQxWiJRMYmPrI=
|
||||
modernc.org/cc/v3 v3.33.5/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
|
||||
modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo=
|
||||
modernc.org/ccgo/v3 v3.9.4 h1:mt2+HyTZKxva27O6T4C9//0xiNQ/MornL3i8itM5cCs=
|
||||
modernc.org/ccgo/v3 v3.9.4/go.mod h1:19XAY9uOrYnDhOgfHwCABasBvK69jgC4I8+rizbk3Bc=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v1.9.5 h1:zv111ldxmP7DJ5mOIqzRbza7ZDl3kh4ncKfASB2jIYY=
|
||||
modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
|
||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.10.8 h1:tZzV+/FwlSBddiJAHLR+qxsw2nx7jpLMKOCVu6NTjxI=
|
||||
modernc.org/sqlite v1.10.8/go.mod h1:k45BYY2DU82vbS/dJ24OzHCtjPeMEcZ1DV2POiE8nRs=
|
||||
modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
|
||||
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/tcl v1.5.2 h1:sYNjGr4zK6cDH74USl8wVJRrvDX6UOLpG0j4lFvR0W0=
|
||||
modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo=
|
||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
|
||||
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
|
||||
56
main.go
@@ -3,16 +3,30 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||||
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
|
||||
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
|
||||
// 词库类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/atri" // ATRI词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/chat" // 基础词库
|
||||
|
||||
// 实用类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/manager" // 群管
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/runcode" // 在线运行代码
|
||||
|
||||
// 娱乐类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/music" // 点歌
|
||||
//_ "github.com/FloatTech/ZeroBot-ACGImage" //简易随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/setutime" // 涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/shindan" // 测定
|
||||
|
||||
// 以下为内置依赖,勿动
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/chat"
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/github"
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/manager"
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/music"
|
||||
//_ "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime"
|
||||
log "github.com/sirupsen/logrus"
|
||||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -24,20 +38,34 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Printf(`
|
||||
fmt.Print(`
|
||||
====================[ZeroBot-Plugin]====================
|
||||
* OneBot + ZeroBot + Golang
|
||||
* Copyright © 2018-2020 Kanri, All Rights Reserved
|
||||
* Project: https://github.com/Yiwen-Chan/ZeroBot-Plugin
|
||||
* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST
|
||||
* Copyright © 2021 Kanri, DawnNights, Fumiama
|
||||
* Project: https://github.com/FloatTech/ZeroBot-Plugin
|
||||
========================================================
|
||||
`)
|
||||
`) // 启动打印
|
||||
zero.Run(zero.Config{
|
||||
NickName: []string{"椛椛"},
|
||||
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
|
||||
CommandPrefix: "/",
|
||||
SuperUsers: []string{"825111790", "213864964"}, // 必须修改,否则无权限
|
||||
SuperUsers: []string{"213864964"}, // 必须修改,否则无权限
|
||||
Driver: []zero.Driver{
|
||||
driver.NewWebSocketClient("127.0.0.1", "6700", ""),
|
||||
&driver.WSClient{
|
||||
Url: "ws://127.0.0.1:6700",
|
||||
AccessToken: "",
|
||||
},
|
||||
},
|
||||
})
|
||||
// 帮助
|
||||
zero.OnFullMatchGroup([]string{"help", "/help", ".help", "菜单", "帮助"}, zero.OnlyToMe).SetBlock(true).SetPriority(999).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(
|
||||
"* OneBot + ZeroBot + Golang ", "\n",
|
||||
"* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST", "\n",
|
||||
"* Copyright © 2021 Kanri, DawnNights, Fumiama ", "\n",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
))
|
||||
})
|
||||
select {}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,39 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
timer "github.com/FloatTech/ZeroBot-Plugin-Timer"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// 菜单
|
||||
zero.OnFullMatch("群管系统", zero.AdminPermission).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send(`====群管====
|
||||
- 禁言@QQ 1分钟
|
||||
- 解除禁言 @QQ
|
||||
- 我要自闭 1分钟
|
||||
- 开启全员禁言
|
||||
- 解除全员禁言
|
||||
- 升为管理@QQ
|
||||
- 取消管理@QQ
|
||||
- 修改名片@QQ XXX
|
||||
- 修改头衔@QQ XXX
|
||||
- 申请头衔 XXX
|
||||
- 踢出群聊@QQ
|
||||
- 退出群聊 1234
|
||||
- 群聊转发 1234 XXX
|
||||
- 私聊转发 0000 XXX`)
|
||||
ctx.SendChain(message.Text(
|
||||
"====群管====", "\n",
|
||||
"- 禁言@QQ 1分钟", "\n",
|
||||
"- 解除禁言 @QQ", "\n",
|
||||
"- 我要自闭 1分钟", "\n",
|
||||
"- 开启全员禁言", "\n",
|
||||
"- 解除全员禁言", "\n",
|
||||
"- 升为管理@QQ", "\n",
|
||||
"- 取消管理@QQ", "\n",
|
||||
"- 修改名片@QQ XXX", "\n",
|
||||
"- 修改头衔@QQ XXX", "\n",
|
||||
"- 申请头衔 XXX", "\n",
|
||||
"- 踢出群聊@QQ", "\n",
|
||||
"- 退出群聊 1234", "\n",
|
||||
"- 群聊转发 1234 XXX", "\n",
|
||||
"- 私聊转发 0000 XXX",
|
||||
))
|
||||
return
|
||||
})
|
||||
// 升为管理
|
||||
@@ -41,7 +49,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
ctx.Send(nickname + " 升为了管理~")
|
||||
ctx.SendChain(message.Text(nickname + " 升为了管理~"))
|
||||
return
|
||||
})
|
||||
// 取消管理
|
||||
@@ -57,7 +65,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
ctx.Send("残念~ " + nickname + " 暂时失去了管理员的资格")
|
||||
ctx.SendChain(message.Text("残念~ " + nickname + " 暂时失去了管理员的资格"))
|
||||
return
|
||||
})
|
||||
// 踢出群聊
|
||||
@@ -73,7 +81,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
ctx.Send("残念~ " + nickname + " 被放逐")
|
||||
ctx.SendChain(message.Text("残念~ " + nickname + " 被放逐"))
|
||||
return
|
||||
})
|
||||
// 退出群聊
|
||||
@@ -92,7 +100,7 @@ func init() { // 插件主体
|
||||
ctx.Event.GroupID,
|
||||
true,
|
||||
)
|
||||
ctx.Send("全员自闭开始~")
|
||||
ctx.SendChain(message.Text("全员自闭开始~"))
|
||||
return
|
||||
})
|
||||
// 解除全员禁言
|
||||
@@ -102,7 +110,7 @@ func init() { // 插件主体
|
||||
ctx.Event.GroupID,
|
||||
false,
|
||||
)
|
||||
ctx.Send("全员自闭结束~")
|
||||
ctx.SendChain(message.Text("全员自闭结束~"))
|
||||
return
|
||||
})
|
||||
// 禁言
|
||||
@@ -127,7 +135,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
|
||||
duration*60, // 要禁言的时间(分钟)
|
||||
)
|
||||
ctx.Send("小黑屋收留成功~")
|
||||
ctx.SendChain(message.Text("小黑屋收留成功~"))
|
||||
return
|
||||
})
|
||||
// 解除禁言
|
||||
@@ -138,7 +146,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要解除禁言的人的qq
|
||||
0,
|
||||
)
|
||||
ctx.Send("小黑屋释放成功~")
|
||||
ctx.SendChain(message.Text("小黑屋释放成功~"))
|
||||
return
|
||||
})
|
||||
// 自闭禁言
|
||||
@@ -163,7 +171,7 @@ func init() { // 插件主体
|
||||
ctx.Event.UserID,
|
||||
duration*60, // 要自闭的时间(分钟)
|
||||
)
|
||||
ctx.Send("那我就不手下留情了~")
|
||||
ctx.SendChain(message.Text("那我就不手下留情了~"))
|
||||
return
|
||||
})
|
||||
// 修改名片
|
||||
@@ -174,7 +182,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
|
||||
ctx.State["regex_matched"].([]string)[2], // 修改成的群名片
|
||||
)
|
||||
ctx.Send("嗯!已经修改了")
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
return
|
||||
})
|
||||
// 修改头衔
|
||||
@@ -185,7 +193,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
|
||||
ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
|
||||
)
|
||||
ctx.Send("嗯!已经修改了")
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
return
|
||||
})
|
||||
// 申请头衔
|
||||
@@ -196,7 +204,7 @@ func init() { // 插件主体
|
||||
ctx.Event.UserID, // 被修改群头衔的人
|
||||
ctx.State["regex_matched"].([]string)[1], // 修改成的群头衔
|
||||
)
|
||||
ctx.Send("嗯!不错的头衔呢~")
|
||||
ctx.SendChain(message.Text("嗯!不错的头衔呢~"))
|
||||
return
|
||||
})
|
||||
// 群聊转发
|
||||
@@ -210,7 +218,7 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的群
|
||||
content, // 需要发送的信息
|
||||
)
|
||||
ctx.Send("📧 --> " + ctx.State["regex_matched"].([]string)[1])
|
||||
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
|
||||
return
|
||||
})
|
||||
// 私聊转发
|
||||
@@ -224,14 +232,61 @@ func init() { // 插件主体
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的人的qq
|
||||
content, // 需要发送的信息
|
||||
)
|
||||
ctx.Send("📧 --> " + ctx.State["regex_matched"].([]string)[1])
|
||||
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
|
||||
return
|
||||
})
|
||||
|
||||
// 定时提醒
|
||||
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, false)
|
||||
ts.Grpid = uint64(ctx.Event.GroupID)
|
||||
if ts.Enable {
|
||||
go timer.RegisterTimer(ts, true)
|
||||
ctx.Send("记住了~")
|
||||
} else {
|
||||
ctx.Send("参数非法!")
|
||||
}
|
||||
return
|
||||
})
|
||||
// 取消定时
|
||||
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, true)
|
||||
ti := timer.GetTimerInfo(ts)
|
||||
t, ok := (*timer.Timers)[ti]
|
||||
if ok {
|
||||
t.Enable = false
|
||||
delete(*timer.Timers, ti) //避免重复取消
|
||||
timer.SaveTimers()
|
||||
ctx.Send("取消成功~")
|
||||
} else {
|
||||
ctx.Send("没有这个定时器哦~")
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
// 随机点名
|
||||
zero.OnFullMatchGroup([]string{"翻牌"}).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
list := ctx.GetGroupMemberList(ctx.Event.GroupID)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
rand_index := fmt.Sprint(rand.Intn(int(list.Get("#").Int())))
|
||||
random_card := list.Get(rand_index + ".card").String()
|
||||
if random_card == "" {
|
||||
random_card = list.Get(rand_index + ".nickname").String()
|
||||
}
|
||||
ctx.Send(random_card + ",就是你啦!")
|
||||
}
|
||||
})
|
||||
// 入群欢迎
|
||||
zero.OnNotice().SetBlock(false).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.NoticeType == "group_increase" {
|
||||
ctx.Send("欢迎~")
|
||||
ctx.SendChain(message.Text("欢迎~"))
|
||||
}
|
||||
return
|
||||
})
|
||||
@@ -239,7 +294,7 @@ func init() { // 插件主体
|
||||
zero.OnNotice().SetBlock(false).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.NoticeType == "group_decrease" {
|
||||
ctx.Send("有人跑路了~")
|
||||
ctx.SendChain(message.Text("有人跑路了~"))
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*
|
||||
QQ音乐、网易云、酷狗、酷我 点歌
|
||||
*/
|
||||
package music
|
||||
|
||||
import (
|
||||
|
||||
7
run.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
go version
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go mod tidy
|
||||
::go build -ldflags="-s -w" -o ZeroBot-Plugin.exe
|
||||
go run main.go
|
||||
pause
|
||||
@@ -1,6 +1,6 @@
|
||||
go version
|
||||
gcc -v
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go build -ldflags="-s -w" -o ZeroBot-Plugin-windows.exe
|
||||
pause
|
||||
go mod tidy
|
||||
#go build -ldflags="-s -w" -o ZeroBot-Plugin
|
||||
go run main.go
|
||||
262
runcode/code_runner.go
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
基于 https://tool.runoob.com 的在线运行代码
|
||||
*/
|
||||
package runcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var limit = rate.NewManager(time.Minute*3, 5)
|
||||
|
||||
func init() {
|
||||
RunAllow := true
|
||||
|
||||
templates := map[string]string{
|
||||
"py2": "print 'Hello World!'",
|
||||
"ruby": "puts \"Hello World!\";",
|
||||
"rb": "puts \"Hello World!\";",
|
||||
"php": "<?php\n\techo 'Hello World!';\n?>",
|
||||
"javascript": "console.log(\"Hello World!\");",
|
||||
"js": "console.log(\"Hello World!\");",
|
||||
"node.js": "console.log(\"Hello World!\");",
|
||||
"scala": "object Main {\n def main(args:Array[String])\n {\n println(\"Hello World!\")\n }\n\t\t\n}",
|
||||
"go": "package main\n\nimport \"fmt\"\n\nfunc main() {\n fmt.Println(\"Hello, World!\")\n}",
|
||||
"c": "#include <stdio.h>\n\nint main()\n{\n printf(\"Hello, World! \n\");\n return 0;\n}",
|
||||
"c++": "#include <iostream>\nusing namespace std;\n\nint main()\n{\n cout << \"Hello World\";\n return 0;\n}",
|
||||
"cpp": "#include <iostream>\nusing namespace std;\n\nint main()\n{\n cout << \"Hello World\";\n return 0;\n}",
|
||||
"java": "public class HelloWorld {\n public static void main(String []args) {\n System.out.println(\"Hello World!\");\n }\n}",
|
||||
"rust": "fn main() {\n println!(\"Hello World!\");\n}",
|
||||
"rs": "fn main() {\n println!(\"Hello World!\");\n}",
|
||||
"c#": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
|
||||
"cs": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
|
||||
"csharp": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
|
||||
"shell": "echo 'Hello World!'",
|
||||
"bash": "echo 'Hello World!'",
|
||||
"erlang": "% escript will ignore the first line\n\nmain(_) ->\n io:format(\"Hello World!~n\").",
|
||||
"perl": "print \"Hello, World!\n\";",
|
||||
"python": "print(\"Hello, World!\")",
|
||||
"py": "print(\"Hello, World!\")",
|
||||
"swift": "var myString = \"Hello, World!\"\nprint(myString)",
|
||||
"lua": "var myString = \"Hello, World!\"\nprint(myString)",
|
||||
"pascal": "runcode Hello;\nbegin\n writeln ('Hello, world!')\nend.",
|
||||
"kotlin": "fun main(args : Array<String>){\n println(\"Hello World!\")\n}",
|
||||
"kt": "fun main(args : Array<String>){\n println(\"Hello World!\")\n}",
|
||||
"r": "myString <- \"Hello, World!\"\nprint ( myString)",
|
||||
"vb": "Module Module1\n\n Sub Main()\n Console.WriteLine(\"Hello World!\")\n End Sub\n\nEnd Module",
|
||||
"typescript": "const hello : string = \"Hello World!\"\nconsole.log(hello)",
|
||||
"ts": "const hello : string = \"Hello World!\"\nconsole.log(hello)",
|
||||
}
|
||||
|
||||
table := map[string][2]string{
|
||||
"py2": {"0", "py"},
|
||||
"ruby": {"1", "rb"},
|
||||
"rb": {"1", "rb"},
|
||||
"php": {"3", "php"},
|
||||
"javascript": {"4", "js"},
|
||||
"js": {"4", "js"},
|
||||
"node.js": {"4", "js"},
|
||||
"scala": {"5", "scala"},
|
||||
"go": {"6", "go"},
|
||||
"c": {"7", "c"},
|
||||
"c++": {"7", "cpp"},
|
||||
"cpp": {"7", "cpp"},
|
||||
"java": {"8", "java"},
|
||||
"rust": {"9", "rs"},
|
||||
"rs": {"9", "rs"},
|
||||
"c#": {"10", "cs"},
|
||||
"cs": {"10", "cs"},
|
||||
"csharp": {"10", "cs"},
|
||||
"shell": {"10", "sh"},
|
||||
"bash": {"10", "sh"},
|
||||
"erlang": {"12", "erl"},
|
||||
"perl": {"14", "pl"},
|
||||
"python": {"15", "py3"},
|
||||
"py": {"15", "py3"},
|
||||
"swift": {"16", "swift"},
|
||||
"lua": {"17", "lua"},
|
||||
"pascal": {"18", "pas"},
|
||||
"kotlin": {"19", "kt"},
|
||||
"kt": {"19", "kt"},
|
||||
"r": {"80", "r"},
|
||||
"vb": {"84", "vb"},
|
||||
"typescript": {"1010", "ts"},
|
||||
"ts": {"1010", "ts"},
|
||||
}
|
||||
|
||||
zero.OnFullMatch(">runcode help").SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(
|
||||
"使用说明: ", "\n",
|
||||
">runcode [language] [code block]", "\n",
|
||||
"模板查看: ", "\n",
|
||||
">runcode [language] help", "\n",
|
||||
"支持语种: ", "\n",
|
||||
"Go || Python || C/C++ || C# || Java || Lua ", "\n",
|
||||
"JavaScript || TypeScript || PHP || Shell ", "\n",
|
||||
"Kotlin || Rust || Erlang || Ruby || Swift ", "\n",
|
||||
"R || VB || Py2 || Perl || Pascal || Scala ", "\n",
|
||||
))
|
||||
})
|
||||
|
||||
zero.OnFullMatch(">runcode on", zero.AdminPermission).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
RunAllow = true
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text("在线运行代码功能已启用"),
|
||||
)
|
||||
})
|
||||
|
||||
zero.OnFullMatch(">runcode off", zero.AdminPermission).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
RunAllow = false
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text("在线运行代码功能已禁用"),
|
||||
)
|
||||
})
|
||||
|
||||
zero.OnRegex(`^>runcode\s(.+?)\s([\s\S]+)$`).SetBlock(true).SecondPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
return
|
||||
}
|
||||
language := ctx.State["regex_matched"].([]string)[1]
|
||||
language = strings.ToLower(language)
|
||||
if runType, exist := table[language]; !exist {
|
||||
// 不支持语言
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text("语言不是受支持的编程语种呢~"),
|
||||
)
|
||||
return
|
||||
} else {
|
||||
if RunAllow == false {
|
||||
// 运行代码被禁用
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text("在线运行代码功能已被禁用"),
|
||||
)
|
||||
return
|
||||
}
|
||||
// 执行运行
|
||||
block := ctx.State["regex_matched"].([]string)[2]
|
||||
block = message.UnescapeCQCodeText(block)
|
||||
|
||||
if block == "help" {
|
||||
//输出模板
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, " ", language, "-template:\n"),
|
||||
message.Text(
|
||||
">runcode ", language, "\n",
|
||||
templates[language],
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if output, err := runCode(block, runType); err != nil {
|
||||
// 运行失败
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text("ERROR: ", err),
|
||||
)
|
||||
return
|
||||
} else {
|
||||
// 运行成功
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text(output),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func runCode(code string, runType [2]string) (string, error) {
|
||||
// 对菜鸟api发送数据并返回结果
|
||||
api := "https://tool.runoob.com/compile2.php"
|
||||
|
||||
header := http.Header{
|
||||
"Content-Type": []string{"application/x-www-form-urlencoded; charset=UTF-8"},
|
||||
"Referer": []string{"https://c.runoob.com/"},
|
||||
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0"},
|
||||
}
|
||||
|
||||
val := url.Values{
|
||||
"code": []string{code},
|
||||
"token": []string{"4381fe197827ec87cbac9552f14ec62a"},
|
||||
"stdin": []string{""},
|
||||
"language": []string{runType[0]},
|
||||
"fileext": []string{runType[1]},
|
||||
}
|
||||
// 发送请求
|
||||
client := &http.Client{
|
||||
Timeout: time.Duration(15 * time.Second),
|
||||
}
|
||||
request, _ := http.NewRequest("POST", api, strings.NewReader(val.Encode()))
|
||||
request.Header = header
|
||||
body, err := client.Do(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer body.Body.Close()
|
||||
if body.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("code %d", body.StatusCode)
|
||||
}
|
||||
res, err := ioutil.ReadAll(body.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 结果处理
|
||||
content := gjson.ParseBytes(res)
|
||||
if e := content.Get("errors").Str; e != "\n\n" {
|
||||
return "", fmt.Errorf(cutTooLong(clearNewLineSuffix(e)))
|
||||
}
|
||||
output := content.Get("output").Str
|
||||
|
||||
return cutTooLong(clearNewLineSuffix(output)), nil
|
||||
}
|
||||
|
||||
// 清除末尾多余的换行符
|
||||
func clearNewLineSuffix(text string) string {
|
||||
for strings.HasSuffix(text, "\n") {
|
||||
text = text[:len(text)-1]
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
// 截断过长文本
|
||||
func cutTooLong(text string) string {
|
||||
temp := []rune(text)
|
||||
count := 0
|
||||
for i := range temp {
|
||||
switch {
|
||||
case temp[i] == 13 && i < len(temp)-1 && temp[i+1] == 10:
|
||||
// 匹配 \r\n 跳过,等 \n 自己加
|
||||
case temp[i] == 10:
|
||||
count++
|
||||
case temp[i] == 13:
|
||||
count++
|
||||
}
|
||||
if count > 30 || i > 1000 {
|
||||
temp = append(temp[:i-1], []rune("\n............\n............")...)
|
||||
break
|
||||
}
|
||||
}
|
||||
return string(temp)
|
||||
}
|
||||
111
setutime/classify.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var (
|
||||
CACHE_IMG_FILE = "/tmp/setugt"
|
||||
CACHE_URI = "file:///" + CACHE_IMG_FILE
|
||||
VOTE_API_URL = "http://saki.fumiama.top/vote?uuid=零号&img=%s&class=%d"
|
||||
CLASSIFY_HEAD = "http://saki.fumiama.top:62002/dice?url="
|
||||
MsgofGrp = make(map[int64]int64)
|
||||
dhashofmsg = make(map[int64]string)
|
||||
)
|
||||
|
||||
func Classify(ctx *zero.Ctx, targeturl string, noimg bool) {
|
||||
get_url := CLASSIFY_HEAD + url.QueryEscape(targeturl)
|
||||
if noimg {
|
||||
get_url += "&noimg=true"
|
||||
}
|
||||
resp, err := http.Get(get_url)
|
||||
if err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
} else {
|
||||
if noimg {
|
||||
data, err1 := ioutil.ReadAll(resp.Body)
|
||||
if err1 == nil {
|
||||
dhash := gjson.GetBytes(data, "img").String()
|
||||
class := int(gjson.GetBytes(data, "class").Int())
|
||||
replyClass(ctx, dhash, class, noimg)
|
||||
} else {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err1))
|
||||
}
|
||||
} else {
|
||||
class, err1 := strconv.Atoi(resp.Header.Get("Class"))
|
||||
dhash := resp.Header.Get("DHash")
|
||||
if err1 != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err1))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// 写入文件
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
f, _ := os.OpenFile(CACHE_IMG_FILE, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
defer f.Close()
|
||||
f.Write(data)
|
||||
replyClass(ctx, dhash, class, noimg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Vote(ctx *zero.Ctx, class int) {
|
||||
msg, ok := MsgofGrp[ctx.Event.GroupID]
|
||||
if ok {
|
||||
ctx.DeleteMessage(msg)
|
||||
delete(MsgofGrp, ctx.Event.GroupID)
|
||||
dhash, ok2 := dhashofmsg[msg]
|
||||
if ok2 {
|
||||
http.Get(fmt.Sprintf(VOTE_API_URL, dhash, class))
|
||||
delete(dhashofmsg, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func replyClass(ctx *zero.Ctx, dhash string, class int, noimg bool) {
|
||||
if class > 4 {
|
||||
switch class {
|
||||
case 5:
|
||||
ctx.Send("[5]影响不好啦!")
|
||||
case 6:
|
||||
ctx.Send("[6]太涩啦,🐛了!")
|
||||
}
|
||||
if dhash != "" && !noimg {
|
||||
b14, err3 := url.QueryUnescape(dhash)
|
||||
if err3 == nil {
|
||||
ctx.Send("给你点提示哦:" + b14)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var last_message_id int64
|
||||
if !noimg {
|
||||
last_message_id = ctx.SendChain(message.Image(CACHE_URI).Add("no_cache", "0"))
|
||||
last_group_id := ctx.Event.GroupID
|
||||
MsgofGrp[last_group_id] = last_message_id
|
||||
dhashofmsg[last_message_id] = dhash
|
||||
} else {
|
||||
last_message_id = ctx.Event.MessageID
|
||||
}
|
||||
switch class {
|
||||
case 0:
|
||||
ctx.SendChain(message.Reply(last_message_id), message.Text("[0]一堆像素点"))
|
||||
case 1:
|
||||
ctx.SendChain(message.Reply(last_message_id), message.Text("[1]普通"))
|
||||
case 2:
|
||||
ctx.SendChain(message.Reply(last_message_id), message.Text("[2]有点意思"))
|
||||
case 3:
|
||||
ctx.SendChain(message.Reply(last_message_id), message.Text("[3]不错"))
|
||||
case 4:
|
||||
ctx.SendChain(message.Reply(last_message_id), message.Text("[4]我好啦!"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,137 +2,166 @@ package setutime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
utils "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime/utils"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/ascii2d"
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
"github.com/FloatTech/AnimeAPI/saucenao"
|
||||
)
|
||||
|
||||
var (
|
||||
CACHEPATH = os.TempDir() // 缓冲图片路径
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// 根据PID搜图
|
||||
zero.OnRegex(`^搜图(\d+)$`).SetBlock(true).SetPriority(30).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id := utils.Str2Int(ctx.State["regex_matched"].([]string)[1])
|
||||
id, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
ctx.Send("少女祈祷中......")
|
||||
// 获取P站插图信息
|
||||
illust := &utils.Illust{}
|
||||
if err := illust.IllustInfo(id); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
illust, err := pixiv.Works(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 下载P站插图
|
||||
if _, err := illust.PixivPicDown(CACHEPATH); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
if _, err := download(illust, "data/SetuTime/search/"); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 发送搜索结果
|
||||
ctx.Send(illust.DetailPic)
|
||||
return
|
||||
ctx.SendChain(
|
||||
message.Image(file(illust)),
|
||||
message.Text(
|
||||
"\n",
|
||||
"标题:", illust.Title, "\n",
|
||||
"插画ID:", illust.Pid, "\n",
|
||||
"画师:", illust.UserName, "\n",
|
||||
"画师ID:", illust.UserId, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
|
||||
),
|
||||
)
|
||||
})
|
||||
// 通过回复以图搜图
|
||||
zero.OnRegex(`\[CQ:reply,id=(.*?)\](.*)搜索图片`).SetBlock(true).SetPriority(32).
|
||||
// 以图搜图
|
||||
zero.OnMessage(FullMatchText("以图搜图", "搜索图片", "以图识图"), MustHasPicture()).SetBlock(true).SetPriority(999).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var pics []string // 图片搜索池子
|
||||
// 获取回复的上文图片链接
|
||||
id := utils.Str2Int(ctx.State["regex_matched"].([]string)[1])
|
||||
for _, elem := range ctx.GetMessage(id).Elements {
|
||||
if elem.Type == "image" {
|
||||
pics = append(pics, elem.Data["url"])
|
||||
}
|
||||
}
|
||||
// 没有收到图片则向用户索取
|
||||
if len(pics) == 0 {
|
||||
ctx.Send("请发送多张图片!")
|
||||
next := ctx.FutureEvent("message", ctx.CheckSession())
|
||||
recv, cancel := next.Repeat()
|
||||
for e := range recv { // 循环获取channel发来的信息
|
||||
if len(e.Message) == 1 && e.Message[0].Type == "text" {
|
||||
cancel() // 如果是纯文本则退出索取
|
||||
break
|
||||
}
|
||||
for _, elem := range e.Message {
|
||||
if elem.Type == "image" { // 将信息中的图片添加到搜索池子
|
||||
pics = append(pics, elem.Data["url"])
|
||||
}
|
||||
}
|
||||
if len(pics) >= 5 {
|
||||
cancel() // 如果是图片数量大于等于5则退出索取
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(pics) == 0 {
|
||||
ctx.Send("没有收到图片,搜图结束......")
|
||||
return
|
||||
}
|
||||
// 开始搜索图片
|
||||
ctx.Send("少女祈祷中......")
|
||||
for _, pic := range pics {
|
||||
if text, err := utils.SauceNaoSearch(pic); err == nil {
|
||||
ctx.Send(text) // 返回SauceNAO的结果
|
||||
continue
|
||||
for _, pic := range ctx.State["image_url"].([]string) {
|
||||
fmt.Println(pic)
|
||||
if result, err := saucenao.SauceNAO(pic); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
}
|
||||
if text, err := utils.Ascii2dSearch(pic); err == nil {
|
||||
ctx.Send(text) // 返回Ascii2d的结果
|
||||
// 返回SauceNAO的结果
|
||||
ctx.SendChain(
|
||||
message.Text("我有把握是这个!"),
|
||||
message.Image(result.Thumbnail),
|
||||
message.Text(
|
||||
"\n",
|
||||
"相似度:", result.Similarity, "\n",
|
||||
"标题:", result.Title, "\n",
|
||||
"插画ID:", result.PixivID, "\n",
|
||||
"画师:", result.MemberName, "\n",
|
||||
"画师ID:", result.MemberID, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", result.PixivID,
|
||||
),
|
||||
)
|
||||
continue
|
||||
}
|
||||
if result, err := ascii2d.Ascii2d(pic); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
// 通过命令以图搜图
|
||||
zero.OnKeywordGroup([]string{"以图识图", "以图搜图", "搜索图片"}).SetBlock(true).SetPriority(33).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var pics []string // 图片搜索池子
|
||||
// 获取信息中图片链接
|
||||
for _, elem := range ctx.Event.Message {
|
||||
if elem.Type == "image" {
|
||||
pics = append(pics, elem.Data["url"])
|
||||
}
|
||||
}
|
||||
// 没有收到图片则向用户索取
|
||||
if len(pics) == 0 {
|
||||
ctx.Send("请发送多张图片!")
|
||||
next := ctx.FutureEvent("message", zero.CheckUser(ctx.Event.UserID))
|
||||
recv, cancel := next.Repeat()
|
||||
for e := range recv { // 循环获取channel发来的信息
|
||||
if len(e.Message) == 1 && e.Message[0].Type == "text" {
|
||||
cancel() // 如果是纯文本则退出索取
|
||||
break
|
||||
}
|
||||
for _, elem := range e.Message {
|
||||
if elem.Type == "image" { // 将信息中的图片添加到搜索池子
|
||||
pics = append(pics, elem.Data["url"])
|
||||
}
|
||||
}
|
||||
if len(pics) >= 5 {
|
||||
cancel() // 如果是图片数量大于等于5则退出索取
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(pics) == 0 {
|
||||
ctx.Send("没有收到图片,搜图结束......")
|
||||
return
|
||||
}
|
||||
// 开始搜索图片
|
||||
ctx.Send("少女祈祷中......")
|
||||
for _, pic := range pics {
|
||||
if text, err := utils.SauceNaoSearch(pic); err == nil {
|
||||
ctx.Send(text) // 返回SauceNAO的结果
|
||||
// 返回Ascii2d的结果
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
"大概是这个?", "\n",
|
||||
"标题:", result.Title, "\n",
|
||||
"插画ID:", result.Pid, "\n",
|
||||
"画师:", result.UserName, "\n",
|
||||
"画师ID:", result.UserId, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", result.Pid,
|
||||
),
|
||||
)
|
||||
continue
|
||||
} else {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
}
|
||||
if text, err := utils.Ascii2dSearch(pic); err == nil {
|
||||
ctx.Send(text) // 返回Ascii2d的结果
|
||||
continue
|
||||
} else {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// FullMatchText 如果信息中文本完全匹配则返回 true
|
||||
func FullMatchText(src ...string) zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "text" {
|
||||
text := elem.Data["text"]
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.ReplaceAll(text, "\r", "")
|
||||
text = strings.ReplaceAll(text, "\n", "")
|
||||
for _, s := range src {
|
||||
if text == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// HasPicture 消息含有图片返回 true
|
||||
func HasPicture() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
url := []string{}
|
||||
// 如果是回复信息则将信息替换成被回复的那条
|
||||
if msg[0].Type == "reply" {
|
||||
id, _ := strconv.Atoi(msg[0].Data["id"])
|
||||
msg = ctx.GetMessage(int64(id)).Elements
|
||||
}
|
||||
// 遍历信息中所有图片
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "image" {
|
||||
url = append(url, elem.Data["url"])
|
||||
}
|
||||
}
|
||||
// 如果有图片就返回true
|
||||
if len(url) > 0 {
|
||||
ctx.State["image_url"] = url
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MustHasPicture 消息不存在图片阻塞60秒至有图片,超时返回 false
|
||||
func MustHasPicture() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
if HasPicture()(ctx) {
|
||||
return true
|
||||
}
|
||||
// 没有图片就索取
|
||||
ctx.Send("请发送一张图片")
|
||||
next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID), HasPicture())
|
||||
recv, cancel := next.Repeat()
|
||||
select {
|
||||
case e := <-recv:
|
||||
cancel()
|
||||
newCtx := &zero.Ctx{Event: e, State: zero.State{}}
|
||||
if HasPicture()(newCtx) {
|
||||
ctx.State["image_url"] = newCtx.State["image_url"]
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case <-time.After(time.Second * 60):
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
73
setutime/rand_image.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
RANDOM_API_URL = "https://api.pixivweb.com/anime18r.php?return=img"
|
||||
BLOCK_REQUEST = false
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
zero.OnRegex(`^设置随机图片网址(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(20).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["regex_matched"].([]string)[1]
|
||||
if !strings.HasPrefix(url, "http") {
|
||||
ctx.Send("URL非法!")
|
||||
} else {
|
||||
RANDOM_API_URL = url
|
||||
}
|
||||
return
|
||||
})
|
||||
// 有保护的随机图片
|
||||
zero.OnFullMatch("随机图片").SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
Classify(ctx, RANDOM_API_URL, false)
|
||||
}
|
||||
return
|
||||
})
|
||||
// 直接随机图片,危险,仅管理员可用
|
||||
zero.OnFullMatch("直接随机", zero.AdminPermission).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
if BLOCK_REQUEST {
|
||||
ctx.Send("请稍后再试哦")
|
||||
} else {
|
||||
BLOCK_REQUEST = true
|
||||
last_message_id := ctx.SendChain(message.Image(RANDOM_API_URL).Add("no_cache", "0"))
|
||||
last_group_id := ctx.Event.GroupID
|
||||
MsgofGrp[last_group_id] = last_message_id
|
||||
BLOCK_REQUEST = false
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
// 撤回最后的随机图片
|
||||
zero.OnFullMatch("不许好").SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
Vote(ctx, 5)
|
||||
})
|
||||
// 撤回最后的随机图片
|
||||
zero.OnFullMatch("太涩了").SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
Vote(ctx, 6)
|
||||
})
|
||||
// 上传一张图进行评价
|
||||
zero.OnFullMatch("评价图片", MustHasPicture()).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
ctx.Send("少女祈祷中......")
|
||||
for _, pic := range ctx.State["image_url"].([]string) {
|
||||
fmt.Println(pic)
|
||||
Classify(ctx, pic, true)
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
}
|
||||
@@ -1,140 +1,146 @@
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/setutime/utils"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
)
|
||||
|
||||
var limit = rate.NewManager(time.Minute*1, 5)
|
||||
// Pools 图片缓冲池
|
||||
type Pool struct {
|
||||
Lock sync.Mutex
|
||||
DB *Sqlite
|
||||
Path string
|
||||
Group int64
|
||||
List []string
|
||||
Max int
|
||||
Pool map[string][]*pixiv.Illust
|
||||
Form int64
|
||||
}
|
||||
|
||||
var (
|
||||
BOTPATH = utils.PathExecute() // 当前bot运行目录
|
||||
DATAPATH = BOTPATH + "data/SetuTime/" // 数据目录
|
||||
DBPATH = DATAPATH + "SetuTime.db" // 数据库路径
|
||||
|
||||
CACHEPATH = DATAPATH + "cache/" // 缓冲图片路径
|
||||
CACHEGROUP int64 = 868047498 // 缓冲图片群,不修改无法缓存
|
||||
PoolList = []string{"涩图", "二次元", "风景", "车万"} // 可自定义
|
||||
|
||||
DB = utils.Sqlite{DBPath: DBPATH} // 新建涩图数据库对象
|
||||
PoolsCache = utils.NewPoolsCache() // 新建一个缓冲池对象
|
||||
|
||||
FORM = "PIC" // 默认 PIC 格式
|
||||
)
|
||||
|
||||
func init() {
|
||||
PoolsCache.Group = CACHEGROUP // 图片缓冲群
|
||||
PoolsCache.Path = CACHEPATH // 缓冲图片路径
|
||||
|
||||
utils.CreatePath(DBPATH)
|
||||
utils.CreatePath(CACHEPATH)
|
||||
|
||||
for i := range PoolList {
|
||||
if err := DB.Create(PoolList[i], &utils.Illust{}); err != nil {
|
||||
// NewPoolsCache 返回一个缓冲池对象
|
||||
func NewPools() *Pool {
|
||||
cache := &Pool{
|
||||
DB: &Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
|
||||
Path: "data/SetuTime/cache/",
|
||||
Group: 0,
|
||||
List: []string{"涩图", "二次元", "风景", "车万"}, // 可以自己加类别,得自己加图片进数据库
|
||||
Max: 10,
|
||||
Pool: map[string][]*pixiv.Illust{},
|
||||
Form: 0,
|
||||
}
|
||||
err := os.MkdirAll(cache.Path, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i := range cache.List {
|
||||
if err := cache.DB.Create(cache.List[i], &pixiv.Illust{}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return cache
|
||||
}
|
||||
|
||||
var (
|
||||
POOL = NewPools()
|
||||
limit = rate.NewManager(time.Minute*1, 5)
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
zero.OnRegex(`^来份(.*)$`, FirstValueInList(PoolList)).SetBlock(true).SetPriority(20).
|
||||
zero.OnRegex(`^来份(.*)$`, FirstValueInList(POOL.List)).SetBlock(true).SetPriority(20).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
return
|
||||
}
|
||||
var type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
// 补充池子
|
||||
go func() {
|
||||
times := utils.Min(PoolsCache.Max-PoolsCache.Size(type_), 2)
|
||||
times := Min(POOL.Max-POOL.Size(type_), 2)
|
||||
for i := 0; i < times; i++ {
|
||||
illust := &utils.Illust{}
|
||||
illust := &pixiv.Illust{}
|
||||
// 查询出一张图片
|
||||
if err := DB.Select(type_, illust, "ORDER BY RANDOM() limit 1"); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
if err := POOL.DB.Select(type_, illust, "ORDER BY RANDOM() limit 1"); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
}
|
||||
ctx.SendGroupMessage(PoolsCache.Group, "正在下载"+illust.ImageUrls)
|
||||
file, err := illust.PixivPicDown(PoolsCache.Path)
|
||||
if err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
continue
|
||||
}
|
||||
if id := ctx.SendGroupMessage(PoolsCache.Group, illust.NormalPic(file)); id == 0 {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", "发送到缓存群失败,请确认缓存群群号"))
|
||||
// 下载图片
|
||||
if _, err := download(illust, POOL.Path); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
}
|
||||
ctx.SendGroupMessage(POOL.Group, []message.MessageSegment{message.Image(file(illust))})
|
||||
// 向缓冲池添加一张图片
|
||||
if err := PoolsCache.Push(type_, illust); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
continue
|
||||
}
|
||||
POOL.Push(type_, illust)
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
}()
|
||||
// 如果没有缓存,阻塞5秒
|
||||
if PoolsCache.Size(type_) == 0 {
|
||||
ctx.Send("[SetuTime] 正在填充弹药......")
|
||||
if POOL.Size(type_) == 0 {
|
||||
ctx.SendChain(message.Text("INFO: 正在填充弹药......"))
|
||||
<-time.After(time.Second * 5)
|
||||
if PoolsCache.Size(type_) == 0 {
|
||||
ctx.Send("[SetuTime] 等待填充,请稍后再试......")
|
||||
if POOL.Size(type_) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
|
||||
return
|
||||
}
|
||||
}
|
||||
// 从缓冲池里抽一张
|
||||
if id := ctx.Send(PoolsCache.GetOnePic(type_, FORM)); id == 0 {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", errors.New("可能被风控了")))
|
||||
if id := ctx.SendChain(message.Image(file(POOL.Pop(type_)))); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
zero.OnRegex(`^添加(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
|
||||
zero.OnRegex(`^添加(.*?)(\d+)$`, FirstValueInList(POOL.List), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var (
|
||||
type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
id = utils.Str2Int(ctx.State["regex_matched"].([]string)[2])
|
||||
illust = &utils.Illust{}
|
||||
type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
|
||||
)
|
||||
ctx.Send("少女祈祷中......")
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
// 查询P站插图信息
|
||||
|
||||
if err := illust.IllustInfo(id); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
illust, err := pixiv.Works(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 下载插画
|
||||
if _, err := illust.PixivPicDown(PoolsCache.Path); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
if _, err := download(illust, POOL.Path); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
file := fmt.Sprintf("%s%d.jpg", PoolsCache.Path, illust.Pid)
|
||||
if id := ctx.Send(illust.DetailPic(file)); id == 0 {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", "可能被风控,发送失败"))
|
||||
// 发送到发送者
|
||||
if id := ctx.SendChain(message.Image(file(illust))); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控,发送失败"))
|
||||
return
|
||||
}
|
||||
// 添加插画到对应的数据库table
|
||||
if err := DB.Insert(type_, illust); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
if err := POOL.DB.Insert(type_, illust); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send("添加成功")
|
||||
return
|
||||
})
|
||||
|
||||
zero.OnRegex(`^删除(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
|
||||
zero.OnRegex(`^删除(.*?)(\d+)$`, FirstValueInList(POOL.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var (
|
||||
type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
id = utils.Str2Int(ctx.State["regex_matched"].([]string)[2])
|
||||
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
|
||||
)
|
||||
// 查询数据库
|
||||
if err := DB.Delete(type_, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
|
||||
if err := POOL.DB.Delete(type_, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
return
|
||||
}
|
||||
@@ -143,36 +149,22 @@ func init() { // 插件主体
|
||||
})
|
||||
|
||||
// 查询数据库涩图数量
|
||||
zero.OnFullMatchGroup([]string{"setu -s", "setu --status"}).SetBlock(true).SetPriority(23).
|
||||
zero.OnFullMatchGroup([]string{">setu status"}).SetBlock(true).SetPriority(23).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
state := []string{"[SetuTime]"}
|
||||
for i := range PoolList {
|
||||
num, err := DB.Num(PoolList[i])
|
||||
for i := range POOL.List {
|
||||
num, err := POOL.DB.Num(POOL.List[i])
|
||||
if err != nil {
|
||||
num = 0
|
||||
}
|
||||
state = append(state, "\n")
|
||||
state = append(state, PoolList[i])
|
||||
state = append(state, POOL.List[i])
|
||||
state = append(state, ": ")
|
||||
state = append(state, fmt.Sprintf("%d", num))
|
||||
}
|
||||
ctx.Send(strings.Join(state, ""))
|
||||
return
|
||||
})
|
||||
// 开xml模式
|
||||
zero.OnFullMatchGroup([]string{"setu -x", "setu --xml"}).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
FORM = "XML"
|
||||
ctx.Send("[SetuTime] XML->ON")
|
||||
return
|
||||
})
|
||||
// 关xml模式
|
||||
zero.OnFullMatchGroup([]string{"setu -p", "setu --pic"}).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
FORM = "PIC"
|
||||
ctx.Send("[SetuTime] XML->OFF")
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// FirstValueInList 判断正则匹配的第一个参数是否在列表中
|
||||
@@ -187,3 +179,81 @@ func FirstValueInList(list []string) zero.Rule {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Min 返回两数最小值
|
||||
func Min(a, b int) int {
|
||||
switch {
|
||||
default:
|
||||
return a
|
||||
case a > b:
|
||||
return b
|
||||
case a < b:
|
||||
return a
|
||||
}
|
||||
}
|
||||
|
||||
// Size 返回缓冲池指定类型的现有大小
|
||||
func (p *Pool) Size(type_ string) int {
|
||||
return len(p.Pool[type_])
|
||||
}
|
||||
|
||||
// IsFull 返回缓冲池指定类型是否已满
|
||||
func (p *Pool) IsFull(type_ string) bool {
|
||||
return len(p.Pool[type_]) >= p.Max
|
||||
}
|
||||
|
||||
// Push 向缓冲池插入一张图片
|
||||
func (p *Pool) Push(type_ string, illust *pixiv.Illust) {
|
||||
p.Lock.Lock()
|
||||
defer p.Lock.Unlock()
|
||||
p.Pool[type_] = append(p.Pool[type_], illust)
|
||||
}
|
||||
|
||||
// Push 在缓冲池拿出一张图片
|
||||
func (p *Pool) Pop(type_ string) (illust *pixiv.Illust) {
|
||||
p.Lock.Lock()
|
||||
defer p.Lock.Unlock()
|
||||
if p.Size(type_) == 0 {
|
||||
return
|
||||
}
|
||||
illust = p.Pool[type_][0]
|
||||
p.Pool[type_] = p.Pool[type_][1:]
|
||||
return
|
||||
}
|
||||
|
||||
func file(i *pixiv.Illust) string {
|
||||
filename := fmt.Sprint(i.Pid)
|
||||
pwd, _ := os.Getwd()
|
||||
filepath := pwd + `/` + POOL.Path + filename
|
||||
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
|
||||
return `file:///` + filepath + ".jpg"
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".png"); err == nil || os.IsExist(err) {
|
||||
return `file:///` + filepath + ".png"
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".gif"); err == nil || os.IsExist(err) {
|
||||
return `file:///` + filepath + ".gif"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func download(i *pixiv.Illust, filedir string) (string, error) {
|
||||
filename := fmt.Sprint(i.Pid)
|
||||
filepath := filedir + filename
|
||||
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
|
||||
return filepath + ".jpg", nil
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".png"); err == nil || os.IsExist(err) {
|
||||
return filepath + ".png", nil
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".gif"); err == nil || os.IsExist(err) {
|
||||
return filepath + ".gif", nil
|
||||
}
|
||||
// 下载最大分辨率为 1200 的图片
|
||||
link := i.ImageUrls
|
||||
link = strings.ReplaceAll(link, "img-original", "img-master")
|
||||
link = strings.ReplaceAll(link, "_p0", "_p0_master1200")
|
||||
link = strings.ReplaceAll(link, ".png", ".jpg")
|
||||
// 下载
|
||||
return pixiv.Download(link, filedir, filename)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
// Sqlite 数据库对象
|
||||
@@ -20,7 +20,7 @@ type Sqlite struct {
|
||||
// 返回错误
|
||||
func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
|
||||
if db.DB == nil {
|
||||
database, err := sql.Open("sqlite3", db.DBPath)
|
||||
database, err := sql.Open("sqlite", db.DBPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -62,8 +62,8 @@ func (db *Sqlite) Insert(table string, objptr interface{}) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
tags, _ := rows.Columns()
|
||||
rows.Close()
|
||||
var (
|
||||
values = values(objptr)
|
||||
top = len(tags) - 1
|
||||
@@ -1,100 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
xpath "github.com/antchfx/htmlquery"
|
||||
)
|
||||
|
||||
// Ascii2dSearch Ascii2d 以图搜图
|
||||
// 第一个参数 返回错误
|
||||
// 第二个参数 返回的信息
|
||||
func Ascii2dSearch(pic string) (text string, err error) {
|
||||
var (
|
||||
api = "https://ascii2d.net/search/uri"
|
||||
)
|
||||
transport := http.Transport{
|
||||
DisableKeepAlives: true,
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
|
||||
// 包装请求参数
|
||||
data := url.Values{}
|
||||
data.Set("uri", pic) // 图片链接
|
||||
fromData := strings.NewReader(data.Encode())
|
||||
|
||||
// 网络请求
|
||||
req, _ := http.NewRequest("POST", api, fromData)
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 色合检索改变到特征检索
|
||||
var bovwUrl = strings.ReplaceAll(resp.Request.URL.String(), "color", "bovw")
|
||||
bovwReq, _ := http.NewRequest("POST", bovwUrl, nil)
|
||||
bovwReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
bovwReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36")
|
||||
bovwResp, err := client.Do(bovwReq)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer bovwResp.Body.Close()
|
||||
// 解析XPATH
|
||||
doc, err := xpath.Parse(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 取出每个返回的结果
|
||||
list := xpath.Find(doc, `//div[@class="row item-box"]`)
|
||||
var link string
|
||||
// 遍历取出第一个返回的PIXIV结果
|
||||
for _, n := range list {
|
||||
linkPath := xpath.Find(n, `//div[2]/div[3]/h6/a[1]`)
|
||||
picPath := xpath.Find(n, `//div[1]/img`)
|
||||
if len(linkPath) != 0 && len(picPath) != 0 {
|
||||
link = xpath.SelectAttr(linkPath[0], "href")
|
||||
if strings.Contains(link, "www.pixiv.net") {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 链接取出PIXIV id
|
||||
var index = strings.LastIndex(link, "/")
|
||||
if link == "" || index == -1 {
|
||||
return "", errors.New("Ascii2d not found")
|
||||
}
|
||||
var id = Str2Int(link[index+1:])
|
||||
if id == 0 {
|
||||
return "", errors.New("convert to pid error")
|
||||
}
|
||||
// 根据PID查询插图信息
|
||||
var illust = &Illust{}
|
||||
if err := illust.IllustInfo(id); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if illust.AgeLimit != "all-age" {
|
||||
return "", errors.New("Ascii2d not found")
|
||||
}
|
||||
// 返回插图信息文本
|
||||
return fmt.Sprintf(
|
||||
`[SetuTime] emmm大概是这个?
|
||||
标题:%s
|
||||
插画ID:%d
|
||||
画师:%s
|
||||
画师ID:%d
|
||||
直链:https://pixivel.moe/detail?id=%d`,
|
||||
illust.Title,
|
||||
illust.Pid,
|
||||
illust.UserName,
|
||||
illust.UserId,
|
||||
illust.Pid,
|
||||
), nil
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// urlCache 缓存并返回缓存路径
|
||||
func (this *Illust) PixivPicDown(path string) (savePath string, err error) {
|
||||
url := this.ImageUrls
|
||||
pid := this.Pid
|
||||
url = strings.ReplaceAll(url, "img-original", "img-master")
|
||||
url = strings.ReplaceAll(url, "_p0", "_p0_master1200")
|
||||
url = strings.ReplaceAll(url, ".png", ".jpg")
|
||||
// 文件名为url的hash值
|
||||
savePath = path + Int2Str(pid) + ".jpg"
|
||||
// 文件存在或文件大小大于10kb
|
||||
if PathExists(savePath) && FileSize(savePath) > 10240 {
|
||||
return savePath, nil
|
||||
}
|
||||
|
||||
// 模拟QQ客户端请求
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DisableKeepAlives: true,
|
||||
// 绕过sni审查
|
||||
TLSClientConfig: &tls.Config{
|
||||
ServerName: "-",
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
// 更改dns
|
||||
Dial: func(network, addr string) (net.Conn, error) {
|
||||
return net.Dial("tcp", "210.140.92.140:443")
|
||||
},
|
||||
},
|
||||
}
|
||||
reqest, _ := http.NewRequest("GET", url, nil)
|
||||
reqest.Header.Set("Referer", "https://www.pixiv.net/")
|
||||
reqest.Header.Set("Host", "i.pximg.net")
|
||||
reqest.Header.Set("User-Agent", "QQ/8.2.0.1296 CFNetwork/1126")
|
||||
|
||||
resp, err := client.Do(reqest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Println(resp.StatusCode)
|
||||
if code := resp.StatusCode; code != 200 {
|
||||
return "", errors.New(fmt.Sprintf("Download failed, code %d", code))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// 写入文件
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
f, _ := os.OpenFile(savePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
defer f.Close()
|
||||
f.Write(data)
|
||||
|
||||
return savePath, err
|
||||
}
|
||||
|
||||
// PicHash 返回图片的 md5 值
|
||||
func PicHash(path string) string {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.ToUpper(fmt.Sprintf("%x", md5.Sum(data)))
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// PoolsCache 图片缓冲池
|
||||
type PoolsCache struct {
|
||||
Lock sync.Mutex
|
||||
Max int
|
||||
Path string
|
||||
Group int64
|
||||
Pool map[string][]*Illust
|
||||
}
|
||||
|
||||
// NewPoolsCache 返回一个缓冲池对象
|
||||
func NewPoolsCache() *PoolsCache {
|
||||
return &PoolsCache{
|
||||
Max: 10,
|
||||
Path: "./data/SetuTime/cache/",
|
||||
Group: 1048452984,
|
||||
Pool: map[string][]*Illust{},
|
||||
}
|
||||
}
|
||||
|
||||
// Size 返回缓冲池指定类型的现有大小
|
||||
func (p *PoolsCache) Size(type_ string) int {
|
||||
return len(p.Pool[type_])
|
||||
}
|
||||
|
||||
// IsFull 返回缓冲池指定类型是否已满
|
||||
func (p *PoolsCache) IsFull(type_ string) bool {
|
||||
return len(p.Pool[type_]) >= p.Max
|
||||
}
|
||||
|
||||
// Push 向缓冲池插入一张图片,返回错误
|
||||
func (p *PoolsCache) Push(type_ string, illust *Illust) (err error) {
|
||||
p.Lock.Lock()
|
||||
defer p.Lock.Unlock()
|
||||
p.Pool[type_] = append(p.Pool[type_], illust)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Push 在缓冲池拿出一张图片,返回错误
|
||||
func (p *PoolsCache) Pop(type_ string) (illust *Illust) {
|
||||
p.Lock.Lock()
|
||||
defer p.Lock.Unlock()
|
||||
if p.Size(type_) == 0 {
|
||||
return
|
||||
}
|
||||
illust = p.Pool[type_][0]
|
||||
p.Pool[type_] = p.Pool[type_][1:]
|
||||
return
|
||||
}
|
||||
|
||||
// Push 在缓冲池拿出一张图片,返回指定格式CQ码
|
||||
func (p *PoolsCache) GetOnePic(type_ string, form string) string {
|
||||
var (
|
||||
illust = p.Pop(type_)
|
||||
file = fmt.Sprintf("%s%d.jpg", p.Path, illust.Pid)
|
||||
)
|
||||
switch form {
|
||||
case "XML":
|
||||
return illust.BigPic(file)
|
||||
case "DETAIL":
|
||||
return illust.DetailPic(file)
|
||||
default:
|
||||
return illust.NormalPic(file)
|
||||
}
|
||||
}
|
||||
|
||||
// BigPic 返回一张XML大图CQ码
|
||||
func (i *Illust) BigPic(file string) string {
|
||||
var hash = PicHash(file)
|
||||
return fmt.Sprintf(`[CQ:xml,data=<?xml version='1.0'
|
||||
encoding='UTF-8' standalone='yes' ?><msg serviceID="5"
|
||||
templateID="12345" action="" brief="不够涩!"
|
||||
sourceMsgId="0" url="" flag="0" adverSign="0" multiMsgFlag="0">
|
||||
<item layout="0" advertiser_id="0" aid="0"><image uuid="%s.jpg" md5="%s"
|
||||
GroupFiledid="2235033681" filesize="81322" local_path="%s.jpg"
|
||||
minWidth="200" minHeight="200" maxWidth="500" maxHeight="1000" />
|
||||
</item><source name="%s⭐(id:%d author:%s)" icon=""
|
||||
action="" appid="-1" /></msg>]`,
|
||||
hash,
|
||||
hash,
|
||||
hash,
|
||||
i.Title,
|
||||
i.Pid,
|
||||
i.UserName,
|
||||
)
|
||||
}
|
||||
|
||||
// NormalPic 返回一张普通图CQ码
|
||||
func (i *Illust) NormalPic(file string) string {
|
||||
return fmt.Sprintf(`[CQ:image,file=file:///%s]`, file)
|
||||
}
|
||||
|
||||
// DetailPic 返回一张带详细信息的图片CQ码
|
||||
func (i *Illust) DetailPic(file string) string {
|
||||
return fmt.Sprintf(`[SetuTime] %s 标题:%s
|
||||
插画ID:%d
|
||||
画师:%s
|
||||
画师ID:%d
|
||||
直链:https://pixivel.moe/detail?id=%d`,
|
||||
i.NormalPic(file),
|
||||
i.Title,
|
||||
i.Pid,
|
||||
i.UserName,
|
||||
i.UserId,
|
||||
i.Pid,
|
||||
)
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// Illust 插画信息
|
||||
type Illust struct {
|
||||
Pid int64 `db:"pid"`
|
||||
Title string `db:"title"`
|
||||
Caption string `db:"caption"`
|
||||
Tags string `db:"tags"`
|
||||
ImageUrls string `db:"image_urls"`
|
||||
AgeLimit string `db:"age_limit"`
|
||||
CreatedTime string `db:"created_time"`
|
||||
UserId int64 `db:"user_id"`
|
||||
UserName string `db:"user_name"`
|
||||
}
|
||||
|
||||
// IllustInfo 根据p站插画id返回插画信息Illust
|
||||
func (this *Illust) IllustInfo(id int64) (err error) {
|
||||
api := fmt.Sprintf("https://pixiv.net/ajax/illust/%d", id)
|
||||
transport := http.Transport{
|
||||
DisableKeepAlives: true,
|
||||
// 绕过sni审查
|
||||
TLSClientConfig: &tls.Config{
|
||||
ServerName: "-",
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
// 更改dns
|
||||
Dial: func(network, addr string) (net.Conn, error) {
|
||||
return net.Dial("tcp", "210.140.131.223:443")
|
||||
},
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
|
||||
// 网络请求
|
||||
req, err := http.NewRequest("GET", api, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Host", "pixiv.net")
|
||||
req.Header.Set("Referer", "pixiv.net")
|
||||
req.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if code := resp.StatusCode; code != 200 {
|
||||
return errors.New(fmt.Sprintf("Search illust's info failed, status %d", code))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
json := gjson.ParseBytes(body).Get("body")
|
||||
|
||||
// 如果有"R-18"tag则判断为R-18(暂时)
|
||||
var ageLimit = "all-age"
|
||||
for _, tag := range json.Get("tags.tags.#.tag").Array() {
|
||||
if tag.Str == "R-18" {
|
||||
ageLimit = "r18"
|
||||
break
|
||||
}
|
||||
}
|
||||
// 解决json返回带html格式
|
||||
var caption = strings.ReplaceAll(json.Get("illustComment").Str, "<br />", "\n")
|
||||
if index := strings.Index(caption, "<"); index != -1 {
|
||||
caption = caption[:index]
|
||||
}
|
||||
// 解析返回插画信息
|
||||
this.Pid = json.Get("illustId").Int()
|
||||
this.Title = json.Get("illustTitle").Str
|
||||
this.Caption = caption
|
||||
this.Tags = fmt.Sprintln(json.Get("tags.tags.#.tag").Array())
|
||||
this.ImageUrls = json.Get("urls.original").Str
|
||||
this.AgeLimit = ageLimit
|
||||
this.CreatedTime = json.Get("createDate").Str
|
||||
this.UserId = json.Get("userId").Int()
|
||||
this.UserName = json.Get("userName").Str
|
||||
return nil
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// SauceNaoSearch SauceNao 以图搜图 需要链接 返回错误和信息
|
||||
func SauceNaoSearch(pic string) (text string, err error) {
|
||||
var (
|
||||
api = "https://saucenao.com/search.php"
|
||||
apiKey = "2cc2772ca550dbacb4c35731a79d341d1a143cb5"
|
||||
|
||||
minSimilarity = 70.0 // 返回图片结果的最小相似度
|
||||
)
|
||||
|
||||
transport := http.Transport{
|
||||
DisableKeepAlives: true,
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
|
||||
// 包装请求参数
|
||||
data := url.Values{}
|
||||
data.Set("url", pic) // 图片链接
|
||||
data.Set("api_key", apiKey) // api_key
|
||||
data.Set("db", "5") // 只搜索Pixiv
|
||||
data.Set("numres", "1") // 返回一个结果
|
||||
data.Set("output_type", "2") // 返回JSON格式数据
|
||||
fromData := strings.NewReader(data.Encode())
|
||||
|
||||
// 网络请求
|
||||
req, err := http.NewRequest("POST", api, fromData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if code := resp.StatusCode; code != 200 {
|
||||
// 如果返回不是200则立刻抛出错误
|
||||
return "", errors.New(fmt.Sprintf("SauceNAO not found, code %d", code))
|
||||
}
|
||||
content := gjson.ParseBytes(body)
|
||||
if status := content.Get("header.status").Int(); status != 0 {
|
||||
// 如果json信息返回status不为0则立刻抛出错误
|
||||
return "", errors.New(fmt.Sprintf("SauceNAO not found, status %d", status))
|
||||
}
|
||||
if content.Get("results.0.header.similarity").Float() < minSimilarity {
|
||||
return "", errors.New("SauceNAO not found")
|
||||
}
|
||||
// 正常发送
|
||||
return fmt.Sprintf(
|
||||
`[SetuTime] 我有把握是这个![CQ:image,file=%s]相似度:%s%%
|
||||
标题:%s
|
||||
插画ID:%d
|
||||
画师:%s
|
||||
画师ID:%d
|
||||
直链:https://pixivel.moe/detail?id=%d`,
|
||||
content.Get("results.0.header.thumbnail").Str,
|
||||
content.Get("results.0.header.similarity").Str,
|
||||
content.Get("results.0.data.title").Str,
|
||||
content.Get("results.0.data.pixiv_id").Int(),
|
||||
content.Get("results.0.data.member_name").Str,
|
||||
content.Get("results.0.data.member_id").Int(),
|
||||
content.Get("results.0.data.pixiv_id").Int(),
|
||||
), nil
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package utils
|
||||
|
||||
var (
|
||||
XML = true // 图片XML开关,默认开启
|
||||
)
|
||||
@@ -1,73 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Str2Int string --> int64
|
||||
func Str2Int(str string) int64 {
|
||||
val, _ := strconv.Atoi(str)
|
||||
return int64(val)
|
||||
}
|
||||
|
||||
// Int2Str int64 --> string
|
||||
func Int2Str(val int64) string {
|
||||
str := strconv.FormatInt(val, 10)
|
||||
return str
|
||||
}
|
||||
|
||||
// PathExecute 返回当前运行目录
|
||||
func PathExecute() string {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return dir + "/"
|
||||
}
|
||||
|
||||
// CreatePath 生成路径或文件所对应的目录
|
||||
func CreatePath(path string) {
|
||||
length := len(path)
|
||||
switch {
|
||||
case path[length:] != "/":
|
||||
path = path[:strings.LastIndex(path, "/")]
|
||||
case path[length:] != "\\":
|
||||
path = path[:strings.LastIndex(path, "\\")]
|
||||
default:
|
||||
//
|
||||
}
|
||||
if !PathExists(path) {
|
||||
err := os.MkdirAll(path, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PathExists 判断路径或文件是否存在
|
||||
func PathExists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
// FileSize 获取文件大小
|
||||
func FileSize(file string) int64 {
|
||||
if fi, err := os.Stat(file); err == nil {
|
||||
return fi.Size()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Min 返回两数最小值
|
||||
func Min(a, b int) int {
|
||||
switch {
|
||||
default:
|
||||
return a
|
||||
case a > b:
|
||||
return b
|
||||
case a < b:
|
||||
return a
|
||||
}
|
||||
}
|
||||
56
shindan/shindan.go
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
基于 https://shindanmaker.com 的测定小功能
|
||||
*/
|
||||
package shindan
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/shindanmaker"
|
||||
)
|
||||
|
||||
var (
|
||||
// 限制调用频率
|
||||
limit = rate.NewManager(time.Minute*5, 5)
|
||||
)
|
||||
|
||||
func init() {
|
||||
zero.OnPrefix("异世界转生", number(587874)).SetBlock(true).FirstPriority().Handle(handle)
|
||||
zero.OnPrefix("今天是什么少女", number(162207)).SetBlock(true).FirstPriority().Handle(handle)
|
||||
zero.OnPrefix("卖萌", number(360578)).SetBlock(true).FirstPriority().Handle(handle)
|
||||
}
|
||||
|
||||
// shindanmaker 处理函数
|
||||
var handle = func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
return
|
||||
}
|
||||
// 获取名字
|
||||
name := ctx.State["args"].(string)
|
||||
if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
|
||||
qq, _ := strconv.ParseInt(ctx.Event.Message[1].Data["qq"], 10, 64)
|
||||
name = ctx.GetGroupMemberInfo(ctx.Event.GroupID, qq, false).Get("nickname").Str
|
||||
} else if name == "" {
|
||||
name = ctx.Event.Sender.NickName
|
||||
}
|
||||
// 调用接口
|
||||
text, err := shindanmaker.Shindanmaker(ctx.State["id"].(int64), name)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
ctx.SendChain(message.Text(text))
|
||||
}
|
||||
|
||||
// 传入 shindanmaker id
|
||||
var number = func(id int64) func(ctx *zero.Ctx) bool {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
ctx.State["id"] = id
|
||||
return true
|
||||
}
|
||||
}
|
||||