kensanata / trunk

A web app to maintain publi lists of fediverse accounts
GNU Affero General Public License v3.0
3 stars 0 forks source link

Trunk for Mastodon

Trunk allows you to follow a bunch of people in order to get started with Mastodon. Mastodon is a free, open-source, decentralised microblogging network.

Issues, feature requests and all that: use the Software Wiki.

Table of Contents

Logo

Logo kindly donated by Jens Reuterberg.

API

There's a simple API right now.

Getting the lists

GET /trunk/api/v1/list

This returns a list of strings. Each of these strings is a list name.

Example:

curl https://communitywiki.org/trunk/api/v1/list

Getting the accounts in a list

GET /trunk/api/v1/list/:name

This returns a list of objects. Each of these objects has the following attribute:

Needless to say, the list name has to be encoded appropriately.

Example:

curl https://communitywiki.org/trunk/api/v1/list/Information%20Technology

Get the queue

GET /trunk/api/v1/queue

You will get back a list of objects with the following attributes:

The oldest items in the queue come first.

Add to the queue

POST /trunk/api/v1/queue

You need to pass the following parameters:

Remove from the queue

DELETE /trunk/api/v1/queue

You need to pass along an object with the following attribute:

Installation

If you want to install it, you need a reasonable Perl installation. If this is your only Perl application you're developing, I'm not going to bother telling you about Perlbrew, which allows you to install multiple versions of Perl, or the use of cpanm instead of cpan. I'm just going to assume you have a system with Perl installed.

If you can, install Perl modules using your package manager. Otherwise, use cpan to install them. You can mix and match, but if you use cpan it will pull in all the dependencies using cpan and ignore the package manager. Since most likely there are unpackaged modules, you always end up using cpan. It might not be worth the time to search all the modules using your package manager (or use cpan2deb to turn missing modules from CPAN into Debian packages, for example).

If these modules get installed into ~/perl5 then you need to make sure ~/perl5/bin is in your PATH and that /perl5/lib/perl5 is in your PERL5LIB. At the end of my ~/.bashrc, for example:

PATH="${HOME}/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="${HOME}/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;

You should now be able to run the web application. From the working directory, start the development server:

morbo trunk.pl

This allows you to make changes to trunk.pl and check the result on localhost:3000 after every save.

Configuration

The keys to set:

Example setup:

{
  users => {
    alex => 'Holz',
  },
  uri => 'http://localhost:3000',
  dir => '/home/alex/src/trunk',
  bot => 'trunk@botsin.space',
}

Deployment

Once you are ready to deploy there are various options. The simplest option is to just start it as a daemon, but listening to a different port:

perl trunk.pl daemon --listen "http://*:8080"

The next option you have is to use a tool called hypnotoad which should have come with one of the dependencies you installed. This defaults to port 8080, so you're good:

hypnotoad trunk.pl

If you change the file, you can restart it gracefully with zero downtime by simply running the same command again.

Hypnotoad writes a PID into the hypnotoad.pid file so in order to kill the server, use the following:

kill $(cat hypnotoad.pid)

Ideally, you would be running the application on your server using Hypnotoad and use Apache in front of it. Here's an example site configuration from my /etc/apache2/sites-enabled directory. Here's what it does:

<VirtualHost *:80>
    # all HTTP gets redirected to HTTPS
    ServerName communitywiki.org
    ServerAlias www.communitywiki.org
    Redirect permanent / https://communitywiki.org/
</VirtualHost>
<VirtualHost *:443>
    # all traffic to www gets redirected to the same site without www
    ServerName www.communitywiki.org
    Redirect permanent / https://communitywiki.org/
    SSLEngine on
    SSLCertificateFile      /var/lib/dehydrated/certs/communitywiki.org/cert.pem
    SSLCertificateKeyFile   /var/lib/dehydrated/certs/communitywiki.org/privkey.pem
    SSLCertificateChainFile /var/lib/dehydrated/certs/communitywiki.org/chain.pem
    SSLVerifyClient None
</VirtualHost>
<VirtualHost *:443>
    # this is the real server
    ServerAdmin alex@communitywiki.org
    ServerName communitywiki.org
    DocumentRoot /home/alex/communitywiki.org

    # block Mastodon and others from fetching preview images and bringing my server down
    RewriteEngine on
    RewriteCond "%{HTTP_USER_AGENT}" "Mastodon" [OR]
    RewriteCond "%{HTTP_USER_AGENT}" "Pcore"
    RewriteRule ".*" "-" [redirect=403,last]

    # same as above; this uses dehydrated to manage certificates by Let's Encrypt
    SSLEngine on
    SSLCertificateFile      /var/lib/dehydrated/certs/communitywiki.org/cert.pem
    SSLCertificateKeyFile   /var/lib/dehydrated/certs/communitywiki.org/privkey.pem
    SSLCertificateChainFile /var/lib/dehydrated/certs/communitywiki.org/chain.pem
    SSLVerifyClient None

    # this is the web application we care about
    ProxyPass /trunk            http://communitywiki.org:8080

</VirtualHost>

Actually, if you want to run multiple applications, they each need to listen on a different port, or you make them listen for a different mount point.

Assume you change the Apache config file above to end with the following:

    # with a mount point
    ProxyPass /trunk            http://communitywiki.org:8080/trunk

Then create a new Mojolicious application which does nothing else but use the Mount plugin to mount trunk.pl under /trunk:

use Mojolicious::Lite;
plugin Mount => {'/trunk' => './trunk.pl'};
app->start;

Now start this file instead of trunk.pl using hypnotoad and it should still work.

Troubleshooting

If you're seeing the barfing Tyrannosaurus Rex or the "raptor not found" message, that means that Trunk has run into an error. Your best option is to run the server using morbo and repeat whatever you did. When running with morbo, you should get better error output in your browser and a backtrace in the morbo output.

Translation

If you want to translate the application, there are two things you need to do.

First, you want to translate the Markdown files. These are the files that can be edited via the admin interface via Describe a listSpecial descriptions.

Second, you want to translate all the templates that are included at the end of trunk.pl in the __DATA__ section. In order to do that, run the following command:

perl trunk.pl inflate

This generates external copies of all the template files. Check the new templates folder. All the files ending in .html.ep can be translated and take precedence over the templates stored inside trunk.pl. This is how you can translate the templates and still install a new copy of trunk.pl.

Queue Bot

The Trunk interface has a queue which can be fed using the API. One way of doing that involves a bot. This bot is written in Python. Assuming you have a Python 3 installation, here's how to install the prerequisites:

pip3 install Mastodon.py
pip3 install html2text
pip3 install requests

First, create a bot account and set everything up

Mastodon provides a UI for all of this. Just go to your settings and under the "developer" menu there is a place to create a new app and get your credentials all in one go. We've set up trunk@botsin.space for us.

Got to Settings → Development and create a new application.

  1. give it the name of your Trunk instance
  2. use the URL for your Trunk instance
  3. don't change the default URI
  4. we need read:notifications, read:statuses, write:notifications, and write:statuses
  5. submit
  6. click on the link to your application

You need to save the three codes you got as follows:

The Client Key and Client Secret go into the first file, each on a line of its own. The filename is <account>.client, for example trunk@botsin.space.client.

Example content:

1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890

The Access Token goes to a separate file called <account>.user, for example trunk@botsin.space.user.

Example content:

7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456

Finally, invoke it

You need to invoke the bot with the user account it should check and the URL for the Trunk instance to use, and the admin username and password on that trunk instance.

This is what I do:

./bots.py trunk@botsin.space https://communitywiki.org/trunk trunk '*secret*'

Do this from a cronjob once an hour or so, and it should work:

  1. it checks for new notifications
  2. if they look like Trunk requests, they're added to the queue

Test

The unit tests are simple. The following runs all the tests in the t directory.

prove t

Create the bot on an instance and save the credentials in the *.client and *.user files as instructed above.

Create a list:

touch Test.txt

Start the server locally:

morbo trunk.pl

Use your favorite account (I'm going to use kensanata@octodon.social) and send a message to the bot (I'm going to use trunk@botsin.space):

@trunk Please add me to Test.

If you're logged in with your bot account, you should get a notification.

Run the bot, using your bot account and a username and password from your trunk.conf:

python3 bot.py trunk@botsin.space http://localhost:3000 alex Holz

Check that the bot dismissed the notification by reloading the web UI of your bot account.

Check that the bot added your request to the queue by visiting http://localhost:3000/queue

In the queue, click the OK button.

You should see the following:

The account kensanata@octodon.social was added to the following lists: Test

You should also see that the bot replied to your original request:

@kensanata Done! Added you to Test. 🐘