Skip to content

bakerboy448/RedditModLog

Repository files navigation

Reddit Modlog Wiki Publisher

Automatically publishes Reddit moderation logs to a subreddit wiki page with modmail inquiry links.

Features

  • πŸ“Š Publishes modlogs as organized markdown tables with unique content tracking IDs
  • πŸ“§ Pre-populated modmail links for removal inquiries (formatted as clickable markdown links)
  • πŸ—„οΈ SQLite database for deduplication and retention with multi-subreddit support
  • ⏰ Configurable update intervals with continuous daemon mode
  • πŸ”’ Automatic cleanup of old entries with configurable retention
  • ⚑ Handles Reddit's 524KB wiki size limit automatically
  • 🧩 Fully CLI-configurable (no need to edit config.json)
  • πŸ“ Per-subreddit log files for debugging and monitoring
  • πŸ”’ Configurable moderator anonymization (AutoModerator/HumanModerator)
  • πŸ“ Complete removal reason transparency - AutoModerator rule text, addremovalreason descriptions, all actual removal text (never generic messages or template numbers)
  • πŸ”— Links directly to actual content (posts/comments), never user profiles for privacy
  • πŸ†” Unique content IDs - comments show comment IDs, posts show post IDs for precise tracking
  • βœ… Multi-subreddit database support - single database handles multiple subreddits safely

Quick Start

  1. Install dependencies
pip install praw
  1. Create Reddit App

  2. Copy and edit config

cp config.template.json config.json
# Edit your credentials and subreddit info
  1. Test connection
python modlog_wiki_publisher.py --test
  1. Run
# Run once and exit
python modlog_wiki_publisher.py

# Run continuously
python modlog_wiki_publisher.py --continuous

Configuration

Create config.json:

{
  "reddit": {
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "username": "YOUR_BOT_USERNAME",
    "password": "YOUR_BOT_PASSWORD"
  },
  "source_subreddit": "YourSubreddit",
  "wiki_page": "modlog",
  "ignored_moderators": ["AutoModerator"],
  "update_interval": 300,
  "batch_size": 100,
  "retention_days": 30,
  "anonymize_moderators": true
}

Configurable via CLI

CLI Option JSON Key Description Default Min Max
--source-subreddit source_subreddit Subreddit to read and write logs required - -
--wiki-page wiki_page Wiki page name modlog - -
--retention-days retention_days Keep entries this many days 90 1 365
--batch-size batch_size Entries to fetch per run 50 10 500
--interval update_interval Seconds between updates in daemon mode 600 60 3600
--config – Path to config file config.json - -
--debug – Enable verbose output false - -
--show-config-limits – Show configuration limits and defaults false - -
--force-migrate – Force database migration false - -
--no-auto-update-config – Disable automatic config file updates false - -

CLI values override config file values.

Configuration Limits

All configuration values are automatically validated and enforced within safe limits. Use --show-config-limits to see current limits and defaults.

Automatic Config Updates

The application automatically updates your config file when new configuration options are added, while preserving your existing settings. A backup is created before any changes. Use --no-auto-update-config to disable this behavior.

Database Migration

The database will automatically migrate to the latest schema version on startup. Use --force-migrate to manually trigger migration.

Wiki Output

Sample wiki table output:

## 2025-08-09

| Time | Action | ID | Moderator | Content | Reason | Inquire |
|------|--------|----|-----------|---------|--------|---------|
| 08:15:42 UTC | removecomment | n7ravg2 | AutoModerator | [Comment by u/user123](https://www.reddit.com/r/opensignups/comments/1ab2cd3/title/n7ravg2/) | Possibly requesting an invite - [invited] Offers must be [O] 3x Invites to MyAwesomeTracker | [Contact Mods](https://www.reddit.com/message/compose?to=/r/opensignups&subject=Comment%20Removal%20Inquiry...) |
| 07:45:18 UTC | addremovalreason | 1ab2cd3 | Bakerboy448 | [Post title here](https://www.reddit.com/r/opensignups/comments/1ab2cd3/title/) | Invites - No asking | [Contact Mods](https://www.reddit.com/message/compose?to=/r/opensignups&subject=Removal%20Reason%20Inquiry...) |
| 06:32:15 UTC | removelink | 1xy9def | AutoModerator | [Another post](https://www.reddit.com/r/opensignups/comments/1xy9def/another/) | No standalone URL in post body | [Contact Mods](https://www.reddit.com/message/compose?to=/r/opensignups&subject=Post%20Removal%20Inquiry...) |

Logging

Each subreddit gets its own log file under logs/:

logs/
└── yoursubreddit.log

Use --debug to enable verbose output.

Command Line Options

python modlog_wiki_publisher.py [options]

Options:
  --config FILE            Path to config file (default: config.json)
  --source-subreddit NAME  Subreddit to read from and publish to
  --wiki-page NAME         Wiki page to update (default: modlog)
  --retention-days N       Days to keep processed entries
  --batch-size N           Number of modlog entries to fetch
  --interval N             Seconds between updates (daemon)
  --debug                  Enable debug logging
  --test                   Run a test and exit
  --continuous             Run continuously
  --force-modlog           Fetch ALL actions from Reddit API and rebuild wiki
  --force-wiki             Update wiki even if content appears unchanged
  --force-all              Do both --force-modlog and --force-wiki

Force Commands Explained

--force-modlog: Complete rebuild from Reddit

  • Fetches ALL recent modlog actions from Reddit API
  • Stores them in database
  • Rebuilds entire wiki page from database
  • Use when: Starting fresh, major updates, or troubleshooting

--force-wiki: Force wiki update only

  • Uses existing database data
  • Forces wiki update even if content hash matches
  • Use when: Format changes, modmail updates, or cache issues

--force-all: Complete refresh (replaces old --force)

  • Combines both --force-modlog and --force-wiki
  • Fetches from Reddit AND forces wiki update
  • Use when: Major changes, troubleshooting, or unsure which force to use
# Complete rebuild from Reddit API
python modlog_wiki_publisher.py --source-subreddit usenet --force-modlog

# Update wiki with current database data (bypass cache)  
python modlog_wiki_publisher.py --source-subreddit usenet --force-wiki

# Do both (equivalent to old --force)
python modlog_wiki_publisher.py --source-subreddit usenet --force-all

Database

Uses modlog.db (SQLite) for deduplication and history:

# View recent actions with removal reasons
sqlite3 modlog.db "SELECT action_id, action_type, moderator, removal_reason, subreddit, created_at FROM processed_actions ORDER BY created_at DESC LIMIT 10;"

# View all columns including removal reasons and target author
sqlite3 modlog.db "SELECT * FROM processed_actions ORDER BY created_at DESC LIMIT 10;"

# View actions by subreddit
sqlite3 modlog.db "SELECT action_type, moderator, target_author, removal_reason FROM processed_actions WHERE subreddit = 'usenet' ORDER BY created_at DESC LIMIT 5;"

# Track content lifecycle by target ID
sqlite3 modlog.db "SELECT target_id, action_type, moderator, removal_reason, datetime(created_at, 'unixepoch') FROM processed_actions WHERE target_id LIKE '%1mkz4jm%' ORDER BY created_at;"

# View removal reasons that are text (not numbers)
sqlite3 modlog.db "SELECT action_type, removal_reason FROM processed_actions WHERE removal_reason NOT LIKE '%[0-9]%' AND removal_reason != 'remove' LIMIT 5;"

# Clean manually
sqlite3 modlog.db "DELETE FROM processed_actions WHERE created_at < date('now', '-30 days');"

Database Schema

The database includes comprehensive moderation data with full transparency:

  • removal_reason column: Stores actual removal reason text from Reddit's API
    • AutoModerator actions: Full rule text (e.g., "Possibly requesting an invite - [invited] Offers must be [O]")
    • addremovalreason actions: Readable removal reason (e.g., "Invites - No asking") instead of template numbers
    • Manual removals: Moderator-provided text or rule details
  • target_author column: Actual usernames of content authors (never shows [deleted])
  • subreddit column: Multi-subreddit support with proper data separation
  • Unique content IDs: Comments show comment IDs (e.g., n7ravg2), posts show post IDs

Systemd Service (Optional)

[Unit]
Description=Reddit Modlog Wiki Publisher
After=network.target

[Service]
Type=simple
User=YOUR_USER
WorkingDirectory=/opt/RedditModLog
ExecStart=/usr/bin/python3 modlog_wiki_publisher.py --source-subreddit yoursubreddit --continuous
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl enable modlog-wiki
sudo systemctl start modlog-wiki

Permissions Required

Your bot account needs:

  • Moderator on the subreddit
  • Wiki edit permissions

Add the bot as a moderator or approved wiki contributor:

/r/<yoursubreddit>/wiki/settings/modlog

Troubleshooting

Issue Fix
Auth failed Check credentials, 2FA, use app password
Wiki denied Bot needs wiki mod or contributor access
Rate limiting Increase --interval and reduce --batch-size
Growing DB Lower --retention-days or run cleanup manually

License

MIT or GPLv3 (pick based on your repo)

Contributing

PRs welcome. Include test runs and changes to CLI/help output.

About

Maintain a Reddit Wiki page as a public modlog

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages