Skip to main content

Munibot

Tests

Munibot is a friendly Mastodon bot that posts aerial or satellite imagery of administrative regions (tipically municipalities).

munis_cat_scaled

It is written in a modular way so it's easy to customize to different data sources, via the implementation of profiles.

It currently powers the following Mastodon accounts:

  • @munibot_es: All municipalities in Spain, shown in random order, with base aerial ortophotograhy from PNOA IGN.

  • @munibot_cat: All municipalities in Catalonia, shown in random order, with base aerial ortophotograhy from ICGC.

  • @communebot: All communes in France, shown in random order, with base aerial ortophotograhy from IGN.

Here's how a sample post looks like:

example_post

Table of Contents

Usage

Installation

Munibot is available on PyPI and can be installed with pip. It is strongly recommended to install it in a virtual environment:

python3 -m venv munibot
source munibot/bin/activate

pip install munibot

Or alternatively, using pipx:

pipx install munibot

Munibot uses Rasterio and Fiona, which require GDAL. The wheels installed by pip on Linux (and macOS, although I have not tested it) include binaries for GDAL that cover munibot's need so it doesn't need to be installed separately. On other operating systems you might need to install GDAL.

Configuration

Munibot uses an ini file for configuration. You can download the sample ini file included in this repository running:

curl https://raw.githubusercontent.com/amercader/munibot/main/munibot.sample.ini -o munibot.ini

or:

wget https://raw.githubusercontent.com/amercader/munibot/main/munibot.sample.ini -O munibot.ini

Running it

Once munibot is installed, you should be able to run

munibot --help

Munibot assumes that the configuration ini file is located in the same folder the command is run on (and named "munibot.ini"). If that's not the case, you can pass the location of the configuration file with the --config or -c arguments:

munibot -c /path/to/munibot.ini

If at least a profile is available and all the necessary authorization tokens are available in the ini file (see Mastodon setup) just run the following to post a new image:

munibot post <profile-name>

If you only want to create the image without posting it use the create command:

munibot create <profile-name>

Deploying it

You don't need much to run munibot, just a system capable of running Python >= 3.6. Once installed, you probably want to schedule the sending of posts at regular intervals. An easy way available on Linux and macOS is cron. Here's an example configuration that you can adapt to your preferred interval and local paths (it assumes munibot was installed in a virtualenv in /home/user/munibot):

# Post an image every 8 hours (~3 times a day)
0 */8 * * * /home/user/munibot/bin/munibot --c /home/user/munibot/munibot.ini post cat >> /home/user/out/cat/munibot_cat.log 2>&1

You can adjust the log level in the munibot ini configuration file.

Writing your own profile

Munibot is designed to be easy to customize to different data sources in order to power different bot accounts. This is done via profile classes. Profiles implement a few mandatory and optional properties and methods that provide the different inputs necessary to generate the posts. Munibot takes care of the common functionality like generating the final image and sending the post.

To see the actual methods that your profile should implement check the BaseProfile class in munibot/profiles/base.py. Here's a quick overview of what you should provide:

  • The geometry of the boundary of a particular administrative unit (given an id). This can come from any place that can end up providing a GeoJSON-like Python dict: an actual GeoJSON file, PostGIS database or a WFS service.
  • The base image (aerial photography or satellite imagery) covering the extent of the administrative unit (given the extent). WMS services work really well for this as they allow to retrieve images of arbitrary extent and size.
  • The text that should go along with the image in the post. Generally the name of the unit, plus some higher level unit for reference.
  • A method that defines the id of the next unit that should be posted.
  • Optionally, the latitude and longitude that should be added to the post.

Once you've implemented your profile class you can register using the munibot_profiles entry point in your package setup.py file:

"munibot_profiles": [
	"<profile_id>=<your_package>.profiles.:<YourProfileClass>",
]

You can check the examples included in this repository, in the munibot/profiles directory.

Mastodon setup

Each bot runs on its own dedicated account:

  1. Create an account in your server of choice. Set up mastodon_account_name and mastodon_api_base_url accordingly in the ini file. The latter should be the mastodon server host (e.g. "mastodon.social").
  2. Go to Settings > Development and click "New application"
  3. Add the bot name, and select the profile, write:statuses and write:media scopes. Submit to create
  4. Click on the just created app, the "Your access token" value is the value you need to use for mastodon_access_token in the ini file.

Development installation

Clone the repo and install the requirements:

git clone https://github.com/amercader/munibot.git
pip install -r requirements.txt
pip install -r dev-requirements.txt

To run the tests:

pytest

With coverage:

pytest -v --cov=munibot --cov-report term-missing

License

MIT

Release files for munibot 0.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for munibot 0.0.7
File Size Uploaded
munibot-0.0.7.tar.gz 19.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for munibot 0.0.7
File Interpreter ABI Platform
munibot-0.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 42.5 kB

Release files / munibot-0.0.7.tar.gz

Download URL munibot-0.0.7.tar.gz
Size 19.5 kB
Tags Source
SHA-256 checksum
How to use checksums
53d4cf3bfa80b415e0bbb4faae0dcfb4ce554fd227d5ae41c8ba7ccb82817b70
BLAKE2b-256 checksum
How to use checksums
a82fa1e9d91f6bf3208a30215a717567cc4c3e8283f32ae14bb6ea9b527d81f9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 21, 2025.

Transparency log

Release files / munibot-0.0.7-py3-none-any.whl

Download URL munibot-0.0.7-py3-none-any.whl
Size 23.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1cf811fbca83f90bb9f8156affd973b359aac0c6c83b1bf9b7ec247dcad2d0ce
BLAKE2b-256 checksum
How to use checksums
fa866cc133b85f90137f29438a93a50584b69b33c93cfbaf205ebaff8da58bfb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 21, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.7 This release

2 release files

0.0.5

1 release file

0.0.4

1 release file

0.0.3

1 release file

0.0.2

1 release file

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page