Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb6549c297 | ||
|
|
29816ada2a | ||
|
|
dd12bdc028 | ||
|
|
2a52c0711b | ||
|
|
2653f67193 | ||
|
|
b892617824 | ||
|
|
a6fb05c91d | ||
|
|
ccfb9403c8 | ||
|
|
66fa194c7f | ||
|
|
65d8fae9ca | ||
|
|
58acb14859 | ||
|
|
b63c05a509 | ||
|
|
2a1a2ee8c5 | ||
|
|
8c4b515093 | ||
|
|
6d43989a4d | ||
|
|
fb1f15bcb4 | ||
|
|
81ad585a18 | ||
|
|
eb3bd2b4a6 | ||
|
|
e401914790 | ||
|
|
fef5dadaba | ||
|
|
c1348d08ed | ||
|
|
fbd7c568d9 | ||
|
|
2941774913 | ||
|
|
b96d910401 | ||
|
|
9275d0782b | ||
|
|
7acc6cf6af | ||
|
|
d380a9aacc | ||
|
|
495377da13 | ||
|
|
218eed4068 | ||
|
|
1e9c99dec1 | ||
|
|
0326bc2831 | ||
|
|
aed770a761 | ||
|
|
3de487fb24 | ||
|
|
c802dfda22 | ||
|
|
3a4378e4c6 | ||
|
|
955a1f8a7f | ||
|
|
ab69e5c477 | ||
|
|
55e42e8334 | ||
|
|
a0f59bc2c2 | ||
|
|
66dabd0c8a | ||
|
|
915d585e3a | ||
|
|
979080d281 | ||
|
|
335f76c532 | ||
|
|
b50b934a12 | ||
|
|
6a1684d277 | ||
|
|
4926e4d69c | ||
|
|
b29a26551a | ||
|
|
d1c1d93ab7 | ||
|
|
907df4253c | ||
|
|
658152fdc9 | ||
|
|
1a68ede632 | ||
|
|
b70851b810 | ||
|
|
17506691a8 | ||
|
|
37a651da4e | ||
|
|
c535a32230 | ||
|
|
bb54781209 | ||
|
|
dcb538a3a9 | ||
|
|
185f7d9c31 | ||
|
|
c802c4413a | ||
|
|
19d650c35d | ||
|
|
21c1950898 | ||
|
|
661e1d77b9 | ||
|
|
dae0450a52 | ||
|
|
ce5cfc818c | ||
|
|
dec199f32d | ||
|
|
a87a50a89b | ||
|
|
c253b43a70 | ||
|
|
4ce4e4c44c | ||
|
|
3319fa72e4 | ||
|
|
1033d585c7 | ||
|
|
6014c3f975 | ||
|
|
d9ca42226a | ||
|
|
71026542df | ||
|
|
e756a50d97 | ||
|
|
49c47c01a3 | ||
|
|
e7eea2a7d9 | ||
|
|
311ae7d4e8 | ||
|
|
058f0885f7 | ||
|
|
c6eaf435f2 | ||
|
|
22676f3bfa | ||
|
|
fedcb37b1a | ||
|
|
54025c9cfc | ||
|
|
2cdf3c28b6 | ||
|
|
ba29232c9f | ||
|
|
5fd0667061 | ||
|
|
2c9f99ac3c | ||
|
|
775b1b937b | ||
|
|
65723aee15 | ||
|
|
46b55e4224 | ||
|
|
918adc4b1c | ||
|
|
e99341c6aa | ||
|
|
4b0d2a104b | ||
|
|
eb9bb1b173 | ||
|
|
f2b4204a23 | ||
|
|
b63aa952c4 | ||
|
|
7a5767717f | ||
|
|
22af4f2b27 | ||
|
|
00658cf165 | ||
|
|
87ed445a58 | ||
|
|
36ea174804 | ||
|
|
6ba2fedba2 | ||
|
|
ca89ff7761 | ||
|
|
f39d53a865 | ||
|
|
6864d54e27 | ||
|
|
bdc084212f | ||
|
|
fc2487df0e | ||
|
|
264a827a2c | ||
|
|
401886805b | ||
|
|
efcdf79f57 | ||
|
|
616f215075 | ||
|
|
00b674cebb | ||
|
|
8ac440335e | ||
|
|
4b1821ce42 | ||
|
|
3ad955abf9 | ||
|
|
5fabb974ce | ||
|
|
5325bc3e32 | ||
|
|
6688c4626b | ||
|
|
2b95ab3d7e | ||
|
|
23e6d7e27e | ||
|
|
2760e22336 | ||
|
|
d026d09f98 | ||
|
|
e6fd1ce791 | ||
|
|
342eaa9a97 | ||
|
|
dc7681357e | ||
|
|
b61cb49c1a | ||
|
|
c7b341393d | ||
|
|
1f9fa2adb9 |
@@ -0,0 +1,145 @@
|
|||||||
|
### Python template
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
test.py
|
||||||
|
server.py
|
||||||
|
member_activity_handle.py
|
||||||
|
Yu-Gi-Oh/
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
@@ -7,17 +7,15 @@
|
|||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
software and other kinds of works.
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
The licenses for most software and other practical works are designed
|
||||||
to take away your freedom to share and change the works. By contrast,
|
to take away your freedom to share and change the works. By contrast,
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
share and change all versions of a program--to make sure it remains free
|
share and change all versions of a program--to make sure it remains free
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
software for all its users.
|
||||||
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
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
@@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
|
|||||||
want it, that you can change the software or use pieces of it in new
|
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.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
Developers that use our General Public Licenses protect your rights
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
you this License which gives you legal permission to copy, distribute
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
and/or modify the software.
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
A secondary benefit of defending all users' freedom is that
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
improvements made in alternate versions of the program, if they
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
receive widespread use, become available for other developers to
|
||||||
or can get the source code. And you must show them these terms so they
|
incorporate. Many developers of free software are heartened and
|
||||||
know their rights.
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
The GNU Affero General Public License is designed specifically to
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
ensure that, in such cases, the modified source code becomes available
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
An older license, called the Affero General Public License and
|
||||||
that there is no warranty for this free software. For both users' and
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
changed, so that their problems will not be attributed erroneously to
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
authors of previous versions.
|
this license.
|
||||||
|
|
||||||
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
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
@@ -72,7 +60,7 @@ modification follow.
|
|||||||
|
|
||||||
0. Definitions.
|
0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
works, such as semiconductor masks.
|
works, such as semiconductor masks.
|
||||||
@@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
|
|||||||
the Program, the only way you could satisfy both those terms and this
|
the Program, the only way you could satisfy both those terms and this
|
||||||
License would be to refrain entirely from conveying the Program.
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
permission to link or combine any covered work with a work licensed
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
under version 3 of the GNU General Public License into a single
|
||||||
combined work, and to convey the resulting work. The terms of this
|
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,
|
License will continue to apply to the part which is the covered work,
|
||||||
but the special requirements of the GNU Affero General Public License,
|
but the work with which it is combined will remain governed by version
|
||||||
section 13, concerning interaction through a network will apply to the
|
3 of the GNU General Public License.
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
the GNU General Public License from time to time. Such new versions will
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Program specifies that a certain numbered version of the GNU General
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
Public License "or any later version" applies to it, you have the
|
Public License "or any later version" applies to it, you have the
|
||||||
option of following the terms and conditions either of that numbered
|
option of following the terms and conditions either of that numbered
|
||||||
version or of any later version published by the Free Software
|
version or of any later version published by the Free Software
|
||||||
Foundation. If the Program does not specify a version number of the
|
Foundation. If the Program does not specify a version number of the
|
||||||
GNU General Public License, you may choose any version ever published
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
by the Free Software Foundation.
|
by the Free Software Foundation.
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
If the Program specifies that a proxy can decide which future
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
public statement of acceptance of a version permanently authorizes you
|
public statement of acceptance of a version permanently authorizes you
|
||||||
to choose that version for the Program.
|
to choose that version for the Program.
|
||||||
|
|
||||||
@@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
Copyright (C) <year> <name of author>
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU Affero General Public License as published
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
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.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
If your software can interact with users remotely through a computer
|
||||||
notice like this when it starts in an interactive mode:
|
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
|
||||||
<program> Copyright (C) <year> <name of author>
|
interface could display a "Source" link that leads users to an archive
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
of the code. There are many ways you could offer source, and different
|
||||||
This is free software, and you are welcome to redistribute it
|
solutions will be better for different programs; see section 13 for the
|
||||||
under certain conditions; type `show c' for details.
|
specific requirements.
|
||||||
|
|
||||||
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,
|
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.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
<https://www.gnu.org/licenses/>.
|
<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>.
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div align=center><img width="320" height="320" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs/zhenxun.jpg"/></div>
|
<div align=center><img width="320" height="320" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/logo.png"/></div>
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
@@ -18,9 +18,17 @@
|
|||||||
## 声明
|
## 声明
|
||||||
此项目仅用于学习交流,请勿用于非法用途
|
此项目仅用于学习交流,请勿用于非法用途
|
||||||
|
|
||||||
|
## 未完成的文档
|
||||||
|
|
||||||
|
[传送门](https://hibikier.github.io/zhenxun_bot/)
|
||||||
|
|
||||||
## 真寻的帮助
|
## 真寻的帮助
|
||||||
请对真寻说: '真寻帮助' or '管理员帮助' or '超级用户帮助' or '真寻帮助 指令'
|
请对真寻说: '真寻帮助' or '管理员帮助' or '超级用户帮助' or '真寻帮助 指令'
|
||||||
|
|
||||||
|
## 提供符合真寻标准的插件仓库
|
||||||
|
|
||||||
|
[AkashiCoin/nonebot_plugins_zhenxun_bot](https://github.com/AkashiCoin/nonebot_plugins_zhenxun_bot)
|
||||||
|
|
||||||
|
|
||||||
## 功能列表
|
## 功能列表
|
||||||
<details>
|
<details>
|
||||||
@@ -43,9 +51,11 @@
|
|||||||
- [x] 商店/我的金币/购买道具/使用道具
|
- [x] 商店/我的金币/购买道具/使用道具
|
||||||
- [x] 8种手游抽卡 (查看 [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw))
|
- [x] 8种手游抽卡 (查看 [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw))
|
||||||
- [x] 我有一个朋友想问问..(借鉴pcrbot插件)
|
- [x] 我有一个朋友想问问..(借鉴pcrbot插件)
|
||||||
- [x] 原神黄历 (使用[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
|
- [x] 原神黄历
|
||||||
- [x] 原神今日素材
|
- [x] 原神今日素材
|
||||||
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
|
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
|
||||||
|
- [x] 原神便笺查询
|
||||||
|
- [x] 原神玩家查询
|
||||||
- [x] 金币红包
|
- [x] 金币红包
|
||||||
- [x] 微博热搜
|
- [x] 微博热搜
|
||||||
- [x] B站主播/UP/番剧订阅
|
- [x] B站主播/UP/番剧订阅
|
||||||
@@ -81,6 +91,8 @@
|
|||||||
- [x] 通过PID获取图片
|
- [x] 通过PID获取图片
|
||||||
- [x] 功能统计可视化
|
- [x] 功能统计可视化
|
||||||
|
|
||||||
|
- [x] 关于
|
||||||
|
|
||||||
### 已实现的管理员功能
|
### 已实现的管理员功能
|
||||||
- [x] 更新群组成员信息
|
- [x] 更新群组成员信息
|
||||||
- [x] 95%的群功能开关
|
- [x] 95%的群功能开关
|
||||||
@@ -92,6 +104,8 @@
|
|||||||
- [x] 移动图片 (同上)
|
- [x] 移动图片 (同上)
|
||||||
- [x] 删除图片 (同上)
|
- [x] 删除图片 (同上)
|
||||||
- [x] 群内B站订阅
|
- [x] 群内B站订阅
|
||||||
|
- [x] 群词条
|
||||||
|
- [x] 休息吧/醒来
|
||||||
|
|
||||||
### 已实现的超级用户功能
|
### 已实现的超级用户功能
|
||||||
- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
|
- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
|
||||||
@@ -117,6 +131,11 @@
|
|||||||
- [x] 功能开关(更多设置)
|
- [x] 功能开关(更多设置)
|
||||||
- [x] 功能状态
|
- [x] 功能状态
|
||||||
- [x] b了
|
- [x] b了
|
||||||
|
- [x] 执行sql
|
||||||
|
- [x] 重载配置
|
||||||
|
- [x] 清理临时数据
|
||||||
|
- [x] 增删群认证
|
||||||
|
- [x] 同意/拒绝好友/群聊请求
|
||||||
|
|
||||||
#### 超级用户的被动技能
|
#### 超级用户的被动技能
|
||||||
- [x] 邀请入群提醒(别人邀请真寻入群)
|
- [x] 邀请入群提醒(别人邀请真寻入群)
|
||||||
@@ -143,127 +162,10 @@
|
|||||||
- [x] 定时更新权限
|
- [x] 定时更新权限
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 功能具体指令
|
## 详细配置请前往文档,以下为最简部署和配置,如果你有基础并学习过nonebot2的话
|
||||||
<details>
|
|
||||||
<summary>功能具体指令说明</summary>
|
|
||||||
|
|
||||||
### 常用功能
|
|
||||||
|
|
||||||
** [*]:表示该参数可有多个 [?]:表示参数可选 **
|
|
||||||
|
|
||||||
| 功能 | 指令 | 说明
|
|
||||||
| ----------------------| :--------------------------------------:| :------------------------:
|
|
||||||
| 签到 | 签到/我的签到/好感度排行/好感度总榜/好感度总榜\[显示我/屏蔽我] | 普通的签到插件,可以获得好感度和金币<br>好感度影响开箱次数和涩图触发概率,金币用于购买道具,俄罗斯轮盘赌注以及金币红包<br>好感度总榜,显示所有群的群员好感度排行,可通过命令好感度总榜\[显示我/屏蔽我] 来设置是否隐藏
|
|
||||||
| 发送图片 | 美图/壁纸/萝莉 \[id]?(默认随机)/\[num]张图\[keyword] | 发送指定文件夹下的图片<br>示例:萝莉->发送img文件夹下luoli文件夹下的图片<br>在线搜索一些不色的图,示例:3张图米浴
|
|
||||||
| 色图 | 色图/色图xx/n张色图/n张xx的色图/查色图(查询本地色图信息)/色图r【n<10】 | 色图r返回10张r18色图(仅私聊),并限制每日次数(默认5次)<br>其他示例:色图 真寻 <br>5张真寻的色图
|
|
||||||
| 黑白草图 | 黑白草图/黑白图 \[文字] \[图片] | 整活生成器,示例:黑白图 我喜欢真寻 \[图片]
|
|
||||||
| coser | coser/cos/括丝 | coser图片,说实话挺失望的,太色了
|
|
||||||
| 骂我 | 骂我 | 就是发送钉宫的语音罢了
|
|
||||||
| 戳一戳 | 戳一戳 | 随机发送钉宫语音 or 美图 or 萝莉图 or 文本
|
|
||||||
| 模拟开箱 | 开箱 \[武器箱名称](默认随机)/N连开箱 \[武器箱名称](默认随机)/我的开箱/群开箱统计/我的金色 | 当不指定武器箱时默认随机,此功能需要先在/open_cases/config.py中编写指定武器箱数据,然后提前爬取价格,使用超级用户命令更新cookie后,再使用命令更新xx武器箱【注:未设置爬取频率,可能会被禁用api(请谨慎!!用小号!!)】
|
|
||||||
| 鲁迅说过 | 鲁迅说过 \[文本] | 示例:鲁迅说过 真寻世界第一可爱
|
|
||||||
| 假消息 | 假消息 \[网址] \[标题] \[内容]? \[图片]? | 构造虚假的分享消息
|
|
||||||
| 商店系统 | 商店/我的金币/购买道具 \[名称或序号] \[数量](默认1)/使用道具 \[名称或序号] | 示例:<br>购买道具 1 3<br>购买道具 好感度双倍加持卡Ⅰ 3<br>使用道具 1<br>使用道具 好感度双倍加持卡Ⅰ
|
|
||||||
| 抽卡系统 | 原神/明日方舟/赛马娘/坎公骑冠剑/碧蓝航线/阴阳师/公主连结(pcr)/FGO N抽/一井 | 详细帮助请查看: [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw) <br>示例:原神90抽
|
|
||||||
| 我有一个朋友 | 我有一个朋友他说/想问问/\[文本] | 会将文本中的(他,她,它)替换成 '我'<br>示例:我有一个朋友想问问他喜不喜欢真寻
|
|
||||||
| 昵称系统 | 以后叫我\[昵称]/以后请叫我\[昵称]/我是谁/我叫什么 | 此昵称会替换与真寻聊天中 '你' 的名称(群名片),群与群与私聊的昵称相互独立
|
|
||||||
| 原神黄历 | 原神黄历 | 查看今日原神黄历,含有每日10:25的定时任务
|
|
||||||
| 原神材料 | 今日素材 | 发送可莉特调的截图
|
|
||||||
| 丘丘语翻译 | 丘丘翻译/丘丘一下/丘丘语翻译 | 示例:丘丘一下 mimi
|
|
||||||
| 原神资源查询 | 原神资源查询 \[资源名称] \[路线]?/\[资源名称]在哪/哪里有\[资源名称]/原神资源列表 | 如果资源名称末尾添加‘路线’的话将生成残缺缺缺版的优先路径<br>示例:嘟嘟莲在哪<br>原神资源查询嘟嘟莲路线
|
|
||||||
| 俄罗斯轮盘 | 装弹\[子弹数] \[金额](默认200)/开枪/结算/我的战绩/胜场排行/败场排行/欧洲人排行/慈善家排行 | 紧张刺激的群内小游戏,使用每日签到的金币作为赌注,具体玩法请发送 真寻帮助 俄罗斯轮盘
|
|
||||||
| 红包系统 | 塞红包\[金额] \[数量](默认5)/抢/开/戳一戳/退回 | 仿微信明日方舟红包的样式(pil拼图大师!),每个红包金额随机生成,最多会是红包总金额的1/3,退回用于退回一分钟后还未开完的红包
|
|
||||||
| 金币排行 | 金币排行 | 字面意思
|
|
||||||
|网易云热评 | 到点了/12点了/网易云热评/网易云评论 | 防下塔
|
|
||||||
| 古诗 | 念诗/念首诗/来首诗 | 突然文艺起来了
|
|
||||||
|微博热搜 | 微博热搜/微博热搜[序号]? | 快捷热搜查询方式
|
|
||||||
| pil对图片的操作 | 修改尺寸/等比压缩/旋转图片/水平翻转/铅笔滤镜/模糊效果/锐化效果/高斯模糊/边缘检测/底色替换 | 选项较多,请直接发送 真寻图片帮助
|
|
||||||
| BUFF皮肤底价查询 | 查询皮肤 \[武器名称] \[皮肤名称] | 网络不友好的话会经常超时<br>示例:查询皮肤 沙漠之鹰 印花集
|
|
||||||
| 天气查询 | \[城市]天气 | 非常常见的插件,第一个入门插件
|
|
||||||
| 疫情查询 | 疫情/查询疫情 \[城市名或省份名] | 示例:疫情杭州
|
|
||||||
| bt磁力搜索 | bt \[关键词] \[页数]?(默认第1页) | 该功能仅仅提供给私聊,因为可以搜到一些色色的东西,示例:bt钢铁侠 5
|
|
||||||
| 上车 | 略 | 直接查看真寻帮助 上车,每日限制次数(默认5)
|
|
||||||
| 以图识番 | 识番 \[图片] | 以图搜翻,图片越清晰越完整正确率越高
|
|
||||||
| 以图搜图 | 识图 (asc)? \[图片] | 参数asc更换搜索引擎为ascii2d,默认为saucenao
|
|
||||||
| 点歌 | 点歌 \[歌名] | 网易云点歌小助手
|
|
||||||
| 搜番 | 搜番 \[关键字] | 群聊只返回5个结果,私聊返回20个结果
|
|
||||||
| epic白嫖游戏通知 | epic | 通知你又到了白嫖游戏的时候,可以不玩,不能没有
|
|
||||||
| P站排行榜 | p站排行 \[排行类型参数]? \[数量]? \[日期]?| 9种不同排行榜,r18类型仅可私聊,通过参数选择,查看真寻帮助p站排行<br>示例:p站排行榜 1 9 2018-4-25
|
|
||||||
| 搜图 | 搜图 \[关键词] \[数量]? \[排序方式]? \[r18]?| r18仅可私聊,查看真寻帮助搜图
|
|
||||||
| 通过PID搜索图片 | p搜 [pid] | 在群内使用此功能会在30秒内撤回
|
|
||||||
| 翻译 | 英翻/日翻/韩翻/翻韩/翻日/翻英 \[文本] | 三种语言互相翻译
|
|
||||||
| 获取b站视频封面 | b封面 [链接/av/bv/cv/直播id] | 快捷的封面获取方式
|
|
||||||
| 群欢迎消息 | 群欢迎消息/查看群欢迎消息/查看当前群欢迎消息 | 查看给真寻设置的群欢迎消息
|
|
||||||
| 自我介绍 | 自我介绍 | 没错,一份正经的真寻自我介绍
|
|
||||||
| 我的权限 | 我的权限 | 真寻内部定义的一套权限系统
|
|
||||||
| 我的信息 | 我的信息 | 唯一的作用就是看看什么时候加入群
|
|
||||||
| 撤回 | 撤回 \[消息位置]?(默认为最新一条消息) | 按顺序撤回发送的消息,示例:撤回 1
|
|
||||||
| 滴滴滴- | 滴滴滴- \[文本] | 用于用户联系真寻的超级用户
|
|
||||||
|功能调用统计可视化 | 功能调用统计(自记录以来的功能调用统计)<br>周功能调用统计 [plugin_name]<br>月功能调用统计 [plugin_name]| 当plugin_name为空时为7天或30内的所有功能统计
|
|
||||||
| pix | pix/PIX [tags/uid/pid:pid] [num] | 无参数时随机查看pix图库的图片(无r18),num数量默认=1,tags:查看相关tags图片,uid:查找相关画师图片,pid:pid:指定查看pid图片<br>示例:pix原神 3<br>pix23493844<br>pixpid:29429933
|
|
||||||
| 添加pix关键词/uid/pid | 添加pix关键词/uid/pid *[关键词/uid/pid]| 添加关键词或uid或pid用于下次搜索,关键词搜索相关tag,uid会收录作者下收藏符合标准的作品,pid收录单张作品<br>示例:添加pix关键词 原神<br> 添加pixuid 123441<br>添加pixpid 2748937|
|
|
||||||
| 查看pix图库 | 查看pix图库 [tags] | 查看已收录的tag相关图片数量<br>示例:查看pix图库 原神 莫娜
|
|
||||||
|显示pix关键词 | 显示pix关键词 | 查看已收录的所有关键词/UID/PID
|
|
||||||
| b了 | b了 [at] | 使真寻完全忽略一个用户的所有信息
|
|
||||||
| B站订阅 | 添加订阅 [主播/UP/番剧] [id/链接/番名] / 删除订阅 [id] / 查看订阅 | 可以通过直接间链接或主播间id添加订阅主播开播提醒,动态和投稿,可以通过番名,番剧的id,或者番剧链接添加番剧订阅(是番剧id,md开头,不是集数id,ep开头的)更新, 可以通过UP个人id或UP主页链接订阅UP动态和投稿
|
|
||||||
|
|
||||||
### 管理员功能
|
|
||||||
|
|
||||||
**群主与群管理员默认5级权限**
|
|
||||||
|
|
||||||
| 功能 | 权限等级 | 指令 | 说明
|
|
||||||
| -------------| --------------| :--------------------------------------:| :------------------------:
|
|
||||||
| 更新群组成员信息 | 1 | 更新群组成员信息/更新群组成员列表 | 存储群员的基本信息,虽然有自动更新,但备个命令以防万一
|
|
||||||
| 群功能开关 | 2 | 开启/关闭\[指令名]功能 | 群帮助中左边带有√的功能都可以通过此命令开启或关闭,示例:开启色图
|
|
||||||
| 查看群被动技能 | 2 | 群通知状态 | 详细请查看被动技能列表
|
|
||||||
| 被动技能开关 | 2 | 开启/关闭被动技能 | 有时候花里胡哨通知也会很烦人
|
|
||||||
| 自定义群欢迎消息 | 2 | 自定义群欢迎消息 \[文本] \[图片] | 文本和图片至少需要一个,在文本内添加"\[at]"字符串可以用来设置艾特进群的新群员
|
|
||||||
| 黑名单 | 5 | .ban/.unban \[at] \[小时]? \[分钟]?| 不提供具体时间的话则ban掉永久,且权限低的用户无法unban高权限用户的ban,同级权限也无法进行ban/unban <br>示例:.ban@笨蛋 1 50
|
|
||||||
| 刷屏检测相关 | 5 | 刷屏检测设置/设置检测时间 \[文本]/设置检测次数 \[文本]/设置禁言时长 \[分钟]| 非常讨厌刷屏的人,打算给他们一点教训
|
|
||||||
| 上传图片 | 6 | 上传图片 \[图库] \[图片]... | 上传图片至指定图库,虽然并不打算开放给群员,但还是写了,支持批量图片<br>示例:上传图片 美图 \[图片]..
|
|
||||||
| 删除图片 | 6 | 删除图片 [图库] \[图片id] | 通过指定本地图片id来删除指定图库的图片<br>示例:删除图片 美图 1
|
|
||||||
| 移动图片 | 6 | 移动图片 \[移出的图库] \[移入的图库] \[图片id] | 移动指定图库中的图片到指定的新图库中,移入的图片id更改为移入图库的最后一位,移除的图库中原本图片的id又最后一位图片替代<br>示例:移动图片 美图 萝莉 22
|
|
||||||
|B站订阅 | 5 | 功能同上,就是在群中有权限限制 | 略
|
|
||||||
|
|
||||||
### 超级用户功能
|
|
||||||
|
|
||||||
| 功能 | 指令 | 说明
|
|
||||||
| ----------------------| :--------------------------------------:| :------------------------:
|
|
||||||
| 权限增删 | 添加/删除权限 \[at] \[level]<br>添加/删除权限 [qq] [group] [level] | 用于添加或修改权限等级,且该权限不会被自动更新取消
|
|
||||||
| 所有群组/好友 | 所有群组/好友 | 查看真寻添加的群组与好友
|
|
||||||
| 广播 | 广播- [文本] | 广播所有群组
|
|
||||||
| 更新色图 | 更新色图 | 更新群友搜索色图时保存的url
|
|
||||||
| 回复 | /t | 命令较多,请查看/t帮助,省略群号则私聊用户(必须要有用户的好友)
|
|
||||||
| 更新cookie | 更新cookie \[cookie] | 用于更新开箱数据和查询buff皮肤
|
|
||||||
| 开启广播通知 | 开启/关闭广播通知 \[群号] | 用于开启/关闭是否对某些群进行广播(上边的广播方法)
|
|
||||||
| 退群 | 退群 \[群号] | 用于退出某一些群
|
|
||||||
| 检查系统状态 | 自检 | 略
|
|
||||||
| 更新好友/群组信息| 更新好友/群组信息 | 包含自动更新,被t出群等等有更好的可视信息
|
|
||||||
| 重载卡池 | 略 | 重载抽卡的游戏卡池,请查看 \[nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw)
|
|
||||||
| 添加商品 | 添加商品 \[名称]-\[价格]-\[描述]-\[折扣](小数)?-\[限时时间](分钟)? | 为真寻的商店添加一点点道具<br>示例:添加商品-昏睡红茶-300-一杯上好的奇怪红茶-0.9-60
|
|
||||||
| 删除商品 | 删除商品 \[名称或序号] | 在真寻的商店中删除一点东西
|
|
||||||
| 修改商品 | 修改商品 -name \[名称或序号] -price \[价格] -des \[描述] -discount \[折扣] -time \[限时]| 注意空格,不需要的参数可以不加<br>示例:修改商品 -name 1 -price 900 【修改序号为1的商品的价格为900】
|
|
||||||
| 节日红包 | 节日红包 \[金额] \[数量] \[祝福语]? \[群号]?... | 群号支持批量,使用空格隔开,不使用群号则对所有群发送节日红包,节日红包有效时间为24小时,祝福语默认为“恭喜发财 大吉大利”<br>示例:节日红包 10000 15 真寻真可爱 123324423 23423423
|
|
||||||
| 修改群权限 | 修改群权限 \[group] \[level] | 所以说这功能是对内鬼的无奈,默认群权限为5,默认无法使用 色图/coser/p站排行/搜图(这些功能都要9级权限)
|
|
||||||
|更新原神今日素材| 更新原神今日素材 | 自动更新原神每日素材失败时可以手动触发
|
|
||||||
|更新原神资源信息| 更新原神资源信息 | 除了每日自动更新的资源外,额外更新大地图
|
|
||||||
| 清理数据 | 清理数据 | 清理 temp,rar,r18_rar 文件夹的文件数据
|
|
||||||
|添加pix关键词/uid/pid | 添加pix关键词/uid/pid [keyword/pid:pid/uid:uid] [-f]? | 与普通功能相同,额外可以通过参数 -f 强制通过检测
|
|
||||||
|删除pix关键词 | 删除pix关键词 *[keyword/uid/pid:pid] | 删除已收录的keyword/uid/pid
|
|
||||||
|更新pix关键词 | 更新pix关键词 [keyword/pid:pid/uid:uid] [num]?| 更新keyword,uid,pid或指定uid,pid,未指定时,则更新全部,当num未指定时为keyword/uid/pid更新全部<br>示例:更新pix关键词<br>更新pix关键词uid 8<br>更新pix关键词pid:83457477<br>num:倒叙更新数量
|
|
||||||
|删除pix图片 | 删除pix图片 [*pid] [-b]? | [-b]参数为删除的同时加入黑名单(不再更新),虽然是pid,但是_p也可以<br>示例:删除pix图片3458344 8235234_p1 -b
|
|
||||||
|显示pix关键词 | 显示pix关键词 | 与普通功能相同,额外显示待收录和黑名单
|
|
||||||
|pix检测更新 | pix检测更新 [update]? | 检测从未更新过的pid或uid,-update参数将在检测后直接更新未更新过的pid或uid<br>示例:pix检测更新 update
|
|
||||||
| 检查更新真寻 | 检查更新真寻 | 不再需要麻烦的clone第一步
|
|
||||||
| 关闭功能 | 关闭[功能] [group/private]/*[群号]? | 关闭色图:维护功能(关闭总开关)<br>关闭色图 g:在群内限制功能<br>关闭色图 p:在私聊限制功能<br>关闭色图 1234678:禁用12345678的色图功能
|
|
||||||
| 群白名单 | 添加/删除群白名单 *[群号] / 查看群白名单 | 白名单内的群不会受到 维护 限制
|
|
||||||
| 功能状态 | 功能状态 | 查看功能开关状态
|
|
||||||
| pix | pix [-s/-r] [keyword] | 可以通过pix -s 查看图库的涩图,pix -r查看图库的r18图,支持搜索,当然,pix图库只区分了r18和非r18,如果-s查询到不色的图也问题不大
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
## 部署
|
## 简单部署
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -288,8 +190,7 @@ pip install -r requirements.txt
|
|||||||
python bot.py
|
python bot.py
|
||||||
```
|
```
|
||||||
|
|
||||||
## 配置(暂时不更新 json 配置,请将USE_CONFIG_FILE设置为False)
|
## 简单配置
|
||||||
在 configs/config.py 中的 USE_CONFIG_FILE,默认为False
|
|
||||||
|
|
||||||
```
|
```
|
||||||
1.在.env.dev文件中
|
1.在.env.dev文件中
|
||||||
@@ -297,174 +198,165 @@ python bot.py
|
|||||||
SUPERUSERS = [""] # 填写你的QQ
|
SUPERUSERS = [""] # 填写你的QQ
|
||||||
|
|
||||||
2.在configs/config.py文件中
|
2.在configs/config.py文件中
|
||||||
必填:
|
* 数据库配置
|
||||||
1. API KEY
|
|
||||||
2.数据库配置
|
|
||||||
|
|
||||||
在./configs/config.py中配置基本配置(除API KEY ,数据库和代理外都含有默认值)
|
3.在configs/config.yaml文件中 # 该文件需要启动一次后生成
|
||||||
在./configs/path_config.py配置路径(含有默认配置)
|
* 修改插件配置项
|
||||||
|
|
||||||
########(暂时不更新 json 配置,请将USE_CONFIG_FILE设置为False,直接进入./configs/config.py进行配置)
|
|
||||||
# 是否使用配置文件(为True时这将会生成三份配置文件
|
|
||||||
./config.json:主要配置
|
|
||||||
./configs/plugins2cmd_config.json: 功能模块与对应命令配置
|
|
||||||
./configs/other_config.json: 一些插件配置)
|
|
||||||
|
|
||||||
USE_CONFIG_FILE = True
|
|
||||||
|
|
||||||
# 如果不使用配置文件,将USE_CONFIG_FILE设置为False
|
|
||||||
#可在./configs/config.py文件中修改配置,在./configs/path_config.py修改资源路径
|
|
||||||
# 已在./configs/config.py和./configs/path_config.py中为各个配置提供注解!
|
|
||||||
```
|
|
||||||
|
|
||||||
## 配置文件注解(如果使用配置文件的话)
|
|
||||||
<details>
|
|
||||||
<summary>配置文件注解</summary>
|
|
||||||
./config.json
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
# 必填(影响功能运行)
|
|
||||||
"apikey": {
|
|
||||||
"LOLICON_KEY": "", # loliconAPI,缺失会导致色图功能异常
|
|
||||||
"TL_KEY": [] # 图灵Key(为什么要用列表?因为白嫖用户能拿5个apikey,每个apikey每日限制100条)
|
|
||||||
},
|
|
||||||
|
|
||||||
# (必填!!!)
|
|
||||||
# 数据库配置(如果填写了bind,后面就不用再填了)只是帮你拼接好)
|
|
||||||
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
|
|
||||||
"sql": {
|
|
||||||
"bind": "",
|
|
||||||
"sql_name": "",
|
|
||||||
"user": "",
|
|
||||||
"password": "",
|
|
||||||
"address": "",
|
|
||||||
"port": "",
|
|
||||||
"database": ""
|
|
||||||
},
|
|
||||||
|
|
||||||
# 路径设置(不填则使用默认)
|
|
||||||
"path": {
|
|
||||||
"IMAGE_PATH": "", # 图片路径
|
|
||||||
"VOICE_PATH": "", # 音频路径
|
|
||||||
"TXT_PATH": "", # 文本路径
|
|
||||||
"LOG_PATH": "", # 日志路径
|
|
||||||
"DATA_PATH": "", # 数据路径
|
|
||||||
"DRAW_PATH": "" # 抽卡数据路径
|
|
||||||
"TEMP_PATH": "" # 临时图片路径
|
|
||||||
},
|
|
||||||
|
|
||||||
# 代理设置
|
|
||||||
"proxy": {
|
|
||||||
"system_proxy": "", # 系统代理
|
|
||||||
"buff_proxy": "" # buff代理
|
|
||||||
},
|
|
||||||
|
|
||||||
# RSSHUB地址
|
|
||||||
"rsshub": {
|
|
||||||
"RSSHUBAPP": "https:\/\/docs.rsshub.app\/"
|
|
||||||
},
|
|
||||||
|
|
||||||
# 各个管理员功能 对应的 权限
|
|
||||||
"level": {
|
|
||||||
"DELETE_IMG_LEVEL": 7,
|
|
||||||
"MOVE_IMG_LEVEL": 7,
|
|
||||||
"UPLOAD_LEVEL": 6,
|
|
||||||
"BAN_LEVEL": 5,
|
|
||||||
"OC_LEVEL": 2,
|
|
||||||
"MUTE_LEVEL": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
./configs/plugins2cmd_config.json
|
|
||||||
```
|
|
||||||
# 单个例子注解
|
|
||||||
"send_img": [
|
|
||||||
"发送图片",
|
|
||||||
"萝莉",
|
|
||||||
"美图",
|
|
||||||
"壁纸"
|
|
||||||
]
|
|
||||||
# 发送 关闭发送图片/关闭萝莉/关闭美图/关闭壁纸 都将触发命令 关闭send_img
|
|
||||||
```
|
|
||||||
|
|
||||||
./configs/other_config.json
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"base": {
|
|
||||||
# 图库配置,会影响 上传/删除/移动/发送图片等功能
|
|
||||||
"IMAGE_DIR_LIST": [
|
|
||||||
"色图",
|
|
||||||
"美图",
|
|
||||||
"萝莉",
|
|
||||||
"壁纸"
|
|
||||||
],
|
|
||||||
"BAN_RESULT": "才不会给你发消息." # 当被ban用户触发命令后发送的消息
|
|
||||||
},
|
|
||||||
|
|
||||||
"bool": {
|
|
||||||
"AUTO_ADD_FRIEND": true, # 是否自动添加好友
|
|
||||||
"DOWNLOAD_SETU": true # 是否下载bot发送过的色图(不会重复)
|
|
||||||
},
|
|
||||||
|
|
||||||
"max_count": {
|
|
||||||
"MAXINFO_REIMU": 7, # 上车(reimu)功能查找目的地的最大数
|
|
||||||
"COUNT_PER_DAY_REIMU": 5, # 每日上车(reimu)次数限制
|
|
||||||
"MAXINFO_BT": 10, # bt功能单次查找最大数
|
|
||||||
"MAXINFO_PRIVATE_ANIME": 20, # 私聊搜索动漫返回的最大数量
|
|
||||||
"MAXINFO_GROUP_ANIME": 5, # 群搜索动漫返回的最大数量
|
|
||||||
"MAX_FIND_IMG_COUNT": 3, # 识图最大返回数
|
|
||||||
"MAX_SIGN_GOLD": 200, # 签到好感度加成额外获得的最大金币数
|
|
||||||
"MAX_SETU_R_COUNT": 5, # 每日色图r次数限制
|
|
||||||
},
|
|
||||||
|
|
||||||
"probability": {
|
|
||||||
"INITIAL_SETU_PROBABILITY": 0.7, # 涩图触发的基础概率(触发概率 = 基础概率 + 好感度)
|
|
||||||
"FUDU_PROBABILITY": 0.7 # 复读概率
|
|
||||||
},
|
|
||||||
|
|
||||||
# 注:即在 MALICIOUS_CHECK_TIME 时间内触发相同命令 MALICIOUS_BAN_COUNT 将被ban MALICIOUS_BAN_TIME 分钟
|
|
||||||
"malicious_ban": {
|
|
||||||
"MALICIOUS_BAN_TIME": 30, # 恶意触发命令被ban的时长(分钟)
|
|
||||||
"MALICIOUS_BAN_COUNT": 4, # 恶意触发命令的规定次数
|
|
||||||
"MALICIOUS_CHECK_TIME": 5 # 恶意触发命令的规定时间(秒)
|
|
||||||
},
|
|
||||||
"open_case": {
|
|
||||||
"INITIAL_OPEN_CASE_COUNT": 20 # 每日开箱的基本数量(总数量=基本数量 + 好感度/3)
|
|
||||||
},
|
|
||||||
|
|
||||||
# 注:即在 MUTE_DEFAULT_TIME 内发送相似(包含)消息超过 MUTE_DEFAULT_COUNT 将会被 MUTE_DEFAULT_DURATION 分钟
|
|
||||||
# 这只是默认配置,各个群可以自由设置群内刷屏检测配置
|
|
||||||
"mute": {
|
|
||||||
"MUTE_DEFAULT_COUNT": 10, # 刷屏检测默认检测最大次数
|
|
||||||
"MUTE_DEFAULT_TIME": 7, # 刷屏检测默认规定时间(秒)
|
|
||||||
"MUTE_DEFAULT_DURATION": 10 # 刷屏检测默认禁言时长(分钟)
|
|
||||||
},
|
|
||||||
"other": {
|
|
||||||
"UPDATE_GOCQ_GROUP": [], # 是否需要为某些群上传最新版的gocq?
|
|
||||||
"ADMIN_DEFAULT_AUTH": 5 # 默认群管理员权限
|
|
||||||
},
|
|
||||||
|
|
||||||
# 管理员功能 和 对应的 权限
|
|
||||||
"auth": {
|
|
||||||
"admin_plugins_auth": {
|
|
||||||
"admin_bot_manage": 2,
|
|
||||||
"ban": 5,
|
|
||||||
"delete_img": 7,
|
|
||||||
"move_img": 7,
|
|
||||||
"upload_img": 6,
|
|
||||||
"admin_help": 1,
|
|
||||||
"mute": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
## 更新
|
## 更新
|
||||||
|
|
||||||
|
### 2021/12/16 \[v0.0.7.0]
|
||||||
|
|
||||||
|
* 提供了真寻群聊功能总开关和对应默认配置项,命令:休息吧 醒来
|
||||||
|
* 新增原神玩家查询,原神便笺查询
|
||||||
|
* 群功能管理提供全部开启/关闭命令:开启/关闭全部功能
|
||||||
|
* 提供主要数据自动备份,且提供自定义配置项
|
||||||
|
* 提供命令:关于,用于介绍Bot之类的
|
||||||
|
* 新增命令exec,用于执行sql语句
|
||||||
|
* 签到提供参数 "all",用于签到所有群聊
|
||||||
|
* Ban提醒提供cd
|
||||||
|
* 本地图库提供配置项SHOW_ID,用于设置发送图片时是否显示id
|
||||||
|
* 色图和PIX提供配置项SHOW_INFO,用于设置发送图片时是否显示图片信息
|
||||||
|
* 所有被动技能提供了进群默认状态配置项
|
||||||
|
* 修复添加权限第二种添加形式无法正确添加正确的权限
|
||||||
|
* 修复签到获取好感度卡时金币不会增加
|
||||||
|
* 修复当红包数量不合法时依旧扣除金币
|
||||||
|
* 修复金币红包再次使用塞红包时无法正确退回上次未开完的金币
|
||||||
|
* 修复 滴滴滴- 只包含图片时不会发送至管理员
|
||||||
|
* 修复群词条以bot名称为开头时无法正确触发
|
||||||
|
* 修改了权限插件加载顺序防止小概率优先加载权限插件引起报错
|
||||||
|
* 本地图库新图库会统一建立在resource/img/image_management文件夹下,如果该文件夹内未找到图库,会从上级目录查找(即:resource/img/)
|
||||||
|
|
||||||
|
### 2021/12/1 \[v0.0.6.5/6]
|
||||||
|
|
||||||
|
* 群权限-1时超级用户命令依旧生效
|
||||||
|
* 修复以真寻为开头的词条不会被回复
|
||||||
|
* 修复购买道具可以为负数
|
||||||
|
* P站排行/搜图提供配置项,将略过大于指定张数的作品
|
||||||
|
* 昵称提供关键词屏蔽配置项,会将指定关键词替换为“*”
|
||||||
|
* 取消了自动更新,改为自动检测版本
|
||||||
|
* 自动更新不再覆盖config.py和移动config.yaml
|
||||||
|
|
||||||
|
### 2021/11/29 \[v0.0.6.4]
|
||||||
|
|
||||||
|
* 新增cos图撤回配置项
|
||||||
|
* 新增默认群权限配置项
|
||||||
|
* 修复权限等级类配置无法正常应用
|
||||||
|
|
||||||
|
### 2021/11/24 \[v0.0.6.3]
|
||||||
|
|
||||||
|
* 修复在线搜索色图出错
|
||||||
|
* 修复pix无法正确获取HIBIAPI
|
||||||
|
|
||||||
|
### 2021/11/23 \[v0.0.6.2]
|
||||||
|
|
||||||
|
* 替换cos API
|
||||||
|
* 提供私聊b了,即跨群b了用户
|
||||||
|
* 修复游戏抽卡导入角色失败(原神)
|
||||||
|
* 修复无Pixiv代理时报错
|
||||||
|
* 将项目中大部分aiohttp替换为httpx
|
||||||
|
* 删除了丘丘人翻译插件
|
||||||
|
* 新增群词条
|
||||||
|
* 修复游戏抽卡碧蓝航线bwiki格式更改导致获取报错
|
||||||
|
* 首次启动会生成配置文件后停止程序,配置后再次启动即可
|
||||||
|
|
||||||
|
### 2021/11/18
|
||||||
|
|
||||||
|
* 修复超级用户无法正确拉真寻入群
|
||||||
|
|
||||||
|
### 2021/11/14
|
||||||
|
|
||||||
|
* 修复功能总开关无法正确开启
|
||||||
|
|
||||||
|
### 2021/11/12
|
||||||
|
|
||||||
|
* 修复PIX无法url无法正确获取
|
||||||
|
|
||||||
|
### 2021/11/10
|
||||||
|
|
||||||
|
* 修复PIX表重复创建导致首次无法运行
|
||||||
|
* 检测Omage图库改为命令方式:检测omega图库
|
||||||
|
|
||||||
|
### 2021/11/9
|
||||||
|
|
||||||
|
* 修复管理员帮助无法正常响应
|
||||||
|
* 修复被ban时会一直回复被ban提醒
|
||||||
|
|
||||||
|
### 2021/11/5
|
||||||
|
|
||||||
|
* 修复ai没有图灵key时报错
|
||||||
|
* 提供图片路径resource/img/background/check
|
||||||
|
|
||||||
|
### 2021/11/4
|
||||||
|
|
||||||
|
* 通用排行榜改用图片消息,且可以自定义排行榜人数
|
||||||
|
* 优化CreateMat排行榜数据显示
|
||||||
|
* 修复了pix更新多余参数导致失败的问题
|
||||||
|
* 修复滴滴滴-注入风险
|
||||||
|
* 修复无法正常关闭滴滴滴,戳一戳
|
||||||
|
* 添加了发送图片撤回配置项WITHDRAW_IMAGE_TIME
|
||||||
|
* 修复了天气regex文本过长时会正则匹配过久导致nb卡顿
|
||||||
|
* message_build新增custom_forward_msg用于快捷生成转发消息
|
||||||
|
* 插件配置改为yaml存储,新增Config,用于获取和新增插件配置
|
||||||
|
* 新增 当插件加载失败时,会发送消息提醒超级用户,且在功能状态中对应失败插件写上[ERROR]
|
||||||
|
* 修复当查看-spuer插件帮助时无法正确回复
|
||||||
|
* 群内帮助图片会随群内功能开关和插件总开关变化
|
||||||
|
* 自检改为图像形式
|
||||||
|
* 更新色图删除了rar_setu,r18_rar和rar文件夹,压缩将统一在temp文件夹
|
||||||
|
* 更新色图只有在有更新数量或报错时才会提醒超级用户
|
||||||
|
* 群欢迎消息加入cd
|
||||||
|
* 加入资源管理resources_manager
|
||||||
|
* 新增 好友请求/群聊邀请 控制命令
|
||||||
|
|
||||||
|
### 2021/10/15
|
||||||
|
|
||||||
|
* 适配了原神资源查询米游社地图返回的新格式
|
||||||
|
|
||||||
|
### 2021/10/8
|
||||||
|
|
||||||
|
* 修复疫情省份查询失效
|
||||||
|
* 修复功能调用统计全局下统计可能发生错误
|
||||||
|
|
||||||
|
### 2021/10/4
|
||||||
|
|
||||||
|
* 修复了功能调用统计失效问题
|
||||||
|
* 当色图库中没有色图时,会在线搜索色图而不是‘没找到符合条件的色图...’
|
||||||
|
* 快速更新权限再给超级用户发送错误日志
|
||||||
|
* 修复疫情未加载省份城市无法正常使用
|
||||||
|
|
||||||
|
### 2021/10/3
|
||||||
|
|
||||||
|
* 对插件进行分离
|
||||||
|
* 重写了插件与限制管理器以及帮助获取
|
||||||
|
* 修改一些插件目录和数据存储目录
|
||||||
|
* 插件通用配置与限制数据将以ymal文件存储 \[路径:data/configs]
|
||||||
|
* 所有商店相关操作调用统计合并为商店(包括之前已经保存的数据,会先进行备份)
|
||||||
|
* 简化了点歌的代码相关
|
||||||
|
* 修复了碧蓝航线抽卡新框导致报错无法正常初始化
|
||||||
|
* 修复了P站排行/搜图在PC端无法正常显示
|
||||||
|
* 添加了插件对超级用户是否限制的配置 ‘limit_superuser’
|
||||||
|
* 添加命令 ‘重载插件配置’,用于生效手动修改配文件
|
||||||
|
* 超级用户帮助可以添加 -super 来显示该插件的超级用户帮助,示例:帮助.ban -super
|
||||||
|
* 原神黄历改为网页截图
|
||||||
|
* 修改了鲁迅说逻辑结构
|
||||||
|
* 修改了统计图表样式,改为自定义CreateMat
|
||||||
|
* 节日红包不再被24小时限制,群内多个节日红包将会覆盖
|
||||||
|
* 当群权限为-1时,不会对群发送修改权限通知,并屏蔽此群一切命令(包括提醒)
|
||||||
|
* 修复了红包数量可以过大或为负数,红包数量大于群员数量时会修改为群员数量
|
||||||
|
* 修复了负数开箱
|
||||||
|
* 签到最低好感度设置为0.01 [@pull/53](https://github.com/HibiKier/zhenxun_bot/pull/53)
|
||||||
|
* pip安装新依赖 ruamel.yaml
|
||||||
|
* 修复功能 EPIC [@pull/58](https://github.com/HibiKier/zhenxun_bot/pull/58)
|
||||||
|
|
||||||
|
### 2021/9/10
|
||||||
|
|
||||||
|
* 修复撤回消息有时无法正确获取消息id
|
||||||
|
|
||||||
### 2021/9/9
|
### 2021/9/9
|
||||||
|
|
||||||
* 替换coser API
|
* 替换coser API
|
||||||
@@ -472,6 +364,10 @@ python bot.py
|
|||||||
* 修复签到可能重复的问题
|
* 修复签到可能重复的问题
|
||||||
* 修复无订阅时递归出错
|
* 修复无订阅时递归出错
|
||||||
* 启用了plugins2info_dict, plugins2cd_dict, plugins2exists_dict配置文件,通过USE_CONFIG_FILE=True开启
|
* 启用了plugins2info_dict, plugins2cd_dict, plugins2exists_dict配置文件,通过USE_CONFIG_FILE=True开启
|
||||||
|
* 修复涩图local_id会被固定为50
|
||||||
|
* 优化图库数量查询
|
||||||
|
* 修复原神大地图过大无法打开报错
|
||||||
|
* 修复无法显示正确的涩图上限
|
||||||
|
|
||||||
### 2021/9/7
|
### 2021/9/7
|
||||||
|
|
||||||
@@ -479,7 +375,7 @@ python bot.py
|
|||||||
* 修改 更新信息 图片大小
|
* 修改 更新信息 图片大小
|
||||||
* 修复 查看订阅 命令 UP和番剧无法正常显示
|
* 修复 查看订阅 命令 UP和番剧无法正常显示
|
||||||
* 修复订阅推送无法正确推送
|
* 修复订阅推送无法正确推送
|
||||||
* 修复搜图返回列表为空时无法正确回复 @[pull/40](https://github.com/HibiKier/zhenxun_bot/pull/40)
|
* 修复搜图返回列表为空时无法正确回复 [@pull/40](https://github.com/HibiKier/zhenxun_bot/pull/40)
|
||||||
|
|
||||||
### 2021/9/5
|
### 2021/9/5
|
||||||
* 添加配置PIX_IMAGE_SIZE,调整PIX下载图片大小,当设置的图片404时,改为原图
|
* 添加配置PIX_IMAGE_SIZE,调整PIX下载图片大小,当设置的图片404时,改为原图
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__: v0.0.4.5
|
__version__: v0.0.6.5
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
from configs.config import Config
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"admin_bot_manage:custom_welcome_message",
|
||||||
|
"SET_GROUP_WELCOME_MESSAGE_LEVEL [LEVEL]",
|
||||||
|
2,
|
||||||
|
name="群管理员操作",
|
||||||
|
help_="设置群欢迎消息权限",
|
||||||
|
default_value=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"admin_bot_manage:switch_rule",
|
||||||
|
"CHANGE_GROUP_SWITCH_LEVEL [LEVEL]",
|
||||||
|
2,
|
||||||
|
help_="开关群功能权限",
|
||||||
|
default_value=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"admin_bot_manage",
|
||||||
|
"ADMIN_DEFAULT_AUTH",
|
||||||
|
5,
|
||||||
|
help_="默认群管理员权限",
|
||||||
|
default_value=5
|
||||||
|
)
|
||||||
|
|
||||||
|
nonebot.load_plugins("basic_plugins/admin_bot_manage")
|
||||||
@@ -4,12 +4,12 @@ from nonebot.adapters.cqhttp import Bot, GroupAdminNoticeEvent
|
|||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from models.level_user import LevelUser
|
from models.level_user import LevelUser
|
||||||
from models.group_member_info import GroupInfoUser
|
from models.group_member_info import GroupInfoUser
|
||||||
from configs.config import ADMIN_DEFAULT_AUTH
|
from configs.config import Config
|
||||||
|
|
||||||
|
|
||||||
__plugin_name__ = "群管理员监测"
|
__zx_plugin_name__ = "群管理员变动监测 [Hidden]"
|
||||||
|
__plugin_version__ = 0.1
|
||||||
__plugin_usage__ = "无"
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
admin_notice = on_notice(priority=5)
|
admin_notice = on_notice(priority=5)
|
||||||
@@ -24,8 +24,15 @@ async def _(bot: Bot, event: GroupAdminNoticeEvent, state: T_State):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
nickname = event.user_id
|
nickname = event.user_id
|
||||||
if event.sub_type == "set":
|
if event.sub_type == "set":
|
||||||
await LevelUser.set_level(event.user_id, event.group_id, ADMIN_DEFAULT_AUTH)
|
await LevelUser.set_level(
|
||||||
logger.info(f"为新晋管理员 {nickname}({event.user_id}) 添加权限等级:{ADMIN_DEFAULT_AUTH}")
|
event.user_id,
|
||||||
|
event.group_id,
|
||||||
|
Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
f"为新晋管理员 {nickname}({event.user_id}) "
|
||||||
|
f"添加权限等级:{Config.get_config('admin_bot_manage', 'ADMIN_DEFAULT_AUTH')}"
|
||||||
|
)
|
||||||
elif event.sub_type == "unset":
|
elif event.sub_type == "unset":
|
||||||
await LevelUser.delete_level(event.user_id, event.group_id)
|
await LevelUser.delete_level(event.user_id, event.group_id)
|
||||||
logger.info(f"将非管理员 {nickname}({event.user_id}) 取消权限等级")
|
logger.info(f"将非管理员 {nickname}({event.user_id}) 取消权限等级")
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from utils.utils import get_message_text, get_message_imgs
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
|
||||||
|
from .data_source import custom_group_welcome
|
||||||
|
from nonebot.adapters.cqhttp.permission import GROUP
|
||||||
|
from configs.config import Config
|
||||||
|
from services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "自定义进群欢迎消息 [Admin]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
指令:
|
||||||
|
自定义进群欢迎消息 ?[文本] ?[图片]
|
||||||
|
示例:自定义进群欢迎消息 欢迎新人![图片]
|
||||||
|
Note:可以通过[at]来确认是否艾特新成员
|
||||||
|
示例:自定义进群欢迎消息 欢迎你[at]
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = '简易的自定义群欢迎消息'
|
||||||
|
__plugin_cmd__ = ['自定义群欢迎消息 ?[文本] ?[图片]']
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = 'HibiKier'
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"admin_level": Config.get_config("admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL"),
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_welcome = on_command(
|
||||||
|
"自定义进群欢迎消息",
|
||||||
|
aliases={"自定义欢迎消息", "自定义群欢迎消息", "设置群欢迎消息"},
|
||||||
|
permission=GROUP,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@custom_welcome.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
try:
|
||||||
|
msg = get_message_text(event.json())
|
||||||
|
imgs = get_message_imgs(event.json())
|
||||||
|
if not msg and not imgs:
|
||||||
|
await custom_welcome.finish(__plugin_usage__)
|
||||||
|
await custom_welcome.send(
|
||||||
|
await custom_group_welcome(msg, imgs, event.user_id, event.group_id),
|
||||||
|
at_sender=True,
|
||||||
|
)
|
||||||
|
logger.info(f"USER {event.user_id} GROUP {event.group_id} 自定义群欢迎消息:{msg}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"自定义进群欢迎消息发生错误 {type(e)}:{e}")
|
||||||
|
await custom_welcome.send("发生了一些未知错误...")
|
||||||
@@ -0,0 +1,319 @@
|
|||||||
|
from typing import List
|
||||||
|
from nonebot.adapters.cqhttp.message import MessageSegment
|
||||||
|
from services.log import logger
|
||||||
|
from configs.path_config import DATA_PATH
|
||||||
|
from utils.message_builder import image
|
||||||
|
from utils.utils import get_local_proxy, get_bot
|
||||||
|
from pathlib import Path
|
||||||
|
from models.group_member_info import GroupInfoUser
|
||||||
|
from datetime import datetime
|
||||||
|
from services.db_context import db
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
from configs.config import Config
|
||||||
|
from utils.manager import group_manager, plugins2settings_manager, plugins_manager
|
||||||
|
from utils.image_utils import BuildImage
|
||||||
|
from utils.http_utils import AsyncHttpx
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ujson as json
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
async def group_current_status(group_id: int) -> str:
|
||||||
|
"""
|
||||||
|
获取当前所有通知的开关
|
||||||
|
:param group_id: 群号
|
||||||
|
"""
|
||||||
|
rst = "[被动技能 状态]\n"
|
||||||
|
_data = group_manager.get_task_data()
|
||||||
|
for task in _data.keys():
|
||||||
|
rst += f'{_data[task]}: {"√" if await group_manager.check_group_task_status(group_id, task) else "×"}\n'
|
||||||
|
return rst.strip()
|
||||||
|
|
||||||
|
|
||||||
|
custom_welcome_msg_json = (
|
||||||
|
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def custom_group_welcome(
|
||||||
|
msg: str, imgs: List[str], user_id: int, group_id: int
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
替换群欢迎消息
|
||||||
|
:param msg: 欢迎消息文本
|
||||||
|
:param imgs: 欢迎消息图片,只取第一张
|
||||||
|
:param user_id: 用户id,用于log记录
|
||||||
|
:param group_id: 群号
|
||||||
|
"""
|
||||||
|
img_result = ""
|
||||||
|
img = imgs[0] if imgs else ""
|
||||||
|
result = ""
|
||||||
|
if os.path.exists(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg"):
|
||||||
|
os.remove(DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
|
||||||
|
if not custom_welcome_msg_json.exists():
|
||||||
|
custom_welcome_msg_json.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
data = {}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
data = json.load(open(custom_welcome_msg_json, "r"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
data = {}
|
||||||
|
try:
|
||||||
|
if msg:
|
||||||
|
data[str(group_id)] = str(msg)
|
||||||
|
json.dump(
|
||||||
|
data, open(custom_welcome_msg_json, "w"), indent=4, ensure_ascii=False
|
||||||
|
)
|
||||||
|
logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息 {msg}")
|
||||||
|
result += msg
|
||||||
|
if img:
|
||||||
|
await AsyncHttpx.download_file(
|
||||||
|
img, DATA_PATH + f"custom_welcome_msg/{group_id}.jpg"
|
||||||
|
)
|
||||||
|
img_result = image(abspath=DATA_PATH + f"custom_welcome_msg/{group_id}.jpg")
|
||||||
|
logger.info(f"USER {user_id} GROUP {group_id} 更换群欢迎消息图片")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"GROUP {group_id} 替换群消息失败 e:{e}")
|
||||||
|
return "替换群消息失败.."
|
||||||
|
return f"替换群欢迎消息成功:\n{result}" + img_result
|
||||||
|
|
||||||
|
|
||||||
|
task_data = None
|
||||||
|
|
||||||
|
|
||||||
|
async def change_group_switch(cmd: str, group_id: int, is_super: bool = False):
|
||||||
|
global task_data
|
||||||
|
"""
|
||||||
|
修改群功能状态
|
||||||
|
:param cmd: 功能名称
|
||||||
|
:param group_id: 群号
|
||||||
|
:param is_super: 是否位超级用户,超级用户用于私聊开关功能状态
|
||||||
|
"""
|
||||||
|
if not task_data:
|
||||||
|
task_data = group_manager.get_task_data()
|
||||||
|
group_help_file = Path(DATA_PATH) / "group_help" / f"{group_id}.png"
|
||||||
|
status = cmd[:2]
|
||||||
|
cmd = cmd[2:]
|
||||||
|
type_ = "plugin"
|
||||||
|
modules = plugins2settings_manager.get_plugin_module(cmd, True)
|
||||||
|
if cmd == "全部被动":
|
||||||
|
for task in task_data:
|
||||||
|
if status == "开启":
|
||||||
|
if not await group_manager.check_group_task_status(group_id, task):
|
||||||
|
await group_manager.open_group_task(group_id, task)
|
||||||
|
else:
|
||||||
|
if await group_manager.check_group_task_status(group_id, task):
|
||||||
|
await group_manager.close_group_task(group_id, task)
|
||||||
|
if group_help_file.exists():
|
||||||
|
group_help_file.unlink()
|
||||||
|
return f"已 {status} 全部被动技能!"
|
||||||
|
if cmd == "全部功能":
|
||||||
|
for f in plugins2settings_manager.get_data():
|
||||||
|
if status == "开启":
|
||||||
|
group_manager.unblock_plugin(f, group_id)
|
||||||
|
else:
|
||||||
|
group_manager.block_plugin(f, group_id)
|
||||||
|
return f"已 {status} 全部功能!"
|
||||||
|
if cmd in [task_data[x] for x in task_data.keys()]:
|
||||||
|
type_ = "task"
|
||||||
|
modules = [x for x in task_data.keys() if task_data[x] == cmd]
|
||||||
|
for module in modules:
|
||||||
|
if is_super:
|
||||||
|
module = f"{module}:super"
|
||||||
|
if status == "开启":
|
||||||
|
if type_ == "task":
|
||||||
|
if await group_manager.check_group_task_status(group_id, module):
|
||||||
|
return f"被动 {task_data[module]} 正处于开启状态!不要重复开启."
|
||||||
|
await group_manager.open_group_task(group_id, module)
|
||||||
|
else:
|
||||||
|
if group_manager.get_plugin_status(module, group_id):
|
||||||
|
return f"功能 {cmd} 正处于开启状态!不要重复开启."
|
||||||
|
group_manager.unblock_plugin(module, group_id)
|
||||||
|
else:
|
||||||
|
if type_ == "task":
|
||||||
|
if not await group_manager.check_group_task_status(group_id, module):
|
||||||
|
return f"被动 {task_data[module]} 正处于关闭状态!不要重复关闭."
|
||||||
|
await group_manager.close_group_task(group_id, module)
|
||||||
|
else:
|
||||||
|
if not group_manager.get_plugin_status(module, group_id):
|
||||||
|
return f"功能 {cmd} 正处于关闭状态!不要重复关闭."
|
||||||
|
group_manager.block_plugin(module, group_id)
|
||||||
|
if group_help_file.exists():
|
||||||
|
group_help_file.unlink()
|
||||||
|
if is_super:
|
||||||
|
for file in os.listdir(Path(DATA_PATH) / "group_help"):
|
||||||
|
file = Path(DATA_PATH) / "group_help" / file
|
||||||
|
file.unlink()
|
||||||
|
else:
|
||||||
|
_help_image = Path(DATA_PATH) / "group_help" / f"{group_id}.png"
|
||||||
|
if _help_image.exists():
|
||||||
|
_help_image.unlink()
|
||||||
|
return f"{status} {cmd} 功能!"
|
||||||
|
|
||||||
|
|
||||||
|
def set_plugin_status(cmd: str, block_type: str = "all"):
|
||||||
|
"""
|
||||||
|
设置插件功能状态(超级用户使用)
|
||||||
|
:param cmd: 功能名称
|
||||||
|
:param block_type: 限制类型, 'all': 私聊+群里, 'private': 私聊, 'group': 群聊
|
||||||
|
"""
|
||||||
|
status = cmd[:2]
|
||||||
|
cmd = cmd[2:]
|
||||||
|
module = plugins2settings_manager.get_plugin_module(cmd)
|
||||||
|
if status == "开启":
|
||||||
|
plugins_manager.unblock_plugin(module)
|
||||||
|
else:
|
||||||
|
plugins_manager.block_plugin(module, block_type=block_type)
|
||||||
|
for file in os.listdir(Path(DATA_PATH) / "group_help"):
|
||||||
|
file = Path(DATA_PATH) / "group_help" / file
|
||||||
|
file.unlink()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_plugin_status():
|
||||||
|
"""
|
||||||
|
获取功能状态
|
||||||
|
"""
|
||||||
|
return await asyncio.get_event_loop().run_in_executor(None, _get_plugin_status)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_plugin_status() -> MessageSegment:
|
||||||
|
"""
|
||||||
|
合成功能状态图片
|
||||||
|
"""
|
||||||
|
rst = "\t功能\n"
|
||||||
|
flag_str = "状态".rjust(4) + "\n"
|
||||||
|
for module in plugins_manager.get_data():
|
||||||
|
flag = plugins_manager.get_plugin_block_type(module)
|
||||||
|
flag = flag.upper() + " CLOSE" if flag else "OPEN"
|
||||||
|
try:
|
||||||
|
plugin_name = plugins_manager.get(module)["plugin_name"]
|
||||||
|
if (
|
||||||
|
"[Hidden]" in plugin_name
|
||||||
|
or "[Admin]" in plugin_name
|
||||||
|
or "[Superuser]" in plugin_name
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
rst += f"{plugin_name}"
|
||||||
|
except KeyError:
|
||||||
|
rst += f"{module}"
|
||||||
|
if plugins_manager.get(module)["error"]:
|
||||||
|
rst += "[ERROR]"
|
||||||
|
rst += "\n"
|
||||||
|
flag_str += f"{flag}\n"
|
||||||
|
height = len(rst.split("\n")) * 24
|
||||||
|
a = BuildImage(250, height, font_size=20)
|
||||||
|
a.text((10, 10), rst)
|
||||||
|
b = BuildImage(200, height, font_size=20)
|
||||||
|
b.text((10, 10), flag_str)
|
||||||
|
A = BuildImage(500, height)
|
||||||
|
A.paste(a)
|
||||||
|
A.paste(b, (270, 0))
|
||||||
|
return image(b64=A.pic2bs4())
|
||||||
|
|
||||||
|
|
||||||
|
async def update_member_info(group_id: int, remind_superuser: bool = False) -> bool:
|
||||||
|
"""
|
||||||
|
更新群成员信息
|
||||||
|
:param group_id: 群号
|
||||||
|
:param remind_superuser: 失败信息提醒超级用户
|
||||||
|
"""
|
||||||
|
bot = get_bot()
|
||||||
|
_group_user_list = await bot.get_group_member_list(group_id=group_id)
|
||||||
|
_error_member_list = []
|
||||||
|
_exist_member_list = []
|
||||||
|
# try:
|
||||||
|
for user_info in _group_user_list:
|
||||||
|
if user_info["card"] == "":
|
||||||
|
nickname = user_info["nickname"]
|
||||||
|
else:
|
||||||
|
nickname = user_info["card"]
|
||||||
|
async with db.transaction():
|
||||||
|
# 更新权限
|
||||||
|
if (
|
||||||
|
user_info["role"]
|
||||||
|
in [
|
||||||
|
"owner",
|
||||||
|
"admin",
|
||||||
|
]
|
||||||
|
and not await LevelUser.is_group_flag(user_info["user_id"], group_id)
|
||||||
|
):
|
||||||
|
await LevelUser.set_level(
|
||||||
|
user_info["user_id"],
|
||||||
|
user_info["group_id"],
|
||||||
|
Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
|
||||||
|
)
|
||||||
|
if str(user_info["user_id"]) in bot.config.superusers:
|
||||||
|
await LevelUser.set_level(
|
||||||
|
user_info["user_id"], user_info["group_id"], 9
|
||||||
|
)
|
||||||
|
user = await GroupInfoUser.get_member_info(
|
||||||
|
user_info["user_id"], user_info["group_id"]
|
||||||
|
)
|
||||||
|
if user:
|
||||||
|
if user.user_name != nickname:
|
||||||
|
await user.update(user_name=nickname).apply()
|
||||||
|
logger.info(
|
||||||
|
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
|
||||||
|
)
|
||||||
|
_exist_member_list.append(int(user_info["user_id"]))
|
||||||
|
continue
|
||||||
|
join_time = datetime.strptime(
|
||||||
|
time.strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
|
||||||
|
),
|
||||||
|
"%Y-%m-%d %H:%M:%S",
|
||||||
|
)
|
||||||
|
if await GroupInfoUser.add_member_info(
|
||||||
|
user_info["user_id"],
|
||||||
|
user_info["group_id"],
|
||||||
|
nickname,
|
||||||
|
join_time,
|
||||||
|
):
|
||||||
|
_exist_member_list.append(int(user_info["user_id"]))
|
||||||
|
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
|
||||||
|
else:
|
||||||
|
_error_member_list.append(
|
||||||
|
f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败\n"
|
||||||
|
)
|
||||||
|
_del_member_list = list(
|
||||||
|
set(_exist_member_list).difference(
|
||||||
|
set(await GroupInfoUser.get_group_member_id_list(group_id))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if _del_member_list:
|
||||||
|
for del_user in _del_member_list:
|
||||||
|
if await GroupInfoUser.delete_member_info(del_user, group_id):
|
||||||
|
logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
|
||||||
|
else:
|
||||||
|
logger.info(f"退群用户{del_user} 所属{group_id} 删除失败")
|
||||||
|
if _error_member_list and remind_superuser:
|
||||||
|
result = ""
|
||||||
|
for error_user in _error_member_list:
|
||||||
|
result += error_user
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]), message=result[:-1]
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def set_group_bot_status(group_id: int, status: bool) -> str:
|
||||||
|
"""
|
||||||
|
设置群聊bot开关状态
|
||||||
|
:param group_id: 群号
|
||||||
|
:param status: 状态
|
||||||
|
"""
|
||||||
|
if status:
|
||||||
|
if group_manager.check_group_bot_status(group_id):
|
||||||
|
return "我还醒着呢!"
|
||||||
|
group_manager.turn_on_group_bot_status(group_id)
|
||||||
|
return "呜..醒来了..."
|
||||||
|
else:
|
||||||
|
group_manager.shutdown_group_bot_status(group_id)
|
||||||
|
# for x in group_manager.get_task_data():
|
||||||
|
# group_manager.close_group_task(group_id, x)
|
||||||
|
return "那我先睡觉了..."
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
from nonebot.adapters.cqhttp import Bot, Event
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from utils.manager import group_manager, plugins2settings_manager
|
||||||
|
from utils.utils import get_message_text
|
||||||
|
from services.log import logger
|
||||||
|
|
||||||
|
cmd = []
|
||||||
|
|
||||||
|
|
||||||
|
def switch_rule(bot: Bot, event: Event, state: T_State) -> bool:
|
||||||
|
"""
|
||||||
|
检测文本是否是关闭功能命令
|
||||||
|
:param bot: pass
|
||||||
|
:param event: pass
|
||||||
|
:param state: pass
|
||||||
|
"""
|
||||||
|
global cmd
|
||||||
|
try:
|
||||||
|
if not cmd:
|
||||||
|
cmd = ["关闭全部被动", "开启全部被动", "开启全部功能", "关闭全部功能"]
|
||||||
|
_data = group_manager.get_task_data()
|
||||||
|
for key in _data:
|
||||||
|
cmd.append(f"开启{_data[key]}")
|
||||||
|
cmd.append(f"关闭{_data[key]}")
|
||||||
|
cmd.append(f"开启 {_data[key]}")
|
||||||
|
cmd.append(f"关闭 {_data[key]}")
|
||||||
|
_data = plugins2settings_manager.get_data()
|
||||||
|
for key in _data:
|
||||||
|
try:
|
||||||
|
for x in _data[key]["cmd"]:
|
||||||
|
cmd.append(f"开启{x}")
|
||||||
|
cmd.append(f"关闭{x}")
|
||||||
|
cmd.append(f"开启 {x}")
|
||||||
|
cmd.append(f"关闭 {x}")
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
msg = get_message_text(event.json()).split()
|
||||||
|
msg = msg[0] if msg else ""
|
||||||
|
return msg in cmd
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"检测是否为功能开关命令发生错误 {type(e)}: {e}")
|
||||||
|
return False
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
from nonebot import on_command, on_message, on_regex
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent, GROUP
|
||||||
|
from .data_source import (
|
||||||
|
change_group_switch,
|
||||||
|
set_plugin_status,
|
||||||
|
get_plugin_status,
|
||||||
|
group_current_status,
|
||||||
|
set_group_bot_status
|
||||||
|
)
|
||||||
|
from services.log import logger
|
||||||
|
from configs.config import NICKNAME, Config
|
||||||
|
from utils.utils import get_message_text, is_number
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from .rule import switch_rule
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "群功能开关 [Admin]"
|
||||||
|
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
群内功能与被动技能开关
|
||||||
|
指令:
|
||||||
|
开启/关闭[功能]
|
||||||
|
群被动状态
|
||||||
|
开启全部被动
|
||||||
|
关闭全部被动
|
||||||
|
醒来/休息吧
|
||||||
|
示例:开启/关闭色图
|
||||||
|
""".strip()
|
||||||
|
__plugin_superuser_usage__ = """
|
||||||
|
usage:
|
||||||
|
功能总开关与指定群禁用
|
||||||
|
指令:
|
||||||
|
功能状态
|
||||||
|
开启/关闭[功能] [group]
|
||||||
|
开启/关闭[功能] ['private'/'group']
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "群内功能开关"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"开启/关闭[功能]",
|
||||||
|
"群被动状态",
|
||||||
|
"开启全部被动",
|
||||||
|
"关闭全部被动",
|
||||||
|
"醒来/休息吧",
|
||||||
|
"功能状态 [_superuser]",
|
||||||
|
"开启/关闭[功能] [group] [_superuser]",
|
||||||
|
"开启/关闭[功能] ['private'/'group'] [_superuser]",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"admin_level": Config.get_config("admin_bot_manage", "CHANGE_GROUP_SWITCH_LEVEL"),
|
||||||
|
"cmd": ["开启功能", "关闭功能", "开关"]
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_rule_matcher = on_message(rule=switch_rule, priority=4, block=True)
|
||||||
|
|
||||||
|
plugins_status = on_command("功能状态", permission=SUPERUSER, priority=5, block=True)
|
||||||
|
|
||||||
|
group_task_status = on_command("群被动状态", permission=GROUP, priority=5, block=True)
|
||||||
|
|
||||||
|
group_status = on_regex("^(休息吧|醒来)$", permission=GROUP, priority=5, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@switch_rule_matcher.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
_cmd = get_message_text(event.json()).split()[0]
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
await switch_rule_matcher.send(await change_group_switch(_cmd, event.group_id))
|
||||||
|
logger.info(f"USER {event.user_id} GROUP {event.group_id} 使用群功能管理命令 {_cmd}")
|
||||||
|
else:
|
||||||
|
if str(event.user_id) in bot.config.superusers:
|
||||||
|
block_type = " ".join(get_message_text(event.json()).split()[1:])
|
||||||
|
block_type = block_type if block_type else "a"
|
||||||
|
if is_number(block_type):
|
||||||
|
if not int(block_type) in [
|
||||||
|
g["group_id"]
|
||||||
|
for g in await bot.get_group_list(self_id=int(bot.self_id))
|
||||||
|
]:
|
||||||
|
await switch_rule_matcher.finish(f"{NICKNAME}未加入群聊:{block_type}")
|
||||||
|
await change_group_switch(_cmd, int(block_type), True)
|
||||||
|
group_name = (await bot.get_group_info(group_id=int(block_type)))[
|
||||||
|
"group_name"
|
||||||
|
]
|
||||||
|
await switch_rule_matcher.send(
|
||||||
|
f"已禁用群聊 {group_name}({block_type}) 的 {_cmd[2:]} 功能"
|
||||||
|
)
|
||||||
|
elif block_type in ["all", "private", "group", "a", "p", "g"]:
|
||||||
|
block_type = "all" if block_type == "a" else block_type
|
||||||
|
block_type = "private" if block_type == "p" else block_type
|
||||||
|
block_type = "group" if block_type == "g" else block_type
|
||||||
|
set_plugin_status(_cmd, block_type)
|
||||||
|
if block_type == "all":
|
||||||
|
await switch_rule_matcher.send(f"已{_cmd[:2]}功能:{_cmd[2:]}")
|
||||||
|
elif block_type == "private":
|
||||||
|
await switch_rule_matcher.send(f"已在私聊中{_cmd[:2]}功能:{_cmd[2:]}")
|
||||||
|
else:
|
||||||
|
await switch_rule_matcher.send(f"已在群聊中{_cmd[:2]}功能:{_cmd[2:]}")
|
||||||
|
else:
|
||||||
|
await switch_rule_matcher.finish("格式错误:关闭[功能] [group]/[p/g]")
|
||||||
|
logger.info(f"USER {event.user_id} 使用功能管理命令 {_cmd} | {block_type}")
|
||||||
|
|
||||||
|
|
||||||
|
@plugins_status.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
await plugins_status.send(await get_plugin_status())
|
||||||
|
|
||||||
|
|
||||||
|
@group_task_status.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
await group_task_status.send(await group_current_status(event.group_id))
|
||||||
|
|
||||||
|
|
||||||
|
@group_status.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
r = re.search("^(休息吧|醒来)$", get_message_text(event.json()))
|
||||||
|
if r:
|
||||||
|
if r.group(1) == "休息吧":
|
||||||
|
msg = set_group_bot_status(event.group_id, False)
|
||||||
|
else:
|
||||||
|
msg = set_group_bot_status(event.group_id, True)
|
||||||
|
await group_status.send(msg)
|
||||||
|
logger.info(f"USER {event.user_id} GROUP {event.group_id} 使用总开关命令:{r.group(1)}")
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from utils.utils import scheduler, get_bot
|
||||||
|
from .data_source import update_member_info
|
||||||
|
from services.log import logger
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
from asyncpg.exceptions import ConnectionDoesNotExistError, UndefinedColumnError
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = '管理方面定时任务 [Hidden]'
|
||||||
|
__plugin_usage__ = '无'
|
||||||
|
__plugin_des__ = '成员信息和管理权限的定时更新'
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = 'HibiKier'
|
||||||
|
|
||||||
|
|
||||||
|
# 自动更新群员信息
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
"cron",
|
||||||
|
hour=2,
|
||||||
|
minute=1,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
bot = get_bot()
|
||||||
|
if bot:
|
||||||
|
gl = await bot.get_group_list()
|
||||||
|
gl = [g["group_id"] for g in gl]
|
||||||
|
for g in gl:
|
||||||
|
try:
|
||||||
|
await update_member_info(g)
|
||||||
|
logger.info(f"更新群组 g:{g} 成功")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"更新群组错误 g:{g} e:{e}")
|
||||||
|
|
||||||
|
|
||||||
|
# 快速更新群员信息以及管理员权限
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
"interval",
|
||||||
|
minutes=5,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
try:
|
||||||
|
bot = get_bot()
|
||||||
|
if bot:
|
||||||
|
gl = await bot.get_group_list()
|
||||||
|
gl = [g["group_id"] for g in gl]
|
||||||
|
all_group = [x.group_id for x in await GroupInfo.get_all_group()]
|
||||||
|
for g in gl:
|
||||||
|
if g not in all_group:
|
||||||
|
await update_member_info(g, False)
|
||||||
|
logger.info(f"快速更新群信息以及权限:{g}")
|
||||||
|
except (IndexError, ConnectionDoesNotExistError, UndefinedColumnError):
|
||||||
|
pass
|
||||||
@@ -1,35 +1,41 @@
|
|||||||
from nonebot import on_command, on_notice
|
from nonebot import on_command, on_notice
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
|
||||||
from .data_source import update_member_info
|
from .data_source import update_member_info
|
||||||
|
|
||||||
__plugin_name__ = "更新群组成员列表"
|
__zx_plugin_name__ = "更新群组成员列表 [Admin]"
|
||||||
|
__plugin_usage__ = """
|
||||||
__plugin_usage__ = """
|
usage:
|
||||||
说明:
|
更新群组成员的基本信息
|
||||||
更新群组成员的基本信息
|
指令:
|
||||||
示例:
|
更新群组成员列表/更新群组成员信息
|
||||||
更新群组成员列表
|
""".strip()
|
||||||
"""
|
__plugin_des__ = '更新群组成员列表'
|
||||||
|
__plugin_cmd__ = ['更新群组成员列表']
|
||||||
|
__plugin_version__ = 0.1
|
||||||
refresh_member_group = on_command(
|
__plugin_author__ = 'HibiKier'
|
||||||
"更新群组成员列表", aliases={"更新群组成员信息"}, permission=GROUP, priority=5, block=True
|
__plugin_settings__ = {
|
||||||
)
|
"admin_level": 1,
|
||||||
|
}
|
||||||
|
|
||||||
@refresh_member_group.handle()
|
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
refresh_member_group = on_command(
|
||||||
if await update_member_info(event.group_id):
|
"更新群组成员列表", aliases={"更新群组成员信息"}, permission=GROUP, priority=5, block=True
|
||||||
await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
|
)
|
||||||
else:
|
|
||||||
await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
|
|
||||||
|
@refresh_member_group.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
group_increase_handle = on_notice(priority=1, block=False)
|
if await update_member_info(event.group_id):
|
||||||
|
await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
|
||||||
|
else:
|
||||||
@group_increase_handle.handle()
|
await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
|
||||||
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
|
|
||||||
if event.user_id == int(bot.self_id):
|
|
||||||
await update_member_info(event.group_id)
|
group_increase_handle = on_notice(priority=1, block=False)
|
||||||
|
|
||||||
|
|
||||||
|
@group_increase_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
|
||||||
|
if event.user_id == int(bot.self_id):
|
||||||
|
await update_member_info(event.group_id)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters import Bot
|
||||||
|
from nonebot.adapters.cqhttp import GroupMessageEvent
|
||||||
|
from utils.message_builder import image
|
||||||
|
from .data_source import create_help_image, admin_help_image
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = '管理帮助 [Admin]'
|
||||||
|
__plugin_usage__ = '管理员帮助,在群内回复“管理员帮助”'
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = 'HibiKier'
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"admin_level": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
admin_help = on_command("管理员帮助", aliases={"管理帮助"}, priority=5, block=True)
|
||||||
|
|
||||||
|
if admin_help_image.exists():
|
||||||
|
admin_help_image.unlink()
|
||||||
|
|
||||||
|
|
||||||
|
@admin_help.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
if not admin_help_image.exists():
|
||||||
|
await create_help_image()
|
||||||
|
await admin_help.send(image('admin_help_img.png'))
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
from utils.image_utils import BuildImage
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from services.log import logger
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
from utils.manager import group_manager
|
||||||
|
from nonebot.adapters.cqhttp import Bot
|
||||||
|
from pathlib import Path
|
||||||
|
from nonebot import Driver
|
||||||
|
import asyncio
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
background = Path(IMAGE_PATH) / "background" / "0.png"
|
||||||
|
|
||||||
|
admin_help_image = Path(IMAGE_PATH) / 'admin_help_img.png'
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_bot_connect
|
||||||
|
async def init_task(bot: Bot = None):
|
||||||
|
if not group_manager.get_task_data():
|
||||||
|
await group_manager.init_group_task()
|
||||||
|
logger.info(f'已成功加载 {len(group_manager.get_task_data())} 个被动技能.')
|
||||||
|
|
||||||
|
|
||||||
|
async def create_help_image():
|
||||||
|
"""
|
||||||
|
创建管理员帮助图片
|
||||||
|
"""
|
||||||
|
await asyncio.get_event_loop().run_in_executor(
|
||||||
|
None, _create_help_image
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_help_image():
|
||||||
|
"""
|
||||||
|
创建管理员帮助图片
|
||||||
|
"""
|
||||||
|
_matchers = get_matchers()
|
||||||
|
_plugin_name_list = []
|
||||||
|
width = 0
|
||||||
|
_plugin_level = {}
|
||||||
|
for matcher in _matchers:
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
_module = _plugin.module
|
||||||
|
try:
|
||||||
|
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
"[admin]" in plugin_name.lower()
|
||||||
|
and plugin_name not in _plugin_name_list
|
||||||
|
and plugin_name != "管理帮助 [Admin]"
|
||||||
|
):
|
||||||
|
_plugin_name_list.append(plugin_name)
|
||||||
|
plugin_settings = _module.__getattribute__("__plugin_settings__")
|
||||||
|
plugin_des = _module.__getattribute__("__plugin_des__")
|
||||||
|
plugin_cmd = _module.__getattribute__("__plugin_cmd__")
|
||||||
|
plugin_cmd = [x for x in plugin_cmd if "[_superuser]" not in x]
|
||||||
|
admin_level = int(plugin_settings["admin_level"])
|
||||||
|
if _plugin_level.get(admin_level):
|
||||||
|
_plugin_level[admin_level].append(
|
||||||
|
f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_plugin_level[admin_level] = [
|
||||||
|
f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)
|
||||||
|
]
|
||||||
|
x = len(f"[{admin_level}] {plugin_des} -> " + " / ".join(plugin_cmd)) * 23
|
||||||
|
width = width if width > x else x
|
||||||
|
except AttributeError:
|
||||||
|
logger.warning(f"获取管理插件 {matcher.module}: {plugin_name} 设置失败...")
|
||||||
|
help_str = "* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" \
|
||||||
|
"[权限等级] 管理员帮助:\n\n"
|
||||||
|
x = list(_plugin_level.keys())
|
||||||
|
x.sort()
|
||||||
|
for level in x:
|
||||||
|
for help_ in _plugin_level[level]:
|
||||||
|
help_str += f"\t{help_}\n\n"
|
||||||
|
help_str += '-----[被动技能开关]-----\n\n'
|
||||||
|
task_data = group_manager.get_task_data()
|
||||||
|
for i, x in enumerate(task_data.keys()):
|
||||||
|
help_str += f'{i+1}.开启/关闭{task_data[x]}\n\n'
|
||||||
|
height = len(help_str.split("\n")) * 33
|
||||||
|
A = BuildImage(width, height, font_size=24)
|
||||||
|
_background = BuildImage(width, height, background=background)
|
||||||
|
A.text((150, 110), help_str)
|
||||||
|
A.paste(_background, alpha=True)
|
||||||
|
A.save(admin_help_image)
|
||||||
|
logger.info(f'已成功加载 {len(_plugin_name_list)} 条管理员命令')
|
||||||
|
|
||||||
|
|
||||||
@@ -1,37 +1,63 @@
|
|||||||
from utils.message_builder import image
|
from utils.message_builder import image
|
||||||
from utils.utils import scheduler, get_bot
|
from utils.utils import scheduler, get_bot
|
||||||
|
from nonebot import on_message
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from models.group_remind import GroupRemind
|
|
||||||
from models.group_info import GroupInfo
|
from models.group_info import GroupInfo
|
||||||
from models.friend_user import FriendUser
|
from models.friend_user import FriendUser
|
||||||
from nonebot.adapters.cqhttp.exception import ActionFailed
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
from configs.config import NICKNAME
|
from configs.config import NICKNAME, Config
|
||||||
|
from utils.manager import group_manager
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
|
||||||
__name__ = "早晚安 [Hidden]"
|
__zx_plugin_name__ = "定时任务相关 [Hidden]"
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_task__ = {'zwa': '早晚安'}
|
||||||
|
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"_task",
|
||||||
|
"DEFAULT_ZWA",
|
||||||
|
True,
|
||||||
|
help_="被动 早晚安 进群默认开关状态",
|
||||||
|
default_value=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"_backup",
|
||||||
|
"BACKUP_FLAG",
|
||||||
|
True,
|
||||||
|
help_="是否开启文件备份",
|
||||||
|
default_value=True
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"_backup",
|
||||||
|
"BACKUP_DIR_OR_FILE",
|
||||||
|
['data/black_word', 'data/configs', 'data/statistics', 'data/word_bank', 'data/manager', 'configs'],
|
||||||
|
name="文件备份",
|
||||||
|
help_="备份的文件夹或文件",
|
||||||
|
default_value=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
cx = on_message(priority=9, block=False)
|
||||||
|
|
||||||
|
|
||||||
# 早上好
|
# 早上好
|
||||||
@scheduler.scheduled_job(
|
@scheduler.scheduled_job(
|
||||||
"cron",
|
"cron",
|
||||||
# year=None,
|
|
||||||
# month=None,
|
|
||||||
# day=None,
|
|
||||||
# week=None,
|
|
||||||
# day_of_week="mon,tue,wed,thu,fri",
|
|
||||||
hour=6,
|
hour=6,
|
||||||
minute=1,
|
minute=1,
|
||||||
# second=None,
|
|
||||||
# start_date=None,
|
|
||||||
# end_date=None,
|
|
||||||
# timezone=None,
|
|
||||||
)
|
)
|
||||||
async def _():
|
async def _():
|
||||||
try:
|
try:
|
||||||
bot = get_bot()
|
bot = get_bot()
|
||||||
gl = await bot.get_group_list(self_id=bot.self_id)
|
gl = await bot.get_group_list()
|
||||||
gl = [g["group_id"] for g in gl]
|
gl = [g["group_id"] for g in gl]
|
||||||
for g in gl:
|
for g in gl:
|
||||||
if await GroupRemind.get_status(g, "zwa"):
|
if await group_manager.check_group_task_status(g, 'zwa'):
|
||||||
result = image("zao.jpg", "zhenxun")
|
result = image("zao.jpg", "zhenxun")
|
||||||
try:
|
try:
|
||||||
await bot.send_group_msg(group_id=g, message="早上好" + result)
|
await bot.send_group_msg(group_id=g, message="早上好" + result)
|
||||||
@@ -50,10 +76,10 @@ async def _():
|
|||||||
async def _():
|
async def _():
|
||||||
try:
|
try:
|
||||||
bot = get_bot()
|
bot = get_bot()
|
||||||
gl = await bot.get_group_list(self_id=bot.self_id)
|
gl = await bot.get_group_list()
|
||||||
gl = [g["group_id"] for g in gl]
|
gl = [g["group_id"] for g in gl]
|
||||||
for g in gl:
|
for g in gl:
|
||||||
if await GroupRemind.get_status(g, "zwa"):
|
if await group_manager.check_group_task_status(g, 'zwa'):
|
||||||
result = image("sleep.jpg", "zhenxun")
|
result = image("sleep.jpg", "zhenxun")
|
||||||
try:
|
try:
|
||||||
await bot.send_group_msg(
|
await bot.send_group_msg(
|
||||||
@@ -74,7 +100,7 @@ async def _():
|
|||||||
async def _():
|
async def _():
|
||||||
try:
|
try:
|
||||||
bot = get_bot()
|
bot = get_bot()
|
||||||
gl = await bot.get_group_list(self_id=bot.self_id)
|
gl = await bot.get_group_list()
|
||||||
gl = [g["group_id"] for g in gl]
|
gl = [g["group_id"] for g in gl]
|
||||||
for g in gl:
|
for g in gl:
|
||||||
group_info = await bot.get_group_info(group_id=g)
|
group_info = await bot.get_group_info(group_id=g)
|
||||||
@@ -98,7 +124,7 @@ async def _():
|
|||||||
async def _():
|
async def _():
|
||||||
try:
|
try:
|
||||||
bot = get_bot()
|
bot = get_bot()
|
||||||
fl = await bot.get_friend_list(self_id=bot.self_id)
|
fl = await bot.get_friend_list()
|
||||||
for f in fl:
|
for f in fl:
|
||||||
if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
|
if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
|
||||||
logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
|
logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
|
||||||
@@ -108,7 +134,35 @@ async def _():
|
|||||||
logger.error(f"自动更新群组信息错误 e:{e}")
|
logger.error(f"自动更新群组信息错误 e:{e}")
|
||||||
|
|
||||||
|
|
||||||
# 一次性任务
|
# 自动备份
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
"cron",
|
||||||
|
hour=3,
|
||||||
|
minute=25,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
if Config.get_config("_backup", "BACKUP_FLAG"):
|
||||||
|
_backup_path = Path() / 'backup'
|
||||||
|
_backup_path.mkdir(exist_ok=True, parents=True)
|
||||||
|
for x in Config.get_config("_backup", "BACKUP_DIR_OR_FILE"):
|
||||||
|
try:
|
||||||
|
path = Path(x)
|
||||||
|
_p = _backup_path / x
|
||||||
|
if path.exists():
|
||||||
|
if path.is_dir():
|
||||||
|
if _p.exists():
|
||||||
|
shutil.rmtree(_p, ignore_errors=True)
|
||||||
|
shutil.copytree(x, _p)
|
||||||
|
else:
|
||||||
|
if _p.exists():
|
||||||
|
_p.unlink()
|
||||||
|
shutil.copy(x, _p)
|
||||||
|
logger.info(f'已完成自动备份:{x}')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"自动备份文件 {x} 发生错误 {type(e)}:{e}")
|
||||||
|
|
||||||
|
|
||||||
|
# 一次性任务
|
||||||
# 固定时间触发,仅触发一次:
|
# 固定时间触发,仅触发一次:
|
||||||
#
|
#
|
||||||
# from datetime import datetime
|
# from datetime import datetime
|
||||||
@@ -3,23 +3,51 @@ from models.ban_user import BanUser
|
|||||||
from models.level_user import LevelUser
|
from models.level_user import LevelUser
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot
|
from nonebot.adapters.cqhttp import Bot
|
||||||
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
|
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent, MessageEvent
|
||||||
from utils.utils import get_message_at, get_message_text, is_number
|
from utils.utils import get_message_at, get_message_text, is_number
|
||||||
from configs.config import NICKNAME
|
from configs.config import NICKNAME, Config
|
||||||
from nonebot.permission import SUPERUSER
|
from nonebot.permission import SUPERUSER
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
|
|
||||||
|
|
||||||
__plugin_name__ = "Ban/unBan"
|
__zx_plugin_name__ = "封禁Ban用户 [Admin]"
|
||||||
__plugin_usage__ = (
|
__plugin_usage__ = """
|
||||||
"用法:\n"
|
usage:
|
||||||
f"(不是禁言!是针对{NICKNAME}是否处理封禁用户消息)\n"
|
将用户拉入或拉出黑名单
|
||||||
"封禁/解封用户 [小时] [分钟]\n"
|
指令:
|
||||||
"示例:.ban @djdsk\n"
|
.ban [at] ?[小时] ?[分钟]
|
||||||
"示例:.ban @djdsk 0 30\n"
|
.unban
|
||||||
"示例:.ban @sdasf 4\n"
|
示例:.ban @user
|
||||||
"示例:.unban @sdasf"
|
示例:.ban @user 6
|
||||||
)
|
示例:.ban @user 3 10
|
||||||
|
示例:.unban @user
|
||||||
|
""".strip()
|
||||||
|
__plugin_superuser_usage__ = """
|
||||||
|
usage:
|
||||||
|
b了=屏蔽用户消息,相当于最上级.ban
|
||||||
|
跨群ban以及跨群b了
|
||||||
|
指令:
|
||||||
|
b了 [at/qq]
|
||||||
|
.ban [user_id] ?[小时] ?[分钟]
|
||||||
|
示例:b了 @user
|
||||||
|
示例:b了 1234567
|
||||||
|
示例:.ban 12345567
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = '你被逮捕了!丢进小黑屋!'
|
||||||
|
__plugin_cmd__ = ['.ban [at] ?[小时] ?[分钟]', '.unban [at]', 'b了 [at] [_superuser]']
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = 'HibiKier'
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"admin_level": Config.get_config("ban", "BAN_LEVEL"),
|
||||||
|
"cmd": ['.ban', '.unban', 'ban', 'unban']
|
||||||
|
}
|
||||||
|
__plugin_configs__ = {
|
||||||
|
"BAN_LEVEL [LEVEL]": {
|
||||||
|
"value": 5,
|
||||||
|
"help": "ban/unban所需要的管理员权限等级",
|
||||||
|
"default_value": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ban = on_command(
|
ban = on_command(
|
||||||
@@ -158,8 +186,14 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
|||||||
|
|
||||||
|
|
||||||
@super_ban.handle()
|
@super_ban.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
qq = get_message_at(event.json())
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
qq = get_message_at(event.json())
|
||||||
|
else:
|
||||||
|
qq = get_message_text(event.json())
|
||||||
|
if not is_number(qq):
|
||||||
|
await super_ban.finish("对象qq必须为纯数字...")
|
||||||
|
qq = [qq]
|
||||||
if qq:
|
if qq:
|
||||||
qq = qq[0]
|
qq = qq[0]
|
||||||
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||||
@@ -167,7 +201,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
if not await BanUser.ban(qq, 10, 99999999):
|
if not await BanUser.ban(qq, 10, 99999999):
|
||||||
await BanUser.unban(qq)
|
await BanUser.unban(qq)
|
||||||
await BanUser.ban(qq, 10, 99999999)
|
await BanUser.ban(qq, 10, 99999999)
|
||||||
await ban.send(f"{user_name} 已在黑名单!预计不解封了..")
|
await ban.send(f"已将 {user_name} 拉入黑名单!")
|
||||||
else:
|
else:
|
||||||
await super_ban.send('需要艾特被super ban的对象..')
|
await super_ban.send('需要艾特被super ban的对象..')
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters import Bot, Event
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
import asyncio
|
||||||
|
from utils.utils import get_message_text, get_message_imgs
|
||||||
|
from services.log import logger
|
||||||
|
from utils.message_builder import image
|
||||||
|
from utils.manager import group_manager
|
||||||
|
from configs.config import Config
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "广播 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
指令:
|
||||||
|
广播- ?[消息] ?[图片]
|
||||||
|
示例:广播- 你们好!
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "昭告天下!"
|
||||||
|
__plugin_cmd__ = ["广播-"]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_task__ = {"broadcast": "广播"}
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"_task",
|
||||||
|
"DEFAULT_BROADCAST",
|
||||||
|
True,
|
||||||
|
help_="被动 广播 进群默认开关状态",
|
||||||
|
default_value=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
broadcast = on_command("广播-", priority=1, permission=SUPERUSER, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@broadcast.handle()
|
||||||
|
async def _(bot: Bot, event: Event, state: T_State):
|
||||||
|
msg = get_message_text(event.json())
|
||||||
|
imgs = get_message_imgs(event.json())
|
||||||
|
rst = ""
|
||||||
|
for img in imgs:
|
||||||
|
rst += image(img)
|
||||||
|
sid = bot.self_id
|
||||||
|
gl = await bot.get_group_list(self_id=sid)
|
||||||
|
gl = [
|
||||||
|
g["group_id"]
|
||||||
|
for g in gl
|
||||||
|
if await group_manager.check_group_task_status(g["group_id"], "broadcast")
|
||||||
|
]
|
||||||
|
g_cnt = len(gl)
|
||||||
|
cnt = 0
|
||||||
|
error = ""
|
||||||
|
x = 0.25
|
||||||
|
for g in gl:
|
||||||
|
cnt += 1
|
||||||
|
if cnt / g_cnt > x:
|
||||||
|
await broadcast.send(f"已播报至 {int(cnt / g_cnt * 100)}% 的群聊")
|
||||||
|
x += 0.25
|
||||||
|
try:
|
||||||
|
await bot.send_group_msg(self_id=sid, group_id=g, message=msg + rst)
|
||||||
|
logger.info(f"GROUP {g} 投递广播成功")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"GROUP {g} 投递广播失败:{type(e)}")
|
||||||
|
error += f"GROUP {g} 投递广播失败:{type(e)}\n"
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
await broadcast.send(f"已播报至 100% 的群聊")
|
||||||
|
if error:
|
||||||
|
await broadcast.send(f"播报时错误:{error}")
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
from nonebot import on_notice, on_request
|
||||||
|
from configs.path_config import IMAGE_PATH, DATA_PATH
|
||||||
|
from utils.message_builder import image
|
||||||
|
from models.group_member_info import GroupInfoUser
|
||||||
|
from datetime import datetime
|
||||||
|
from services.log import logger
|
||||||
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
GroupIncreaseNoticeEvent,
|
||||||
|
GroupDecreaseNoticeEvent,
|
||||||
|
)
|
||||||
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
from utils.manager import group_manager, plugins2settings_manager, requests_manager
|
||||||
|
from configs.config import NICKNAME
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
from utils.utils import FreqLimiter
|
||||||
|
from configs.config import Config
|
||||||
|
from pathlib import Path
|
||||||
|
import random
|
||||||
|
import os
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ujson as json
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "群事件处理 [Hidden]"
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_task__ = {"group_welcome": "进群欢迎", "refund_group_remind": "退群提醒"}
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"invite_manager", "message", f"请不要未经同意就拉{NICKNAME}入群!告辞!", help_="强制拉群后进群回复的内容.."
|
||||||
|
)
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"invite_manager", "flag", True, help_="被强制拉群后是否直接退出", default_value=True
|
||||||
|
)
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"invite_manager", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5
|
||||||
|
)
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"_task",
|
||||||
|
"DEFAULT_GROUP_WELCOME",
|
||||||
|
True,
|
||||||
|
help_="被动 进群欢迎 进群默认开关状态",
|
||||||
|
default_value=True,
|
||||||
|
)
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"_task",
|
||||||
|
"DEFAULT_REFUND_GROUP_REMIND",
|
||||||
|
True,
|
||||||
|
help_="被动 退群提醒 进群默认开关状态",
|
||||||
|
default_value=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_flmt = FreqLimiter(Config.get_config("invite_manager", "welcome_msg_cd"))
|
||||||
|
|
||||||
|
|
||||||
|
# 群员增加处理
|
||||||
|
group_increase_handle = on_notice(priority=1, block=False)
|
||||||
|
# 群员减少处理
|
||||||
|
group_decrease_handle = on_notice(priority=1, block=False)
|
||||||
|
# (群管理)加群同意请求
|
||||||
|
add_group = on_request(priority=1, block=False)
|
||||||
|
|
||||||
|
|
||||||
|
@group_increase_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
|
||||||
|
if event.user_id == int(bot.self_id):
|
||||||
|
group = await GroupInfo.get_group_info(event.group_id)
|
||||||
|
# 群聊不存在或被强制拉群,退出该群
|
||||||
|
if (not group or group.group_flag == 0) and Config.get_config(
|
||||||
|
"invite_manager", "flag"
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
msg = Config.get_config("invite_manager", "message")
|
||||||
|
if msg:
|
||||||
|
await bot.send_group_msg(group_id=event.group_id, message=msg)
|
||||||
|
await bot.set_group_leave(group_id=event.group_id)
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=f"触发强制入群保护,已成功退出群聊 {event.group_id}..",
|
||||||
|
)
|
||||||
|
logger.info(f"强制拉群或未有群信息,退出群聊 {group} 成功")
|
||||||
|
requests_manager.remove_request("group", event.group_id)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"强制拉群或未有群信息,退出群聊 {group} 失败 e:{e}")
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=f"触发强制入群保护,退出群聊 {event.group_id} 失败..",
|
||||||
|
)
|
||||||
|
# 默认群功能开关
|
||||||
|
elif event.group_id not in group_manager["group_manager"].keys():
|
||||||
|
data = plugins2settings_manager.get_data()
|
||||||
|
for plugin in data.keys():
|
||||||
|
if not data[plugin]["default_status"]:
|
||||||
|
group_manager.block_plugin(plugin, event.group_id)
|
||||||
|
else:
|
||||||
|
join_time = datetime.now()
|
||||||
|
user_info = await bot.get_group_member_info(
|
||||||
|
group_id=event.group_id, user_id=event.user_id
|
||||||
|
)
|
||||||
|
if await GroupInfoUser.add_member_info(
|
||||||
|
user_info["user_id"],
|
||||||
|
user_info["group_id"],
|
||||||
|
user_info["nickname"],
|
||||||
|
join_time,
|
||||||
|
):
|
||||||
|
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
|
||||||
|
else:
|
||||||
|
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
|
||||||
|
|
||||||
|
# 群欢迎消息
|
||||||
|
if await group_manager.check_group_task_status(
|
||||||
|
event.group_id, "group_welcome"
|
||||||
|
) and _flmt.check(event.group_id):
|
||||||
|
_flmt.start_cd(event.group_id)
|
||||||
|
msg = ""
|
||||||
|
img = ""
|
||||||
|
at_flag = False
|
||||||
|
custom_welcome_msg_json = (
|
||||||
|
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
|
||||||
|
)
|
||||||
|
if custom_welcome_msg_json.exists():
|
||||||
|
data = json.load(open(custom_welcome_msg_json, "r"))
|
||||||
|
if data.get(str(event.group_id)):
|
||||||
|
msg = data[str(event.group_id)]
|
||||||
|
if msg.find("[at]") != -1:
|
||||||
|
msg = msg.replace("[at]", "")
|
||||||
|
at_flag = True
|
||||||
|
if os.path.exists(DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"):
|
||||||
|
img = image(
|
||||||
|
abspath=DATA_PATH + f"custom_welcome_msg/{event.group_id}.jpg"
|
||||||
|
)
|
||||||
|
if msg or img:
|
||||||
|
await group_increase_handle.send(
|
||||||
|
"\n" + msg.strip() + img, at_sender=at_flag
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await group_increase_handle.send(
|
||||||
|
"新人快跑啊!!本群现状↓(快使用自定义!)"
|
||||||
|
+ image(random.choice(os.listdir(IMAGE_PATH + "qxz/")), "qxz")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@group_decrease_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupDecreaseNoticeEvent, state: dict):
|
||||||
|
# 被踢出群
|
||||||
|
if event.sub_type == "kick_me":
|
||||||
|
group_id = event.group_id
|
||||||
|
operator_id = event.operator_id
|
||||||
|
try:
|
||||||
|
operator_name = (
|
||||||
|
await GroupInfoUser.get_member_info(event.operator_id, event.group_id)
|
||||||
|
).user_name
|
||||||
|
except AttributeError:
|
||||||
|
operator_name = "None"
|
||||||
|
group = await GroupInfo.get_group_info(group_id)
|
||||||
|
group_name = group.group_name if group else ""
|
||||||
|
coffee = int(list(bot.config.superusers)[0])
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=coffee,
|
||||||
|
message=f"****呜..一份踢出报告****\n"
|
||||||
|
f"我被 {operator_name}({operator_id})\n"
|
||||||
|
f"踢出了 {group_name}({group_id})\n"
|
||||||
|
f"日期:{str(datetime.now()).split('.')[0]}",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
if event.user_id == int(bot.self_id):
|
||||||
|
group_manager.delete_group(event.group_id)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
user_name = (
|
||||||
|
await GroupInfoUser.get_member_info(event.user_id, event.group_id)
|
||||||
|
).user_name
|
||||||
|
except AttributeError:
|
||||||
|
user_name = str(event.user_id)
|
||||||
|
if await GroupInfoUser.delete_member_info(event.user_id, event.group_id):
|
||||||
|
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除成功")
|
||||||
|
else:
|
||||||
|
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除失败")
|
||||||
|
if await group_manager.check_group_task_status(
|
||||||
|
event.group_id, "refund_group_remind"
|
||||||
|
):
|
||||||
|
rst = ""
|
||||||
|
if event.sub_type == "leave":
|
||||||
|
rst = f"{user_name}离开了我们..."
|
||||||
|
if event.sub_type == "kick":
|
||||||
|
operator = await bot.get_group_member_info(
|
||||||
|
user_id=event.operator_id, group_id=event.group_id
|
||||||
|
)
|
||||||
|
operator_name = (
|
||||||
|
operator["card"] if operator["card"] else operator["nickname"]
|
||||||
|
)
|
||||||
|
rst = f"{user_name} 被 {operator_name} 送走了."
|
||||||
|
try:
|
||||||
|
await group_decrease_handle.send(f"{rst}")
|
||||||
|
except ActionFailed:
|
||||||
|
return
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
GroupMessageEvent
|
||||||
|
)
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from configs.path_config import IMAGE_PATH, DATA_PATH
|
||||||
|
from utils.message_builder import image
|
||||||
|
from .data_source import create_help_img, get_plugin_help
|
||||||
|
from utils.utils import get_message_text
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "帮助"
|
||||||
|
|
||||||
|
group_help_path = Path(DATA_PATH) / "group_help"
|
||||||
|
help_image = Path(IMAGE_PATH) / "help.png"
|
||||||
|
simple_help_image = Path(IMAGE_PATH) / "simple_help.png"
|
||||||
|
if help_image.exists():
|
||||||
|
help_image.unlink()
|
||||||
|
if simple_help_image.exists():
|
||||||
|
simple_help_image.unlink()
|
||||||
|
group_help_path.mkdir(exist_ok=True, parents=True)
|
||||||
|
for x in os.listdir(group_help_path):
|
||||||
|
group_help_image = group_help_path / x
|
||||||
|
group_help_image.unlink()
|
||||||
|
|
||||||
|
_help = on_command("详细功能", rule=to_me(), aliases={"详细帮助"}, priority=1, block=True)
|
||||||
|
simple_help = on_command("功能", rule=to_me(), aliases={"help", "帮助"}, priority=1, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@_help.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
if not help_image.exists():
|
||||||
|
if help_image.exists():
|
||||||
|
help_image.unlink()
|
||||||
|
if simple_help_image.exists():
|
||||||
|
simple_help_image.unlink()
|
||||||
|
await create_help_img(None, help_image, simple_help_image)
|
||||||
|
await _help.finish(image("help.png"))
|
||||||
|
|
||||||
|
|
||||||
|
@simple_help.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
msg = get_message_text(event.json())
|
||||||
|
is_super = False
|
||||||
|
if msg:
|
||||||
|
if '-super' in msg:
|
||||||
|
if str(event.user_id) in bot.config.superusers:
|
||||||
|
is_super = True
|
||||||
|
msg = msg.replace('-super', '').strip()
|
||||||
|
msg = get_plugin_help(msg, is_super)
|
||||||
|
if msg:
|
||||||
|
await _help.send(image(b64=msg))
|
||||||
|
else:
|
||||||
|
await _help.send("没有此功能的帮助信息...")
|
||||||
|
else:
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
_image_path = group_help_path / f"{event.group_id}.png"
|
||||||
|
if not _image_path.exists():
|
||||||
|
await create_help_img(event.group_id, help_image, _image_path)
|
||||||
|
await simple_help.send(image(_image_path))
|
||||||
|
else:
|
||||||
|
if not simple_help_image.exists():
|
||||||
|
if help_image.exists():
|
||||||
|
help_image.unlink()
|
||||||
|
if simple_help_image.exists():
|
||||||
|
simple_help_image.unlink()
|
||||||
|
await create_help_img(None, help_image, simple_help_image)
|
||||||
|
await _help.finish(image("simple_help.png"))
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
from utils.image_utils import BuildImage
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from utils.manager import (
|
||||||
|
plugins2settings_manager,
|
||||||
|
admin_manager,
|
||||||
|
plugins_manager,
|
||||||
|
group_manager,
|
||||||
|
)
|
||||||
|
from typing import Optional
|
||||||
|
from services.log import logger
|
||||||
|
from pathlib import Path
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
import random
|
||||||
|
import asyncio
|
||||||
|
import nonebot
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
random_bk_path = Path(IMAGE_PATH) / "background" / "help" / "simple_help"
|
||||||
|
|
||||||
|
background = Path(IMAGE_PATH) / "background" / "0.png"
|
||||||
|
|
||||||
|
|
||||||
|
async def create_help_img(
|
||||||
|
group_id: Optional[int], help_image: Path, simple_help_image: Path
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
生成帮助图片
|
||||||
|
:param group_id: 群号
|
||||||
|
:param help_image: 图片路径
|
||||||
|
:param simple_help_image: 简易帮助图片路径
|
||||||
|
"""
|
||||||
|
return await asyncio.get_event_loop().run_in_executor(
|
||||||
|
None, _create_help_img, group_id, help_image, simple_help_image
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_help_img(
|
||||||
|
group_id: Optional[int], help_image: Path, simple_help_image: Path
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
生成帮助图片
|
||||||
|
:param group_id: 群号
|
||||||
|
:param help_image: 图片路径
|
||||||
|
:param simple_help_image: 简易帮助图片路径
|
||||||
|
"""
|
||||||
|
_matchers = get_matchers()
|
||||||
|
width = 0
|
||||||
|
matchers_data = {}
|
||||||
|
_des_tmp = {}
|
||||||
|
_plugin_name_tmp = []
|
||||||
|
_tmp = []
|
||||||
|
tmp_img = BuildImage(0, 0, plain_text="1", font_size=24)
|
||||||
|
font_height = tmp_img.h
|
||||||
|
# 插件分类
|
||||||
|
for matcher in _matchers:
|
||||||
|
plugin_name = None
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
_module = _plugin.module
|
||||||
|
try:
|
||||||
|
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||||
|
try:
|
||||||
|
plugin_des = _module.__getattribute__("__plugin_des__")
|
||||||
|
except AttributeError:
|
||||||
|
plugin_des = "_"
|
||||||
|
if (
|
||||||
|
"[hidden]" in plugin_name.lower()
|
||||||
|
or "[admin]" in plugin_name.lower()
|
||||||
|
or "[superuser]" in plugin_name.lower()
|
||||||
|
or plugin_name in _plugin_name_tmp
|
||||||
|
or plugin_name == "帮助"
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
plugin_type = ("normal",)
|
||||||
|
text_type = 0
|
||||||
|
if plugins2settings_manager.get(
|
||||||
|
matcher.module
|
||||||
|
) and plugins2settings_manager[matcher.module].get("plugin_type"):
|
||||||
|
plugin_type = tuple(
|
||||||
|
plugins2settings_manager.get_plugin_data(matcher.module)[
|
||||||
|
"plugin_type"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
plugin_type = _module.__getattribute__("__plugin_type__")
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if len(plugin_type) > 1:
|
||||||
|
try:
|
||||||
|
text_type = int(plugin_type[1])
|
||||||
|
except ValueError as e:
|
||||||
|
logger.warning(f"生成列向帮助排列失败 {plugin_name}: {type(e)}: {e}")
|
||||||
|
plugin_type = plugin_type[0]
|
||||||
|
else:
|
||||||
|
plugin_type = plugin_type[0]
|
||||||
|
try:
|
||||||
|
plugin_cmd = _module.__getattribute__("__plugin_cmd__")
|
||||||
|
plugin_cmd = [x for x in plugin_cmd if "[_superuser]" not in x]
|
||||||
|
except AttributeError:
|
||||||
|
plugin_cmd = []
|
||||||
|
if plugin_type not in matchers_data.keys():
|
||||||
|
matchers_data[plugin_type] = {}
|
||||||
|
if plugin_des in _des_tmp.keys():
|
||||||
|
try:
|
||||||
|
matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"] = (
|
||||||
|
matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"]
|
||||||
|
+ plugin_cmd
|
||||||
|
)
|
||||||
|
except KeyError as e:
|
||||||
|
logger.warning(f"{type(e)}: {e}")
|
||||||
|
else:
|
||||||
|
matchers_data[plugin_type][plugin_name] = {
|
||||||
|
"module": matcher.module,
|
||||||
|
"des": plugin_des,
|
||||||
|
"cmd": plugin_cmd,
|
||||||
|
"text_type": text_type,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
if text_type == 0:
|
||||||
|
x = tmp_img.getsize(
|
||||||
|
f'{plugin_name}: {matchers_data[plugin_type][plugin_name]["des"]} ->'
|
||||||
|
+ " / ".join(matchers_data[plugin_type][plugin_name]["cmd"])
|
||||||
|
)[0]
|
||||||
|
width = width if width > x else x
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if plugin_des not in _des_tmp:
|
||||||
|
_des_tmp[plugin_des] = plugin_name
|
||||||
|
except AttributeError as e:
|
||||||
|
if plugin_name not in _plugin_name_tmp:
|
||||||
|
logger.warning(f"获取功能 {matcher.module}: {plugin_name} 设置失败...e:{e}")
|
||||||
|
if plugin_name not in _plugin_name_tmp:
|
||||||
|
_plugin_name_tmp.append(plugin_name)
|
||||||
|
help_img_list = []
|
||||||
|
simple_help_img_list = []
|
||||||
|
types = list(matchers_data.keys())
|
||||||
|
types.sort()
|
||||||
|
ix = 0
|
||||||
|
# 详细帮助
|
||||||
|
for type_ in types:
|
||||||
|
keys = list(matchers_data[type_].keys())
|
||||||
|
keys.sort()
|
||||||
|
help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
|
||||||
|
simple_help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
|
||||||
|
for i, k in enumerate(keys):
|
||||||
|
# 禁用flag
|
||||||
|
flag = True
|
||||||
|
if plugins_manager.get_plugin_status(
|
||||||
|
matchers_data[type_][k]["module"], "all"
|
||||||
|
):
|
||||||
|
flag = False
|
||||||
|
if group_id:
|
||||||
|
flag = flag and plugins_manager.get_plugin_status(
|
||||||
|
matchers_data[type_][k]["module"], "group"
|
||||||
|
)
|
||||||
|
simple_help_str += (
|
||||||
|
f"{i+1}.{k}<|_|~|>"
|
||||||
|
f"{group_manager.get_plugin_status(matchers_data[type_][k]['module'], group_id) if group_id else '_'}|"
|
||||||
|
f"{flag}\n"
|
||||||
|
)
|
||||||
|
if matchers_data[type_][k]["text_type"] == 1:
|
||||||
|
_x = tmp_img.getsize(
|
||||||
|
f"{i+1}".rjust(5)
|
||||||
|
+ f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
|
||||||
|
)[0]
|
||||||
|
_str = (
|
||||||
|
f"{i+1}".rjust(5)
|
||||||
|
+ f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
|
||||||
|
)
|
||||||
|
_str += matchers_data[type_][k]["cmd"][0] + "\n"
|
||||||
|
for c in matchers_data[type_][k]["cmd"][1:]:
|
||||||
|
_str += "".rjust(int(_x * 0.125) + 1) + f"{c}\n"
|
||||||
|
help_str += _str
|
||||||
|
else:
|
||||||
|
help_str += (
|
||||||
|
f"{i+1}".rjust(5)
|
||||||
|
+ f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
|
||||||
|
+ " / ".join(matchers_data[type_][k]["cmd"])
|
||||||
|
+ "\n"
|
||||||
|
)
|
||||||
|
height = len(help_str.split("\n")) * (font_height + 5)
|
||||||
|
simple_height = len(simple_help_str.split("\n")) * (font_height + 5)
|
||||||
|
A = BuildImage(
|
||||||
|
width + 150, height, font_size=24, color="white" if not ix % 2 else "black"
|
||||||
|
)
|
||||||
|
A.text((10, 10), help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
|
||||||
|
# 生成各个分类的插件简易帮助图片
|
||||||
|
simple_width = 0
|
||||||
|
for x in [
|
||||||
|
tmp_img.getsize(x.split("<|_|~|>")[0])[0]
|
||||||
|
for x in simple_help_str.split("\n")
|
||||||
|
]:
|
||||||
|
simple_width = simple_width if simple_width > x else x
|
||||||
|
bk = BuildImage(simple_width + 20, simple_height, font_size=24, color="#6495ED")
|
||||||
|
B = BuildImage(
|
||||||
|
simple_width + 20,
|
||||||
|
simple_height,
|
||||||
|
font_size=24,
|
||||||
|
color="white" if not ix % 2 else "black",
|
||||||
|
)
|
||||||
|
# 切分,判断插件开关状态
|
||||||
|
_s_height = 10
|
||||||
|
for _s in simple_help_str.split("\n"):
|
||||||
|
text_color = (255, 255, 255) if ix % 2 else (0, 0, 0)
|
||||||
|
_line_flag = False
|
||||||
|
if "<|_|~|>" in _s:
|
||||||
|
_x = _s.split("<|_|~|>")
|
||||||
|
_flag_sp = _x[-1].split("|")
|
||||||
|
if group_id:
|
||||||
|
if _flag_sp[0].lower() != "true":
|
||||||
|
text_color = (252, 75, 13)
|
||||||
|
if _flag_sp[1].lower() == "true":
|
||||||
|
_line_flag = True
|
||||||
|
_s = _x[0]
|
||||||
|
B.text((10, _s_height), _s, text_color)
|
||||||
|
if _line_flag:
|
||||||
|
B.line(
|
||||||
|
(
|
||||||
|
7,
|
||||||
|
_s_height + int(B.getsize(_s)[1] / 2) + 2,
|
||||||
|
B.getsize(_s)[0] + 11,
|
||||||
|
_s_height + int(B.getsize(_s)[1] / 2) + 2,
|
||||||
|
),
|
||||||
|
(236, 66, 7),
|
||||||
|
3,
|
||||||
|
)
|
||||||
|
_s_height += B.getsize("1")[1] + 5
|
||||||
|
# B.text((10, 10), simple_help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
|
||||||
|
bk.paste(B, center_type="center")
|
||||||
|
bk.transparent(2)
|
||||||
|
ix += 1
|
||||||
|
help_img_list.append(A)
|
||||||
|
simple_help_img_list.append(bk)
|
||||||
|
height = 0
|
||||||
|
for img in help_img_list:
|
||||||
|
height += img.h
|
||||||
|
if not group_id:
|
||||||
|
A = BuildImage(width + 150, height + 50, font_size=24)
|
||||||
|
A.text(
|
||||||
|
(10, 10), '* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" "功能名: 功能简介 -> 指令\n\n'
|
||||||
|
)
|
||||||
|
current_height = 50
|
||||||
|
for img in help_img_list:
|
||||||
|
A.paste(img, (0, current_height))
|
||||||
|
current_height += img.h
|
||||||
|
A.save(help_image)
|
||||||
|
# 详细帮助生成完毕
|
||||||
|
# 简易帮助图片合成
|
||||||
|
height = 0
|
||||||
|
width = 0
|
||||||
|
for img in simple_help_img_list:
|
||||||
|
if img.h > height:
|
||||||
|
height = img.h
|
||||||
|
width += img.w + 10
|
||||||
|
B = BuildImage(width + 100, height + 250, font_size=24)
|
||||||
|
width, _ = get_max_width_or_paste(simple_help_img_list, B)
|
||||||
|
bk = None
|
||||||
|
random_bk = os.listdir(random_bk_path)
|
||||||
|
if random_bk:
|
||||||
|
bk = random.choice(random_bk)
|
||||||
|
x = max(width + 50, height + 250)
|
||||||
|
B = BuildImage(
|
||||||
|
x,
|
||||||
|
x,
|
||||||
|
font_size=24,
|
||||||
|
color="#FFEFD5",
|
||||||
|
background=random_bk_path / bk,
|
||||||
|
)
|
||||||
|
B.filter("GaussianBlur", 10)
|
||||||
|
_, B = get_max_width_or_paste(simple_help_img_list, B, True)
|
||||||
|
w = 10
|
||||||
|
h = 10
|
||||||
|
for msg in ["目前支持的功能列表:", "可以通过 ‘帮助[功能名称]’ 来获取对应功能的使用方法", "或者使用 ‘详细帮助’ 来获取所有功能方法"]:
|
||||||
|
text = BuildImage(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text=msg,
|
||||||
|
font_size=24,
|
||||||
|
font="yuanshen.ttf",
|
||||||
|
)
|
||||||
|
B.paste(text, (w, h), True)
|
||||||
|
h += 50
|
||||||
|
if msg == "目前支持的功能列表:":
|
||||||
|
w += 50
|
||||||
|
B.paste(
|
||||||
|
BuildImage(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
plain_text="注: 红字代表功能被群管理员禁用,红线代表功能正在维护",
|
||||||
|
font_size=24,
|
||||||
|
font="yuanshen.ttf",
|
||||||
|
font_color=(231, 74, 57)
|
||||||
|
),
|
||||||
|
(300, 10),
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
B.save(simple_help_image)
|
||||||
|
|
||||||
|
|
||||||
|
def get_max_width_or_paste(
|
||||||
|
simple_help_img_list: list, B: BuildImage = None, is_paste: bool = False
|
||||||
|
) -> "int, BuildImage":
|
||||||
|
"""
|
||||||
|
获取最大宽度,或直接贴图
|
||||||
|
:param simple_help_img_list: 简单帮助图片列表
|
||||||
|
:param B: 背景图
|
||||||
|
:param is_paste: 是否直接贴图
|
||||||
|
"""
|
||||||
|
current_width = 50
|
||||||
|
current_height = 180
|
||||||
|
max_width = simple_help_img_list[0].w
|
||||||
|
for i in range(len(simple_help_img_list)):
|
||||||
|
try:
|
||||||
|
if is_paste and B:
|
||||||
|
B.paste(simple_help_img_list[i], (current_width, current_height), True)
|
||||||
|
current_height += simple_help_img_list[i].h + 40
|
||||||
|
if current_height + simple_help_img_list[i + 1].h > B.h - 10:
|
||||||
|
current_height = 180
|
||||||
|
current_width += max_width + 30
|
||||||
|
max_width = 0
|
||||||
|
elif simple_help_img_list[i].w > max_width:
|
||||||
|
max_width = simple_help_img_list[i].w
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
if current_width > simple_help_img_list[0].w + 50:
|
||||||
|
current_width += simple_help_img_list[-1].w
|
||||||
|
return current_width, B
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin_help(msg: str, is_super: bool = False) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取功能的帮助信息
|
||||||
|
:param msg: 功能cmd
|
||||||
|
:param is_super: 是否为超级用户
|
||||||
|
"""
|
||||||
|
module = plugins2settings_manager.get_plugin_module(msg)
|
||||||
|
if not module:
|
||||||
|
module = admin_manager.get_plugin_module(msg)
|
||||||
|
if module:
|
||||||
|
try:
|
||||||
|
plugin = nonebot.plugin.get_plugin(module)
|
||||||
|
if plugin:
|
||||||
|
if is_super:
|
||||||
|
result = plugin.module.__getattribute__(
|
||||||
|
"__plugin_superuser_usage__"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
result = plugin.module.__getattribute__("__plugin_usage__")
|
||||||
|
if result:
|
||||||
|
width = 0
|
||||||
|
for x in result.split("\n"):
|
||||||
|
_width = len(x) * 24
|
||||||
|
width = width if width > _width else _width
|
||||||
|
height = len(result.split("\n")) * 45
|
||||||
|
A = BuildImage(width, height, font_size=24)
|
||||||
|
bk = BuildImage(
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
background=Path(IMAGE_PATH) / "background" / "1.png",
|
||||||
|
)
|
||||||
|
A.paste(bk, alpha=True)
|
||||||
|
A.text((int(width * 0.048), int(height * 0.21)), result)
|
||||||
|
return A.pic2bs4()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
from configs.config import Config
|
||||||
|
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"hook",
|
||||||
|
"CHECK_NOTICE_INFO_CD",
|
||||||
|
300,
|
||||||
|
name="基础hook配置",
|
||||||
|
help_="群检测,个人权限检测等各种检测提示信息cd",
|
||||||
|
default_value=300
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"hook",
|
||||||
|
"MALICIOUS_BAN_TIME",
|
||||||
|
30,
|
||||||
|
help_="恶意命令触发检测触发后ban的时长(分钟)",
|
||||||
|
default_value=30
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"hook",
|
||||||
|
"MALICIOUS_CHECK_TIME",
|
||||||
|
5,
|
||||||
|
help_="恶意命令触发检测规定时间内(秒)",
|
||||||
|
default_value=5
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"hook",
|
||||||
|
"MALICIOUS_BAN_COUNT",
|
||||||
|
6,
|
||||||
|
help_="恶意命令触发检测最大触发次数",
|
||||||
|
default_value=6
|
||||||
|
)
|
||||||
|
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_preprocessor, IgnoredException
|
||||||
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
from utils.manager import (
|
||||||
|
plugins2settings_manager,
|
||||||
|
admin_manager,
|
||||||
|
group_manager,
|
||||||
|
plugins_manager,
|
||||||
|
)
|
||||||
|
from .utils import set_block_limit_false, status_message_manager
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
PokeNotifyEvent
|
||||||
|
)
|
||||||
|
from configs.config import Config
|
||||||
|
from models.ban_user import BanUser
|
||||||
|
from utils.utils import FreqLimiter
|
||||||
|
from utils.message_builder import at
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
_flmt = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
|
||||||
|
_flmt_g = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
|
||||||
|
_flmt_s = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
|
||||||
|
_flmt_c = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
|
||||||
|
|
||||||
|
|
||||||
|
ignore_rst_module = ["ai", "poke", "dialogue"]
|
||||||
|
|
||||||
|
|
||||||
|
# 权限检测
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
module = matcher.module
|
||||||
|
plugins2info_dict = plugins2settings_manager.get_data()
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
(not isinstance(event, MessageEvent) and module != "poke")
|
||||||
|
or await BanUser.is_ban(event.user_id)
|
||||||
|
and str(event.user_id) not in bot.config.superusers
|
||||||
|
) or (
|
||||||
|
str(event.user_id) in bot.config.superusers
|
||||||
|
and plugins2info_dict.get(module)
|
||||||
|
and not plugins2info_dict[module]["limit_superuser"]
|
||||||
|
):
|
||||||
|
return
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
# 超级用户命令
|
||||||
|
try:
|
||||||
|
_plugin = nonebot.plugin.get_plugin(module)
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||||
|
if (
|
||||||
|
"[superuser]" in plugin_name.lower()
|
||||||
|
and str(event.user_id) in bot.config.superusers
|
||||||
|
):
|
||||||
|
return
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
# 群黑名单检测 群总开关检测
|
||||||
|
if isinstance(event, GroupMessageEvent) or matcher.module == "poke":
|
||||||
|
try:
|
||||||
|
if group_manager.get_group_level(event.group_id) < 0:
|
||||||
|
raise IgnoredException("群黑名单")
|
||||||
|
if not group_manager.check_group_bot_status(event.group_id):
|
||||||
|
try:
|
||||||
|
if str(event.get_message()) != "醒来":
|
||||||
|
raise IgnoredException("功能总开关关闭状态")
|
||||||
|
except ValueError:
|
||||||
|
raise IgnoredException("功能总开关关闭状态")
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if module in admin_manager.keys() and matcher.priority not in [1, 9]:
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
# 个人权限
|
||||||
|
if (
|
||||||
|
not await LevelUser.check_level(
|
||||||
|
event.user_id,
|
||||||
|
event.group_id,
|
||||||
|
admin_manager.get_plugin_level(module),
|
||||||
|
)
|
||||||
|
and admin_manager.get_plugin_level(module) > 0
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
if _flmt.check(event.user_id):
|
||||||
|
_flmt.start_cd(event.user_id)
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id,
|
||||||
|
message=f"{at(event.user_id)}你的权限不足喔,该功能需要的权限等级:"
|
||||||
|
f"{admin_manager.get_plugin_level(module)}",
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
if event.is_tome():
|
||||||
|
status_message_manager.add(event.group_id)
|
||||||
|
raise IgnoredException("权限不足")
|
||||||
|
else:
|
||||||
|
if not await LevelUser.check_level(
|
||||||
|
event.user_id, 0, admin_manager.get_plugin_level(module)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=event.user_id,
|
||||||
|
message=f"你的权限不足喔,该功能需要的权限等级:{admin_manager.get_plugin_level(module)}",
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
if event.is_tome():
|
||||||
|
status_message_manager.add(event.user_id)
|
||||||
|
raise IgnoredException("权限不足")
|
||||||
|
if module in plugins2info_dict.keys() and matcher.priority not in [1, 9]:
|
||||||
|
# 戳一戳单独判断
|
||||||
|
if isinstance(event, GroupMessageEvent) or (
|
||||||
|
isinstance(event, PokeNotifyEvent) and event.group_id
|
||||||
|
):
|
||||||
|
if status_message_manager.get(event.group_id) is None:
|
||||||
|
status_message_manager.delete(event.group_id)
|
||||||
|
if plugins2info_dict[module]["level"] > group_manager.get_group_level(
|
||||||
|
event.group_id
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
if _flmt_g.check(event.user_id) and module not in ignore_rst_module:
|
||||||
|
_flmt_g.start_cd(event.user_id)
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id, message="群权限不足..."
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
if event.is_tome():
|
||||||
|
status_message_manager.add(event.group_id)
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
raise IgnoredException("群权限不足")
|
||||||
|
# 插件状态
|
||||||
|
if not group_manager.get_plugin_status(module, event.group_id):
|
||||||
|
try:
|
||||||
|
if module not in ignore_rst_module and _flmt_s.check(
|
||||||
|
event.group_id
|
||||||
|
):
|
||||||
|
_flmt_s.start_cd(event.group_id)
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id, message="该群未开启此功能.."
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
if event.is_tome():
|
||||||
|
status_message_manager.add(event.group_id)
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
raise IgnoredException("未开启此功能...")
|
||||||
|
# 管理员禁用
|
||||||
|
if not group_manager.get_plugin_status(f"{module}:super", event.group_id):
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
_flmt_s.check(event.group_id)
|
||||||
|
and module not in ignore_rst_module
|
||||||
|
):
|
||||||
|
_flmt_s.start_cd(event.group_id)
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id, message="管理员禁用了此群该功能..."
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
if event.is_tome():
|
||||||
|
status_message_manager.add(event.group_id)
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
raise IgnoredException("管理员禁用了此群该功能...")
|
||||||
|
# 群聊禁用
|
||||||
|
if not plugins_manager.get_plugin_status(module, block_type="group"):
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
_flmt_c.check(event.group_id)
|
||||||
|
and module not in ignore_rst_module
|
||||||
|
):
|
||||||
|
_flmt_c.start_cd(event.group_id)
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id, message="该功能在群聊中已被禁用..."
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
if event.is_tome():
|
||||||
|
status_message_manager.add(event.group_id)
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
raise IgnoredException("该插件在群聊中已被禁用...")
|
||||||
|
else:
|
||||||
|
# 私聊禁用
|
||||||
|
if not plugins_manager.get_plugin_status(module, block_type="private"):
|
||||||
|
try:
|
||||||
|
if _flmt_c.check(event.user_id):
|
||||||
|
_flmt_c.start_cd(event.user_id)
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=event.user_id, message="该功能在私聊中已被禁用..."
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
if event.is_tome():
|
||||||
|
status_message_manager.add(event.user_id)
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
raise IgnoredException("该插件在私聊中已被禁用...")
|
||||||
|
# 维护
|
||||||
|
if not plugins_manager.get_plugin_status(module, block_type="all"):
|
||||||
|
if isinstance(
|
||||||
|
event, GroupMessageEvent
|
||||||
|
) and group_manager.check_group_is_white(event.group_id):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
if (
|
||||||
|
_flmt_c.check(event.group_id)
|
||||||
|
and module not in ignore_rst_module
|
||||||
|
):
|
||||||
|
_flmt_c.start_cd(event.group_id)
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id, message="此功能正在维护..."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=event.user_id, message="此功能正在维护..."
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
if event.is_tome():
|
||||||
|
id_ = (
|
||||||
|
event.group_id
|
||||||
|
if isinstance(event, GroupMessageEvent)
|
||||||
|
else event.user_id
|
||||||
|
)
|
||||||
|
status_message_manager.add(id_)
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
raise IgnoredException("此功能正在维护...")
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_preprocessor, IgnoredException
|
||||||
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
)
|
||||||
|
from configs.config import Config
|
||||||
|
from models.ban_user import BanUser
|
||||||
|
from utils.utils import is_number, static_flmt, FreqLimiter
|
||||||
|
from utils.message_builder import at
|
||||||
|
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"hook",
|
||||||
|
"BAN_RESULT",
|
||||||
|
"才不会给你发消息.",
|
||||||
|
help_="对被ban用户发送的消息",
|
||||||
|
)
|
||||||
|
|
||||||
|
_flmt = FreqLimiter(300)
|
||||||
|
|
||||||
|
|
||||||
|
# 检查是否被ban
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
await BanUser.is_super_ban(event.user_id)
|
||||||
|
and str(event.user_id) not in bot.config.superusers
|
||||||
|
):
|
||||||
|
raise IgnoredException("用户处于超级黑名单中")
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if not isinstance(event, MessageEvent):
|
||||||
|
return
|
||||||
|
if matcher.type == "message" and matcher.priority not in [1, 9]:
|
||||||
|
if (
|
||||||
|
await BanUser.is_ban(event.user_id)
|
||||||
|
and str(event.user_id) not in bot.config.superusers
|
||||||
|
):
|
||||||
|
time = await BanUser.check_ban_time(event.user_id)
|
||||||
|
if is_number(time):
|
||||||
|
time = abs(int(time))
|
||||||
|
if time < 60:
|
||||||
|
time = str(time) + " 秒"
|
||||||
|
else:
|
||||||
|
time = str(int(time / 60)) + " 分钟"
|
||||||
|
else:
|
||||||
|
time = str(time) + " 分钟"
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
if not static_flmt.check(event.user_id):
|
||||||
|
raise IgnoredException("用户处于黑名单中")
|
||||||
|
static_flmt.start_cd(event.user_id)
|
||||||
|
if matcher.priority != 9:
|
||||||
|
try:
|
||||||
|
ban_result = Config.get_config("hook", "BAN_RESULT")
|
||||||
|
if ban_result and _flmt.check(event.user_id):
|
||||||
|
_flmt.start_cd(event.user_id)
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id,
|
||||||
|
message=at(event.user_id)
|
||||||
|
+ ban_result
|
||||||
|
+ f" 在..在 {time} 后才会理你喔",
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if not static_flmt.check(event.user_id):
|
||||||
|
raise IgnoredException("用户处于黑名单中")
|
||||||
|
static_flmt.start_cd(event.user_id)
|
||||||
|
if matcher.priority != 9:
|
||||||
|
try:
|
||||||
|
ban_result = Config.get_config("hook", "BAN_RESULT")
|
||||||
|
if ban_result:
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=event.user_id,
|
||||||
|
message=at(event.user_id)
|
||||||
|
+ ban_result
|
||||||
|
+ f" 在..在 {time}后才会理你喔",
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
raise IgnoredException("用户处于黑名单中")
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_preprocessor, IgnoredException
|
||||||
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
)
|
||||||
|
from configs.config import Config
|
||||||
|
from models.ban_user import BanUser
|
||||||
|
from utils.utils import BanCheckLimiter
|
||||||
|
from utils.message_builder import at
|
||||||
|
from services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
_blmt = BanCheckLimiter(
|
||||||
|
Config.get_config("hook", "MALICIOUS_CHECK_TIME"),
|
||||||
|
Config.get_config("hook", "MALICIOUS_BAN_COUNT"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# 恶意触发命令检测
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
if not isinstance(event, MessageEvent):
|
||||||
|
return
|
||||||
|
if matcher.type == "message" and matcher.priority not in [1, 9]:
|
||||||
|
if state["_prefix"]["raw_command"]:
|
||||||
|
if _blmt.check(f'{event.user_id}{state["_prefix"]["raw_command"]}'):
|
||||||
|
if await BanUser.ban(
|
||||||
|
event.user_id,
|
||||||
|
9,
|
||||||
|
Config.get_config("hook", "MALICIOUS_BAN_TIME") * 60,
|
||||||
|
):
|
||||||
|
logger.info(f"USER {event.user_id} 触发了恶意触发检测")
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
try:
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id,
|
||||||
|
message=at(event.user_id) + "检测到恶意触发命令,您将被封禁 30 分钟",
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=event.user_id,
|
||||||
|
message=at(event.user_id) + "检测到恶意触发命令,您将被封禁 30 分钟",
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
raise IgnoredException("检测到恶意触发命令")
|
||||||
|
_blmt.add(f'{event.user_id}{state["_prefix"]["raw_command"]}')
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
|
||||||
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
from models.friend_user import FriendUser
|
||||||
|
from models.group_member_info import GroupInfoUser
|
||||||
|
from utils.message_builder import at
|
||||||
|
from .utils import status_message_manager, set_block_limit_false
|
||||||
|
from utils.manager import (
|
||||||
|
plugins2cd_manager,
|
||||||
|
plugins2block_manager,
|
||||||
|
plugins2count_manager,
|
||||||
|
)
|
||||||
|
from typing import Optional
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
Event,
|
||||||
|
MessageEvent,
|
||||||
|
PrivateMessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
Message,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# 命令cd | 命令阻塞 | 命令次数
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
if not isinstance(event, MessageEvent) and matcher.module != "poke":
|
||||||
|
return
|
||||||
|
module = matcher.module
|
||||||
|
if (
|
||||||
|
isinstance(event, GroupMessageEvent)
|
||||||
|
and status_message_manager.get(event.group_id) is None
|
||||||
|
):
|
||||||
|
status_message_manager.delete(event.group_id)
|
||||||
|
# Count
|
||||||
|
if (
|
||||||
|
plugins2count_manager.check_plugin_count_status(module)
|
||||||
|
and event.user_id not in bot.config.superusers
|
||||||
|
):
|
||||||
|
plugin_count_data = plugins2count_manager.get_plugin_count_data(module)
|
||||||
|
limit_type = plugin_count_data["limit_type"]
|
||||||
|
rst = plugin_count_data["rst"]
|
||||||
|
count_type_ = event.user_id
|
||||||
|
if limit_type == "group" and isinstance(event, GroupMessageEvent):
|
||||||
|
count_type_ = event.group_id
|
||||||
|
if not plugins2count_manager.check(module, count_type_):
|
||||||
|
if rst:
|
||||||
|
rst = await init_rst(rst, event)
|
||||||
|
await send_msg(rst, bot, event)
|
||||||
|
raise IgnoredException(f"{module} count次数限制...")
|
||||||
|
else:
|
||||||
|
plugins2count_manager.increase(module, count_type_)
|
||||||
|
# Cd
|
||||||
|
if plugins2cd_manager.check_plugin_cd_status(module):
|
||||||
|
plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module)
|
||||||
|
check_type = plugin_cd_data["check_type"]
|
||||||
|
limit_type = plugin_cd_data["limit_type"]
|
||||||
|
rst = plugin_cd_data["rst"]
|
||||||
|
if (
|
||||||
|
(isinstance(event, PrivateMessageEvent) and check_type == "private")
|
||||||
|
or (isinstance(event, GroupMessageEvent) and check_type == "group")
|
||||||
|
or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all"
|
||||||
|
):
|
||||||
|
cd_type_ = event.user_id
|
||||||
|
if limit_type == "group" and isinstance(event, GroupMessageEvent):
|
||||||
|
cd_type_ = event.group_id
|
||||||
|
if not plugins2cd_manager.check(module, cd_type_):
|
||||||
|
if rst:
|
||||||
|
rst = await init_rst(rst, event)
|
||||||
|
await send_msg(rst, bot, event)
|
||||||
|
raise IgnoredException(f"{module} 正在cd中...")
|
||||||
|
else:
|
||||||
|
plugins2cd_manager.start_cd(module, cd_type_)
|
||||||
|
# Block
|
||||||
|
if plugins2block_manager.check_plugin_block_status(module):
|
||||||
|
plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
|
||||||
|
check_type = plugin_block_data["check_type"]
|
||||||
|
limit_type = plugin_block_data["limit_type"]
|
||||||
|
rst = plugin_block_data["rst"]
|
||||||
|
if (
|
||||||
|
(isinstance(event, PrivateMessageEvent) and check_type == "private")
|
||||||
|
or (isinstance(event, GroupMessageEvent) and check_type == "group")
|
||||||
|
or check_type == "all"
|
||||||
|
):
|
||||||
|
block_type_ = event.user_id
|
||||||
|
if limit_type == "group" and isinstance(event, GroupMessageEvent):
|
||||||
|
block_type_ = event.group_id
|
||||||
|
if plugins2block_manager.check(block_type_, module):
|
||||||
|
if rst:
|
||||||
|
rst = await init_rst(rst, event)
|
||||||
|
await send_msg(rst, bot, event)
|
||||||
|
raise IgnoredException(f"{event.user_id}正在调用{module}....")
|
||||||
|
else:
|
||||||
|
plugins2block_manager.set_true(block_type_, module)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_msg(rst: str, bot: Bot, event: MessageEvent):
|
||||||
|
"""
|
||||||
|
发送信息
|
||||||
|
:param rst: pass
|
||||||
|
:param bot: pass
|
||||||
|
:param event: pass
|
||||||
|
"""
|
||||||
|
rst = await init_rst(rst, event)
|
||||||
|
try:
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
status_message_manager.add(event.group_id)
|
||||||
|
await bot.send_group_msg(group_id=event.group_id, message=Message(rst))
|
||||||
|
else:
|
||||||
|
status_message_manager.add(event.user_id)
|
||||||
|
await bot.send_private_msg(user_id=event.user_id, message=Message(rst))
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# 解除命令block阻塞
|
||||||
|
@run_postprocessor
|
||||||
|
async def _(
|
||||||
|
matcher: Matcher,
|
||||||
|
exception: Optional[Exception],
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
):
|
||||||
|
if not isinstance(event, MessageEvent) and matcher.module != "poke":
|
||||||
|
return
|
||||||
|
module = matcher.module
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
|
||||||
|
|
||||||
|
async def init_rst(rst: str, event: MessageEvent):
|
||||||
|
if "[uname]" in rst:
|
||||||
|
uname = event.sender.card if event.sender.card else event.sender.nickname
|
||||||
|
rst = rst.replace("[uname]", uname)
|
||||||
|
if "[nickname]" in rst:
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
nickname = await GroupInfoUser.get_group_member_nickname(
|
||||||
|
event.user_id, event.group_id
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
nickname = await FriendUser.get_friend_nickname(event.user_id)
|
||||||
|
rst = rst.replace("[nickname]", nickname)
|
||||||
|
if "[at]" in rst and isinstance(event, GroupMessageEvent):
|
||||||
|
rst = rst.replace("[at]", str(at(event.user_id)))
|
||||||
|
return rst
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_preprocessor, IgnoredException
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from .utils import status_message_manager
|
||||||
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
PrivateMessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# 为什么AI会自己和自己聊天
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: PrivateMessageEvent, state: T_State):
|
||||||
|
if not isinstance(event, MessageEvent):
|
||||||
|
return
|
||||||
|
if event.user_id == int(bot.self_id):
|
||||||
|
raise IgnoredException("为什么AI会自己和自己聊天")
|
||||||
|
|
||||||
|
|
||||||
|
# 有命令就别说话了
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
if not isinstance(event, MessageEvent):
|
||||||
|
return
|
||||||
|
if matcher.type == "message" and matcher.module == "ai":
|
||||||
|
if (
|
||||||
|
isinstance(event, GroupMessageEvent)
|
||||||
|
and not status_message_manager.check(event.group_id)
|
||||||
|
):
|
||||||
|
status_message_manager.delete(event.group_id)
|
||||||
|
raise IgnoredException("有命令就别说话了")
|
||||||
|
elif (
|
||||||
|
isinstance(event, PrivateMessageEvent)
|
||||||
|
and not status_message_manager.check(event.user_id)
|
||||||
|
):
|
||||||
|
print(status_message_manager)
|
||||||
|
status_message_manager.delete(event.user_id)
|
||||||
|
raise IgnoredException("有命令就别说话了")
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
from nonebot.adapters.cqhttp import GroupMessageEvent, PrivateMessageEvent
|
||||||
|
from utils.manager import plugins2block_manager, StaticData
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class StatusMessageManager(StaticData):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(None)
|
||||||
|
|
||||||
|
def add(self, id_: int):
|
||||||
|
self._data[id_] = time.time()
|
||||||
|
|
||||||
|
def delete(self, id_: int):
|
||||||
|
if self._data.get(id_):
|
||||||
|
del self._data[id_]
|
||||||
|
|
||||||
|
def check(self, id_: int, t: int = 30) -> bool:
|
||||||
|
if self._data.get(id_):
|
||||||
|
if time.time() - self._data[id_] > t:
|
||||||
|
del self._data[id_]
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
status_message_manager = StatusMessageManager()
|
||||||
|
|
||||||
|
|
||||||
|
def set_block_limit_false(event, module):
|
||||||
|
"""
|
||||||
|
设置用户block为false
|
||||||
|
:param event: event
|
||||||
|
:param module: 插件模块
|
||||||
|
"""
|
||||||
|
if plugins2block_manager.check_plugin_block_status(module):
|
||||||
|
plugin_block_data = plugins2block_manager.get_plugin_block_data(module)
|
||||||
|
check_type = plugin_block_data["check_type"]
|
||||||
|
limit_type = plugin_block_data["limit_type"]
|
||||||
|
if not (
|
||||||
|
(isinstance(event, GroupMessageEvent) and check_type == "private")
|
||||||
|
or (isinstance(event, PrivateMessageEvent) and check_type == "group")
|
||||||
|
):
|
||||||
|
block_type_ = event.user_id
|
||||||
|
if limit_type == "group" and isinstance(event, GroupMessageEvent):
|
||||||
|
block_type_ = event.group_id
|
||||||
|
plugins2block_manager.set_false(block_type_, module)
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_postprocessor
|
||||||
|
from typing import Optional
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, Event
|
||||||
|
from utils.manager import withdraw_message_manager
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
|
# 消息撤回
|
||||||
|
@run_postprocessor
|
||||||
|
async def _(
|
||||||
|
matcher: Matcher,
|
||||||
|
exception: Optional[Exception],
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
):
|
||||||
|
tasks = []
|
||||||
|
for id_, time in withdraw_message_manager.data:
|
||||||
|
tasks.append(asyncio.ensure_future(_withdraw_message(bot, id_, time)))
|
||||||
|
withdraw_message_manager.remove((id_, time))
|
||||||
|
await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
|
||||||
|
async def _withdraw_message(bot: Bot, id_: int, time: int):
|
||||||
|
await asyncio.sleep(time)
|
||||||
|
await bot.delete_msg(message_id=id_, self_id=int(bot.self_id))
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
from .init_group_manager import init_group_manager, group_manager
|
||||||
|
from .init_plugins_config import init_plugins_config
|
||||||
|
from .init_plugins_data import init_plugins_data, plugins_manager
|
||||||
|
from .init_none_plugin_count_manager import init_none_plugin_count_manager
|
||||||
|
from .init_plugins_resources import init_plugins_resources
|
||||||
|
from .init_plugins_settings import init_plugins_settings
|
||||||
|
from .init_plugins_limit import (
|
||||||
|
init_plugins_block_limit,
|
||||||
|
init_plugins_count_limit,
|
||||||
|
init_plugins_cd_limit,
|
||||||
|
)
|
||||||
|
from .init import init
|
||||||
|
from .check_plugin_status import check_plugin_status
|
||||||
|
from utils.manager import admin_manager
|
||||||
|
from nonebot.adapters.cqhttp import Bot
|
||||||
|
from configs.path_config import DATA_PATH
|
||||||
|
from services.log import logger
|
||||||
|
from pathlib import Path
|
||||||
|
from nonebot import Driver
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "初始化插件数据 [Hidden]"
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
def _():
|
||||||
|
"""
|
||||||
|
初始化数据
|
||||||
|
"""
|
||||||
|
_flag = False
|
||||||
|
config_file = Path(DATA_PATH) / "configs" / "plugins2config.yaml"
|
||||||
|
if not config_file.exists():
|
||||||
|
_flag = True
|
||||||
|
init()
|
||||||
|
init_plugins_settings(DATA_PATH)
|
||||||
|
init_plugins_cd_limit(DATA_PATH)
|
||||||
|
init_plugins_block_limit(DATA_PATH)
|
||||||
|
init_plugins_count_limit(DATA_PATH)
|
||||||
|
init_plugins_data(DATA_PATH)
|
||||||
|
init_plugins_config(DATA_PATH)
|
||||||
|
init_plugins_resources()
|
||||||
|
init_none_plugin_count_manager()
|
||||||
|
x = group_manager.get_super_old_data()
|
||||||
|
if x:
|
||||||
|
for key in x.keys():
|
||||||
|
plugins_manager.block_plugin(key, block_type=x[key])
|
||||||
|
if _flag:
|
||||||
|
raise Exception("首次运行,已在configs目录下生成配置文件config.yaml,修改后重启即可...")
|
||||||
|
logger.info("初始化数据完成...")
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_bot_connect
|
||||||
|
async def _(bot: Bot):
|
||||||
|
await init_group_manager()
|
||||||
|
await check_plugin_status(bot)
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from utils.manager import plugins_manager
|
||||||
|
from nonebot.adapters.cqhttp import Bot
|
||||||
|
|
||||||
|
|
||||||
|
async def check_plugin_status(bot: Bot):
|
||||||
|
"""
|
||||||
|
遍历查看插件加载情况
|
||||||
|
"""
|
||||||
|
rst = ""
|
||||||
|
for plugin in plugins_manager.keys():
|
||||||
|
data = plugins_manager.get(plugin)
|
||||||
|
if data.get("error") or data.get("error") is None:
|
||||||
|
rst += f'{plugin}:{data["plugin_name"]}\n'
|
||||||
|
if rst:
|
||||||
|
rst = "以下插件加载失败..\n" + rst
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]), message=rst[:-1]
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
from utils.manager import plugins2settings_manager
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
if plugins2settings_manager.get("update_pic"):
|
||||||
|
plugins2settings_manager["update_picture"] = plugins2settings_manager["update_pic"]
|
||||||
|
plugins2settings_manager.delete("update_pic")
|
||||||
|
if plugins2settings_manager.get("white2black_img"):
|
||||||
|
plugins2settings_manager["white2black_image"] = plugins2settings_manager["white2black_img"]
|
||||||
|
plugins2settings_manager.delete("white2black_img")
|
||||||
|
if plugins2settings_manager.get("send_img"):
|
||||||
|
plugins2settings_manager["send_image"] = plugins2settings_manager["send_img"]
|
||||||
|
plugins2settings_manager.delete("send_img")
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from utils.manager import group_manager
|
||||||
|
from services.db_context import db
|
||||||
|
from asyncpg.exceptions import DuplicateColumnError
|
||||||
|
from services.log import logger
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ujson as json
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
import json
|
||||||
|
try:
|
||||||
|
from models.group_remind import GroupRemind
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
async def init_group_manager():
|
||||||
|
"""
|
||||||
|
旧数据格式替换为新格式
|
||||||
|
初始化数据
|
||||||
|
"""
|
||||||
|
old_group_level_file = Path() / "data" / "manager" / "group_level.json"
|
||||||
|
old_plugin_list_file = Path() / "data" / "manager" / "plugin_list.json"
|
||||||
|
if old_group_level_file.exists():
|
||||||
|
data = json.load(open(old_group_level_file, "r", encoding="utf8"))
|
||||||
|
for key in data.keys():
|
||||||
|
group = key
|
||||||
|
level = data[key]
|
||||||
|
group_manager.set_group_level(group, level)
|
||||||
|
old_group_level_file.unlink()
|
||||||
|
group_manager.save()
|
||||||
|
|
||||||
|
if old_plugin_list_file.exists():
|
||||||
|
data = json.load(open(old_plugin_list_file, "r", encoding="utf8"))
|
||||||
|
for plugin in data.keys():
|
||||||
|
for group in data[plugin].keys():
|
||||||
|
if group == "default" and not data[plugin]["default"]:
|
||||||
|
group_manager.block_plugin(plugin)
|
||||||
|
elif not data[plugin][group]:
|
||||||
|
group_manager.block_plugin(plugin, group)
|
||||||
|
old_plugin_list_file.unlink()
|
||||||
|
old_data_table = Path() / "models" / "group_remind.py"
|
||||||
|
try:
|
||||||
|
if old_data_table.exists():
|
||||||
|
b = {
|
||||||
|
"hy": "group_welcome",
|
||||||
|
"kxcz": "open_case_reset_remind",
|
||||||
|
"zwa": "zwa",
|
||||||
|
"blpar": "bilibili_parse",
|
||||||
|
"epic": "epic_free_game",
|
||||||
|
"pa": "pa",
|
||||||
|
"almanac": "genshin_alc",
|
||||||
|
}
|
||||||
|
for group in group_manager.get_data()["group_manager"]:
|
||||||
|
for remind in b:
|
||||||
|
try:
|
||||||
|
status = await GroupRemind.get_status(int(group), remind)
|
||||||
|
if status is not None:
|
||||||
|
if status:
|
||||||
|
await group_manager.open_group_task(group, b[remind])
|
||||||
|
logger.info(f"读取旧数据-->{group} 开启 {b[remind]}")
|
||||||
|
else:
|
||||||
|
await group_manager.close_group_task(group, b[remind])
|
||||||
|
logger.info(f"读取旧数据-->{group} 关闭 {b[remind]}")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
query = db.text("DROP TABLE group_reminds;")
|
||||||
|
await db.first(query)
|
||||||
|
old_data_table.unlink()
|
||||||
|
logger.info("旧数据读取完毕,删除了舍弃表 group_reminds...")
|
||||||
|
except (ModuleNotFoundError, DuplicateColumnError):
|
||||||
|
pass
|
||||||
|
group_manager.save()
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
from utils.manager import (
|
||||||
|
none_plugin_count_manager,
|
||||||
|
plugins2count_manager,
|
||||||
|
plugins2cd_manager,
|
||||||
|
plugins2settings_manager,
|
||||||
|
plugins2block_manager,
|
||||||
|
plugins_manager,
|
||||||
|
resources_manager
|
||||||
|
)
|
||||||
|
from services.log import logger
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ujson as json
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def init_none_plugin_count_manager():
|
||||||
|
"""
|
||||||
|
清除已删除插件数据
|
||||||
|
"""
|
||||||
|
modules = [x.module for x in get_matchers()]
|
||||||
|
for module in none_plugin_count_manager.keys():
|
||||||
|
if module not in modules:
|
||||||
|
none_plugin_count_manager.add_count(module)
|
||||||
|
else:
|
||||||
|
none_plugin_count_manager.reset(module)
|
||||||
|
if none_plugin_count_manager.check(module):
|
||||||
|
try:
|
||||||
|
plugin_name = plugins_manager.get(module)["plugin_name"]
|
||||||
|
except (AttributeError, KeyError):
|
||||||
|
plugin_name = ""
|
||||||
|
try:
|
||||||
|
plugins2settings_manager.delete(module)
|
||||||
|
plugins2count_manager.delete(module)
|
||||||
|
plugins2cd_manager.delete(module)
|
||||||
|
plugins2block_manager.delete(module)
|
||||||
|
plugins_manager.delete(module)
|
||||||
|
resources_manager.remove_resource(module)
|
||||||
|
logger.info(f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据...")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据失败...{type(e)}:{e}"
|
||||||
|
)
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from ruamel.yaml import round_trip_load, round_trip_dump, YAML
|
||||||
|
from utils.manager import admin_manager, plugins_manager
|
||||||
|
from configs.config import Config
|
||||||
|
from services.log import logger
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
from ruamel import yaml
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
_yaml = YAML(typ="safe")
|
||||||
|
|
||||||
|
|
||||||
|
def init_plugins_config(data_path):
|
||||||
|
"""
|
||||||
|
初始化插件数据配置
|
||||||
|
"""
|
||||||
|
plugins2config_file = Path(data_path) / "configs" / "plugins2config.yaml"
|
||||||
|
plugins2config_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
_data = {}
|
||||||
|
if plugins2config_file.exists():
|
||||||
|
_data = _yaml.load(open(plugins2config_file, "r", encoding="utf8"))
|
||||||
|
_matchers = get_matchers()
|
||||||
|
for matcher in _matchers:
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
plugin_version = _module.__getattribute__("__plugin_version__")
|
||||||
|
except AttributeError:
|
||||||
|
plugin_version = None
|
||||||
|
try:
|
||||||
|
plugin_configs = _module.__getattribute__("__plugin_configs__")
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
# 插件配置版本更新或为Version为None或不在存储配置内
|
||||||
|
if (
|
||||||
|
plugin_version is None
|
||||||
|
or (
|
||||||
|
_data.get(matcher.module)
|
||||||
|
and _data[matcher.module].keys() != plugin_configs.keys()
|
||||||
|
)
|
||||||
|
or plugin_version > plugins_manager.get(matcher.module)["version"]
|
||||||
|
or matcher.module not in _data.keys()
|
||||||
|
):
|
||||||
|
for key in plugin_configs:
|
||||||
|
if isinstance(plugin_configs[key], dict):
|
||||||
|
Config.add_plugin_config(
|
||||||
|
matcher.module,
|
||||||
|
key,
|
||||||
|
plugin_configs[key].get("value"),
|
||||||
|
help_=plugin_configs[key].get("help"),
|
||||||
|
default_value=plugin_configs[key].get("default_value"),
|
||||||
|
_override=True,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
Config.add_plugin_config(matcher.module, key, plugin_configs[key])
|
||||||
|
else:
|
||||||
|
plugin_configs = _data[matcher.module]
|
||||||
|
for key in plugin_configs:
|
||||||
|
Config.add_plugin_config(
|
||||||
|
matcher.module,
|
||||||
|
key,
|
||||||
|
plugin_configs[key]["value"],
|
||||||
|
help_=plugin_configs[key]["help"],
|
||||||
|
default_value=plugin_configs[key]["default_value"],
|
||||||
|
_override=True,
|
||||||
|
)
|
||||||
|
if not Config.is_empty():
|
||||||
|
Config.save()
|
||||||
|
_data = round_trip_load(open(plugins2config_file, encoding="utf8"))
|
||||||
|
for plugin in _data.keys():
|
||||||
|
try:
|
||||||
|
plugin_name = plugins_manager.get(plugin)["plugin_name"]
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
plugin_name = plugin
|
||||||
|
_data[plugin].yaml_set_start_comment(plugin_name, indent=2)
|
||||||
|
# 初始化未设置的管理员权限等级
|
||||||
|
for k, v in Config.get_admin_level_data():
|
||||||
|
admin_manager.set_admin_level(k, v)
|
||||||
|
# 存完插件基本设置
|
||||||
|
with open(plugins2config_file, "w", encoding="utf8") as wf:
|
||||||
|
round_trip_dump(
|
||||||
|
_data, wf, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True
|
||||||
|
)
|
||||||
|
# 再开始读取用户配置
|
||||||
|
user_config_file = Path() / "configs" / "config.yaml"
|
||||||
|
_data = {}
|
||||||
|
_tmp_data = {}
|
||||||
|
if user_config_file.exists():
|
||||||
|
with open(user_config_file, "r", encoding="utf8") as f:
|
||||||
|
_data = _yaml.load(f)
|
||||||
|
# 数据替换
|
||||||
|
for plugin in Config.keys():
|
||||||
|
_tmp_data[plugin] = {}
|
||||||
|
for k in Config[plugin].keys():
|
||||||
|
if _data.get(plugin) and k in _data[plugin].keys():
|
||||||
|
Config.set_config(plugin, k, _data[plugin][k])
|
||||||
|
if level2module := Config.get_level2module(plugin, k):
|
||||||
|
admin_manager.set_admin_level(level2module, _data[plugin][k])
|
||||||
|
_tmp_data[plugin][k] = Config.get_config(plugin, k)
|
||||||
|
Config.save()
|
||||||
|
temp_file = Path() / "configs" / "temp_config.yaml"
|
||||||
|
try:
|
||||||
|
with open(temp_file, "w", encoding="utf8") as wf:
|
||||||
|
yaml.dump(
|
||||||
|
_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True
|
||||||
|
)
|
||||||
|
with open(temp_file, "r", encoding="utf8") as rf:
|
||||||
|
_data = round_trip_load(rf)
|
||||||
|
# 添加注释
|
||||||
|
for plugin in _data.keys():
|
||||||
|
rst = ""
|
||||||
|
plugin_name = None
|
||||||
|
try:
|
||||||
|
plugin_data = Config.get(plugin)
|
||||||
|
for x in list(Config.get(plugin).keys()):
|
||||||
|
try:
|
||||||
|
_x = plugin_data[x].get("name")
|
||||||
|
if _x:
|
||||||
|
plugin_name = _x
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except (KeyError, AttributeError):
|
||||||
|
plugin_name = None
|
||||||
|
if not plugin_name:
|
||||||
|
try:
|
||||||
|
plugin_name = plugins_manager.get(plugin)["plugin_name"]
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
plugin_name = plugin
|
||||||
|
plugin_name = (
|
||||||
|
plugin_name.replace("[Hidden]", "")
|
||||||
|
.replace("[Superuser]", "")
|
||||||
|
.replace("[Admin]", "")
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
rst += plugin_name + "\n"
|
||||||
|
for k in _data[plugin].keys():
|
||||||
|
rst += f'{k}: {Config[plugin][k]["help"]}' + "\n"
|
||||||
|
_data[plugin].yaml_set_start_comment(rst[:-1], indent=2)
|
||||||
|
with open(Path() / "configs" / "config.yaml", "w", encoding="utf8") as wf:
|
||||||
|
round_trip_dump(
|
||||||
|
_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"生成简易配置注释错误 {type(e)}:{e}")
|
||||||
|
if temp_file.exists():
|
||||||
|
temp_file.unlink()
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
from utils.manager import plugins_manager
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ujson as json
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
_yaml = YAML(typ="safe")
|
||||||
|
|
||||||
|
|
||||||
|
def init_plugins_data(data_path):
|
||||||
|
"""
|
||||||
|
初始化插件数据信息
|
||||||
|
"""
|
||||||
|
plugin2data_file = Path(data_path) / "manager" / "plugin_manager.json"
|
||||||
|
plugin2data_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
_data = {}
|
||||||
|
if plugin2data_file.exists():
|
||||||
|
_data = json.load(open(plugin2data_file, "r", encoding="utf8"))
|
||||||
|
_matchers = get_matchers()
|
||||||
|
for matcher in _matchers:
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
if matcher.module not in _data.keys():
|
||||||
|
plugins_manager.add_plugin_data(
|
||||||
|
matcher.module, matcher.module, error=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
plugins_manager.set_module_data(matcher.module, "error", True)
|
||||||
|
plugin_data = plugins_manager.get(matcher.module)
|
||||||
|
if plugin_data:
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.module, "version", plugin_data.get("version")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
plugin_version = _module.__getattribute__("__plugin_version__")
|
||||||
|
except AttributeError:
|
||||||
|
plugin_version = None
|
||||||
|
try:
|
||||||
|
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||||
|
except AttributeError:
|
||||||
|
plugin_name = matcher.module
|
||||||
|
try:
|
||||||
|
plugin_author = _module.__getattribute__("__plugin_author__")
|
||||||
|
except AttributeError:
|
||||||
|
plugin_author = None
|
||||||
|
if matcher.module in plugins_manager.keys():
|
||||||
|
plugins_manager.set_module_data(matcher.module, "error", False)
|
||||||
|
if matcher.module not in plugins_manager.keys():
|
||||||
|
plugins_manager.add_plugin_data(
|
||||||
|
matcher.module,
|
||||||
|
plugin_name=plugin_name,
|
||||||
|
author=plugin_author,
|
||||||
|
version=plugin_version,
|
||||||
|
)
|
||||||
|
elif plugins_manager[matcher.module]["version"] is None or (
|
||||||
|
plugin_version is not None
|
||||||
|
and plugin_version > plugins_manager[matcher.module]["version"]
|
||||||
|
):
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.module, "plugin_name", plugin_name
|
||||||
|
)
|
||||||
|
plugins_manager.set_module_data(matcher.module, "author", plugin_author)
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.module, "version", plugin_version
|
||||||
|
)
|
||||||
|
if matcher.module in _data.keys():
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.module, "error", _data[matcher.module]["error"]
|
||||||
|
)
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.module, "plugin_name", _data[matcher.module]["plugin_name"]
|
||||||
|
)
|
||||||
|
plugins_manager.save()
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from ruamel.yaml import round_trip_load, round_trip_dump, YAML
|
||||||
|
from utils.manager import (
|
||||||
|
plugins2cd_manager,
|
||||||
|
plugins2block_manager,
|
||||||
|
plugins2count_manager,
|
||||||
|
)
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
from ruamel import yaml
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
_yaml = YAML(typ="safe")
|
||||||
|
|
||||||
|
|
||||||
|
def init_plugins_cd_limit(data_path):
|
||||||
|
"""
|
||||||
|
加载 cd 限制
|
||||||
|
"""
|
||||||
|
plugins2cd_file = Path(data_path) / "configs" / "plugins2cd.yaml"
|
||||||
|
plugins2cd_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
_data = {}
|
||||||
|
_matchers = get_matchers()
|
||||||
|
for matcher in _matchers:
|
||||||
|
if not plugins2cd_manager.get_plugin_cd_data(matcher.module):
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_cd_limit = _module.__getattribute__("__plugin_cd_limit__")
|
||||||
|
plugins2cd_manager.add_cd_limit(
|
||||||
|
matcher.module, data_dict=plugin_cd_limit
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if not plugins2cd_manager.keys():
|
||||||
|
plugins2cd_manager.add_cd_limit(
|
||||||
|
"这是一个示例"
|
||||||
|
)
|
||||||
|
_tmp_data = {"PluginCdLimit": plugins2cd_manager.get_data()}
|
||||||
|
with open(plugins2cd_file, "w", encoding="utf8") as wf:
|
||||||
|
yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
_data = round_trip_load(open(plugins2cd_file, encoding="utf8"))
|
||||||
|
_data["PluginCdLimit"].yaml_set_start_comment(
|
||||||
|
"""# 需要cd的功能
|
||||||
|
# 自定义的功能需要cd也可以在此配置
|
||||||
|
# key:模块名称
|
||||||
|
# cd:cd 时长(秒)
|
||||||
|
# status:此限制的开关状态
|
||||||
|
# check_type:'private'/'group'/'all',限制私聊/群聊/全部
|
||||||
|
# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
||||||
|
# 示例:'user':用户N秒内触发1次,'group':群N秒内触发1次
|
||||||
|
# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
|
||||||
|
# rst 为 "" 或 None 时则不回复
|
||||||
|
# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
|
||||||
|
# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
|
||||||
|
# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
with open(plugins2cd_file, "w", encoding="utf8") as wf:
|
||||||
|
round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
plugins2cd_manager.reload_cd_limit()
|
||||||
|
|
||||||
|
|
||||||
|
def init_plugins_block_limit(data_path):
|
||||||
|
"""
|
||||||
|
加载阻塞限制
|
||||||
|
"""
|
||||||
|
plugins2block_file = Path(data_path) / "configs" / "plugins2block.yaml"
|
||||||
|
plugins2block_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
_data = {}
|
||||||
|
_matchers = get_matchers()
|
||||||
|
for matcher in _matchers:
|
||||||
|
if not plugins2block_manager.get_plugin_block_data(matcher.module):
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_block_limit = _module.__getattribute__("__plugin_block_limit__")
|
||||||
|
plugins2block_manager.add_block_limit(
|
||||||
|
matcher.module, data_dict=plugin_block_limit
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if not plugins2block_manager.keys():
|
||||||
|
plugins2block_manager.add_block_limit(
|
||||||
|
"这是一个示例"
|
||||||
|
)
|
||||||
|
_tmp_data = {"PluginBlockLimit": plugins2block_manager.get_data()}
|
||||||
|
with open(plugins2block_file, "w", encoding="utf8") as wf:
|
||||||
|
yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
_data = round_trip_load(open(plugins2block_file, encoding="utf8"))
|
||||||
|
_data["PluginBlockLimit"].yaml_set_start_comment(
|
||||||
|
"""# 用户调用阻塞
|
||||||
|
# 即 当用户调用此功能还未结束时
|
||||||
|
# 用发送消息阻止用户重复调用此命令直到该命令结束
|
||||||
|
# key:模块名称
|
||||||
|
# status:此限制的开关状态
|
||||||
|
# check_type:'private'/'group'/'all',限制私聊/群聊/全部
|
||||||
|
# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
||||||
|
# 示例:'user':阻塞用户,'group':阻塞群聊
|
||||||
|
# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
|
||||||
|
# rst 为 "" 或 None 时则不回复
|
||||||
|
# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
|
||||||
|
# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
|
||||||
|
# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
with open(plugins2block_file, "w", encoding="utf8") as wf:
|
||||||
|
round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
plugins2block_manager.reload_block_limit()
|
||||||
|
|
||||||
|
|
||||||
|
def init_plugins_count_limit(data_path):
|
||||||
|
"""
|
||||||
|
加载次数限制
|
||||||
|
"""
|
||||||
|
plugins2count_file = Path(data_path) / "configs" / "plugins2count.yaml"
|
||||||
|
plugins2count_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
_data = {}
|
||||||
|
_matchers = get_matchers()
|
||||||
|
for matcher in _matchers:
|
||||||
|
if not plugins2count_manager.get_plugin_count_data(matcher.module):
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_count_limit = _module.__getattribute__("__plugin_count_limit__")
|
||||||
|
plugins2count_manager.add_count_limit(
|
||||||
|
matcher.module, data_dict=plugin_count_limit
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if not plugins2count_manager.keys():
|
||||||
|
plugins2count_manager.add_count_limit(
|
||||||
|
"这是一个示例"
|
||||||
|
)
|
||||||
|
_tmp_data = {"PluginCountLimit": plugins2count_manager.get_data()}
|
||||||
|
with open(plugins2count_file, "w", encoding="utf8") as wf:
|
||||||
|
yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
_data = round_trip_load(open(plugins2count_file, encoding="utf8"))
|
||||||
|
_data["PluginCountLimit"].yaml_set_start_comment(
|
||||||
|
"""# 命令每日次数限制
|
||||||
|
# 即 用户/群聊 每日可调用命令的次数 [数据内存存储,重启将会重置]
|
||||||
|
# 每日调用直到 00:00 刷新
|
||||||
|
# key:模块名称
|
||||||
|
# max_count: 每日调用上限
|
||||||
|
# status:此限制的开关状态
|
||||||
|
# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
||||||
|
# 示例:'user':用户上限,'group':群聊上限
|
||||||
|
# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
|
||||||
|
# rst 为 "" 或 None 时则不回复
|
||||||
|
# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
|
||||||
|
# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
|
||||||
|
# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑""",
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
with open(plugins2count_file, "w", encoding="utf8") as wf:
|
||||||
|
round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
plugins2count_manager.reload_count_limit()
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
from utils.manager import resources_manager
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
from services.log import logger
|
||||||
|
from pathlib import Path
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
def init_plugins_resources():
|
||||||
|
"""
|
||||||
|
资源文件路径的移动
|
||||||
|
"""
|
||||||
|
_tmp = []
|
||||||
|
for matcher in get_matchers():
|
||||||
|
if matcher.module not in _tmp:
|
||||||
|
_tmp.append(matcher.module)
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
logger.warning(f"插件 {matcher.module} 加载失败...,资源控制未加载...")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
resources = _module.__getattribute__("__plugin_resources__")
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
path = Path(_module.__getattribute__("__file__")).parent
|
||||||
|
for resource in resources.keys():
|
||||||
|
resources_manager.add_resource(matcher.module, (path / resource).absolute(), resources[resource])
|
||||||
|
resources_manager.save()
|
||||||
|
resources_manager.start_move()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from ruamel.yaml import round_trip_load, round_trip_dump, YAML
|
||||||
|
from utils.manager import plugins2settings_manager, admin_manager
|
||||||
|
from services.log import logger
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
from ruamel import yaml
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
_yaml = YAML(typ="safe")
|
||||||
|
|
||||||
|
|
||||||
|
def init_plugins_settings(data_path: str):
|
||||||
|
"""
|
||||||
|
初始化插件设置,从插件中获取 __zx_plugin_name__,__plugin_cmd__,__plugin_settings__
|
||||||
|
"""
|
||||||
|
plugins2settings_file = Path(data_path) / "configs" / "plugins2settings.yaml"
|
||||||
|
plugins2settings_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
_matchers = get_matchers()
|
||||||
|
_tmp_module = {}
|
||||||
|
_tmp = []
|
||||||
|
for x in plugins2settings_manager.keys():
|
||||||
|
try:
|
||||||
|
_plugin = nonebot.plugin.get_plugin(x)
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||||
|
_tmp_module[x] = plugin_name
|
||||||
|
except (KeyError, AttributeError) as e:
|
||||||
|
logger.warning(f"配置文件 模块:{x} 获取 plugin_name 失败...{e}")
|
||||||
|
_tmp_module[x] = ""
|
||||||
|
for matcher in _matchers:
|
||||||
|
if matcher.module not in plugins2settings_manager.keys():
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
logger.warning(f"插件 {matcher.module} 加载失败...,插件控制未加载.")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||||
|
if "[admin]" in plugin_name.lower():
|
||||||
|
try:
|
||||||
|
admin_settings = _module.__getattribute__(
|
||||||
|
"__plugin_settings__"
|
||||||
|
)
|
||||||
|
level = admin_settings["admin_level"]
|
||||||
|
cmd = admin_settings.get("cmd")
|
||||||
|
except (AttributeError, KeyError):
|
||||||
|
level = 5
|
||||||
|
cmd = None
|
||||||
|
if level is None:
|
||||||
|
level = 5
|
||||||
|
admin_manager.add_admin_plugin_settings(
|
||||||
|
matcher.module, cmd, level
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
"[hidden]" in plugin_name.lower()
|
||||||
|
or "[admin]" in plugin_name.lower()
|
||||||
|
or "[superuser]" in plugin_name.lower()
|
||||||
|
or matcher.module in plugins2settings_manager.keys()
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
except AttributeError:
|
||||||
|
if matcher.module not in _tmp:
|
||||||
|
logger.warning(
|
||||||
|
f"获取插件 {matcher.module} __zx_plugin_name__ 失败...,插件控制未加载."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
_tmp_module[matcher.module] = plugin_name
|
||||||
|
plugin_settings = _module.__getattribute__(
|
||||||
|
"__plugin_settings__"
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
plugin_settings["cmd"] is not None
|
||||||
|
and plugin_name not in plugin_settings["cmd"]
|
||||||
|
):
|
||||||
|
plugin_settings["cmd"].append(plugin_name)
|
||||||
|
if plugins2settings_manager.get(
|
||||||
|
matcher.module
|
||||||
|
) and plugins2settings_manager[matcher.module].get(
|
||||||
|
"plugin_type"
|
||||||
|
):
|
||||||
|
plugin_type = tuple(
|
||||||
|
plugins2settings_manager.get_plugin_data(
|
||||||
|
matcher.module
|
||||||
|
)["plugin_type"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
plugin_type = _module.__getattribute__(
|
||||||
|
"__plugin_type__"
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
plugin_type = ("normal",)
|
||||||
|
if plugin_settings and matcher.module:
|
||||||
|
plugins2settings_manager.add_plugin_settings(
|
||||||
|
matcher.module,
|
||||||
|
plugin_type=plugin_type,
|
||||||
|
data_dict=plugin_settings,
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
_tmp.append(matcher.module)
|
||||||
|
_tmp_data = {"PluginSettings": plugins2settings_manager.get_data()}
|
||||||
|
with open(plugins2settings_file, "w", encoding="utf8") as wf:
|
||||||
|
yaml.dump(_tmp_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
_data = round_trip_load(open(plugins2settings_file, encoding="utf8"))
|
||||||
|
_data["PluginSettings"].yaml_set_start_comment(
|
||||||
|
"""# 模块与对应命令和对应群权限
|
||||||
|
# 用于生成帮助图片 和 开关功能
|
||||||
|
# key:模块名称
|
||||||
|
# level:需要的群等级
|
||||||
|
# default_status:加入群时功能的默认开关状态
|
||||||
|
# limit_superuser: 功能状态是否限制超级用户
|
||||||
|
# cmd: 关闭[cmd] 都会触发命令 关闭对应功能,cmd列表第一个词为统计的功能名称
|
||||||
|
# plugin_type: 帮助类别 示例:('原神相关',) 或 ('原神相关', 1),1代表帮助命令列向排列,否则为横向排列""",
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
for plugin in _data["PluginSettings"].keys():
|
||||||
|
_data["PluginSettings"][plugin].yaml_set_start_comment(
|
||||||
|
f"{plugin}:{_tmp_module[plugin]}", indent=2
|
||||||
|
)
|
||||||
|
with open(plugins2settings_file, "w", encoding="utf8") as wf:
|
||||||
|
round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
||||||
|
logger.info(f"已成功加载 {len(plugins2settings_manager.get_data())} 个非限制插件.")
|
||||||
@@ -1,16 +1,31 @@
|
|||||||
from nonebot import on_request
|
from nonebot import on_request, on_message
|
||||||
from nonebot.adapters.cqhttp import Bot, FriendRequestEvent, GroupRequestEvent
|
from nonebot.adapters.cqhttp import (
|
||||||
|
Bot,
|
||||||
|
FriendRequestEvent,
|
||||||
|
GroupRequestEvent,
|
||||||
|
MessageEvent,
|
||||||
|
)
|
||||||
from models.friend_user import FriendUser
|
from models.friend_user import FriendUser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from configs.config import AUTO_ADD_FRIEND, NICKNAME
|
from configs.config import NICKNAME, Config
|
||||||
from nonebot.adapters.cqhttp.exception import ActionFailed
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
from utils.manager import requests_manager
|
||||||
|
from models.group_info import GroupInfo
|
||||||
from utils.utils import scheduler
|
from utils.utils import scheduler
|
||||||
|
import asyncio
|
||||||
import time
|
import time
|
||||||
|
import re
|
||||||
|
|
||||||
__plugin_name__ = "好友群聊处理请求 [Hidden]"
|
__zx_plugin_name__ = "好友群聊处理请求 [Hidden]"
|
||||||
|
__plugin_version__ = 0.1
|
||||||
friend_req = on_request(priority=5)
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_configs__ = {
|
||||||
|
"AUTO_ADD_FRIEND": {"value": False, "help": "是否自动同意好友添加", "default_value": False}
|
||||||
|
}
|
||||||
|
|
||||||
|
friend_req = on_request(priority=5, block=True)
|
||||||
|
group_req = on_request(priority=5, block=True)
|
||||||
|
x = on_message(priority=9, block=False)
|
||||||
|
|
||||||
exists_data = {"private": {}, "group": {}}
|
exists_data = {"private": {}, "group": {}}
|
||||||
|
|
||||||
@@ -24,20 +39,30 @@ async def _(bot: Bot, event: FriendRequestEvent, state: dict):
|
|||||||
exists_data["private"][event.user_id] = time.time()
|
exists_data["private"][event.user_id] = time.time()
|
||||||
user = await bot.get_stranger_info(user_id=event.user_id)
|
user = await bot.get_stranger_info(user_id=event.user_id)
|
||||||
nickname = user["nickname"]
|
nickname = user["nickname"]
|
||||||
|
sex = user["sex"]
|
||||||
|
age = str(user["age"])
|
||||||
|
comment = event.comment
|
||||||
await bot.send_private_msg(
|
await bot.send_private_msg(
|
||||||
user_id=int(list(bot.config.superusers)[0]),
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
message=f"*****一份好友申请*****\n"
|
message=f"*****一份好友申请*****\n"
|
||||||
f"昵称:{nickname}({event.user_id})\n"
|
f"昵称:{nickname}({event.user_id})\n"
|
||||||
f"自动同意:{'√' if AUTO_ADD_FRIEND else '×'}\n"
|
f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
|
||||||
f"日期:{str(datetime.now()).split('.')[0]}\n"
|
f"日期:{str(datetime.now()).split('.')[0]}\n"
|
||||||
f"备注:{event.comment}",
|
f"备注:{event.comment}",
|
||||||
)
|
)
|
||||||
if AUTO_ADD_FRIEND:
|
if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
|
||||||
await bot.set_friend_add_request(flag=event.flag, approve=True)
|
await bot.set_friend_add_request(flag=event.flag, approve=True)
|
||||||
await FriendUser.add_friend_info(user["user_id"], user["nickname"])
|
await FriendUser.add_friend_info(user["user_id"], user["nickname"])
|
||||||
|
else:
|
||||||
|
requests_manager.add_request(
|
||||||
group_req = on_request(priority=5, block=True)
|
event.user_id,
|
||||||
|
"private",
|
||||||
|
event.flag,
|
||||||
|
nickname=nickname,
|
||||||
|
sex=sex,
|
||||||
|
age=age,
|
||||||
|
comment=comment,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@group_req.handle()
|
@group_req.handle()
|
||||||
@@ -46,12 +71,26 @@ async def _(bot: Bot, event: GroupRequestEvent, state: dict):
|
|||||||
if event.sub_type == "invite":
|
if event.sub_type == "invite":
|
||||||
if str(event.user_id) in bot.config.superusers:
|
if str(event.user_id) in bot.config.superusers:
|
||||||
try:
|
try:
|
||||||
|
if await GroupInfo.get_group_info(event.group_id):
|
||||||
|
await GroupInfo.set_group_flag(event.group_id, 1)
|
||||||
|
else:
|
||||||
|
group_info = await bot.get_group_info(group_id=event.group_id)
|
||||||
|
await GroupInfo.add_group_info(
|
||||||
|
group_info["group_id"],
|
||||||
|
group_info["group_name"],
|
||||||
|
group_info["max_member_count"],
|
||||||
|
group_info["member_count"],
|
||||||
|
1,
|
||||||
|
)
|
||||||
await bot.set_group_add_request(
|
await bot.set_group_add_request(
|
||||||
flag=event.flag, sub_type="invite", approve=True
|
flag=event.flag, sub_type="invite", approve=True
|
||||||
)
|
)
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
user = await bot.get_stranger_info(user_id=event.user_id)
|
||||||
|
sex = user["sex"]
|
||||||
|
age = str(user["age"])
|
||||||
if exists_data["group"].get(f"{event.user_id}:{event.group_id}"):
|
if exists_data["group"].get(f"{event.user_id}:{event.group_id}"):
|
||||||
if (
|
if (
|
||||||
time.time()
|
time.time()
|
||||||
@@ -74,6 +113,31 @@ async def _(bot: Bot, event: GroupRequestEvent, state: dict):
|
|||||||
"请确保已经群主或群管理沟通过!\n"
|
"请确保已经群主或群管理沟通过!\n"
|
||||||
"等待管理员处理吧!",
|
"等待管理员处理吧!",
|
||||||
)
|
)
|
||||||
|
requests_manager.add_request(
|
||||||
|
event.user_id,
|
||||||
|
"group",
|
||||||
|
event.flag,
|
||||||
|
invite_group=event.group_id,
|
||||||
|
nickname=nickname,
|
||||||
|
sex=sex,
|
||||||
|
age=age,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@x.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: dict):
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
r = re.search(r'groupcode="(.*?)"', str(event.get_message()))
|
||||||
|
if r:
|
||||||
|
group_id = int(r.group(1))
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
r = re.search(r'groupname="(.*?)"', str(event.get_message()))
|
||||||
|
if r:
|
||||||
|
group_name = r.group(1)
|
||||||
|
else:
|
||||||
|
group_name = "None"
|
||||||
|
requests_manager.set_group_name(group_name, group_id)
|
||||||
|
|
||||||
|
|
||||||
@scheduler.scheduled_job(
|
@scheduler.scheduled_job(
|
||||||
@@ -8,12 +8,28 @@ from models.friend_user import FriendUser
|
|||||||
import random
|
import random
|
||||||
from models.ban_user import BanUser
|
from models.ban_user import BanUser
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from configs.config import NICKNAME
|
from configs.config import NICKNAME, Config
|
||||||
|
|
||||||
|
|
||||||
__plugin_name__ = "昵称系统"
|
__zx_plugin_name__ = "昵称系统"
|
||||||
|
__plugin_usage__ = f"""
|
||||||
__plugin_usage__ = f"用法:\n以后叫我 [名称]\n{NICKNAME}我是谁"
|
usage:
|
||||||
|
个人昵称系统,群聊 与 私聊 昵称相互独立
|
||||||
|
指令:
|
||||||
|
以后叫我 [昵称]
|
||||||
|
{NICKNAME}我是谁
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "区区昵称,才不想叫呢!"
|
||||||
|
__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_configs__ = {
|
||||||
|
"BLACK_WORD": {
|
||||||
|
"value": ["爸", "爹", "爷"],
|
||||||
|
"help": "昵称所屏蔽的关键词,会被替换为 *",
|
||||||
|
"default_value": None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nickname = on_command(
|
nickname = on_command(
|
||||||
"nickname",
|
"nickname",
|
||||||
@@ -38,52 +54,52 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
|
await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
|
||||||
if len(msg) > 10:
|
if len(msg) > 10:
|
||||||
await nickname.finish("昵称可不能超过10个字!", at_sender=True)
|
await nickname.finish("昵称可不能超过10个字!", at_sender=True)
|
||||||
if await GroupInfoUser.set_group_member_nickname(
|
if msg in bot.config.superusers:
|
||||||
event.user_id, event.group_id, msg
|
await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
|
||||||
):
|
_tmp = ""
|
||||||
if len(msg) < 5:
|
black_word = Config.get_config("nickname", "BLACK_WORD")
|
||||||
if random.random() < 0.5:
|
for x in msg:
|
||||||
msg = "~".join(msg)
|
_tmp += "*" if x in black_word else x
|
||||||
await nickname.send(
|
msg = _tmp
|
||||||
random.choice(
|
if isinstance(event, GroupMessageEvent):
|
||||||
[
|
if await GroupInfoUser.set_group_member_nickname(
|
||||||
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
event.user_id, event.group_id, msg
|
||||||
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
):
|
||||||
f"好突然,突然要叫你昵称什么的...{msg}..",
|
if len(msg) < 5:
|
||||||
f"{NICKNAME}会好好记住的{msg}的,放心吧",
|
if random.random() < 0.3:
|
||||||
f"好..好.,那窝以后就叫你{msg}了.",
|
msg = "~".join(msg)
|
||||||
]
|
await nickname.send(
|
||||||
|
random.choice(
|
||||||
|
[
|
||||||
|
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
||||||
|
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
||||||
|
f"好突然,突然要叫你昵称什么的...{msg}..",
|
||||||
|
f"{NICKNAME}会好好记住的{msg}的,放心吧",
|
||||||
|
f"好..好.,那窝以后就叫你{msg}了.",
|
||||||
|
]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
logger.info(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg}")
|
||||||
logger.info(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg}")
|
else:
|
||||||
|
await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
|
||||||
|
logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
|
||||||
else:
|
else:
|
||||||
await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
|
if await FriendUser.set_friend_nickname(event.user_id, msg):
|
||||||
logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
|
await nickname.send(
|
||||||
|
random.choice(
|
||||||
|
[
|
||||||
@nickname.handle()
|
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
||||||
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
||||||
msg = get_message_text(event.json())
|
f"好突然,突然要叫你昵称什么的...{msg}..",
|
||||||
if not msg:
|
f"{NICKNAME}会好好记住的{msg}的,放心吧",
|
||||||
await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
|
f"好..好.,那窝以后就叫你{msg}了.",
|
||||||
if len(msg) > 10:
|
]
|
||||||
await nickname.finish("不要超过10个字!", at_sender=True)
|
)
|
||||||
if await FriendUser.set_friend_nickname(event.user_id, msg):
|
|
||||||
await nickname.send(
|
|
||||||
random.choice(
|
|
||||||
[
|
|
||||||
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
|
|
||||||
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
|
|
||||||
f"好突然,突然要叫你昵称什么的...{msg}..",
|
|
||||||
f"{NICKNAME}会好好记住的{msg}的,放心吧",
|
|
||||||
f"好..好.,那窝以后就叫你{msg}了.",
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
)
|
logger.info(f"USER {event.user_id} 设置昵称 {msg}")
|
||||||
logger.info(f"USER {event.user_id} 设置昵称 {msg}")
|
else:
|
||||||
else:
|
await nickname.send("设置昵称失败了,明天再来试一试!或联系管理员更新好友!", at_sender=True)
|
||||||
await nickname.send("设置昵称失败了,明天再来试一试!或联系管理员更新好友!", at_sender=True)
|
logger.warning(f"USER {event.user_id} 设置昵称 {msg} 失败")
|
||||||
logger.warning(f"USER {event.user_id} 设置昵称 {msg} 失败")
|
|
||||||
|
|
||||||
|
|
||||||
@my_nickname.handle()
|
@my_nickname.handle()
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
from nonebot import Driver
|
||||||
|
from services.db_context import db
|
||||||
|
from asyncpg.exceptions import DuplicateColumnError
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
from nonebot.adapters.cqhttp import Bot
|
||||||
|
from services.log import logger
|
||||||
|
from configs.path_config import TEXT_PATH
|
||||||
|
from asyncio.exceptions import TimeoutError
|
||||||
|
from utils.http_utils import AsyncHttpx
|
||||||
|
from pathlib import Path
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ujson as json
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def update_city():
|
||||||
|
"""
|
||||||
|
部分插件需要中国省份城市
|
||||||
|
这里直接更新,避免插件内代码重复
|
||||||
|
"""
|
||||||
|
china_city = Path(TEXT_PATH) / "china_city.json"
|
||||||
|
data = {}
|
||||||
|
try:
|
||||||
|
res = await AsyncHttpx.get(
|
||||||
|
"http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
|
||||||
|
)
|
||||||
|
res.encoding = "utf8"
|
||||||
|
provinces_data = json.loads(res.text)
|
||||||
|
for province in provinces_data.keys():
|
||||||
|
data[provinces_data[province]] = []
|
||||||
|
res = await AsyncHttpx.get(
|
||||||
|
f"http://www.weather.com.cn/data/city3jdata/provshi/{province}.html",
|
||||||
|
timeout=5,
|
||||||
|
)
|
||||||
|
res.encoding = "utf8"
|
||||||
|
city_data = json.loads(res.text)
|
||||||
|
for city in city_data.keys():
|
||||||
|
data[provinces_data[province]].append(city_data[city])
|
||||||
|
with open(china_city, "w", encoding="utf8") as f:
|
||||||
|
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||||
|
logger.info("自动更新城市列表完成.....")
|
||||||
|
except TimeoutError:
|
||||||
|
logger.warning("自动更新城市列表超时.....")
|
||||||
|
except ValueError:
|
||||||
|
logger.warning("自动城市列表失败.....")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"自动城市列表未知错误 {type(e)}:{e}")
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def _():
|
||||||
|
"""
|
||||||
|
数据库表结构变换
|
||||||
|
"""
|
||||||
|
sql_str = [
|
||||||
|
"ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;" # group_info表添加一个group_flag
|
||||||
|
]
|
||||||
|
for sql in sql_str:
|
||||||
|
try:
|
||||||
|
query = db.text(sql)
|
||||||
|
await db.first(query)
|
||||||
|
except DuplicateColumnError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_bot_connect
|
||||||
|
async def _(bot: Bot):
|
||||||
|
"""
|
||||||
|
版本某些需要的变换
|
||||||
|
"""
|
||||||
|
# 清空不存在的群聊信息,并将已所有已存在的群聊group_flag设置为1(认证所有已存在的群)
|
||||||
|
if not await GroupInfo.get_group_info(114514):
|
||||||
|
# 标识符,该功能只需执行一次
|
||||||
|
await GroupInfo.add_group_info(114514, "114514", 114514, 114514, 1)
|
||||||
|
group_list = await bot.get_group_list()
|
||||||
|
group_list = [g["group_id"] for g in group_list]
|
||||||
|
_gl = [x.group_id for x in await GroupInfo.get_all_group()]
|
||||||
|
if 114514 in _gl:
|
||||||
|
_gl.remove(114514)
|
||||||
|
for group_id in _gl:
|
||||||
|
if group_id in group_list:
|
||||||
|
if await GroupInfo.get_group_info(group_id):
|
||||||
|
await GroupInfo.set_group_flag(group_id, 1)
|
||||||
|
else:
|
||||||
|
group_info = await bot.get_group_info(group_id=group_id)
|
||||||
|
await GroupInfo.add_group_info(
|
||||||
|
group_info["group_id"],
|
||||||
|
group_info["group_name"],
|
||||||
|
group_info["max_member_count"],
|
||||||
|
group_info["member_count"],
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
logger.info(f"已将群聊 {group_id} 添加认证...")
|
||||||
|
else:
|
||||||
|
await GroupInfo.delete_group_info(group_id)
|
||||||
|
logger.info(f"移除不存在的群聊信息:{group_id}")
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
nonebot.load_plugins('basic_plugins/super_cmd')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent, Message
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import get_message_text, is_number
|
||||||
|
from utils.manager import requests_manager
|
||||||
|
from utils.message_builder import image
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "显示所有好友群组 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
显示所有好友群组
|
||||||
|
指令:
|
||||||
|
查看所有好友/查看所有群组
|
||||||
|
同意好友请求 [id]
|
||||||
|
拒绝好友请求 [id]
|
||||||
|
同意群聊请求 [id]
|
||||||
|
拒绝群聊请求 [id]
|
||||||
|
查看所有请求
|
||||||
|
清空所有请求
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "显示所有好友群组"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"查看所有好友/查看所有群组",
|
||||||
|
"同意好友请求 [id]",
|
||||||
|
"拒绝好友请求 [id]",
|
||||||
|
"同意群聊请求 [id]",
|
||||||
|
"拒绝群聊请求 [id]",
|
||||||
|
"查看所有请求",
|
||||||
|
"清空所有请求",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
cls_group = on_command(
|
||||||
|
"查看所有群组", rule=to_me(), permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
cls_friend = on_command(
|
||||||
|
"查看所有好友", rule=to_me(), permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
friend_handle = on_command(
|
||||||
|
"同意好友请求", aliases={"拒绝好友请求"}, permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
group_handle = on_command(
|
||||||
|
"同意群聊请求", aliases={"拒绝群聊请求"}, permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
clear_request = on_command("清空所有请求", permission=SUPERUSER, priority=1, block=True)
|
||||||
|
|
||||||
|
cls_request = on_command("查看所有请求", permission=SUPERUSER, priority=1, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@cls_group.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
gl = await bot.get_group_list(self_id=int(bot.self_id))
|
||||||
|
msg = ["{group_id} {group_name}".format_map(g) for g in gl]
|
||||||
|
msg = "\n".join(msg)
|
||||||
|
msg = f"bot:{bot.self_id}\n| 群号 | 群名 | 共{len(gl)}个群\n" + msg
|
||||||
|
await bot.send_private_msg(
|
||||||
|
self_id=int(bot.self_id),
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=msg,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@cls_friend.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
gl = await bot.get_friend_list(self_id=int(bot.self_id))
|
||||||
|
msg = ["{user_id} {nickname}".format_map(g) for g in gl]
|
||||||
|
msg = "\n".join(msg)
|
||||||
|
msg = f"| QQ号 | 昵称 | 共{len(gl)}个好友\n" + msg
|
||||||
|
await bot.send_private_msg(
|
||||||
|
self_id=int(bot.self_id),
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=msg,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@friend_handle.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
id_ = get_message_text(event.json())
|
||||||
|
if is_number(id_):
|
||||||
|
id_ = int(id_)
|
||||||
|
if state["_prefix"]["raw_command"][:2] == "同意":
|
||||||
|
if await requests_manager.approve(bot, id_, "private"):
|
||||||
|
await friend_handle.send("同意好友请求成功..")
|
||||||
|
else:
|
||||||
|
await friend_handle.send("同意好友请求失败,可能是未找到此id的请求..")
|
||||||
|
else:
|
||||||
|
if await requests_manager.refused(bot, id_, "private"):
|
||||||
|
await friend_handle.send("拒绝好友请求成功..")
|
||||||
|
else:
|
||||||
|
await friend_handle.send("拒绝好友请求失败,可能是未找到此id的请求..")
|
||||||
|
else:
|
||||||
|
await friend_handle.send("id必须为纯数字!")
|
||||||
|
|
||||||
|
|
||||||
|
@group_handle.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
id_ = get_message_text(event.json())
|
||||||
|
if is_number(id_):
|
||||||
|
id_ = int(id_)
|
||||||
|
if state["_prefix"]["raw_command"][:2] == "同意":
|
||||||
|
rid = await requests_manager.approve(bot, id_, "group")
|
||||||
|
if rid:
|
||||||
|
await friend_handle.send("同意群聊请求成功..")
|
||||||
|
if await GroupInfo.get_group_info(rid):
|
||||||
|
await GroupInfo.set_group_flag(rid, 1)
|
||||||
|
else:
|
||||||
|
group_info = await bot.get_group_info(group_id=rid)
|
||||||
|
await GroupInfo.add_group_info(
|
||||||
|
rid,
|
||||||
|
group_info["group_name"],
|
||||||
|
group_info["max_member_count"],
|
||||||
|
group_info["member_count"],
|
||||||
|
1
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await friend_handle.send("同意群聊请求失败,可能是未找到此id的请求..")
|
||||||
|
else:
|
||||||
|
if await requests_manager.refused(bot, id_, "group"):
|
||||||
|
await friend_handle.send("拒绝群聊请求成功..")
|
||||||
|
else:
|
||||||
|
await friend_handle.send("拒绝群聊请求失败,可能是未找到此id的请求..")
|
||||||
|
else:
|
||||||
|
await friend_handle.send("id必须为纯数字!")
|
||||||
|
|
||||||
|
|
||||||
|
@cls_request.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
_str = ""
|
||||||
|
for type_ in ["private", "group"]:
|
||||||
|
msg = await requests_manager.show(type_)
|
||||||
|
if msg:
|
||||||
|
_str += image(b64=msg)
|
||||||
|
else:
|
||||||
|
_str += "没有任何好友请求.." if type_ == "private" else "没有任何群聊请求.."
|
||||||
|
if type_ == "private":
|
||||||
|
_str += '\n--------------------\n'
|
||||||
|
await cls_request.send(Message(_str))
|
||||||
|
|
||||||
|
|
||||||
|
@clear_request.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
requests_manager.clear()
|
||||||
|
await cls_request.send("已清空所有好友/群聊请求..")
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent
|
||||||
|
from configs.path_config import TEMP_PATH
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import scheduler
|
||||||
|
from services.log import logger
|
||||||
|
from utils.manager import resources_manager
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "清理临时数据 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
清理临时数据
|
||||||
|
指令:
|
||||||
|
清理临时数据
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "清理临时数据"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"清理临时数据",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
clear_data = on_command(
|
||||||
|
"清理临时数据", rule=to_me(), permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
resources_manager.add_temp_dir(TEMP_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
@clear_data.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
await clear_data.send("开始清理临时数据....")
|
||||||
|
size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
|
||||||
|
await clear_data.send("共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
|
||||||
|
|
||||||
|
|
||||||
|
def _clear_data() -> float:
|
||||||
|
size = 0
|
||||||
|
for dir_ in resources_manager.get_temp_data_dir():
|
||||||
|
if dir_.exists():
|
||||||
|
for file in os.listdir(dir_):
|
||||||
|
file = dir_ / file
|
||||||
|
try:
|
||||||
|
if time.time() - os.path.getatime(file) > 300:
|
||||||
|
file_size = os.path.getsize(file)
|
||||||
|
file.unlink()
|
||||||
|
size += file_size
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"清理临时数据错误...{type(e)}:{e}")
|
||||||
|
return float(size)
|
||||||
|
|
||||||
|
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
"cron",
|
||||||
|
hour=1,
|
||||||
|
minute=1,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
|
||||||
|
logger.info("自动清理临时数据完成," + "共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
|
||||||
@@ -1,44 +1,43 @@
|
|||||||
from models.group_remind import GroupRemind
|
|
||||||
|
|
||||||
|
|
||||||
async def open_remind(group: int, name: str) -> str:
|
# async def open_remind(group: int, name: str) -> str:
|
||||||
_name = ""
|
# _name = ""
|
||||||
if name == "zwa":
|
# if name == "zwa":
|
||||||
_name = "早晚安"
|
# _name = "早晚安"
|
||||||
if name == "dz":
|
# if name == "dz":
|
||||||
_name = "地震播报"
|
# _name = "地震播报"
|
||||||
if name == "hy":
|
# if name == "hy":
|
||||||
_name = "群欢迎"
|
# _name = "群欢迎"
|
||||||
if name == "kxcz":
|
# if name == "kxcz":
|
||||||
_name = "开箱重置提醒"
|
# _name = "开箱重置提醒"
|
||||||
if name == "gb":
|
# if name == "gb":
|
||||||
_name = "广播"
|
# _name = "广播"
|
||||||
if await GroupRemind.get_status(group, name):
|
# if await GroupRemind.get_status(group, name):
|
||||||
return f"该群已经开启过 {_name} 通知,请勿重复开启!"
|
# return f"该群已经开启过 {_name} 通知,请勿重复开启!"
|
||||||
if await GroupRemind.set_status(group, name, True):
|
# if await GroupRemind.set_status(group, name, True):
|
||||||
return f"成功开启 {_name} 通知!0v0"
|
# return f"成功开启 {_name} 通知!0v0"
|
||||||
else:
|
# else:
|
||||||
return f"开启 {_name} 通知失败了..."
|
# return f"开启 {_name} 通知失败了..."
|
||||||
|
#
|
||||||
|
#
|
||||||
async def close_remind(group: int, name: str) -> str:
|
# async def close_remind(group: int, name: str) -> str:
|
||||||
_name = ""
|
# _name = ""
|
||||||
if name == "zwa":
|
# if name == "zwa":
|
||||||
_name = "早晚安"
|
# _name = "早晚安"
|
||||||
if name == "dz":
|
# if name == "dz":
|
||||||
_name = "地震播报"
|
# _name = "地震播报"
|
||||||
if name == "hy":
|
# if name == "hy":
|
||||||
_name = "群欢迎"
|
# _name = "群欢迎"
|
||||||
if name == "kxcz":
|
# if name == "kxcz":
|
||||||
_name = "开箱重置提醒"
|
# _name = "开箱重置提醒"
|
||||||
if name == "gb":
|
# if name == "gb":
|
||||||
_name = "广播"
|
# _name = "广播"
|
||||||
if not await GroupRemind.get_status(group, name):
|
# if not await GroupRemind.get_status(group, name):
|
||||||
return f"该群已经取消过 {_name} 通知,请勿重复取消!"
|
# return f"该群已经取消过 {_name} 通知,请勿重复取消!"
|
||||||
if await GroupRemind.set_status(group, name, False):
|
# if await GroupRemind.set_status(group, name, False):
|
||||||
return f"成功关闭 {_name} 通知!0v0"
|
# return f"成功关闭 {_name} 通知!0v0"
|
||||||
else:
|
# else:
|
||||||
return f"关闭 {_name} 通知失败了..."
|
# return f"关闭 {_name} 通知失败了..."
|
||||||
|
|
||||||
|
|
||||||
# cmd_list = ['总开关', '签到', '发送图片', '色图', '黑白草图', 'coser', '鸡汤/语录', '骂我', '开箱', '鲁迅说', '假消息', '商店系统',
|
# cmd_list = ['总开关', '签到', '发送图片', '色图', '黑白草图', 'coser', '鸡汤/语录', '骂我', '开箱', '鲁迅说', '假消息', '商店系统',
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from services.db_context import db
|
||||||
|
from utils.utils import get_message_text
|
||||||
|
from services.log import logger
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "执行sql [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
执行一段sql语句
|
||||||
|
指令:
|
||||||
|
exec [sql语句]
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "执行一段sql语句"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"exec [sql语句]",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
exec_ = on_command("exec", rule=to_me(), permission=SUPERUSER, priority=1, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@exec_.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
sql = get_message_text(event.json())
|
||||||
|
async with db.transaction():
|
||||||
|
try:
|
||||||
|
query = db.text(sql)
|
||||||
|
await db.first(query)
|
||||||
|
await exec_.send("执行 sql 语句成功.")
|
||||||
|
except Exception as e:
|
||||||
|
await exec_.send(f"执行 sql 语句失败 {type(e)}:{e}")
|
||||||
|
logger.error(f"执行 sql 语句失败 {type(e)}:{e}")
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
from nonebot import on_command, on_regex
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent, GROUP, GroupMessageEvent
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import get_message_text, is_number
|
||||||
|
from utils.manager import group_manager, plugins2settings_manager
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
from services.log import logger
|
||||||
|
from configs.config import NICKNAME
|
||||||
|
from nonebot.adapters.cqhttp.exception import ActionFailed
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "管理群操作 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
群权限 | 群白名单 | 退出群 操作
|
||||||
|
指令:
|
||||||
|
退群 [group_id]
|
||||||
|
修改群权限 [group_id] [等级]
|
||||||
|
添加群白名单 *[group_id]
|
||||||
|
删除群白名单 *[group_id]
|
||||||
|
添加群认证 *[group_id]
|
||||||
|
删除群认证 *[group_id]
|
||||||
|
查看群白名单
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "管理群操作"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"退群 [group_id]",
|
||||||
|
"修改群权限 [group_id] [等级]",
|
||||||
|
"添加群白名单 *[group_id]",
|
||||||
|
"删除群白名单 *[group_id]",
|
||||||
|
"添加群认证 *[group_id]",
|
||||||
|
"删除群认证 *[group_id]",
|
||||||
|
"查看群白名单",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
del_group = on_command("退群", rule=to_me(), permission=SUPERUSER, priority=1, block=True)
|
||||||
|
|
||||||
|
add_group_level = on_command("修改群权限", priority=1, permission=SUPERUSER, block=True)
|
||||||
|
my_group_level = on_command(
|
||||||
|
"查看群权限", aliases={"群权限"}, priority=5, permission=GROUP, block=True
|
||||||
|
)
|
||||||
|
what_up_group_level = on_regex(
|
||||||
|
".*?(提高|提升|升高|增加|加上)(.*?)群权限.*?",
|
||||||
|
rule=to_me(),
|
||||||
|
priority=5,
|
||||||
|
permission=GROUP,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
manager_group_whitelist = on_command(
|
||||||
|
"添加群白名单", aliases={"删除群白名单"}, priority=1, permission=SUPERUSER, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
show_group_whitelist = on_command(
|
||||||
|
"查看群白名单", priority=1, permission=SUPERUSER, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
group_auth = on_command(
|
||||||
|
"添加群认证", aliases={"删除群认证"}, priority=1, permission=SUPERUSER, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@del_group.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
group_id = get_message_text(event.json())
|
||||||
|
if group_id:
|
||||||
|
if is_number(group_id):
|
||||||
|
try:
|
||||||
|
await bot.set_group_leave(group_id=int(group_id))
|
||||||
|
logger.info(f"退出群聊 {group_id} 成功")
|
||||||
|
await del_group.send(f"退出群聊 {group_id} 成功", at_sender=True)
|
||||||
|
group_manager.delete_group(int(group_id))
|
||||||
|
await GroupInfo.delete_group_info(int(group_id))
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"退出群聊 {group_id} 失败 e:{e}")
|
||||||
|
else:
|
||||||
|
await del_group.finish(f"请输入正确的群号", at_sender=True)
|
||||||
|
else:
|
||||||
|
await del_group.finish(f"请输入群号", at_sender=True)
|
||||||
|
|
||||||
|
|
||||||
|
@add_group_level.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
msg = get_message_text(event.json())
|
||||||
|
group_id = 0
|
||||||
|
level = 0
|
||||||
|
if not msg:
|
||||||
|
await add_group_level.finish("用法:修改群权限 [group] [level]")
|
||||||
|
msg = msg.split(" ")
|
||||||
|
if len(msg) < 2:
|
||||||
|
await add_group_level.finish("参数不完全..[group] [level]")
|
||||||
|
if is_number(msg[0]) and is_number(msg[1]):
|
||||||
|
group_id = msg[0]
|
||||||
|
level = int(msg[1])
|
||||||
|
else:
|
||||||
|
await add_group_level.finish("参数错误...group和level必须是数字..")
|
||||||
|
old_level = group_manager.get_group_level(group_id)
|
||||||
|
group_manager.set_group_level(group_id, level)
|
||||||
|
await add_group_level.send("修改成功...", at_sender=True)
|
||||||
|
if level > -1:
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=int(group_id), message=f"管理员修改了此群权限:{old_level} -> {level}"
|
||||||
|
)
|
||||||
|
logger.info(f"{event.user_id} 修改了 {group_id} 的权限:{level}")
|
||||||
|
|
||||||
|
|
||||||
|
@my_group_level.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
level = group_manager.get_group_level(event.group_id)
|
||||||
|
tmp = ""
|
||||||
|
data = plugins2settings_manager.get_data()
|
||||||
|
for module in data:
|
||||||
|
if data[module]["level"] > level:
|
||||||
|
plugin_name = data[module]["cmd"][0]
|
||||||
|
if plugin_name == "pixiv":
|
||||||
|
plugin_name = "搜图 p站排行"
|
||||||
|
tmp += f"{plugin_name}\n"
|
||||||
|
if tmp:
|
||||||
|
tmp = "\n目前无法使用的功能:\n" + tmp
|
||||||
|
await my_group_level.finish(f"当前群权限:{level}{tmp}")
|
||||||
|
|
||||||
|
|
||||||
|
@what_up_group_level.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
await what_up_group_level.finish(
|
||||||
|
f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.管理员修改权限"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@manager_group_whitelist.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
msg = get_message_text(event.json()).split()
|
||||||
|
all_group = [
|
||||||
|
g["group_id"] for g in await bot.get_group_list(self_id=int(bot.self_id))
|
||||||
|
]
|
||||||
|
group_list = []
|
||||||
|
for group in msg:
|
||||||
|
if is_number(group) and int(group) in all_group:
|
||||||
|
group_list.append(int(group))
|
||||||
|
if group_list:
|
||||||
|
for group in group_list:
|
||||||
|
if state["_prefix"]["raw_command"] in ["添加群白名单"]:
|
||||||
|
group_manager.add_group_white_list(group)
|
||||||
|
else:
|
||||||
|
group_manager.delete_group_white_list(group)
|
||||||
|
group_list = [str(x) for x in group_list]
|
||||||
|
await manager_group_whitelist.send(
|
||||||
|
"已成功将 " + "\n".join(group_list) + " " + state["_prefix"]["raw_command"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
|
||||||
|
|
||||||
|
|
||||||
|
@show_group_whitelist.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
x = group_manager.get_group_white_list()
|
||||||
|
x = [str(g) for g in x]
|
||||||
|
if x:
|
||||||
|
await show_group_whitelist.send("目前的群白名单:\n" + "\n".join(x))
|
||||||
|
else:
|
||||||
|
await show_group_whitelist.send("没有任何群在群白名单...")
|
||||||
|
|
||||||
|
|
||||||
|
@group_auth.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
msg = get_message_text(event.json()).split()
|
||||||
|
for group_id in msg:
|
||||||
|
if not is_number(group_id):
|
||||||
|
await group_auth.send(f"{group_id}非纯数字,已跳过该项..")
|
||||||
|
group_id = int(group_id)
|
||||||
|
if state["_prefix"]["raw_command"][:2] == "添加":
|
||||||
|
if await GroupInfo.get_group_info(group_id):
|
||||||
|
await GroupInfo.set_group_flag(group_id, 1)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
group_info = await bot.get_group_info(group_id=group_id)
|
||||||
|
except ActionFailed:
|
||||||
|
group_info = {
|
||||||
|
"group_id": group_id,
|
||||||
|
"group_name": "_",
|
||||||
|
"max_member_count": -1,
|
||||||
|
"member_count": -1,
|
||||||
|
}
|
||||||
|
await GroupInfo.add_group_info(
|
||||||
|
group_info["group_id"],
|
||||||
|
group_info["group_name"],
|
||||||
|
group_info["max_member_count"],
|
||||||
|
group_info["member_count"],
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if await GroupInfo.get_group_info(group_id):
|
||||||
|
await GroupInfo.set_group_flag(group_id, 0)
|
||||||
|
await group_auth.send(
|
||||||
|
f'已为 {group_id} {state["_prefix"]["raw_command"][:2]}群认证..'
|
||||||
|
)
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.manager import (
|
||||||
|
plugins2cd_manager,
|
||||||
|
plugins2settings_manager,
|
||||||
|
plugins2block_manager,
|
||||||
|
group_manager,
|
||||||
|
)
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "重载插件配置 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
重载插件配置
|
||||||
|
plugins2settings,
|
||||||
|
plugins2cd
|
||||||
|
plugins2block
|
||||||
|
group_manager
|
||||||
|
指令:
|
||||||
|
重载插件配置
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "重载插件配置"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"重载插件配置",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
reload_plugins_manager = on_command(
|
||||||
|
"重载配置", rule=to_me(), permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@reload_plugins_manager.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
plugins2settings_manager.reload()
|
||||||
|
plugins2cd_manager.reload()
|
||||||
|
plugins2block_manager.reload()
|
||||||
|
group_manager.reload()
|
||||||
|
await reload_plugins_manager.send("重载完成...")
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, Message
|
||||||
|
from utils.utils import get_message_at, get_message_text, is_number
|
||||||
|
from services.log import logger
|
||||||
|
from utils.message_builder import at
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "用户权限管理 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
增删改用户的权限
|
||||||
|
指令:
|
||||||
|
添加权限 [at] [权限]
|
||||||
|
添加权限 [qq] [group_id] [权限]
|
||||||
|
删除权限 [at]
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "增删改用户的权限"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"添加权限 [at] [权限]",
|
||||||
|
"添加权限 [qq] [group_id] [权限]",
|
||||||
|
"删除权限 [at]",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
super_cmd = on_command(
|
||||||
|
"添加管理",
|
||||||
|
aliases={"删除管理", "添加权限", "删除权限"},
|
||||||
|
priority=1,
|
||||||
|
permission=SUPERUSER,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@super_cmd.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
|
group_id = -1
|
||||||
|
level = 0
|
||||||
|
try:
|
||||||
|
args = get_message_text(event.json()).split()
|
||||||
|
qq = get_message_at(event.json())
|
||||||
|
flag = -1
|
||||||
|
if not qq:
|
||||||
|
if len(args) > 2:
|
||||||
|
if is_number(args[0]) and is_number(args[1]) and is_number(args[2]):
|
||||||
|
qq = int(args[0])
|
||||||
|
group_id = int(args[1])
|
||||||
|
level = int(args[2])
|
||||||
|
flag = 1
|
||||||
|
else:
|
||||||
|
await super_cmd.finish("所有参数必须是数字!", at_sender=True)
|
||||||
|
else:
|
||||||
|
await super_cmd.finish(
|
||||||
|
"权限参数不完全\n\t格式:添加/删除权限 [at] [level]"
|
||||||
|
"\n\t格式:添加/删除权限 [qq] [group_id] [level]",
|
||||||
|
at_sender=True,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
qq = qq[0]
|
||||||
|
group_id = event.group_id
|
||||||
|
flag = 2
|
||||||
|
if state["_prefix"]["raw_command"][:2] == "添加":
|
||||||
|
if await LevelUser.set_level(qq, group_id, level, 1):
|
||||||
|
result = "添加管理成功, 权限: " + str(level)
|
||||||
|
else:
|
||||||
|
result = "管理已存在, 更新权限: " + str(level)
|
||||||
|
else:
|
||||||
|
if await LevelUser.delete_level(qq, event.group_id):
|
||||||
|
result = "删除管理成功!"
|
||||||
|
else:
|
||||||
|
result = "该账号无管理权限!"
|
||||||
|
if flag == 2:
|
||||||
|
await super_cmd.send(result)
|
||||||
|
elif flag == 1:
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=group_id,
|
||||||
|
message=Message(f"{at(qq)}管理员修改了你的权限" f"\n--------\n你当前的权限等级:{level}"),
|
||||||
|
)
|
||||||
|
await super_cmd.send("修改成功")
|
||||||
|
except Exception as e:
|
||||||
|
await super_cmd.send("执行指令失败!")
|
||||||
|
logger.error(f"执行指令失败 e:{e}")
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import get_message_text, is_number
|
||||||
|
from services.log import logger
|
||||||
|
from utils.manager import group_manager
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "超级用户被动开关 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
超级用户被动开关
|
||||||
|
指令:
|
||||||
|
开启/关闭广播通知
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "超级用户被动开关"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"开启/关闭广播通知",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
oc_gb = on_command(
|
||||||
|
"开启广播通知",
|
||||||
|
aliases={"关闭广播通知"},
|
||||||
|
rule=to_me(),
|
||||||
|
permission=SUPERUSER,
|
||||||
|
priority=1,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@oc_gb.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
group = get_message_text(event.json())
|
||||||
|
if group:
|
||||||
|
if is_number(group):
|
||||||
|
group = int(group)
|
||||||
|
for g in await bot.get_group_list():
|
||||||
|
if g["group_id"] == group:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
await oc_gb.finish("没有加入这个群...", at_sender=True)
|
||||||
|
if state["_prefix"]["raw_command"] == "开启广播通知":
|
||||||
|
logger.info(f"USER {event.user_id} 开启了 GROUP {group} 的广播")
|
||||||
|
await oc_gb.finish(await group_manager.open_group_task(group, "broadcast",), at_sender=True)
|
||||||
|
else:
|
||||||
|
logger.info(f"USER {event.user_id} 关闭了 GROUP {group} 的广播")
|
||||||
|
await oc_gb.finish(await group_manager.close_group_task(group, "broadcast"), at_sender=True)
|
||||||
|
else:
|
||||||
|
await oc_gb.finish("请输入正确的群号", at_sender=True)
|
||||||
|
else:
|
||||||
|
await oc_gb.finish("请输入要关闭广播的群号", at_sender=True)
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.cqhttp import Bot, MessageEvent
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import get_bot
|
||||||
|
from services.log import logger
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
from models.friend_user import FriendUser
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "更新群/好友信息 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
更新群/好友信息
|
||||||
|
指令:
|
||||||
|
更新群信息
|
||||||
|
更新好友信息
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "更新群/好友信息"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"更新群信息",
|
||||||
|
"更新好友信息",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
update_group_info = on_command(
|
||||||
|
"更新群信息", rule=to_me(), permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
update_friend_info = on_command(
|
||||||
|
"更新好友信息", rule=to_me(), permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@update_group_info.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
bot = get_bot()
|
||||||
|
gl = await bot.get_group_list()
|
||||||
|
gl = [g["group_id"] for g in gl]
|
||||||
|
num = 0
|
||||||
|
rst = ""
|
||||||
|
for g in gl:
|
||||||
|
group_info = await bot.get_group_info(group_id=g)
|
||||||
|
if await GroupInfo.add_group_info(
|
||||||
|
group_info["group_id"],
|
||||||
|
group_info["group_name"],
|
||||||
|
group_info["max_member_count"],
|
||||||
|
group_info["member_count"],
|
||||||
|
):
|
||||||
|
num += 1
|
||||||
|
logger.info(f"自动更新群组 {g} 信息成功")
|
||||||
|
else:
|
||||||
|
logger.info(f"自动更新群组 {g} 信息失败")
|
||||||
|
rst += f"{g} 更新失败\n"
|
||||||
|
await update_group_info.send(f"成功更新了 {num} 个群的信息\n{rst[:-1]}")
|
||||||
|
|
||||||
|
|
||||||
|
@update_friend_info.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||||
|
num = 0
|
||||||
|
rst = ""
|
||||||
|
fl = await get_bot().get_friend_list()
|
||||||
|
for f in fl:
|
||||||
|
if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
|
||||||
|
logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
|
||||||
|
num += 1
|
||||||
|
else:
|
||||||
|
logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
|
||||||
|
rst += f'{f["user_id"]} 更新失败\n'
|
||||||
|
await update_friend_info.send(f"成功更新了 {num} 个好友的信息\n{rst[:-1]}")
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters import Bot, Event
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from utils.message_builder import image
|
||||||
|
from .data_source import create_help_image
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = '超级用户帮助 [Superuser]'
|
||||||
|
|
||||||
|
|
||||||
|
superuser_help_image = Path(IMAGE_PATH) / 'superuser_help.png'
|
||||||
|
|
||||||
|
if superuser_help_image.exists():
|
||||||
|
superuser_help_image.unlink()
|
||||||
|
|
||||||
|
super_help = on_command(
|
||||||
|
"超级用户帮助", rule=to_me(), priority=1, permission=SUPERUSER, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@super_help.handle()
|
||||||
|
async def _(bot: Bot, event: Event, state: T_State):
|
||||||
|
if not superuser_help_image.exists():
|
||||||
|
await create_help_image()
|
||||||
|
x = image(superuser_help_image)
|
||||||
|
await super_help.finish(x)
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
from utils.image_utils import BuildImage
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from services.log import logger
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
from nonebot.adapters.cqhttp import Bot
|
||||||
|
from pathlib import Path
|
||||||
|
from nonebot import Driver
|
||||||
|
import asyncio
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
background = Path(IMAGE_PATH) / "background" / "0.png"
|
||||||
|
|
||||||
|
superuser_help_image = Path(IMAGE_PATH) / "superuser_help.png"
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_bot_connect
|
||||||
|
async def create_help_image(bot: Bot = None):
|
||||||
|
"""
|
||||||
|
创建超级用户帮助图片
|
||||||
|
"""
|
||||||
|
await asyncio.get_event_loop().run_in_executor(None, _create_help_image)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_help_image():
|
||||||
|
"""
|
||||||
|
创建管理员帮助图片
|
||||||
|
"""
|
||||||
|
_matchers = get_matchers()
|
||||||
|
_plugin_name_list = []
|
||||||
|
width = 0
|
||||||
|
help_str = "超级用户帮助\n\n* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n"
|
||||||
|
tmp_img = BuildImage(0, 0, plain_text='1', font_size=24)
|
||||||
|
for matcher in _matchers:
|
||||||
|
plugin_name = ""
|
||||||
|
try:
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.module)
|
||||||
|
_module = _plugin.module
|
||||||
|
try:
|
||||||
|
plugin_name = _module.__getattribute__("__zx_plugin_name__")
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
is_superuser_usage = False
|
||||||
|
try:
|
||||||
|
_ = _module.__getattribute__("__plugin_superuser_usage__")
|
||||||
|
is_superuser_usage = True
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if (
|
||||||
|
("[superuser]" in plugin_name.lower() or is_superuser_usage)
|
||||||
|
and plugin_name != "超级用户帮助 [Superuser]"
|
||||||
|
and plugin_name not in _plugin_name_list
|
||||||
|
and "[hidden]" not in plugin_name.lower()
|
||||||
|
):
|
||||||
|
_plugin_name_list.append(plugin_name)
|
||||||
|
try:
|
||||||
|
plugin_des = _module.__getattribute__("__plugin_des__")
|
||||||
|
except AttributeError:
|
||||||
|
plugin_des = '_'
|
||||||
|
plugin_cmd = _module.__getattribute__("__plugin_cmd__")
|
||||||
|
if is_superuser_usage:
|
||||||
|
plugin_cmd = [x for x in plugin_cmd if "[_superuser]" in x]
|
||||||
|
plugin_cmd = " / ".join(plugin_cmd).replace('[_superuser]', '').strip()
|
||||||
|
help_str += f"{plugin_des} -> {plugin_cmd}\n\n"
|
||||||
|
x = tmp_img.getsize(f"{plugin_des} -> {plugin_cmd}")[0]
|
||||||
|
width = width if width > x else x
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(
|
||||||
|
f"获取超级用户插件 {matcher.module}: {plugin_name} 设置失败... {type(e)}:{e}"
|
||||||
|
)
|
||||||
|
height = len(help_str.split("\n")) * 33
|
||||||
|
width += 500
|
||||||
|
A = BuildImage(width, height, font_size=24)
|
||||||
|
_background = BuildImage(width, height, background=background)
|
||||||
|
A.text((300, 140), help_str)
|
||||||
|
A.paste(_background, alpha=True)
|
||||||
|
A.save(superuser_help_image)
|
||||||
|
logger.info(f"已成功加载 {len(_plugin_name_list)} 条超级用户命令")
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.adapters.cqhttp import Bot, Event
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from utils.message_builder import image
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "更新信息"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
更新信息
|
||||||
|
指令:
|
||||||
|
更新信息
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "当前版本的更新信息"
|
||||||
|
__plugin_cmd__ = ["更新信息"]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"limit_superuser": False,
|
||||||
|
"cmd": ["更新信息"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update_info = on_command("更新信息", aliases={"更新日志"}, priority=5, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@update_info.handle()
|
||||||
|
async def _(bot: Bot, event: Event, state: T_State):
|
||||||
|
img = image("update_info.png")
|
||||||
|
if img:
|
||||||
|
await update_info.finish(image("update_info.png"))
|
||||||
|
else:
|
||||||
|
await update_info.finish("目前没有更新信息哦")
|
||||||
@@ -2,19 +2,19 @@ import nonebot
|
|||||||
from nonebot.adapters.cqhttp import Bot as CQHTTPBot
|
from nonebot.adapters.cqhttp import Bot as CQHTTPBot
|
||||||
from services.db_context import init, disconnect
|
from services.db_context import init, disconnect
|
||||||
|
|
||||||
|
|
||||||
nonebot.init()
|
nonebot.init()
|
||||||
driver = nonebot.get_driver()
|
driver = nonebot.get_driver()
|
||||||
driver.register_adapter("cqhttp", CQHTTPBot)
|
driver.register_adapter("cqhttp", CQHTTPBot)
|
||||||
config = driver.config
|
config = driver.config
|
||||||
driver.on_startup(init)
|
driver.on_startup(init)
|
||||||
driver.on_shutdown(disconnect)
|
driver.on_shutdown(disconnect)
|
||||||
nonebot.load_builtin_plugins()
|
# 优先加载定时任务
|
||||||
|
nonebot.load_plugin("nonebot_plugin_apscheduler")
|
||||||
|
nonebot.load_plugins("basic_plugins")
|
||||||
nonebot.load_plugins("plugins")
|
nonebot.load_plugins("plugins")
|
||||||
nonebot.load_plugins("plugins/shop")
|
# 最后加载权限控制
|
||||||
nonebot.load_plugins("plugins/genshin")
|
nonebot.load_plugins("basic_plugins/hooks")
|
||||||
nonebot.load_plugins("plugins/alapi")
|
|
||||||
nonebot.load_plugins("plugins/pix_gallery")
|
|
||||||
nonebot.load_plugins("plugins/admin_bot_manage")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,31 +1,11 @@
|
|||||||
from typing import List, Optional, Tuple
|
from typing import Optional
|
||||||
from services.service_config import TL_M_KEY, SYSTEM_M_PROXY, ALAPI_M_TOKEN
|
|
||||||
from .path_config import DATA_PATH
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from .utils import ConfigsManager
|
||||||
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
# 是否使用配置文件
|
|
||||||
# 使用配置文件在每次启动时 plugins2info_dict, plugins2cd_dict, plugins2exists_dict 将从本地读取
|
|
||||||
# 除了 plugins2info_dict 新增内容键值会写入 plugins2info_file
|
|
||||||
# 其他修改或新增在 configs.config.py中对 plugins2info_dict, plugins2cd_dict, plugins2exists_dict 的配置无效
|
|
||||||
# 目录:data/configs/
|
|
||||||
USE_CONFIG_FILE: bool = False
|
|
||||||
|
|
||||||
# 回复消息名称
|
# 回复消息名称
|
||||||
NICKNAME: str = "小真寻"
|
NICKNAME: str = "小真寻"
|
||||||
|
|
||||||
# API KEY(必要)
|
|
||||||
RSSHUBAPP: str = "https://rsshub.app" # rsshub
|
|
||||||
ALAPI_TOKEN: str = "" # ALAPI https://admin.alapi.cn/user/login
|
|
||||||
HIBIAPI: str = "https://api.obfs.dev"
|
|
||||||
# 图灵
|
|
||||||
TL_KEY: List[str] = []
|
|
||||||
|
|
||||||
# 数据库(必要)
|
# 数据库(必要)
|
||||||
# 如果填写了bind就不需要再填写后面的字段了#)
|
# 如果填写了bind就不需要再填写后面的字段了#)
|
||||||
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
|
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
|
||||||
@@ -37,327 +17,8 @@ address: str = "" # 数据库地址
|
|||||||
port: str = "" # 数据库端口
|
port: str = "" # 数据库端口
|
||||||
database: str = "" # 数据库名称
|
database: str = "" # 数据库名称
|
||||||
|
|
||||||
# 代理
|
# 代理,例如 "http://127.0.0.1:7890"
|
||||||
SYSTEM_PROXY: Optional[str] = None # 全局代理
|
SYSTEM_PROXY: Optional[str] = None # 全局代理
|
||||||
BUFF_PROXY: Optional[str] = None # Buff代理
|
|
||||||
|
|
||||||
# 公开图库列表
|
|
||||||
IMAGE_DIR_LIST: List[str] = ["美图", "萝莉", "壁纸"]
|
|
||||||
|
|
||||||
# 对被ban用户发送的消息
|
|
||||||
BAN_RESULT: str = "才不会给你发消息."
|
|
||||||
|
|
||||||
# PIX图库下载的画质 可能的值:original:原图,master:缩略图(加快发送速度)
|
|
||||||
PIX_IMAGE_SIZE: str = "master"
|
|
||||||
|
|
||||||
|
|
||||||
# 插件配置
|
Config = ConfigsManager(Path() / "data" / "configs" / "plugins2config.yaml")
|
||||||
MAXINFO_REIMU: int = 7 # 上车(reimu)功能查找目的地的最大数
|
|
||||||
COUNT_PER_DAY_REIMU: int = 5 # 每日上车(reimu)次数限制
|
|
||||||
MAXINFO_BT: int = 10 # bt功能单次查找最大数
|
|
||||||
MAXINFO_PRIVATE_ANIME: int = 20 # 私聊搜索动漫返回的最大数量
|
|
||||||
MAXINFO_GROUP_ANIME: int = 5 # 群搜索动漫返回的最大数量
|
|
||||||
MAX_FIND_IMG_COUNT: int = 3 # 识图最大返回数
|
|
||||||
# 参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)
|
|
||||||
WITHDRAW_SETU_TIME: Tuple[int, int] = (90, 1)
|
|
||||||
# 参1:延迟撤回PIX图片时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)
|
|
||||||
WITHDRAW_PIX_TIME: Tuple[int, int] = (0, 1)
|
|
||||||
|
|
||||||
# PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1:PIX图库 参2:OmegaPixivIllusts扩展图库(没有此图库请设置为0)
|
|
||||||
PIX_OMEGA_PIXIV_RATIO: Tuple[int, int] = (2, 8)
|
|
||||||
|
|
||||||
# 各种卡池的开关
|
|
||||||
PRTS_FLAG = True # 明日方舟
|
|
||||||
GENSHIN_FLAG = True # 原神
|
|
||||||
PRETTY_FLAG = True # 赛马娘
|
|
||||||
GUARDIAN_FLAG = True # 坎公骑冠剑
|
|
||||||
PCR_FLAG = True # 公主连结
|
|
||||||
AZUR_FLAG = True # 碧蓝航线
|
|
||||||
FGO_FLAG = True # 命运-冠位指定(FGO)
|
|
||||||
ONMYOJI_FLAG = True # 阴阳师
|
|
||||||
|
|
||||||
PCR_TAI = True # pcr是否开启台服卡池
|
|
||||||
SEMAPHORE = 5 # 限制碧蓝航线和FGO并发数
|
|
||||||
|
|
||||||
ADMIN_DEFAULT_AUTH: int = 5 # 默认群管理员权限
|
|
||||||
|
|
||||||
MAX_SIGN_GOLD: int = 200 # 签到好感度加成额外获得的最大金币数
|
|
||||||
MAX_RUSSIAN_BET_GOLD: int = 1000 # 俄罗斯轮盘最大赌注金额
|
|
||||||
|
|
||||||
INITIAL_SETU_PROBABILITY: float = 0.7 # 色图概率
|
|
||||||
FUDU_PROBABILITY: float = 0.7 # 复读概率
|
|
||||||
|
|
||||||
INITIAL_OPEN_CASE_COUNT: int = 20 # 初始开箱次数
|
|
||||||
MUTE_DEFAULT_COUNT: int = 10 # 刷屏禁言默认检测次数
|
|
||||||
MUTE_DEFAULT_TIME: int = 7 # 刷屏检测默认规定时间
|
|
||||||
MUTE_DEFAULT_DURATION: int = 10 # 刷屏检测默禁言时长(分钟)
|
|
||||||
|
|
||||||
CHECK_NOTICE_INFO_CD = 300 # 群检测,个人权限检测等各种检测提示信息cd
|
|
||||||
|
|
||||||
# 注:即在 MALICIOUS_CHECK_TIME 时间内触发相同命令 MALICIOUS_BAN_COUNT 将被ban MALICIOUS_BAN_TIME 分钟
|
|
||||||
MALICIOUS_BAN_TIME: int = 30 # 恶意命令触发检测触发后ban的时长(分钟)
|
|
||||||
MALICIOUS_BAN_COUNT: int = 3 # 恶意命令触发检测最大触发次数
|
|
||||||
MALICIOUS_CHECK_TIME: int = 5 # 恶意命令触发检测规定时间内(秒)
|
|
||||||
|
|
||||||
# LEVEL
|
|
||||||
DELETE_IMG_LEVEL: int = 7 # 删除图片权限
|
|
||||||
MOVE_IMG_LEVEL: int = 7 # 移动图片权限
|
|
||||||
UPLOAD_LEVEL: int = 6 # 上传图片权限
|
|
||||||
BAN_LEVEL: int = 5 # BAN权限
|
|
||||||
OC_LEVEL: int = 2 # 开关群功能权限
|
|
||||||
MUTE_LEVEL: int = 5 # 更改禁言设置权限
|
|
||||||
MEMBER_ACTIVITY_LEVEL = 5 # 群员活跃检测设置权限
|
|
||||||
GROUP_BILIBILI_SUB_LEVEL = 5 # 群内bilibili订阅需要的权限
|
|
||||||
|
|
||||||
DEFAULT_GROUP_LEVEL = 5 # 默认群等级
|
|
||||||
|
|
||||||
# 是否开启HIBIAPI搜图功能(该功能会搜索群友提交的xp)
|
|
||||||
HIBIAPI_FLAG: bool = True
|
|
||||||
# HIBIAPI搜图图片的最低收藏
|
|
||||||
HIBIAPI_BOOKMARKS: int = 5000
|
|
||||||
|
|
||||||
# 需要为哪些群更新最新版gocq吗?(上传最新版gocq)
|
|
||||||
# 示例:[434995955, 239483248]
|
|
||||||
UPDATE_GOCQ_GROUP: List[int] = []
|
|
||||||
|
|
||||||
# 是否存储色图
|
|
||||||
DOWNLOAD_SETU: bool = True
|
|
||||||
# 仅仅使用本地色图
|
|
||||||
ONLY_USE_LOCAL_SETU: bool = False
|
|
||||||
# 是否自动同意好友添加
|
|
||||||
AUTO_ADD_FRIEND: bool = True
|
|
||||||
# 当含有ALAPI_TOKEN时是否检测文本合规,开启检测会减慢回复速度
|
|
||||||
ALAPI_AI_CHECK: bool = True
|
|
||||||
# 导入商店自带的三个商品
|
|
||||||
IMPORT_DEFAULT_SHOP_GOODS: bool = True
|
|
||||||
# 真寻是否自动更新
|
|
||||||
AUTO_UPDATE_ZHENXUN: bool = True
|
|
||||||
|
|
||||||
# 群管理员功能 与 对应权限
|
|
||||||
admin_plugins_auth = {
|
|
||||||
"custom_welcome_message": OC_LEVEL,
|
|
||||||
"group_notification_state": OC_LEVEL,
|
|
||||||
"switch_rule": OC_LEVEL,
|
|
||||||
"update_group_member_info": OC_LEVEL,
|
|
||||||
"ban": BAN_LEVEL,
|
|
||||||
"delete_img": DELETE_IMG_LEVEL,
|
|
||||||
"move_img": MOVE_IMG_LEVEL,
|
|
||||||
"upload_img": UPLOAD_LEVEL,
|
|
||||||
"admin_help": 1,
|
|
||||||
"mute": MUTE_LEVEL,
|
|
||||||
"member_activity_handle": MEMBER_ACTIVITY_LEVEL,
|
|
||||||
}
|
|
||||||
|
|
||||||
# 需要cd的功能(方便管理)[秒]
|
|
||||||
# 自定义的功能需要cd也可以在此配置
|
|
||||||
# key:模块名称
|
|
||||||
# cd:cd 时长(秒)
|
|
||||||
# status:此限制的开关状态
|
|
||||||
# check_type:'private'/'group'/'all',限制私聊/群聊/全部
|
|
||||||
# limit_type:监听对象,以user_id或group_id作为键来限制,'user':用户id,'group':群id
|
|
||||||
# 示例:'user':用户N秒内触发1次,'group':群N秒内触发1次
|
|
||||||
# rst:回复的话,可以添加[at],[uname],[nickname]来对应艾特,用户群名称,昵称系统昵称
|
|
||||||
# rst 为 "" 或 None 时则不回复
|
|
||||||
# rst示例:"[uname]你冲的太快了,[nickname]先生,请稍后再冲[at]"
|
|
||||||
# rst回复:"老色批你冲的太快了,欧尼酱先生,请稍后再冲@老色批"
|
|
||||||
# 用户昵称↑ 昵称系统的昵称↑ 艾特用户↑
|
|
||||||
plugins2cd_dict = {
|
|
||||||
"open_cases": {
|
|
||||||
"cd": 5,
|
|
||||||
"status": True,
|
|
||||||
"check_type": "all",
|
|
||||||
"limit_type": "user",
|
|
||||||
"rst": "着什么急啊,慢慢来!",
|
|
||||||
},
|
|
||||||
"send_setu": {
|
|
||||||
"cd": 5,
|
|
||||||
"status": True,
|
|
||||||
"check_type": "all",
|
|
||||||
"limit_type": "user",
|
|
||||||
"rst": "您冲得太快了,请稍候再冲",
|
|
||||||
},
|
|
||||||
"sign_in": {
|
|
||||||
"cd": 5,
|
|
||||||
"status": True,
|
|
||||||
"check_type": "group",
|
|
||||||
"limit_type": "user",
|
|
||||||
"rst": None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 用户调用阻塞(方便管理)
|
|
||||||
# 即 当用户调用此功能还未结束时
|
|
||||||
# 用发送消息阻止用户重复调用此命令直到该命令结束
|
|
||||||
# 参数同上 plugin2cd_dict
|
|
||||||
plugins2exists_dict = {
|
|
||||||
"send_setu": {
|
|
||||||
"status": False,
|
|
||||||
"check_type": "all",
|
|
||||||
"limit_type": "user",
|
|
||||||
"rst": "您有色图正在处理,请稍等.....",
|
|
||||||
},
|
|
||||||
"pixiv": {
|
|
||||||
"status": True,
|
|
||||||
"check_type": "all",
|
|
||||||
"limit_type": "user",
|
|
||||||
"rst": "P站排行榜或搜图正在搜索,请不要重复触发命令...",
|
|
||||||
},
|
|
||||||
"pix": {
|
|
||||||
"status": True,
|
|
||||||
"check_type": "all",
|
|
||||||
"limit_type": "user",
|
|
||||||
"rst": "您有PIX图片正在处理,请稍等...",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 模块与对应命令和对应群权限
|
|
||||||
# 用于生成帮助图片 和 开关功能
|
|
||||||
# key:模块名称
|
|
||||||
# level:需要的群等级
|
|
||||||
# default_status:加入群时功能的默认开关状态
|
|
||||||
# cmd:关闭[cmd] 都会触发命令 关闭对应功能,cmd列表第一个词为统计的功能名称
|
|
||||||
plugins2info_dict = {
|
|
||||||
"sign_in": {"level": 5, "default_status": True, "cmd": ["签到"]},
|
|
||||||
"send_img": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["发送图片", "发图", "萝莉", "美图", "壁纸"],
|
|
||||||
},
|
|
||||||
"send_setu": {"level": 9, "default_status": True, "cmd": ["色图", "涩图", "瑟图", "查色图"]},
|
|
||||||
"white2black": {"level": 5, "default_status": True, "cmd": ["黑白图", "黑白草图"]},
|
|
||||||
"coser": {"level": 9, "default_status": True, "cmd": ["coser", "cos"]},
|
|
||||||
"quotations": {"level": 5, "default_status": True, "cmd": ["语录"]},
|
|
||||||
"jitang": {"level": 5, "default_status": True, "cmd": ["鸡汤"]},
|
|
||||||
"send_dinggong_voice": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["骂我", "骂老子", "骂劳资"],
|
|
||||||
},
|
|
||||||
"open_cases": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["开箱", "我的开箱", "群开箱统计", "我的金色"],
|
|
||||||
},
|
|
||||||
"luxun": {"level": 5, "default_status": True, "cmd": ["鲁迅说", "鲁迅说过"]},
|
|
||||||
"fake_msg": {"level": 5, "default_status": True, "cmd": ["假消息"]},
|
|
||||||
"buy": {"level": 5, "default_status": True, "cmd": ["购买", "购买道具"]},
|
|
||||||
"my_gold": {"level": 5, "default_status": True, "cmd": ["我的金币"]},
|
|
||||||
"my_props": {"level": 5, "default_status": True, "cmd": ["我的道具"]},
|
|
||||||
"shop_handle": {"level": 5, "default_status": True, "cmd": ["商店"]},
|
|
||||||
"update_pic": {"level": 5, "default_status": True, "cmd": ["图片", "操作图片", "修改图片"]},
|
|
||||||
"search_buff_skin_price": {"level": 5, "default_status": True, "cmd": ["查询皮肤"]},
|
|
||||||
"weather": {"level": 5, "default_status": True, "cmd": ["天气", "查询天气", "天气查询"]},
|
|
||||||
"yiqing": {"level": 5, "default_status": True, "cmd": ["疫情", "疫情查询", "查询疫情"]},
|
|
||||||
"what_anime": {"level": 5, "default_status": True, "cmd": ["识番"]},
|
|
||||||
"search_anime": {"level": 5, "default_status": True, "cmd": ["搜番"]},
|
|
||||||
"songpicker2": {"level": 5, "default_status": True, "cmd": ["点歌"]},
|
|
||||||
"epic": {"level": 5, "default_status": True, "cmd": ["epic"]},
|
|
||||||
"pixiv": {"level": 9, "default_status": True, "cmd": ["pixiv", "p站排行", "搜图"]},
|
|
||||||
"poke": {"level": 5, "default_status": True, "cmd": ["戳一戳", "拍一拍"]},
|
|
||||||
"draw_card": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": [
|
|
||||||
"抽卡",
|
|
||||||
"游戏抽卡",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"ai": {"level": 5, "default_status": True, "cmd": ["ai", "Ai", "AI", "aI"]},
|
|
||||||
"one_friend": {"level": 5, "default_status": True, "cmd": ["我有一个朋友", "我有一个朋友想问问"]},
|
|
||||||
"translate": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["翻译", "英翻", "翻英", "日翻", "翻日", "韩翻", "翻韩"],
|
|
||||||
},
|
|
||||||
"nonebot_plugin_picsearcher": {"level": 5, "default_status": True, "cmd": ["识图"]},
|
|
||||||
"almanac": {"level": 5, "default_status": True, "cmd": ["原神黄历", "黄历"]},
|
|
||||||
"material_remind": {"level": 5, "default_status": True, "cmd": ["今日素材", "天赋材料"]},
|
|
||||||
"qiu_qiu_translation": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["丘丘翻译", "丘丘一下", "丘丘语翻译"],
|
|
||||||
},
|
|
||||||
"query_resource_points": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["原神资源查询", "原神资源列表"],
|
|
||||||
},
|
|
||||||
"russian": {"level": 5, "default_status": True, "cmd": ["俄罗斯轮盘", "俄罗斯转盘", "装弹"]},
|
|
||||||
"gold_redbag": {"level": 5, "default_status": True, "cmd": ["塞红包", "红包", "抢红包"]},
|
|
||||||
"poetry": {"level": 5, "default_status": True, "cmd": ["念诗", "来首诗", "念首诗"]},
|
|
||||||
"comments_163": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["到点了", "12点了", "网易云热评", "网易云评论"],
|
|
||||||
},
|
|
||||||
"cover": {"level": 5, "default_status": True, "cmd": ["b封面", "B封面"]},
|
|
||||||
"pid_search": {"level": 9, "default_status": True, "cmd": ["p搜", "P搜"]},
|
|
||||||
"pix": {
|
|
||||||
"level": 5,
|
|
||||||
"default_status": True,
|
|
||||||
"cmd": ["pix", "PIX", "pIX", "Pix", "PIx"],
|
|
||||||
},
|
|
||||||
"wbtop": {"level": 5, "default_status": True, "cmd": ["微博热搜", "微博", "wbtop"]},
|
|
||||||
"update_info": {"level": 5, "default_status": True, "cmd": ["更新信息", "更新日志"]},
|
|
||||||
}
|
|
||||||
|
|
||||||
if TL_M_KEY:
|
|
||||||
TL_KEY = TL_M_KEY
|
|
||||||
if SYSTEM_M_PROXY:
|
|
||||||
SYSTEM_PROXY = SYSTEM_M_PROXY
|
|
||||||
if ALAPI_M_TOKEN:
|
|
||||||
ALAPI_TOKEN = ALAPI_M_TOKEN
|
|
||||||
|
|
||||||
|
|
||||||
HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] == "/" else HIBIAPI
|
|
||||||
RSSHUBAPP = RSSHUBAPP[:-1] if RSSHUBAPP[-1] == "/" else RSSHUBAPP
|
|
||||||
|
|
||||||
|
|
||||||
if USE_CONFIG_FILE:
|
|
||||||
# 读取配置文件
|
|
||||||
plugins2info_file = Path(DATA_PATH) / 'configs' / 'plugins2info.json'
|
|
||||||
plugins2info_file.parent.mkdir(exist_ok=True, parents=True)
|
|
||||||
|
|
||||||
if plugins2info_file.exists():
|
|
||||||
with open(plugins2info_file, 'r') as f:
|
|
||||||
_data = json.load(f)
|
|
||||||
for p in plugins2info_dict:
|
|
||||||
if not _data.get(p):
|
|
||||||
_data[p] = plugins2info_dict[p]
|
|
||||||
with open(plugins2info_file, 'w') as wf:
|
|
||||||
json.dump(_data, wf, ensure_ascii=False, indent=4)
|
|
||||||
plugins2info_dict = _data
|
|
||||||
else:
|
|
||||||
with open(plugins2info_file, 'w', encoding='utf8') as wf:
|
|
||||||
json.dump(plugins2info_dict, wf, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
plugins2cd_file = Path(DATA_PATH) / 'configs' / 'plugins2cd.json'
|
|
||||||
if plugins2cd_file.exists():
|
|
||||||
with open(plugins2cd_file, 'r', encoding='utf8') as f:
|
|
||||||
plugins2cd_dict = json.load(f)
|
|
||||||
else:
|
|
||||||
with open(plugins2cd_file, 'w', encoding='utf8') as wf:
|
|
||||||
json.dump(plugins2cd_dict, wf, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
plugins2exists_file = Path(DATA_PATH) / 'configs' / 'plugins2exists.json'
|
|
||||||
if plugins2exists_file.exists():
|
|
||||||
with open(plugins2exists_file, 'r', encoding='utf8') as f:
|
|
||||||
plugins2exists_dict = json.load(f)
|
|
||||||
else:
|
|
||||||
with open(plugins2exists_file, 'w', encoding='utf8') as wf:
|
|
||||||
json.dump(plugins2exists_dict, wf, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
|
|
||||||
# 配置文件应用
|
|
||||||
# if USE_CONFIG_FILE:
|
|
||||||
# config = get_config_data()
|
|
||||||
# if config:
|
|
||||||
# for key in config.keys():
|
|
||||||
# if isinstance(config[key], str):
|
|
||||||
# config[key] = config[key].strip()
|
|
||||||
# if key.find("proxy") != -1:
|
|
||||||
# if not config[key]:
|
|
||||||
# config[key] = None
|
|
||||||
# # if not configs[key] and key.find("PATH") == -1:
|
|
||||||
# # configs[key] = None
|
|
||||||
# globals().update(config)
|
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
from .utils.util import get_config_data
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
# from configs.config import USE_CONFIG_FILE
|
|
||||||
|
|
||||||
# 图片路径
|
# 图片路径
|
||||||
IMAGE_PATH = Path("resources/img/")
|
IMAGE_PATH = Path("resources/img/")
|
||||||
# 音频路径
|
# 音频路径
|
||||||
VOICE_PATH = Path("resources/voice/")
|
VOICE_PATH = Path("resources/voice/")
|
||||||
# 文本路径
|
# 文本路径
|
||||||
TXT_PATH = Path("resources/txt/")
|
TEXT_PATH = Path("resources/txt/")
|
||||||
# 日志路径
|
# 日志路径
|
||||||
LOG_PATH = Path("log/")
|
LOG_PATH = Path("log/")
|
||||||
# 字体路径
|
# 字体路径
|
||||||
TTF_PATH = Path("resources/ttf/")
|
FONT_PATH = Path("resources/ttf/")
|
||||||
# 数据路径
|
# 数据路径
|
||||||
DATA_PATH = Path("data/")
|
DATA_PATH = Path("data/")
|
||||||
# 临时图片路径
|
# 临时图片路径
|
||||||
@@ -19,38 +17,20 @@ TEMP_PATH = Path("resources/img/temp/")
|
|||||||
|
|
||||||
|
|
||||||
def init_path():
|
def init_path():
|
||||||
global IMAGE_PATH, VOICE_PATH, TXT_PATH, LOG_PATH, TTF_PATH, DATA_PATH, TEMP_PATH
|
global IMAGE_PATH, VOICE_PATH, TEXT_PATH, LOG_PATH, FONT_PATH, DATA_PATH, TEMP_PATH
|
||||||
# if USE_CONFIG_FILE:
|
|
||||||
# data = get_config_data()
|
|
||||||
# if data.get('IMAGE_PATH'):
|
|
||||||
# IMAGE_PATH = Path(data['IMAGE_PATH'])
|
|
||||||
# if data.get('VOICE_PATH'):
|
|
||||||
# VOICE_PATH = Path(data['VOICE_PATH'])
|
|
||||||
# if data.get('TXT_PATH'):
|
|
||||||
# TXT_PATH = Path(data['TXT_PATH'])
|
|
||||||
# if data.get('LOG_PATH'):
|
|
||||||
# LOG_PATH = Path(data['LOG_PATH'])
|
|
||||||
# if data.get('TTF_PATH'):
|
|
||||||
# TTF_PATH = Path(data['TTF_PATH'])
|
|
||||||
# if data.get('DATA_PATH'):
|
|
||||||
# DATA_PATH = Path(data['DATA_PATH'])
|
|
||||||
# if data.get('DRAW_PATH'):
|
|
||||||
# DRAW_PATH = Path(data['DRAW_PATH'])
|
|
||||||
# if data.get('TEMP_PATH'):
|
|
||||||
# TEMP_PATH = Path(data['TEMP_PATH'])
|
|
||||||
IMAGE_PATH.mkdir(parents=True, exist_ok=True)
|
IMAGE_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
VOICE_PATH.mkdir(parents=True, exist_ok=True)
|
VOICE_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
TXT_PATH.mkdir(parents=True, exist_ok=True)
|
TEXT_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
LOG_PATH.mkdir(parents=True, exist_ok=True)
|
LOG_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
TTF_PATH.mkdir(parents=True, exist_ok=True)
|
FONT_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
DATA_PATH.mkdir(parents=True, exist_ok=True)
|
DATA_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
TEMP_PATH.mkdir(parents=True, exist_ok=True)
|
TEMP_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
IMAGE_PATH = str(IMAGE_PATH.absolute()) + '/'
|
IMAGE_PATH = str(IMAGE_PATH.absolute()) + '/'
|
||||||
VOICE_PATH = str(VOICE_PATH.absolute()) + '/'
|
VOICE_PATH = str(VOICE_PATH.absolute()) + '/'
|
||||||
TXT_PATH = str(TXT_PATH.absolute()) + '/'
|
TEXT_PATH = str(TEXT_PATH.absolute()) + '/'
|
||||||
LOG_PATH = str(LOG_PATH.absolute()) + '/'
|
LOG_PATH = str(LOG_PATH.absolute()) + '/'
|
||||||
TTF_PATH = str(TTF_PATH.absolute()) + '/'
|
FONT_PATH = str(FONT_PATH.absolute()) + '/'
|
||||||
DATA_PATH = str(DATA_PATH.absolute()) + '/'
|
DATA_PATH = str(DATA_PATH.absolute()) + '/'
|
||||||
TEMP_PATH = str(TEMP_PATH.absolute()) + '/'
|
TEMP_PATH = str(TEMP_PATH.absolute()) + '/'
|
||||||
|
|
||||||
@@ -58,5 +38,4 @@ def init_path():
|
|||||||
init_path()
|
init_path()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print(IMAGE_PATH)
|
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
from typing import Optional, Any, Union
|
||||||
|
from pathlib import Path
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
from ruamel import yaml
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigsManager:
|
||||||
|
"""
|
||||||
|
插件配置 与 资源 管理器
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, file: Path):
|
||||||
|
self._data: dict = {}
|
||||||
|
self._admin_level_data = []
|
||||||
|
if file:
|
||||||
|
file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
self.file = file
|
||||||
|
if file.exists():
|
||||||
|
_yaml = YAML()
|
||||||
|
with open(file, "r", encoding="utf8") as f:
|
||||||
|
self._data = _yaml.load(f)
|
||||||
|
|
||||||
|
def add_plugin_config(
|
||||||
|
self,
|
||||||
|
module: str,
|
||||||
|
key: str,
|
||||||
|
value: Optional[Any],
|
||||||
|
*,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
help_: Optional[str] = None,
|
||||||
|
default_value: Optional[str] = None,
|
||||||
|
_override: bool = False,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
为插件添加一个配置,不会被覆盖,只有第一个生效
|
||||||
|
:param module: 模块
|
||||||
|
:param key: 键
|
||||||
|
:param value: 值
|
||||||
|
:param name: 插件名称
|
||||||
|
:param help_: 配置注解
|
||||||
|
:param default_value: 默认值
|
||||||
|
:param _override: 覆盖前值
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
not (module in self._data.keys() and self._data[module].get(key))
|
||||||
|
or _override
|
||||||
|
):
|
||||||
|
_module = None
|
||||||
|
if ":" in module:
|
||||||
|
module = module.split(":")
|
||||||
|
_module = module[-1]
|
||||||
|
module = module[0]
|
||||||
|
if "[LEVEL]" in key and _module:
|
||||||
|
key = key.replace("[LEVEL]", "").strip()
|
||||||
|
self._admin_level_data.append((_module, value))
|
||||||
|
if self._data.get(module) is None:
|
||||||
|
self._data[module] = {}
|
||||||
|
key = key.upper()
|
||||||
|
self._data[module][key] = {
|
||||||
|
"value": value,
|
||||||
|
"name": name.strip() if isinstance(name, str) else name,
|
||||||
|
"help": help_.strip() if isinstance(help_, str) else help_,
|
||||||
|
"default_value": default_value,
|
||||||
|
"level_module": _module,
|
||||||
|
}
|
||||||
|
|
||||||
|
def remove_plugin_config(self, module: str):
|
||||||
|
"""
|
||||||
|
为插件删除一个配置
|
||||||
|
:param module: 模块名
|
||||||
|
"""
|
||||||
|
if module in self._data.keys():
|
||||||
|
del self._data[module]
|
||||||
|
|
||||||
|
def set_config(self, module: str, key: str, value: str):
|
||||||
|
"""
|
||||||
|
设置配置值
|
||||||
|
:param module: 模块名
|
||||||
|
:param key: 配置名称
|
||||||
|
:param value: 值
|
||||||
|
"""
|
||||||
|
if module in self._data.keys():
|
||||||
|
if self._data[module].get(key) is not None:
|
||||||
|
self._data[module][key]["value"] = value
|
||||||
|
|
||||||
|
def set_help(self, module: str, key: str, help_: str):
|
||||||
|
"""
|
||||||
|
设置配置注释
|
||||||
|
:param module: 模块名
|
||||||
|
:param key: 配置名称
|
||||||
|
:param help_: 注释文本
|
||||||
|
"""
|
||||||
|
if module in self._data.keys():
|
||||||
|
if self._data[module].get(key) is not None:
|
||||||
|
self._data[module][key]["help"] = help_
|
||||||
|
|
||||||
|
def set_default_value(self, module: str, key: str, value: str):
|
||||||
|
"""
|
||||||
|
设置配置默认值
|
||||||
|
:param module: 模块名
|
||||||
|
:param key: 配置名称
|
||||||
|
:param value: 值
|
||||||
|
"""
|
||||||
|
if module in self._data.keys():
|
||||||
|
if self._data[module].get(key) is not None:
|
||||||
|
self._data[module][key]["default_value"] = value
|
||||||
|
|
||||||
|
def get_config(self, module: str, key: str, default: Optional[Any] = None) -> Optional[Any]:
|
||||||
|
"""
|
||||||
|
获取指定配置值
|
||||||
|
:param module: 模块名
|
||||||
|
:param key: 配置名称
|
||||||
|
:param default: 没有key值内容的默认返回值
|
||||||
|
"""
|
||||||
|
key = key.upper()
|
||||||
|
if module in self._data.keys():
|
||||||
|
for key in [key, f"{key} [LEVEL]"]:
|
||||||
|
if self._data[module].get(key) is not None:
|
||||||
|
if self._data[module][key]["value"] is None:
|
||||||
|
return self._data[module][key]["default_value"]
|
||||||
|
return self._data[module][key]["value"]
|
||||||
|
if default is not None:
|
||||||
|
return default
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_level2module(self, module: str, key: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取指定key所绑定的module,一般为权限等级
|
||||||
|
:param module: 模块名
|
||||||
|
:param key: 配置名称
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self._data.get(module) is not None:
|
||||||
|
if self._data[module].get(key) is not None:
|
||||||
|
return self._data[module][key].get("level_module")
|
||||||
|
|
||||||
|
def get(self, key: str):
|
||||||
|
"""
|
||||||
|
获取插件配置数据
|
||||||
|
:param key: 名称
|
||||||
|
"""
|
||||||
|
if key in self._data.keys():
|
||||||
|
return self._data[key]
|
||||||
|
|
||||||
|
def save(self, path: Union[str, Path] = None):
|
||||||
|
"""
|
||||||
|
保存数据
|
||||||
|
:param path: 路径
|
||||||
|
"""
|
||||||
|
path = path if path else self.file
|
||||||
|
with open(path, "w", encoding="utf8") as f:
|
||||||
|
yaml.dump(
|
||||||
|
self._data, f, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_admin_level_data(self):
|
||||||
|
"""
|
||||||
|
获取管理插件等级
|
||||||
|
"""
|
||||||
|
return self._admin_level_data
|
||||||
|
|
||||||
|
def is_empty(self) -> bool:
|
||||||
|
return not bool(self._data)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return self._data.keys()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self._data)
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
self._data[key] = value
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self._data[key]
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
# import nonebot
|
|
||||||
from pathlib import Path
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
import json
|
|
||||||
|
|
||||||
# driver: nonebot.Driver = nonebot.get_driver()
|
|
||||||
|
|
||||||
base_config = Path() / 'config.json'
|
|
||||||
plugins_cmd_config = Path() / 'configs' / 'plugins2cmd_config.json'
|
|
||||||
plugins_setting = Path() / 'configs' / 'plugins_setting.json'
|
|
||||||
|
|
||||||
|
|
||||||
def init_config():
|
|
||||||
if not base_config.exists():
|
|
||||||
base_config.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
config_dict = {
|
|
||||||
'apikey': {
|
|
||||||
'LOLICON_KEY': '',
|
|
||||||
'TL_KEY': [],
|
|
||||||
},
|
|
||||||
'sql': {
|
|
||||||
'bind': '',
|
|
||||||
'sql_name': '',
|
|
||||||
'user': '',
|
|
||||||
'password': '',
|
|
||||||
'address': '',
|
|
||||||
'port': '',
|
|
||||||
'database': '',
|
|
||||||
},
|
|
||||||
'path': {
|
|
||||||
'IMAGE_PATH': '',
|
|
||||||
'VOICE_PATH': '',
|
|
||||||
'TXT_PATH': '',
|
|
||||||
'LOG_PATH': '',
|
|
||||||
'DATA_PATH': '',
|
|
||||||
'DRAW_PATH': '',
|
|
||||||
'TEMP_PATH': '',
|
|
||||||
},
|
|
||||||
'proxy': {
|
|
||||||
'system_proxy': '',
|
|
||||||
'buff_proxy': ''
|
|
||||||
},
|
|
||||||
'level': {
|
|
||||||
'DELETE_IMG_LEVEL': 7,
|
|
||||||
'MOVE_IMG_LEVEL': 7,
|
|
||||||
'UPLOAD_LEVEL': 6,
|
|
||||||
'BAN_LEVEL': 5,
|
|
||||||
'OC_LEVEL': 2,
|
|
||||||
'MUTE_LEVEL': 5,
|
|
||||||
},
|
|
||||||
'auth': {
|
|
||||||
'ADMIN_DEFAULT_AUTH': 5,
|
|
||||||
'admin_plugins_auth': {
|
|
||||||
"admin_bot_manage": 2,
|
|
||||||
"ban": 5,
|
|
||||||
"delete_img": 7,
|
|
||||||
"move_img": 7,
|
|
||||||
"upload_img": 6,
|
|
||||||
"admin_help": 1,
|
|
||||||
"mute": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with open(base_config, 'w', encoding='utf8') as f:
|
|
||||||
json.dump(config_dict, f, indent=4, ensure_ascii=False)
|
|
||||||
if not plugins_cmd_config.exists():
|
|
||||||
plugins_cmd_config.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
config_dict = {
|
|
||||||
'base_config': {
|
|
||||||
'sign_in': ['签到'],
|
|
||||||
'send_img': ['发送图片', '萝莉', '美图', '壁纸'],
|
|
||||||
'send_setu': ['色图', '涩图', '瑟图', '查色图'],
|
|
||||||
'white2black': ['黑白图', '黑白草图'],
|
|
||||||
'coser': ['coser', 'cos'],
|
|
||||||
'quotations': ['语录'],
|
|
||||||
'jitang': ['鸡汤'],
|
|
||||||
'send_dinggong_voice': ['骂我', '骂老子', '骂劳资'],
|
|
||||||
'open_cases': ['开箱', '我的开箱', '群开箱统计', '我的金色'],
|
|
||||||
'luxun': ['鲁迅说过', '鲁迅说'],
|
|
||||||
'fake_msg': ['假消息'],
|
|
||||||
'buy': ['购买', '购买道具'],
|
|
||||||
'my_gold': ['我的金币'],
|
|
||||||
'my_props': ['我的道具'],
|
|
||||||
'shop_handle': ['商店'],
|
|
||||||
'nonebot_plugin_cocdicer': ['骰子娘'],
|
|
||||||
'update_pic': ['图片', '操作图片', '修改图片'],
|
|
||||||
'search_buff_skin_price': ['查询皮肤'],
|
|
||||||
'weather': ['天气', '查询天气', '天气查询'],
|
|
||||||
'yiqing': ['疫情', '疫情查询', '查询疫情'],
|
|
||||||
'what_anime': ['识番'],
|
|
||||||
'search_anime': ['搜番'],
|
|
||||||
'songpicker2': ['点歌'],
|
|
||||||
'epic': ['epic'],
|
|
||||||
'pixiv': ['pixiv', 'p站排行', '搜图'],
|
|
||||||
'poke': ['戳一戳'],
|
|
||||||
'draw_card': ['游戏抽卡', '原神一井', '原神来一井', '方舟一井', '方舟来一井'],
|
|
||||||
'ai': ['ai', 'Ai', 'AI', 'aI'],
|
|
||||||
'one_friend': ['我有一个朋友', '我有一个朋友想问问'],
|
|
||||||
'translate': ['翻译', '英翻', '翻英', '日翻', '翻日', '韩翻', '翻韩'],
|
|
||||||
'nonebot_plugin_picsearcher': ['识图'],
|
|
||||||
'almanac': ['原神黄历', '黄历'],
|
|
||||||
'material_remind': ['今日素材', '天赋材料'],
|
|
||||||
'qiu_qiu_translation': ['丘丘翻译', '丘丘一下', '丘丘语翻译'],
|
|
||||||
'query_resource_points': ['原神资源查询', '原神资源列表'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with open(plugins_cmd_config, 'w', encoding='utf8') as f:
|
|
||||||
json.dump(config_dict, f, indent=4, ensure_ascii=False)
|
|
||||||
if not plugins_setting.exists():
|
|
||||||
plugins_setting.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
config_dict = {
|
|
||||||
'base': {
|
|
||||||
'IMAGE_DIR_LIST': ["色图", "美图", "萝莉", "壁纸"],
|
|
||||||
'BAN_RESULT': "才不会给你发消息.",
|
|
||||||
},
|
|
||||||
'draw_card': {
|
|
||||||
'PRTS_FLAG': True, # 明日方舟
|
|
||||||
'GENSHIN_FLAG': True, # 原神
|
|
||||||
'PRETTY_FLAG': True, # 赛马娘
|
|
||||||
'GUARDIAN_FLAG': True, # 坎公骑冠剑
|
|
||||||
'PCR_FLAG': True, # 公主连结
|
|
||||||
'AZUR_FLAG': True, # 碧蓝航线
|
|
||||||
'FGO_FLAG': True, # 命运-冠位指定(FGO)
|
|
||||||
'ONMYOJI_FLAG': True, # 阴阳师
|
|
||||||
|
|
||||||
'PCR_TAI': False # pcr是否开启台服卡池
|
|
||||||
},
|
|
||||||
'fudu': {
|
|
||||||
'FUDU_PROBABILITY': 0.7,
|
|
||||||
},
|
|
||||||
'reimu': {
|
|
||||||
'MAXINFO_REIMU': 7,
|
|
||||||
'COUNT_PER_DAY_REIMU': 5,
|
|
||||||
},
|
|
||||||
'bt': {
|
|
||||||
'MAXINFO_BT': 10,
|
|
||||||
},
|
|
||||||
'search_anime': {
|
|
||||||
'MAXINFO_PRIVATE_ANIME': 20,
|
|
||||||
'MAXINFO_GROUP_ANIME': 5,
|
|
||||||
},
|
|
||||||
'picsearcher': {
|
|
||||||
'MAX_FIND_IMG_COUNT': 3,
|
|
||||||
},
|
|
||||||
'sign': {
|
|
||||||
'MAX_SIGN_GOLD': 200,
|
|
||||||
},
|
|
||||||
'send_setu': {
|
|
||||||
'INITIAL_SETU_PROBABILITY': 0.7,
|
|
||||||
'MAX_SETU_R_COUNT': 5,
|
|
||||||
'DOWNLOAD_SETU': True,
|
|
||||||
},
|
|
||||||
'malicious_ban': {
|
|
||||||
'MALICIOUS_BAN_TIME': 30,
|
|
||||||
'MALICIOUS_BAN_COUNT': 8,
|
|
||||||
'MALICIOUS_CHECK_TIME': 5,
|
|
||||||
},
|
|
||||||
'open_case': {
|
|
||||||
'INITIAL_OPEN_CASE_COUNT': 20,
|
|
||||||
},
|
|
||||||
'mute': {
|
|
||||||
'MUTE_DEFAULT_COUNT': 10,
|
|
||||||
'MUTE_DEFAULT_TIME': 7,
|
|
||||||
'MUTE_DEFAULT_DURATION': 10,
|
|
||||||
},
|
|
||||||
'update_gocq': {
|
|
||||||
'UPDATE_GOCQ_GROUP': [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
with open(plugins_setting, 'w', encoding='utf8') as f:
|
|
||||||
json.dump(config_dict, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
from configs.utils.init_config import init_config
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
data: dict = {}
|
|
||||||
|
|
||||||
|
|
||||||
def get_config_data():
|
|
||||||
global data
|
|
||||||
if not data:
|
|
||||||
try:
|
|
||||||
base_config = json.load(open(Path() / "config.json", 'r', encoding='utf8'))
|
|
||||||
plugins2cmd_config = json.load(open(Path() / 'configs' / 'plugins2cmd_config.json', 'r', encoding='utf8'))
|
|
||||||
other_config = json.load(open(Path() / 'configs' / 'other_config.json', 'r', encoding='utf8'))
|
|
||||||
for key in base_config.keys():
|
|
||||||
data.update(base_config[key])
|
|
||||||
for key in plugins2cmd_config.keys():
|
|
||||||
data.update(plugins2cmd_config[key])
|
|
||||||
for key in other_config.keys():
|
|
||||||
data.update(other_config[key])
|
|
||||||
except FileNotFoundError:
|
|
||||||
# logger.warning('配置文件不存在,生成默认配置....请填写数据库等必要数据后再次启动bot...')
|
|
||||||
init_config()
|
|
||||||
raise FileNotFoundError('配置文件不存在,生成默认配置....请填写数据库等必要数据后再次启动bot...')
|
|
||||||
except ValueError:
|
|
||||||
# logger.error('配置文件错误....')
|
|
||||||
raise ValueError('配置文件错误....')
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 697 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 251 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 289 KiB |
|
Before Width: | Height: | Size: 424 KiB |
|
Before Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 341 KiB |
|
Before Width: | Height: | Size: 220 KiB |