Level up your JSA experience.
A Discord bot that gamifies participation for the UF Japanese Student Association with an XP-based progression system, quests, leaderboards, and more.
Gamify JSA transforms club participation into an engaging RPG-like experience. Members earn XP by attending events, completing daily and weekly quests, and even playing Wordle. As they accumulate XP, they progress through ranks β from humble Newcomer all the way to Honorary JSA Board.
Officers can easily process event attendance through Google Sheets integration, and the bot automatically awards XP and updates member ranks. The quest system keeps members engaged between events with fun challenges verified by the officer team.
- Join the System β Members use
/joinwith their email to link their Discord account to the XP roster. - Attend Events β Officers process attendance sheets, and XP is automatically awarded to all attendees.
- Complete Quests β Daily and weekly quests are posted automatically. Submit proof and get officer approval for XP.
- Play Wordle β Paste your Wordle results with
/claim_wordleto earn bonus XP. - Climb the Ranks β Check your progress with
/xpand compete on the/leaderboard.
| XP Required | Rank |
|---|---|
| 0 | π± Newcomer |
| 50 | π Daiyo's Classmate |
| 150 | π€ Daiyo's Friend |
| 300 | π Daiyo's Pet |
| 500 | β JSA Regular |
| 750 | π JSA Otaku |
| 1050 | π Honorary JSA Board |
- XP & Rank System β Earn XP from events, quests, and Wordle. Automatically rank up as you progress.
- Event Processing β Officers paste a Google Sheets attendance URL and XP is awarded to all attendees instantly.
- Daily & Weekly Quests β Automated quest announcements with officer-verified submissions.
- Wordle Integration β Claim XP daily by sharing your Wordle results.
- Dual Leaderboards β Separate rankings for regular members and board members.
- Auto-Enrollment β New event attendees are automatically added to the roster.
- Duplicate Protection β Prevents double-processing of events and double-claiming of Wordle puzzles.
- Python 3.8+ β Core programming language
- Discord.py β Discord API wrapper with slash commands
- python-dotenv β Environment variable management
- Google Sheets API β Cloud-based data storage for rosters, quests, and logs
- gspread β Python client for Google Sheets
- google-auth β Service account authentication
- DigitalOcean Droplet β Ubuntu VPS for 24/7 hosting
- systemd β Process management and auto-restart
- Python 3.8+
- Discord Bot Token (Discord Developer Portal)
- Google Cloud Service Account with Sheets API enabled
- Google Sheet set up with required worksheets
-
Clone the repository:
git clone https://github.com/YOUR_USERNAME/Gamify_JSA.git cd Gamify_JSA -
Create and activate a virtual environment:
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies:
pip install -r requirements.txt
-
Set up environment variables:
Create a
.envfile in the root directory:DISCORD_TOKEN=your_discord_bot_token GOOGLE_SHEET_ID=your_google_sheet_id GUILD_NUM=your_discord_server_id
-
Add your Google Cloud service account credentials as
credentials.jsonin the root directory. -
Set up your Google Sheet with these worksheets:
Worksheet Purpose Master_RosterMember data (Name, Email, Year, Discord_ID, Total_XP, Rank, Board_Member) Attendance_LogsTracks processed event sheets (Event_ID, Timestamp, XP_Amount) Audit_LogsQuest approvals and manual XP (Message_ID, Timestamp, Officer_ID, Recipient_ID, XP_Amount, Reason) Daily_QuestsQuest Name, Description, Objective, Verification Method, Last_Used Weekly_QuestsSame structure as Daily_Quests Wordle_ClaimsPuzzle number, Discord_ID, Timestamp β prevents double claims Board_RosterList of board member emails (used by sync_board_members) -
Run the bot:
python bot.py
| Command | Description |
|---|---|
/join <email> |
Register your Discord account with the JSA XP system |
/xp |
Check your current XP and rank |
/leaderboard [type] [top] |
View the leaderboard (regular, board, or all members) |
/claim_wordle <share_text> |
Claim XP for completing Wordle (paste share text) |
/socials |
Get links to JSA social media (Instagram, Linktree, Calendar) |
/shota |
Learn about JSA's founder |
/help |
Show help info and list commands (officers see extra officer commands) |
| Command | Description |
|---|---|
/process_event <sheet_url> <xp_amount> |
Process an attendance sheet and award XP to attendees |
/test_quest <type> |
Post a test quest announcement to the quest channel |
/refresh_quest <type> |
Force a new daily or weekly quest announcement |
/post_specific_quest <type> <name> |
Post a specific quest by exact name from the sheet |
/award_xp <user> <xp_amount> <reason> |
Manually grant XP to a user (logged to Audit_Logs) |
/sync_board_members |
Sync Board_Member column from Board_Roster |
/grant_access_all |
Grant Battle Pass role to all current members (one-time use) |
Gamify_JSA/
βββ bot.py # Main Discord bot: commands, quest loops, reaction handlers
βββ config.py # Configuration and environment variables
βββ requirements.txt # Python dependencies
βββ credentials.json # Google Cloud service account (not in repo)
βββ .env # Environment variables (not in repo)
βββ sheets/
β βββ client.py # Google Sheets authentication (get_client)
β βββ actions.py # Sheet operations (see below)
βββ wordle/
βββ wordle_actions.py # Wordle share text parsing
| Function | Purpose |
|---|---|
calculate_rank, get_next_rank_info, generate_progress_bar |
Rank and XP progress display |
get_id_from_url, find_email_column, find_name_column |
Event sheet parsing |
is_event_processed, log_event_completion |
Event processing idempotency |
is_quest_processed, log_quest_approval, is_manual_xp_given |
Audit and duplicate prevention |
process_event_data |
Process attendance sheet, award XP, auto-enroll new attendees |
get_join, get_leaderboard, get_xp |
Member lookup and display |
award_quest_xp, grant_manual_xp |
Award XP (quest approval and manual) |
get_random_quest, get_specific_quest |
Quest selection from Daily_Quests / Weekly_Quests |
wordle_claim_exists, log_wordle_claim |
Wordle claim tracking |
check_if_board_member |
Sync Board_Member from Board_Roster |
Edit config.py to customize:
| Setting | Description |
|---|---|
DAILY_XP / WEEKLY_XP / WORDLE_XP |
XP rewards for different activities |
QUEST_CHANNEL_ID |
Channel for quest announcements |
DAILY_SUBMISSION_ID / WEEKLY_SUBMISSION_ID |
Channels for quest submissions |
OFFICER_ROLE / OFFICER_ROLE_ID |
Role required for admin commands |
APPROVE_EMOJI |
Emoji used to approve quest submissions (default: β ) |
The bot is deployed on a DigitalOcean Droplet running Ubuntu, managed with systemd for automatic restarts and boot persistence.
| Command | Description |
|---|---|
systemctl status jsabot |
Check if bot is running |
systemctl restart jsabot |
Restart the bot |
systemctl stop jsabot |
Stop the bot |
journalctl -u jsabot -f |
View live logs |
journalctl -u jsabot -n 100 |
View last 100 log lines |
cd ~/Gamify_JSA
git pull
systemctl restart jsabot- Discord.py β Discord API wrapper
- gspread β Google Sheets Python client
- DigitalOcean β Cloud hosting
- Cursor β AI-powered IDE
- Quest streak tracking with bonus XP
-
/profilecommand with detailed stats - Celebratory message for ranking up
- GitHub Actions for automated deployment
- Quest scheduling β Use time-based scheduling (e.g. 8:00 AM Eastern daily, Monday 8:00 AM weekly) so quests donβt re-post on bot restart and timing is consistent.
- Quest repetition β Add a cooldown (e.g. 7 days for daily, 4 weeks for weekly) so the same quest doesnβt appear 2β3 times in a week; prefer least-recently-used when the pool is small.
- Unit tests β Add pytest tests for
sheets/actions.py(rank/progress helpers,get_id_from_url, quest selection with mocks) and optionally CI (e.g. GitHub Actions) to run them.
Made with β€οΈ for the UF Japanese Student Association