YouTube Comment Moderator
Classify, reply to, and delete YouTube comments automatically using Gemini Flash + YouTube Data API v3.
Setup (Agent-Driven)
When a user wants to set up YouTube moderation, walk them through this conversationally. Do not tell them to run shell commands.
1. Collect Channel Info
Ask: "What's your YouTube channel URL or channel ID?"
Resolve it:
source .env
python3 scripts/fetch_comments.py --channel-id <ID> --max-videos 1 --max-comments 0
This validates the channel exists. If they give a URL like youtube.com/@handle, extract the handle and look up the channel ID via the API.
2. Check Environment Keys
Four keys are needed. Check which are missing:
echo "YOUTUBE_API_KEY=${YOUTUBE_API_KEY:+SET}"
echo "GEMINI_API_KEY=${GEMINI_API_KEY:+SET}"
echo "YT_MOD_CLIENT_ID=${YT_MOD_CLIENT_ID:+SET}"
echo "YT_MOD_CLIENT_SECRET=${YT_MOD_CLIENT_SECRET:+SET}"
For any missing keys, tell the user what to do (not how to run scripts):
- YOUTUBE_API_KEY: "Go to Google Cloud Console → Credentials, create an API key, and add
YOUTUBE_API_KEY=...to your.envfile." - GEMINI_API_KEY: "Go to Google AI Studio, create a key, and add
GEMINI_API_KEY=...to your.envfile." - YT_MOD_CLIENT_ID + YT_MOD_CLIENT_SECRET: These require OAuth setup. Walk them through
references/oauth-setup.mdconversationally, or summarize: "In Google Cloud Console, enable YouTube Data API, create an OAuth consent screen (External, Testing mode), add yourself as test user, create a Web Application OAuth client with redirect URIhttp://127.0.0.1:8976/callback, then add the Client ID and Client Secret to your.env."
After they confirm keys are added, restart the gateway so env vars reload.
3. OAuth Authorization
Generate the auth URL and send it to the user:
source .env && python3 scripts/setup.py --auth-url
Tell them: "Open this link, sign in with the Google account that owns your YouTube channel, and click Allow."
If user has a local browser (desktop): The script automatically catches the callback on http://127.0.0.1:8976/callback and saves the token. Tell them: "After clicking Allow, the browser should show a success page. You're done — I'll verify the token was saved."
If user is headless/remote (VPS, Telegram): Tell them: "After clicking Allow, your browser will redirect to a URL starting with http://127.0.0.1:8976/callback?code=.... That page won't load — that's expected. Copy ONLY the code parameter value from the URL (the part between code= and the next &), and paste just that code here. Do NOT paste the full URL — it contains sensitive auth data."
When they provide the code:
source .env && python3 scripts/setup.py --exchange-code "http://127.0.0.1:8976/callback?code=<CODE>"
⚠️ Security note: The OAuth code is single-use and expires in minutes, but avoid logging or echoing the full callback URL. If the user accidentally pastes a full URL in chat, exchange it immediately, then advise them the code is already consumed and useless.
4. Configure
Ask them conversationally:
- "What moderation mode? Auto (replies and deletes automatically), Approval (drafts everything for your review), or Monitor (classify and report only)?"
- "How do you typically talk to your audience? Casual? Professional? Funny?" (this sets voice_style)
- "Any common questions you get? I can pre-load answers so replies are accurate." (optional FAQ)
Then create the config:
python3 scripts/setup.py --create-config \
--channel-id <ID> \
--channel-name "<NAME>" \
--mode <approval|auto|monitor> \
--voice "<VOICE_STYLE>"
5. Test
Run a dry run and show them the results:
source .env && python3 scripts/moderate.py --all-videos --dry-run
Summarize: "Found X videos, Y new comments. Here's what I'd do: Z spam deleted, W questions answered, etc." Show a few examples.
6. Go Live
Once they approve:
source .env && python3 scripts/moderate.py --all-videos
Optionally set up a cron job to run every 15-30 minutes for ongoing moderation.
Scripts Reference
| Script | Purpose |
|---|---|
setup.py | Setup wizard (interactive or --auth-url / --exchange-code / --create-config) |
moderate.py | Main pipeline: fetch → classify → act. Also: --stats, --queue, --approve, --all-videos |
fetch_comments.py | Standalone comment fetcher (API key only) |
classify_comments.py | Standalone classifier (JSON in → JSON out) |
db.py | SQLite persistence layer |
Moderation Modes
- monitor — classify + report only (no OAuth needed)
- approval — drafts replies and queues deletions for review (
--queueto see,--approveto execute) - auto — auto-replies to questions, auto-deletes spam/hate
Classification Categories
| Category | Auto Action | Description |
|---|---|---|
| spam | delete | Promotional links, scam offers, bot text, self-promo |
| question | reply | Genuine question about video/creator/topic |
| praise | thank | Positive feedback, compliments |
| hate | delete | Hateful, abusive, harassing content |
| neutral | skip | Generic reactions, timestamps |
| constructive | flag | Thoughtful criticism, suggestions |
Architecture
- State: SQLite (
data/youtube-comment-moderator/moderator.db) - Classification: Gemini 2.0 Flash (~$0.001/comment)
- Read: YouTube Data API v3 (API key)
- Write: YouTube Data API v3 (OAuth)
- Deduplication: comment_id primary key, already-processed comments skipped
Environment Variables
Required:
YOUTUBE_API_KEY— YouTube Data API v3 key (free, 10K units/day)GEMINI_API_KEY— Gemini Flash for classification
For write operations (reply/delete):
YT_MOD_CLIENT_ID— Google OAuth client IDYT_MOD_CLIENT_SECRET— Google OAuth client secret
Optional overrides:
YT_MOD_DB— SQLite DB path (default:data/youtube-comment-moderator/moderator.db)YT_MOD_OAUTH— OAuth token path (default:skills/youtube-comment-moderator/oauth.json)YT_MOD_CONFIG— Config path (default:skills/youtube-comment-moderator/config.json)
OAuth Setup Details
See references/oauth-setup.md for the full step-by-step Google Cloud setup guide with screenshots-level detail and troubleshooting.