DOGchan:如何做一个能够自动回复的 Mastodon bot
缪尚咖啡馆已经有只傲娇猫猫,当然也要有可爱狗狗!于是决定学习制作一个能够自动回复的狗狗 bot,让缪尚咖啡馆实现猫狗双全。让我们有请小狗汪汪!
利用 Node 及 mastodon-api 实现自动回复 bot
由于这一方法在尝试过程中 bug 百出,且没有找到合适的解决方案,暂时搁置,转而使用 Mastodon.py
。
但此方法本身较为好懂,油管教程也也非常详细、容易上手。虽然很不想承认,但我没有搭建成功应该是我的问题,可能会在以后更熟悉 JavaScript 时再回头看这个教程。
参考
长毛象顶流:操操
油管教程:Mastodon API and Bots: Node.js
注册账号
选择一个合适的站点注册 bot 账号,并修改资料,注意选中 “这是一个 bot 账号 / This is a bot account”。
在管理面板找到开发/Development-创建新应用/New Application,创建新应用并给予读写权限,复制访问令牌。
安装 node
由于服务器上还没有安装 npm,所以第一步需要先安装。直接使用命令安装。
1 | apt install npm |
接下来运行命令:
1 | npm init |
根据提示一步步填写初始化信息:
1 | This utility will walk you through creating a package.json file. |
现在查看 dogchan
目录下会多出一个名为 package.json
的文件,内容是刚才初始化填写的信息。
配置环境
运行命令:
1 | npm install dotenv |
出现问题:
1 | npm WARN notsup Unsupported engine for dotenv@16.0.1: wanted: {"node":">=12"} (current: {"node":"10.19.0","npm":"6.14.4"}) |
提醒安装的 node
和 npm
版本不足。查找教程升级版本后,再次运行命令出现新的报错:
1 | node:internal/modules/cjs/loader:936 |
谷歌解决方法大多数是完全卸载后重装,但无论卸载重装多少次,总会遇到 Error: Cannot find module 'semver'
。最后的解决方式是:
1 | # 完全 uninstall node 和 npm |
这里再次出现状况,运行 npm -v
时报错:
1 | -bash: /usr/bin/npm: No such file or directory |
但如果换为运行 /usr/local/bin/npm -v
则能够正常显示版本号。没有再次搜索问题原因,直接在 .bashrc
文件中增加一行:
1 | alias npm='/usr/local/bin/npm' |
而后执行 source .bashrc
。此时运行 npm -v
即可正常显示版本号。
重新进行关于 npm 的所有命令,直到安装完成 dotenv
。安装完成后出现提醒信息:
1 | added 1 package, and audited 236 packages in 1s |
没有找到解决方法,运行 npm audit fix --force
也无法解决 8 vulnerabilities,暂时搁置。
新建文件 .env
,将前述步骤中得到的 bot 访问令牌填入文件:
1 | # 应用 ID |
保存并退出。
新建 bot.js
文件,在文件内写入:
1 | require('dotenv').config(); |
由于后续会将整个 bot 的代码上传至 github,所以需要将真正的 .env
隐藏起来而上传一个示例文件。
1 | nano .env-example |
connect to mastodon
与 mastodon 连接需要使用 node package (mastodon-api),安装命令:
1 | npm install --save mastodon-api |
安装完成后目录下会多出一个目录 node_modules
和一个文件 package-lock.json
。查看 package.json
会发现其中多出一段:
1 | "dependencies":{ |
想要连接 mastodon 则需要编辑 bot.js
文件,在文件内写入:
1 | const mastodon = require('mastodon-api'); |
log file
每一次发送嘟文会在屏幕上打印一大串内容,包括嘟文发送情况、嘟文的链接等等,但并不需要每一次都打印详细信息,只需要将 debug 所需的信息输出到 log 文件即可。
在 bot.js
文件中写入:
1 | const fs = require('fs'); |
上述代码实际实现了一次完整的发送嘟文,因此可以封装为一个函数,即:
1 | const fs = require('fs'); |
streaming api: user
目前 bot 已经实现自动发嘟,但如果想做一个可以自动回复、给特定人点星而不是随机骚扰用户,则需要监听 streaming api 中的用户部分,并根据所得信息进行相应回应。
在 bot.js
文件中写入:
1 | const listener = M.stream('streaming/user') |
通过 node bot.js
运行 bot,并利用其它账号 @bot 或关注等操作测试 bot 是否正确运行。这一步遇到问题:
1 | Mastodon Bot starting... |
经过一整天的搜索和试图 debug 决定放弃,转而使用 python 中的 Mastodon.py
,即 CATsama 使用的包。
利用 Mastodon.py 实现自动回复 bot
参考
Mastodon.py: Docs , GitHub
mastodon-bot-template: reply.py
mstdn-ebooks: reply.py
注册账号
选择一个合适的站点注册 bot 账号,并修改资料,注意选中 “这是一个 bot 账号 / This is a bot account”。
在管理面板找到开发/Development-创建新应用/New Application,创建新应用并给予读写权限,复制访问令牌。
安装 Mastodon.py
安装 miniconda3:
1 | mkdir miniconda |
通过 pip
安装 Mastodon.py:
1 | pip3 install requests beautifulsoup4 Mastodon.py # 安装mastodon.py |
编辑脚本
整个过程基本上属于一边参考现有的利用 Mastodon.py 实现自动回复的库,一边自己悟每一步都是做什么的。
其中最实用的一个库是: mastodon-bot-template。这个库不仅包括了自动回复模板,也包括了自动发嘟模板。本项目中的 extract_text
函数、process_mention
函数和处理 notifications 都直接借用模板或稍加修改。模板作者要求使用该模板时引用原库,且使用同样的 license (AGPL-3.0 license)。
自动回复脚本
自动回复脚本需要完成接收到 notification、判定 notification 是 mention 、对 mention 嘟文内容进行处理、作出相应的回复。其中所需的函数较多,因此将大多数函数存在 Woof.py
中,大框架放在 dogchan.py
中。
代码基本参考前面提到的 mastodon-bot-template: reply.py。其中代码的注释非常详细,此处不再重复。
完成脚本后使用 systemd
设置定时任务,让服务器自动每 30 秒执行一次脚本。这里的自动执行不如前面尝试失败的方法 利用 mastodon-api 实现自动回复 bot
优雅,如果能够进一步提升将在此处指出。
在服务器上安装 systemd:
1 | sudo apt-get install systemd |
任务设置模板 (来自于 mastodon-bot-template):
1 | # an example for systemd |
自动发嘟脚本
自动发嘟脚本 selfie.py
主要用于实现每周三上午九点发一张汪汪照片。相关代码可参考 一个简单的 mastodon bot 或前面提到的 mastodon-bot-template。
若想要在嘟嘟中添加图片,则需要调用模板以外的函数,具体如下:
1 | # 随机选取指定目录中的一个文件,path2selfie.txt 中含有该目录下所有文件的绝对路径 |
定时每周三上午九点发送一张带有照片的嘟嘟:
1 | 0 9 * * 3 cd /root/miniconda/dogchan && /root/miniconda3/envs/mastbot/bin/python selfie.py >> /root/miniconda/dogchan/log/selfie_log.txt 2>&1 |
奇怪的报错
谷歌一圈,也在 Mastodon.py 提了 issue,还是没有解决。推测这个 bug 是我的站点设置造成的,但完全没有头绪究竟是哪里有问题,用 mstdn.social 的账号测试就没有问题。回看尝试 Node.js 放弃时的报错,很有可能也是同样的问题导致 API 报错,但已经懒得验证。
2022.08.08 更新
提的 issue 得到回复,确定是站点设置的问题。但作者不清楚是哪里出现问题,给出的建议是每当出现该报错就重建一次 streaming,但有可能丢失部分 notifications。
还有一个解决办法是每十分钟从上次读到的 notifications 并进行操作以实现自动回复。这种方法其实是 “伪自动回复”,因此需要设置定时任务,如每十分钟执行一次脚本。目前 DOGchan 使用这种方法实现自动回复。
将代码上传至 GitHub
之前的 CATsama 已经上传过一次,但这次上传还是完全不记得怎么搞,所以决定记录一下。
创建仓库
在 GitHub 创建新的仓库以存放代码。根据实际需要,为仓库添加 README.md
和 license
。创建完成后,在仓库右上角点击绿色的 Code
,复制相应链接。
密钥
可直接参考 生成新 SSH 密钥并添加到 ssh-agent
Personal access tokens
在 GitHub 创建 token 以便于后续代码上传时身份验证。点击个人头像 - Setting - Developer settings - Personal access tokens - Generate new token
,根据实际情况选择 token 的执行权限,完成后复制 token。
将创建的 Personal access tokens 整合到前述步骤复制的仓库链接中备用,具体格式如下:
1 | https://Personal_access_tokens@github.com/your_username/repository_name.git |
上传
在服务器上存放代码的目录下执行如下操作:
1 | # GitHub 默认分支已经改为 main,但 git init 的默认分支还是 master,这一步用于将 git 的默认分支改为 main |
此时刷新 GitHub 库的页面,即可看到新上传的内容。
DOGchan 的 GitHub 库:DOGchan:一个能够关键字触发自动回复的长毛象机器人
后记
整个搭建过程非常漫长,先是觉得油管教程很详细不可能有任何问题,但随着一步步搭建发现问题不少,而且由于对 node.js 完全不熟悉,连报错都看不懂,只能粘贴到谷歌搜索,但也不能得到很好的解决。又问了很多在象上拥有自动回复 bot 的象友,想参考一下,但大家的方法也不能完全适用。最后还是在 GitHub 一个个项目看过去 (感谢愿意开源的人们),找到了现在参考的这个方法。虽然也有不足,但是是目前确实能顺利运行一段时间的方法。接下来只需要思考为什么我的站点 streaming 不能长时间访问,修改好就能顺利运行。
总得来说,也算是一次很快乐的尝试。做这些小小的 project 比科研有趣多了!或许以后还会做这些有趣的小项目,快乐的同时还能丰富 GitHub 的库。
一开始这个 bot 只是为了让缪尚猫狗双全,但做着做着就想起家里的狗狗。在真实世界它已经返回汪星,但它在我自己搭建的赛博世界玩耍。因此从发嘟的照片和头像都用了狗狗的照片,就让它在我的咖啡馆继续做一只快乐小狗吧!