Skip to content

Discord Integration

Plugin: PulseTech Discord Integration (local_pulsetech_discord)
Version: 1.0.1 (2025010501)
Compatibility: Moodle 4.5+ / Moodle 5.0


Overview

The PulseTech Discord Integration plugin enables seamless integration between Discord and PulseLMS, providing:

  • Discord OAuth Login - Users can log in using their Discord account
  • Account Linking - Existing users can link their accounts to Discord
  • Automatic Role Synchronization - Discord server roles automatically translate to course enrollments
  • Cohort Management - Discord roles can also add users to cohorts
  • Web Service API - External Discord bots can interact with PulseLMS via REST API

How It Works

flowchart LR
    A[Discord Server] --> B[PulseTech Billing Server]
    B --> C[PulseLMS]
    A -.->|OAuth Flow| B
    A -.->|Role Data| B
    B -.->|License Verify| C
    B -.->|Role Sync| C

The plugin uses PulseTech's billing server as an intermediary for:

  • License key verification
  • OAuth redirect handling (Discord only allows registered redirect URIs)
  • Discord role management

Key Features

Discord Login Button

Adds a "Continue with Discord" button to the login page, allowing users to authenticate via Discord OAuth2.

Automatic Account Creation

When enabled, new Discord users who log in will automatically have an account created using their Discord profile information.

Email-Based Account Linking

Optionally auto-link Discord accounts to existing users when their email addresses match.

Role-to-Course Mapping

Map Discord server roles to specific courses. When a user has a Discord role, they're automatically enrolled in the corresponding course with the specified role.

Role-to-Cohort Mapping

Discord roles can also be mapped to cohorts, enabling group-based access control and reporting.

Automatic Synchronization

A scheduled task runs hourly (configurable) to sync Discord roles with enrollments for all linked users.


Installation

Prerequisites

  1. PulseLMS 4.5 or higher (tested with version 5.0)
  2. Valid PulseLMS License Key (format: PLMS-XXXX-XXXX-XXXX-XXXX)
  3. Discord Server (Guild) where you have admin permissions
  4. Web Services enabled in PulseLMS

Installation Steps

  1. Upload Plugin Files

    # Copy plugin to PulseLMS
    cp -r pulsetech_discord /var/www/moodle/local/
    
    # Set permissions
    chown -R www-data:www-data /var/www/moodle/local/pulsetech_discord
    

  2. Run Upgrade

    • Navigate to Site administration > Notifications
    • Or run via CLI:
      php admin/cli/upgrade.php
      
  3. Enable Web Services (if not already enabled)

    • Go to Site administration > Advanced features
    • Enable Web services
    • Enable REST protocol under Site administration > Plugins > Web services > Manage protocols
  4. Configure the Plugin

    • Go to Site administration > Plugins > Local plugins > PulseTech Discord Integration
    • Enter your license key and complete configuration

Configuration

Accessing Settings

Navigate to: Site administration > Plugins > Local plugins > PulseTech Discord Integration

License Configuration

Setting Description
License Key Your PulseLMS license key in format PLMS-XXXX-XXXX-XXXX-XXXX. Required for plugin operation.
License Status Read-only display showing verification status (Valid/Invalid/Not verified)

When you enter a valid license key, the plugin:

  1. Verifies with PulseTech billing server
  2. Retrieves your Discord Guild ID automatically
  3. Enables all integration features

Discord Configuration

Setting Description Default
Discord Server ID Auto-populated from license verification. The Discord server (guild) to integrate with. (auto)
Enable Discord Login Show "Continue with Discord" button on login page Enabled
Auto-create Users Automatically create accounts for new Discord users Enabled
Link by Email Auto-link Discord accounts to existing users when emails match Disabled

Synchronization Settings

Setting Description
Sync Interval How often to sync Discord roles with enrollments

Sync Interval Options:

  • Hourly - Sync runs every hour (recommended)
  • Daily - Sync runs once per day
  • Weekly - Sync runs once per week
  • Manual Only - Sync only runs when triggered manually or via API

Web Service Configuration

Setting Description
Web Service Token Auto-generated permanent token for Discord bot integration. Click "Generate" to create.

Security Note

The web service token is sent to the PulseTech billing server for Discord bot authentication. Keep this token secure.


Discord Role Mappings

Role mappings define how Discord server roles translate to course enrollments and cohort memberships.

Accessing Role Mappings

Navigate to: Site administration > Plugins > Local plugins > PulseTech Discord Integration > Role Mappings

Or directly: https://your-site.com/local/pulsetech_discord/rolemappings.php

Creating a Role Mapping

  1. Select Discord Role - Choose from dropdown of roles fetched from your Discord server
  2. Select Course - Choose the course to enroll users in
  3. Select Role - Choose the enrollment role (Student, Teacher, etc.)
  4. Select Cohort (optional) - Choose a cohort to add users to
  5. Click Add Mapping

Example Mappings

Discord Role Course Role Cohort
Student Access Introduction to Programming Student Students 2025
Premium Member Advanced Topics Student Premium Members
Course Creator Staff Training Teacher Instructors

How Mappings Work

When a user has a Discord role:

  • They are enrolled in the mapped course with the specified role
  • They are added to the mapped cohort (if configured)

When a Discord role is removed:

  • They are unenrolled from the mapped course
  • They are removed from the mapped cohort

Creating Discord Roles

You can create new Discord roles directly from the mappings page:

  1. Click Create New Discord Role
  2. Enter the role name
  3. Click Create

The role is created in your Discord server and becomes available for mapping.

Deleting Mappings

Click the Delete button next to any mapping to remove it. This does not unenroll existing users - they will be unenrolled on the next sync.


User Workflows

New User Login with Discord

  1. User visits login page
  2. Clicks "Continue with Discord" button
  3. Redirected to Discord authorization page
  4. Authorizes the PulseTech LMS application
  5. Redirected back to PulseLMS
  6. If "Auto-create Users" is enabled:
    • New account created with Discord profile data
    • Discord account automatically linked
    • Roles synced, user enrolled in appropriate courses
    • Logged in and redirected to dashboard
  7. If "Auto-create Users" is disabled:
    • Error message displayed
    • User must create account manually first
  1. User logs in normally
  2. Navigates to Discord linking page: /local/pulsetech_discord/link.php
  3. Clicks "Link My Discord Account"
  4. Authorizes Discord application
  5. Account linked
  6. Discord roles synced to enrollments

Existing User Login with Discord (Email Match)

Note

Requires "Link by Email" setting enabled

  1. User visits login page
  2. Clicks "Continue with Discord"
  3. System checks for existing user with matching email
  4. If found: accounts linked, user logged in
  5. If not found: follows new user workflow

Account Linking Page

Users can manage their Discord link at: /local/pulsetech_discord/link.php

Features:

  • View linked Discord account (username and avatar)
  • See expected course enrollments based on Discord roles
  • Manually trigger role sync with "Sync Now" button
  • Unlink Discord account with "Unlink Account" button

Synchronization

Automatic Synchronization

The scheduled task \local_pulsetech_discord\task\sync_all_users handles automatic synchronization.

What it does:

  1. Checks license validity
  2. Gets all users with linked Discord accounts
  3. For each user:
    • Fetches current Discord roles
    • Compares to role mappings
    • Enrolls in new courses (when roles added)
    • Unenrolls from courses (when roles removed)
    • Updates cohort memberships

Schedule: Configured in plugin settings (hourly/daily/weekly/manual)

Manual Synchronization

For a single user:

  • User visits their linking page and clicks "Sync Now"
  • Admin triggers via web service API

For all users:

  • Run scheduled task manually:
    php admin/cli/scheduled_task.php --execute='\local_pulsetech_discord\task\sync_all_users'
    

Sync Behavior Details

Enrollment:

  • Uses the manual enrollment plugin
  • Creates enrollment instance if missing
  • Assigns the role specified in mapping

Unenrollment:

  • Removes user from course when Discord role removed
  • Removes role assignment
  • User sessions are invalidated when unenrolled (security feature)

Cohorts:

  • Adds to cohort when role gained
  • Removes from cohort when role lost

Web Service API

The plugin exposes REST API endpoints for external Discord bot integration.

Authentication

All API requests require the web service token in the header or as parameter:

Authorization: Bearer YOUR_TOKEN

or

?wstoken=YOUR_TOKEN

Base URL

https://your-site.com/webservice/rest/server.php

Get User by Discord ID

Looks up a user by their Discord ID.

Function: local_pulsetech_discord_get_user_by_discord_id

Parameters:

Name Type Description
discord_id string Discord user ID (snowflake format)

Response:

{
  "found": true,
  "userid": 123,
  "username": "jsmith",
  "firstname": "John",
  "lastname": "Smith",
  "email": "[email protected]",
  "discord_username": "john#1234",
  "last_synced_at": 1704067200
}

Example Request:

curl -X POST "https://your-site.com/webservice/rest/server.php" \
  -d "wstoken=YOUR_TOKEN" \
  -d "wsfunction=local_pulsetech_discord_get_user_by_discord_id" \
  -d "moodlewsrestformat=json" \
  -d "discord_id=123456789012345678"

Sync User Roles

Triggers role synchronization for a specific user with provided Discord roles.

Function: local_pulsetech_discord_sync_user_roles

Parameters:

Name Type Description
discord_id string Discord user ID
discord_roles array Array of Discord role IDs the user currently has

Response:

{
  "success": true,
  "enrolled": 2,
  "unenrolled": 1,
  "errors": 0,
  "changes": [
    {
      "action": "enrolled",
      "course": "Introduction to Programming",
      "role": "Student"
    }
  ],
  "session_invalidated": true
}

Example Request:

curl -X POST "https://your-site.com/webservice/rest/server.php" \
  -d "wstoken=YOUR_TOKEN" \
  -d "wsfunction=local_pulsetech_discord_sync_user_roles" \
  -d "moodlewsrestformat=json" \
  -d "discord_id=123456789012345678" \
  -d "discord_roles[0]=111111111111111111" \
  -d "discord_roles[1]=222222222222222222"

Get User Courses

Retrieves all courses a Discord-linked user is enrolled in.

Function: local_pulsetech_discord_get_user_courses

Parameters:

Name Type Description
discord_id string Discord user ID

Response:

{
  "found": true,
  "courses": [
    {
      "id": 5,
      "shortname": "PROG101",
      "fullname": "Introduction to Programming",
      "roles": ["Student"]
    }
  ]
}

Get Role Mappings

Retrieves all configured Discord role-to-course mappings.

Function: local_pulsetech_discord_get_role_mappings

Parameters: None

Response:

[
  {
    "id": 1,
    "discord_role_id": "111111111111111111",
    "discord_role_name": "Student Access",
    "courseid": 5,
    "course_name": "Introduction to Programming",
    "roleid": 5,
    "role_name": "Student"
  }
]

Admin Pages Reference

Page URL Description
Plugin Settings /admin/settings.php?section=local_pulsetech_discord Configure license, Discord settings, and sync interval
Role Mappings /local/pulsetech_discord/rolemappings.php Manage Discord role to course/cohort mappings
User Account Linking /local/pulsetech_discord/link.php User-facing page for linking/unlinking Discord accounts
OAuth Callback /local/pulsetech_discord/callback.php Handles Discord OAuth callbacks (not directly accessed)

Required Capabilities:

  • local/pulsetech_discord:manage - Full admin access
  • local/pulsetech_discord:viewmappings - View role mappings
  • local/pulsetech_discord:linkaccount - Link own Discord account (granted to all authenticated users)

Database Schema

Table: local_pulsetech_discord_users

Stores Discord account links for users.

Column Type Description
id INT Primary key
userid INT User ID (unique, FK to user)
discord_id VARCHAR(32) Discord user ID (unique, indexed)
discord_username VARCHAR(255) Discord username
discord_avatar VARCHAR(255) Discord avatar hash
discord_access_token TEXT Encrypted OAuth access token
discord_refresh_token TEXT Encrypted OAuth refresh token
token_expires_at INT Token expiry timestamp
last_synced_at INT Last role sync timestamp
timecreated INT Record creation timestamp
timemodified INT Record modification timestamp

Table: local_pulsetech_discord_role_mappings

Maps Discord roles to courses and cohorts.

Column Type Description
id INT Primary key
discord_role_id VARCHAR(32) Discord role ID
discord_role_name VARCHAR(255) Discord role display name
courseid INT Course ID (FK to course)
roleid INT Role ID (FK to role)
cohortid INT Cohort ID (FK to cohort, optional)
timecreated INT Record creation timestamp
timemodified INT Record modification timestamp

Troubleshooting

"License key invalid" error

Causes:

  • Invalid license key format
  • License expired or revoked
  • Network connectivity to billing server

Solutions:

  1. Verify license key format: PLMS-XXXX-XXXX-XXXX-XXXX
  2. Check license status with PulseTech support
  3. Verify server can reach billing.mypulsetech.com

Discord login button not appearing

Causes:

  • Discord login disabled in settings
  • License not verified
  • Hook not registered

Solutions:

  1. Check "Enable Discord Login" setting is enabled
  2. Verify license key is valid
  3. Purge caches: php admin/cli/purge_caches.php

Users not being enrolled after sync

Causes:

  • No role mapping configured for the Discord role
  • Manual enrollment plugin disabled
  • Course enrollment not enabled

Solutions:

  1. Verify role mapping exists in Role Mappings page
  2. Enable manual enrollment plugin globally
  3. Add manual enrollment method to the course

OAuth error: "Invalid state"

Causes:

  • Session expired
  • CSRF token mismatch
  • Browser cookies blocked

Solutions:

  1. Have user clear browser cache and try again
  2. Check session timeout settings
  3. Verify cookies are enabled

Token refresh failures

Causes:

  • Discord revoked app authorization
  • User left Discord server
  • Network issues

Solutions:

  1. User needs to re-authorize via linking page
  2. Unlink and re-link Discord account

Debug Mode

Enable debugging for detailed error messages:

// In config.php
$CFG->debug = (E_ALL | E_STRICT);
$CFG->debugdisplay = 1;

Log Locations

  • Scheduled Task Logs: Site administration > Server > Tasks > Logs
  • Web Service Logs: Site administration > Server > Web service logs
  • PHP Error Logs: Check your server's PHP error log

Cache Issues

Clear plugin caches if experiencing stale data:

php admin/cli/purge_caches.php

Or via admin: Site administration > Development > Purge all caches


Security Considerations

Token Security

  • OAuth tokens are encrypted using core encryption
  • Tokens are never logged or displayed in plain text
  • Refresh tokens automatically refresh before expiry

Session Management

  • User sessions are invalidated when unenrolled from courses via sync
  • This prevents continued access after role removal
  • CSRF protection on all form submissions

Capabilities

Capability Purpose Default Role
local/pulsetech_discord:manage Full admin access Manager
local/pulsetech_discord:viewmappings View role mappings Manager, Course Creator
local/pulsetech_discord:linkaccount Link own Discord account Authenticated User

Data Privacy

  • Only necessary Discord data is stored (ID, username, avatar hash)
  • Email stored only if provided by Discord
  • Users can unlink their accounts at any time
  • Privacy metadata declared for GDPR compliance

Web Service Security

  • Token-based authentication required
  • Capability checks on all functions
  • Rate limiting recommended at web server level

Support

For issues with this plugin:

  1. Check the troubleshooting section above
  2. Review logs for error messages
  3. Contact PulseTech support at [email protected] with:
    • PulseLMS version
    • Plugin version
    • Error messages
    • Steps to reproduce