This guide provides a step-by-step tutorial to set up the Eligible STEM Bot locally or on a server.
Before starting, ensure you have:
- Git installed (Download).
- Python 3.9 or higher installed (Download).
- A Google Account (for Google Sheets/Cloud).
- A Telegram Account.
Open your terminal or command prompt and run:
git clone https://github.com/zis3c/stem-bot.git
cd stem-botIt is recommended to use a virtual environment to avoid conflicts.
Windows:
python -m venv venv
venv\Scripts\activateMac/Linux:
python3 -m venv venv
source venv/bin/activateInstall the required libraries:
pip install -r requirements.txt- Open Telegram and search for @BotFather.
- Send
/newbot. - Follow the prompts to name your bot (e.g.,
MySTEMBot) and give it a username (e.g.,MySTEM_bot). - Copy the HTTP API Token. You will need this for the
.envfile.
This bot uses Google Sheets as a database. You need a Service Account credentials file.
- Go to the Google Cloud Console.
- Create a New Project (e.g., "STEM Bot").
- Enable APIs:
- Go to APIs & Services > Library.
- Search for "Google Sheets API" -> Enable.
- Search for "Google Drive API" -> Enable.
- Create Service Account:
- Go to APIs & Services > Credentials.
- Click Create Credentials > Service Account.
- Name it (e.g., "bot-service"). Click Create & Continue.
- Role: Editor (Basic > Editor). Click Done.
- Generate Keys:
- Click on the email of the service account you just created (e.g.,
bot-service@project-id.iam.gserviceaccount.com). - Go to the Keys tab.
- Click Add Key > Create new key.
- Select JSON.
- A file will download (e.g.,
project-id-12345.json). Keep this safe!
- Click on the email of the service account you just created (e.g.,
-
Create a New Google Sheet.
-
Share the Sheet:
- Open the JSON key file you downloaded in Step 4.
- Find the
"client_email"field. Copy the email address. - Go to your Google Sheet > Click Share > Paste the email > Editor access > Send.
-
Get Sheet ID:
- Look at the URL of your spreadsheet:
https://docs.google.com/spreadsheets/d/1aBcD...xYz/edit - The ID is the long string between
/d/and/edit. Copy this.
- Look at the URL of your spreadsheet:
-
Create Required Tabs:
- Tab 1 Name:
Registrations - Structure for
RegistrationsSheet (Important!): Ensure your sheet has the following columns (Order is critical):
- Tab 1 Name:
| Col | Field |
|---|---|
| A | Timestamp |
| B | Email Address |
| C | Name |
| D | Matrics Number |
| E | Courses |
| F | Semester |
| G | Phone Number |
| H | Personal Email |
| I | USAS Email |
| J | IC Number |
| K | Birthday |
| L | Birth Place |
| M | Address |
| N | Date of Entry |
| O | Minute Number |
| P | Membership Number |
| Q | Receipt Proof |
| R | Status |
| S | Payment Receipt |
| T | Invoice No |
| U | Statistic |
* **Tab 2 Name**: `system_admins`
* Headers: `User ID`, `Name`, `Added By`
* **Tab 3 Name**: `system_config`
* Headers: `Key`, `Value`
* Add a row: `maintenance_mode` | `False`
* "Run" > "setupTrigger".
* Grant permissions if requested.
> **Note**: This script handles the `Membership ID` generation and `Date of Entry` formatting automatically.
The bot relies on a script running inside the Google Sheet to generate IDs and format dates.
- Open Script Editor:
- In your Google Sheet, go to Extensions > Apps Script.
- Paste Code:
- Delete any existing code in
Code.gs. - Open
google_apps_script.jsfrom this repository. - Copy the entire content and paste it into the script editor.
- Delete any existing code in
- Save:
- Press
Ctrl+S(orCmd+S) to save the project.
- Press
- Setup Trigger:
- In the function dropdown (top bar), select
setupTrigger. - Click Run.
- Grant Permissions: Google will ask for permission. Click "Review Permissions" > Choose Account > "Advanced" > "Go to (Project Name) (unsafe)" > "Allow".
- In the function dropdown (top bar), select
- Verify:
- Go to the Triggers icon (alarm clock) in the left sidebar.
- You should see a trigger for
onFormSubmit.
To enable the automatic monthly separator row (e.g., --- STATISTIK DISEMBER ---):
- In Apps Script, click Triggers (alarm clock).
- Click Add Trigger (blue button).
- Configure:
- Function:
generateMonthlyStats - Deployment:
Head - Event Source:
Time-driven - Type:
Month timer - Select:
1st(Day of month) @Midnight.
- Function:
- Click Save.
Create a file named .env in the stem-bot folder.
Option A: Paste JSON Content (Easier for Cloud) Open your downloaded JSON key file, copy the entire content, and verify it is a single line (or handles escaping). However, for local consistency, we often use the file path.
Recommended .env Format:
TELEGRAM_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
SHEET_ID=1aBcD...xYz # Your Sheet ID
GOOGLE_CREDENTIALS='{ "type": "service_account", ... }'
# Paste the FULL JSON content inside single quotes using one line if possible.
# Alternatively, if running locally, you can modify database.py to read 'service_account.json'.
SUPERADMIN_IDS=123456789
ADMIN_IDS=987654321Tip: If pasting JSON into
.envis difficult, rename your downloaded key file toservice_account.jsonand place it in the project folder. The bot is configured to look for it ifGOOGLE_CREDENTIALSis missing.
python bot.pyIf successful, you will see Bot is polling... in the console.
- SSH into your droplet and install runtime packages:
sudo apt update sudo apt install -y python3 python3-venv python3-pip git
- Clone the repository:
sudo mkdir -p /opt/stem-telebot sudo chown "$USER":"$USER" /opt/stem-telebot git clone --depth 1 --branch main https://github.com/zis3c/STEM-Telebot /opt/stem-telebot cd /opt/stem-telebot
- Create and populate environment values:
- Create
/etc/stem-telebot/bot.envwithTELEGRAM_TOKEN,SHEET_ID,SUPERADMIN_IDS,ADMIN_IDS. - Optional webhook mode: set
WEBHOOK_URL; keep it empty for polling mode.
- Create
- Put Google credentials at
/opt/stem-telebot/service_account.jsonand lock permissions:sudo chown deploy:deploy /opt/stem-telebot/service_account.json sudo chmod 600 /opt/stem-telebot/service_account.json
- Create and start the
systemdservice:sudo systemctl daemon-reload sudo systemctl enable --now stem-telebot
Done! Your bot is live on DigitalOcean.
Membership and demographic web pages are served by the bot itself:
/profile/membership/<token>/stats/demographic/<token>
To use these links publicly, you need:
- A domain/subdomain (for example
bot.yourdomain.com) pointing to your droplet IP via DNSArecord. - HTTPS enabled on that domain (Telegram webhook requires valid SSL).
WEBHOOK_URLset to your public HTTPS base URL (example:https://bot.yourdomain.com).
If WEBHOOK_URL is empty (polling mode), bot features still work, but public web report links will not be reachable from the internet unless you expose the server separately.
The bot now uses separate Python template modules for web report UIs:
- membership_card_template.py for membership profile card pages
- demographic_stats_template.py for demographic dashboard pages
Edit these files when changing web UI design instead of placing long HTML blocks directly in bot.py.