Nonebot2 机器人本地搭建及部署服务器 准备 本地环境:
python环境 pycahrm或者VScode…(不建议拿记事本写代码) 服务器准备:
安装Nonebot 2.0 在cmd中安装nb-cli (nonebot2 Github )
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple nb-cli
下载go-cqhttp :go-cqhttp_windows_amd64.exe (win系统),放置路径\Robot\go-cqhttp_windows_amd64。镜像文档
配置机器人 推荐方法二,更方便一点
方法一 运行go-cqhttp_windows_amd64.exe,生成go-cqhttp.bat并打开,选择输入3,文件夹中出现config.yml,打开对它配置
account: uin: password: '' - ws-reverse: universal: ws://127.0.0.1:53245/onebot/v11/ws/
再次运行go-cqhttp.bat扫码登录,出现warningxxx告诉你连接失败后退出,回到上一级目录\Robot\,打开powshell,来建立机器人
nb create 输入 张时贰# 随便输一个名字作为存放机器人的文件夹,尽量英文 # ↑↓键移动,然后按空格选中,然后再回车,依次选择 src echo Onebot V11
进入文件夹\张时贰\,打开.env,让配置信息指向文件.env.prod(dev做开发版本,prod做稳定版本即部署服务器时)
编辑.env.prod
HOST=127.0.0.1 PORT=53245 SUPERUSERS=["1310446718"] NICKNAME=["BFI","小张","薯条"] COMMAND_START=["/"] COMMAND_SEP=["."]
运行bot.py然后打开go-cqhttp.bat。用另一个QQ向配置配置机器人的QQ发送/echo xxx会自动回复
方法二 使用插件配置,nonebot-plugin-gocqhttp Github仓库
在cmd中安装该插件
pip install nonebot-plugin-gocqhttp
运行go-cqhttp_windows_amd64.exe,生成go-cqhttp.bat并打开,选择输入3,文件夹中出现config.yml,打开对它配置
account: uin: password: '' - ws-reverse: universal: ws://127.0.0.1:13105/onebot/v11/ws/
再次运行go-cqhttp.bat扫码登录,出现warningxxx告诉你连接失败后退出,回到上一级目录\Robot\,打开powshell,来建立机器人
nb create 输入 张时贰# 随便输一个名字作为存放机器人的文件夹 # ↑↓键移动,然后按空格选中,然后再回车,依次选择 src echo Onebot V11
进入文件夹\张时贰\,.env.dev添加端口
HOST=127.0.0.1 PORT=13105 LOG_LEVEL=DEBUG SUPERUSERS=["1310446718","2689438597"] NICKNAME=["小张", "薯条" ] COMMAND_START=["/",""] COMMAND_SEP=["."]
bot.py,修改24、27行
nonebot.load_builtin_plugins("echo" ) nonebot.load_plugin('nonebot_plugin_gocqhttp' )
控制台出现http://127.0.0.1:12345/go-cqhttp/,点击进入
左上角添加账号,设备、密码为空(扫码登录),提交后重启bot.py然后点击网页中的QQ头像,扫码登录。用另一个QQ向配置配置机器人的QQ发送/echo xxx会自动回复
关闭:不要直接关闭 ,在浏览器中点击停止,在pycharm中停止程序运行
相关账号缓存信息\nonebot-plugin-gocqhttp\accounts\xxxxx
另一种启动方式:在文件夹\张时贰\中打开powshell输入nb run,打开go-cqhttp.bat,所以说用插件部署更方便,启动也快捷
扩展其它功能 商店 NoneBot ,右上角点击商店,以人生重开模拟器为例,在命令行输入
pip install nonebot_plugin_remake pip list pip uninstall nonebot_plugin_remake
在bot.py中添加相关插件名称
nonebot.load_builtin_plugins("echo" ) nonebot.load_plugin('nonebot_plugin_gocqhttp' ) nonebot.load_plugin('nonebot_plugin_remake' )
启动后,在另一个QQ对机器人QQ发送/remake或者QQ群@机器人QQ /remake
扩展其它功能时,多看日志报错以及仓库说明,既然是发布版本,代码跑不起来一定是自己的错
以下为自用插件汇总(名字、命令、仓库地址、安装、导包),以及安装过程中的踩坑(有的需要额外依赖及配置),也推荐这样例举出来,之后更新某个包方便查看仓库地址
# 人生模拟 # 命令: [remake] https://github.com/noneplugin/nonebot-plugin-remake pip install nonebot_plugin_remake nonebot.load_plugin('nonebot_plugin_remake')
# 青年大学习 # 命令: [青年大学习、大学习][大学习截图][完成截图][大学习帮助] https://github.com/ayanamiblhx/nonebot_plugin_youthstudy pip install nonebot_plugin_youthstudy nonebot.load_plugin('nonebot_plugin_youthstudy')
# 色色 # 可选配置 群聊需要发送setu_wl add开启 setu_withdraw_time = 30 # 撤回 setu_max_num = 20 # 最大数量 setu_enable_private = True # 命令:[setu x张 r18 色图|色色|白丝],234参数可选 # setu_wl add 添加会话至白名单 setu_wl del 移出会话自白名单 # setu_r18 on 开启会话的r18模式 setu_r18 off 关闭会话的r18模式 # setu_cd xxx 更新会话的冷却时间[0,∞] # setu_wd xxx 撤回前等待的时间[1,100] # setu_mn xxx 最大张数[1,25] https://github.com/Special-Week/nonebot_plugin_setu4 pip install nonebot_plugin_setu4 nonebot.load_plugin('nonebot_plugin_setu4')
# 点歌 需额外配置,参考文档,之后在白名单的群中发送/ncm t k ncm_admin_level=1 # 设置命令权限(1:仅限superusers和群主,2:在1的基础上+管理员,3:所有用户) ncm_ctcode="86" # 手机号区域码,默认86 ncm_phone= # 手机登录 ncm_password= # 密码 ncm_playlist_zip=False # 上传歌单时是否压缩 # 命令:[点歌歌名] https://github.com/kitUIN/nonebot-plugin-ncm pip install nonebot-plugin-ncm nonebot.load_plugin('nonebot-plugin-ncm')
# 点歌 已魔改为发送音频(需要私信) # 命令: [点歌 歌名] https://github.com/maxesisn/nonebot_plugin_songpicker2 nb plugin install nonebot_plugin_songpicker2 nonebot.load_plugin('nonebot_plugin_songpicker2')
# 天气 需额外配置,参考文档 QWEATHER_APIKEY='a584b7c5dd854d59b2186e748fa' QWEATHER_APITYPE = '0' # 命令: [天气地区]、[地区 天气] https://github.com/kexue-z/nonebot-plugin-heweather pip install nonebot-plugin-heweather nonebot.load_plugin('nonebot_plugin_heweather')
# 疫情 需额外配置 COVID19 = {"notice":"True", "red-line": 1000, "filter":[],"group":[]} // notice: str 仅为 True 时开启功能 // red-line: int 新增达到该数值会, 发送疫情信息 // filter: List 过滤城市/地区 (默认过滤 香港 台湾) // group: List[int] | str 发送到群; 为 all 时发送到所有群 # 命令: [城市名疫情]、[城市名疫情政策]、[城市名风险地区] https://github.com/Zeta-qixi/nonebot-plugin-covid19-news pip install nonebot_plugin_covid19_news nonebot.load_plugin('nonebot_plugin_covid19_news')
# 一言 # 命令: [一言] https://github.com/A-kirami/nonebot-plugin-hitokoto pip install nonebot-plugin-hitokoto nonebot.load_plugin('nonebot_plugin_hitokoto')
# 今天吃什么 需额外配置,参考文档 WHAT2EAT_PATH="./src/plugins/resource" EATING_LIMIT=5 # 每个时段吃什么的次数上限,默认5次;每日6点、11点、17点、22点自动刷新 GREETING_GROUPS_ID=["123456789", "987654321"] # 默认开启小助手群组 # 命令: # 吃什么:今天吃什么、中午吃啥、今晚吃啥、中午吃什么、晚上吃啥、晚上吃什么、夜宵吃啥…… # [管理员或超管] 添加或移除群菜名:[添加/移除 菜名]; # 查看群菜单:[菜单/群菜单/查看菜单]; # [超管] 添加至基础菜单:[加菜 菜名]; # 查看基础菜单:[基础菜单]; # [管理员或超管] 开启/关闭吃饭小助手:[开启/启用/关闭/禁用小助手]; # [管理员或超管] 添加/删除吃饭小助手问候语:[添加/删除/移除问候 时段 问候语]; https://github.com/MinatoAquaCrews/nonebot_plugin_what2eat pip install nonebot_plugin_what2eat nonebot.load_plugin('nonebot_plugin_apscheduler') # 其它依赖 nonebot.load_plugin('nonebot_plugin_what2eat')
# 答案之书 # 命令:[翻看答案xx]、[xx翻看答案] https://github.com/A-kirami/nonebot-plugin-answersbook pip install nonebot-plugin-answersbook nonebot.load_plugin('nonebot_plugin_answersbook')
# 支付宝 安装插件https://blog.csdn.net/qq_38863413/article/details/105017775?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22105017775%22%2C%22source%22%3A%22qq_49488584%22%7D&ctrtid=AgDj8 # 命令: [支付宝到账xx] https://github.com/A-kirami/nonebot-plugin-alipayvoice pip install nonebot-plugin-alipayvoice # nonebot.load_plugin('nonebot_plugin_alipayvoice' )
# 扫雷 # 命令: @机器人 + 扫雷 / 扫雷初级 / 扫雷中级 / 扫雷高级 可追加[-r] 、[-c]、[-n] 自定义行列数和雷数 # [挖开/open + 位置] [标记/mark + 位置] 可同时挖开多个[挖开 A1 B1] # [结束] [查看游戏] https://github.com/noneplugin/nonebot-plugin-minesweeper pip install nonebot_plugin_minesweeper nonebot.load_plugin('nonebot_plugin_minesweeper')
# 迷宫 需要配置evn 如下 min_maze_rows = 13 # 迷宫最小行数 max_maze_rows = 35 # 迷宫最大行数 min_maze_cols = 13 # 迷宫最小列数 max_maze_cols = 35 # 迷宫最大列数 default_maze_rows = 18 # 迷宫默认生成行数 default_maze_cols = 27 # 迷宫默认生成列数 # 命令: [maze] 追加[-r]、[-c]、[-m]代表行列算法,算法包括DFS,Prim,Kruskal # [U] [D] [L] [R] 代表上下左右默认一步 追加数字示例 [U2L2]下2左2 # [结束] https://github.com/EtherLeaF/nonebot_plugin_maze pip install nonebot_plugin_maze nonebot.load_plugin('nonebot_plugin_maze')
# 棋类 # 命令:[围棋][五子棋][黑白棋] 后手示例:[五子棋--white] # [落子 字母+数字][结束下棋][查看棋局][悔棋][跳过回合]跳过当前回合仅黑白棋支持 # 手动结束游戏或超时结束游戏时,可发送“重载xx棋局”继续下棋或[boardgame] # -r RULE, --rule RULE: 规则名 # -e, --stop, --end: 停止下棋 # -v, --show, --view: 显示棋盘 # --repent: 悔棋 # --skip: 跳过回合 # --reload: 重新加载已停止的游戏 # --white: 执白,即后手 # POSITION: 落子位置 https://github.com/noneplugin/nonebot-plugin-boardgame pip install nonebot_plugin_boardgame nonebot.load_plugin('nonebot_plugin_htmlrender') # 棋类额外依赖,且需要安装执行apt update && apt install -y locales locales-all fonts-noto libnss3-dev libxss1 libasound2 libxrandr2 libatk1.0-0 libgtk-3-0 libgbm-dev libxshmfence1 nonebot.load_plugin('nonebot_plugin_boardgame')
# 图片表情包额外依赖 https://github.com/noneplugin/nonebot-plugin-imageutils pip install nonebot_plugin_imageutils nonebot.load_plugin('nonebot_plugin_imageutils') # 图片表情包 需要下载图片 参考文档 # 命令[鲁迅说|诺基亚|有内鬼|喜报|记仇|狂爱|低语|别说了|一巴掌|坐牢|滚屏|低情商xx高情商xx|吴京xx中国xx|口号|xx起来了|举牌|可达鸭|王境泽.gif|为所欲为.gif|缠身子.gif|切格瓦拉.gif|谁反对.gif|曾小贤.gif|压力大爷.gif|你好骚啊.gif|食屎啦你.gif|五年怎么过的.gif] https://github.com/noneplugin/nonebot-plugin-memes pip install nonebot_plugin_memes nonebot.load_plugin('nonebot_plugin_memes')
# 头像表情包 # 命令:查看所有图:[@机器人头像表情包],[指令+@xx/QQ号/自己/[图片] https://github.com/noneplugin/nonebot-plugin-petpet pip install nonebot_plugin_petpet nonebot.load_plugin('nonebot_plugin_petpet')
# 文字转图片 # 命令[txt2img] https://github.com/mobyw/nonebot-plugin-txt2img pip install nonebot-plugin-txt2img nonebot.load_plugin("nonebot_plugin_txt2img")
# 筛子 https://github.com/MinatoAquaCrews/nonebot_plugin_roll pip install nonebot_plugin_roll nonebot.load_plugin("nonebot_plugin_roll")
# 机器人撤回 自己发出的消息 # 命令[@机器人 撤回][@机器人 撤回 1][@机器人 撤回 0-3] https://github.com/noneplugin/nonebot-plugin-withdraw pip install nonebot-plugin-withdraw nonebot.load_plugin("nonebot_plugin_withdraw")
# Epic订阅 # 群聊("((E|e)(P|p)(I|i)(C|c))?喜(加一|\+1)" ) # 私聊("喜(加一|\+1)(私聊)?订阅" ) https://github.com/monsterxcn/nonebot_plugin_epicfree pip install --upgrade nonebot_plugin_epicfree nonebot.load_plugin("nonebot_plugin_epicfree")
# LOL订阅 # 主命令:[lol] # 附带:[lol本周]、[lol详情+ID]、[lol订阅+ID]、[lol查看订阅]、[lol联赛] https://github.com/Diaosi1111/nonebot_plugin_lolmatch
# 翻译 # 命令[x翻x 内容] https://github.com/NumberSir/nonebot_plugin_baidutranslate pip install nonebot_plugin_baidutranslate nonebot.load_plugin("nonebot_plugin_baidutranslate")
以上只总结了部分商店插件还有自动续火花,俄罗斯读盘,60s世界,历史上今天
插件更新 pip list --outdated # 查看所有包是否有更新 pip install --upgrade <packagename> # 更新某个模块 pip-review --local --interactive # 更新全部 # 如果仓库更新版本,pip list --outdated没有更新,更换镜像源 cat ~/.pip/pip.conf # 方案一,查看镜像源位置,vim ~/.pip/pip.conf修改镜像源 pip list --outdated -i http://pypi.douban.com/simple --trusted-host pypi.douban.com # 方案二,加-i后缀临时指定镜像源 pip install --upgrade <packagename> -i http://pypi.douban.com/simple --trusted-host pypi.douban.com # 使用镜像源安装
自写插件 也可以自己写插件nonebot2_萌新源 ,nonebot2 聊天机器人插件_starvapour ,书写方法,API调用多看官方文档说明
# 自写插件存放位置../src/plugins下,主要代码放在init中 |-插件名字 |-__init__.py |-xxx.py |-xxx.py
from nonebot import on_keywordfrom nonebot.typing import T_Statefrom nonebot.adapters.onebot.v11 import GroupMessageEventimport warningsfrom nonebot.permission import Botwarnings.filterwarnings("ignore" ) che = on_keyword({'广告' , '沙雕' , '广告' , 'md' , '妈的' , '卧槽' , '嘛的' , '操你妈' , '操你' , '加vx' ,'操' ,'草' }) @che.handle() async def c (bot: Bot, event: GroupMessageEvent, state: T_State ): mid = event.message_id print (mid) await bot.delete_msg(message_id=mid)
菜单功能
''' 菜单 个人编写 预先用插件[nonebot-plugin-txt2img]生成menu.png放在img中 为什么不直接魔改插件?因为他是在线生成图片,改了一下返回延迟4~5s不如预先存放一个 ├─modifymenu │ │ __init__.py │ │ │ ├─img │ │ menu.png # 命令:[@机器人+rmenu] 私聊[rmenu] ''' from nonebot import on_commandfrom nonebot.adapters.onebot.v11 import MessageSegmentfrom nonebot.rule import to_meimport osget_menu = on_command ( "rmenu" , rule=to_me () ) img_path = 'file:///' + os.path.split ( os.path.realpath ( __file__ ) )[ 0 ] + '/img/' @get_menu.handle () async def get_menu_handle (): await get_menu.send ( MessageSegment.image ( img_path + "menu.png" ) )
调用青云客智能聊天机器人API 实现智能聊天
from nonebot import on_keywordfrom nonebot.typing import T_Statefrom nonebot.adapters.onebot.v11 import Bot, Message, Eventimport requestsimport jsonrandom_chat = on_keyword ( {'chat' } ) @random_chat.handle () async def sj (bot: Bot, event: Event, state: T_State ): get_msg = str ( event.get_message () ).strip () get_msg = get_msg.strip ( '#' ) url = f'http://api.qingyunke.com/api.php?key=free&appid=0&msg={get_msg} ' get_data = requests.get ( url ) get_json = json.loads ( get_data.text ) msg = get_json[ 'content' ] name = '菲菲' characters = '{br}' if name in msg: msg = msg.replace ( '菲菲' , '张时叁' ) elif characters in msg: msg = msg.replace ( '{br}' , "\n" ) await random_chat.finish ( Message ( f'{msg} ' ) )
随机头像使用远昔API接口 ,这个API很多,可以实现很多很多功能
from nonebot import on_keywordfrom nonebot.typing import T_Statefrom nonebot.adapters.onebot.v11 import GroupMessageEvent,Bot,Message,MessageSegment,PrivateMessageEventimport requestsimport jsonrandom_head = on_keyword({'随机头像' }) @random_head.handle() async def group_head (bot: Bot, event: GroupMessageEvent, state: T_State ): msg = await get_head() await random_head.send(Message(msg)) @random_head.handle() async def private_head (bot: Bot, event: PrivateMessageEvent, state: T_State ): msg = await get_head() await random_head.send(Message(msg)) async def get_head (): url = 'https://www.yuanxiapi.cn/api/touxiang/?format=json' get_data = requests.get(url) get_json = json.loads(get_data.text) print (get_json) img = get_json['imgurl' ] msg = f"[CQ:image,file={img} ]" return msg
此外自己写的还有Battlefield战绩工具 ,续火花 ,东西比较多,直接看仓库吧。在商店也已上传。还有一部分小功能未上传商店辞辞bot: 辞辞bot ,是我和萌新源做的,萌新源QQ群
部署服务器 本地全部调试好以后,部署服务器,bot.py中先注释掉nonebot_plugin_gocqhttp插件。当前文件全放在Robot文件夹下,复制一份Robot文件夹,上传服务器对副本操作,避免操作失误,可以接着复制一份从头来
Robot_Server(副本可以重命名一下) ├─go-cqhttp_windows_amd64 │ ├─data │ │ ├─cache │ │ ├─images │ │ │ └─guild-images │ │ ├─leveldb-v3 │ │ ├─videos │ │ └─voices │ └─logs └─QQRobot(上一步中的张时贰文件夹我重命名为QQRobot,Linux带中文操作别扭,个人习惯不改也可以) ├─accounts │ ├─1310446718 │ └─binary └─src └─plugins
下载go-cqhttp :go-cqhttp_linux_amd64.tar.gz ,下载好解压得到go-cqhttp ,Robot_Server\go-cqhttp_windows_amd64中删除go-cqhttp.bat,go-cqhttp_windows_amd64.exe,移入go-cqhttp。利用Xftp上传Robot_Server到/home内(个人习惯)。(更新命令go-cqhttp update)
XShell连接服务器,因为需要同时启动go-cqhttp.bat,bot.py,而服务器端一个窗口就只能运行一次,只跑起来一个,不停的输出输出,另一个没法启动,而且一旦窗口关闭,整个后台程序就关闭了,所以用screen插件(打个比方,刚才运行俩个文件我们都是一个文件夹开go-cqhttp.bat,一个编译器去运行bot.py,所以需要两个 窗口),screen有个缺点,服务器重启后需要重新运行机器人,如果有宝塔,学一下Supervisor,服务器重启可以自启动,不再赘述
安装screen
yum install screen which screen cd /home/Robot_Serverls
第一个窗口,如果一直扫码失败,配置config.yml中的密码
screen -R gocq # 命名第一个窗口叫gocq cd go-cqhttp_windows_amd64/ # 进入gocq文件夹中 ./go-cqhttp # 如果返回,bash: ./go-cqhttp: Permission denied,权限不够 用FTP修改这个文件得权限为777(读写全开,最高权限),然后再运行一次 按住ctrl+A+D # 先关闭当前窗口,类似于win上缩小窗口,screen -r gocq可以再次打开
第二个窗口
screen -R nb2 # 命名第一个窗口叫nb2 cd QQRobot # 进入QQRobot文件夹中 pip3 install nb-cli pip3 install xxxx # 把商店的插件全部下一遍 python3 bot.py # 运行即可
其它screen命令
screen -ls Ctrl+d exit screen -S id.session_name -X quit
停止调试ctrl+c,强制停止ctrl+z,如果再次运行有进程占用
ps -ef | grep go-cqhttp # 显示go-cqhttp的进程列表 ps -ef | grep bot.py kill -9 pid # 关闭进程
此外还有
绪山真寻Bot ,基于Nonebot2和gocq开发,自带插件,开箱即用HoshinoBot ,基于Nonebot和gocq开发,自带插件,开箱即用MyQQ ,拥有可视化软件,部署简单,插件付费。组织已解散,更名Moen酷q,小栗子,myqq,暗影这几个就是花钱买省事 推荐还是Nonebot2香,部署难度适中,可以自己编写插件,我喜欢自由度高一些嘿嘿
附权限控制总结 1.利用get_bot() 发送权限 await get_bot().send_private_msg(user_id=xxx, message="") await get_bot().send_group_msg(group_id=xxx, message="") 2.rule(支持cq:_pock) 命令权限 matcher = on_message(rule=_pock)c https://v2.nonebot.dev/docs/next/advanced/rule 3.permission="xxx" | handler装饰器 命令权限 https://v2.nonebot.dev/docs/next/advanced/permission 4.事件处理函数重载 群私聊权限 https://v2.nonebot.dev/docs/advanced/di/overload 5.从装饰器下手 @random_head.handle() async def sj(bot: Bot, event: Event, state: T_State) async def sj(bot: Bot, event: GroupMessageEvent, state: T_State) async def sj(bot: Bot, event: PrivateMessageEvent, state: T_State) 6.发送,图片需要"Message"转义,本地图片需要uri格式 msg1 = Message('快来看涩图') msg2 = MessageSegment.image('http://a.image.com/setu') msg3 = Message('[CQ:at,qq=114514]') msg = msg3 + msg1 + msg2 setu001 = MessageSegment.image('file:///D:/learning_materials/setu/001.jpg') await matcher.send('123') await matcher.send(MessageSegment.image('http://a.image.com/setu'))