Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14d1512b1e | ||
|
|
3f533516af | ||
|
|
f1354308fd | ||
|
|
c06248e46b | ||
|
|
9c8eaed938 | ||
|
|
2081302e32 | ||
|
|
678fc19f2d | ||
|
|
adc2757e8e | ||
|
|
82a1261371 | ||
|
|
067da9dc57 | ||
|
|
0eb9f9fc6f | ||
|
|
aee1340714 | ||
|
|
a72a9bd8cb | ||
|
|
7250410653 | ||
|
|
12f55800b0 | ||
|
|
53b375b4b2 | ||
|
|
fba27abe29 | ||
|
|
4caa3dec04 | ||
|
|
516b0f5ccb | ||
|
|
b5098be08e | ||
|
|
5b08a4650c | ||
|
|
eb02157b94 | ||
|
|
222e1719a4 | ||
|
|
3c8983e753 | ||
|
|
1fe41dd823 | ||
|
|
e8df59203c | ||
|
|
0f6690606b | ||
|
|
a0115309dd | ||
|
|
ca18d45786 | ||
|
|
76df21036a | ||
|
|
c674d581b7 | ||
|
|
fc53c3c487 | ||
|
|
7a4e31df80 | ||
|
|
f1d308d559 | ||
|
|
b7914bac05 | ||
|
|
8c40d88cc4 | ||
|
|
b4ed6dcb5d | ||
|
|
0d3bd8a89c | ||
|
|
87f0189abd | ||
|
|
1c17ac1f9d | ||
|
|
f038763041 | ||
|
|
eaf6d54757 | ||
|
|
d7368c83bc | ||
|
|
4011620da1 | ||
|
|
6e0b91531e | ||
|
|
b8ca1d68aa | ||
|
|
2b9cda40a0 | ||
|
|
d8983bdcbf | ||
|
|
14bce52f2f | ||
|
|
a7b0f7da68 | ||
|
|
7dd68cf1ef | ||
|
|
ab443a21ec | ||
|
|
ed7e8a8a4c | ||
|
|
a1435e2fc4 | ||
|
|
44a80f89da | ||
|
|
164f6af30c | ||
|
|
9093a79101 | ||
|
|
14cce89a18 | ||
|
|
4bce20a0a9 | ||
|
|
f32d8b4eff | ||
|
|
685f2b8c53 | ||
|
|
1e63ca2549 | ||
|
|
c1bc4eff2b | ||
|
|
bc903d3813 | ||
|
|
80fc17b610 | ||
|
|
0efb2bbc60 | ||
|
|
95ad533b87 | ||
|
|
b6e3240df9 | ||
|
|
5ae41e1d38 | ||
|
|
8022ae1fb1 | ||
|
|
0163fc1d88 | ||
|
|
5d9ab40e35 | ||
|
|
b1ca7930bb | ||
|
|
40111261ed | ||
|
|
4cb91b47e6 | ||
|
|
30b56583bd | ||
|
|
5e5168f804 | ||
|
|
4a8122829e | ||
|
|
52ba2cf89a | ||
|
|
58957cdf44 | ||
|
|
71f860a500 | ||
|
|
9b4cde819e | ||
|
|
99637de1de | ||
|
|
19dbd3f2b0 | ||
|
|
7567794f74 | ||
|
|
df0d15c1b3 | ||
|
|
9a84c02bb5 | ||
|
|
e623c4f30f | ||
|
|
3fd7acffb2 | ||
|
|
71f8c16c26 | ||
|
|
b64699c4ab | ||
|
|
786d62bb2f | ||
|
|
ac48d3d542 | ||
|
|
c4d9523ec2 | ||
|
|
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 | ||
|
|
133b927d9d | ||
|
|
46e6b26d75 | ||
|
|
8d0b0e5505 | ||
|
|
754a0c111c | ||
|
|
81ef3f04e4 | ||
|
|
e7c00484b3 | ||
|
|
065432448f | ||
|
|
5d45a9c28a | ||
|
|
7db5b3b5c0 | ||
|
|
5eb64060dc | ||
|
|
2c4877b9f8 | ||
|
|
218dad3b86 | ||
|
|
974c6b106a | ||
|
|
954b281b69 | ||
|
|
b1b15b63a1 | ||
|
|
49567aa958 | ||
|
|
a7a470066b | ||
|
|
4e3010d75e | ||
|
|
cbacd726ef | ||
|
|
58a1fc1ca0 | ||
|
|
a704f88d75 | ||
|
|
10d0ad7d47 | ||
|
|
b47a29eb67 | ||
|
|
887177913d | ||
|
|
b6b0dc85bf | ||
|
|
29f47878e9 | ||
|
|
440b548a4f | ||
|
|
5191953657 | ||
|
|
877ac72761 | ||
|
|
685befee6b | ||
|
|
7afb099c12 | ||
|
|
21a5feda43 | ||
|
|
b7b16cfd21 | ||
|
|
615f3a58e9 | ||
|
|
f65fd73d6d | ||
|
|
6a8eb9e67a | ||
|
|
8b7adf0a6a | ||
|
|
973182c27c | ||
|
|
0dced0bc90 |
@@ -0,0 +1,147 @@
|
|||||||
|
### 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_ip.py
|
||||||
|
member_activity_handle.py
|
||||||
|
Yu-Gi-Oh/
|
||||||
|
black_word/
|
||||||
|
csgo/
|
||||||
|
fantasy_card/
|
||||||
@@ -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>.
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
__version__: v0.1.4.4
|
||||||
@@ -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")
|
||||||
@@ -0,0 +1,323 @@
|
|||||||
|
from typing import List
|
||||||
|
from nonebot.adapters.onebot.v11.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_bot, get_matchers
|
||||||
|
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 (DATA_PATH / f"custom_welcome_msg/{group_id}.jpg").exists():
|
||||||
|
(DATA_PATH / f"custom_welcome_msg/{group_id}.jpg").unlink()
|
||||||
|
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 / "custom_welcome_msg" / f"{group_id}.jpg"
|
||||||
|
)
|
||||||
|
img_result = image(DATA_PATH / "custom_welcome_msg" / f"{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 = 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(DATA_PATH / "group_help"):
|
||||||
|
file = DATA_PATH / "group_help" / file
|
||||||
|
file.unlink()
|
||||||
|
else:
|
||||||
|
_help_image = 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(DATA_PATH / "group_help"):
|
||||||
|
file = 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"
|
||||||
|
tmp_name = []
|
||||||
|
for matcher in get_matchers():
|
||||||
|
if matcher.plugin_name not in tmp_name:
|
||||||
|
tmp_name.append(matcher.plugin_name)
|
||||||
|
module = matcher.plugin_name
|
||||||
|
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,37 @@
|
|||||||
|
from nonebot import on_notice
|
||||||
|
from services.log import logger
|
||||||
|
from nonebot.adapters.onebot.v11 import GroupAdminNoticeEvent
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
from models.group_member_info import GroupInfoUser
|
||||||
|
from configs.config import Config
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "群管理员变动监测 [Hidden]"
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
|
||||||
|
|
||||||
|
admin_notice = on_notice(priority=5)
|
||||||
|
|
||||||
|
|
||||||
|
@admin_notice.handle()
|
||||||
|
async def _(event: GroupAdminNoticeEvent):
|
||||||
|
try:
|
||||||
|
nickname = (
|
||||||
|
await GroupInfoUser.get_member_info(event.user_id, event.group_id)
|
||||||
|
).user_name
|
||||||
|
except AttributeError:
|
||||||
|
nickname = event.user_id
|
||||||
|
if event.sub_type == "set":
|
||||||
|
await LevelUser.set_level(
|
||||||
|
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":
|
||||||
|
await LevelUser.delete_level(event.user_id, event.group_id)
|
||||||
|
logger.info(f"将非管理员 {nickname}({event.user_id}) 取消权限等级")
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from utils.utils import get_message_img
|
||||||
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
from ._data_source import custom_group_welcome
|
||||||
|
from nonebot.adapters.onebot.v11.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 _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||||
|
try:
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
img = get_message_img(event.json())
|
||||||
|
if not msg and not img:
|
||||||
|
await custom_welcome.finish(__plugin_usage__)
|
||||||
|
await custom_welcome.send(
|
||||||
|
await custom_group_welcome(msg, img, 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,39 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import Event
|
||||||
|
from utils.manager import group_manager, plugins2settings_manager
|
||||||
|
from utils.utils import get_message_text
|
||||||
|
from services.log import logger
|
||||||
|
|
||||||
|
cmd = []
|
||||||
|
|
||||||
|
|
||||||
|
def switch_rule(event: Event) -> bool:
|
||||||
|
"""
|
||||||
|
检测文本是否是关闭功能命令
|
||||||
|
:param event: 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,124 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent, GROUP
|
||||||
|
from nonebot import on_command, on_message, on_regex
|
||||||
|
from nonebot.params import RegexGroup
|
||||||
|
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 typing import Tuple, Any
|
||||||
|
from .rule import switch_rule
|
||||||
|
|
||||||
|
|
||||||
|
__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):
|
||||||
|
_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()
|
||||||
|
]:
|
||||||
|
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 _():
|
||||||
|
await plugins_status.send(await get_plugin_status())
|
||||||
|
|
||||||
|
|
||||||
|
@group_task_status.handle()
|
||||||
|
async def _(event: GroupMessageEvent):
|
||||||
|
await group_task_status.send(await group_current_status(event.group_id))
|
||||||
|
|
||||||
|
|
||||||
|
@group_status.handle()
|
||||||
|
async def _(event: GroupMessageEvent, reg_group: Tuple[Any, ...] = RegexGroup()):
|
||||||
|
cmd = reg_group[0]
|
||||||
|
if cmd == "休息吧":
|
||||||
|
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} 使用总开关命令:{cmd}")
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
from nonebot import on_command, on_notice
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, GROUP, GroupIncreaseNoticeEvent
|
||||||
|
from ._data_source import update_member_info
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "更新群组成员列表 [Admin]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
更新群组成员的基本信息
|
||||||
|
指令:
|
||||||
|
更新群组成员列表/更新群组成员信息
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = '更新群组成员列表'
|
||||||
|
__plugin_cmd__ = ['更新群组成员列表']
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = 'HibiKier'
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"admin_level": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
refresh_member_group = on_command(
|
||||||
|
"更新群组成员列表", aliases={"更新群组成员信息"}, permission=GROUP, priority=5, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@refresh_member_group.handle()
|
||||||
|
async def _(event: GroupMessageEvent):
|
||||||
|
if await update_member_info(event.group_id):
|
||||||
|
await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
|
||||||
|
else:
|
||||||
|
await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
|
||||||
|
|
||||||
|
|
||||||
|
group_increase_handle = on_notice(priority=1, block=False)
|
||||||
|
|
||||||
|
|
||||||
|
@group_increase_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
|
||||||
|
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.onebot.v11 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,93 @@
|
|||||||
|
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.onebot.v11 import Bot
|
||||||
|
from nonebot import Driver
|
||||||
|
import asyncio
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
background = IMAGE_PATH / "background" / "0.png"
|
||||||
|
|
||||||
|
admin_help_image = 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.plugin_name)
|
||||||
|
_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.plugin_name}: {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,42 +1,67 @@
|
|||||||
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.onebot.v11.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"):
|
result = image("zao.jpg", "zhenxun")
|
||||||
result = image("zao.jpg", "zhenxun")
|
try:
|
||||||
try:
|
await bot.send_group_msg(group_id=g, message="[[_task|zwa]]早上好" + result)
|
||||||
await bot.send_group_msg(group_id=g, message="早上好" + result)
|
except ActionFailed:
|
||||||
except ActionFailed:
|
logger.warning(f"{g} 群被禁言中,无法发送早安")
|
||||||
logger.warning(f"{g} 群被禁言中,无法发送早安")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"早晚安错误 e:{e}")
|
logger.error(f"早晚安错误 e:{e}")
|
||||||
|
|
||||||
@@ -50,17 +75,16 @@ 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"):
|
result = image("sleep.jpg", "zhenxun")
|
||||||
result = image("sleep.jpg", "zhenxun")
|
try:
|
||||||
try:
|
await bot.send_group_msg(
|
||||||
await bot.send_group_msg(
|
group_id=g, message=f"[[_task|zwa]]{NICKNAME}要睡觉了,你们也要早点睡呀" + result
|
||||||
group_id=g, message=f"{NICKNAME}要睡觉了,你们也要早点睡呀" + result
|
)
|
||||||
)
|
except ActionFailed:
|
||||||
except ActionFailed:
|
logger.warning(f"{g} 群被禁言中,无法发送晚安")
|
||||||
logger.warning(f"{g} 群被禁言中,无法发送晚安")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"早晚安错误 e:{e}")
|
logger.error(f"早晚安错误 e:{e}")
|
||||||
|
|
||||||
@@ -74,7 +98,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 +122,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 +132,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
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent, MessageEvent, Message, Bot
|
||||||
|
from nonebot.params import CommandArg, Command
|
||||||
|
from nonebot import on_command
|
||||||
|
from models.ban_user import BanUser
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
from typing import Tuple
|
||||||
|
from utils.utils import get_message_at, is_number
|
||||||
|
from configs.config import NICKNAME, Config
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from .data_source import parse_ban_time, a_ban
|
||||||
|
from services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "封禁Ban用户 [Admin]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
将用户拉入或拉出黑名单
|
||||||
|
指令:
|
||||||
|
.ban [at] ?[小时] ?[分钟]
|
||||||
|
.unban
|
||||||
|
示例:.ban @user
|
||||||
|
示例:.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",
|
||||||
|
aliases={".unban", "/ban", "/unban"},
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
super_ban = on_command('b了', permission=SUPERUSER, priority=5, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ban.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||||
|
cmd = cmd[0]
|
||||||
|
result = ""
|
||||||
|
qq = get_message_at(event.json())
|
||||||
|
if qq:
|
||||||
|
qq = qq[0]
|
||||||
|
user_name = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||||
|
user_name = user_name['card'] or user_name['nickname']
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
time = parse_ban_time(msg)
|
||||||
|
if isinstance(time, str):
|
||||||
|
await ban.finish(time, at_sender=True)
|
||||||
|
if cmd in [".ban", "/ban"]:
|
||||||
|
if (
|
||||||
|
await LevelUser.get_user_level(event.user_id, event.group_id)
|
||||||
|
<= await LevelUser.get_user_level(qq, event.group_id)
|
||||||
|
and str(event.user_id) not in bot.config.superusers
|
||||||
|
):
|
||||||
|
await ban.finish(
|
||||||
|
f"您的权限等级比对方低或相等, {NICKNAME}不能为您使用此功能!",
|
||||||
|
at_sender=True,
|
||||||
|
)
|
||||||
|
result = await a_ban(qq, time, user_name, event)
|
||||||
|
else:
|
||||||
|
if (
|
||||||
|
await BanUser.check_ban_level(
|
||||||
|
qq, await LevelUser.get_user_level(event.user_id, event.group_id)
|
||||||
|
)
|
||||||
|
and str(event.user_id) not in bot.config.superusers
|
||||||
|
):
|
||||||
|
await ban.finish(
|
||||||
|
f"ban掉 {user_name} 的管理员权限比您高,无法进行unban", at_sender=True
|
||||||
|
)
|
||||||
|
if await BanUser.unban(qq):
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 解禁"
|
||||||
|
)
|
||||||
|
result = f"已经把 {user_name} 从黑名单中删除了!"
|
||||||
|
else:
|
||||||
|
result = f"{user_name} 不在黑名单!"
|
||||||
|
else:
|
||||||
|
await ban.finish("艾特人了吗??", at_sender=True)
|
||||||
|
await ban.send(result, at_sender=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ban.handle()
|
||||||
|
async def _(bot: Bot, event: PrivateMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||||
|
cmd = cmd[0]
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
if msg:
|
||||||
|
if str(event.user_id) in bot.config.superusers:
|
||||||
|
if is_number(arg.extract_plain_text().strip().split()[0]):
|
||||||
|
qq = int(msg[0])
|
||||||
|
msg = msg[1:]
|
||||||
|
if cmd in [".ban", "/ban"]:
|
||||||
|
time = parse_ban_time(msg)
|
||||||
|
if isinstance(time, str):
|
||||||
|
await ban.finish(time)
|
||||||
|
result = await a_ban(qq, time, str(qq), event, 9)
|
||||||
|
else:
|
||||||
|
if await BanUser.unban(qq):
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} 将 USER {qq} 解禁"
|
||||||
|
)
|
||||||
|
result = f"已经把 {qq} 从黑名单中删除了!"
|
||||||
|
else:
|
||||||
|
result = f"{qq} 不在黑名单!"
|
||||||
|
await ban.send(result)
|
||||||
|
else:
|
||||||
|
await ban.finish('qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?', at_sender=True)
|
||||||
|
|
||||||
|
|
||||||
|
@super_ban.handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
qq = get_message_at(event.json())
|
||||||
|
else:
|
||||||
|
qq = arg.extract_plain_text().strip()
|
||||||
|
if not is_number(qq):
|
||||||
|
await super_ban.finish("对象qq必须为纯数字...")
|
||||||
|
qq = [qq]
|
||||||
|
if qq:
|
||||||
|
qq = qq[0]
|
||||||
|
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
|
||||||
|
user_name = user['card'] or user['nickname']
|
||||||
|
if not await BanUser.ban(qq, 10, 99999999):
|
||||||
|
await BanUser.unban(qq)
|
||||||
|
await BanUser.ban(qq, 10, 99999999)
|
||||||
|
await ban.send(f"已将 {user_name} 拉入黑名单!")
|
||||||
|
else:
|
||||||
|
await super_ban.send('需要添加被super ban的对象,可以使用at或者指定qq..')
|
||||||
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
|
||||||
|
from configs.config import NICKNAME
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
from utils.utils import is_number
|
||||||
|
from models.ban_user import BanUser
|
||||||
|
from services.log import logger
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
|
def parse_ban_time(msg: str) -> Union[int, str]:
|
||||||
|
"""
|
||||||
|
解析ban时长
|
||||||
|
:param msg: 文本消息
|
||||||
|
"""
|
||||||
|
if not msg:
|
||||||
|
return -1
|
||||||
|
msg = msg.split()
|
||||||
|
if len(msg) == 1:
|
||||||
|
if not is_number(msg[0].strip()):
|
||||||
|
return "参数必须是数字!"
|
||||||
|
return int(msg[0]) * 60 * 60
|
||||||
|
else:
|
||||||
|
if not is_number(msg[0].strip()) or not is_number(msg[1].strip()):
|
||||||
|
return "参数必须是数字!"
|
||||||
|
return int(msg[0]) * 60 * 60 + int(msg[1]) * 60
|
||||||
|
|
||||||
|
|
||||||
|
async def a_ban(qq: int, time: int, user_name: str, event: MessageEvent, ban_level: int = None) -> str:
|
||||||
|
"""
|
||||||
|
ban
|
||||||
|
:param qq: qq
|
||||||
|
:param time: ban时长
|
||||||
|
:param user_name: ban用户昵称
|
||||||
|
:param event: event
|
||||||
|
:param ban_level: ban级别
|
||||||
|
"""
|
||||||
|
if isinstance(event, GroupMessageEvent):
|
||||||
|
ban_level = await LevelUser.get_user_level(event.user_id, event.group_id)
|
||||||
|
if await BanUser.ban(qq, ban_level, time):
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 封禁 时长 {time / 60} 分钟"
|
||||||
|
)
|
||||||
|
result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
|
||||||
|
if time != -1:
|
||||||
|
result += f"将在 {time / 60} 分钟后解封"
|
||||||
|
else:
|
||||||
|
result += f"将在 ∞ 分钟后解封"
|
||||||
|
else:
|
||||||
|
time = await BanUser.check_ban_time(qq)
|
||||||
|
if is_number(time):
|
||||||
|
time = abs(int(time))
|
||||||
|
if time < 60:
|
||||||
|
time = str(time) + " 秒"
|
||||||
|
else:
|
||||||
|
time = str(int(time / 60)) + " 分钟"
|
||||||
|
else:
|
||||||
|
time += " 分钟"
|
||||||
|
result = f"{user_name} 已在黑名单!预计 {time}后解封"
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
|
||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
from utils.utils import get_message_img
|
||||||
|
from services.log import logger
|
||||||
|
from utils.message_builder import image
|
||||||
|
from utils.manager import group_manager
|
||||||
|
from configs.config import Config
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
|
__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: MessageEvent, arg: Message = CommandArg()):
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
img_list = get_message_img(event.json())
|
||||||
|
rst = ""
|
||||||
|
for img in img_list:
|
||||||
|
rst += image(img)
|
||||||
|
gl = await bot.get_group_list()
|
||||||
|
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(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,195 @@
|
|||||||
|
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.onebot.v11 import (
|
||||||
|
Bot,
|
||||||
|
GroupIncreaseNoticeEvent,
|
||||||
|
GroupDecreaseNoticeEvent,
|
||||||
|
)
|
||||||
|
from nonebot.adapters.onebot.v11.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):
|
||||||
|
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 _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 (DATA_PATH / "custom_welcome_msg" / f"{event.group_id}.jpg").exists():
|
||||||
|
img = image(
|
||||||
|
DATA_PATH / "custom_welcome_msg" / f"{event.group_id}.jpg"
|
||||||
|
)
|
||||||
|
if msg or img:
|
||||||
|
msg = msg.strip() + img
|
||||||
|
msg = "\n" + msg if at_flag else msg
|
||||||
|
await group_increase_handle.send(
|
||||||
|
"[[_task|group_welcome]]" + msg, at_sender=at_flag
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await group_increase_handle.send(
|
||||||
|
"[[_task|group_welcome]]新人快跑啊!!本群现状↓(快使用自定义!)"
|
||||||
|
+ image(random.choice(os.listdir(IMAGE_PATH / "qxz")), "qxz")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@group_decrease_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
|
||||||
|
# 被踢出群
|
||||||
|
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} 删除失败")
|
||||||
|
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"[[_task|refund_group_remind]]{rst}")
|
||||||
|
except ActionFailed:
|
||||||
|
return
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.adapters.onebot.v11 import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
Message
|
||||||
|
)
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
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
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "帮助"
|
||||||
|
|
||||||
|
group_help_path = DATA_PATH / "group_help"
|
||||||
|
help_image = IMAGE_PATH / "help.png"
|
||||||
|
simple_help_image = 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, arg: Message = CommandArg()):
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
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 = IMAGE_PATH / "background" / "help" / "simple_help"
|
||||||
|
|
||||||
|
background = 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.plugin_name)
|
||||||
|
_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.plugin_name
|
||||||
|
) and plugins2settings_manager[matcher.plugin_name].get("plugin_type"):
|
||||||
|
plugin_type = tuple(
|
||||||
|
plugins2settings_manager.get_plugin_data(matcher.plugin_name)[
|
||||||
|
"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] = {
|
||||||
|
"modules": matcher.plugin_name,
|
||||||
|
"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.plugin_name}: {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]["modules"], "all"
|
||||||
|
):
|
||||||
|
flag = False
|
||||||
|
if group_id:
|
||||||
|
flag = flag and plugins_manager.get_plugin_status(
|
||||||
|
matchers_data[type_][k]["modules"], "group"
|
||||||
|
)
|
||||||
|
simple_help_str += (
|
||||||
|
f"{i+1}.{k}<|_|~|>"
|
||||||
|
f"{group_manager.get_plugin_status(matchers_data[type_][k]['modules'], 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=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,52 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent
|
||||||
|
from utils.manager import plugins2block_manager, StaticData
|
||||||
|
import time
|
||||||
|
|
||||||
|
ignore_rst_module = ["ai", "poke", "dialogue"]
|
||||||
|
|
||||||
|
other_limit_plugins = ["poke"]
|
||||||
|
|
||||||
|
|
||||||
|
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,386 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
|
||||||
|
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||||
|
from models.friend_user import FriendUser
|
||||||
|
from models.group_member_info import GroupInfoUser
|
||||||
|
from models.bag_user import BagUser
|
||||||
|
from utils.manager import (
|
||||||
|
plugins2settings_manager,
|
||||||
|
admin_manager,
|
||||||
|
group_manager,
|
||||||
|
plugins_manager,
|
||||||
|
plugins2cd_manager,
|
||||||
|
plugins2block_manager,
|
||||||
|
plugins2count_manager,
|
||||||
|
)
|
||||||
|
from ._utils import (
|
||||||
|
set_block_limit_false,
|
||||||
|
status_message_manager,
|
||||||
|
ignore_rst_module,
|
||||||
|
other_limit_plugins,
|
||||||
|
)
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from typing import Optional
|
||||||
|
from nonebot.adapters.onebot.v11 import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
PokeNotifyEvent,
|
||||||
|
PrivateMessageEvent,
|
||||||
|
Message,
|
||||||
|
Event,
|
||||||
|
)
|
||||||
|
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"))
|
||||||
|
|
||||||
|
|
||||||
|
# 权限检测
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
|
||||||
|
module = matcher.plugin_name
|
||||||
|
plugins2info_dict = plugins2settings_manager.get_data()
|
||||||
|
# 功能的金币检测 #######################################
|
||||||
|
# 功能的金币检测 #######################################
|
||||||
|
# 功能的金币检测 #######################################
|
||||||
|
cost_gold = 0
|
||||||
|
if isinstance(
|
||||||
|
event, GroupMessageEvent
|
||||||
|
) and plugins2settings_manager.get_plugin_data(module).get("cost_gold"):
|
||||||
|
cost_gold = plugins2settings_manager.get_plugin_data(module).get("cost_gold")
|
||||||
|
if await BagUser.get_gold(event.user_id, event.group_id) < cost_gold:
|
||||||
|
await send_msg(f"金币不足..该功能需要{cost_gold}金币..", bot, event)
|
||||||
|
raise IgnoredException(f"{module} 金币限制...")
|
||||||
|
# 当插件不阻塞超级用户时,超级用户提前扣除金币
|
||||||
|
if (
|
||||||
|
str(event.user_id) in bot.config.superusers
|
||||||
|
and not plugins2info_dict[module]["limit_superuser"]
|
||||||
|
):
|
||||||
|
await BagUser.spend_gold(event.user_id, event.group_id, cost_gold)
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
(not isinstance(event, MessageEvent) and module not in other_limit_plugins)
|
||||||
|
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.plugin_name == other_limit_plugins:
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
group_manager.get_group_level(event.group_id) < 0
|
||||||
|
and str(event.user_id) not in bot.config.superusers
|
||||||
|
):
|
||||||
|
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) or matcher.plugin_name in other_limit_plugins:
|
||||||
|
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("此功能正在维护...")
|
||||||
|
|
||||||
|
# 以下为限制检测 #######################################################
|
||||||
|
# 以下为限制检测 #######################################################
|
||||||
|
# 以下为限制检测 #######################################################
|
||||||
|
# 以下为限制检测 #######################################################
|
||||||
|
# 以下为限制检测 #######################################################
|
||||||
|
# 以下为限制检测 #######################################################
|
||||||
|
# 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)
|
||||||
|
# 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_)
|
||||||
|
# 功能花费的金币 #######################################
|
||||||
|
# 功能花费的金币 #######################################
|
||||||
|
if cost_gold:
|
||||||
|
await BagUser.spend_gold(event.user_id, event.group_id, cost_gold)
|
||||||
|
|
||||||
|
|
||||||
|
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.plugin_name != "poke":
|
||||||
|
return
|
||||||
|
module = matcher.plugin_name
|
||||||
|
set_block_limit_false(event, module)
|
||||||
|
|
||||||
|
|
||||||
|
async def init_rst(rst: str, event: MessageEvent):
|
||||||
|
if "[uname]" in rst:
|
||||||
|
uname = event.sender.card or 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,94 @@
|
|||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.message import run_preprocessor, IgnoredException
|
||||||
|
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.onebot.v11 import (
|
||||||
|
Bot,
|
||||||
|
Event,
|
||||||
|
MessageEvent,
|
||||||
|
PokeNotifyEvent,
|
||||||
|
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
|
||||||
|
from ._utils import ignore_rst_module, other_limit_plugins
|
||||||
|
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"hook",
|
||||||
|
"BAN_RESULT",
|
||||||
|
"才不会给你发消息.",
|
||||||
|
help_="对被ban用户发送的消息",
|
||||||
|
)
|
||||||
|
|
||||||
|
_flmt = FreqLimiter(300)
|
||||||
|
|
||||||
|
|
||||||
|
# 检查是否被ban
|
||||||
|
@run_preprocessor
|
||||||
|
async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
|
||||||
|
if (
|
||||||
|
(isinstance(event, MessageEvent) or isinstance(event, PokeNotifyEvent))
|
||||||
|
and matcher.priority not in [1, 9]
|
||||||
|
) or matcher.plugin_name in other_limit_plugins:
|
||||||
|
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 (
|
||||||
|
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)
|
||||||
|
and matcher.plugin_name not in ignore_rst_module
|
||||||
|
):
|
||||||
|
_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 and matcher.plugin_name not in ignore_rst_module:
|
||||||
|
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.onebot.v11.exception import ActionFailed
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.adapters.onebot.v11 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,51 @@
|
|||||||
|
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 utils.image_utils import text2image
|
||||||
|
from typing import Dict, Any
|
||||||
|
from nonebot.adapters.onebot.v11 import (
|
||||||
|
Bot,
|
||||||
|
MessageEvent,
|
||||||
|
PrivateMessageEvent,
|
||||||
|
GroupMessageEvent,
|
||||||
|
)
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
# 为什么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.plugin_name == "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)
|
||||||
|
):
|
||||||
|
status_message_manager.delete(event.user_id)
|
||||||
|
raise IgnoredException("有命令就别说话了")
|
||||||
|
|
||||||
|
# @Bot.on_calling_api
|
||||||
|
# async def handle_api_call(bot: Bot, api: str, data: Dict[str, Any]):
|
||||||
|
# if api in ["send_msg", "send_group_msg", "send_private_msg"]:
|
||||||
|
# msg = str(data["message"])
|
||||||
|
# if (r := re.search("\[\[To_Img\|?(.*?)]]", msg)) or (r := re.search("[[To_Img\|?(.*?)[[")):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
from nonebot.exception import MockApiException
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot, Message
|
||||||
|
from utils.manager import group_manager
|
||||||
|
from typing import Dict, Any
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
@Bot.on_calling_api
|
||||||
|
async def handle_api_call(bot: Bot, api: str, data: Dict[str, Any]):
|
||||||
|
r = None
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
(api == "send_msg" and data["message_type"] == "group")
|
||||||
|
or api == "send_group_msg"
|
||||||
|
)
|
||||||
|
and (
|
||||||
|
(
|
||||||
|
r := re.search(
|
||||||
|
"^\[\[_task\|(.*)]]",
|
||||||
|
data["message"].strip()
|
||||||
|
if isinstance(data["message"], str)
|
||||||
|
else str(data["message"]["text"]).strip(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
r := re.search(
|
||||||
|
"^[[_task\|(.*)]]",
|
||||||
|
data["message"].strip()
|
||||||
|
if isinstance(data["message"], str)
|
||||||
|
else str(data["message"]["text"]).strip(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
and r.group(1) in group_manager.get_task_data().keys()
|
||||||
|
):
|
||||||
|
task = r.group(1)
|
||||||
|
group_id = data["group_id"]
|
||||||
|
if group_manager.get_group_level(
|
||||||
|
group_id
|
||||||
|
) < 0 or not await group_manager.check_group_task_status(group_id, task):
|
||||||
|
raise MockApiException(f"被动技能 {task} 处于关闭状态...")
|
||||||
|
else:
|
||||||
|
msg = str(data["message"]).strip()
|
||||||
|
msg = msg.replace(f"[[_task|{task}]]", "").replace(
|
||||||
|
f"[[_task|{task}]]", ""
|
||||||
|
)
|
||||||
|
data["message"] = Message(msg)
|
||||||
@@ -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.onebot.v11 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_)
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
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 nonebot.adapters.onebot.v11 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 = 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.onebot.v11 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,153 @@
|
|||||||
|
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 = 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.plugin_name)
|
||||||
|
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.plugin_name)
|
||||||
|
and _data[matcher.plugin_name].keys() != plugin_configs.keys()
|
||||||
|
)
|
||||||
|
or plugin_version > plugins_manager.get(matcher.plugin_name)["version"]
|
||||||
|
or matcher.plugin_name not in _data.keys()
|
||||||
|
):
|
||||||
|
for key in plugin_configs:
|
||||||
|
if isinstance(plugin_configs[key], dict):
|
||||||
|
Config.add_plugin_config(
|
||||||
|
matcher.plugin_name,
|
||||||
|
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.plugin_name, key, plugin_configs[key])
|
||||||
|
else:
|
||||||
|
plugin_configs = _data[matcher.plugin_name]
|
||||||
|
for key in plugin_configs:
|
||||||
|
Config.add_plugin_config(
|
||||||
|
matcher.plugin_name,
|
||||||
|
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):
|
||||||
|
try:
|
||||||
|
admin_manager.set_admin_level(level2module, _data[plugin][k])
|
||||||
|
except KeyError:
|
||||||
|
logger.warning(f"{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 = 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.plugin_name)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
if matcher.plugin_name not in _data.keys():
|
||||||
|
plugins_manager.add_plugin_data(
|
||||||
|
matcher.plugin_name, matcher.plugin_name, error=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
plugins_manager.set_module_data(matcher.plugin_name, "error", True)
|
||||||
|
plugin_data = plugins_manager.get(matcher.plugin_name)
|
||||||
|
if plugin_data:
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.plugin_name, "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.plugin_name
|
||||||
|
try:
|
||||||
|
plugin_author = _module.__getattribute__("__plugin_author__")
|
||||||
|
except AttributeError:
|
||||||
|
plugin_author = None
|
||||||
|
if matcher.plugin_name in plugins_manager.keys():
|
||||||
|
plugins_manager.set_module_data(matcher.plugin_name, "error", False)
|
||||||
|
if matcher.plugin_name not in plugins_manager.keys():
|
||||||
|
plugins_manager.add_plugin_data(
|
||||||
|
matcher.plugin_name,
|
||||||
|
plugin_name=plugin_name,
|
||||||
|
author=plugin_author,
|
||||||
|
version=plugin_version,
|
||||||
|
)
|
||||||
|
elif plugins_manager[matcher.plugin_name]["version"] is None or (
|
||||||
|
plugin_version is not None
|
||||||
|
and plugin_version > plugins_manager[matcher.plugin_name]["version"]
|
||||||
|
):
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.plugin_name, "plugin_name", plugin_name
|
||||||
|
)
|
||||||
|
plugins_manager.set_module_data(matcher.plugin_name, "author", plugin_author)
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.plugin_name, "version", plugin_version
|
||||||
|
)
|
||||||
|
if matcher.plugin_name in _data.keys():
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.plugin_name, "error", _data[matcher.plugin_name]["error"]
|
||||||
|
)
|
||||||
|
plugins_manager.set_module_data(
|
||||||
|
matcher.plugin_name, "plugin_name", _data[matcher.plugin_name]["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 = 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.plugin_name):
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_cd_limit = _module.__getattribute__("__plugin_cd_limit__")
|
||||||
|
plugins2cd_manager.add_cd_limit(
|
||||||
|
matcher.plugin_name, 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 = 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.plugin_name):
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_block_limit = _module.__getattribute__("__plugin_block_limit__")
|
||||||
|
plugins2block_manager.add_block_limit(
|
||||||
|
matcher.plugin_name, 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 = 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.plugin_name):
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
plugin_count_limit = _module.__getattribute__("__plugin_count_limit__")
|
||||||
|
plugins2count_manager.add_count_limit(
|
||||||
|
matcher.plugin_name, 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.plugin_name not in _tmp:
|
||||||
|
_tmp.append(matcher.plugin_name)
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
logger.warning(f"插件 {matcher.plugin_name} 加载失败...,资源控制未加载...")
|
||||||
|
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.plugin_name, path / resource, resources[resource])
|
||||||
|
resources_manager.save()
|
||||||
|
resources_manager.start_move()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
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 = 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.plugin_name not in plugins2settings_manager.keys():
|
||||||
|
_plugin = nonebot.plugin.get_plugin(matcher.plugin_name)
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
logger.warning(f"插件 {matcher.plugin_name} 加载失败...,插件控制未加载.")
|
||||||
|
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.plugin_name, cmd, level
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
"[hidden]" in plugin_name.lower()
|
||||||
|
or "[admin]" in plugin_name.lower()
|
||||||
|
or "[superuser]" in plugin_name.lower()
|
||||||
|
or matcher.plugin_name in plugins2settings_manager.keys()
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
except AttributeError:
|
||||||
|
if matcher.plugin_name not in _tmp:
|
||||||
|
logger.warning(
|
||||||
|
f"获取插件 {matcher.plugin_name} __zx_plugin_name__ 失败...,插件控制未加载."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
_tmp_module[matcher.plugin_name] = plugin_name
|
||||||
|
plugin_settings = _module.__getattribute__(
|
||||||
|
"__plugin_settings__"
|
||||||
|
)
|
||||||
|
if plugin_settings.get('cost_gold') is None:
|
||||||
|
plugin_settings['cost_gold'] = 0
|
||||||
|
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.plugin_name
|
||||||
|
) and plugins2settings_manager[matcher.plugin_name].get(
|
||||||
|
"plugin_type"
|
||||||
|
):
|
||||||
|
plugin_type = tuple(
|
||||||
|
plugins2settings_manager.get_plugin_data(
|
||||||
|
matcher.plugin_name
|
||||||
|
)["plugin_type"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
plugin_type = _module.__getattribute__(
|
||||||
|
"__plugin_type__"
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
plugin_type = ("normal",)
|
||||||
|
if plugin_settings and matcher.plugin_name:
|
||||||
|
plugins2settings_manager.add_plugin_settings(
|
||||||
|
matcher.plugin_name,
|
||||||
|
plugin_type=plugin_type,
|
||||||
|
**plugin_settings,
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
_tmp.append(matcher.plugin_name)
|
||||||
|
_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())} 个非限制插件.")
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
from nonebot import on_request, on_message
|
||||||
|
from nonebot.adapters.onebot.v11 import (
|
||||||
|
Bot,
|
||||||
|
FriendRequestEvent,
|
||||||
|
GroupRequestEvent,
|
||||||
|
MessageEvent,
|
||||||
|
)
|
||||||
|
from models.friend_user import FriendUser
|
||||||
|
from datetime import datetime
|
||||||
|
from configs.config import NICKNAME, Config
|
||||||
|
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||||
|
from utils.manager import requests_manager
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
from utils.utils import scheduler
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "好友群聊处理请求 [Hidden]"
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__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": {}}
|
||||||
|
|
||||||
|
|
||||||
|
@friend_req.handle()
|
||||||
|
async def _(bot: Bot, event: FriendRequestEvent):
|
||||||
|
global exists_data
|
||||||
|
if exists_data["private"].get(event.user_id):
|
||||||
|
if time.time() - exists_data["private"][event.user_id] < 60 * 5:
|
||||||
|
return
|
||||||
|
exists_data["private"][event.user_id] = time.time()
|
||||||
|
user = await bot.get_stranger_info(user_id=event.user_id)
|
||||||
|
nickname = user["nickname"]
|
||||||
|
sex = user["sex"]
|
||||||
|
age = str(user["age"])
|
||||||
|
comment = event.comment
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=f"*****一份好友申请*****\n"
|
||||||
|
f"昵称:{nickname}({event.user_id})\n"
|
||||||
|
f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
|
||||||
|
f"日期:{str(datetime.now()).split('.')[0]}\n"
|
||||||
|
f"备注:{event.comment}",
|
||||||
|
)
|
||||||
|
if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
|
||||||
|
await bot.set_friend_add_request(flag=event.flag, approve=True)
|
||||||
|
await FriendUser.add_friend_info(user["user_id"], user["nickname"])
|
||||||
|
else:
|
||||||
|
requests_manager.add_request(
|
||||||
|
event.user_id,
|
||||||
|
"private",
|
||||||
|
event.flag,
|
||||||
|
nickname=nickname,
|
||||||
|
sex=sex,
|
||||||
|
age=age,
|
||||||
|
comment=comment,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@group_req.handle()
|
||||||
|
async def _(bot: Bot, event: GroupRequestEvent):
|
||||||
|
global exists_data
|
||||||
|
if event.sub_type == "invite":
|
||||||
|
if str(event.user_id) in bot.config.superusers:
|
||||||
|
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(
|
||||||
|
flag=event.flag, sub_type="invite", approve=True
|
||||||
|
)
|
||||||
|
except ActionFailed:
|
||||||
|
pass
|
||||||
|
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 (
|
||||||
|
time.time()
|
||||||
|
- exists_data["group"][f"{event.user_id}:{event.group_id}"]
|
||||||
|
< 60 * 5
|
||||||
|
):
|
||||||
|
return
|
||||||
|
exists_data["group"][f"{event.user_id}:{event.group_id}"] = time.time()
|
||||||
|
nickname = await FriendUser.get_user_name(event.user_id)
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(list(bot.config.superusers)[0]),
|
||||||
|
message=f"*****一份入群申请*****\n"
|
||||||
|
f"申请人:{nickname}({event.user_id})\n"
|
||||||
|
f"群聊:{event.group_id}\n"
|
||||||
|
f"邀请日期:{str(datetime.now()).split('.')[0]}",
|
||||||
|
)
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=event.user_id,
|
||||||
|
message=f"想要邀请我偷偷入群嘛~已经提醒{NICKNAME}的管理员大人了\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 _(event: MessageEvent):
|
||||||
|
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(
|
||||||
|
"interval",
|
||||||
|
minutes=5,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
global exists_data
|
||||||
|
exists_data = {"private": {}, "group": {}}
|
||||||
@@ -1,19 +1,34 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, PrivateMessageEvent, Message
|
||||||
from nonebot import on_command
|
from nonebot import on_command
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent
|
|
||||||
from nonebot.rule import to_me
|
from nonebot.rule import to_me
|
||||||
from utils.utils import get_message_text
|
|
||||||
from models.group_member_info import GroupInfoUser
|
from models.group_member_info import GroupInfoUser
|
||||||
from models.friend_user import FriendUser
|
from models.friend_user import FriendUser
|
||||||
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
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
import random
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "昵称系统"
|
||||||
__plugin_name__ = "昵称系统"
|
__plugin_usage__ = f"""
|
||||||
|
usage:
|
||||||
__plugin_usage__ = f"用法:\n以后叫我 [名称]\n{NICKNAME}我是谁"
|
个人昵称系统,群聊 与 私聊 昵称相互独立
|
||||||
|
指令:
|
||||||
|
以后叫我 [昵称]
|
||||||
|
{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",
|
||||||
@@ -32,62 +47,62 @@ cancel_nickname = on_command("取消昵称", rule=to_me(), priority=5, block=Tru
|
|||||||
|
|
||||||
|
|
||||||
@nickname.handle()
|
@nickname.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||||
msg = get_message_text(event.json())
|
msg = arg.extract_plain_text().strip()
|
||||||
if not msg:
|
if not msg:
|
||||||
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()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(event: GroupMessageEvent):
|
||||||
try:
|
try:
|
||||||
nickname_ = await GroupInfoUser.get_group_member_nickname(
|
nickname_ = await GroupInfoUser.get_group_member_nickname(
|
||||||
event.user_id, event.group_id
|
event.user_id, event.group_id
|
||||||
@@ -108,7 +123,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
nickname_ = event.sender.card if event.sender.card else event.sender.nickname
|
nickname_ = event.sender.card or event.sender.nickname
|
||||||
await my_nickname.send(
|
await my_nickname.send(
|
||||||
random.choice(
|
random.choice(
|
||||||
["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
|
["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
|
||||||
@@ -142,7 +157,7 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
|||||||
|
|
||||||
|
|
||||||
@cancel_nickname.handle()
|
@cancel_nickname.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(event: GroupMessageEvent):
|
||||||
nickname_ = await GroupInfoUser.get_group_member_nickname(
|
nickname_ = await GroupInfoUser.get_group_member_nickname(
|
||||||
event.user_id, event.group_id
|
event.user_id, event.group_id
|
||||||
)
|
)
|
||||||
@@ -165,7 +180,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
|
|
||||||
|
|
||||||
@cancel_nickname.handle()
|
@cancel_nickname.handle()
|
||||||
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
async def _(event: PrivateMessageEvent):
|
||||||
nickname_ = await FriendUser.get_friend_nickname(event.user_id)
|
nickname_ = await FriendUser.get_friend_nickname(event.user_id)
|
||||||
if nickname_:
|
if nickname_:
|
||||||
await cancel_nickname.send(
|
await cancel_nickname.send(
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
from asyncpg.exceptions import (
|
||||||
|
DuplicateColumnError,
|
||||||
|
UndefinedColumnError,
|
||||||
|
PostgresSyntaxError,
|
||||||
|
)
|
||||||
|
from nonebot import Driver
|
||||||
|
from services.db_context import db
|
||||||
|
from models.group_info import GroupInfo
|
||||||
|
from models.bag_user import BagUser
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot
|
||||||
|
from services.log import logger
|
||||||
|
from configs.path_config import TEXT_PATH
|
||||||
|
from asyncio.exceptions import TimeoutError
|
||||||
|
from typing import List
|
||||||
|
from utils.http_utils import AsyncHttpx
|
||||||
|
from utils.utils import scheduler
|
||||||
|
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 = TEXT_PATH / "china_city.json"
|
||||||
|
data = {}
|
||||||
|
if not china_city.exists():
|
||||||
|
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 _():
|
||||||
|
"""
|
||||||
|
数据库表结构变换
|
||||||
|
"""
|
||||||
|
_flag = []
|
||||||
|
sql_str = [
|
||||||
|
(
|
||||||
|
"ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;",
|
||||||
|
"group_info",
|
||||||
|
), # group_info表添加一个group_flag
|
||||||
|
(
|
||||||
|
"ALTER TABLE bag_users rename belonging_group To group_id;",
|
||||||
|
"bag_users",
|
||||||
|
), # 将 bag_users 的 belonging_group 改为 group_id
|
||||||
|
(
|
||||||
|
"ALTER TABLE group_info_users rename belonging_group To group_id;",
|
||||||
|
"group_info_users",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ALTER TABLE sign_group_users rename belonging_group To group_id;",
|
||||||
|
"sign_group_users",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ALTER TABLE open_cases_users rename belonging_group To group_id;",
|
||||||
|
"open_cases_users",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';",
|
||||||
|
"bag_users",
|
||||||
|
), # bag_users 新增字段 property 替代 props
|
||||||
|
(
|
||||||
|
"ALTER TABLE genshin ADD auto_sign_time timestamp with time zone;",
|
||||||
|
"genshin"
|
||||||
|
), # 新增原神自动签到字段
|
||||||
|
(
|
||||||
|
"ALTER TABLE genshin ADD resin_remind boolean DEFAULT False;",
|
||||||
|
"genshin"
|
||||||
|
), # 新增原神自动签到字段
|
||||||
|
(
|
||||||
|
"ALTER TABLE genshin ADD resin_recovery_time timestamp with time zone;",
|
||||||
|
"genshin"
|
||||||
|
), # 新增原神自动签到字段
|
||||||
|
(
|
||||||
|
"ALTER TABLE genshin ADD bind_group Integer;",
|
||||||
|
"genshin"
|
||||||
|
), # 新增原神群号绑定字段
|
||||||
|
]
|
||||||
|
for sql in sql_str:
|
||||||
|
try:
|
||||||
|
flag = sql[1]
|
||||||
|
sql = sql[0]
|
||||||
|
query = db.text(sql)
|
||||||
|
await db.first(query)
|
||||||
|
logger.info(f"完成sql操作:{sql}")
|
||||||
|
_flag.append(flag)
|
||||||
|
except (DuplicateColumnError, UndefinedColumnError):
|
||||||
|
pass
|
||||||
|
except PostgresSyntaxError:
|
||||||
|
logger.error(f"语法错误:执行sql失败:{sql}")
|
||||||
|
# bag_user 将文本转为字典格式
|
||||||
|
await __database_script(_flag)
|
||||||
|
|
||||||
|
# 完成后
|
||||||
|
end_sql_str = [
|
||||||
|
# "ALTER TABLE bag_users DROP COLUMN props;" # 删除 bag_users 的 props 字段(还不到时候)
|
||||||
|
]
|
||||||
|
for sql in end_sql_str:
|
||||||
|
try:
|
||||||
|
query = db.text(sql)
|
||||||
|
await db.first(query)
|
||||||
|
logger.info(f"完成执行sql操作:{sql}")
|
||||||
|
except (DuplicateColumnError, UndefinedColumnError):
|
||||||
|
pass
|
||||||
|
except PostgresSyntaxError:
|
||||||
|
logger.error(f"语法错误:执行sql失败:{sql}")
|
||||||
|
|
||||||
|
# str2json_sql = ["alter table bag_users alter COLUMN props type json USING props::json;"] # 字段类型替换
|
||||||
|
# rename_sql = 'alter table {} rename {} to {};' # 字段更名
|
||||||
|
# for sql in str2json_sql:
|
||||||
|
# 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}")
|
||||||
|
|
||||||
|
|
||||||
|
async def __database_script(_flag: List[str]):
|
||||||
|
# bag_user 将文本转为字典格式
|
||||||
|
if "bag_users" in _flag:
|
||||||
|
for x in await BagUser.get_all_users():
|
||||||
|
props = {}
|
||||||
|
if x.props:
|
||||||
|
for prop in [p for p in x.props.split(",") if p]:
|
||||||
|
if props.get(prop):
|
||||||
|
props[prop] += 1
|
||||||
|
else:
|
||||||
|
props[prop] = 1
|
||||||
|
logger.info(
|
||||||
|
f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}"
|
||||||
|
)
|
||||||
|
await x.update(
|
||||||
|
property=props,
|
||||||
|
props="",
|
||||||
|
).apply()
|
||||||
|
|
||||||
|
|
||||||
|
# 自动更新城市列表
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
"cron",
|
||||||
|
hour=6,
|
||||||
|
minute=1,
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
await update_city()
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import nonebot
|
||||||
|
from configs.config import Config
|
||||||
|
|
||||||
|
|
||||||
|
Config.add_plugin_config(
|
||||||
|
"shop",
|
||||||
|
"IMPORT_DEFAULT_SHOP_GOODS",
|
||||||
|
True,
|
||||||
|
help_="导入商店自带的三个商品",
|
||||||
|
default_value=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
nonebot.load_plugins("basic_plugins/shop")
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from services.log import logger
|
||||||
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
from utils.utils import is_number
|
||||||
|
from models.bag_user import BagUser
|
||||||
|
from services.db_context import db
|
||||||
|
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||||
|
from models.goods_info import GoodsInfo
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "商店 - 购买道具"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
购买道具
|
||||||
|
指令:
|
||||||
|
购买 [序号或名称] ?[数量=1]
|
||||||
|
示例:购买 好感双倍加持卡Ⅰ
|
||||||
|
示例:购买 1 4
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "商店 - 购买道具"
|
||||||
|
__plugin_cmd__ = ["购买 [序号或名称] ?[数量=1]"]
|
||||||
|
__plugin_type__ = ("商店",)
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"limit_superuser": False,
|
||||||
|
"cmd": ["商店", "购买道具"],
|
||||||
|
}
|
||||||
|
__plugin_cd_limit__ = {"cd": 3}
|
||||||
|
|
||||||
|
|
||||||
|
buy = on_command("购买", aliases={"购买道具"}, priority=5, block=True, permission=GROUP)
|
||||||
|
|
||||||
|
|
||||||
|
@buy.handle()
|
||||||
|
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||||
|
goods = None
|
||||||
|
if arg.extract_plain_text().strip() in ["神秘药水"]:
|
||||||
|
await buy.finish("你们看看就好啦,这是不可能卖给你们的~", at_sender=True)
|
||||||
|
goods_list = [
|
||||||
|
x
|
||||||
|
for x in await GoodsInfo.get_all_goods()
|
||||||
|
if x.goods_limit_time > time.time() or x.goods_limit_time == 0
|
||||||
|
]
|
||||||
|
goods_name_list = [
|
||||||
|
x.goods_name
|
||||||
|
for x in goods_list
|
||||||
|
]
|
||||||
|
msg = arg.extract_plain_text().strip().split()
|
||||||
|
num = 1
|
||||||
|
if len(msg) > 1:
|
||||||
|
if is_number(msg[1]) and int(msg[1]) > 0:
|
||||||
|
num = int(msg[1])
|
||||||
|
else:
|
||||||
|
await buy.finish("购买的数量要是数字且大于0!", at_sender=True)
|
||||||
|
if is_number(msg[0]):
|
||||||
|
msg = int(msg[0])
|
||||||
|
if msg > len(goods_name_list) or msg < 1:
|
||||||
|
await buy.finish("请输入正确的商品id!", at_sender=True)
|
||||||
|
goods = goods_list[msg - 1]
|
||||||
|
else:
|
||||||
|
if msg[0] in goods_name_list:
|
||||||
|
for i in range(len(goods_name_list)):
|
||||||
|
if msg[0] == goods_name_list[i]:
|
||||||
|
goods = goods_list[i]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
await buy.finish("请输入正确的商品名称!")
|
||||||
|
else:
|
||||||
|
await buy.finish("请输入正确的商品名称!", at_sender=True)
|
||||||
|
async with db.transaction():
|
||||||
|
if (
|
||||||
|
await BagUser.get_gold(event.user_id, event.group_id)
|
||||||
|
) < goods.goods_price * num * goods.goods_discount:
|
||||||
|
await buy.finish("您的金币好像不太够哦", at_sender=True)
|
||||||
|
if await BagUser.buy_property(event.user_id, event.group_id, goods, num):
|
||||||
|
await buy.send(
|
||||||
|
f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!",
|
||||||
|
at_sender=True,
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} GROUP {event.group_id} "
|
||||||
|
f"花费 {goods.goods_price*num} 金币购买 {goods.goods_name} ×{num} 成功!"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await buy.send(f"{goods.goods_name} 购买失败!", at_sender=True)
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} GROUP {event.group_id} "
|
||||||
|
f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 失败!"
|
||||||
|
)
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||||
|
from utils.data_utils import init_rank
|
||||||
|
from models.bag_user import BagUser
|
||||||
|
from utils.message_builder import image
|
||||||
|
from utils.utils import is_number
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "商店 - 我的金币"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
我的金币
|
||||||
|
指令:
|
||||||
|
我的金币
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "商店 - 我的金币"
|
||||||
|
__plugin_cmd__ = ["我的金币"]
|
||||||
|
__plugin_type__ = ("商店",)
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"limit_superuser": False,
|
||||||
|
"cmd": ["商店", "我的金币"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
my_gold = on_command("我的金币", priority=5, block=True, permission=GROUP)
|
||||||
|
|
||||||
|
gold_rank = on_command("金币排行", priority=5, block=True, permission=GROUP)
|
||||||
|
|
||||||
|
|
||||||
|
@my_gold.handle()
|
||||||
|
async def _(event: GroupMessageEvent):
|
||||||
|
await my_gold.finish(await BagUser.get_user_total_gold(event.user_id, event.group_id))
|
||||||
|
|
||||||
|
|
||||||
|
@gold_rank.handle()
|
||||||
|
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||||
|
num = arg.extract_plain_text().strip()
|
||||||
|
if is_number(num) and 51 > int(num) > 10:
|
||||||
|
num = int(num)
|
||||||
|
else:
|
||||||
|
num = 10
|
||||||
|
all_users = await BagUser.get_all_users(event.group_id)
|
||||||
|
all_user_id = [user.user_qq for user in all_users]
|
||||||
|
all_user_data = [user.gold for user in all_users]
|
||||||
|
rank_image = await init_rank("金币排行", all_user_id, all_user_data, event.group_id, num)
|
||||||
|
if rank_image:
|
||||||
|
await gold_rank.finish(image(b64=rank_image.pic2bs4()))
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from services.log import logger
|
||||||
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent
|
||||||
|
from models.bag_user import BagUser
|
||||||
|
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "商店 - 我的道具"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
我的道具
|
||||||
|
指令:
|
||||||
|
我的道具
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "商店 - 我的道具"
|
||||||
|
__plugin_cmd__ = ["我的道具"]
|
||||||
|
__plugin_type__ = ('商店',)
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"limit_superuser": False,
|
||||||
|
"cmd": ["商店", "我的道具"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
my_props = on_command("我的道具", priority=5, block=True, permission=GROUP)
|
||||||
|
|
||||||
|
|
||||||
|
@my_props.handle()
|
||||||
|
async def _(event: GroupMessageEvent):
|
||||||
|
props = await BagUser.get_property(event.user_id, event.group_id)
|
||||||
|
if props:
|
||||||
|
rst = ""
|
||||||
|
for i, p in enumerate(props.keys()):
|
||||||
|
rst += f"{i+1}.{p}\t×{props[p]}\n"
|
||||||
|
await my_props.send("\n" + rst[:-1], at_sender=True)
|
||||||
|
logger.info(f"USER {event.user_id} GROUP {event.group_id} 查看我的道具")
|
||||||
|
else:
|
||||||
|
await my_props.finish("您的背包里没有任何的道具噢~", at_sender=True)
|
||||||
@@ -1,21 +1,26 @@
|
|||||||
from utils.utils import scheduler
|
from utils.utils import scheduler
|
||||||
from models.bag_user import BagUser
|
from models.bag_user import BagUser
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
|
|
||||||
|
|
||||||
# 重置每日金币
|
__zx_plugin_name__ = "每日金币重置 [Hidden]"
|
||||||
@scheduler.scheduled_job(
|
__plugin_version__ = 0.1
|
||||||
"cron",
|
__plugin_author__ = "HibiKier"
|
||||||
hour=0,
|
|
||||||
minute=1,
|
|
||||||
)
|
# 重置每日金币
|
||||||
async def _():
|
@scheduler.scheduled_job(
|
||||||
try:
|
"cron",
|
||||||
user_list = await BagUser.get_all_users()
|
hour=0,
|
||||||
for user in user_list:
|
minute=1,
|
||||||
await user.update(
|
)
|
||||||
get_today_gold=0,
|
async def _():
|
||||||
spend_today_gold=0,
|
try:
|
||||||
).apply()
|
user_list = await BagUser.get_all_users()
|
||||||
except Exception as e:
|
for user in user_list:
|
||||||
logger.error(f"重置每日金币错误 e:{e}")
|
await user.update(
|
||||||
|
get_today_gold=0,
|
||||||
|
spend_today_gold=0,
|
||||||
|
).apply()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"重置每日金币错误 e:{e}")
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
from .data_source import create_shop_help, delete_goods, update_goods, register_goods, parse_goods_info
|
||||||
|
from nonebot.adapters.onebot.v11 import MessageEvent, Message
|
||||||
|
from nonebot import on_command
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from utils.message_builder import image
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from utils.utils import is_number
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
from nonebot.plugin import export
|
||||||
|
from services.log import logger
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "商店"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
商店项目,这可不是奸商
|
||||||
|
指令:
|
||||||
|
商店
|
||||||
|
""".strip()
|
||||||
|
__plugin_superuser_usage__ = """
|
||||||
|
usage:
|
||||||
|
商品操作
|
||||||
|
指令:
|
||||||
|
添加商品 name:[名称] price:[价格] des:[描述] ?discount:[折扣](小数) ?limit_time:[限时时间](小时)
|
||||||
|
删除商品 [名称或序号]
|
||||||
|
修改商品 name:[名称或序号] price:[价格] des:[描述] discount:[折扣] limit_time:[限时]
|
||||||
|
示例:添加商品 name:萝莉酒杯 price:9999 des:普通的酒杯,但是里面.. discount:0.4 limit_time:90
|
||||||
|
示例:添加商品 name:可疑的药 price:5 des:效果未知
|
||||||
|
示例:删除商品 2
|
||||||
|
示例:修改商品 name:1 price:900 修改序号为1的商品的价格为900
|
||||||
|
* 修改商品只需添加需要值即可 *
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "商店系统[金币回收计划]"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"商店",
|
||||||
|
"添加商品 name:[名称] price:[价格] des:[描述] ?discount:[折扣](小数) ?limit_time:[限时时间](小时)) [_superuser]",
|
||||||
|
"删除商品 [名称或序号] [_superuser]",
|
||||||
|
"修改商品 name:[名称或序号] price:[价格] des:[描述] discount:[折扣] limit_time:[限时] [_superuser]",
|
||||||
|
]
|
||||||
|
__plugin_type__ = ('商店',)
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"limit_superuser": False,
|
||||||
|
"cmd": ["商店"],
|
||||||
|
}
|
||||||
|
__plugin_block_limit__ = {
|
||||||
|
"limit_type": "group"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 导出方法供其他插件使用
|
||||||
|
export = export()
|
||||||
|
export.register_goods = register_goods
|
||||||
|
export.delete_goods = delete_goods
|
||||||
|
export.update_goods = update_goods
|
||||||
|
|
||||||
|
shop_help = on_command("商店", priority=5, block=True)
|
||||||
|
|
||||||
|
shop_add_goods = on_command("添加商品", priority=5, permission=SUPERUSER, block=True)
|
||||||
|
|
||||||
|
shop_del_goods = on_command("删除商品", priority=5, permission=SUPERUSER, block=True)
|
||||||
|
|
||||||
|
shop_update_goods = on_command("修改商品", priority=5, permission=SUPERUSER, block=True)
|
||||||
|
|
||||||
|
|
||||||
|
@shop_help.handle()
|
||||||
|
async def _():
|
||||||
|
await shop_help.send(image(b64=await create_shop_help()))
|
||||||
|
|
||||||
|
|
||||||
|
@shop_add_goods.handle()
|
||||||
|
async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
if msg:
|
||||||
|
data = parse_goods_info(msg)
|
||||||
|
if isinstance(data, str):
|
||||||
|
await shop_add_goods.finish(data)
|
||||||
|
if not data.get("name") or not data.get("price") or not data.get("des"):
|
||||||
|
await shop_add_goods.finish("name:price:des 参数不可缺少!")
|
||||||
|
if await register_goods(**data):
|
||||||
|
await shop_add_goods.send(f"添加商品 {data['name']} 成功!\n"
|
||||||
|
f"名称:{data['name']}\n"
|
||||||
|
f"价格:{data['price']}金币\n"
|
||||||
|
f"简介:{data['des']}\n"
|
||||||
|
f"折扣:{data.get('discount')}\n"
|
||||||
|
f"限时:{data.get('limit_time')}", at_sender=True)
|
||||||
|
logger.info(f"USER {event.user_id} 添加商品 {msg} 成功")
|
||||||
|
else:
|
||||||
|
await shop_add_goods.send(f"添加商品 {msg} 失败了...", at_sender=True)
|
||||||
|
logger.warning(f"USER {event.user_id} 添加商品 {msg} 失败")
|
||||||
|
|
||||||
|
|
||||||
|
@shop_del_goods.handle()
|
||||||
|
async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
if msg:
|
||||||
|
name = ""
|
||||||
|
id_ = 0
|
||||||
|
if is_number(msg):
|
||||||
|
id_ = int(msg)
|
||||||
|
else:
|
||||||
|
name = msg
|
||||||
|
rst, goods_name, code = await delete_goods(name, id_)
|
||||||
|
if code == 200:
|
||||||
|
await shop_del_goods.send(f"删除商品 {goods_name} 成功了...", at_sender=True)
|
||||||
|
if os.path.exists(f"{IMAGE_PATH}/shop_help.png"):
|
||||||
|
os.remove(f"{IMAGE_PATH}/shop_help.png")
|
||||||
|
logger.info(f"USER {event.user_id} 删除商品 {goods_name} 成功")
|
||||||
|
else:
|
||||||
|
await shop_del_goods.send(f"删除商品 {goods_name} 失败了...", at_sender=True)
|
||||||
|
logger.info(f"USER {event.user_id} 删除商品 {goods_name} 失败")
|
||||||
|
|
||||||
|
|
||||||
|
@shop_update_goods.handle()
|
||||||
|
async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
if msg:
|
||||||
|
data = parse_goods_info(msg)
|
||||||
|
if isinstance(data, str):
|
||||||
|
await shop_add_goods.finish(data)
|
||||||
|
if not data.get("name"):
|
||||||
|
await shop_add_goods.finish("name 参数不可缺少!")
|
||||||
|
flag, name, text = await update_goods(**data)
|
||||||
|
if flag:
|
||||||
|
await shop_update_goods.send(f"修改商品 {name} 成功了...\n{text}", at_sender=True)
|
||||||
|
logger.info(f"USER {event.user_id} 修改商品 {name} 数据 {text} 成功")
|
||||||
|
else:
|
||||||
|
await shop_update_goods.send(f"修改商品 {name} 失败了...", at_sender=True)
|
||||||
|
logger.info(f"USER {event.user_id} 修改商品 {name} 数据 {text} 失败")
|
||||||
|
|
||||||
@@ -0,0 +1,269 @@
|
|||||||
|
from models.goods_info import GoodsInfo
|
||||||
|
from utils.image_utils import BuildImage
|
||||||
|
from models.sign_group_user import SignGroupUser
|
||||||
|
from utils.utils import is_number
|
||||||
|
from configs.path_config import IMAGE_PATH
|
||||||
|
from typing import Optional, Union
|
||||||
|
from configs.config import Config
|
||||||
|
from nonebot import Driver
|
||||||
|
from nonebot.plugin import require
|
||||||
|
import nonebot
|
||||||
|
import time
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
use = require("use")
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def init_default_shop_goods():
|
||||||
|
"""
|
||||||
|
导入内置的三个商品
|
||||||
|
"""
|
||||||
|
async def sign_card(**kwargs):
|
||||||
|
user_id = kwargs['user_id']
|
||||||
|
group_id = kwargs['group_id']
|
||||||
|
prob = kwargs["prob"]
|
||||||
|
user = await SignGroupUser.ensure(user_id, group_id)
|
||||||
|
await user.update(add_probability=prob).apply()
|
||||||
|
|
||||||
|
if Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS"):
|
||||||
|
await register_goods(
|
||||||
|
"好感度双倍加持卡Ⅰ", 30, "下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)"
|
||||||
|
)
|
||||||
|
use.register_use("好感度双倍加持卡Ⅰ", sign_card, **{"prob": 0.1})
|
||||||
|
await register_goods("好感度双倍加持卡Ⅱ", 150, "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)")
|
||||||
|
use.register_use("好感度双倍加持卡Ⅱ", sign_card, **{"prob": 0.2})
|
||||||
|
await register_goods(
|
||||||
|
"好感度双倍加持卡Ⅲ", 250, "下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)"
|
||||||
|
)
|
||||||
|
use.register_use("好感度双倍加持卡Ⅲ", sign_card, **{"prob": 0.3})
|
||||||
|
|
||||||
|
|
||||||
|
# 创建商店界面
|
||||||
|
async def create_shop_help() -> str:
|
||||||
|
"""
|
||||||
|
制作商店图片
|
||||||
|
:return: 图片base64
|
||||||
|
"""
|
||||||
|
goods_lst = await GoodsInfo.get_all_goods()
|
||||||
|
idx = 1
|
||||||
|
_dc = {}
|
||||||
|
font_h = BuildImage(0, 0).getsize("正")[1]
|
||||||
|
h = 10
|
||||||
|
_list = []
|
||||||
|
for goods in goods_lst:
|
||||||
|
if goods.goods_limit_time == 0 or time.time() < goods.goods_limit_time:
|
||||||
|
h += len(goods.goods_description.strip().split("\n")) * font_h + 80
|
||||||
|
_list.append(goods)
|
||||||
|
A = BuildImage(1000, h, color="#f9f6f2")
|
||||||
|
current_h = 0
|
||||||
|
for goods in _list:
|
||||||
|
bk = BuildImage(
|
||||||
|
700, 80, font_size=15, color="#f9f6f2", font="CJGaoDeGuo.otf"
|
||||||
|
)
|
||||||
|
goods_image = BuildImage(
|
||||||
|
600, 80, font_size=20, color="#a29ad6", font="CJGaoDeGuo.otf"
|
||||||
|
)
|
||||||
|
name_image = BuildImage(
|
||||||
|
580, 40, font_size=25, color="#e67b6b", font="CJGaoDeGuo.otf"
|
||||||
|
)
|
||||||
|
await name_image.atext(
|
||||||
|
(15, 0), f"{idx}.{goods.goods_name}", center_type="by_height"
|
||||||
|
)
|
||||||
|
await name_image.aline((380, -5, 280, 45), "#a29ad6", 5)
|
||||||
|
await name_image.atext((390, 0), "售价:", center_type="by_height")
|
||||||
|
await name_image.atext(
|
||||||
|
(440, 0), str(goods.goods_price), (255, 255, 255), center_type="by_height"
|
||||||
|
)
|
||||||
|
await name_image.atext(
|
||||||
|
(
|
||||||
|
440
|
||||||
|
+ BuildImage(0, 0, plain_text=str(goods.goods_price), font_size=25).w,
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
" 金币",
|
||||||
|
center_type="by_height",
|
||||||
|
)
|
||||||
|
await name_image.acircle_corner(5)
|
||||||
|
await goods_image.apaste(name_image, (0, 5), True, center_type="by_width")
|
||||||
|
await goods_image.atext((15, 50), f"简介:{goods.goods_description}")
|
||||||
|
await goods_image.acircle_corner(20)
|
||||||
|
await bk.apaste(goods_image, alpha=True)
|
||||||
|
# 添加限时图标和时间
|
||||||
|
if goods.goods_limit_time > 0:
|
||||||
|
_limit_time_logo = BuildImage(40, 40, background=f"{IMAGE_PATH}/other/time.png")
|
||||||
|
await bk.apaste(_limit_time_logo, (600, 0), True)
|
||||||
|
await bk.apaste(BuildImage(0, 0, plain_text="限时!", font_size=23, font="CJGaoDeGuo.otf"), (640, 10), True)
|
||||||
|
limit_time = time.strftime("%Y-%m-%d %H:%M", time.localtime(goods.goods_limit_time)).split()
|
||||||
|
y_m_d = limit_time[0]
|
||||||
|
_h_m = limit_time[1].split(":")
|
||||||
|
h_m = _h_m[0] + "时 " + _h_m[1] + "分"
|
||||||
|
await bk.atext((605, 38), str(y_m_d))
|
||||||
|
await bk.atext((615, 57), str(h_m))
|
||||||
|
await bk.aline((550, -1, 710, -1), "#a29ad6", 5)
|
||||||
|
await bk.aline((550, 80, 710, 80), "#a29ad6", 5)
|
||||||
|
idx += 1
|
||||||
|
await A.apaste(bk, (0, current_h), True)
|
||||||
|
current_h += 90
|
||||||
|
w = 1000
|
||||||
|
h = A.h + 230 + 100
|
||||||
|
h = 1000 if h < 1000 else h
|
||||||
|
shop_logo = BuildImage(100, 100, background=f"{IMAGE_PATH}/other/shop_text.png")
|
||||||
|
shop = BuildImage(w, h, font_size=20, color="#f9f6f2")
|
||||||
|
shop.paste(A, (20, 230))
|
||||||
|
zx_img = BuildImage(0, 0, background=f"{IMAGE_PATH}/zhenxun/toukan.png")
|
||||||
|
zx_img.replace_color_tran(((240, 240, 240), (255, 255, 255)), (249, 246, 242))
|
||||||
|
await shop.apaste(zx_img, (780, 100))
|
||||||
|
await shop.apaste(shop_logo, (450, 30), True)
|
||||||
|
shop.text(
|
||||||
|
(int((1000 - shop.getsize("注【通过 序号 或者 商品名称 购买】")[0]) / 2), 170),
|
||||||
|
"注【通过 序号 或者 商品名称 购买】",
|
||||||
|
)
|
||||||
|
shop.text((20, h - 100), "神秘药水\t\t售价:9999999金币\n\t\t鬼知道会有什么效果~")
|
||||||
|
return shop.pic2bs4()
|
||||||
|
|
||||||
|
|
||||||
|
async def register_goods(
|
||||||
|
name: str,
|
||||||
|
price: int,
|
||||||
|
des: str,
|
||||||
|
discount: Optional[float] = 1,
|
||||||
|
limit_time: Optional[int] = 0,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
添加商品
|
||||||
|
例如: 折扣:可选参数↓ 限时时间:可选,单位为小时
|
||||||
|
添加商品 name:萝莉酒杯 price:9999 des:普通的酒杯,但是里面.. discount:0.4 limit_time:90
|
||||||
|
添加商品 name:可疑的药 price:5 des:效果未知
|
||||||
|
:param name: 商品名称
|
||||||
|
:param price: 商品价格
|
||||||
|
:param des: 商品简介
|
||||||
|
:param discount: 商品折扣
|
||||||
|
:param limit_time: 商品限时销售时间,单位为小时
|
||||||
|
:param kwargs: kwargs
|
||||||
|
:return: 是否添加成功
|
||||||
|
"""
|
||||||
|
if kwargs:
|
||||||
|
name = kwargs.get("name")
|
||||||
|
price = kwargs.get("price")
|
||||||
|
des = kwargs.get("des")
|
||||||
|
discount = kwargs.get("discount")
|
||||||
|
limit_time = kwargs.get("time_limit")
|
||||||
|
limit_time = float(limit_time) if limit_time else limit_time
|
||||||
|
discount = discount if discount is None else 1
|
||||||
|
limit_time = int(time.time() + limit_time * 60 * 60) if limit_time is not None and limit_time != 0 else 0
|
||||||
|
return await GoodsInfo.add_goods(
|
||||||
|
name, int(price), des, float(discount), limit_time
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# 删除商品
|
||||||
|
async def delete_goods(name: str, id_: int) -> "str, str, int":
|
||||||
|
"""
|
||||||
|
删除商品
|
||||||
|
:param name: 商品名称
|
||||||
|
:param id_: 商品id
|
||||||
|
:return: 删除状况
|
||||||
|
"""
|
||||||
|
goods_lst = await GoodsInfo.get_all_goods()
|
||||||
|
if id_:
|
||||||
|
if id_ < 1 or id_ > len(goods_lst):
|
||||||
|
return "序号错误,没有该序号商品...", "", 999
|
||||||
|
goods_name = goods_lst[id_ - 1].goods_name
|
||||||
|
if await GoodsInfo.delete_goods(goods_name):
|
||||||
|
return f"删除商品 {goods_name} 成功!", goods_name, 200
|
||||||
|
else:
|
||||||
|
return f"删除商品 {goods_name} 失败!", goods_name, 999
|
||||||
|
if name:
|
||||||
|
if await GoodsInfo.delete_goods(name):
|
||||||
|
return f"删除商品 {name} 成功!", name, 200
|
||||||
|
else:
|
||||||
|
return f"删除商品 {name} 失败!", name, 999
|
||||||
|
|
||||||
|
|
||||||
|
# 更新商品信息
|
||||||
|
async def update_goods(**kwargs) -> "str, str, int":
|
||||||
|
"""
|
||||||
|
更新商品信息
|
||||||
|
:param kwargs: kwargs
|
||||||
|
:return: 更新状况
|
||||||
|
"""
|
||||||
|
if kwargs:
|
||||||
|
goods_lst = await GoodsInfo.get_all_goods()
|
||||||
|
if is_number(kwargs["name"]):
|
||||||
|
if int(kwargs["name"]) < 1 or int(kwargs["name"]) > len(goods_lst):
|
||||||
|
return "序号错误,没有该序号的商品...", "", 999
|
||||||
|
goods = goods_lst[int(kwargs["name"]) - 1]
|
||||||
|
else:
|
||||||
|
goods = await GoodsInfo.get_goods_info(kwargs["name"])
|
||||||
|
if not goods:
|
||||||
|
return "名称错误,没有该名称的商品...", "", 999
|
||||||
|
name = goods.goods_name
|
||||||
|
price = goods.goods_price
|
||||||
|
des = goods.goods_description
|
||||||
|
discount = goods.goods_discount
|
||||||
|
limit_time = goods.goods_limit_time
|
||||||
|
new_time = 0
|
||||||
|
tmp = ""
|
||||||
|
if kwargs.get("price"):
|
||||||
|
tmp += f'价格:{price} --> {kwargs["price"]}\n'
|
||||||
|
price = kwargs["price"]
|
||||||
|
if kwargs.get("des"):
|
||||||
|
tmp += f'描述:{des} --> {kwargs["des"]}\n'
|
||||||
|
des = kwargs["des"]
|
||||||
|
if kwargs.get("discount"):
|
||||||
|
tmp += f'折扣:{discount} --> {kwargs["discount"]}\n'
|
||||||
|
discount = kwargs["discount"]
|
||||||
|
if kwargs.get("limit_time"):
|
||||||
|
kwargs["limit_time"] = float(kwargs["limit_time"])
|
||||||
|
new_time = time.strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S",
|
||||||
|
time.localtime(time.time() + kwargs["limit_time"] * 60 * 60),
|
||||||
|
)
|
||||||
|
tmp += f"限时至: {new_time}\n"
|
||||||
|
limit_time = kwargs["limit_time"]
|
||||||
|
return (
|
||||||
|
await GoodsInfo.update_goods(
|
||||||
|
name,
|
||||||
|
int(price),
|
||||||
|
des,
|
||||||
|
float(discount),
|
||||||
|
int(time.time() + limit_time * 60 * 60 if limit_time != 0 and new_time else 0),
|
||||||
|
),
|
||||||
|
name,
|
||||||
|
tmp[:-1],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_goods_info(msg: str) -> Union[dict, str]:
|
||||||
|
"""
|
||||||
|
解析格式数据
|
||||||
|
:param msg: 消息
|
||||||
|
:return: 解析完毕的数据data
|
||||||
|
"""
|
||||||
|
if "name:" not in msg:
|
||||||
|
return "必须指定修改的商品名称或序号!"
|
||||||
|
data = {}
|
||||||
|
for x in msg.split():
|
||||||
|
sp = x.split(":", maxsplit=1)
|
||||||
|
if str(sp[1]).strip():
|
||||||
|
sp[1] = sp[1].strip()
|
||||||
|
if sp[0] == "name":
|
||||||
|
data["name"] = sp[1]
|
||||||
|
elif sp[0] == "price":
|
||||||
|
if not is_number(sp[1]) or int(sp[1]) < 0:
|
||||||
|
return "price参数不合法,必须大于等于0!"
|
||||||
|
data["price"] = sp[1]
|
||||||
|
elif sp[0] == "des":
|
||||||
|
data["des"] = sp[1]
|
||||||
|
elif sp[0] == "discount":
|
||||||
|
if not is_number(sp[1]) or float(sp[1]) < 0:
|
||||||
|
return "discount参数不合法,必须大于0!"
|
||||||
|
data["discount"] = sp[1]
|
||||||
|
elif sp[0] == "limit_time":
|
||||||
|
if not is_number(sp[1]) or float(sp[1]) < 0:
|
||||||
|
return "limit_time参数不合法,必须大于0!"
|
||||||
|
data["limit_time"] = sp[1]
|
||||||
|
return data
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from services.log import logger
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
from utils.utils import is_number
|
||||||
|
from models.bag_user import BagUser
|
||||||
|
from nonebot.adapters.onebot.v11.permission import GROUP
|
||||||
|
from services.db_context import db
|
||||||
|
from nonebot.plugin import export
|
||||||
|
from .data_source import effect, register_use, func_manager
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "商店 - 使用道具"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
普通的使用道具
|
||||||
|
指令:
|
||||||
|
使用道具 [序号或道具名称] ?[数量]=1
|
||||||
|
* 序号以 ”我的道具“ 为准 *
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "商店 - 使用道具"
|
||||||
|
__plugin_cmd__ = ["使用道具 [序号或道具名称]"]
|
||||||
|
__plugin_type__ = ('商店',)
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_settings__ = {
|
||||||
|
"level": 5,
|
||||||
|
"default_status": True,
|
||||||
|
"limit_superuser": False,
|
||||||
|
"cmd": ["商店", "使用道具"],
|
||||||
|
}
|
||||||
|
|
||||||
|
# 导出方法供其他插件使用
|
||||||
|
export = export()
|
||||||
|
export.register_use = register_use
|
||||||
|
|
||||||
|
use_props = on_command("使用道具", priority=5, block=True, permission=GROUP)
|
||||||
|
|
||||||
|
|
||||||
|
@use_props.handle()
|
||||||
|
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
num = 1
|
||||||
|
msg_sp = msg.split()
|
||||||
|
if len(msg_sp) > 1 and is_number(msg_sp[-1]) and int(msg_sp[-1]) > 0:
|
||||||
|
num = int(msg.split()[-1])
|
||||||
|
msg = " ".join(msg.split()[:-1])
|
||||||
|
property_ = await BagUser.get_property(event.user_id, event.group_id)
|
||||||
|
if property_:
|
||||||
|
async with db.transaction():
|
||||||
|
if is_number(msg):
|
||||||
|
if 0 < int(msg) <= len(property_):
|
||||||
|
name = list(property_.keys())[int(msg) - 1]
|
||||||
|
else:
|
||||||
|
await use_props.finish("仔细看看自己的道具仓库有没有这个道具?", at_sender=True)
|
||||||
|
else:
|
||||||
|
if msg not in property_.keys():
|
||||||
|
await use_props.finish("道具名称错误!", at_sender=True)
|
||||||
|
name = msg
|
||||||
|
_user_prop_count = property_[name]
|
||||||
|
if num > _user_prop_count:
|
||||||
|
await use_props.finish(f"道具数量不足,无法使用{num}次!")
|
||||||
|
if num > (n := func_manager.get_max_num_limit(name)):
|
||||||
|
await use_props.finish(f"该道具单次只能使用 {n} 个!")
|
||||||
|
if await BagUser.delete_property(
|
||||||
|
event.user_id, event.group_id, name, num
|
||||||
|
):
|
||||||
|
if func_manager.check_send_success_message(name):
|
||||||
|
await use_props.send(f"使用道具 {name} {num} 次成功!", at_sender=True)
|
||||||
|
if msg := await effect(bot, event, name, num):
|
||||||
|
await use_props.send(msg, at_sender=True)
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次成功"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await use_props.send(f"使用道具 {name} {num} 次失败!", at_sender=True)
|
||||||
|
logger.info(
|
||||||
|
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次失败"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await use_props.send("您的背包里没有任何的道具噢", at_sender=True)
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageSegment
|
||||||
|
from services.log import logger
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot
|
||||||
|
from typing import Optional, Union
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
|
class GoodsUseFuncManager:
|
||||||
|
def __init__(self):
|
||||||
|
self._data = {}
|
||||||
|
|
||||||
|
def register_use(self, goods_name: str, **kwargs):
|
||||||
|
"""
|
||||||
|
注册商品使用方法
|
||||||
|
:param goods_name: 商品名称
|
||||||
|
:param kwargs: kwargs
|
||||||
|
"""
|
||||||
|
self._data[goods_name] = kwargs
|
||||||
|
|
||||||
|
def exists(self, goods_name: str) -> bool:
|
||||||
|
"""
|
||||||
|
判断商品使用方法是否被注册
|
||||||
|
:param goods_name: 商品名称
|
||||||
|
"""
|
||||||
|
return bool(self._data.get(goods_name))
|
||||||
|
|
||||||
|
def get_max_num_limit(self, goods_name: str) -> int:
|
||||||
|
"""
|
||||||
|
获取单次商品使用数量
|
||||||
|
:param goods_name: 商品名称
|
||||||
|
"""
|
||||||
|
if self.exists(goods_name):
|
||||||
|
return self._data[goods_name]["kwargs"]["_max_num_limit"]
|
||||||
|
return 1
|
||||||
|
|
||||||
|
async def use(self, **kwargs) -> Optional[Union[str, MessageSegment]]:
|
||||||
|
"""
|
||||||
|
使用道具
|
||||||
|
:param kwargs: kwargs
|
||||||
|
"""
|
||||||
|
goods_name = kwargs.get("goods_name")
|
||||||
|
if self.exists(goods_name):
|
||||||
|
if asyncio.iscoroutinefunction(self._data[goods_name]["func"]):
|
||||||
|
return await self._data[goods_name]["func"](
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return self._data[goods_name]["func"](
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_send_success_message(self, goods_name: str) -> bool:
|
||||||
|
"""
|
||||||
|
检查是否发送使用成功信息
|
||||||
|
:param goods_name: 商品名称
|
||||||
|
"""
|
||||||
|
if self.exists(goods_name):
|
||||||
|
return bool(self._data[goods_name]["kwargs"]["send_success_msg"])
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_kwargs(self, goods_name: str) -> dict:
|
||||||
|
"""
|
||||||
|
获取商品使用方法的kwargs
|
||||||
|
:param goods_name: 商品名称
|
||||||
|
"""
|
||||||
|
if self.exists(goods_name):
|
||||||
|
return self._data[goods_name]["kwargs"]
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
func_manager = GoodsUseFuncManager()
|
||||||
|
|
||||||
|
|
||||||
|
async def effect(
|
||||||
|
bot: Bot, event: GroupMessageEvent, goods_name: str, num: int
|
||||||
|
) -> Optional[Union[str, MessageSegment]]:
|
||||||
|
"""
|
||||||
|
商品生效
|
||||||
|
:param bot: Bot
|
||||||
|
:param event: GroupMessageEvent
|
||||||
|
:param goods_name: 商品名称
|
||||||
|
:param num: 使用数量
|
||||||
|
:return: 使用是否成功
|
||||||
|
"""
|
||||||
|
# 优先使用注册的商品插件
|
||||||
|
try:
|
||||||
|
if func_manager.exists(goods_name):
|
||||||
|
_kwargs = func_manager.get_kwargs(goods_name)
|
||||||
|
return await func_manager.use(
|
||||||
|
**{
|
||||||
|
**_kwargs,
|
||||||
|
"_bot": bot,
|
||||||
|
"event": event,
|
||||||
|
"group_id": event.group_id,
|
||||||
|
"user_id": event.user_id,
|
||||||
|
"num": num,
|
||||||
|
"goods_name": goods_name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"use 商品生效函数effect 发生错误 {type(e)}:{e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def register_use(goods_name: str, func, **kwargs):
|
||||||
|
"""
|
||||||
|
注册商品使用方法
|
||||||
|
:param goods_name: 商品名称
|
||||||
|
:param func: 使用函数
|
||||||
|
:param kwargs: kwargs
|
||||||
|
"""
|
||||||
|
if func_manager.exists(goods_name):
|
||||||
|
raise ValueError("该商品使用函数已被注册!")
|
||||||
|
# 发送使用成功信息
|
||||||
|
if kwargs.get("send_success_msg") is None:
|
||||||
|
kwargs["send_success_msg"] = True
|
||||||
|
kwargs["_max_num_limit"] = (
|
||||||
|
kwargs.get("_max_num_limit") if kwargs.get("_max_num_limit") else 1
|
||||||
|
)
|
||||||
|
func_manager.register_use(goods_name, **{"func": func, "kwargs": kwargs})
|
||||||
|
logger.info(f"register_use 成功注册商品:{goods_name} 的使用函数")
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
nonebot.load_plugins('basic_plugins/super_cmd')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot, Message
|
||||||
|
from nonebot.params import Command, CommandArg
|
||||||
|
from typing import Tuple
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import 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):
|
||||||
|
gl = await bot.get_group_list()
|
||||||
|
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 cls_group.send(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@cls_friend.handle()
|
||||||
|
async def _(bot: Bot):
|
||||||
|
gl = await bot.get_friend_list()
|
||||||
|
msg = ["{user_id} {nickname}".format_map(g) for g in gl]
|
||||||
|
msg = "\n".join(msg)
|
||||||
|
msg = f"| QQ号 | 昵称 | 共{len(gl)}个好友\n" + msg
|
||||||
|
await cls_friend.send(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@friend_handle.handle()
|
||||||
|
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||||
|
cmd = cmd[0]
|
||||||
|
id_ = arg.extract_plain_text().strip()
|
||||||
|
if is_number(id_):
|
||||||
|
id_ = int(id_)
|
||||||
|
if cmd[: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, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||||
|
cmd = cmd[0]
|
||||||
|
id_ = arg.extract_plain_text().strip()
|
||||||
|
if is_number(id_):
|
||||||
|
id_ = int(id_)
|
||||||
|
if cmd[:2] == "同意":
|
||||||
|
rid = requests_manager.get_group_id(id_)
|
||||||
|
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
|
||||||
|
)
|
||||||
|
await requests_manager.approve(bot, id_, "group")
|
||||||
|
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 _():
|
||||||
|
_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 _():
|
||||||
|
requests_manager.clear()
|
||||||
|
await cls_request.send("已清空所有好友/群聊请求..")
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
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 _():
|
||||||
|
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
|
||||||
|
if file.is_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))
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import Message
|
||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from services.db_context import db
|
||||||
|
from nonebot.params import CommandArg
|
||||||
|
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 _(arg: Message = CommandArg()):
|
||||||
|
sql = arg.extract_plain_text().strip()
|
||||||
|
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,204 @@
|
|||||||
|
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GROUP, GroupMessageEvent, Message
|
||||||
|
from nonebot import on_command, on_regex
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import 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.onebot.v11.exception import ActionFailed
|
||||||
|
from nonebot.params import Command, CommandArg
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
|
||||||
|
__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, arg: Message = CommandArg()):
|
||||||
|
group_id = arg.extract_plain_text().strip()
|
||||||
|
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, arg: Message = CommandArg()):
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
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 _(event: GroupMessageEvent):
|
||||||
|
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 _():
|
||||||
|
await what_up_group_level.finish(
|
||||||
|
f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.管理员修改权限"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@manager_group_whitelist.handle()
|
||||||
|
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||||
|
cmd = cmd[0]
|
||||||
|
msg = arg.extract_plain_text().strip()
|
||||||
|
all_group = [
|
||||||
|
g["group_id"] for g in await bot.get_group_list()
|
||||||
|
]
|
||||||
|
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 cmd 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) + " " + cmd
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
|
||||||
|
|
||||||
|
|
||||||
|
@show_group_whitelist.handle()
|
||||||
|
async def _():
|
||||||
|
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, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||||
|
cmd = cmd[0]
|
||||||
|
msg = arg.extract_plain_text().strip().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 cmd[: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} {cmd[:2]}群认证..'
|
||||||
|
)
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
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 configs.config import Config
|
||||||
|
from services.log import logger
|
||||||
|
from utils.utils import scheduler
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = "重载插件配置 [Superuser]"
|
||||||
|
__plugin_usage__ = """
|
||||||
|
usage:
|
||||||
|
重载插件配置
|
||||||
|
plugins2settings,
|
||||||
|
plugins2cd
|
||||||
|
plugins2block
|
||||||
|
group_manager
|
||||||
|
指令:
|
||||||
|
重载插件配置
|
||||||
|
""".strip()
|
||||||
|
__plugin_des__ = "重载插件配置"
|
||||||
|
__plugin_cmd__ = [
|
||||||
|
"重载插件配置",
|
||||||
|
]
|
||||||
|
__plugin_version__ = 0.1
|
||||||
|
__plugin_author__ = "HibiKier"
|
||||||
|
__plugin_configs__ = {
|
||||||
|
"AUTO_RELOAD": {
|
||||||
|
"value": False,
|
||||||
|
"help": "自动重载配置文件",
|
||||||
|
"default_value": False
|
||||||
|
},
|
||||||
|
"AUTO_RELOAD_TIME": {
|
||||||
|
"value": 180,
|
||||||
|
"help": "控制自动重载配置文件时长",
|
||||||
|
"default_value": 180
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
reload_plugins_manager = on_command(
|
||||||
|
"重载配置", rule=to_me(), permission=SUPERUSER, priority=1, block=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@reload_plugins_manager.handle()
|
||||||
|
async def _():
|
||||||
|
plugins2settings_manager.reload()
|
||||||
|
plugins2cd_manager.reload()
|
||||||
|
plugins2block_manager.reload()
|
||||||
|
group_manager.reload()
|
||||||
|
Config.reload()
|
||||||
|
await reload_plugins_manager.send("重载完成...")
|
||||||
|
|
||||||
|
|
||||||
|
@scheduler.scheduled_job(
|
||||||
|
'interval',
|
||||||
|
seconds=Config.get_config("reload_setting", "AUTO_RELOAD_TIME", 180),
|
||||||
|
)
|
||||||
|
async def _():
|
||||||
|
if Config.get_config("reload_setting", "AUTO_RELOAD"):
|
||||||
|
plugins2settings_manager.reload()
|
||||||
|
plugins2cd_manager.reload()
|
||||||
|
plugins2block_manager.reload()
|
||||||
|
group_manager.reload()
|
||||||
|
Config.reload()
|
||||||
|
logger.debug("已自动重载所有配置文件...")
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from models.level_user import LevelUser
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
|
||||||
|
from utils.utils import get_message_at, is_number
|
||||||
|
from services.log import logger
|
||||||
|
from utils.message_builder import at
|
||||||
|
from nonebot.params import Command, CommandArg
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
__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: MessageEvent,
|
||||||
|
cmd: Tuple[str, ...] = Command(),
|
||||||
|
arg: Message = CommandArg(),
|
||||||
|
):
|
||||||
|
group_id = event.group_id if isinstance(event, GroupMessageEvent) else -1
|
||||||
|
level = None
|
||||||
|
args = arg.extract_plain_text().strip().split()
|
||||||
|
qq = get_message_at(event.json())
|
||||||
|
flag = 2
|
||||||
|
try:
|
||||||
|
if qq:
|
||||||
|
qq = qq[0]
|
||||||
|
if cmd[0][:2] == "添加" and args and is_number(args[0]):
|
||||||
|
level = int(args[0])
|
||||||
|
else:
|
||||||
|
if cmd[0][:2] == "添加":
|
||||||
|
if (
|
||||||
|
len(args) > 2
|
||||||
|
and 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])
|
||||||
|
else:
|
||||||
|
if len(args) > 1 and is_number(args[0]) and is_number(args[1]):
|
||||||
|
qq = int(args[0])
|
||||||
|
group_id = int(args[1])
|
||||||
|
flag = 1
|
||||||
|
level = -1 if cmd[0][:2] == "删除" else level
|
||||||
|
if group_id == -1 or not level or not qq:
|
||||||
|
raise IndexError()
|
||||||
|
except IndexError:
|
||||||
|
await super_cmd.finish(__plugin_usage__)
|
||||||
|
try:
|
||||||
|
if cmd[0][:2] == "添加":
|
||||||
|
if await LevelUser.set_level(qq, group_id, level, 1):
|
||||||
|
result = f"添加管理成功, 权限: {level}"
|
||||||
|
else:
|
||||||
|
result = f"管理已存在, 更新权限: {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 if level != -1 else 0}"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
await super_cmd.send("修改成功")
|
||||||
|
except Exception as e:
|
||||||
|
await super_cmd.send("执行指令失败!")
|
||||||
|
logger.error(f"执行指令失败 e:{e}")
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message
|
||||||
|
from nonebot.rule import to_me
|
||||||
|
from utils.utils import is_number
|
||||||
|
from services.log import logger
|
||||||
|
from utils.manager import group_manager
|
||||||
|
from nonebot.params import Command, CommandArg
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
|
||||||
|
__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, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||||
|
cmd = cmd[0]
|
||||||
|
group = arg.extract_plain_text().strip()
|
||||||
|
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 cmd == "开启广播通知":
|
||||||
|
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,69 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
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 = 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 _():
|
||||||
|
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,27 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
__zx_plugin_name__ = '超级用户帮助 [Superuser]'
|
||||||
|
|
||||||
|
|
||||||
|
superuser_help_image = 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 _():
|
||||||
|
if not superuser_help_image.exists():
|
||||||
|
await create_help_image()
|
||||||
|
x = image(superuser_help_image)
|
||||||
|
await super_help.finish(x)
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
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.onebot.v11 import Bot
|
||||||
|
from nonebot import Driver
|
||||||
|
import asyncio
|
||||||
|
import nonebot
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
background = IMAGE_PATH / "background" / "0.png"
|
||||||
|
|
||||||
|
superuser_help_image = 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.plugin_name)
|
||||||
|
_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.plugin_name}: {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,33 @@
|
|||||||
|
from nonebot import on_command
|
||||||
|
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 _():
|
||||||
|
img = image("update_info.png")
|
||||||
|
if img:
|
||||||
|
await update_info.finish(image("update_info.png"))
|
||||||
|
else:
|
||||||
|
await update_info.finish("目前没有更新信息哦")
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
import nonebot
|
import nonebot
|
||||||
from nonebot.adapters.cqhttp import Bot as CQHTTPBot
|
from nonebot.adapters.onebot.v11 import Adapter
|
||||||
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(Adapter)
|
||||||
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,24 +1,10 @@
|
|||||||
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 pathlib import Path
|
||||||
|
from .utils import ConfigsManager
|
||||||
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
# 是否使用配置文件
|
|
||||||
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就不需要再填写后面的字段了#)
|
||||||
@@ -31,199 +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 = "才不会给你发消息."
|
|
||||||
|
|
||||||
|
|
||||||
# 插件配置
|
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] = (0, 1)
|
|
||||||
|
|
||||||
# 各种卡池的开关
|
|
||||||
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 = 8 # 恶意命令触发检测最大触发次数
|
|
||||||
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 # 群员活跃检测设置权限
|
|
||||||
|
|
||||||
# 是否开启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,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# 模块与对应命令和对应群权限
|
|
||||||
# 用于生成帮助图片 和 开关功能
|
|
||||||
plugins2info_dict = {
|
|
||||||
"sign_in": {"level": 5, "cmd": ["签到"]},
|
|
||||||
"send_img": {"level": 5, "cmd": ["发送图片", "发图", "萝莉", "美图", "壁纸"]},
|
|
||||||
"send_setu": {"level": 9, "cmd": ["色图", "涩图", "瑟图", "查色图"]},
|
|
||||||
"white2black": {"level": 5, "cmd": ["黑白图", "黑白草图"]},
|
|
||||||
"coser": {"level": 9, "cmd": ["coser", "cos"]},
|
|
||||||
"quotations": {"level": 5, "cmd": ["语录"]},
|
|
||||||
"jitang": {"level": 5, "cmd": ["鸡汤"]},
|
|
||||||
"send_dinggong_voice": {"level": 5, "cmd": ["骂我", "骂老子", "骂劳资"]},
|
|
||||||
"open_cases": {"level": 5, "cmd": ["开箱", "我的开箱", "群开箱统计", "我的金色"]},
|
|
||||||
"luxun": {"level": 5, "cmd": ["鲁迅说", "鲁迅说过"]},
|
|
||||||
"fake_msg": {"level": 5, "cmd": ["假消息"]},
|
|
||||||
"buy": {"level": 5, "cmd": ["购买", "购买道具"]},
|
|
||||||
"my_gold": {"level": 5, "cmd": ["我的金币"]},
|
|
||||||
"my_props": {"level": 5, "cmd": ["我的道具"]},
|
|
||||||
"shop_handle": {"level": 5, "cmd": ["商店"]},
|
|
||||||
"update_pic": {"level": 5, "cmd": ["图片", "操作图片", "修改图片"]},
|
|
||||||
"search_buff_skin_price": {"level": 5, "cmd": ["查询皮肤"]},
|
|
||||||
"weather": {"level": 5, "cmd": ["天气", "查询天气", "天气查询"]},
|
|
||||||
"yiqing": {"level": 5, "cmd": ["疫情", "疫情查询", "查询疫情"]},
|
|
||||||
"what_anime": {"level": 5, "cmd": ["识番"]},
|
|
||||||
"search_anime": {"level": 5, "cmd": ["搜番"]},
|
|
||||||
"songpicker2": {"level": 5, "cmd": ["点歌"]},
|
|
||||||
"epic": {"level": 5, "cmd": ["epic"]},
|
|
||||||
"pixiv": {"level": 9, "cmd": ["pixiv", "p站排行", "搜图"]},
|
|
||||||
"poke": {"level": 5, "cmd": ["戳一戳", "拍一拍"]},
|
|
||||||
"draw_card": {
|
|
||||||
"level": 5,
|
|
||||||
"cmd": [
|
|
||||||
"抽卡",
|
|
||||||
"游戏抽卡",
|
|
||||||
"原神抽卡",
|
|
||||||
"方舟抽卡",
|
|
||||||
"坎公骑冠剑抽卡",
|
|
||||||
"pcr抽卡",
|
|
||||||
"fgo抽卡",
|
|
||||||
"碧蓝抽卡",
|
|
||||||
"碧蓝航线抽卡",
|
|
||||||
"阴阳师抽卡",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"ai": {"level": 5, "cmd": ["ai", "Ai", "AI", "aI"]},
|
|
||||||
"one_friend": {"level": 5, "cmd": ["我有一个朋友", "我有一个朋友想问问"]},
|
|
||||||
"translate": {"level": 5, "cmd": ["翻译", "英翻", "翻英", "日翻", "翻日", "韩翻", "翻韩"]},
|
|
||||||
"nonebot_plugin_picsearcher": {"level": 5, "cmd": ["识图"]},
|
|
||||||
"almanac": {"level": 5, "cmd": ["原神黄历", "黄历"]},
|
|
||||||
"material_remind": {"level": 5, "cmd": ["今日素材", "天赋材料"]},
|
|
||||||
"qiu_qiu_translation": {"level": 5, "cmd": ["丘丘翻译", "丘丘一下", "丘丘语翻译"]},
|
|
||||||
"query_resource_points": {"level": 5, "cmd": ["原神资源查询", "原神资源列表"]},
|
|
||||||
"russian": {"level": 5, "cmd": ["俄罗斯轮盘", "俄罗斯转盘", "装弹"]},
|
|
||||||
"gold_redbag": {"level": 5, "cmd": ["塞红包", "红包", "抢红包"]},
|
|
||||||
"poetry": {"level": 5, "cmd": ["念诗", "来首诗", "念首诗"]},
|
|
||||||
"comments_163": {"level": 5, "cmd": ["到点了", "12点了", "网易云热评", "网易云评论"]},
|
|
||||||
"cover": {"level": 5, "cmd": ["b封面", "B封面"]},
|
|
||||||
"pid_search": {"level": 9, "cmd": ["p搜", "P搜"]},
|
|
||||||
"pix": {
|
|
||||||
"level": 5,
|
|
||||||
"cmd": ["pix", "PIX", "pIX", "Pix", "PIx"],
|
|
||||||
},
|
|
||||||
"wbtop": {
|
|
||||||
"level": 5,
|
|
||||||
"cmd": ['微博热搜', "微博", "wbtop"]
|
|
||||||
},
|
|
||||||
"update_info": {
|
|
||||||
"level": 5,
|
|
||||||
"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:
|
|
||||||
# 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,62 +1,45 @@
|
|||||||
from .utils.util import get_config_data
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
# from configs.config import USE_CONFIG_FILE
|
import os
|
||||||
|
|
||||||
# 图片路径
|
# 图片路径
|
||||||
IMAGE_PATH = Path("resources/img/")
|
IMAGE_PATH = Path() / "resources" / "image"
|
||||||
# 音频路径
|
# 语音路径
|
||||||
VOICE_PATH = Path("resources/voice/")
|
RECORD_PATH = Path() / "resources" / "record"
|
||||||
# 文本路径
|
# 文本路径
|
||||||
TXT_PATH = Path("resources/txt/")
|
TEXT_PATH = Path() / "resources" / "text"
|
||||||
# 日志路径
|
# 日志路径
|
||||||
LOG_PATH = Path("log/")
|
LOG_PATH = Path() / "log"
|
||||||
# 字体路径
|
# 字体路径
|
||||||
TTF_PATH = Path("resources/ttf/")
|
FONT_PATH = Path() / "resources" / "font"
|
||||||
# 数据路径
|
# 数据路径
|
||||||
DATA_PATH = Path("data/")
|
DATA_PATH = Path() / "data"
|
||||||
# 临时图片路径
|
# 临时数据路径
|
||||||
TEMP_PATH = Path("resources/img/temp/")
|
TEMP_PATH = Path() / "resources" / "temp"
|
||||||
|
|
||||||
|
|
||||||
def init_path():
|
def load_path():
|
||||||
global IMAGE_PATH, VOICE_PATH, TXT_PATH, LOG_PATH, TTF_PATH, DATA_PATH, TEMP_PATH
|
old_img_dir = Path() / "resources" / "img"
|
||||||
# if USE_CONFIG_FILE:
|
if not IMAGE_PATH.exists() and old_img_dir.exists():
|
||||||
# data = get_config_data()
|
os.rename(old_img_dir, IMAGE_PATH)
|
||||||
# if data.get('IMAGE_PATH'):
|
old_voice_dir = Path() / "resources" / "voice"
|
||||||
# IMAGE_PATH = Path(data['IMAGE_PATH'])
|
if not RECORD_PATH.exists() and old_voice_dir.exists():
|
||||||
# if data.get('VOICE_PATH'):
|
os.rename(old_voice_dir, RECORD_PATH)
|
||||||
# VOICE_PATH = Path(data['VOICE_PATH'])
|
old_ttf_dir = Path() / "resources" / "ttf"
|
||||||
# if data.get('TXT_PATH'):
|
if not FONT_PATH.exists() and old_ttf_dir.exists():
|
||||||
# TXT_PATH = Path(data['TXT_PATH'])
|
os.rename(old_ttf_dir, FONT_PATH)
|
||||||
# if data.get('LOG_PATH'):
|
old_txt_dir = Path() / "resources" / "txt"
|
||||||
# LOG_PATH = Path(data['LOG_PATH'])
|
if not TEXT_PATH.exists() and old_txt_dir.exists():
|
||||||
# if data.get('TTF_PATH'):
|
os.rename(old_txt_dir, TEXT_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)
|
RECORD_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()) + '/'
|
|
||||||
VOICE_PATH = str(VOICE_PATH.absolute()) + '/'
|
load_path()
|
||||||
TXT_PATH = str(TXT_PATH.absolute()) + '/'
|
|
||||||
LOG_PATH = str(LOG_PATH.absolute()) + '/'
|
|
||||||
TTF_PATH = str(TTF_PATH.absolute()) + '/'
|
|
||||||
DATA_PATH = str(DATA_PATH.absolute()) + '/'
|
|
||||||
TEMP_PATH = str(TEMP_PATH.absolute()) + '/'
|
|
||||||
|
|
||||||
|
|
||||||
init_path()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print(IMAGE_PATH)
|
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
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 reload(self):
|
||||||
|
"""
|
||||||
|
重新加载配置文件
|
||||||
|
"""
|
||||||
|
_yaml = YAML()
|
||||||
|
temp_file = Path() / "configs" / "config.yaml"
|
||||||
|
if temp_file.exists():
|
||||||
|
with open(temp_file, "r", encoding="utf8") as f:
|
||||||
|
temp = _yaml.load(f)
|
||||||
|
for key in temp.keys():
|
||||||
|
for k in temp[key].keys():
|
||||||
|
self._data[key][k]["value"] = temp[key][k]
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
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 |