aserper 15409ff4e1 Refactor integration tests to use feedparser mocking
Replace responses library HTTP mocking with direct feedparser.parse()
mocking to eliminate XML parsing compatibility issues. All integration
tests now mock feedparser output directly, avoiding HTTP layer complexity.

Changes:
- Replace responses.activate decorators with feedparser.parse patches
- Mock feed objects directly instead of mocking HTTP responses
- Remove responses library dependency from requirements-test.txt
- Simplify test setup by eliminating XML string encoding issues

This approach provides more reliable testing by directly controlling
feedparser behavior rather than relying on HTTP mocking layer.
2025-12-12 23:43:07 -05:00
2023-12-06 13:03:19 -05:00
2024-01-04 20:03:56 -05:00

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!

Description
A Mastodon bot that posts RSS updates to a Mastodon account
Readme GPL-3.0 486 KiB
Languages
Python 97.5%
Dockerfile 2.5%