# tootapalooza

Python program to fill a mastodon timeline with randomized toots. If you want to see what this creates, have a look at the [local timeline on always.grumpy.world](https://always.grumpy.world/public/local).

The idea is to generate some somewhat realistic looking users, posts, interactions, etc. This will help fill up a local timeline and provide test data and a playground in which to try new features. I built this because I want to test a few functions that would look at the raw, underlying database on a mastodon instance. But I need to get some data into that database so that I can see what it looks like.

# Setting up a Dev environment

You need:
1. Administrator access to a Mastodon server. Part of this runs the admin CLI tool.
2. Python 3.9 or later

## 1. Python prep

1. Check out the code. 
2. cd to the repository.
3. Build it and install it in your working environment.
    1. `python3 -m venv .venv`
    2. `. .venv/bin/activate`
    3. `pip install -r requirements.txt`
    4. Assuming your current working directory is the root of this repository, install into your build environment with `pip install -e .`
4. Copy the `example.env` file to a file named `.env` in the root of this repo.
5. Edit that `.env` file to contain all the secrets!

## 2. Initialise your Mastodon app

This is a one-time thing you do ever. First time you go to run the bot in a new environment where it hasn't run before.

1. Find `tootapalooza/__init__.py` and edit it
2. Edit the lines to uncomment them and change any values you need to (like app name and server)
3. Run it one time (e.g., `python __init__.py`). It should just exit, creating the file.
4. Edit the file and comment the lines out again. You just do that once.

## 3. Getting your fleet of users to run

Follow the instructions for unning [the server-util make-users.py](server-util/README.md). You'll copy that onto your mastodon server, run it once to generate a `users.toml` file that contains plaintext user names and passwords for your test users, and then copy that file to where you want it to run. 

You do that just once.

Then copy the `users.toml` file to the location where you have checked out `tootapalooza`.

# Running

Install the `tootapalooza` command into your path so you can invoke it. Run `pip install -e .`

You need to run this in a location that can make API calls to your mastodon instance. I say it this way because you might have a load balancer, a private network, etc. so that running this ON the mastodon server itself isn't desirable. There is no reason to run this directly on the mastodon server. You can, but there's no compelling reason to do that. It makes API calls over the public Internet.

Assuming everything is up to date, all your files initialised with correct values, you can just run `tootapalooza --once users.toml`. Every user in your `users.toml` file will pick a random action and do one random action.

## Weights and random actions

If you look in the `random_interactions()` method, you'll see a table of weights. (Example shown below). Those weights are fed into Python's [random.choices()](https://docs.python.org/3/library/random.html#random.choices) function and that's how it picks the actions to take. In the example below, the weights sum to 33. `unfollow_random()` has a weight of 1, so it has a 1 in 33 (3%) chance of happening. Whereas `reply_random_local` has a weight of 4, so it has a 4 in 33 (12%) chance of happening. Adjust the weights to get the blend of traffic you want. If you don't want an action to happen at all, set its weight to 0.
```
interactions = {
    self.reply_random_local:      4,
    self.reply_random_home:       4,
    self.reply_random_public:     4,
    self.follow_random_local:     2,
    self.unfollow_random:         1,
    self.toot_plain_public:       1,
    self.toot_tagged_public:      4,
    self.toot_plain_unlisted:     1,
    self.favourite_random_local:  2,
    self.favourite_random_home:   2,
    self.favourite_random_public: 2,
    self.boost_random_local:      2,
    self.boost_random_home:       2,
    self.boost_random_public:     2,
    self.report_random_local:     0
}
```

# Future plans

I intend to make this a multi-threaded daemom that will sleep a little bit, wake up and do a few random actions, go back to sleep, etc. One thread per user, with a bit of randomness on the sleep times. It will just run in the background, generating test data slowly over time.