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.

Every time a match changes state in your Faceit Hub, a webhook fires and the bot translates it into a rich Discord embed. Rather than posting separate messages for each stage, the bot edits the same message in place — so your announcements channel stays clean and each match is represented by a single, always-up-to-date post. The full pipeline lives in webhooks/faceit.js and services/matchMessages.js.

The Four Match States

The bot handles six incoming webhook event types, mapped to four distinct embed styles:
Webhook eventState labelEmbed color
match_status_configuringConfiguring#FFAA00 orange
match_status_starting / match_status_readyStarted#FF6B00 orange-red
match_status_finishedFinished#10B981 green
match_status_cancelled / match_status_abortedCancelled#EF4444 red
Any other webhook event type is logged and silently ignored.
Set DISCORD_MATCHES_CHANNEL_ID (or discordMatchesChannelId in the admin settings panel) to the channel where all match embeds should be posted. The value may be a comma-separated list of channel IDs; the bot will use the first one it can successfully fetch.

Embed Details from createMatchEmbed()

Each embed is produced by the createMatchEmbed(matchData, type) function in services/matchMessages.js.
Title: 🎮 ¡Lobby de Partida Creado!Signals that captains are in the Faceit voting phase (map and server selection). Fields shown:
  • 🌐 ClubmatchData.entity_custom_name
  • 🎮 Game — e.g., CS2
The embed links directly to https://www.faceit.com/en/cs2/room/<matchId>. The Discord message ID returned by channel.send() is persisted to Firestore via db.addActiveMatch() so it can be edited in subsequent states.
Title: 🎮 ¡Partida Iniciada en el Club!Posted (or the configuring embed is edited in-place) once the match begins. Fields shown:
  • 🌐 Club
  • 🗺️ Map — from matchData.voting.map.pick[0]
  • 📍 Server — from matchData.voting.location.pick[0]
  • 👥 Team A roster — built by buildTeamList()
  • 👥 Team B roster — built by buildTeamList()
Player names in the roster are Discord mentions (<@discordId>) for verified players, or code-formatted Faceit nicknames for unverified ones.
Title: 🏁 Partida FinalizadaThe started embed is edited in-place. Additional fields shown:
  • 📊 Score — formatted with a 🏆 trophy next to the winner’s score, e.g., 🏆 **16** vs 10
  • 🏆 Winner — the winning team name highlighted with 🎉
After the embed is updated, all players in the match have their Faceit level and ELO re-synced via syncPlayerLevels() if autoRoleSync is enabled.
Title: ❌ Partida CanceladaThe existing embed is edited to show the cancellation notice. Fields include club, map, and server. The description reads:
⚠️ Esta partida fue cancelada o abortada en Faceit.
The active match record is removed from Firestore via db.removeActiveMatch().

In-Place Message Editing

Whenever the bot receives a match_status_starting or terminal event, it calls db.getActiveMatch(matchData.id) to retrieve the message_id stored during the configuring phase. It then fetches that message with channel.messages.fetch(activeMatch.message_id) and calls msg.edit({ embeds: [newEmbed] }). If the original message has been deleted, a new message is sent instead and the record is updated.

Team List Building — buildTeamList()

async function buildTeamList(faction, db, guildId)
For each player in faction.roster, the function:
  1. Tries db.getDiscordIdByFaceitId(playerId, guildId) first.
  2. Falls back to db.getDiscordIdByNickname(p.nickname, guildId) if the ID lookup fails.
  3. Returns a <@discordId> mention for linked players, or `nickname` in backticks for unlinked ones.
The result is a numbered list (1–5) added as an inline field for each team.

Live Match Panel — updateLivePanel()

When the liveMatchPanel feature flag is enabled, updateLivePanel(client, matchesChannelId, db) maintains a single pinned embed in DISCORD_MATCHES_CHANNEL_ID listing every active match at a glance. It is called after every state change.

Active matches

Each entry shows team names (linked to the Faceit room), map, server location, and a relative timestamp using Discord’s <t:...:R> format.

No matches

When db.getActiveMatches() returns an empty array, the panel shows a grey embed inviting players to queue in Faceit.
The panel message is pinned automatically the first time it is created. Its message ID and channel ID are persisted via db.setPanelMessageConfig() so it survives bot restarts.

Server Status Embed — createServerStatusEmbed()

When serverStatusAnnouncements is enabled and DISCORD_STATUS_CHANNEL_ID is configured, the bot posts or edits a status embed in the status channel every time a match starts. The embed shows:
  • FACEIT API, LiveChat Service, Steam API, Steam Sessions, and Steam Community — all reported as Operational.
  • LATAM server regions with their current status:
    • 🇵🇪 Lima
    • 🇨🇱 Santiago
    • 🇦🇷 Buenos Aires
    • 🇧🇷 São Paulo
  • The currently active server is highlighted with 👈 (Jugando aquí 🎮).
  • The latest CS2 patch note date (fetched from the Steam API) if available.
The status message is edited in-place on subsequent match starts via db.setStatusMessageConfig() / db.getStatusMessageConfig().

Feature Flags

FlagEffect
matchAnnouncementsMaster switch — disables all match embed posting when off
liveMatchPanelControls the pinned live-panel embed in the matches channel
serverStatusAnnouncementsControls the LATAM server status embed in the status channel

Build docs developers (and LLMs) love