Skip to main content

Table of Contents

Getting Started

Basic Usage

All exports are called via exports.LonexDiscordAPI:ExportName(...).
-- Example: Get a player's Discord username
local username = exports.LonexDiscordAPI:GetDiscordUsername(source)
print("Player's Discord: " .. (username or "Not linked"))

Important Notes

  • All role functions use Role IDs only (not role names)
  • To get a Role ID: Enable Developer Mode in Discord → Right-click role → Copy Role ID
  • Most functions return nil if the player doesn’t have Discord linked to FiveM
  • Functions with “ById” suffix accept a Discord ID instead of player source

Player Data

GetDiscordId

Get a player’s Discord ID from their FiveM source.
local discordId = exports.LonexDiscordAPI:GetDiscordId(source)
-- Returns: "306838265174949888" or nil

GetDiscordUser

Get full Discord user data.
local user = exports.LonexDiscordAPI:GetDiscordUser(source)
-- Returns: {
--   id = "306838265174949888",
--   username = "johndoe",
--   discriminator = "0",
--   globalName = "John Doe",
--   avatar = "abc123...",
--   bot = false,
--   banner = nil,
--   accentColor = 5793266
-- }

GetDiscordUserById

Get user data by Discord ID (doesn’t require player to be online).
local user = exports.LonexDiscordAPI:GetDiscordUserById("306838265174949888")

GetDiscordMember

Get full guild member data (includes server-specific info).
local member = exports.LonexDiscordAPI:GetDiscordMember(source)
-- Returns: {
--   user = { ... },          -- User object
--   nickname = "Johnny",     -- Server nickname
--   roles = { "123...", "456..." },  -- Array of role IDs
--   joinedAt = "2023-01-15T...",
--   premiumSince = nil,      -- Nitro boost date
--   avatar = nil,            -- Server-specific avatar
--   ...
-- }

GetDiscordMemberById

Get member data by Discord ID.
local member = exports.LonexDiscordAPI:GetDiscordMemberById("306838265174949888")

GetDiscordName

Get display name (nickname → global name → username).
local name = exports.LonexDiscordAPI:GetDiscordName(source)
-- Returns: "Johnny" (nickname) or "John Doe" (global) or "johndoe" (username)

GetDiscordNickname

Get server nickname only.
local nickname = exports.LonexDiscordAPI:GetDiscordNickname(source)
-- Returns: "Johnny" or nil if no nickname set

GetDiscordUsername

Get Discord username only.
local username = exports.LonexDiscordAPI:GetDiscordUsername(source)
-- Returns: "johndoe"

GetDiscordAvatar

Get avatar URL (uses server avatar if set, falls back to user avatar).
local avatar = exports.LonexDiscordAPI:GetDiscordAvatar(source, 256)
-- Size is optional (default: 128)
-- Returns: "https://cdn.discordapp.com/avatars/306.../abc123.png?size=256"

GetDiscordAvatarById

Get avatar URL by Discord ID.
local avatar = exports.LonexDiscordAPI:GetDiscordAvatarById("306838265174949888", 128)

IsInDiscordGuild

Check if player is in the Discord server.
local inGuild = exports.LonexDiscordAPI:IsInDiscordGuild(source)
-- Returns: true or false

Role Checking

GetDiscordRoles

Get all roles as full role objects (sorted by position).
local roles = exports.LonexDiscordAPI:GetDiscordRoles(source)
-- Returns: {
--   { id = "123...", name = "Admin", color = 16711680, position = 10, ... },
--   { id = "456...", name = "Member", color = 0, position = 1, ... },
-- }

GetDiscordRoleIds

Get array of role IDs.
local roleIds = exports.LonexDiscordAPI:GetDiscordRoleIds(source)
-- Returns: { "123456789012345678", "234567890123456789" }

GetDiscordRoleNames

Get array of role names (for display purposes).
local roleNames = exports.LonexDiscordAPI:GetDiscordRoleNames(source)
-- Returns: { "Admin", "Member", "VIP" }

HasDiscordRole

Check if player has a specific role.
local isAdmin = exports.LonexDiscordAPI:HasDiscordRole(source, "123456789012345678")
-- Returns: true or false

HasAnyDiscordRole

Check if player has any of the specified roles.
local isStaff = exports.LonexDiscordAPI:HasAnyDiscordRole(source, {
    "123456789012345678",  -- Admin
    "234567890123456789",  -- Moderator
})
-- Returns: true or false

HasAllDiscordRoles

Check if player has all of the specified roles.
local isVerifiedVIP = exports.LonexDiscordAPI:HasAllDiscordRoles(source, {
    "345678901234567890",  -- Verified
    "456789012345678901",  -- VIP
})
-- Returns: true or false

Role Management

All role management functions support audit log reasons (visible in Discord’s audit log).

AddRole

Add a role to a player.
local success, err = exports.LonexDiscordAPI:AddRole(source, "123456789012345678", "Purchased VIP")
if not success then
    print("Failed to add role: " .. err)
end

AddRoleById

Add a role by Discord ID (player doesn’t need to be online).
local success, err = exports.LonexDiscordAPI:AddRoleById("306838265174949888", "123456789012345678", "Manual add")

RemoveRole

Remove a role from a player.
local success, err = exports.LonexDiscordAPI:RemoveRole(source, "123456789012345678", "VIP expired")

RemoveRoleById

Remove a role by Discord ID.
local success, err = exports.LonexDiscordAPI:RemoveRoleById("306838265174949888", "123456789012345678", "Banned")

SetRoles

Replace all roles for a player (use with caution).
local success, err = exports.LonexDiscordAPI:SetRoles(source, {
    "123456789012345678",  -- Member
    "234567890123456789",  -- Verified
}, "Role sync")

SetRolesById

Replace all roles by Discord ID.
local success, err = exports.LonexDiscordAPI:SetRolesById("306838265174949888", {
    "123456789012345678",
}, "Reset roles")

SetNickname

Set a player’s Discord nickname.
local success, err = exports.LonexDiscordAPI:SetNickname(source, "Officer Smith", "On duty")

SetNicknameById

Set nickname by Discord ID.
local success, err = exports.LonexDiscordAPI:SetNicknameById("306838265174949888", "John D.", "Name change")

Reset Nickname

Pass empty string or nil to reset nickname.
local success, err = exports.LonexDiscordAPI:SetNickname(source, "", "Off duty")

MoveToVoiceChannel

Move a player to a voice channel.
local success, err = exports.LonexDiscordAPI:MoveToVoiceChannel(source, "123456789012345678", "Moved to staff")

MoveToVoiceChannelById

Move by Discord ID. Pass nil as channel to disconnect from voice.
-- Move to channel
local success, err = exports.LonexDiscordAPI:MoveToVoiceChannelById("306838265174949888", "123456789012345678")

-- Disconnect from voice
local success, err = exports.LonexDiscordAPI:MoveToVoiceChannelById("306838265174949888", nil, "Disconnected")

Guild Data

GetGuildInfo

Get information about the Discord server.
local guild = exports.LonexDiscordAPI:GetGuildInfo()
-- Returns: {
--   id = "123456789012345678",
--   name = "My Server",
--   icon = "abc123...",
--   ownerId = "306838265174949888",
--   memberCount = 150,
--   ...
-- }

GetAllRoles

Get all roles in the server.
local roles = exports.LonexDiscordAPI:GetAllRoles()
-- Returns array of role objects sorted by position (highest first)

GetRoleById

Get a specific role by ID.
local role = exports.LonexDiscordAPI:GetRoleById("123456789012345678")
-- Returns: { id, name, color, position, permissions, ... }

GetRoleByName

Get a role by name (for display/lookup purposes).
local role = exports.LonexDiscordAPI:GetRoleByName("Admin")

GetRoleIdFromName

Get role ID from name.
local roleId = exports.LonexDiscordAPI:GetRoleIdFromName("Admin")
-- Returns: "123456789012345678"

GetRoleNameFromId

Get role name from ID.
local roleName = exports.LonexDiscordAPI:GetRoleNameFromId("123456789012345678")
-- Returns: "Admin"

GetRolesAbovePosition

Get all roles above a certain position.
local highRoles = exports.LonexDiscordAPI:GetRolesAbovePosition(10)

GetRolesWithPermission

Get roles that have a specific Discord permission.
local adminRoles = exports.LonexDiscordAPI:GetRolesWithPermission("administrator")
local modRoles = exports.LonexDiscordAPI:GetRolesWithPermission("kick_members")

RefreshRoles

Force refresh roles from Discord API.
exports.LonexDiscordAPI:RefreshRoles()

Permission System

The permission system automatically maps Discord roles to FiveM ACE permissions.

Configuration

In config.lua, define role mappings using Role IDs:
Config.Permissions = {
    Enabled = true,
    
    Roles = {
        ['123456789012345678'] = {  -- Member role ID
            permissions = { 'command.help', 'command.me' },
            groups = { 'user' },
            priority = 1,
        },
        
        ['234567890123456789'] = {  -- Moderator role ID
            permissions = { 'command.kick', 'command.warn' },
            groups = { 'mod' },
            inherits = { '123456789012345678' },  -- Inherits Member permissions
            priority = 50,
        },
        
        ['345678901234567890'] = {  -- Admin role ID
            permissions = { 'command.*', 'admin.*' },  -- Wildcards supported
            groups = { 'admin' },
            inherits = { '234567890123456789' },
            priority = 100,
        },
    },
}

HasPermission

Check if player has a specific permission.
local canKick = exports.LonexDiscordAPI:HasPermission(source, "command.kick")

HasAnyPermission

Check if player has any of the specified permissions.
local canModerate = exports.LonexDiscordAPI:HasAnyPermission(source, {
    "command.kick",
    "command.ban",
    "command.mute",
})

HasAllPermissions

Check if player has all specified permissions.
local isFullAdmin = exports.LonexDiscordAPI:HasAllPermissions(source, {
    "admin.noclip",
    "admin.godmode",
})

IsInGroup

Check if player is in an ACE group.
local isAdmin = exports.LonexDiscordAPI:IsInGroup(source, "admin")

GetPermissions

Get all permissions assigned to a player.
local perms = exports.LonexDiscordAPI:GetPermissions(source)
-- Returns: { "command.help", "command.kick", "admin.spectate", ... }

GetGroups

Get all ACE groups assigned to a player.
local groups = exports.LonexDiscordAPI:GetGroups(source)
-- Returns: { "user", "mod", "admin" }

SyncPermissions

Manually re-sync a player’s permissions from Discord.
local success, err = exports.LonexDiscordAPI:SyncPermissions(source)

ResyncAllPermissions

Re-sync permissions for all connected players.
exports.LonexDiscordAPI:ResyncAllPermissions()

Webhooks

Send messages and embeds to Discord channels via webhooks.

Configuration

In config.lua, define your webhooks:
Config.Webhooks = {
    Enabled = true,
    
    Urls = {
        ['logs'] = 'https://discord.com/api/webhooks/xxx/xxx',
        ['admin'] = {
            url = 'https://discord.com/api/webhooks/xxx/xxx',
            username = 'Admin Bot',
            avatar_url = 'https://example.com/avatar.png',
        },
    },
    
    Templates = {
        ['player_join'] = {
            title = '👋 Player Connected',
            description = '**{player}** joined the server',
            color = 5763719,
        },
    },
}

SendWebhookMessage

Send a simple text message.
local success, err = exports.LonexDiscordAPI:SendWebhookMessage('logs', 'Server restarting in 5 minutes!')

SendWebhookEmbed

Send an embed.
local success, err = exports.LonexDiscordAPI:SendWebhookEmbed('logs', {
    title = 'Player Report',
    description = 'A player has been reported for cheating',
    color = 16711680,  -- Red (decimal)
    fields = {
        { name = 'Reporter', value = 'John', inline = true },
        { name = 'Suspect', value = 'Jane', inline = true },
        { name = 'Reason', value = 'Speed hacking', inline = false },
    },
    footer = { text = 'Report ID: 12345' },
    thumbnail = 'https://example.com/image.png',
})

SendWebhookTemplate

Send using a pre-defined template with placeholders.
local success, err = exports.LonexDiscordAPI:SendWebhookTemplate('logs', 'player_join', {
    player = 'John Doe',
    discord = '<@306838265174949888>',
    id = source,
})

SendWebhook

Send a full webhook payload (advanced).
local success, err = exports.LonexDiscordAPI:SendWebhook('logs', {
    content = 'Hello @everyone!',
    username = 'Custom Bot',
    avatar_url = 'https://example.com/avatar.png',
    embeds = {
        { title = 'Embed 1', description = 'First embed' },
        { title = 'Embed 2', description = 'Second embed' },
    },
})

SendWebhookDirect

Send directly to a URL (bypasses named webhooks).
local success, err = exports.LonexDiscordAPI:SendWebhookDirect('https://discord.com/api/webhooks/xxx/xxx', {
    content = 'Direct message',
})

BuildEmbed

Build an embed object for use elsewhere.
local embed = exports.LonexDiscordAPI:BuildEmbed({
    title = 'My Embed',
    description = 'Description here',
    color = 5793266,
    fields = {
        { name = 'Field', value = 'Value', inline = true },
    },
})

BuildEmbedFromTemplate

Build an embed from a template.
local embed = exports.LonexDiscordAPI:BuildEmbedFromTemplate('player_join', {
    player = 'John',
})

Embed Options

OptionTypeDescription
titlestringEmbed title
descriptionstringEmbed description
colornumberDecimal color (e.g., 16711680 for red)
urlstringURL for the title
thumbnailstringThumbnail image URL
imagestringLarge image URL
authortable{ name, url, icon_url }
footerstring/table"text" or { text, icon_url }
fieldstableArray of { name, value, inline }
timestampstringISO timestamp (auto-added by default)

Color Reference

Common colors in decimal:
  • Red: 16711680
  • Green: 5763719
  • Blue: 5793266
  • Yellow: 16776960
  • Orange: 16744448
  • Purple: 10181046

Cache Management

InvalidatePlayer

Clear cached data for a player (forces re-fetch on next request).
exports.LonexDiscordAPI:InvalidatePlayer(source)

InvalidatePlayerById

Clear cache by Discord ID.
exports.LonexDiscordAPI:InvalidatePlayerById("306838265174949888")

PrefetchAllPlayers

Fetch and cache data for all connected players.
exports.LonexDiscordAPI:PrefetchAllPlayers()

ClearCache

Clear all cached data.
exports.LonexDiscordAPI:ClearCache()

GetCacheStats

Get cache statistics.
local stats = exports.LonexDiscordAPI:GetCacheStats()
-- Returns: { members = 25, roles = 15, users = 30, ... }

GetHttpStats

Get HTTP request statistics.
local stats = exports.LonexDiscordAPI:GetHttpStats()
-- Returns: {
--   totalRequests = 150,
--   successfulRequests = 148,
--   failedRequests = 2,
--   rateLimitHits = 0,
--   retries = 1,
-- }

Utilities

IsInitialized

Check if the API is ready.
local ready = exports.LonexDiscordAPI:IsInitialized()
if not ready then
    print("Discord API not ready yet")
end

GetInitializationError

Get initialization error if any.
local err = exports.LonexDiscordAPI:GetInitializationError()
if err then
    print("Init failed: " .. err)
end

Server Utilities

LonexDiscordAPI includes built-in server utilities for AOP, PeaceTime, Announcements, Postals, and HUD. These are managed via config and chat commands, but you can also listen to events from your own resources.

AOP (Area of Play)

Command: /aop <zone> - Change the current AOP Events:
-- Listen for AOP changes
AddEventHandler('LonexDiscord:AOP:Changed', function(newAOP)
    print('AOP changed to: ' .. newAOP)
end)

PeaceTime

Commands: /peacetime or /pt - Toggle PeaceTime Features (v1.2.0):
  • Weapons are automatically disabled during PeaceTime
  • Speed limit warnings when driving over the configured limit
Events:
-- Listen for PeaceTime changes
AddEventHandler('LonexDiscord:PeaceTime:Changed', function(enabled)
    if enabled then
        print('PeaceTime is now ON')
    else
        print('PeaceTime is now OFF')
    end
end)

Announcements

Command: /announce <message> - Send a server-wide announcement Events:
-- Listen for announcements (client-side)
AddEventHandler('LonexDiscord:Announcement:Show', function(data)
    -- data.message = announcement text
    -- data.duration = display duration
    print('Announcement: ' .. data.message)
end)

Postals

Command: /postal <code> - Set waypoint to postal code, /postal - Cancel waypoint Events:
-- Listen for postal waypoint set (client-side)
AddEventHandler('LonexDiscord:Postal:Set', function(postal)
    -- postal.code = postal code
    -- postal.x, postal.y = coordinates
    print('Waypoint set to postal ' .. postal.code)
end)

-- Listen for postal waypoint cancelled (client-side)
AddEventHandler('LonexDiscord:Postal:Cancel', function()
    print('Postal waypoint cancelled')
end)

Server HUD

The Server HUD displays compass, street, zone, postal, AOP, PeaceTime status, and player info. Command: /togglehud - Toggle HUD visibility Placeholders available:
  • {COMPASS} - Direction (N, NE, E, etc.)
  • {STREET} - Current street name
  • {ZONE} - Current zone/area
  • {POSTAL} - Nearest postal code
  • {POSTAL_DIST} - Distance to nearest postal
  • {AOP} - Current Area of Play
  • {PEACETIME} - PeaceTime status
  • {ID} - Player’s server ID
  • {PLAYERS} - Online player count
  • {TAG} - Player’s current tag

Emergency Calls

The emergency calls system (911/311) allows players to request assistance with location tracking.

Commands

  • /911 <message> - Send emergency call
  • /311 <message> - Send non-emergency call (if enabled)
  • /resp <call_id> - Respond to a call (sets waypoint)
  • /duty - Toggle duty status (if duty system enabled)

Events

-- Server: Listen for incoming calls
AddEventHandler('LonexDiscord:EmergencyCall:Submit', function(callType, message, coords)
    -- callType = '911' or '311'
    -- message = caller's message
    -- coords = { x, y, z }
    print('New ' .. callType .. ' call: ' .. message)
end)

-- Client: Notified when a call comes in (responders only)
AddEventHandler('LonexDiscord:EmergencyCall:Notify', function(callType, callId)
    print('New ' .. callType .. ' call received! ID: ' .. callId)
end)

-- Client: Set waypoint to call location
AddEventHandler('LonexDiscord:EmergencyCall:SetWaypoint', function(coords)
    -- coords = { x, y, z }
end)

-- Client: Duty status changed
AddEventHandler('LonexDiscord:EmergencyCall:DutyChanged', function(isOnDuty)
    if isOnDuty then
        print('You are now ON DUTY')
    else
        print('You are now OFF DUTY')
    end
end)

Tags System

The unified tags system provides head tags, chat prefixes, and pma-voice integration.

Commands

  • /tags - Open the tag selection menu

Events

-- Client: Player tag updated
AddEventHandler('LonexDiscord:Tags:UpdatePlayer', function(playerId, tagData)
    -- tagData.tag = { text, color }
    -- tagData.settings = { showOthers, showOwn }
    print('Player ' .. playerId .. ' tag: ' .. tagData.tag.text)
end)

-- Client: Request to sync all tags
AddEventHandler('LonexDiscord:Tags:SyncAll', function(allTags, settings, available, selectedIndex)
    -- allTags = table of all player tags
    -- settings = player's tag settings
    -- available = tags available to this player
    -- selectedIndex = currently selected tag index
end)

-- Client: Player left (remove their tag)
AddEventHandler('LonexDiscord:Tags:PlayerLeft', function(playerId)
    print('Player ' .. playerId .. ' left, removing tag')
end)

-- Client: Open tag menu
AddEventHandler('LonexDiscord:Tags:OpenMenu', function(available, selectedIndex, settings)
    -- available = tags available to player
    -- selectedIndex = currently selected
    -- settings = { showOthers, showOwn }
end)

Server Events (for custom integrations)

-- Request tag sync from server
TriggerServerEvent('LonexDiscord:Tags:RequestSync')

-- Select a tag (by index in available list)
TriggerServerEvent('LonexDiscord:Tags:SelectTag', tagIndex)

-- Update settings
TriggerServerEvent('LonexDiscord:Tags:UpdateSettings', {
    showOthers = true,
    showOwn = true,
})

Activity System

The Activity System provides comprehensive duty tracking for emergency services with live blips, loadouts, database logging, and HTTP API access.

Commands

  • /duty [department] - Clock in/out of duty
  • /bliptag [id] - Change your displayed blip tag
  • /units - List all on-duty players by department

IsOnDuty

Check if a player is currently on duty.
local onDuty = exports.LonexDiscordAPI:IsOnDuty(source)
-- Returns: true or false

GetPlayerDepartment

Get the department a player is currently on duty for.
local department = exports.LonexDiscordAPI:GetPlayerDepartment(source)
-- Returns: "leo" or nil if not on duty

GetDutyInfo

Get full duty information for a player.
local info = exports.LonexDiscordAPI:GetDutyInfo(source)
-- Returns: {
--   department = "leo",
--   discordId = "306838265174949888",
--   playerName = "John Doe",
--   clockIn = 1706185200,  -- Unix timestamp
--   blipTag = "leo",
-- } or nil if not on duty

GetOnDutyPlayers

Get all currently on-duty players.
local players = exports.LonexDiscordAPI:GetOnDutyPlayers()
-- Returns: {
--   {
--     source = 1,
--     department = "leo",
--     discordId = "306838265174949888",
--     playerName = "John Doe",
--     clockIn = 1706185200,
--     durationSeconds = 3600,
--   },
--   ...
-- }

GetOnDutyByDepartment

Get on-duty players for a specific department.
local leoPlayers = exports.LonexDiscordAPI:GetOnDutyByDepartment('leo')
-- Returns array of player info (same format as GetOnDutyPlayers)

GetDepartmentCounts

Get count of on-duty players per department.
local counts = exports.LonexDiscordAPI:GetDepartmentCounts()
-- Returns: { leo = 5, fire = 2, ems = 3 }

SetDutyStatus

Programmatically set a player’s duty status.
-- Clock in to a department
local success = exports.LonexDiscordAPI:SetDutyStatus(source, true, 'leo')

-- Clock out
local success = exports.LonexDiscordAPI:SetDutyStatus(source, false)

GetDutyDuration

Get how long a player has been on duty (in seconds).
local seconds = exports.LonexDiscordAPI:GetDutyDuration(source)
-- Returns: 3600 (1 hour) or 0 if not on duty

GetPlayerDepartments

Get list of departments a player has access to (based on Discord roles).
local departments = exports.LonexDiscordAPI:GetPlayerDepartments(source)
-- Returns: { "leo", "fire" }

Activity System Events

-- Server: Fired when player clocks in
AddEventHandler('LonexDiscord:Activity:OnDuty', function(source, department)
    print(GetPlayerName(source) .. ' is now on duty as ' .. department)
end)

-- Server: Fired when player clocks out
AddEventHandler('LonexDiscord:Activity:OffDuty', function(source, department, durationSeconds)
    local hours = math.floor(durationSeconds / 3600)
    local mins = math.floor((durationSeconds % 3600) / 60)
    print(GetPlayerName(source) .. ' was on duty for ' .. hours .. 'h ' .. mins .. 'm')
end)

HTTP API Endpoints

When Config.ActivitySystem.API.Enabled = true, the following endpoints are available: Get Online Units
GET /lonex/activity/online
Authorization: your-token

Response:
{
  "success": true,
  "data": {
    "total": 10,
    "departments": { "leo": 5, "fire": 3, "ems": 2 },
    "players": [
      {
        "source": 1,
        "playerName": "John Doe",
        "department": "leo",
        "discordId": "306838265174949888",
        "durationSeconds": 3600
      }
    ]
  }
}
Get Player History
GET /lonex/activity/history?discord_id=306838265174949888&days=7
Authorization: your-token

Response:
{
  "success": true,
  "data": {
    "discordId": "306838265174949888",
    "sessions": [
      {
        "department": "leo",
        "clockIn": "2024-01-25T10:00:00Z",
        "clockOut": "2024-01-25T14:00:00Z",
        "duration": 14400
      }
    ],
    "totals": { "leo": 36000, "fire": 7200 }
  }
}
Get Leaderboard
GET /lonex/activity/leaderboard?department=leo&days=30&limit=10
Authorization: your-token

Response:
{
  "success": true,
  "data": [
    {
      "discordId": "306838265174949888",
      "totalSeconds": 360000,
      "totalFormatted": "100h 0m"
    }
  ]
}

Blip Features

The Activity System provides live blips for on-duty players:
  • Dynamic Sprites: Different icons for on-foot vs in-vehicle
  • Siren Detection: Blips flash red/blue when lights & sirens are active
  • Heading Indicator: Shows which direction the player is facing
  • Department Tags: Display department abbreviation on blip

Loadout System

When players clock in, they automatically receive configured weapons and armor:
-- In config.lua
Departments = {
    ['leo'] = {
        Loadout = {
            Armor = 100,
            Weapons = {
                { weapon = 'WEAPON_COMBATPISTOL', ammo = 120, tint = 5, attachments = { 'COMPONENT_AT_PI_FLSH' } },
                { weapon = 'WEAPON_STUNGUN', ammo = 1 },
            },
        },
    },
}
Weapons and armor are automatically removed when clocking out (if configured).

Error Handling

Most functions that can fail return value, error:
local member, err = exports.LonexDiscordAPI:GetDiscordMember(source)
if not member then
    print("Error: " .. (err or "Unknown error"))
    return
end

-- Safe to use member here
print("Player nickname: " .. (member.nickname or "None"))
For role management, always check success:
local success, err = exports.LonexDiscordAPI:AddRole(source, "123456789012345678", "Reason")
if success then
    print("Role added!")
else
    print("Failed: " .. err)
end

Events

The resource triggers these events that you can listen for:
-- Player permissions synced
AddEventHandler('LonexDiscord:PermissionsSynced', function(source, permissions, groups)
    print("Player " .. source .. " has " .. #permissions .. " permissions")
end)

-- Utility state synced to client
AddEventHandler('LonexDiscord:Utils:SyncState', function(state)
    -- state.aop = current AOP
    -- state.peacetime = PeaceTime enabled
end)

-- Activity System: Player clocked in
AddEventHandler('LonexDiscord:Activity:OnDuty', function(source, department)
    print("Player " .. source .. " is now on duty as " .. department)
end)

-- Activity System: Player clocked out
AddEventHandler('LonexDiscord:Activity:OffDuty', function(source, department, durationSeconds)
    print("Player " .. source .. " was on duty for " .. durationSeconds .. " seconds")
end)

Debug Commands

Available when Config.Debug = true:
CommandDescription
lonex_discord_statusShow initialization status
lonex_discord_guildShow guild information
lonex_discord_rolesList all cached roles
lonex_discord_testTest player exports (in-game)
lonex_discord_testid <discord_id>Test by Discord ID
lonex_discord_addrole <discord_id> <role_id>Add role
lonex_discord_removerole <discord_id> <role_id>Remove role
lonex_discord_setnick <discord_id> [nickname]Set nickname
lonex_discord_perms <player_id>Show player permissions
lonex_debug_vehicles <player_id>Debug vehicle permissions
lonex_discord_hasperm <player_id> <perm>Check permission
lonex_discord_syncperms <player_id/all>Sync permissions
lonex_discord_testwebhook <webhook_name>Test webhook
lonex_discord_webhook <name> <message>Send webhook message