✨ 添加用户消息撤回命令 (#1719)
@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
### 1. 体验一下?
|
### 1. 体验一下?
|
||||||
|
|
||||||
这是一个免费的,版本为 dev 的 zhenxun,你可以通过 napcat 或拉格朗日等直接连接用于体验与测试
|
这是一个免费的,版本为 dev 的 zhenxun,你可以通过 [napcat](https://github.com/NapNeko/NapCatQQ) 或 [拉格朗日](https://github.com/LagrangeDev/Lagrange.Core) 以及 [matcha](https://github.com/A-kirami/matcha) 等直接连接用于体验与测试
|
||||||
(球球了测试君!)
|
(球球了测试君!)
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -95,6 +95,7 @@ AccessToken: PUBLIC_ZHENXUN_TEST
|
|||||||
<details>
|
<details>
|
||||||
<summary> <strong> WebUI </strong>后台示例图 </summary>
|
<summary> <strong> WebUI </strong>后台示例图 </summary>
|
||||||
|
|
||||||
|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
@ -319,7 +320,7 @@ python bot.py
|
|||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>爱发电 以及 感谢投喂 </summary>
|
<summary>爱发电 以及 感谢投喂 </summary>
|
||||||
<img width="365px" height="450px" src="https://user-images.githubusercontent.com/45528451/175059389-cfeb8174-fa07-4939-80ab-a039087a50f6.png">
|
<img width="365px" height="450px" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/afd.jpg">
|
||||||
|
|
||||||
### 感谢名单
|
### 感谢名单
|
||||||
|
|
||||||
@ -369,6 +370,7 @@ python bot.py
|
|||||||
[哇](https://afdian.net/u/9b266244f23911eca19052540025c377)
|
[哇](https://afdian.net/u/9b266244f23911eca19052540025c377)
|
||||||
[yajiwa](https://github.com/yajiwa)
|
[yajiwa](https://github.com/yajiwa)
|
||||||
[爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377)
|
[爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377)
|
||||||
|
...
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
BIN
docs_image/afd.jpg
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
docs_image/webui0.png
Normal file
|
After Width: | Height: | Size: 315 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 171 KiB After Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 193 KiB |
23
zhenxun/builtin_plugins/hooks/call_hook.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from nonebot.adapters import Bot
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.utils.manager.message_manager import MessageManager
|
||||||
|
|
||||||
|
|
||||||
|
@Bot.on_called_api
|
||||||
|
async def handle_api_result(
|
||||||
|
bot: Bot, exception: Exception | None, api: str, data: dict[str, Any], result: Any
|
||||||
|
):
|
||||||
|
if not exception and api == "send_msg":
|
||||||
|
try:
|
||||||
|
if (uid := data.get("user_id")) and (msg_id := result.get("message_id")):
|
||||||
|
MessageManager.add(str(uid), str(msg_id))
|
||||||
|
logger.debug(
|
||||||
|
f"收集消息id,user_id: {uid}, msg_id: {msg_id}", "msg_hook"
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(
|
||||||
|
f"收集消息id发生错误...data: {data}, result: {result}", "msg_hook", e=e
|
||||||
|
)
|
||||||
61
zhenxun/builtin_plugins/withdraw.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
from nonebot.rule import Rule
|
||||||
|
from nonebot.adapters import Bot, Event
|
||||||
|
from nonebot_plugin_uninfo import Uninfo
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
from nonebot_plugin_alconna.uniseg.tools import reply_fetch
|
||||||
|
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.utils.message import MessageUtils
|
||||||
|
from zhenxun.utils.platform import PlatformUtils
|
||||||
|
from zhenxun.configs.utils import PluginExtraData
|
||||||
|
from zhenxun.utils.manager.message_manager import MessageManager
|
||||||
|
|
||||||
|
__plugin_meta__ = PluginMetadata(
|
||||||
|
name="消息撤回",
|
||||||
|
description="撤回自己触发的消息撤回,不允许撤回其他人触发消息的撤回哦",
|
||||||
|
usage="""
|
||||||
|
引用消息 撤回
|
||||||
|
""".strip(),
|
||||||
|
extra=PluginExtraData(author="HibiKier", version="0.1", menu_type="其他").dict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def reply_check() -> Rule:
|
||||||
|
"""
|
||||||
|
检查是否存在回复消息
|
||||||
|
|
||||||
|
返回:
|
||||||
|
Rule: Rule
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def _rule(bot: Bot, event: Event, session: Uninfo):
|
||||||
|
if event.get_type() == "message":
|
||||||
|
return (
|
||||||
|
bool(await reply_fetch(event, bot))
|
||||||
|
and PlatformUtils.get_platform(session) == "qq"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return Rule(_rule)
|
||||||
|
|
||||||
|
|
||||||
|
_matcher = on_alconna(Alconna("撤回"), priority=5, block=True, rule=reply_check())
|
||||||
|
|
||||||
|
|
||||||
|
@_matcher.handle()
|
||||||
|
async def _(bot: Bot, event: Event, session: Uninfo, arparma: Arparma):
|
||||||
|
if reply := await reply_fetch(event, bot):
|
||||||
|
if (
|
||||||
|
MessageManager.check(session.user.id, reply.id)
|
||||||
|
or session.user.id in bot.config.superusers
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
await bot.delete_msg(message_id=reply.id)
|
||||||
|
logger.info("撤回消息", arparma.header_result, session=session)
|
||||||
|
except Exception:
|
||||||
|
await MessageUtils.build_message("撤回失败,可能消息已过期...").send()
|
||||||
|
else:
|
||||||
|
await MessageUtils.build_message(
|
||||||
|
"权限不足,不是你触发的消息不要胡乱撤回哦..."
|
||||||
|
).send()
|
||||||
27
zhenxun/utils/manager/message_manager.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
|
|
||||||
|
class MessageManager:
|
||||||
|
data: ClassVar[dict[str, list[str]]] = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add(cls, uid: str, msg_id: str):
|
||||||
|
if uid not in cls.data:
|
||||||
|
cls.data[uid] = []
|
||||||
|
cls.data[uid].append(msg_id)
|
||||||
|
cls.remove_check(uid)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def check(cls, uid: str, msg_id: str) -> bool:
|
||||||
|
return msg_id in cls.data.get(uid, [])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def remove_check(cls, uid: str):
|
||||||
|
if len(cls.data[uid]) > 200:
|
||||||
|
cls.data[uid] = cls.data[uid][100:]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, uid: str) -> list[str]:
|
||||||
|
if uid in cls.data:
|
||||||
|
return cls.data[uid]
|
||||||
|
return []
|
||||||