Automatically publishes Reddit moderation logs to a subreddit wiki page with modmail inquiry links.
- π 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
- Install dependencies
pip install praw
-
Create Reddit App
- Visit: https://www.reddit.com/prefs/apps
- Click "Create App" β Choose "script"
- Note
client_id
andclient_secret
-
Copy and edit config
cp config.template.json config.json
# Edit your credentials and subreddit info
- Test connection
python modlog_wiki_publisher.py --test
- Run
# Run once and exit
python modlog_wiki_publisher.py
# Run continuously
python modlog_wiki_publisher.py --continuous
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
}
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.
All configuration values are automatically validated and enforced within safe limits. Use --show-config-limits
to see current limits and defaults.
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.
The database will automatically migrate to the latest schema version on startup. Use --force-migrate
to manually trigger migration.
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...) |
Each subreddit gets its own log file under logs/
:
logs/
βββ yoursubreddit.log
Use --debug
to enable verbose output.
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-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
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');"
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
[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
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
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 |
MIT or GPLv3 (pick based on your repo)
PRs welcome. Include test runs and changes to CLI/help output.