Files
masto-rss/README.md
aserper f2056b90f2 Add comprehensive test suite with GitHub Actions CI/CD
- Refactor code into testable bot.py module with MastodonRSSBot class
- Create 20+ unit tests covering core functionality and edge cases
- Create 10+ integration tests for RSS parsing and Mastodon posting
- Add GitHub Actions workflow for automated testing
  - Unit tests on Python 3.10, 3.11, 3.12
  - Integration tests with mocked external services
  - Code quality checks (flake8, black, mypy)
  - Docker build validation
- Configure pytest with 80% minimum coverage requirement
- Add test dependencies in requirements-test.txt
- Update .gitignore to exclude test artifacts
- Add comprehensive TESTING.md documentation
- Add test status badge to README
- Maintain full backward compatibility with existing setup
2025-12-12 23:30:38 -05:00

6.9 KiB

Masto-RSS Header

Masto-RSS

Build Status Tests Docker Hub GHCR License: GPL v3 Python GitHub stars

A simple, lightweight Mastodon bot that automatically posts updates from RSS feeds to the Fediverse. Built with Python and designed to run seamlessly in Docker with multiarch support (amd64 & arm64).

Features

  • Automatically monitors RSS/Atom feeds and posts new items to Mastodon
  • Persistent state tracking to avoid duplicate posts
  • Configurable post visibility (public, unlisted, private, direct)
  • Lightweight Alpine-based Docker image
  • Multiarch support (amd64 & arm64) for broad compatibility
  • Continuous monitoring with configurable check intervals

Quick Start

The easiest way to run Masto-RSS is using the pre-built multiarch Docker images available on both Docker Hub and GitHub Container Registry.

Pull from Docker Hub

docker pull amitserper/masto-rss:latest

Pull from GitHub Container Registry

docker pull ghcr.io/aserper/masto-rss:latest

Run the Bot

docker run -d \
  --name masto-rss-bot \
  -e MASTODON_CLIENT_ID="your_client_id" \
  -e MASTODON_CLIENT_SECRET="your_client_secret" \
  -e MASTODON_ACCESS_TOKEN="your_access_token" \
  -e MASTODON_INSTANCE_URL="https://mastodon.social" \
  -e RSS_FEED_URL="https://example.com/feed.xml" \
  -e TOOT_VISIBILITY="public" \
  -e CHECK_INTERVAL="300" \
  -v /path/to/state:/state \
  amitserper/masto-rss:latest

Important: Use a bind mount for /state to persist the list of processed feed items across container restarts.

Using Docker Compose

Create a docker-compose.yml:

version: '3.8'

services:
  masto-rss:
    image: amitserper/masto-rss:latest
    # Or use GHCR: ghcr.io/aserper/masto-rss:latest
    container_name: masto-rss-bot
    restart: unless-stopped
    environment:
      MASTODON_CLIENT_ID: "your_client_id"
      MASTODON_CLIENT_SECRET: "your_client_secret"
      MASTODON_ACCESS_TOKEN: "your_access_token"
      MASTODON_INSTANCE_URL: "https://mastodon.social"
      RSS_FEED_URL: "https://example.com/feed.xml"
      TOOT_VISIBILITY: "public"
      CHECK_INTERVAL: "300"
    volumes:
      - ./state:/state

Then run:

docker-compose up -d

Configuration

All configuration is done via environment variables:

Variable Description Required Example
MASTODON_CLIENT_ID Mastodon application client ID Yes abc123...
MASTODON_CLIENT_SECRET Mastodon application client secret Yes xyz789...
MASTODON_ACCESS_TOKEN Mastodon access token Yes token123...
MASTODON_INSTANCE_URL URL of your Mastodon instance Yes https://mastodon.social
RSS_FEED_URL URL of the RSS/Atom feed to monitor Yes https://example.com/feed.xml
TOOT_VISIBILITY Post visibility level Yes public, unlisted, private, or direct
CHECK_INTERVAL Seconds between feed checks Yes 300 (5 minutes)

Getting Mastodon API Credentials

  1. Log into your Mastodon instance
  2. Go to SettingsDevelopmentNew Application
  3. Give it a name (e.g., "RSS Bot")
  4. Set scopes to write:statuses
  5. Save and copy the client ID, client secret, and access token

Building from Source

Build Locally

git clone https://github.com/aserper/masto-rss.git
cd masto-rss
docker build -t masto-rss .

Build Multiarch Images

# Set up buildx
docker buildx create --use

# Build for both architectures
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t yourusername/masto-rss:latest \
  --push \
  .

Running Without Docker

If you prefer to run the bot directly with Python:

# Clone the repository
git clone https://github.com/aserper/masto-rss.git
cd masto-rss

# Install dependencies
pip install -r requirements.txt

# Set environment variables
export MASTODON_CLIENT_ID="your_client_id"
export MASTODON_CLIENT_SECRET="your_client_secret"
export MASTODON_ACCESS_TOKEN="your_access_token"
export MASTODON_INSTANCE_URL="https://mastodon.social"
export RSS_FEED_URL="https://example.com/feed.xml"
export TOOT_VISIBILITY="public"
export CHECK_INTERVAL="300"

# Run the bot
python main.py

Note: When running without Docker, the bot stores its state in /state/processed_entries.txt. Make sure this directory exists or modify main.py to use a different path.

How It Works

  1. The bot fetches the RSS feed at regular intervals (defined by CHECK_INTERVAL)
  2. For each feed item, it checks if the item's URL has been processed before
  3. If the item is new, it posts to Mastodon with the format: {title}\n\n{link}
  4. The item URL is saved to prevent duplicate posts
  5. The process repeats indefinitely

Architecture

  • Base Image: Alpine Linux 3.18 (minimal footprint)
  • Python Version: 3.10+
  • Platforms: linux/amd64, linux/arm64
  • Dependencies: feedparser, mastodon.py (see requirements.txt)

State Persistence

The bot maintains state in /state/processed_entries.txt to track which feed items have already been posted. This prevents duplicate posts across restarts.

Important: Always mount /state as a volume to preserve this state file.

Contributing

Contributions are welcome! Feel free to:

  • Report bugs by opening an issue
  • Submit pull requests for improvements
  • Suggest new features or enhancements

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

Support

If you find this project useful, please consider giving it a star on GitHub!