Awesome
MXToot - Matrix-Mastodon bot written on java.
Overview
Usage
Requirements:
- openjdk 8 (openjdk 9, 10 don't supported, I need time to test it).
Run application service
Command:
java -jar mxtoot-X.X.X.jar check mxtoot.yaml
will check you configuration in the mxtoot.yaml file.
Command:
java -Xmx100m -jar mxtoot-X.X.X.jar server mxtoot.yaml
will run the application service.
An example mxtoot.service file is provided for systemd usage with mxtoot
home user.
Invite a bot
Invite a bot with unique mxid like '@mxtoot_clientapp:homeserver.url' where
- homeserver.url is a homeserver which attached to the applicatin service.
- clientapp is a name of the mastodon application.
It is important that the name of the bot be unique. You can do this by choose unique clientapp (for example, your mastodon's username).
Application service will create the bot and join it to the invited room. Also user who sent invite will be a owner of the bot.
Registration bot in the Mastodon.
To start registration flow use command !reg <mastodon.url>
where first parameter is a mastodon url.
Bot will answer with a url to authorize in the mastodon. Please open this url, login into your account
and authorize new application. After this copy the authorization code and execute command
!auth <authorization.code>
After this you can enable your home stream by command !timeline auto
,
post new messages !toot Hello, World!
, reply to messages !reply <status_id> text
,
boost messages !boost <status_id>
, setup format of the messages, ...
Also owner can rejoin bot to a new room by command !join <room_id>
.
To delete bot execute command !leave
. If bot detects that it doesn't exist in any rooms it will
send deactivate request to the homeserver and delete itself in the application service.
Registration
Each application service should me registered on the homeserver via registration file. There is an example how to register mxtoot:
# unique identifier of the application service
id: "mxtoot"
# url of the application service
url: "https://app.me:8443"
# token AS will add to requests to HS
as_token: "EapiSh7h"
# token token HS will add to requests to AS
hs_token: "tah6Zoox"
# This is a field which denotes the user_id localpart when using the AS token
sender_localpart: "mxtoot"
namespaces:
users: # List of users we're interested in
- exclusive: true
regex: "@mxtoot_.*"
rooms: [] # List of aliases we're interested in
aliases: [] # List of room ids we're interested in
Certificate
Application service can use certificates stored in pkcs12 file (at current moment) to work under secure connection (https).
To convert pem-based certificates to pkcs12 you can use next command:
openssl pkcs12 -export -inkey privkey.pem -in fullchain.pem -out mxtoot.pkcs12
where privkey.pem and fullchain.pem are private key and certificate with public key and all parent certificates. You can use certificates from Lets Encrypt.
Configuration
There is only an one configuration yaml-file which include all settings.
homeserverUrl
Url of the matrix homeserver. For example "https://matrix.org:8448"
displayName
Initial bot's displayName. If command is enabled it is possible to change this name. Can be invoked only by owner. For example, "mxtoot".
prefix
Initial command's prefix. If command is enabled it is possible to change prefix. Can be invoked only by owner. For example, "!".
DO NOT USE "/". This character is internal used by Web Riot and all commands with "/" prefix will be invoked only by Riot not bot. Workaround ro execute commands: place one or more spaces before prefix.
Also there is a special placeholder {{display_name}} which will be replaced by current bot's name. You can set prefix as "{{display_name}}:" and all commands should be execute by bot's mention. For example, "mxtoot: help".
commands
There is a list of all enabled commands described by command's class. See more.
runState
There are two run states: APPLICATION_SERVICE and STANDALONE.
In STANDALONE mode each of the bots will run in separated thread and receive events from /sync request like a common client.
In APPLICATION_SERVICE mode bots wont'be run in threads and will receive events only from application service via /transaction endpoint. This state is recommended because reduces load of the homeserver.
strictMode
May be true
or false
.
When Application service receive events via /transaction endpoint it will validate event.
When strictMode is enabled if unknown field is found application service will throw exception and stop it process.
When strictMode is disabled it will skip event's validations and all unknown fields will be ignored.
postFormat
replyFormat
boostFormat
mentionFormat
favouriteFormat
followFormat
Initial template of the post, reply, boost, mention, favourite and follow messages which come from Mastodon. To create messages uses jmustache library, it is another java implementation of the logic-less templating engine mustache.
For example, how you can define template:
postFormat: >
<hr/>[{{id}}]: <a href="{{url}}">{{url}}</a>:<br/>
{{account.acct}} at {{created_at}} wrote:<br/>
{{content}}
When bot receive message from the Mastodon it fill all placeholders {{value}}
by values and write
the message to the room.
So, portFormat describe how display general toots from the Mastodon, replyFormat - replies,
boostFormat - boost/reblog messages.
Available placeholders:
Notification
Attribute | Description | Nullable |
---|---|---|
id | The notification ID | no |
type | One of: "mention", "reblog", "favourite", "follow" | no |
created_at | The time the notification was created | no |
account | The Account sending the notification to the user | no |
status | The Status associated with the notification, if applicable | yes |
Status
Attribute | Description | Nullable |
---|---|---|
id | The ID of the status | no |
uri | A Fediverse-unique resource ID | no |
url | URL to the status page (can be remote) | yes |
account | The Account which posted the status | no |
in_reply_to_id | null or the ID of the status it replies to | yes |
in_reply_to_account_id | null or the ID of the account it replies to | yes |
reblog | null or the reblogged Status | yes |
content | Body of the status; this will contain HTML (remote HTML already sanitized) | no |
created_at | The time the status was created | no |
emojis | An array of Emoji | no |
reblogged | Whether the authenticated user has reblogged the status | yes |
favourited | Whether the authenticated user has favourited the status | yes |
sensitive | Whether media attachments should be hidden by default | no |
spoiler_text | If not empty, warning text that should be displayed before the actual content | no |
visibility | One of: public , unlisted , private , direct | no |
media_attachments | An array of Attachments | no |
mentions | An array of Mentions | no |
tags | An array of Tags | no |
application | Application from which the status was posted | yes |
If fetch statuses is enabled then add next fields:
Attribute | Description | Nullable |
---|---|---|
in_reply_to | full origin Status in replies messages | yes |
in_replay_to_account | full origin Account in replies messages | yes |
Account
Attribute | Description | Nullable |
---|---|---|
id | The ID of the account | no |
username | The username of the account | no |
acct | Equals username for local users, includes @domain for remote ones | no |
display_name | The account's display name | no |
locked | Boolean for when the account cannot be followed without waiting for approval first | no |
created_at | The time the account was created | no |
followers_count | The number of followers for the account | no |
following_acount | The number of accounts the given account is following | no |
statuses_count | The number of statuses the account has made | no |
note | Biography of user | no |
url | URL of the user's profile page (can be remote) | no |
avatar | URL to the avatar image | no |
header | URL to the header image | no |
Emoji
Attribute | Description | Nullable |
---|---|---|
shortcode | The shortcode of the emoji | no |
static_url | URL to the emoji static image | no |
url | URL to the emoji image | no |
Attachment
Attribute | Description | Nullable |
---|---|---|
id | ID of the attachment | no |
type | One of: "image", "video", "gifv", "unknown" | no |
url | URL of the locally hosted version of the image | no |
remote_url | For remote images, the remote URL of the original image | yes |
preview_url | URL of the preview image | no |
text_url | Shorter URL for the image, for insertion into text (only present on local images) | yes |
Mention
Attribute | Description | Nullable |
---|---|---|
url | URL of user's profile (can be remote) | no |
username | The username of the account | no |
acct | Equals username for local users, includes @domain for remote ones | no |
id | Account ID | no |
Tag
Attribute | Description | Nullable |
---|---|---|
name | The hashtag, not including the preceding # | no |
url | The URL of the hashtag | no |
Application
Attribute | Description | Nullable |
---|---|---|
name | Name of the app | no |
website | Homepage URL of the app | yes |
dateTimeFormat
Defines how display date and time from all Mastodon's messages. See more on the https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html in the Section "Patterns for Formatting and Parsing".
dateTimeLocale
Defines locale of the localized date terms in the dateTimeFormat template.
For example, you can set dateTimeFormat: "MMM, dd, yyyy"
and dateTimeLocale: "ru"
. Then date
will be rendered as Май, 02, 2018
because the Russian locale was defined.
fetchMissingStatuses
May be true
or false
.
Also there are a lot of dropwizard's settings. You can check it in the corresponding page.
Because synapse doesn't work with zipped requests it need to disable zipping. And increase timeouts to avoid a lot of timeout errors in the /sync request (in STANDALONE run mode).
jerseyClient:
gzipEnabled: false
gzipEnabledForRequests: false
chunkedEncodingEnabled: false
timeout: 20s
Commands
There are two command's categories: commands which can be invoked only by owner (who invited bot) and commands which can be invoked as access policy configured (everyone or only owner).
Access policy is configured by command SetAccessPolicy
To use commands you should list all available commands (class names) in the command
setting
in the configuration file.
io.github.ma1uta.matrix.bot.command.Leave
Leave current room. If bot isn't available in any rooms it will delete itself.
io.github.ma1uta.matrix.bot.command.NewName
Set new name.
io.github.ma1uta.matrix.bot.command.Pong
Just pong.
io.github.ma1uta.matrix.bot.command.SetAccessPolicy
Set or show access policy. All commands are divided into two categories: commands which can be invoked only by owner (who invited bot) or category which is set by this command.
Possible values: OWNER or ALL.
io.github.ma1uta.matrix.bot.command.Join
Rejoin to a new room. Bot will leave from old room.
io.github.ma1uta.matrix.bot.command.Prefix
Set or show command prefix, override the prefix setting.
io.github.ma1uta.matrix.bot.command.DefaultCommand
Set default command. If invoked unknown commands or entered some text it would invoke the default command.
For example, if invoke !default toot
every message will be tooted into the Mastodon.
io.github.ma1uta.matrix.bot.command.Help
Show all commands.
io.github.ma1uta.mxtoot.matrix.command.RegisterMastodonClient
Start registration flow.
Syntax: !reg mastodon.server.tld
where mastodon.server.tld is you mastodon server (mstdn.jp,
mastodon.social, etc.)
io.github.ma1uta.mxtoot.matrix.command.AuthorizeMastodonClient
Validate auth code.
io.github.ma1uta.mxtoot.matrix.command.Timeline
Start or stop timeline. Bot create connection to the streaming resource and will receive all new messages.
Possible value: on
, off
, auto
(autorestart after application service's restart).
io.github.ma1uta.mxtoot.matrix.command.Public
Post a new public message to the Mastodon.
io.github.ma1uta.mxtoot.matrix.command.Private
Post a new private message to the Mastodon.
io.github.ma1uta.mxtoot.matrix.command.Unlisted
Post a new unlistedpublic message to the Mastodon.
io.github.ma1uta.mxtoot.matrix.command.Direct
Post a new direct message to the Mastodon.
io.github.ma1uta.mxtoot.matrix.command.Reply
Reply to the message from Mastodon. The reply has the same visibility (public, private, unlisted, direct) as the origin.
io.github.ma1uta.mxtoot.matrix.command.FetchStatuses
Some messages from Mastodon has only identifier of the statuses or accounts. If this parameter is true
then bot will retrieve this statuses or accounts by id.
io.github.ma1uta.mxtoot.matrix.command.Format
Set or show post, reply or boost message templates.
io.github.ma1uta.mxtoot.matrix.command.Boost
Boost(reblog) message.
io.github.ma1uta.mxtoot.matrix.command.Follow
Follow to somebody.
io.github.ma1uta.mxtoot.matrix.command.Unfollow
Unfollow.
io.github.ma1uta.mxtoot.matrix.command.Mute
Mute somebody.
io.github.ma1uta.mxtoot.matrix.command.Unmute
Unmute.
io.github.ma1uta.mxtoot.matrix.command.Block
Block somebody.
io.github.ma1uta.mxtoot.matrix.command.Unblock
Unblock.
io.github.ma1uta.mxtoot.matrix.command.Followers
Show followers of the specified user id.
io.github.ma1uta.mxtoot.matrix.command.Following
Show followings of the specified user id.
Compile
To build you need jdk 8 (oracle or openjdk) and apache maven 3.5.2 or higher.
- clone repository
git clone https://gitlab.com/ma1uta/mxtoot
cd mxtoot
- build common modules and mxtoot
mvn clean package
Don't hesitate to contact me in the #mxtoot:matrix.org room. :-)