From b409111e7c5f1078cfdc6be54fe7ae8f850c775d Mon Sep 17 00:00:00 2001 From: aoyangli Date: Tue, 19 Dec 2023 17:06:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E7=BE=A4/C2C?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E4=BA=8B=E4=BB=B6demo,=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E8=BF=87=E6=97=B6demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- botpy/api.py | 13 +++- botpy/client.py | 2 +- examples/README.md | 2 + examples/demo_announce.py | 3 +- examples/demo_at_reply_command.py | 3 +- examples/demo_at_reply_keyboard_buttons.py | 74 ------------------- examples/demo_c2c_manage_event.py | 42 +++++++++++ examples/demo_dms_reply.py | 10 ++- examples/demo_group_manage_event.py | 42 +++++++++++ .../demo_handle_direct_msg_delete_event.py | 31 -------- 10 files changed, 110 insertions(+), 112 deletions(-) delete mode 100644 examples/demo_at_reply_keyboard_buttons.py create mode 100644 examples/demo_c2c_manage_event.py create mode 100644 examples/demo_group_manage_event.py delete mode 100644 examples/demo_handle_direct_msg_delete_event.py diff --git a/botpy/api.py b/botpy/api.py index cfd158e..5976af0 100644 --- a/botpy/api.py +++ b/botpy/api.py @@ -342,6 +342,10 @@ async def create_channel( Kwargs(fields): position (int): 排序,非必填 parent_id (str): 否,分组 ID + private_type (int): 子频道私密类型 PrivateType + private_user_ids (List[str]): 子频道私密类型成员 ID + speak_permission (int): 子频道发言权限 SpeakPermission + application_id (str): 应用类型子频道 AppID,仅应用子频道需要该字段 Returns: 通道对象。 @@ -351,7 +355,14 @@ async def create_channel( "type": int(type), "subtype": int(sub_type), } - valid_keys = ("position", "parent_id") + valid_keys = ( + "position", + "parent_id", + "private_type", + "private_user_ids", + "speak_permission", + "application_id", + ) payload.update({k: v for k, v in fields.items() if k in valid_keys and v}) route = Route("POST", "/guilds/{guild_id}/channels", guild_id=guild_id) return await self._http.request(route, json=payload) diff --git a/botpy/client.py b/botpy/client.py index 71dfcab..822691f 100644 --- a/botpy/client.py +++ b/botpy/client.py @@ -258,7 +258,7 @@ def ws_dispatch(self, event: str, *args: Any, **kwargs: Any) -> None: try: coro = getattr(self, method) except AttributeError: - _log.warning("[botpy] 事件: %s 未注册", event) + _log.debug("[botpy] 事件: %s 未注册", event) else: self._schedule_event(coro, method, *args, **kwargs) diff --git a/examples/README.md b/examples/README.md index 2b4a337..8c2beca 100644 --- a/examples/README.md +++ b/examples/README.md @@ -26,8 +26,10 @@ examples/ ├── demo_schedule.py # 机器人日程相关示例 ├── demo_group_reply_text.py # 机器人群内发消息相关示例 ├── demo_group_reply_file.py # 机器人群内发富媒体消息相关示例 +├── demo_group_manage_event.py # 机器人群管理事件 ├── demo_c2c_reply_text.py # 机器人好友内发消息相关示例 ├── demo_c2c_reply_file.py # 机器人好友内发富媒体消息相关示例 +├── demo_c2c_manage_event.py # 机器人好友管理事件 ├── demo_audio_or_live_channel_member.py # 音视频/直播子频道成员进出事件 ├── demo_open_forum_event.py # 开放论坛事件对象 ``` diff --git a/examples/demo_announce.py b/examples/demo_announce.py index e5b25b7..6bc9783 100644 --- a/examples/demo_announce.py +++ b/examples/demo_announce.py @@ -21,7 +21,8 @@ async def on_at_message_create(self, message: Message): await self.api.post_message(message.channel_id, content="command received: %s" % message.content) # 输入/xxx后的处理 - message_id = "088de19cbeb883e7e97110a2e39c0138d401" + # 对用户引用回复的消息设置/删除公告 + message_id = message.message_reference.message_id if "/建公告" in message.content: await self.api.create_announce(message.guild_id, message.channel_id, message_id) diff --git a/examples/demo_at_reply_command.py b/examples/demo_at_reply_command.py index 1471afe..23eef17 100644 --- a/examples/demo_at_reply_command.py +++ b/examples/demo_at_reply_command.py @@ -13,7 +13,7 @@ _log = logging.get_logger() -@Commands(name=("你好", "hello")) +@Commands("你好", "hello") async def hello(api: BotAPI, message: Message, params=None): _log.info(params) # 第一种用reply发送消息 @@ -45,7 +45,6 @@ async def on_at_message_create(self, message: Message): return - if __name__ == "__main__": # 通过预设置的类型,设置需要监听的事件通道 # intents = botpy.Intents.none() diff --git a/examples/demo_at_reply_keyboard_buttons.py b/examples/demo_at_reply_keyboard_buttons.py deleted file mode 100644 index 1fef2c3..0000000 --- a/examples/demo_at_reply_keyboard_buttons.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import asyncio -import os.path - -import qqbot -from qqbot.core.util.yaml_util import YamlUtil -from qqbot.model.inline_keyboard import RenderData, Action, Permission, Button, InlineKeyboardRow, InlineKeyboard -from qqbot.model.message import MessageMarkdown, MessageKeyboard -from qqbot.model.ws_context import WsContext - -test_config = YamlUtil.read(os.path.join(os.path.dirname(__file__), "config.yaml")) - - -async def _message_handler(context: WsContext, message: qqbot.Message): - """ - 发送带消息按钮的 markdown 消息。(消息按钮只能和 markdown 一起使用) - - :param context: WsContext 对象,包含 event_type 和 event_id - :param message: 事件对象(如监听消息是Message对象) - """ - await send_template_keyboard(message.channel_id, message.id) - await send_self_defined_keyboard(message.channel_id, message.id) - - -async def send_template_keyboard(channel_id, msg_id): - msg_api = qqbot.AsyncMessageAPI(t_token, False) - - markdown = MessageMarkdown(content="# 123 \n 今天是个好天气") - keyword: MessageKeyboard = MessageKeyboard(id='62') - send = qqbot.MessageSendRequest(markdown=markdown, msg_id=msg_id, keyboard=keyword) - # 通过api发送回复消息 - await msg_api.post_message(channel_id, send) - - -async def send_self_defined_keyboard(channel_id, msg_id): - msg_api = qqbot.AsyncMessageAPI(t_token, False) - - markdown = MessageMarkdown(content="# 标题 \n## 简介 \n内容") - keyboard: MessageKeyboard = build_a_demo_keyboard() - send = qqbot.MessageSendRequest(markdown=markdown, msg_id=msg_id, keyboard=keyboard) - # 通过api发送回复消息 - await msg_api.post_message(channel_id, send) - - -def build_a_demo_keyboard() -> MessageKeyboard: - """ - 创建一个只有一行且该行只有一个 button 的键盘 - """ - button1 = Button( - '1', - RenderData( - "button", - "BUTTON", - 0 - ), - Action( - 2, - Permission(2, specify_role_ids=["1"]), - 10, - "/搜索", - True - ) - ) - row1 = InlineKeyboardRow([button1]) - inline_keyboard = InlineKeyboard([row1]) - return MessageKeyboard(content=inline_keyboard) - - -if __name__ == "__main__": - # async的异步接口的使用示例 - t_token = qqbot.Token(test_config["appid"], test_config["secret"]) - qqbot_handler = qqbot.Handler(qqbot.HandlerType.AT_MESSAGE_EVENT_HANDLER, _message_handler) - qqbot.async_listen_events(t_token, False, qqbot_handler) diff --git a/examples/demo_c2c_manage_event.py b/examples/demo_c2c_manage_event.py new file mode 100644 index 0000000..94f220c --- /dev/null +++ b/examples/demo_c2c_manage_event.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +import os + +import botpy +from botpy import logging +from botpy.ext.cog_yaml import read +from botpy.manage import C2CManageEvent + +test_config = read(os.path.join(os.path.dirname(__file__), "config.yaml")) + +_log = logging.get_logger() + + +class MyClient(botpy.Client): + async def on_friend_add(self, event: C2CManageEvent): + _log.info("用户添加机器人:" + str(event)) + await self.api.post_c2c_message( + openid=event.openid, + msg_type=0, + event_id=event.event_id, + content="hello", + ) + + async def on_friend_del(self, event: C2CManageEvent): + _log.info("用户删除机器人:" + str(event)) + + async def on_c2c_msg_reject(self, event: C2CManageEvent): + _log.info("用户关闭机器人主动消息:" + str(event)) + + async def on_c2c_msg_receive(self, event: C2CManageEvent): + _log.info("用户打开机器人主动消息:" + str(event)) + + +if __name__ == "__main__": + # 通过预设置的类型,设置需要监听的事件通道 + # intents = botpy.Intents.none() + # intents.public_messages=True + + # 通过kwargs,设置需要监听的事件通道 + intents = botpy.Intents(public_messages=True) + client = MyClient(intents=intents) + client.run(appid=test_config["appid"], secret=test_config["secret"]) diff --git a/examples/demo_dms_reply.py b/examples/demo_dms_reply.py index 41c6c88..d33c986 100644 --- a/examples/demo_dms_reply.py +++ b/examples/demo_dms_reply.py @@ -4,7 +4,7 @@ import botpy from botpy import logging -from botpy.message import DirectMessage +from botpy.message import DirectMessage, Message from botpy.ext.cog_yaml import read test_config = read(os.path.join(os.path.dirname(__file__), "config.yaml")) @@ -23,6 +23,12 @@ async def on_direct_message_create(self, message: DirectMessage): msg_id=message.id, ) + async def on_at_message_create(self, message: Message): + if "/私信" in message.content: + dms_payload = await self.api.create_dms(message.guild_id, message.author.id) + _log.info("发送私信") + await self.api.post_dms(dms_payload["guild_id"], content="hello", msg_id=message.id) + if __name__ == "__main__": # 通过预设置的类型,设置需要监听的事件通道 @@ -30,6 +36,6 @@ async def on_direct_message_create(self, message: DirectMessage): # intents.public_guild_messages=True # 通过kwargs,设置需要监听的事件通道 - intents = botpy.Intents(direct_message=True) + intents = botpy.Intents(direct_message=True, public_guild_messages=True) client = MyClient(intents=intents) client.run(appid=test_config["appid"], secret=test_config["secret"]) diff --git a/examples/demo_group_manage_event.py b/examples/demo_group_manage_event.py new file mode 100644 index 0000000..d257eb4 --- /dev/null +++ b/examples/demo_group_manage_event.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +import os + +import botpy +from botpy import logging +from botpy.ext.cog_yaml import read +from botpy.manage import GroupManageEvent + +test_config = read(os.path.join(os.path.dirname(__file__), "config.yaml")) + +_log = logging.get_logger() + + +class MyClient(botpy.Client): + async def on_group_add_robot(self, event: GroupManageEvent): + _log.info("机器人被添加到群聊:" + str(event)) + await self.api.post_group_message( + group_openid=event.group_openid, + msg_type=0, + event_id=event.event_id, + content="hello", + ) + + async def on_group_del_robot(self, event: GroupManageEvent): + _log.info("机器人被移除群聊:" + str(event)) + + async def on_group_msg_reject(self, event: GroupManageEvent): + _log.info("群聊关闭机器人主动消息:" + str(event)) + + async def on_group_msg_receive(self, event: GroupManageEvent): + _log.info("群聊打开机器人主动消息:" + str(event)) + + +if __name__ == "__main__": + # 通过预设置的类型,设置需要监听的事件通道 + # intents = botpy.Intents.none() + # intents.public_messages=True + + # 通过kwargs,设置需要监听的事件通道 + intents = botpy.Intents(public_messages=True) + client = MyClient(intents=intents) + client.run(appid=test_config["appid"], secret=test_config["secret"]) diff --git a/examples/demo_handle_direct_msg_delete_event.py b/examples/demo_handle_direct_msg_delete_event.py deleted file mode 100644 index 50f4077..0000000 --- a/examples/demo_handle_direct_msg_delete_event.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import os.path - -import qqbot -from qqbot.core.util.yaml_util import YamlUtil -from qqbot.model.ws_context import WsContext - -test_config = YamlUtil.read(os.path.join(os.path.dirname(__file__), "config.yaml")) - - -async def _direct_message_handler(context: WsContext, deletion_info: qqbot.DeletedMessageInfo): - """ - 定义事件回调的处理 - - :param context: WsContext 对象,包含 event_type 和 event_id - :param deletion_info: 事件对象(如监听消息是Message对象) - """ - msg_api = qqbot.AsyncDmsAPI(t_token, False) - # 打印返回信息 - qqbot.logger.info("event_type %s" % context.event_type + ",deleted message %s" % deletion_info.message.id) - # 构造消息发送请求数据对象 - send = qqbot.MessageSendRequest("监听到了私信消息删除:%s" % deletion_info.message.id) - # 通过api发送回复消息 - await msg_api.post_direct_message(deletion_info.message.guild_id, send) - - -if __name__ == "__main__": - t_token = qqbot.Token(test_config["appid"], test_config["secret"]) - qqbot_handler = qqbot.Handler(qqbot.HandlerType.DIRECT_MESSAGE_DELETE_EVENT_HANDLER, _direct_message_handler) - qqbot.async_listen_events(t_token, False, qqbot_handler)