Skip to content

FSU-Pulchowk/discord-bot

Repository files navigation

Pulchowk Discord Bot

A versatile Discord bot designed for the Pulchowk Campus community, featuring email verification, administrative tools, community engagement features, and academic information.

✨ Features

This bot offers a wide range of functionalities to manage and enhance Discord server:

Verification & Onboarding:

  • Email Verification (/verify, /confirmotp): Verifies users using their official Pulchowk Campus email by sending a one-time password (OTP).
  • Welcome Messages: Configurable welcome messages for new members, sent to a channel or via DM.

Moderation & Administration:

  • Anti-Spam System: Automatically detects and takes action (mute, kick, ban) against spamming users based on configurable thresholds.
  • Warnings (/warn): Records warnings for users in the database, with a confirmation box before execution and an option to reset warnings.
  • Kick (/kick): Kicks a user from the server.
  • Ban (/ban): Bans a user from the server.
  • Timeout (/timeout): Temporarily mutes a user.
  • Setup FSU (/setupfsu): Creates a basic set of FSU-related roles, categories, and channels for quick server setup.
  • Admin Tasks (/addtask, /listtasks, /completetask): Manage administrative to-do items.
  • Verified Users List (/gotverified): Displays a list of verified users with their real names and college email addresses (Admin/Moderator only).

Community Engagement & Information:

  • Leveling/XP System: Awards experience points (XP) for messages sent and voice chat activity, allowing users to level up and gain recognition.
  • Suggestions (/suggest, /approvesuggestion, /denysuggestion, /listsuggestions): Allows members to submit suggestions and administrators to review them.
  • Reaction Roles (/setreactionrole, /removereactionrole): Enables users to assign themselves roles by reacting to specific messages.
  • FAQs (/addfaq, /getfaq, /removefaq): Create and retrieve frequently asked questions.
  • User Stats (/mystats, /topchatters, /topvoice): Tracks user activity (messages sent, voice chat time) and displays leaderboards.
  • Birthday Announcements: Announces birthdays of members who have set their birthday.
  • Important Links (/links): Provides quick access to relevant Pulchowk Campus and FSU links.
  • News/Notices (/news): Provides links to official campus news and notice boards, and scrapes latest notices.
  • Holidays (/holidays): Displays upcoming holidays fetched from Google Calendar.

Role Management:

  • Assign Role (/assignrole): Assigns a specified role to a user.
  • Remove Role (/removerole): Removes a specified role from a user.
  • List All Roles (/allroles): Lists all roles in the server with their IDs.
  • List User Roles (/roles): Lists roles of a specified user or self.

πŸ“‚ Project Structure

β”œβ”€β”€ .dockerignore
β”œβ”€β”€ .env.example
β”œβ”€β”€ .github
β”‚   └── workflows
β”‚       β”œβ”€β”€ build-docker-image.yml
β”‚       β”œβ”€β”€ codeql.yml
β”‚       └── summary.yml
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md
β”œβ”€β”€ deploy-commands.js
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ generateToken.js
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ package.json
└── src
    β”œβ”€β”€ bot.js
    β”œβ”€β”€ commands
    β”‚   └── slash
    β”‚       β”œβ”€β”€ addFaq.js
    β”‚       β”œβ”€β”€ allRoles.js
    β”‚       β”œβ”€β”€ approveSuggestion.js
    β”‚       β”œβ”€β”€ assignRole.js
    β”‚       β”œβ”€β”€ ban.js
    β”‚       β”œβ”€β”€ clean.js
    β”‚       β”œβ”€β”€ confirmotp.js
    β”‚       β”œβ”€β”€ denySuggestion.js
    β”‚       β”œβ”€β”€ getFaq.js
    β”‚       β”œβ”€β”€ gotVerified.js
    β”‚       β”œβ”€β”€ help.js
    β”‚       β”œβ”€β”€ holidays.js
    β”‚       β”œβ”€β”€ kick.js
    β”‚       β”œβ”€β”€ links.js
    β”‚       β”œβ”€β”€ listSuggestions.js
    β”‚       β”œβ”€β”€ myStats.js
    β”‚       β”œβ”€β”€ news.js
    β”‚       β”œβ”€β”€ remindVerify.js
    β”‚       β”œβ”€β”€ removeBirthday.js
    β”‚       β”œβ”€β”€ removeFaq.js
    β”‚       β”œβ”€β”€ removeReactionRole.js
    β”‚       β”œβ”€β”€ removeRole.js
    β”‚       β”œβ”€β”€ repu.js
    β”‚       β”œβ”€β”€ roles.js
    β”‚       β”œβ”€β”€ rss.js
    β”‚       β”œβ”€β”€ setAntiSpam.js
    β”‚       β”œβ”€β”€ setBirthday.js
    β”‚       β”œβ”€β”€ setReactionRole.js
    β”‚       β”œβ”€β”€ setWelcome.js
    β”‚       β”œβ”€β”€ setupFSU.js
    β”‚       β”œβ”€β”€ suggest.js
    β”‚       β”œβ”€β”€ tasks.js
    β”‚       β”œβ”€β”€ timeout.js
    β”‚       β”œβ”€β”€ topChatters.js
    β”‚       β”œβ”€β”€ topVoice.js
    β”‚       β”œβ”€β”€ verify.js
    β”‚       β”œβ”€β”€ viewAntiSpam.js
    β”‚       └── warn.js
    β”œβ”€β”€ database.js
    β”œβ”€β”€ services
    β”‚   β”œβ”€β”€ emailService.js
    β”‚   β”œβ”€β”€ rssDbManager.js
    β”‚   β”œβ”€β”€ rssService.js
    β”‚   └── scraper.js
    └── utils
        β”œβ”€β”€ debug.js
        β”œβ”€β”€ imageExtactorRSS.js
        └── otpGenerator.js

πŸš€ Getting Started

Follow these steps to get Pulchowk Discord Bot up and running.

# Discord Bot Token (from Discord Developer Portal -> Bot -> Token)
BOT_TOKEN="_DISCORD_BOT_TOKEN_HERE"
# Discord Application (Client) ID (from Discord Developer Portal -> General Information)
CLIENT_ID="_DISCORD_APPLICATION_CLIENT_ID_HERE"
# ID of the Guild (Server) where you want to test/deploy commands (right-click server -> Copy ID - Developer Mode must be enabled)
GUILD_ID="_DISCORD_GUILD_ID_HERE"
# ID of the role to assign on successful verification (right-click role -> Copy ID)
VERIFIED_ROLE_ID="_VERIFIED_ROLE_ID_HERE"

# --- Google Cloud Project Credentials for Gmail API ---
# GOOGLE_CLIENT_ID (from Google Cloud Console -> APIs & Services -> Credentials -> OAuth 2.0 Client IDs)
GOOGLE_CLIENT_ID="_GOOGLE_CLIENT_ID_HERE"
# GOOGLE_CLIENT_SECRET (from Google Cloud Console -> APIs & Services -> Credentials -> OAuth 2.0 Client IDs)
GOOGLE_CLIENT_SECRET="_GOOGLE_CLIENT_SECRET_HERE"
# Redirect URI used during OAuth2 consent screen setup (e.g., https://developers.google.com/oauthplayground)
REDIRECT_URI="https://developers.google.com/oauthplayground" # Or custom redirect URI
# Refresh Token generated from OAuth2 Playground with https://www.googleapis.com/auth/gmail.send scope
REFRESH_TOKEN="_GOOGLE_REFRESH_TOKEN_HERE"
# The email address from college Workspace that will send the OTP emails
SENDER_EMAIL="college-email@pcampus.edu.np"

# --- Google Calendar API (for Holidays command) ---
# Path to Google Service Account Key JSON file (e.g., ./service_account_key.json)
# If not using service account, leave blank or remove. Holidays command will be disabled.
GOOGLE_SERVICE_ACCOUNT_KEY_PATH="./service_account_key.json"
# Google Calendar ID for holidays (e.g., 'en.nepali#holiday@group.v.calendar.google.com' for Nepal holidays)
GOOGLE_HOLIDAY_CALENDAR_ID="en.nepali#holiday@group.v.calendar.google.com"

# Optional: provide service account JSON as base64 (bot will decode to `src/service_account_key.json` on startup)
GOOGLE_SERVICE_ACCOUNT_KEY_B64=""

# --- Notice Scraper Configuration ---
# Channel ID where new notices will be posted
TARGET_NOTICE_CHANNEL_ID="_NOTICE_CHANNEL_ID_HERE"
# Channel ID for scraper error notifications (e.g., an admin channel)
NOTICE_ADMIN_CHANNEL_ID="_NOTICE_ADMIN_CHANNEL_ID_HERE"
# Interval for checking new notices in milliseconds (e.g., 30 minutes = 1800000)
NOTICE_CHECK_INTERVAL_MS=1800000

# --- Suggestions Feature Configuration ---
# Channel ID where suggestions will be posted and reacted to
SUGGESTIONS_CHANNEL_ID="_SUGGESTIONS_CHANNEL_ID_HERE"

# --- Birthday Announcements Configuration ---
# Channel ID where birthday announcements will be posted
BIRTHDAY_ANNOUNCEMENT_CHANNEL_ID="_BIRTHDAY_ANNOUNCEMENT_CHANNEL_ID_HERE"

# --- Club / Event Automation (optional) ---
CLUB_AUTO_SYNC_ENABLED="false"
CLUB_SYNC_INTERVAL_MINUTES=30
CLUB_AUTO_APPROVE="false"
EVENT_APPROVAL_CHANNEL_ID=""
CLUB_EVENT_REMINDER_HOURS=24
CLUB_JOIN_REQUESTS_PATH="./data/join_requests.xlsx"
CLUB_REGISTRATIONS_PATH="./data/club_registrations.xlsx"
CLUB_ATTENDANCE_PATH="./data/attendance.xlsx"

# --- Bot Prefix for traditional commands (e.g., !help) ---
BOT_PREFIX="!"
  - Copy the generated URL and paste it into browser to invite the bot.
  1. Create a "Verified" Role:
    • In Discord server, go to Server Settings -> Roles.
    • Create a new role named "Verified" (or anything you prefer).
    • Copy its ID: Right-click the role and select "Copy ID". This is VERIFIED_ROLE_ID. Ensure this role is positioned below bot's role in the server's role hierarchy so the bot can assign it.

2. Google Cloud Project Setup (for Gmail & Calendar APIs)

This bot uses Google APIs for email verification and holiday announcements.

  1. Create a Google Cloud Project:
  2. Enable APIs:
    • In project, navigate to "APIs & Services" -> "Enabled APIs & Services".
    • Click "+ ENABLE APIS AND SERVICES".
    • Search for and enable:
      • Gmail API (for sending OTP emails)
      • Google Calendar API (for /holidays command)
  3. Create OAuth Consent Screen:
    • Go to "APIs & Services" -> "OAuth consent screen".
    • Configure it (choose "External" for personal use, fill in required info).
    • Add https://www.googleapis.com/auth/gmail.send as a scope.
    • Add https://www.googleapis.com/auth/calendar.readonly as a scope.
    • Add email as a test user.
  4. Create OAuth 2.0 Client ID (for Gmail API):
    • Go to "APIs & Services" -> "Credentials".
    • Click "+ CREATE CREDENTIALS" and choose "OAuth client ID".
    • Select "Desktop app" as the application type.
    • Copy GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.
    • Generate Refresh Token:
      • Go to Google OAuth 2.0 Playground.
      • In the left pane, authorize the https://www.googleapis.com/auth/gmail.send scope and https://www.googleapis.com/auth/calendar.readonly scope.
      • Click "Authorize APIs".
      • Select Google account and grant permissions.
      • Click "Exchange authorization code for tokens".
      • Copy the Refresh Token. This is REFRESH_TOKEN.
      • Set REDIRECT_URI in .env to https://developers.google.com/oauthplayground (or custom URI if you set one up).
    • Set SENDER_EMAIL in .env to the email address you want the OTPs to be sent from (must be associated with Google Workspace account).
  5. Create Service Account Key (for Google Calendar API - Optional but Recommended):
    • Go to "APIs & Services" -> "Credentials".
    • Click "+ CREATE CREDENTIALS" and choose "Service Account".
    • Follow the steps to create a new service account.
    • Grant it the "Calendar Viewer" role (or a custom role with calendar.events.list permission).
    • After creation, click on the service account email.
    • Go to the "Keys" tab and click "ADD KEY" -> "Create new key".
    • Select "JSON" and click "CREATE". A JSON file will download.
    • Rename this file to service_account_key.json and place it in the root directory of bot project.
    • Set GOOGLE_SERVICE_ACCOUNT_KEY_PATH="./service_account_key.json" in .env.
    • Set GOOGLE_HOLIDAY_CALENDAR_ID in .env (e.g., 'en.nepali#holiday@group.v.calendar.google.com' for Nepal holidays).

3. Environment Variables (.env)

Create a file named .env in the root directory of project and populate it with the values obtained from the previous steps.

# Discord Bot Token (from Discord Developer Portal -> Bot -> Token)
BOT_TOKEN="_DISCORD_BOT_TOKEN_HERE"
# Discord Application (Client) ID (from Discord Developer Portal -> General Information)
CLIENT_ID="_DISCORD_APPLICATION_CLIENT_ID_HERE"
# ID of the Guild (Server) where you want to test/deploy commands (right-click server -> Copy ID - Developer Mode must be enabled)
GUILD_ID="_DISCORD_GUILD_ID_HERE"
# ID of the role to assign on successful verification (right-click role -> Copy ID)
VERIFIED_ROLE_ID="_VERIFIED_ROLE_ID_HERE"

# --- Google Cloud Project Credentials for Gmail API ---
# GOOGLE_CLIENT_ID (from Google Cloud Console -> APIs & Services -> Credentials -> OAuth 2.0 Client IDs)
GOOGLE_CLIENT_ID="_GOOGLE_CLIENT_ID_HERE"
# GOOGLE_CLIENT_SECRET (from Google Cloud Console -> APIs & Services -> Credentials -> OAuth 2.0 Client IDs)
GOOGLE_CLIENT_SECRET="_GOOGLE_CLIENT_SECRET_HERE"
# Redirect URI used during OAuth2 consent screen setup (e.g., [https://developers.google.com/oauthplayground](https://developers.google.com/oauthplayground))
REDIRECT_URI="[https://developers.google.com/oauthplayground](https://developers.google.com/oauthplayground)" # Or custom redirect URI
# Refresh Token generated from OAuth2 Playground with [https://www.googleapis.com/auth/gmail.send](https://www.googleapis.com/auth/gmail.send) scope
REFRESH_TOKEN="_GOOGLE_REFRESH_TOKEN_HERE"
# The email address from college Workspace that will send the OTP emails
SENDER_EMAIL="-college-email@pcampus.edu.np"

# --- Google Calendar API (for Holidays command) ---
# Path to Google Service Account Key JSON file (e.g., ./service_account_key.json)
# If not using service account, leave blank or remove. Holidays command will be disabled.
GOOGLE_SERVICE_ACCOUNT_KEY_PATH="./service_account_key.json"
# Google Calendar ID for holidays (e.g., 'en.nepali#holiday@group.v.calendar.google.com' for Nepal holidays)
GOOGLE_HOLIDAY_CALENDAR_ID="en.nepali#holiday@group.v.calendar.google.com"

# --- Notice Scraper Configuration ---
# Channel ID where new notices will be posted
TARGET_NOTICE_CHANNEL_ID="_NOTICE_CHANNEL_ID_HERE"
# Channel ID for scraper error notifications (e.g., an admin channel)
NOTICE_ADMIN_CHANNEL_ID="_NOTICE_ADMIN_CHANNEL_ID_HERE"
# Interval for checking new notices in milliseconds (e.g., 30 minutes = 1800000)
NOTICE_CHECK_INTERVAL_MS=1800000

# --- Suggestions Feature Configuration ---
# Channel ID where suggestions will be posted and reacted to
SUGGESTIONS_CHANNEL_ID="_SUGGESTIONS_CHANNEL_ID_HERE"

# --- Birthday Announcements Configuration ---
# Channel ID where birthday announcements will be posted
BIRTHDAY_ANNOUNCEMENT_CHANNEL_ID="_BIRTHDAY_ANNOUNCEMENT_CHANNEL_ID_HERE"

# --- Bot Prefix for traditional commands (e.g., !help) ---
BOT_PREFIX="!"

4. Installation

Open terminal in the project's root directory and run:

npm install

5. Deploying Slash Commands

Slash commands need to be registered with Discord. You can deploy them to a specific guild for testing or globally for production.

  • For testing (recommended): Deploy to specific test guild.
    node deploy-commands.js --guild
  • For global deployment (production): This can take up to an hour to propagate.
    node deploy-commands.js --global

6. Running the Bot

Once commands are deployed, you can start bot:

npm start

Usage

Slash Commands

  • /verify: Initiates the email verification process.
  • /confirmotp <code>: Confirms the verification with a One-Time Password.

Commands

Command Description Example Usage
/help [command_name] Displays a list of all commands or detailed information. /help
/news Shows the latest notices scraped from the Pulchowk Campus website. /news
/holidays Displays upcoming holidays fetched from Google Calendar. /holidays
/addfaq "Question" "Answer" [keywords] Adds a new FAQ entry. /addfaq "What is FSU?" "Future Skills University"
/getfaq <ID> Retrieves an FAQ by ID or searches by keywords. /getfaq "What is FSU?"
/removefaq <ID> Removes an existing FAQ entry. /removefaq 123
/addtask <description> Adds a new administrative task. /addtask "Study for exam"
/listtasks [status] Lists pending, completed, or all administrative tasks. /listtasks
/completetask <ID> Marks an administrative task as complete. /completetask 1
/suggest <suggestion> Submits a suggestion to the server staff. /suggest "Add more channels"
/listsuggestions [status] Lists all pending suggestions (Moderator). /listsuggestions
/approvesuggestion <ID> [reason] Approves a suggestion (Moderator). /approvesuggestion 1
/denysuggestion <ID> [reason] Denies a suggestion (Moderator). /denysuggestion 1
/links Displays important Pulchowk Campus/FSU-related links. /links
/mystats Shows personal chat and voice activity. /myStats
/topchatters [limit] Displays the top chatters in the server. /topchatters 10
/topvoice [limit] Displays the top voice activity users in the server. /topvoice 5
/setbirthday <MM/DD/YYYY> Sets birthday for announcements. /setbirthday 01/15
/removebirthday Removes saved birthday. /removebirthday
/assignrole @user <RoleNameOrID> Assigns a role to a user (Moderator). /assignrole @User Member
/removeRole @user <RoleNameOrID> Removes a role from a user (Moderator). /removerole @User Member
/allroles Lists all available roles on the server. /allroles
/setreactionrole <messageId> <emoji> <RoleNameOrID> Sets up a reaction role message. /setreactionrole 1234567890 🍎 9876543210
/removereactionrole <messageId> <emoji> Removes a reaction role from a message. /removereactionrole 1234567890 🍎
/setwelcome "message" Sets the welcome message for new members. /setwelcome "Welcome {user}!"
/setwelcome disable Disables the welcome message. /setwelcome disable
/ban @user [reason] Bans a user from the server (Moderator). /ban @User Spamming
/kick @user [reason] Kicks a user from the server (Moderator). /kick @User Rule break
/timeout @user <duration> [reason] Times out a user (Moderator). /timeout @User 5m Misbehaving
/warn @user [reason] Issues a warning to a user (Moderator). /warn @User Off-topic
/setantispam [setting <value>] ... Configures anti-spam settings (Admin). /setantispam message_limit 7 time_window_seconds 10
/viewantispam Views current anti-spam settings (Admin). /viewantispam
/gotverified Displays a list of verified users with their real names and college email addresses (Admin/Moderator).

πŸ“š Documentation

Detailed guides for the Club & Event Management system:

Key Features Overview

  • Club registration: Clubs are created (via commands) and may require admin approval.
  • Event creation: /createevent triggers a workflow for event details, payment settings, and poster uploads.
  • Payment System: Built-in verification loop for paid events using DM proofs.
  • Automation: Scheduled reminders, Excel export syncs, and inactive club checks.

Google Service Account (two options)

The bot can access Google Calendar using a service account JSON file or by accepting a base64-encoded JSON in an environment variable. This is useful in CI/CD or when secret files are not convenient.

  • File approach (existing): set GOOGLE_SERVICE_ACCOUNT_KEY_PATH to the JSON file path (commonly ./service_account_key.json).
  • Base64 env approach (supported by src/bot.js): set GOOGLE_SERVICE_ACCOUNT_KEY_B64 to the base64-encoded contents of the service account JSON. The bot will decode and write src/service_account_key.json at startup.

Example to create base64 string locally (Unix/macOS):

base64 -w0 service_account_key.json > sa_key.b64
# copy the content of sa_key.b64 into env var GOOGLE_SERVICE_ACCOUNT_KEY_B64

Security note: Do NOT commit service account JSON or the base64 string to version control. Use secret management in your deployment platform.

Developer Reference (quick map)

  • src/bot.js β€” Main bot class. Initializes client, commands, events, schedules, and integrations.
  • src/database.js β€” SQLite initialization and migration logic (creates all tables used by the bot).
  • src/commands/slash/ β€” Slash commands (one file per command). Examples: createEvent.js, setupFSU.js, verify.js.
  • src/services/ β€” Background services (email, RSS, scraper, club automation).
  • src/utils/ β€” Utility modules (logging, permission checks, OTP generator, notice processor).

Operations checklist

  • Back up bot.db regularly. The file is created at the repository root as bot.db by default.
  • If using Docker or Render, ensure persistent storage for bot.db (bind mount or persistent disk).
  • Store service_account_key.json and other credentials as secrets in your deployment platform, or provide GOOGLE_SERVICE_ACCOUNT_KEY_B64 as a protected env var.
  • To redeploy commands after changing a command file, run:
node deploy-commands.js --guild   # for testing in a guild
node deploy-commands.js --global  # for global deployment

For details on Render and Docker deployment, see the sections below.

This section provides detailed instructions for deploying bot on Render.com.

Important Note on Database Persistence: Bot uses SQLite (bot.db) for data storage. Render's standard web services use ephemeral storage, meaning any data written to the disk (like bot.db file) will be lost on redeploys or restarts. To ensure bot's data (user stats, anti-spam configs, suggestions, etc.) persists, you must configure a persistent disk.

Steps to Deploy:

  1. Push Code to a Git Repository:

    • Ensure all bot files (including the src folder, deploy-commands.js, package.json, .env.example if you create one, and service_account_key.json if using it) are committed and pushed to a GitHub, GitLab, or Bitbucket repository.
    • Crucially, add bot.db and service_account_key.json to .gitignore file if repository is public! You will upload service_account_key.json as a secret file on Render, and bot.db will be created by the persistent disk.
  2. Create a Render Account:

    • If you don't have one, sign up at Render.com. You can sign in with GitHub account.
  3. Create a New Web Service:

    • From Render Dashboard, click "New" -> "Web Service".
    • Connect Git repository: Select the repository where bot's code is hosted. You might need to grant Render access to repository.
    • Click "Connect".
  4. Configure Web Service:

    • Name: Give service a meaningful name (e.g., pulchowk-discord-bot).
    • Region: Choose a region closest to users or where you prefer.
    • Branch: Select the Git branch you want to deploy from (e.g., main or master).
    • Root Directory: If package.json is not in the root of repository (e.g., it's in a bot/ folder), specify that folder here. Otherwise, leave it blank.
    • Runtime: Node
    • Build Command: npm install
    • Start Command: npm start (This uses the start script defined in package.json)
    • Instance Type: Choose a suitable instance type. The "Free" tier might be sufficient for a small bot, but keep in mind free instances spin down after inactivity. A paid tier (e.g., "Starter") is recommended for 24/7 uptime.
  5. Add Environment Variables:

    • Scroll down to the "Environment Variables" section.
    • Add each key-value pair from local .env file here.
    • Important: For GOOGLE_SERVICE_ACCOUNT_KEY_PATH, you will use a secret file instead of an environment variable.
  6. Add Secret File for service_account_key.json:

    • Still in the "Environment Variables" section, click "Add Secret File".
    • Filename: service_account_key.json (This must exactly match the filename you set in GOOGLE_SERVICE_ACCOUNT_KEY_PATH in .env and the path in holidays.js command).
    • Content: Copy and paste the entire content of local service_account_key.json file into this text area.
    • Click "Add Secret File".
  7. Configure Persistent Disk (Crucial for SQLite):

    • Scroll down to the "Disks" section.
    • Click "Add Disk".
    • Name: bot-data (or any descriptive name).
    • Mount Path: /opt/render/project/bot.db (This is the path where Render expects bot.db file to be stored persistently. It aligns with where database.js creates the bot.db file relative to the project root on Render's file system).
    • Size: Choose a small size (e.g., 1 GB) as SQLite databases are typically small.
    • Click "Add Disk".
  8. Create Web Service:

    • Click "Create Web Service" at the bottom.
  9. Monitor Deployment:

    • Render will now start building and deploying bot. You can monitor the progress in the logs.
    • If the build fails, check the build logs for errors (e.g., missing dependencies, syntax errors).
    • If the deploy succeeds but the bot doesn't come online, check the runtime logs for errors (e.g., incorrect environment variables, bot token issues, API key problems).

After Deployment:

  • Verify Bot Status: Check Discord server to see if the bot is online.
  • Test Commands: Try using slash commands (/verify) and prefix commands (!help, !setbirthday, etc.) to ensure everything is working as expected.
  • Data Persistence: After testing, try manually restarting Render service. Then, check if /mystats or /listsuggestions data is still present. If it is, persistent disk is working correctly.

Troubleshooting Tips for Render:

  • "Web service failed to start": Check Start Command and ensure package.json start script is correct (node src/bot.js).
  • "Cannot find module": Ensure all dependencies are listed in package.json and npm install ran successfully during the build.
  • Bot goes offline: If on a free tier, it will spin down after inactivity. Upgrade to a paid instance type for 24/7 uptime.
  • Errors related to Google APIs: Double-check all Google API environment variables and the service_account_key.json content. Ensure the API is enabled in Google Cloud Console.
  • Permissions errors (Discord): Verify bot's permissions in the Discord Developer Portal and its role hierarchy in server.

Hosting on Local Server using Docker

To host your Pulchowk Discord Bot on a local server using Docker, follow these steps:

1. Prerequisites:

  • Docker: Make sure Docker Desktop (or Docker Engine for Linux) is installed and running on your system.

2. Project Setup:

  • Place Dockerfile and docker-compose.yml: Ensure the Dockerfile and docker-compose.yml files are in the root directory of your bot project, alongside your package.json and src directory.
  • .env file: Create a .env file in the root directory of your project and populate it with all the necessary environment variables as described in the README.md file, including your Discord bot token, Google API credentials, and other configurations.
    BOT_TOKEN="_DISCORD_BOT_TOKEN_HERE"
    CLIENT_ID="_DISCORD_APPLICATION_CLIENT_ID_HERE"
    GUILD_ID="_DISCORD_GUILD_ID_HERE"
    VERIFIED_ROLE_ID="_VERIFIED_ROLE_ID_HERE"
    GOOGLE_CLIENT_ID="_GOOGLE_CLIENT_ID_HERE"
    GOOGLE_CLIENT_SECRET="_GOOGLE_CLIENT_SECRET_HERE"
    REDIRECT_URI="[https://developers.google.com/oauthplayground](https://developers.google.com/oauthplayground)"
    REFRESH_TOKEN="_GOOGLE_REFRESH_TOKEN_HERE"
    SENDER_EMAIL="-college-email@pcampus.edu.np"
    GOOGLE_SERVICE_ACCOUNT_KEY_PATH="./service_account_key.json"
    GOOGLE_HOLIDAY_CALENDAR_ID="en.nepali#holiday@group.v.calendar.google.com"
    TARGET_NOTICE_CHANNEL_ID="_NOTICE_CHANNEL_ID_HERE"
    NOTICE_ADMIN_CHANNEL_ID="_NOTICE_ADMIN_CHANNEL_ID_HERE"
    NOTICE_CHECK_INTERVAL_MS=1800000
    SUGGESTIONS_CHANNEL_ID="_SUGGESTIONS_CHANNEL_ID_HERE"
    BIRTHDAY_ANNOUNCEMENT_CHANNEL_ID="_BIRTHDAY_ANNOUNCEMENT_CHANNEL_ID_HERE"
    BOT_PREFIX="!"
  • service_account_key.json: If you are using the Google Calendar API, ensure your service_account_key.json file is in the root directory of your project.

3. Deploy Slash Commands (One-Time Setup):

Before running the bot with Docker, you need to deploy the slash commands to Discord. This is typically done directly using Node.js, not within the Docker container build process for the first time.

  1. Install dependencies locally (if you haven't already):
    npm install
  2. Deploy slash commands:
    • For testing on a specific guild (recommended for local development):
      node deploy-commands.js --guild
    • For global deployment (takes up to an hour to propagate):
      node deploy-commands.js --global

4. Build and Run with Docker Compose:

Navigate to the root directory of your bot project in your terminal where docker-compose.yml and Dockerfile are located.

  1. Build the Docker image: This command will build the image defined in your Dockerfile.
    docker-compose build
  2. Start the bot: This command will create and start the Docker container for your bot.
    docker-compose up -d
    • fsu-discord-bot is the service name defined in docker-compose.yml.
    • The -d flag runs the container in detached mode (in the background).

Explanation of docker-compose.yml and Dockerfile:

  • Dockerfile:

    • FROM node:20-slim: Uses a slim Node.js 20 image as the base, which is good for smaller image sizes.
    • RUN groupadd -r botuser && useradd -r -g botuser -d /app -s /bin/bash botuser: Creates a non-root user botuser for security best practices.
    • WORKDIR /app: Sets the working directory inside the container to /app.
    • RUN chown -R botuser:botuser /app: Ensures the botuser owns the working directory.
    • RUN apt-get update ... chromium ...: Installs necessary system dependencies, including chromium for web scraping (Puppeteer).
    • ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium: Configures Puppeteer to use the installed Chromium.
    • COPY --chown=botuser:botuser package*.json ./: Copies package.json and package-lock.json (or yarn.lock) to leverage Docker's build cache.
    • USER botuser: Switches to the botuser.
    • RUN npm ci --omit=dev && npm cache clean --force: Installs production dependencies and cleans the npm cache. npm ci is used for clean installs in CI/CD environments.
    • COPY --chown=botuser:botuser . .: Copies the rest of your application code into the container.
    • CMD ["node", "./src/bot.js"]: Specifies the command to run when the container starts. This executes your main bot file.
  • docker-compose.yml:

    • version: "3.8": Specifies the Docker Compose file format version.
    • services:: Defines the services (containers) for your application.
      • fsu-discord-bot: The name of your bot service.
      • container_name: fsu-discord-bot: Assigns a specific name to the container.
      • image: agntperfect/fsu-discord-bot: Specifies the image to build/use. If you change the image name, remember to update it here.
      • user: botuser: Runs the container process as the botuser created in the Dockerfile.
      • security_opt: - no-new-privileges:true: Enhances security by preventing privilege escalation.
      • env_file: - .env: Tells Docker Compose to load environment variables from your local .env file into the container.
      • restart: unless-stopped: Configures the container to restart automatically unless it's explicitly stopped.
      • volumes:: Defines data persistence.
        • - fsu_data:/app/data:rw: This mounts a Docker volume named fsu_data to /app/data inside the container. If your bot needs to write any other persistent data (e.g., logs, temporary files) besides bot.db in a specific /app/data directory, this volume will ensure it persists across container restarts.
        • - ./bot.db:/app/bot.db:rw: This is crucial for SQLite persistence. It mounts your local bot.db file (or creates it if it doesn't exist) directly into the container at /app/bot.db. Any changes to bot.db inside the container will be reflected on your host machine, ensuring data persistence.
      • tmpfs: - /tmp: Mounts a tmpfs (temporary file system) at /tmp for temporary files, which improves performance and security by not writing ephemeral data to disk.
      • logging:: Configures logging for the container.
      • networks: - fsu_net: Connects the bot to a custom Docker network.
    • volumes: fsu_data: driver: local: Defines the named volume fsu_data.
    • networks: fsu_net: ...: Defines the custom bridge network for the services.

5. Verify and Manage:

  • Check container status:
    docker-compose ps
  • View logs:
    docker-compose logs fsu-discord-bot
  • Stop the bot:
    docker-compose down
    This will stop and remove the container and the fsu_net network, but the fsu_data volume and your local bot.db file will persist.
  • Stop and remove everything (including volumes):
    docker-compose down --volumes
    Use with caution, as --volumes will delete the fsu_data volume, but your explicit bot.db bind mount will keep bot.db on your host.

Important Considerations:

  • Firewall: Ensure your local firewall isn't blocking outgoing connections from the Docker container to Discord or Google APIs.
  • service_account_key.json: Since you're mounting the current directory, the service_account_key.json file should be accessible to the bot within the container at the path specified in your .env file (./service_account_key.json relative to /app).
  • Initial bot.db: The database.js script in your bot's src directory is responsible for creating the bot.db file and its tables if it doesn't exist. When you first run the container, it will create this file on your host machine at the path specified in the volume mount (./bot.db).
  • Updates: If you make changes to your bot's code, you'll need to rebuild the Docker image:
    docker-compose build
    docker-compose up -d

🀝 Contributing

Contributions are welcome! If you have suggestions for improvements or new features, feel free to open an issue or submit a pull request.

  • Fork the repository.
  • Create feature branch (git checkout -b feature/AmazingFeature).
  • Commit changes (git commit -m 'Add some AmazingFeature').
  • Push to the branch (git push origin feature/AmazingFeature).
  • Open a Pull Request.

πŸ“„ License

This project is licensed under the [No Redistribution License](https://www.google.com/search?q=LICENSE).

About

A versatile Discord bot for the Pulchowk Campus community, featuring email verification, comprehensive moderation tools, and various engagement features like suggestions, FAQs, user stats, and academic information.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors