-
Notifications
You must be signed in to change notification settings - Fork 0
feat: vibes branch consolidation (48 commits) #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b39eedd
a585179
b9e0e71
3d9560c
b4bfe4f
ec6b295
b38bf7e
2285098
3f935f7
4521518
9db4117
2662ec6
a66fc30
943ff33
e4b1a41
3a2b26e
0868c87
1cc7e09
7c4ce64
6d9f78f
27c6b2a
a473211
8f0fa3b
2590ccc
dd62526
9d6ddcb
053f8bf
4b9df06
262db56
8c48d33
76f7fd3
9e01a39
df5ad91
bc0e0d6
3949ec3
d16e916
effc9cd
dde11cf
9e279d7
7186292
74cdc40
1769052
893cb8a
ac2bd14
1ec3f9a
2d39cb8
6d2d4de
a56a858
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,14 +4,19 @@ Automatically publishes Reddit moderation logs to a subreddit wiki page with mod | |||||||||
|
|
||||||||||
| ## Features | ||||||||||
|
|
||||||||||
| * 📊 Publishes modlogs as organized markdown tables | ||||||||||
| * 📧 Pre-populated modmail links for removal inquiries | ||||||||||
| * 🗄️ SQLite database for deduplication and retention | ||||||||||
| * ⏰ Configurable update intervals | ||||||||||
| * 🔒 Automatic cleanup of old entries | ||||||||||
| * ⚡ Handles Reddit's 524KB wiki size limit | ||||||||||
| * 📊 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 | ||||||||||
| * 📁 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 | ||||||||||
|
|
||||||||||
|
|
@@ -67,33 +72,52 @@ Create `config.json`: | |||||||||
| "ignored_moderators": ["AutoModerator"], | ||||||||||
| "update_interval": 300, | ||||||||||
| "batch_size": 100, | ||||||||||
| "retention_days": 30 | ||||||||||
| "retention_days": 30, | ||||||||||
| "anonymize_moderators": true | ||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| ### Configurable via CLI | ||||||||||
|
|
||||||||||
| | CLI Option | JSON Key | Description | Default | | ||||||||||
| | -------------------- | ------------------ | -------------------------------------- | ------------- | | ||||||||||
| | `--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 | `30` | | ||||||||||
| | `--batch-size` | `batch_size` | Entries to fetch per run | `100` | | ||||||||||
| | `--interval` | `update_interval` | Seconds between updates in daemon mode | `300` | | ||||||||||
| | `--config` | – | Path to config file | `config.json` | | ||||||||||
| | 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: | ||||||||||
|
|
||||||||||
| ```markdown | ||||||||||
| ## 2025-01-15 | ||||||||||
| ## 2025-08-09 | ||||||||||
|
|
||||||||||
| | Time | Action | Moderator | Content | Reason | Inquire | | ||||||||||
| |------|--------|-----------|---------|--------|---------| | ||||||||||
| | 14:25:33 UTC | removepost | ModName | [Post Title](url) | spam | [Contact Mods](modmail_url) | | ||||||||||
| | 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 | ||||||||||
|
|
@@ -122,20 +146,76 @@ Options: | |||||||||
| --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 | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| # 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: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| # View recent actions | ||||||||||
| # 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;" | ||||||||||
|
|
||||||||||
|
Comment on lines
+200
to
+202
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
SQLite's If the intent is "no digits", use a 📝 Proposed fix-# 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;"
+# View removal reasons that contain no digits (text-only reasons)
+sqlite3 modlog.db "SELECT action_type, removal_reason FROM processed_actions WHERE removal_reason NOT GLOB '*[0-9]*' AND removal_reason != 'remove' LIMIT 5;"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| # 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) | ||||||||||
|
|
||||||||||
| ```ini | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documented defaults are stale and disagree with code/README.
CONFIG_LIMITSinmodlog_wiki_publisher.pysetsretention_days=90,batch_size=50,update_interval=600, and the table inREADME.md(lines 86–88) reflects those. The values listed here (30,100,300) match the pre-refactor defaults and will mislead operators.📝 Proposed fix
As per coding guidelines: "Always update commands and flags in documentation".
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 65-65: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents