├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_request.yml
├── renovate.json
└── workflows
│ └── python-publish.yml
├── LICENSE
├── README.md
├── nonebot_plugin_blacklist
└── __init__.py
└── pyproject.toml
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 🐛 问题汇报
2 | description: 汇报错误或意外行为
3 | labels: [ bug ]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | [GitHub Issues](https://github.com/tkgs0/nonebot-plugin-blacklist/issues) 专门用于错误报告和功能需求,这意味着我们不接受使用问题。如果您打开的问题不符合要求,它将会被无条件关闭。
9 |
10 | 有关使用问题,请通过以下途径:
11 |
12 | - 阅读文档以解决
13 | - 在社区内寻求他人解答
14 | - 在 [GitHub Discussions](https://github.com/tkgs0/nonebot-plugin-blacklist/discussions) 上提问
15 | - 在网络中搜索是否有人遇到过类似的问题
16 |
17 | 如果您不知道如何有效、精准地提出一个问题,我们建议您先阅读[《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)。
18 |
19 | 最后,请记得遵守我们的社区准则,友好交流。
20 |
21 | - type: markdown
22 | attributes:
23 | value: "## 注意事项"
24 | - type: markdown
25 | attributes:
26 | value: |
27 | 在提 issue 前请确保你仔细阅读过文档,搜索过现有的 issue ,并确保你使用的是最新的 nonebot-plugin-blacklist 。
28 |
29 | 在启动本项目出现错误时,你可以无视堆栈 (stack) 相关的信息,但错误信息 (Error: xxxxx) 请认真看看,自己稍微翻译翻译就知道大体意思,大部分问题你都可以在本项目文档或搜索引擎中找到解答。
30 |
31 | **这些 issue 不会被受理:**
32 |
33 | 1. 文档中有提到的
34 | 2. 使用的 nonebot-plugin-blacklist 不是最新的
35 | 3. 大部分“连接失败”问题,请自己排查配置等原因
36 |
37 | - type: checkboxes
38 | attributes:
39 | label: 报告清单
40 | description: 请确认您已遵守所有必选项。
41 | options:
42 | - label: 我已仔细阅读并了解上述注意事项。
43 | required: true
44 | - label: 我已使用最新版本测试过,确认问题依旧存在。
45 | required: true
46 | - label: 我确定在 [GitHub Issues](https://github.com/tkgs0/nonebot-plugin-blacklist/issues) 中没有相同或相似的问题。
47 | required: true
48 |
49 | - type: input
50 | attributes:
51 | label: nonebot-plugin-blacklist
52 | placeholder: 你所使用的 nonebot-plugin-blacklist 版本
53 | validations:
54 | required: true
55 |
56 | - type: input
57 | attributes:
58 | label: client
59 | placeholder: 你所使用的协议端名称以及其版本
60 | validations:
61 | required: true
62 |
63 | - type: input
64 | attributes:
65 | label: nonebot-adapter
66 | placeholder: 你所使用的适配器名称以及其版本
67 | validations:
68 | required: true
69 |
70 | - type: input
71 | attributes:
72 | label: nonebot
73 | placeholder: 你所使用的 nonebot 版本
74 | validations:
75 | required: true
76 |
77 | - type: input
78 | attributes:
79 | label: Python
80 | placeholder: 你所使用的 Python 版本
81 | validations:
82 | required: true
83 |
84 | - type: input
85 | attributes:
86 | label: 操作系统
87 | placeholder: 你所使用的操作系统以及其版本
88 | validations:
89 | required: true
90 |
91 | - type: textarea
92 | id: installed_packages
93 | attributes:
94 | label: 列出安装的 Python 包
95 | placeholder: 把 pip freeze -l 执行的结果贴到此处。
96 | description: 如果你不是通过 pip 或 nb-cli 下载的 nonebot-plugin-blacklist ,请把你安装的 Python 包列出来。
97 | validations:
98 | required: false
99 |
100 | - type: textarea
101 | id: problem_description
102 | attributes:
103 | label: 问题描述
104 | description: 请清晰简洁地说明问题是什么,并解释您是如何遇到此问题的,以及您为此做出的尝试。
105 | validations:
106 | required: true
107 |
108 | - type: textarea
109 | id: reproduction
110 | attributes:
111 | label: 复现步骤
112 | description: |
113 | 提供能复现此问题的详细操作步骤。如果可能,请尝试提供一个可复现的测试用例,该测试用例是发生问题所需的最低限度。
114 | 推荐阅读:[《如何创建一个最小的、可复现的示例》](https://stackoverflow.com/help/minimal-reproducible-example)
115 | placeholder: "1. 当......\n2. 然后......\n3. 发生......"
116 | validations:
117 | required: true
118 |
119 | - type: textarea
120 | id: expectation
121 | attributes:
122 | label: 期望行为
123 | placeholder: 期望的正常行为是怎么样的?
124 | validations:
125 | required: false
126 |
127 | - type: textarea
128 | id: actuality
129 | attributes:
130 | label: 实际行为
131 | placeholder: 实际上发生了什么?
132 | validations:
133 | required: true
134 |
135 | - type: textarea
136 | id: log
137 | attributes:
138 | label: 日志信息
139 | description: |
140 | 提供有助于诊断问题的任何日志和完整的错误信息。
141 | 可截图,可粘贴文本,可上传日志文件,如粘贴文本请务必用 markdown 代码块包裹。
142 | placeholder: 请注意将您的敏感信息从日志中过滤或替换。
143 | validations:
144 | required: true
145 |
146 | - type: textarea
147 | id: other
148 | attributes:
149 | label: 额外补充
150 | description: |
151 | 在此处添加相关的任何其他上下文或截图,或者您觉得有帮助的信息。
152 | - 问题相关截图,例如机器人回复异常时的聊天截图
153 | - 可能与 bug 有关的配置内容
154 | validations:
155 | required: false
156 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: ✨ 功能需求
2 | description: 为项目提出一个新的想法或建议
3 | labels: [ enhancement ]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | [GitHub Issues](https://github.com/tkgs0/nonebot-plugin-blacklist/issues) 专门用于错误报告和功能需求,这意味着我们不接受使用问题。如果您打开的问题不符合要求,它将会被无条件关闭。
9 |
10 | 有关使用问题,请通过以下途径:
11 |
12 | - 阅读文档以解决
13 | - 在社区内寻求他人解答
14 | - 在 [GitHub Discussions](https://github.com/tkgs0/nonebot-plugin-blacklist/discussions) 上提问
15 | - 在网络中搜索是否有人遇到过类似的问题
16 |
17 | 如果您不知道如何有效、精准地提出一个问题,我们建议您先阅读[《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)。
18 |
19 | 最后,请记得遵守我们的社区准则,友好交流。
20 |
21 | - type: markdown
22 | attributes:
23 | value: "## 注意事项"
24 | - type: markdown
25 | attributes:
26 | value: |
27 | 在提 issue 前请确保你仔细阅读过文档,搜索过现有的 issue ,并确保你使用的是最新的 nonebot-plugin-blacklist ,避免发生 “提出的需求是已经实现了的” 这种令人哭笑不得的情况。
28 |
29 | - type: checkboxes
30 | attributes:
31 | label: 报告清单
32 | description: 请确认您已遵守所有必选项。
33 | options:
34 | - label: 我已仔细阅读并了解上述注意事项。
35 | required: true
36 | - label: 我已使用最新版本测试过,确认功能并未实现。
37 | required: true
38 | - label: 我确定在 [GitHub Issues](https://github.com/tkgs0/nonebot-plugin-blacklist/issues) 中没有相同或相似的需求。
39 | required: true
40 | - label: 我有足够的时间和能力,愿意为此提交 [PR](https://github.com/tkgs0/nonebot-plugin-blacklist/pulls) 来实现功能。
41 | required: false
42 |
43 | - type: textarea
44 | attributes:
45 | label: 您希望能解决什么样的问题?
46 | description: 请简要地说明是什么问题导致您想要一个新功能。也许我们可以提出一种现有的解决办法。
47 | validations:
48 | required: true
49 |
50 | - type: textarea
51 | attributes:
52 | label: 您想要的解决方案
53 | description: 请说明您希望使用什么样的方法解决上述问题。
54 | validations:
55 | required: true
56 |
57 | - type: textarea
58 | attributes:
59 | label: 您考虑过的替代方案
60 | description: 除了上述方法以外,您还考虑过哪些其他的实现方式?
61 | validations:
62 | required: false
63 |
64 | - type: textarea
65 | attributes:
66 | label: 实现的功能是什么样的?
67 | description: |
68 | 提供功能在实现后如何使用的代码示例。
69 | 请注意,您可以使用 Markdown 来设置代码块的格式。
70 | 尽可能多地提供细节。您希望它如何使用的示例代码会有所帮助。
71 | validations:
72 | required: false
73 |
74 | - type: textarea
75 | attributes:
76 | label: 额外补充
77 | description: 在此处添加相关的任何其他上下文或截图,或者您觉得有帮助的信息。
78 | validations:
79 | required: false
80 |
81 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base",
4 | "schedule:weekends"
5 | ],
6 | "dependencyDashboard": false,
7 | "rangeStrategy": "bump",
8 | "enabledManagers": [
9 | "github-actions",
10 | "poetry",
11 | "pre-commit"
12 | ],
13 | "pre-commit": {
14 | "enabled": true
15 | },
16 | "packageRules": [
17 | {
18 | "matchPackagePatterns": [
19 | "*"
20 | ],
21 | "matchUpdateTypes": [
22 | "minor",
23 | "patch"
24 | ],
25 | "groupName": "all non-major dependencies",
26 | "groupSlug": "all-minor-patch",
27 | "labels": [
28 | "dependencies"
29 | ],
30 | "automerge": true
31 | },
32 | {
33 | "matchPackagePatterns": [
34 | "*"
35 | ],
36 | "matchUpdateTypes": [
37 | "major"
38 | ],
39 | "labels": [
40 | "dependencies",
41 | "breaking"
42 | ]
43 | },
44 | {
45 | "description": "disable python updates for poetry manager",
46 | "matchPackageNames": ["python"],
47 | "matchManagers": ["poetry"],
48 | "enabled": false
49 | }
50 | ]
51 | }
52 |
--------------------------------------------------------------------------------
/.github/workflows/python-publish.yml:
--------------------------------------------------------------------------------
1 |
2 | name: Publish Python 🐍 distributions 📦 to PyPI
3 |
4 | on:
5 | push:
6 | tags:
7 | - '*'
8 |
9 | jobs:
10 | deploy:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v4
16 | - name: Set up Python
17 | uses: actions/setup-python@v5
18 | with:
19 | python-version: "3.x"
20 | - name: Install dependencies
21 | run: |
22 | python -m pip install --upgrade pip
23 | pip install build
24 | - name: Build package
25 | run: python -m build
26 | - name: Publish package
27 | uses: pypa/gh-action-pypi-publish@release/v1
28 | with:
29 | user: __token__
30 | password: ${{ secrets.PYPI_API_TOKEN }}
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 月ヶ瀬
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |

5 |
6 |
7 |
31 |
32 |
33 | ## 📖 介绍
34 |
35 | 基于 [A-kirami](https://github.com/A-kirami) 大佬的 [黑白名单](https://github.com/A-kirami/nonebot-plugin-namelist) 插件 魔改(?)的仅黑名单插件
36 |
37 | 超级用户不受黑名单影响
38 |
39 | ## 💿 安装
40 |
41 | **nb-cli安装, 包管理器安装 二选一**
42 |
43 |
44 | 使用 nb-cli 安装
45 |
46 | 在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
47 |
48 | nb plugin install nonebot-plugin-blacklist
49 |
50 |
51 |
52 |
53 | 使用包管理器安装
54 |
55 | 在 nonebot2 项目的插件目录下, 打开命令行,
56 |
57 | **根据你使用的包管理器, 输入相应的安装命令**
58 |
59 |
60 | pip
61 |
62 | pip install nonebot-plugin-blacklist
63 |
64 |
65 |
66 | pdm
67 |
68 | pdm add nonebot-plugin-blacklist
69 |
70 |
71 |
72 | poetry
73 |
74 | poetry add nonebot-plugin-blacklist
75 |
76 |
77 |
78 | conda
79 |
80 | conda install nonebot-plugin-blacklist
81 |
82 |
83 |
84 | 打开 bot项目下的 `pyproject.toml` 文件,
85 |
86 | 在其 `plugins` 里加入 `nonebot_plugin_blacklist`
87 |
88 | plugins = ["nonebot_plugin_blacklist"]
89 |
90 |
91 |
92 |
93 | ## 🎉 使用
94 |
95 | **总开关**
96 | ```
97 | 群聊静默/静默群聊
98 |
99 | 群聊响应/响应群聊
100 |
101 | 私聊静默/静默私聊
102 |
103 | 私聊响应/响应私聊
104 | ```
105 |
106 | **拉黑**
107 | ```
108 | 拉黑用户 qq qq1 qq2
109 | 拉黑群 qq qq1 qq2
110 | 拉黑私聊 qq qq1 qq2
111 | 拉黑所有群
112 | 拉黑所有好友
113 | ```
114 |
115 | **解禁**
116 | ```
117 | 解禁用户 qq qq1 qq2
118 | 解禁群 qq qq1 qq2
119 | 解禁私聊 qq qq1 qq2
120 | 解禁所有群
121 | 解禁所有好友
122 | ```
123 |
124 | **查看黑名单**
125 | ```
126 | 查看用户黑名单 bot
127 | 查看群聊黑名单 bot
128 | 查看私聊黑名单 bot
129 |
130 | 重置黑名单 bot bot1 bot2 ...
131 | 重置所有黑名单
132 |
133 | ## 不指定bot则为当前bot
134 | ```
135 |
136 | **被禁言自动屏蔽该群**
137 | ```
138 | 自觉静默开
139 | 自觉静默关
140 | ```
141 |
142 | 群内发送 `/静默` `/响应` 可快捷拉黑/解禁当前群聊
143 |
144 | `拉黑所有` 只对已添加的群/好友生效
145 |
146 | ## ⚠️ 注意事项
147 |
148 | **本插件目前仅支持 nonebot2 + onebot.v11 的使用方式, 一切非此二者结合的使用方式造成的问题请自行探索解决, 或者使用其他插件**
149 |
--------------------------------------------------------------------------------
/nonebot_plugin_blacklist/__init__.py:
--------------------------------------------------------------------------------
1 | import asyncio, random, unicodedata
2 | from pathlib import Path
3 | from typing import Literal
4 |
5 | from nonebot import get_driver, on_command, on_notice
6 | from nonebot.plugin import PluginMetadata
7 | from nonebot.log import logger
8 | from nonebot.matcher import Matcher
9 | from nonebot.adapters.onebot.v11 import (
10 | Bot,
11 | Message,
12 | Event,
13 | MessageEvent,
14 | GroupMessageEvent,
15 | GroupBanNoticeEvent,
16 | )
17 | from nonebot.exception import IgnoredException
18 | from nonebot.message import event_preprocessor
19 | from nonebot.permission import SUPERUSER
20 | from nonebot.params import CommandArg
21 |
22 | import ujson as json
23 |
24 |
25 | usage: str ="""
26 |
27 | 指令表:
28 | 静默(响应)私聊(群聊)
29 |
30 | 拉黑(解禁)用户(群/私聊) qq qq1 qq2 ...
31 | 拉黑(解禁)所有好友(群)
32 | 自觉静默开(关)
33 |
34 | 查看用户(群聊/私聊)黑名单 bot
35 | 重置黑名单 bot bot1 bot2 ...
36 | 重置所有黑名单
37 |
38 | # 不指定bot则为当前bot
39 |
40 | # 群内发送 "/静默" "/响应" 可快捷拉黑/解禁当前群聊
41 | # "拉黑所有" 只对已添加的群/好友生效
42 |
43 | """.strip()
44 |
45 |
46 | __plugin_meta__ = PluginMetadata(
47 | name="黑名单",
48 | description="黑名单插件",
49 | usage=usage,
50 | type="application",
51 | homepage="https://github.com/tkgs0/nonebot-plugin-blacklist",
52 | supported_adapters={"~onebot.v11"},
53 | extra={
54 | "author": "月ヶ瀬"
55 | }
56 | )
57 |
58 |
59 | superusers = get_driver().config.superusers
60 |
61 | file_path = Path() / 'data' / 'blacklist' / 'blacklist.json'
62 | file_path.parent.mkdir(parents=True, exist_ok=True)
63 |
64 | blacklist = (
65 | json.loads(file_path.read_text('utf-8'))
66 | if file_path.is_file()
67 | else {}
68 | )
69 |
70 | template = {
71 | 'private': False,
72 | 'group': True,
73 | 'privlist': [],
74 | 'grouplist': [],
75 | 'userlist': [],
76 | 'ban_auto_sleep': True
77 | }
78 |
79 |
80 | def save_blacklist() -> None:
81 | file_path.write_text(
82 | json.dumps(
83 | blacklist,
84 | ensure_ascii=False,
85 | escape_forward_slashes=False,
86 | indent=2
87 | ),
88 | encoding='utf-8'
89 | )
90 |
91 |
92 | def check_self_id(self_id) -> str:
93 | self_id = f'{self_id}'
94 | temp: dict = {}
95 | temp.update(template)
96 |
97 | try:
98 | if not blacklist.get(self_id):
99 | blacklist.update({
100 | self_id: temp
101 | })
102 | save_blacklist()
103 | for i in template:
104 | if blacklist[self_id].get(i) == None:
105 | blacklist[self_id].update({i: temp[i]})
106 | save_blacklist()
107 | except Exception:
108 | blacklist.update({
109 | self_id: temp
110 | })
111 | save_blacklist()
112 |
113 | return self_id
114 |
115 |
116 | def is_number(s: str) -> bool:
117 | try:
118 | float(s)
119 | return True
120 | except ValueError:
121 | pass
122 | try:
123 | unicodedata.numeric(s)
124 | return True
125 | except (TypeError, ValueError):
126 | pass
127 | return False
128 |
129 |
130 | @event_preprocessor
131 | def blacklist_processor(event: Event):
132 | self_id = check_self_id(event.self_id)
133 | uid = vars(event).get('user_id')
134 | gid = vars(event).get('group_id')
135 |
136 | if uid and f'{uid}' in superusers:
137 | return
138 |
139 | if gid and (not blacklist[self_id]['group'] or f'{gid}' in blacklist[self_id]['grouplist']):
140 | logger.debug(f'群聊 {gid} 在 {self_id} 黑名单中, 忽略本次消息')
141 | raise IgnoredException('黑名单群组')
142 |
143 | if uid and f'{uid}' in blacklist[self_id]['userlist']:
144 | logger.debug(f'用户 {uid} 在 {self_id} 黑名单中, 忽略本次消息')
145 | raise IgnoredException('黑名单用户')
146 |
147 | if not gid and uid:
148 | if not blacklist[self_id]['private'] or f'{uid}' in blacklist[self_id]['privlist']:
149 | logger.debug(f'私聊 {uid} 在 {self_id} 黑名单中, 忽略本次消息')
150 | raise IgnoredException('黑名单会话')
151 |
152 |
153 | def handle_msg(
154 | self_id,
155 | arg,
156 | mode: Literal['add', 'del'],
157 | type_: Literal['userlist', 'grouplist', 'privlist'],
158 | ) -> str:
159 | uids = arg.extract_plain_text().strip().split()
160 | if not uids:
161 | return '用法: \n拉黑(解禁)用户(群/私聊) qq qq1 qq2 ...'
162 | for uid in uids:
163 | if not is_number(uid):
164 | return '参数错误, id必须是数字..'
165 | msg = handle_blacklist(self_id, uids, mode, type_)
166 | return msg
167 |
168 |
169 | def handle_blacklist(
170 | self_id,
171 | uids: list,
172 | mode: Literal['add', 'del'],
173 | type_: Literal['userlist', 'grouplist', 'privlist'],
174 | ) -> str:
175 | self_id = check_self_id(self_id)
176 |
177 | types = {
178 | 'userlist': '用户',
179 | 'grouplist': '群聊',
180 | 'privlist': '私聊',
181 | }
182 |
183 | if mode == 'add':
184 | blacklist[self_id][type_].extend(uids)
185 | blacklist[self_id][type_] = list(set(blacklist[self_id][type_]))
186 | _mode = '拉黑'
187 | elif mode == 'del':
188 | blacklist[self_id][type_] = [uid for uid in blacklist[self_id][type_] if uid not in uids]
189 | _mode = '解禁'
190 | save_blacklist()
191 | _type = types[type_]
192 | return f"已{_mode} {len(uids)} 个{_type}: {', '.join(uids)}"
193 |
194 |
195 | add_userlist = on_command('拉黑用户', aliases={'屏蔽用户'}, permission=SUPERUSER, priority=1, block=True)
196 |
197 | @add_userlist.handle()
198 | async def add_user_list(event: MessageEvent, arg: Message = CommandArg()):
199 | if uids := [at.data['qq'] for at in event.get_message()['at']]:
200 | msg = handle_blacklist(event.self_id, uids, 'add', 'userlist')
201 | await add_userlist.finish(msg)
202 | msg = handle_msg(event.self_id, arg, 'add', 'userlist')
203 | await add_userlist.finish(msg)
204 |
205 |
206 | add_grouplist = on_command('拉黑群', aliases={'屏蔽群'}, permission=SUPERUSER, priority=1, block=True)
207 |
208 | @add_grouplist.handle()
209 | async def add_group_list(event: MessageEvent, arg: Message = CommandArg()):
210 | msg = handle_msg(event.self_id, arg, 'add', 'grouplist')
211 | await add_grouplist.finish(msg)
212 |
213 |
214 | add_privlist = on_command('拉黑私聊', aliases={'屏蔽私聊'}, permission=SUPERUSER, priority=1, block=True)
215 |
216 | @add_privlist.handle()
217 | async def add_priv_list(event: MessageEvent, arg: Message = CommandArg()):
218 | if uids := [at.data['qq'] for at in event.get_message()['at']]:
219 | msg = handle_blacklist(event.self_id, uids, 'add', 'privlist')
220 | await add_privlist.finish(msg)
221 | msg = handle_msg(event.self_id, arg, 'add', 'privlist')
222 | await add_privlist.finish(msg)
223 |
224 |
225 | del_userlist = on_command('解禁用户', aliases={'解封用户'}, permission=SUPERUSER, priority=1, block=True)
226 |
227 | @del_userlist.handle()
228 | async def del_user_list(event: MessageEvent, arg: Message = CommandArg()):
229 | if uids := [at.data['qq'] for at in event.get_message()['at']]:
230 | msg = handle_blacklist(event.self_id, uids, 'del', 'userlist')
231 | await del_userlist.finish(msg)
232 | msg = handle_msg(event.self_id, arg, 'del', 'userlist')
233 | await del_userlist.finish(msg)
234 |
235 |
236 | del_grouplist = on_command('解禁群', aliases={'解封群'}, permission=SUPERUSER, priority=1, block=True)
237 |
238 | @del_grouplist.handle()
239 | async def del_group_list(event: MessageEvent, arg: Message = CommandArg()):
240 | msg = handle_msg(event.self_id, arg, 'del', 'grouplist')
241 | await del_grouplist.finish(msg)
242 |
243 |
244 | del_privlist = on_command('解禁私聊', aliases={'解封私聊'}, permission=SUPERUSER, priority=1, block=True)
245 |
246 | @del_privlist.handle()
247 | async def del_priv_list(event: MessageEvent, arg: Message = CommandArg()):
248 | if uids := [at.data['qq'] for at in event.get_message()['at']]:
249 | msg = handle_blacklist(event.self_id, uids, 'del', 'privlist')
250 | await del_privlist.finish(msg)
251 | msg = handle_msg(event.self_id, arg, 'del', 'privlist')
252 | await del_privlist.finish(msg)
253 |
254 |
255 | check_userlist = on_command('查看用户黑名单', permission=SUPERUSER, priority=1, block=True)
256 |
257 | @check_userlist.handle()
258 | async def check_user_list(event: MessageEvent, args: Message = CommandArg()):
259 | arg = args.extract_plain_text().strip()
260 | self_id = check_self_id(arg) if is_number(arg) else check_self_id(event.self_id)
261 | uids = blacklist[self_id]['userlist']
262 | await check_userlist.finish(f"{self_id}\n当前已屏蔽 {len(uids)} 个用户: {', '.join(uids)}")
263 |
264 |
265 | check_grouplist = on_command('查看群聊黑名单', permission=SUPERUSER, priority=1, block=True)
266 |
267 | @check_grouplist.handle()
268 | async def check_group_list(event: MessageEvent, args: Message = CommandArg()):
269 | arg = args.extract_plain_text().strip()
270 | self_id = check_self_id(arg) if is_number(arg) else check_self_id(event.self_id)
271 | gids = blacklist[self_id]['grouplist']
272 | await check_grouplist.finish(f"{self_id}\n群聊状态: {'响应' if blacklist[self_id]['group'] else '静默'}\n自觉静默: {'开' if blacklist[self_id]['ban_auto_sleep'] else '关'}\n当前已屏蔽 {len(gids)} 个群聊: {', '.join(gids)}")
273 |
274 |
275 | check_privlist = on_command('查看私聊黑名单', permission=SUPERUSER, priority=1, block=True)
276 |
277 | @check_privlist.handle()
278 | async def check_priv_list(event: MessageEvent, args: Message = CommandArg()):
279 | arg = args.extract_plain_text().strip()
280 | self_id = check_self_id(arg) if is_number(arg) else check_self_id(event.self_id)
281 | uids = blacklist[self_id]['privlist']
282 | await check_privlist.finish(f"{self_id}\n私聊状态: {'响应' if blacklist[self_id]['private'] else '静默'}\n当前已屏蔽 {len(uids)} 个私聊: {', '.join(uids)}")
283 |
284 |
285 | enable_group = on_command('群聊响应', aliases={'响应群聊'}, permission=SUPERUSER, priority=1, block=True)
286 |
287 | @enable_group.handle()
288 | async def _(event: MessageEvent, args: Message = CommandArg()):
289 | arg = args.extract_plain_text().strip()
290 | self_id = check_self_id(arg) if is_number(arg) else check_self_id(event.self_id)
291 | blacklist[self_id]['group'] = True
292 | save_blacklist()
293 | await enable_group.finish(f'{self_id} 群聊响应.')
294 |
295 |
296 | disable_group = on_command('群聊静默', aliases={'静默群聊'}, permission=SUPERUSER, priority=1, block=True)
297 |
298 | @disable_group.handle()
299 | async def _(event: MessageEvent, args: Message = CommandArg()):
300 | arg = args.extract_plain_text().strip()
301 | self_id = check_self_id(arg) if is_number(arg) else check_self_id(event.self_id)
302 | blacklist[self_id]['group'] = False
303 | save_blacklist()
304 | await disable_group.finish(f'{self_id} 群聊静默.')
305 |
306 |
307 | enable_private = on_command('私聊响应', aliases={'响应私聊'}, permission=SUPERUSER, priority=1, block=True)
308 |
309 | @enable_private.handle()
310 | async def _(event: MessageEvent, args: Message = CommandArg()):
311 | arg = args.extract_plain_text().strip()
312 | self_id = check_self_id(arg) if is_number(arg) else check_self_id(event.self_id)
313 | blacklist[self_id]['private'] = True
314 | save_blacklist()
315 | await enable_private.finish(f'{self_id} 私聊响应.')
316 |
317 |
318 | disable_private = on_command('私聊静默', aliases={'静默私聊'}, permission=SUPERUSER, priority=1, block=True)
319 |
320 | @disable_private.handle()
321 | async def _(event: MessageEvent, args: Message = CommandArg()):
322 | arg = args.extract_plain_text().strip()
323 | self_id = check_self_id(arg) if is_number(arg) else check_self_id(event.self_id)
324 | blacklist[self_id]['private'] = False
325 | save_blacklist()
326 | await disable_private.finish(f'{self_id} 私聊静默.')
327 |
328 |
329 | add_group = on_command('/静默', permission=SUPERUSER, priority=1, block=True)
330 |
331 | @add_group.handle()
332 | async def add_group_(event: GroupMessageEvent):
333 | handle_blacklist(event.self_id, [f'{event.group_id}'], 'add', 'grouplist')
334 | await add_group.finish('那我先去睡觉了...')
335 |
336 |
337 | del_group = on_command('/响应', permission=SUPERUSER, priority=1, block=True)
338 |
339 | @del_group.handle()
340 | async def del_group_(event: GroupMessageEvent):
341 | handle_blacklist(event.self_id, [f'{event.group_id}'], 'del', 'grouplist')
342 | await del_group.finish('呜......醒来力...')
343 |
344 |
345 | add_all_group = on_command('拉黑所有群', aliases={'屏蔽所有群'}, permission=SUPERUSER, priority=1, block=True)
346 |
347 | @add_all_group.handle()
348 | async def add_all_group_(bot: Bot, event: MessageEvent):
349 | gl = await bot.get_group_list()
350 | gids = ['{group_id}'.format_map(g) for g in gl]
351 | handle_blacklist(event.self_id, gids, 'add', 'grouplist')
352 | await add_all_group.finish(f'已拉黑 {len(gids)} 个群聊')
353 |
354 |
355 | del_all_group = on_command('解禁所有群', aliases={'解封所有群'}, permission=SUPERUSER, priority=1, block=True)
356 |
357 | @del_all_group.handle()
358 | async def del_all_group_(event: MessageEvent):
359 | self_id = check_self_id(event.self_id)
360 | n = len(blacklist[self_id]['grouplist'])
361 | blacklist[self_id]['grouplist'].clear()
362 | save_blacklist()
363 | await del_all_group.finish(f'已解禁 {n} 个群聊')
364 |
365 |
366 | add_all_friend = on_command('拉黑所有好友', aliases={'屏蔽所有好友'}, permission=SUPERUSER, priority=1, block=True)
367 |
368 | @add_all_friend.handle()
369 | async def add_all_friend_(bot: Bot, event: MessageEvent):
370 | gl = await bot.get_friend_list()
371 | uids = ['{user_id}'.format_map(g) for g in gl]
372 | handle_blacklist(event.self_id, uids, 'add', 'userlist')
373 | await add_all_friend.finish(f'已拉黑 {len(uids)} 个用户')
374 |
375 |
376 | del_all_friend = on_command('解禁所有好友', aliases={'解封所有好友'}, permission=SUPERUSER, priority=1, block=True)
377 |
378 | @del_all_friend.handle()
379 | async def del_all_friend_(event: MessageEvent):
380 | self_id = check_self_id(event.self_id)
381 | n = len(blacklist[self_id]['userlist'])
382 | blacklist[self_id]['userlist'].clear()
383 | save_blacklist()
384 | await del_all_friend.finish(f'已解禁 {n} 个用户')
385 |
386 |
387 | reset_all_blacklist = on_command('重置所有黑名单', aliases={'清空所有黑名单'}, permission=SUPERUSER, priority=1, block=True)
388 |
389 | @reset_all_blacklist.got('FLAG', prompt='确定重置所有黑名单? (y/n)')
390 | async def reset_all_list(matcher: Matcher):
391 | flag = matcher.state['FLAG'].extract_plain_text().strip()
392 | if flag.lower() in ['y', 'yes', 'true']:
393 | blacklist.clear()
394 | save_blacklist()
395 | await reset_all_blacklist.finish('已重置所有黑名单')
396 | else:
397 | await reset_all_blacklist.finish('操作已取消')
398 |
399 |
400 | reset_blacklist = on_command('重置黑名单', aliases={'清空黑名单'}, permission=SUPERUSER, priority=1, block=True)
401 |
402 | @reset_blacklist.handle()
403 | async def _(matcher: Matcher, args: Message = CommandArg()):
404 | matcher.state["ARGS"] = args.extract_plain_text().strip()
405 |
406 | @reset_blacklist.got('FLAG', prompt='确定重置黑名单? (y/n)')
407 | async def reset_list(event: MessageEvent, matcher: Matcher):
408 | args = matcher.state['ARGS']
409 | flag = matcher.state['FLAG'].extract_plain_text().strip()
410 |
411 | uids = args.strip().split()
412 | uids = [check_self_id(i) for i in uids if is_number(i)] or [check_self_id(event.self_id)]
413 |
414 | if flag.lower() in ['y', 'yes', 'true']:
415 | for i in uids:
416 | blacklist.pop(i)
417 | save_blacklist()
418 | await reset_blacklist.finish(f'已重置{len(uids)}个黑名单')
419 | else:
420 | await reset_blacklist.finish('操作已取消')
421 |
422 |
423 | @on_notice(priority=2, block=False).handle()
424 | async def _(bot: Bot, event: GroupBanNoticeEvent):
425 | self_id = check_self_id(event.self_id)
426 |
427 | if event.is_tome() and event.duration:
428 | msg = f"在群聊 {event.group_id} 受到 {event.operator_id} 禁言"
429 | logger.info(f'{self_id} {msg}')
430 | if blacklist[self_id]['ban_auto_sleep']:
431 | handle_blacklist(self_id, [f'{event.group_id}'], 'add', 'grouplist')
432 | for superuser in bot.config.superusers:
433 | await bot.send_private_msg(
434 | user_id=int(superuser),
435 | message=f'ⓘ{msg}, 已自动拉黑该群聊.'
436 | )
437 | await asyncio.sleep(random.random()+1)
438 |
439 |
440 | ban_auto_sleep = on_command('自觉静默', permission=SUPERUSER, priority=1, block=True)
441 |
442 | @ban_auto_sleep.handle()
443 | async def _(event: MessageEvent, arg: Message = CommandArg()):
444 | self_id = check_self_id(event.self_id)
445 | msg = arg.extract_plain_text().strip()
446 |
447 | if not msg or msg.startswith('开'):
448 | blacklist[self_id]['ban_auto_sleep'] = True
449 | text = '自觉静默已开启.'
450 | elif msg.startswith('关'):
451 | blacklist[self_id]['ban_auto_sleep'] = False
452 | text = '自觉静默已关闭.'
453 | else:
454 | return
455 | save_blacklist()
456 | await ban_auto_sleep.finish(text)
457 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "nonebot-plugin-blacklist"
3 | version = "1.4.3"
4 | description = "Blacklist in NoneBot2"
5 | authors = ["月ヶ瀬"]
6 | license = "MIT"
7 | readme = "README.md"
8 | packages = [
9 | { include = "nonebot_plugin_blacklist" },
10 | ]
11 | homepage = "https://github.com/tkgs0/nonebot-plugin-blacklist"
12 | repository = "https://github.com/tkgs0/nonebot-plugin-blacklist"
13 | keywords = ["nonebot", "blacklist"]
14 |
15 | [tool.poetry.dependencies]
16 | python = "^3.9"
17 | nonebot2 = "^2.3.1"
18 | nonebot-adapter-onebot = "^2.4.1"
19 | ujson = ">=5.2.0"
20 |
21 | [tool.poetry.dev-dependencies]
22 |
23 | [tool.mypy]
24 | python_version = "3.9"
25 | ignore_missing_imports = true
26 | implicit_reexport = true
27 | pretty = true
28 | show_error_codes = true
29 | strict = true
30 |
31 | [build-system]
32 | requires = ["poetry-core>=1.0.0"]
33 | build-backend = "poetry.core.masonry.api"
34 |
35 |
--------------------------------------------------------------------------------