A complete tournament management system for Magic: The Gathering Arena tournaments. Fetches tournament data, calculates league points, and automatically updates Google Sheets.
✅ Easy Copy-Paste URLs - Paste tournament URLs directly from your browser ✅ Tournament Data Fetching - Retrieves MTGA tournament data via GWT-RPC protocol ✅ League Points Calculator - Automatic points calculation based on placement ✅ Google Sheets Integration - Auto-updates player scores, prize pools, and history ✅ One-Click OAuth Login - Automatic Google login for both MTGA and Sheets ✅ Hebrew Support - Fully supports Hebrew player names ✅ Champion Events - 2× points multiplier for special tournaments ✅ Cross-Platform - Works on Windows, Linux, and macOS ✅ Interactive Mode - User-friendly prompts for easy operation ✅ Idempotent Updates - Prevents duplicate tournament processing
# Create virtual environment
python3 -m venv venv
# Activate (Linux/Mac)
source venv/bin/activate
# Activate (Windows)
venv\Scripts\activate
# Install requirements
pip install -r requirements.txtOption A: Automatic Google Login (Recommended)
# Linux/Mac
./login.sh
# Windows
login.batThis will open a browser where you login with Google, then automatically save your SACSID.
Option B: Manual SACSID Get your SACSID cookie from https://mtgarena.appspot.com:
- Open DevTools (F12) → Application → Cookies
- Copy the SACSID value
# Linux/Mac
./update_sacsid.sh YOUR_SACSID_HERE
# Windows
update_sacsid.bat YOUR_SACSID_HEREInteractive Mode:
# Linux/Mac
./process_tournament.sh
# Windows
process_tournament.batCommand Line:
# Linux/Mac
./process_tournament.sh <tournament_url_or_id> <encoded_id> --update-sheets
# Windows
process_tournament.bat <tournament_url_or_id> <encoded_id> --update-sheetsSupported URL Formats:
- Full URL:
https://mtgarena.appspot.com/#t4651297216135168 - Hash format:
#t4651297216135168 - Short format:
t4651297216135168 - Numeric ID:
4651297216135168
# Using full URL (easy copy-paste from browser)
./process_tournament.sh https://mtgarena.appspot.com/#t4651297216135168 QhlSGUAAA
# Using numeric ID
./process_tournament.sh 4651297216135168 QhlSGUAAA./process_tournament.sh https://mtgarena.appspot.com/#t4651297216135168 QhlSGUAAA --update-sheets./process_tournament.sh #t4651297216135168 QhlSGUAAA --update-sheets --championThe MTGA API requires a GWT-encoded tournament ID. To get it:
- Visit the tournament page in your browser
- Open DevTools (F12) → Network tab
- Find the POST request to
/arena/tournament - Click Payload tab
- Copy the value before the last
|(e.g.,QhlSGUAAA)
The script provides human-readable tournament results:
======================================================================
TOURNAMENT RESULTS & LEAGUE POINTS
======================================================================
Tournament: RTMS Pokemon Tourny Oct 18
Format: Limited: Draft
Players: 20
Player Placement Points Earned
----------------------------------------------------------------------
Jake P #1 +5 points
Chase C #2 +4 points
Carson B #3 +2 points
William F #4 +2 points
...
Prize Pool Increment: +100 NIS
======================================================================
- All players: +1 participation point
- 1st place: +4 bonus points (total: 5)
- 2nd place: +3 bonus points (total: 4)
- 3rd-4th: +1-2 bonus points (based on player count)
- 5th-8th: +1 bonus point (if 21+ players)
- Champion events: All points doubled
- Prize pool: 5 NIS per player
To enable automatic sheets updates, choose one option:
-
Create OAuth credentials:
- Go to Google Cloud Console
- Create project → Enable Google Sheets API
- Create OAuth 2.0 Client ID (Desktop app)
- Download as
client_secret.json
-
Run setup:
./venv/bin/python3 setup_google_sheets.py
This opens a browser for authorization and saves credentials.
-
Configure
.env:SPREADSHEET_KEY=your_spreadsheet_key_here
- Create Service Account in Google Cloud Console
- Download JSON as
service_account.json - Share your Sheet with the service account email
- Configure
.envas above
TopDeckProject/
├── process_tournament_complete.py # Main processor script
├── process_tournament.sh # Linux/Mac wrapper
├── process_tournament.bat # Windows wrapper
├── fetch_tournament_simple.py # Standalone fetcher
├── parse_tournament_url.py # URL/ID parser
├── google_login.py # Automated SACSID extraction
├── setup_google_sheets.py # OAuth setup for Sheets
├── login.sh / login.bat # Google login wrappers
├── update_sacsid.sh / .bat # Cookie updater
├── test_tournament.sh # Test script
├── mtga_fetch.py # GWT-RPC utilities
├── league_logic.py # Points calculation
├── sheets_io.py # Google Sheets I/O
├── name_match.py # Fuzzy name matching
├── app.py # FastAPI server (optional)
├── requirements.txt # Python dependencies
├── QUICK_START_GUIDE.md # Quick reference
├── WINDOWS_GUIDE.md # Windows-specific guide
└── SOLUTION_SUMMARY.md # Technical documentation
See WINDOWS_GUIDE.md for detailed Windows-specific instructions, including:
- Python installation
- Virtual environment setup
- Batch file usage
- Troubleshooting
The project includes an optional REST API for automation:
# Linux/Mac
./start_server.sh
# Windows
start_server.batAPI will be available at:
- http://127.0.0.1:8000
- Interactive docs: http://127.0.0.1:8000/docs
POST /auth/set-sacsid- Store SACSID cookieGET /auth/status- Check authenticationPOST /api/league/update-from-url- Process tournament from URLPOST /api/league/update- Process with manual standings
"SACSID cookie is missing"
→ Run ./update_sacsid.sh YOUR_SACSID first
"Failed to fetch tournament" → SACSID may be expired - get a fresh one from your browser
"No module named 'gspread'" → Make sure you've activated the virtual environment and installed dependencies
"HTTP 500 error" → Check that you're logged into mtgarena.appspot.com
- Protocol: GWT-RPC (Google Web Toolkit Remote Procedure Call)
- Authentication: SACSID session cookie
- Data Format: Custom GWT serialization
- Encoding: Tournament IDs use GWT's proprietary base64 encoding
- Parsing: Regex-based extraction from GWT-RPC response
- Encoded tournament ID must be manually extracted from browser DevTools
- SACSID cookies expire after ~24 hours and must be refreshed
- Google OAuth login may have different permissions than classic auth
- Final standings must match the order players finished
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details
For issues or questions:
- Check QUICK_START_GUIDE.md for usage help
- See WINDOWS_GUIDE.md for Windows-specific issues
- Review SOLUTION_SUMMARY.md for technical details
- Open an issue on GitHub
Built for TopDeck League management system.