Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/VasquezRivero92/Discord_Faceit/llms.txt

Use this file to discover all available pages before exploring further.

The bot keeps your Discord server’s role hierarchy in perfect sync with Faceit. Level roles are created on demand with the correct colour, assigned on verification, and updated after every finished match. Club membership roles arrive via Faceit Hub webhooks the moment they are granted or revoked on the platform. Every piece of role logic lives in services/roles.js and is wired together in webhooks/faceit.js and events/ready.js.
The bot’s own role must sit above all Faceit Level and Club roles in your server’s role hierarchy, and the bot must have the Manage Roles permission. Without this, guild.roles.create() and member.roles.add() will throw a permissions error and role sync will silently fail.

Level Roles — Faceit Level 1 through Faceit Level 10

Auto-creation with getOrCreateLevelRole()

async function getOrCreateLevelRole(guild, level)
When a sync is needed, this function searches guild.roles.cache for a role named Faceit Level <N>. If the role does not exist it calls guild.roles.create() with the appropriate colour from LEVEL_ROLE_COLORS (defined in config/index.js).

Color Table

RoleLevelsHex
Faceit Level 1Faceit Level 31, 2, 3#8C8C8C grey
Faceit Level 4Faceit Level 74, 5, 6, 7#15C253 green
Faceit Level 8Faceit Level 98, 9#FF9E00 orange
Faceit Level 1010#FF3E3E red

Syncing a Member — syncMemberLevelRole()

async function syncMemberLevelRole(guild, memberId, level)
This is the workhorse of the role system. It:
  1. Fetches the guild member.
  2. Calls getOrCreateLevelRole(guild, level) to obtain the target role.
  3. Iterates levels 1–10, building a list of all other Faceit Level X roles that the member currently holds.
  4. Removes those roles in a single member.roles.remove(rolesToRemove) call.
  5. Adds the new target role if the member does not already have it.
syncMemberLevelRole() is triggered in three scenarios:
  • On verification — immediately after db.linkAccounts() if autoRoleSync is enabled.
  • On /sincronizar_fc — when a player manually requests a sync.
  • After a finished matchsyncPlayerLevels() in webhooks/faceit.js runs it for every player in both rosters.

Detecting the Skill Level — getPlayerSkillLevel()

export function getPlayerSkillLevel(playerData) {
  return playerData.games?.cs2?.skill_level
      || playerData.games?.csgo?.skill_level
      || null;
}
CS2 is always checked first; CS:GO is the fallback for players who have not yet played CS2 ranked.

Club / Special Roles

Club roles represent membership tiers in the Faceit Hub. They are defined in config/index.js in the CLUB_ROLES_MAP object, which maps Faceit role UUIDs to Discord role names:
Faceit UUIDDiscord RoleHex Color
d79607e7-77b8-4db0-9abf-c2592820066cEXTREME#FF0000
f6b04720-3908-4933-9555-f61e63bf420bEXTREME BAJOS#D35400
dfb94a9b-b17f-4f8e-ace7-6d4863b2ea69PREMIUM#FFD700
38d0142f-04da-4130-8df6-c5d801ff5c3ePLUS#00BFFF

Webhook-Driven Role Events

The hub_user_role_added and hub_user_role_removed webhook events call handleRoleEvent() in webhooks/faceit.js. The flow:
1

Look up the Faceit player

roleData.user_id is used to call db.getDiscordIdByFaceitId() — no Discord ID means the player is unverified and the event is skipped.
2

Resolve the Discord role

getOrCreateSpecialRole(guild, roleName) finds the role in guild.roles.cache (case-insensitive) or creates it with the colour from SPECIAL_ROLE_COLORS.
3

Add or remove

For hub_user_role_added, the role is added and a public notification is sent in DISCORD_ROLES_CHANNEL_ID:
✨ @Player ha recibido el rol de Club: EXTREME
For hub_user_role_removed, the role is removed and a warning notification is posted.

Auto-create with getOrCreateSpecialRole()

async function getOrCreateSpecialRole(guild, roleName)
Role name matching is case-insensitive (roleName.toUpperCase()). If the role does not exist it is created with the colour from SPECIAL_ROLE_COLORS. This means you never need to manually create Club roles — they appear the first time a webhook fires.

Removing All Roles — removeAllFaceitRoles()

Used by /desvincular_fc to cleanly strip every Faceit-related role when unlinking:
async function removeAllFaceitRoles(member, guild)
It iterates Faceit Level 1 through Faceit Level 10 plus the four special roles (EXTREME, EXTREME BAJOS, PREMIUM, PLUS), collects those the member actually has, and removes them in one batched call. Returns the count of removed roles.

Automatic 12-Hour Bulk Sync

Every 12 hours (events/ready.js), syncAllUserRoles() iterates every document in the faceit_users Firestore collection and:
  1. Fetches the current Faceit profile via fetchFaceitPlayerById().
  2. Calls syncMemberLevelRole() with the fresh level.
  3. Writes the updated level and ELO back to Firestore via db.updatePlayerStats().
A 150 ms delay (setTimeout(resolve, 150)) is inserted between each user to respect Faceit API rate limits. The sync is silently skipped if autoRoleSync is false in settings.
You can also trigger a manual bulk sync at any time from the Sincronizar button in the admin panel, which calls POST /api/admin/users/sync-all.

Feature Flag

FlagEffect
autoRoleSyncMaster switch for all role assignment — level roles on link/sync, Club roles on webhook events, and the 12-hour scheduled bulk sync

Build docs developers (and LLMs) love