Skip to content

Latest commit

 

History

History
185 lines (151 loc) · 5.81 KB

New Text Document 5.md

File metadata and controls

185 lines (151 loc) · 5.81 KB

使用 NoneBot 和 go-cqhttp 搭建 QQ 群聊机器人

处理请求

NoneBot 也提供了 on_requeston_notice 装饰器。当机器人收到请求的时候便会调用相应的处理器,例如下面的例子。

创建 luciabot/lucia/bot_plugins/request_handler.py

from nonebot import get_bot, on_request
from nonebot.helpers import send_to_superusers
from nonebot.notice_request import RequestSession


__plugin_name__ = '处理请求 [Hidden]'


@on_request('friend', 'group.invite')
async def _(session: RequestSession):
    bot = session.bot
    event = session.event
    if event.detail_type == 'friend':
        msg = f'用户 {event.user_id} 请求添加好友。消息:{event.comment}'
    else:  # == 'group'
        msg = f'用户 {event.user_id} 邀请加入群 {event.group_id}。消息:{event.comment}'

    # 如果邀请者是超级用户,那么就自动同意请求
    if event.user_id in bot.config.SUPERUSERS:
        await session.approve()
        msg += '(已自动接受)'

    # 给超级用户发送这条消息
    await send_to_superusers(bot, msg)
    # TODO: 使用 broadcast() 广播这条消息到监控面板

这个处理器会处理好友请求和邀请机器人加群的请求。OneBot 中规定了相关的请求种类。

当机器人收到请求的时候,调用辅助函数 send_to_superusersmsg 私聊给所有的超级用户。例子:

lucia:
  用户 123456789 请求添加好友。消息:一些验证消息(已自动接受)

为机器人编写说明书

最后,我们的机器人既然已经有了 4 个功能,那么组织一份“帮助”命令显得很重要。

得利于我们为每个插件都之前定义过 __plugin_name____plugin_usage__ 常量,我们可以利用它们来生成一份帮助信息。来看下面的例子:

luciabot/lucia/bot_plugins/usage.py

from nonebot.command import CommandSession
from nonebot.plugin import on_command, get_loaded_plugins

from services.command_use_count import record_successful_invocation


__plugin_name__ = '帮助'
__plugin_usage__ = (
    '用法:\n'
    '对我说 “帮助” 获取我支持的功能\n'
    '“帮助 功能名” 获取对应详细帮助'
)


help_permission = lambda sender: (not sender.is_privatechat) or sender.is_superuser


@on_command('help', aliases={'帮助'}, permission=help_permission)
@record_successful_invocation('help')
async def _(session: CommandSession):
    # 获取加载的插件,注意名字以 [Hidden] 结尾的不应该被展示!
    plugins = (p for p in get_loaded_plugins() if p.name and not p.name.endswith('[Hidden]'))

    arg = session.current_arg_text.strip()
    # 没有参数:展示功能列表
    if not arg:
        await session.send(
            '我的功能有:\n  ' + '\n  '.join(p.name for p in plugins) +
            '\n对我说 “帮助 功能名” 获取对应详细帮助'
        )
    # 有参数:展示对应 usage
    else:
        for p in plugins:
            if arg.lower() in p.name.lower():
                await session.send(p.usage)

本例中为了方便返回了一份非常 generic 的帮助信息。用户也可以根据自己的需求从 get_loaded_plugins api 中筛选想要的插件。

我们来尝试调用一下这个功能:

群主:
  莉西亚,帮助
lucia:
  我的功能有:
    ping
    grouptty
    帮助
    天气
    签到
  对我说 “帮助 功能名” 获取对应详细帮助
群主:
  莉西亚,帮助 帮助
lucia:
  用法:
  对我说 "帮助" 获取我支持的功能
  “帮助 功能名” 获取对应详细帮助
群主:
  莉西亚,帮助 ping
lucia:
  用法: 对我说 "ping",我会回复 "pong!"
群主:
  莉西亚,ping
lucia:
  pong!

好吧,现在是 5 个功能。

下一步

我们的机器人已经近乎完备,这里对 NoneBot 的介绍也差不多要结束了。从此以后,我们就可以像搭积木一样向这个框架添加功能。

这个机器人的提升空间有:

  • 我们要补充 service 中的异常处理
  • 提取一些公共函数,比如 ensure
  • 分离生产和开发用的环境
  • 提供更完善的面板,比如展示好友请求
  • 等等...
  • 更多的功能!

此教程对 NoneBot api 的介绍不是 100% 全面,仍有很多没有被提及的地方。读者可以查看官方文档来取得更多的样例融入到自己的项目中。

不要忘了 NoneBot 支持主动调用 gocqhttp 的 api!例如

bot = get_bot()
await bot.set_group_kick(group_id=87654321, user_id=9876543210)

可以将用户踢出群聊。


这是最终 lucia 的目录结构:

lucia
├── Dockerfile
├── bot.py
├── bot_config.py
├── bot_plugins/
│   ├── group_user_checkin.py
│   ├── grouptty.py
│   ├── inmsg_count.py
│   ├── ping.py
│   ├── request_handler.py
│   ├── usage.py
│   └── weather.py
├── controllers.py
├── models/
│   ├── command_use.py
│   └── group_user.py
├── requirements.txt
├── resources/
│   ├── SourceHanSans-Regular.otf
│   ├── dashboard.html
│   └── group_user_check_bg.png
├── service_config.py
└── services/
    ├── broadcast.py
    ├── command_use_count.py
    ├── common.py
    ├── db_context.py
    ├── group_user_checkin.py
    ├── inmsg_count.py
    ├── log.py
    ├── processpool.py
    └── weather.py

Cheers!

img