banner
NEWS LETTER

基于NapCat+Nonebot2的QQ+Discord Bot 搭建

Scroll down

参考: https://catarium.me/posts/20251031

部署前准备

确保Python版本>=3.9(如果要使用GsCore,则推荐>=3.12,但不建议3.13)

QQ协议端——NapCat (需要QQNT客户端)

Windows:

NapCat下载:Releases · NapNeko/NapCatQQ

下载NapCat.Shell.zip

启动: 目录下launcher.bat QQ号

在雨云等Linux云服务器上部署NapCat (Docker,无需QQNT客户端)

使用如下Docker命令进行部署:

1
2
3
4
5
6
7
8
9
10
11
docker run -d \
-e NAPCAT_GID=$(id -g) \
-e NAPCAT_UID=$(id -u) \
-v /root/expbot/expbot:/root/expbot/expbot \ #挂在服务器的/root/expbot/expbot目录到容器的/root/expbot/expbot目录 (前为服务器目录,后为容器目录)
--network=host \ #指定网络为使用服务器网络,即让容器和宿主服务器为同一ip
--name napcat \
--restart=always \
mlikiowa/napcat-docker:latest


# 不挂载会导致图片发送错误:找不到文件

或者使用Docker-compose进行容器编排:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
services:
napcat:
image: mlikiowa/napcat-docker:latest
container_name: napcat
restart: always
network_mode: host
environment:
- NAPCAT_UID=${MY_UID:-0} # 如果环境变量没传,默认用 0 (root)
- NAPCAT_GID=${MY_GID:-0} # 如果环境变量没传,默认用 0 (root)
volumes:
# 宿主机路径 : 容器内路径
- /root/expbot/expbot:/root/expbot/expbot
- /app/.config/QQ:/app/.config/QQ
- /app/napcat/config:/app/napcat/config
- /app/napcat/plugins:/app/napcat/plugins

Nonebot2

安装

1
2
3
4
5
python -m pip install --user pipx
python -m pipx ensurepath # 如果无法执行ensurepath需要手动把pipx所在地址添加到系统环境变量Path中

# 新开一个终端。安装nb-cli。
pipx install nb-cli

若在Ubuntu或其它Linux发行版中,可使用:apt install pipx安装pipx

创建bot

nb create

然后一步步选择:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 # 选择bootstrap模板
[?] Select a template to use: (Use ↑ and ↓ to choose, Enter to submit)
> bootstrap (for beginner or user)

# 填写Bot项目名,也是Bot文件夹名
[?] Project Name:

# 选择OneBot V11协议
[?] Which adapter(s) would you like to use?
○ OneBot V11 (OneBot V11 协议)
○ Discord (Discord 适配)

# 选择驱动器FastAPI + HTTPX + websockets
[?] Which driver(s) would you like to use?
○ FastAPI (FastAPI 驱动器)
○ HTTPX (HTTPX 驱动器)
○ websockets (websockets 驱动器)

# 输入Y安装依赖,创建虚拟环境
[?] Install dependencies now? (Y/n)
[?] Create virtual environment? (Y/n)

# 选择默认插件是否安装
[?] Which builtin plugin(s) would you like to use?
○ echo
○ single_session

然后切到bot项目根目录即可运行Bot:

nb start --reload

环境配置

bot的环境配置由.env这一文件及其下属文件.env.{$ENVIRONMENT}文件进行指定。

其中ENVIRONMENT这个变量在.env中写,默认值为prod(即默认读取.env.prod文件作为配置)

.env和.env.{$ENVIRONMENT}中的配置会同时生效,但.env.{$ENVIRONMENT}中的配置会覆盖掉.env中的同名配置

一般的.env中的基本配置项如下 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# NoneBot2 运行所使用的驱动器,文件默认一般只有这一行
# 见 https://nonebot.dev/docs/next/advanced/driver
DRIVER=~fastapi+~httpx+~websockets

# 重定向 localstore 插件的存储路径,便于后续迁移 Bot
LOCALSTORE_CACHE_DIR=data/nonebot/cache
LOCALSTORE_CONFIG_DIR=data/nonebot/config
LOCALSTORE_DATA_DIR=data/nonebot/data

# LogPile 日志文件保存路径
# LOGPILE_PATH=./log

# LogPile 日志输出等级,可以为列表
LOGPILE_LEVEL=INFO

# LogPile 日志保留天数
# LOGPILE_RETENTION=14

### NoneBot 配置项 ###

# 机器人超级用户
# 超级用户拥有对 Bot 的最高权限
SUPERUSERS=[""]

# 机器人的昵称
# 消息以机器人昵称开头可以代替艾特
NICKNAME=[""]

# ENVIRONMENT子环境配置(即.env.{$ENVIRONMENT}), 该配置项应存在于.env文件中
ENVIRONMENT=prod

# 命令起始字符
# 一般只有 on_command 匹配规则适用
# 如果有一个指令为 查询,当该配置项为 ["/"] 时使用 /查询 才能够触发
COMMAND_START=["", "/"]

# 命令分割字符
# 一般用于二级指令(不常见)
COMMAND_SEP=[".", " "]

# NoneBot2 监听的 IP 或 主机名
# 如果要对公网开放,请改成 0.0.0.0
HOST=127.0.0.1
# NoneBot2 监听的端口
# 请保证该端口号与连接端配置相同 或与端口映射配置相关
PORT=8080

# NoneBot2 日志输出等级, 为了便于查错可换为DEBUG
LOG_LEVEL=INFO

### OneBot 适配器配置 ###

# OneBot Access Token 配置
# ONEBOT_ACCESS_TOKEN=你的访问令牌

# OneBot V11 Secret 配置
# ONEBOT_SECRET=你的签名

# OneBot V11 正向 Universal WebSocket 配置
# 参考 https://onebot.adapters.nonebot.dev/docs/guide/setup#%E6%AD%A3%E5%90%91-websocket-%E8%BF%9E%E6%8E%A5
# 请确保你的 NoneBot 使用的是 ForwardDriver,否则无法使用此连接方式。
# ONEBOT_WS_URLS=["ws://127.0.0.1:5700"]

# OneBot V11 HTTP POST 配置
# 参考 https://onebot.adapters.nonebot.dev/docs/guide/setup#http-post
# 请确保你的 NoneBot 使用的是 ForwardDriver 和 ReverseDriver,否则无法使用此连接方式。
# ONEBOT_API_ROOTS={"Bot QQ号": "http://127.0.0.1:5700/"}

# OneBot V12 正向 WebSocket 配置
# 参考 https://onebot.adapters.nonebot.dev/docs/guide/setup#%E6%AD%A3%E5%90%91-websocket-%E8%BF%9E%E6%8E%A5-1
# 请确保你的 NoneBot 使用的是 ForwardDriver,否则无法使用此连接方式。
# ONEBOT_V12_WS_URLS=["ws://127.0.0.1:5700"]

# OneBot V12 HTTP Webhook 配置
# 参考 https://onebot.adapters.nonebot.dev/docs/guide/setup#http-webhook
# 请确保你的 NoneBot 使用的是 ForwardDriver 和 ReverseDriver,否则无法使用此连接方式。
# ONEBOT_V12_API_ROOTS={"Bot QQ号": "http://127.0.0.1:5700/"}

使用插件

在插件商店中寻找需要的插件,展开插件详情——复制安装命令,在Bot项目目录下执行,然后重启nb。部分插件需要在.env.prod进行额外配置,具体请查看每个插件的文档说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
nb plugin install <插件包名>
nb plugin uninstall <插件包名>
nb plugin update <插件包名>

::或是调出nonebot菜单
nb plugin

::管理nonebot适配器:
nb adapter


::管理nonebot驱动器器:
nb driver

对接NapCat

nb默认启用反向WS。确保.env文件中已配置HOST和PORT两个配置项

然后在NapCat目录中(NapCat.Shell)打开/config/webui.json 找到端口和Token:

1
2
3
"host": "::",
"port": ,
"token":

然后打开NapCat WebUI 链接,切到网络配置并新建:

图中HOST和PORT与.env中的监听配置要一致

对接Discord

连接到Discord时,需要下述配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DISCORD_BOTS='
[
{
"token": (Discord APP Token),
"intent": {
"guild_messages": true,
"direct_messages": true
},
"application_commands": {"*": ["*"]}
}
]
'

# application_commands的{"*": ["*"]}代表将全部应用命令注册为全局应用命令
# {"admin": ["123", "456"]}则代表将admin命令注册为id是123、456服务器的局部命令,其余命令不注册

DISCORD_API_VERSION=10
# Discord API 版本,默认为 10

DISCORD_API_TIMEOUT=15.0
# Discord API 超时时间,默认为 30 秒

DISCORD_HANDLE_SELF_MESSAGE=True
#是否处理自己发送的消息,默认为 False

token需要从 主页 | Discord 开发者门户 的APP->机器人中获取

依赖管理(PDM)

在bot项目根目录中执行:

1
pdm init

切换到PDM国内镜像:

1
2
3
4
# 清华大学源
pdm config pypi.url https://pypi.tuna.tsinghua.edu.cn/simple
# 阿里源
pdm config pypi.url https://mirrors.aliyun.com/pypi/simple

容器编排(MongoDB)

在服务器上编排MongoDB镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Docker compose
services:
mongodb:
image: mongo:${VERSION}
container_name: ${CONTAINER_NAME}
deploy:
resources:
limits:
cpus: ${CPUS}
memory: ${MEMORY_LIMIT}
restart: always
environment:
# 初始超级管理员账号和密码
MONGO_INITDB_ROOT_USERNAME: ${USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${PASSWORD}
volumes:
- ${APP_PATH}/data:/data/db
labels:
createdBy: "AXIS5"
# 显式声明使用 bridge 模式(默认其实也是 bridge)
networks:
- mongo-network
ports:
# 映射格式:宿主机端口:容器内端口
# 这样你访问 <指定端口> 就等同于访问容器内的 27017
- "${HOST_IP}:${SERVICE_PORT}:27017"

networks:
mongo-network:
driver: bridge

# .env
VERSION=8.2.2
CONTAINER_NAME=Botmongo
HOST_IP=0.0.0.0
SERVICE_PORT=<需要映射到宿主机的指定端口>
USERNAME=(用户名)
PASSWORD=你的密码
CPUS=0
MEMORY_LIMIT=0MB
# 要把服务挂在到宿主机硬盘的哪个位置
APP_PATH=/www/dk_project/dk_app/mongodb/mongodb

技巧:Linux下的多窗口运行

Screen——传奇Linux多开窗口程序

screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s <shell>][-S <作业名称>]

  • -A  将所有的视窗都调整为目前终端机的大小。
  • -d<作业名称>  将指定的screen作业离线。
  • -h <行数>  指定视窗的缓冲区行数。
  • -m  即使目前已在作业中的screen作业,仍强制建立新的screen作业。
  • -r <作业名称|PID>  恢复离线的screen作业。
  • -R  先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。
  • -s  指定建立新视窗时,所要执行的shell。
  • -S<作业名称>  指定screen作业的名称。
  • -v  显示版本信息。
  • -x  恢复之前离线的screen作业。
  • -ls或–list  显示目前所有的screen作业。
  • -wipe  检查目前所有的screen作业,并删除已经无法使用的screen作业。

退出当前窗口:exit

断开当前会话:Ctrl+A+D

其他文章