This is a brief introduction about building an auto-reply Mastodon Bot with Python in 10 minutes.
Prerequests
Check your system
First of all, you need a server or a PC that has Linux system or WSL in Windows.
Open terminal and check python version. Please make sure your Python version number is higher than or equal to 3.8. and your pip version is as high as possible. Mine is 23.0.1.
Make an application
- Click ⚙ (Preferences) -> </> Development -> New application
- Name your application whatever you like
- Select read and write in Scopes
- Click SUBMIT
Now your have 3 strings: Client key
, Client secret
, and Your access token
.
Create a text file and name it as clientcred.secret
. Copy and paste the Client key
and Client secret
into the first and second line (The meaningless string!). The third line will be the api base url of your bot, such as https://mastodon.social .
Create another text file and name it as usercred.secret
. Copy and past the Your access token
into the first line (The meaningless string! Again!). The second line will be the api base url as well.
Install packages
Here are some necessary packages for the auto-reply bot. You can install them via those commands:
pip install Mastodon.py
pip install datetime
pip install html2text
If it is not working, try to replace pip
by pip3
.
It is time to Python
Create a text file called main.py
, put everything in it and run it by
python main.py
Make sure main.py
, usercred.secret
, clientcred.secret
are in the same folder.
Test if you can interact with your account
1 | from mastodon import Mastodon |
If you can see a new toot, you succeed.
Streaming
I recommend streaming API provided by Mastodon.py. If you can use it, try to use it. I failed. So I wrote this article XD.
Some useful information
You can check Full template without wasting any time.
If you want me to explain how to do…
It is a combination of Mastodon.notifications(mentions_only=True)
, Mastodon.notifications_dismiss(notification_id)
, and Mastodon.status_reply(to_status, status, in_reply_to_id=status_id)
. Putting all of them in a infinite loop, this bot will run forever. Do not forget to sleep every 1 second or 10 seconds. Be kind to the server of your Mastodon instance.
Get a mentions list
Basically you call Mastodon.notifications(mentions_only=True)
to get all mentions, put all mentions (15 mentions at a time) into a queue (list
in Python), then deal with them one by one in a for-loop.
The data structure of notifications dict
of dict
in Python. A notification has id
and status
as its keys. A status has id
, account
, mentions
etc. There are all kinds of information you need.
Here is an example of a notification
1 | { |
1 | status = notification['status'] # dict |
The text in obj[‘status’][‘content’] is HTML formated. You need to use BeautifulSoup
or html2text
to clean it. Or you can simply use RegExp to do the job. Some NLP techniques are necessary if you want to build a powerful auto-reply chat-bot.
Reply a status
Call Mastodon.status_reply(to_status, status, in_reply_to_id=status_id)
to reply to the status. The second status
could be a str
.
※ Remember to use try
, except
to avoid status not found error! If someone delete the toot before you reply, you will get this error. If you forget to catch this error, the program will crash.
Reply to not bot
Be aware of the bot account. You can find this info in account[‘bot’]. If this value is True
, be silent.
Finish a mention
If you read a mentions, call Mastodon.notifications_dismiss(notification_id)
to dismiss the mention. It guarantees this mention will not be reached next time. But you cannot find it either.
Run it in backend by Screen
- Create a bot environment
screen -S bot_env
- Detach current screen
Ctrl+A+D
- Check all screens and find the process id
screen -ls
- Enter bot_env
screen -r processid_of_bot_env
- Destroy a env
kill processid_of_bot_env
References
beloved caocao: https://github.com/TheTarr/mastodon_bot
Doc of Mastodon.py: https://mastodonpy.readthedocs.io/en/stable/
以下是方便阅读的中文版
一些准备工作
确认工作环境
首先你得有一台服务器或者闲置的 PC ,系统的话需要是 Linux 或者 Windows 有 WSL 或 WSL2 的环境。Powershell 似乎跑不起来某些 package。Python 的版本最好在3.8及以上,pip 的版本尽量新一些。亲测服务器默认的 Python 3.6 和 pip 9 是用不了的,会在安装相关 packages的过程中出现各种各样的问题。我用的是 Python 3.8 和 pip 23.0.1 供参考。
申请一个毛象的 application
- 选 ⚙ (Preferences) -> </> 开发 -> 新增应用之类的文字在右上角
- 设置一下应用的名称 发送的时候会显示的
- 把 范围 里 read 和 write 勾起来
- 保存修改
你会看到生成了3个长长的字符串乱码,分别是“客户端的key”,“密钥”和你的token。创建一个名为clientcred.secret
的文本文件,第一行存储客户端的key,第二行存储客户端密钥,第三行存你的实例url 例如 https://mastodon.social 。再创建一个名为 usercred.secret
的文本文件,第一行存你的token,第二行也存你的实例 url。文件名本身不重要,能把 client 和 user 区分开就行,后面要用。
安装必要的 packages
使用 pip
命令安装这些 packages ,如果不管用,试试用 pip3
:
pip install Mastodon.py
pip install datetime
pip install html2text
这个 bot 主要依赖的就是 Mastodon.py 这个 package 来实现各种功能,它应该是把相关的接口都用 Python 封装了一下方便调用。详情请看上面的参考链接。
开始写 Python 吧
创建一个名为 main.py
的文件用来放你的代码,在终端这样执行它:
python main.py
方便起见,请把 main.py
, usercred.secret
, clientcred.secret
这三个文件放在一个文件夹下。
试试用 Python 嘟一次
执行如下命令
1 | from mastodon import Mastodon |
中间的 client_id
和 access_token
换成你的两个文件的文件名就行。成功执行的话应该能在你的主页里看到一条新嘟,内容就是 ‘Tooting from Python using #mastodonpy !’。
Streaming
Mastodon.py 这个 package 其实提供了 Streaming 的功能,可以监听你主页的各种动态。如果你非常地原教旨,或者追求优雅地代码,或者你可以跑通它,请优先使用它。我虽然也有这样的追求,但是因为实在是执行不了,反复遇到 urllib3 这个包相关的错误,最后放弃了,琢磨出了后面的这一套东西。所以才有了这一篇博客。如果你看到这里转头就去试了并成功了,那你很棒棒哦!
源码和少许原理的讲解
假如你是一个心急的人,可以直接从 这里 跳去看模板的源码。因为是模板所以不保证能跑通。
如果你想看讲解的话就继续看下去……
这个方案的基本逻辑是使用 Mastodon.notifications(mentions_only=True)
, Mastodon.notifications_dismiss(notification_id)
, Mastodon.status_reply(to_status, status, in_reply_to_id=status_id)
这三个函数来实现整个功能。换句话说就是无数次地依次执行“查看提到我的内容列表”,“挨个回复内容”,“把列表里我回复过的内容删掉”这三个动作。需要注意的是加上sleep函数,让它不要执行得太频繁,不然可能你的实例会限制你的刷新次数之类的……不愿再说亲测了
获取提到我的内容列表
执行一次 Mastodon.notifications(mentions_only=True)
可以获得最多15个mentions,把它存到一个队列里,然后用 for 循环挨个获取里面的 notifacation,再处理。处理完再调用一次上面那个函数获得15个 mentions……
notification
的数据结构就是 dict
的多重嵌套. 一个 notification
的 key 会包含 id
和 status
等. 一个 status
的 key 又会包含 id
, account
, mentions
等等。因此所有的信息都可以通过 dict
相关的操作提取出来。以下是一个简化的例子:
1 | { |
1 | status = notification['status'] # dict |
其中我们最关心的嘟文存在 obj['status']['content']
里,它的结构是一个 HTML 树. 嫌麻烦的话你可以用 BeautifulSoup
or html2text
里的一些函数去解析它,不嫌麻烦的话你也可以自己写一个正则表达式把它 sub 掉。提取到嘟文之后要怎么回复就看你的了。
回复一个嘟
调用这个函数来回复: Mastodon.status_reply(to_status, status, in_reply_to_id=status_id)
to reply to the status. 这里面的 status
可以是一个字符串。第一个 to_status
就是你要回复的那个 status ,它是个 dict
。
※ 有时候等你回复的时候原始的那条嘟已经被删掉了,这时候系统就会给你抛出一个嘟文不存在的 error。 所以这边要注意多用 try: except
,不然你的进程会挂掉的。
不要给 bot 回复
想当年……总之为了避免出现两个 bot 无限聊天的危机事件,记得在代码中加上这样的判断。一个账号如果是 bot 的话它的 account['bot'] == True
。
已读
如果已经对一个嘟执行完了操作,调用 Mastodon.notifications_dismiss(notification_id)
把这个 mention 忽略掉。这样能保证你下次再查看 notifacations 的时候就看不到它了。但是这样一来你即使在网页版里打开自己的 notifacations 列表也看不到它了,除非你从自己的回复里看。目前也没有更优雅的办法标记已读了就这样吧……我不想在本地写一个文件。
后台执行这个文件
就是 Screen 的基础用法这样…… nohup 理论上也可以,看你自己喜好吧
- Create a bot environment
screen -S bot_env
- Detach current screen
Ctrl+A+D
- Check all screens and find the process id
screen -ls
- Enter bot_env
screen -r processid_of_bot_env
- Destroy a env
kill processid_of_bot_env