A Discord bot that manages community engagement for the vVv project. It tracks member activity across crusade channels, validates submissions via emoji reactions, syncs everything to Google Sheets, sends grouped welcome messages, and acts as an AI-powered guide that answers questions about vVv.
Tracks every member that joins the server in a Google Sheet (Discord_Data) with the following columns:
| Column | Field | Description |
|---|---|---|
| A | Join Date | Timestamp of when the member joined |
| B | Discord ID | Unique numeric Discord ID |
| C | Discord Handle | Username |
| D | Role Check | Whether they have the target role (TRUE/FALSE) |
| E | Message Sent | Whether they have sent at least one message (TRUE/FALSE) |
| F | Holder Column | Whether they hold one of the NFT/asset roles |
| G | Member Left | Whether they have left the guild |
Columns D, E, F, G are refreshed every 6 minutes by the role-check task.
Members submit "crusade" entries by posting in one of the designated channels. An entry is only counted as valid when an authorized user reacts to it with one of the approved custom emoji IDs. This stops spam and gives moderators control over what counts.
3. Monthly Activity Sheets https://docs.google.com/spreadsheets/d/1tGOXOQnUWIFz9liYOu2n5OSoGN6yAYbQqVkuXrFlxGo/edit?gid=384067431#gid=384067431
- A new Google Sheet tab is created each month, copied from a
Templatetab (e.g.April 2025,May 2025). - Reserved area (A3:C) stores per-channel stats: channel name, unique participants, total entries.
- Side area (E3 onward) logs every valid submission: timestamp, user, ID, channel.
- Bottom area (A16 onward) stores per-user upload counts.
- Stats are written live as new submissions come in.
- On startup, the bot backtracks the last 30 days so any uploads it missed while offline are still counted.
A multi-tier system designed to keep members posting weekly:
- Regular reminder — sent to users who miss 2 consecutive weekly updates.
- Chronic defaulter — flagged after 4 weeks of inactivity; messages sent at most once every 4 weeks.
- Auto-removal — after 49 missed updates, the user is removed from tracking.
- Counters reset at the start of every new month.
The bot listens in the main channel and uses OpenAI (gpt-4o-mini) to answer questions about vVv.
- Vanilla greetings (
gm,hello,morning, etc.) get a hardcoded reply — no API call, no token cost. - Everything else is sent to OpenAI with:
- A system prompt that pins the bot's identity and forbids off-topic replies.
- The project context loaded from
info.txt. - The last 10 messages of conversation history (sliding window).
- Replies use short paragraphs, bullet points, and clean formatting.
Instead of spamming a welcome per new member, joins are queued and flushed every 5 minutes into a single message:
GFM @user1, @user2, @user3
Welcome to vVv.
Get tokens before they launch.
.
├── bot.py # Entry point — Discord client, event handlers, task scheduling
├── reminders.py # Reminder logic, defaulter tiers, monthly stats aggregation
├── sheet.py # Google Sheets read/write, caching, monthly tab creation
├── welcome.py # Grouped welcome message queue and sender task
├── vVv_info.py # OpenAI client and project-context loader (reads info.txt)
├── info.txt # vVv project context fed to the LLM (create this yourself)
└── sheet_key.json # Google service account credentials (DO NOT commit)
discord.py
gspread
oauth2client
openai>=1.0.0
DISCORD_TOKEN=<your discord bot token>
OPENAI_API_KEY=<your openai api key>sheet_key.json— Google service account credentials. Create via Google Cloud Console → IAM & Admin → Service Accounts. Share the target spreadsheet with the service account email.info.txt— Plain-text vVv project context. Read fresh on every query so edits take effect without restarting.
| File | Variable | What it is |
|---|---|---|
bot.py |
CHANNEL_ID |
Main chat channel |
bot.py |
YOUR_GUILD_ID |
Your Discord server ID |
bot.py |
TARGET_ROLE_ID |
Role tracked in column D |
bot.py |
ADDITIONAL_ROLE_IDS |
Holder/NFT role IDs for column F |
reminders.py |
CRUSADE_CHANNEL_IDS |
Designated upload channels |
reminders.py |
REMINDER_CHANNEL_ID |
Where reminder pings are sent |
sheet.py |
SHEET_ID |
Google Sheet ID (from the URL) |
python bot.py