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¶
- PulseLMS 4.5 or higher (tested with version 5.0)
- Valid PulseLMS License Key (format:
PLMS-XXXX-XXXX-XXXX-XXXX) - Discord Server (Guild) where you have admin permissions
- Web Services enabled in PulseLMS
Installation Steps¶
-
Upload Plugin Files
-
Run Upgrade
- Navigate to Site administration > Notifications
- Or run via CLI:
-
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
-
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:
- Verifies with PulseTech billing server
- Retrieves your Discord Guild ID automatically
- 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¶
- Select Discord Role - Choose from dropdown of roles fetched from your Discord server
- Select Course - Choose the course to enroll users in
- Select Role - Choose the enrollment role (Student, Teacher, etc.)
- Select Cohort (optional) - Choose a cohort to add users to
- 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:
- Click Create New Discord Role
- Enter the role name
- 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¶
- User visits login page
- Clicks "Continue with Discord" button
- Redirected to Discord authorization page
- Authorizes the PulseTech LMS application
- Redirected back to PulseLMS
- 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
- If "Auto-create Users" is disabled:
- Error message displayed
- User must create account manually first
Existing User Links Discord Account¶
- User logs in normally
- Navigates to Discord linking page:
/local/pulsetech_discord/link.php - Clicks "Link My Discord Account"
- Authorizes Discord application
- Account linked
- Discord roles synced to enrollments
Existing User Login with Discord (Email Match)¶
Note
Requires "Link by Email" setting enabled
- User visits login page
- Clicks "Continue with Discord"
- System checks for existing user with matching email
- If found: accounts linked, user logged in
- 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:
- Checks license validity
- Gets all users with linked Discord accounts
- 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:
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:
or
Base URL¶
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 accesslocal/pulsetech_discord:viewmappings- View role mappingslocal/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:
- Verify license key format:
PLMS-XXXX-XXXX-XXXX-XXXX - Check license status with PulseTech support
- 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:
- Check "Enable Discord Login" setting is enabled
- Verify license key is valid
- 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:
- Verify role mapping exists in Role Mappings page
- Enable manual enrollment plugin globally
- Add manual enrollment method to the course
OAuth error: "Invalid state"¶
Causes:
- Session expired
- CSRF token mismatch
- Browser cookies blocked
Solutions:
- Have user clear browser cache and try again
- Check session timeout settings
- Verify cookies are enabled
Token refresh failures¶
Causes:
- Discord revoked app authorization
- User left Discord server
- Network issues
Solutions:
- User needs to re-authorize via linking page
- Unlink and re-link Discord account
Debug Mode¶
Enable debugging for detailed error messages:
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:
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:
- Check the troubleshooting section above
- Review logs for error messages
- Contact PulseTech support at [email protected] with:
- PulseLMS version
- Plugin version
- Error messages
- Steps to reproduce