Skip to content
/ Zam Public

A Telegram/Twitter Bot for posting tweets to Telegram channels

License

Notifications You must be signed in to change notification settings

AminAlam/Zam

Repository files navigation


Zam


built with Python3 uv Docker PostgreSQL

Zam: A Telegram Bot for capturing and posting tweets to Telegram channels

This program is dedicated to Roohollah Zam. He was an Iranian activist and journalist. Zam played a high-profile role in the 2017–2018 Iranian protests, to which he devoted special coverage at the time. In June 2020, an Iran court found him guilty of "corruption on earth" for running a popular anti-government forum, which officials said had incited the 2017–2018 Iranian protests. He was sentenced to death by the regime court and was executed on 12 December 2020.

Roohollah Zam

Table of contents


Overview

Zam is a Telegram bot that captures tweets as screenshots and allows admins to schedule them for posting to a Telegram channel. It uses a priority-based queue system where admin requests are processed before user suggestions.

Note: Looking for the Twitter API version? The legacy code that uses the Twitter/X API (Tweepy) is available in the legacy branch. This version uses screenshot capture instead, as the Twitter API became restricted/expensive after the X acquisition.


Features

Core Features

  • 📸 Tweet Screenshot Capture: Captures tweets as high-quality screenshots using headless Chrome with full Persian/Arabic font support
  • 🔄 Priority Queue System: Admin tweets are processed before user suggestions
  • Smart Auto-Scheduling: Intelligent scheduling algorithm with peak hour optimization and minimum gap enforcement
  • 🐳 Docker Containerized: Easy deployment with Docker Compose
  • 🗄️ PostgreSQL Database: Reliable data storage with connection pooling
  • 👥 Multi-Bot Architecture: Separate bots for admins and user suggestions
  • 🚦 Rate Limiting: Configurable hourly limits for user suggestions
  • 🇮🇷 Persian Calendar Support: Displays dates in Persian/Jalali calendar

Admin Bot Features

  • 📊 Monitoring Dashboard (/stats): Real-time statistics including queue status, scheduled posts, and peak hour availability
  • Manual & Auto Scheduling: Choose specific times or let the smart algorithm pick optimal slots
  • 📈 Visual Progress Bars: See hourly slot availability at a glance

Suggestions Bot Features

  • 🎯 Interactive Menu: User-friendly button-based navigation
  • 📤 Tweet Submission: Easy tweet URL submission with queue position feedback
  • 💬 Categorized Feedback: Users can send suggestions, bug reports, or questions to admins
  • 📊 Submission Tracking: Users can view their remaining hourly submissions

Installation

Using Docker (Recommended)

  1. Clone the repository

    git clone https://github.com/AminAlam/Zam.git
    cd Zam
  2. Configure environment variables

    cp .env.example .env

    Edit .env with your credentials (see Configuration section).

  3. Build and start the containers

    docker compose up --build -d
  4. View logs

    docker compose logs -f app
  5. Stop the application

    docker compose down

Manual Installation (Development)

This project uses uv for fast, reliable Python package management.

  1. Install uv (if not already installed)

    # macOS/Linux
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
    # Or with Homebrew
    brew install uv
    
    # Or with pip
    pip install uv
  2. Clone the repository

    git clone https://github.com/AminAlam/Zam.git
    cd Zam
  3. Install dependencies

    # Install all dependencies (including dev)
    uv sync
    
    # Or without dev dependencies
    uv sync --no-dev
  4. Install Chromium (required for tweet-capture)

    # Ubuntu/Debian
    sudo apt-get install chromium chromium-driver
    
    # macOS
    brew install chromium
  5. Set up PostgreSQL database

    # Create database and run init.sql
    psql -U postgres -c "CREATE DATABASE zam_db;"
    psql -U postgres -d zam_db -f src/database/init.sql
  6. Configure environment variables

    cp .env.example .env
    # Edit .env with your credentials
  7. Run the application

    uv run python -m src.main

Common uv Commands

# Sync dependencies from lockfile
uv sync

# Add a new dependency
uv add <package>

# Add a dev dependency  
uv add --dev <package>

# Update all dependencies
uv lock --upgrade

# Run any command in the virtual environment
uv run <command>

# Run tests
uv run pytest

# Run the linter
uv run ruff check .

Configuration

Create a .env file in the project root with the following variables:

Database Configuration

DB_HOST=db              # Use 'localhost' for manual installation
DB_PORT=5432
DB_USER=zam
DB_PASSWORD=your_secure_password
DB_NAME=zam_db

Telegram Bot Tokens

Get bot tokens from @BotFather on Telegram.

ADMIN_TELEGRAM_BOT=your_admin_bot_token
SUGGESTIONS_TELEGRAM_BOT=your_suggestions_bot_token

Telegram Channel/Chat IDs

Get chat IDs by forwarding a message from the channel to @userinfobot.

MAIN_CHANNEL_CHAT_ID=your_main_channel_id
ADMIN_CHAT_ID=your_admin_chat_id
SUGGESTIONS_CHAT_ID=your_suggestions_chat_id

Channel Info

CHANNEL_NAME=@YourChannelName
ADMIN_IDS=admin1,admin2,admin3    # Telegram usernames without @

Usage

Command Line Options

uv run python -m src.main --help

Usage: main.py [OPTIONS]

  Zam: A Telegram Bot for posting tweets in a Telegram channel

Options:
  --time_diff TEXT              Difference between server time and target 
                                timezone. Format: HOURS:MINUTES (default: 3:30)
  --mahsa_message BOOLEAN       Enable Mahsa Amini memorial timer message
  --reference_snapshot BOOLEAN  Include snapshots of quoted/replied tweets
  --num_tweets_to_preserve INTEGER RANGE
                                Number of tweets to keep in database [500-5000]
  --user_tweet_limit INTEGER RANGE
                                Hourly limit per user for suggestions [0-120]
                                Set to 0 for unlimited
  --help                        Show this message and exit

Docker with Options

# Run with custom options
docker compose run app uv run python -m src.main --time_diff 3:30 --user_tweet_limit 5

Bot Commands

Admin Bot:

  • Send a tweet URL (twitter.com or x.com) to add it to the queue
  • /start - Start the bot
  • /queue - View current queue status
  • /stats - View comprehensive channel statistics:
    📊 Channel Statistics
    
    📝 Queue Status:
       • Pending captures: 3
       • Currently processing: 1
    
    📅 Scheduled Posts:
       • Awaiting posting: 8
       • Next post: 20:15 (in 12 min)
    
    📈 Today's Activity:
       • Posts sent: 24
    
    ⏰ Next 6 Hours Availability:
    20:00 ████████░░ 4/6
    21:00 ██████░░░░ 3/6
    22:00 ██░░░░░░░░ 1/6
    23:00 ░░░░░░░░░░ FULL
    

Suggestions Bot:

  • /start - Open the interactive menu with options:
    • 📤 Submit Tweet: Send a tweet URL to suggest for the channel
    • 💬 Send Feedback: Send a message to admins (categorized as suggestion, bug report, or question)
    • 📊 My Remaining Submissions: Check your hourly submission limit status

How It Works

  1. Submit a Tweet: Send a tweet URL to either the admin or suggestions bot
  2. Queue Processing: The tweet is added to a priority queue (admin tweets have higher priority)
  3. Screenshot Capture: A background worker captures the tweet as a screenshot
  4. Admin Review: The captured tweet is sent to the admin channel with scheduling options
  5. Schedule or Post: Admins can schedule the tweet manually or use Auto timing for smart scheduling
  6. Channel Posting: At the scheduled time, the tweet is posted to the main channel

Smart Auto-Scheduling

The "Auto timing" feature uses an intelligent algorithm to schedule tweets:

  • Peak Hour Optimization: More tweets are scheduled during high-engagement hours (8 PM - 1 AM)
  • Quiet Hour Reduction: Fewer tweets during low-activity hours (2 AM - 6 AM)
  • Minimum Gap Enforcement: Ensures at least 5 minutes between consecutive tweets
  • Next-Day Rollover: Automatically schedules for tomorrow if today's slots are full

Hour Weight Distribution:

Period Hours Relative Weight
Quiet 2-6 AM Low (0.3x)
Morning 7-11 AM Medium (0.7x)
Afternoon 12-7 PM Normal (0.8x)
Evening 8-10 PM High (1.5x)
Night 11 PM-1 AM High (1.3x)

Architecture

┌─────────────────────────────────────────────────────────┐
│                    Docker Compose                        │
│  ┌─────────────────────────────────────────────────┐    │
│  │         App Container (uv + Python 3.11)         │    │
│  │  ┌─────────────┐  ┌─────────────────────────┐   │    │
│  │  │ Admin Bot   │  │ Suggestions Bot         │   │    │
│  │  └──────┬──────┘  └───────────┬─────────────┘   │    │
│  │         │                     │                  │    │
│  │         └──────────┬──────────┘                  │    │
│  │                    ▼                             │    │
│  │         ┌─────────────────────┐                  │    │
│  │         │   Queue Worker      │                  │    │
│  │         │  (Priority-based)   │                  │    │
│  │         └──────────┬──────────┘                  │    │
│  │                    ▼                             │    │
│  │         ┌─────────────────────┐                  │    │
│  │         │   Tweet Capture     │                  │    │
│  │         │  (Headless Chrome)  │                  │    │
│  │         └─────────────────────┘                  │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │           PostgreSQL Container                   │    │
│  │  ┌─────────────────────────────────────────┐    │    │
│  │  │  Tables: tweets, tweet_queue, states,   │    │    │
│  │  │  tweets_line, errors, user_feedback     │    │    │
│  │  └─────────────────────────────────────────┘    │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

Project Structure

Zam/
├── pyproject.toml          # Project configuration & dependencies
├── uv.lock                 # Lockfile for reproducible builds
├── .python-version         # Python version specification
├── Dockerfile              # Docker build with uv
├── docker compose.yml      # Container orchestration
├── src/                    # Main application code
│   ├── main.py             # Entry point
│   ├── telegram_backend.py # Telegram bot handlers
│   ├── twitter_backend.py  # Tweet capture & queue
│   ├── utils.py            # Utility functions
│   ├── ocr.py              # OCR text extraction
│   ├── migrations.py       # Database migrations
│   └── database/           # Database module
│       ├── database.py     # Database operations
│       └── init.sql        # Schema definitions
├── tweetcapture/           # Local tweet screenshot package
│   ├── pyproject.toml      # Package configuration
│   └── tweetcapture/       # Package source
└── tests/                  # Test suite

Testing

Running Tests Locally

# Run all unit tests
uv run pytest tests/ -m "not integration and not slow"

# Run with coverage
uv run pytest tests/ --cov=src --cov-report=html

# Run integration tests (requires Chrome/Chromium)
uv run pytest tests/test_integration.py -m "integration"

# Run all tests
uv run pytest

Test Structure

  • tests/test_twitter_backend.py - URL parsing, queue management tests
  • tests/test_utils.py - Utility function tests
  • tests/test_database.py - Database operation tests
  • tests/test_integration.py - End-to-end integration tests

GitHub Actions

Tests run automatically on pull requests with the following workflow:

  1. Approval Gate: PRs require manual approval before tests run (protects against malicious code)
  2. Unit Tests: Fast tests that don't require external services
  3. Integration Tests: Tests with PostgreSQL and Chrome for screenshot capture
  4. Docker Build: Verifies the Docker image builds correctly

The test suite uses Jack Dorsey's first tweet (https://x.com/jack/status/20) as a stable reference for screenshot capture tests.


License

This project is open source and available under the MIT License.

About

A Telegram/Twitter Bot for posting tweets to Telegram channels

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages