Documentation Complete - Version 3.5.0

Puissance 4 API

Référence HTTP + Socket.IO du projet en version 3.5.0. Cette page décrit les routes disponibles, les erreurs probables, les headers attendus et des exemples directement réutilisables. Elle inclut les styles de pseudo, la recherche des bots, les historiques ELO humain/bot, les outils développeur et les commandes Discord francisées.

Base API
/api/...
Session joueur
token ou x-session-token
Session admin
x-admin-token
Version active
3.5.0

Authentification

Création de compte, connexion classique et reset de mot de passe.

POSTGET
POST/api/auth/register

Crée un nouveau compte joueur.

Body
pseudo, password, color, shape
Erreurs
pseudo déjà pris, pseudo invalide, mot de passe manquant
await fetch('/api/auth/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    pseudo: 'Lili_y',
    password: 'MonMotDePasse',
    color: '#ff2d55',
    shape: 'circle'
  })
});
curl -X POST http://localhost:8080/api/auth/register ^
  -H "Content-Type: application/json" ^
  -d "{\"pseudo\":\"Lili_y\",\"password\":\"MonMotDePasse\",\"color\":\"#ff2d55\",\"shape\":\"circle\"}"
POST/api/auth/login

Connecte un joueur avec pseudo + mot de passe.

const res = await fetch('/api/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ pseudo: 'Lili_y', password: 'MonMotDePasse' })
});
const data = await res.json();
localStorage.setItem('token', data.token);
curl -X POST http://localhost:8080/api/auth/login ^
  -H "Content-Type: application/json" ^
  -d "{\"pseudo\":\"Lili_y\",\"password\":\"MonMotDePasse\"}"
POST/api/auth/guest

Crée une session invité locale. Utilisé pour les duels amicaux sans connexion.

Retour
token + player invité
Usage
création ou acceptation d'un duel amical sans compte
const guest = await fetch('/api/auth/guest', { method: 'POST' })
  .then(r => r.json());
localStorage.setItem('token', guest.token);
localStorage.setItem('player', JSON.stringify(guest.player));
curl -X POST http://localhost:8080/api/auth/guest
POST/api/reset-password

Réinitialise le mot de passe avec un code envoyé via Discord.

Erreurs typiques : joueur introuvable, code expiré, code invalide.

Joueurs et Profil

Lecture de profil, recherche, follow, cosmétique, statut live et premium.

GETPATCHPOSTDELETE
GET/api/players/:id

Retourne le profil complet d’un joueur.

{
  "id": 2,
  "pseudo": "Lili_y",
  "elo": 1000,
  "coins": 250,
  "role": "admin",
  "is_vip": 1,
  "is_vip_plus": 0,
  "is_perso": 1,
  "avatar": "...",
  "banner": "...",
  "avatar_decoration": "/decorations/frame.png",
  "shape": "circle",
  "color": "#ff2d55",
  "color_secondary": "#85EBFF",
  "pseudo_color": "#ffffff",
  "pseudo_color_secondary": "#85EBFF",
  "pseudo_font": "barlow",
  "pseudo_format": "bold,underline",
  "pseudo_rgb": 1,
  "elo_curve_color": "#ff2d55",
  "elo_curve_color_secondary": "#85EBFF",
  "elo_curve_rgb": 1,
  "referral_slug": "lili"
}
const player = await fetch('/api/players/2').then(r => r.json());
GET/api/players/:id/elo-history?days=1|7|15

Retourne la courbe ELO compressée sur 1, 7 ou 15 jours. Les historiques des bots incluent leurs parties contre des humains et contre d’autres bots. Chaque point indique aussi la nature de l’adversaire.

{
  "generatedAt": "2026-05-16T12:00:00.000Z",
  "player": { "id": 2, "pseudo": "Lili_y", "elo": 1012, "wins": 4, "elo_curve_rgb": 1 },
  "days": 7,
  "points": [{
    "gameId": 42,
    "finishedAt": "2026-05-16 12:00:00",
    "beforeElo": 1000,
    "afterElo": 1012,
    "delta": 12,
    "result": "win",
    "opponent": { "id": 7, "pseudo": "P4-Bot-Nova", "isBot": true }
  }],
  "stats": {
    "startElo": 1000, "endElo": 1012, "delta": 12,
    "games": 3, "gamesAgainstHumans": 2, "gamesAgainstBots": 1,
    "averageElo": 1008
  }
}
curl "http://localhost:8080/api/players/2/elo-history?days=7"
GET/api/players/:id/elo-history/export?days=1|7|15&format=json|csv

Télécharge les données brutes du graphique ELO en JSON ou CSV. Le bouton CSV/JSON du profil utilise cet endpoint.

curl -L "http://localhost:8080/api/players/2/elo-history/export?days=7&format=csv" -o elo-history.csv
const file = await fetch('/api/players/2/elo-history/export?days=15&format=json').then(r => r.json());
GET/api/players?type=all|humans|bots&online=1&q=...

Annuaire public des joueurs et bots : ELO, badges, rang, statut online, file et partie active. Utilisé par /players et /bots.

curl "http://localhost:8080/api/players?type=bots"
const bots = await fetch('/api/players?type=bots').then(r => r.json());
GET/api/players/search?q=...&includeBots=0|1

Recherche par pseudo pour le profil et l’autocomplete. Par défaut, seuls les humains sont retournés. includeBots=1 ajoute les bots et chaque résultat expose is_bot pour afficher son badge.

POST/api/players/:id/convert-bot

Transforme un compte non lié Discord en compte bot API. Session joueur obligatoire. Accepte owner, ownerPseudo, ownerId ou creatorId pour associer un créateur humain qui recevra les Cristaux du bot.

Retour
botToken, activationCurl, owner optionnel
Erreur
403 session invalide, 409 compte lié Discord ou déjà bot, 400 créateur invalide
GET/api/players/by-pseudo/:pseudo

Lookup direct par pseudo exact.

PATCH/api/players/:id/pseudo

Change le pseudo côté joueur.

Règles
3 à 16 caractères, unique, 1 fois / 30 jours
Erreurs
session invalide, pseudo pris, cooldown actif, format invalide
await fetch('/api/players/2/pseudo', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token, pseudo: 'Crystal' })
});
curl -X PATCH http://localhost:8080/api/players/2/pseudo ^
  -H "Content-Type: application/json" ^
  -d "{\"token\":\"SESSION_TOKEN\",\"pseudo\":\"Crystal\"}"
PATCH/api/players/:id/color

Met à jour la couleur principale du pion, et selon le pack la seconde couleur.

PATCH/api/players/:id/shape

Définit la forme active du pion.

PATCH/api/players/:id/pseudo-style

Met à jour la couleur, le dégradé, la police et la mise en forme du pseudo. format accepte une liste séparée par des virgules parmi bold, italic, underline, lowercase et uppercase. Minuscules et majuscules sont mutuellement exclusives. rgb active la vague colorée animée.

Body
token, color, colorSecondary, font, format, rgb
Accès
VIP, VIP+, Perso, admin. Dégradé réservé VIP+/Perso.
await fetch('/api/players/2/pseudo-style', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token, color: '#ffffff', colorSecondary: '#85EBFF',
    font: 'orbitron', format: 'bold,underline', rgb: true
  })
});
PATCH/api/players/:id/elo-curve-style

Met à jour la couleur du graphique ELO. Le champ rgb active une vague RGB animée, réservée au rang Perso.

Body
token, color, colorSecondary, rgb
Cooldown
VIP/VIP+ toutes les 24h, Perso sans limite.
await fetch('/api/players/2/elo-curve-style', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token, color: '#ff2d55', colorSecondary: '#85EBFF', rgb: true })
});
PATCH/api/players/:id/custom-role

Met à jour le badge Perso directement depuis le profil joueur. Utilise un texte court, un emoji optionnel et une couleur simple ou en dégradé via colorSecondary.

PATCH/api/players/:id/avatar

Change l’avatar. Erreurs typiques : fichier trop lourd, GIF non autorisé, cooldown VIP/VIP+ actif.

PATCH/api/players/:id/banner

Change la bannière principale du profil.

PATCH/api/players/:id/token-emoji

Définit l’emoji custom ou l’image emoji selon le pack.

PATCH/api/players/:id/custom-cursor

Applique ou retire un curseur PNG 32x32. Fonction réservée au grade Perso, avec token et cursor dans le body.

PATCH/api/players/:id/wallpaper

Applique ou retire un fond personnalisé pour le profil/site. Session joueur obligatoire, payload avec token, image et options de rendu.

PATCH/api/players/:id/avatar-decoration

Applique une décoration d’avatar depuis la bibliothèque serveur.

PATCH/api/players/:id/profile-banner

Applique une bannière pseudo depuis la bibliothèque serveur.

GET/api/decorations

Liste auto des décorations disponibles.

{ "decorations": ["/decorations/a.png", "/decorations/b.png"] }
GET/api/token-collection/catalog

Liste publique des pions secrets, modèles, thèmes et taux de spawn : Commun 49 %, Rare 25 %, Épique 12 %, Légendaire 7 %, Mythique 3,5 %, Artefact 1,5 %, QueenPawn 1 %, Fantastique 0,9 % et Inoubliable 0,1 %.

Retour
items, rarities, themes, total
Designs
classic, ring, queen-dark, dragon-gem, image, event-*...
GET/api/players/:id/token-collection

Retourne la collection publique d’un joueur : quantité par pion secret, doublons, progression, copies, regroupements par rareté et par thème.

Seuls les pions voyageurs alimentent la collection. Réapparition : Joueur 1 h, VIP 30 min, VIP+ 15 min, Perso 10 min. Les petits pions trésors donnent 10 à 50 coins et ont une chance très rare de donner 5 à 10 gemmes, sans remplir la collection.
{
  "collection": {
    "items": [],
    "collectedItems": [],
    "rarities": [{ "key": "rare", "total": 8, "collected": 2, "copies": 3 }],
    "themes": [{ "label": "Prestige", "total": 8, "collected": 1, "copies": 1 }],
    "stats": { "collected": 3, "total": 39, "totalCopies": 4, "duplicates": 1 }
  }
}
GET/api/profile-banners

Liste auto des bannières pseudo disponibles.

{ "banners": ["/banners/static.png", "/banners/static2.png"] }
POST/api/players/:id/follow

Suit un joueur.

DELETE/api/players/:id/follow

Retire un follow.

GET/api/players/:id/follow-status

Retourne l’état de follow entre le joueur courant et le profil ciblé.

GET/api/players/:id/status

Retourne l’état live d’un joueur.

POST/api/players/:id/vip-boost

Active le boost premium individuel du joueur courant selon son pack actif.

GET/api/players/:id/vip-boost

Retourne l’état du boost premium individuel : actif, multiplicateur, temps restant, cooldown.

GET/api/referral/me

Retourne le lien de parrainage du joueur, son parrain actif, ses filleuls et les bonus boutique disponibles.

Le filleul obtient une remise boutique, et le parrain profite aussi de son avantage quand le lien a servi au login.
PATCH/api/referral/me

Personnalise le slug de parrainage. Le lien peut ensuite être résolu par id joueur, pseudo ou slug unique.

await fetch('/api/referral/me', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token, slug: 'lili' })
});
GET/api/crystal/alert

Lit le message de connexion Crystal du joueur courant : message, emoji, couleur, animation et état d’activation.

POST/api/crystal/alert

Met à jour l’alerte de connexion Crystal affichée une fois à la connexion, pas à chaque changement de page.

PATCH/api/players/:id/queue-music

Sélectionne la musique de file d’attente active du joueur quand la collection est disponible.

DELETE/api/players/:id

Ferme / supprime un compte joueur (session obligatoire). Ce endpoint existe dans le backend et est utilisé par le profil.

Parties, Live et Replay

Données live, reconstruction des coups, analyse, précision et IA.

GET/api/live

Liste les parties actives visibles sur la page live, y compris les parties contre bots. Le payload expose aussi les spectateurs de la partie sélectionnée.

{
  "games": [{
    "id": 1165,
    "moves": 6,
    "botGame": true,
    "spectators": [
      { "name": "Lili_y", "anonymous": false },
      { "name": "Anonyme", "anonymous": true }
    ]
  }]
}
const live = await fetch('/api/live').then(r => r.json());
GET/api/games/:id

Données de base d’une partie.

GET/api/games/:id/moves

Liste ordonnée des coups pour reconstruire la grille.

GET/api/games/:id/replay-view

Payload enrichi pour replay.html.

POST/api/games/:id/analysis

Enregistre l’analyse d’une partie. Erreurs typiques : partie introuvable, payload vide.

GET/api/games/:id/analysis

Relit l’analyse enregistrée.

POST/api/games/:id/accuracy

Stocke la précision finale côté base.

POST/api/bot-replay

Calcul bot / ELO bot / résultat IA pour le mode contre l’ordinateur. Les parties bot peuvent être enregistrées comme replay sans polluer les stats des invités amicaux.

Les fins de partie distinguent maintenant alignment, resignation, agreement_draw et position_draw. Le profil et le replay utilisent result_reason pour afficher Victoire par abandon, Nulle par accord, etc.

Boutique, Coins et Boosters

Inventaire joueur, achat de packs premium et gestion des boosters.

GET/api/shop/me

Retourne l’état complet de la boutique pour le joueur courant.

{
  "player": { "id": 2, "coins": 4800 },
  "items": { "elo_mini": { "price": 250, "multiplier": 1.05 } },
  "prices": { "elo_mini": 250 },
  "stock": { "elo_mini": 10 },
  "inventory": { "elo_mini": 2, "coin_boost": 1 },
  "limitedOffer": {
    "code": "FLASH20",
    "label": "Pack week-end",
    "expiresAt": 1779120000000,
    "coupon": { "type": "discount", "value": 20 }
  }
}
const shop = await fetch('/api/shop/me?token=' + token)
  .then(r => r.json());
curl "http://localhost:8080/api/shop/me?token=SESSION_TOKEN"
POST/api/shop/buy

Achète un pack, un booster, le rang Crystal ou offre un item à un autre joueur.

Body
token, pack, giftToId optionnel (ou giftTo avec le pseudo)
Erreurs
pas assez de coins, pack déjà actif, rupture de stock, session invalide, cadeau à soi-même
await fetch('/api/shop/buy', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token, pack: 'elo_mini', giftToId: 12 })
});
curl -X POST http://localhost:8080/api/shop/buy ^
  -H "Content-Type: application/json" ^
  -d "{\"token\":\"SESSION_TOKEN\",\"pack\":\"elo_mini\",\"giftToId\":12}"
POST/api/shop/boosters/activate

Active un booster personnel depuis l’inventaire joueur. Les boosts globaux restent gérés via l’admin.

POST/api/shop/coupon/validate

Valide un coupon boutique avant achat : remise fixe ou pourcentage, expiration, usages restants et compatibilité pack.

POST/api/shop/product-key/redeem

Utilise une clé produit créée par le staff et applique ses récompenses au joueur connecté ou à un pseudo cible.

Body
token, code, targetPseudo optionnel
Erreurs
clé invalide, déjà utilisée, expirée ou sans récompense
POST/api/shop/buy

Le pack bot_host_1m s’achète avec currency: "crystals" pour 3000 Cristaux. Le joueur doit posséder au moins un bot associé via bot_owner_id. Les comptes admin peuvent activer ou renouveler ce host gratuitement.

Les coins sont gagnés via les parties. Les gemmes complètent les coins pour certaines offres. Les boosters ELO / coins sont des items d’inventaire, distincts des boosts globaux admin.
Quand limitedOffer contient un coupon, la boutique peut l’appliquer automatiquement en preview avant confirmation d’achat. Les stocks, timers et coupons restent recalculés côté serveur au moment de valider.

Duels

Défi direct ou par lien, en Ranked ou Amical. Les liens amicaux expirent en 15 minutes et acceptent les invités.

POSTSOCKET
POST/api/duels/challenge

Envoie un duel à un joueur connecté. gameType peut valoir ranked ou friendly.

Body
token, targetId, gameType
Retour
challenge + shareUrl
Erreurs
joueur hors ligne, duel déjà en attente, joueur déjà en partie, self-duel
await fetch('/api/duels/challenge', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token,
    targetId: 12,
    gameType: 'friendly'
  })
});
curl -X POST http://localhost:8080/api/duels/challenge ^
  -H "Content-Type: application/json" ^
  -d "{\"token\":\"SESSION_TOKEN\",\"targetId\":12,\"gameType\":\"friendly\"}"
POST/api/duels/link

Crée un lien de duel partageable de type /duel/:id. En friendly, le lien expire au bout de 15 minutes et peut être créé avec une session invité.

Body
token, gameType
Retour
challenge.id, shareUrl, mode, statut, expiresAt
Erreurs
session invalide, joueur déjà en partie, génération impossible
await fetch('/api/duels/link', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token, gameType: 'ranked' })
});
curl -X POST http://localhost:8080/api/duels/link ^
  -H "Content-Type: application/json" ^
  -d "{\"token\":\"SESSION_TOKEN\",\"gameType\":\"ranked\"}"
GET/api/duels/:id

Retourne l’état public du duel afin d’afficher la page de validation.

POST/api/duels/:id/guest-session

Prépare une session invité uniquement pour les duels friendly. Utilisé automatiquement par duel.html si le visiteur n’est pas connecté.

POST/api/duels/:id/accept

Valide un duel par lien si l’utilisateur est connecté et disponible, ou après passage en session invité pour un duel amical.

Body
token
Effet
fixe le joueur cible, vide les files puis lance la partie
Erreurs
duel expiré, propre duel, joueur occupé, session invalide
Les duels ranked demandent une connexion. Si un visiteur ouvre un lien ranked, il passe par /duel-auth/:id avant de revenir automatiquement sur le lien.
Le cycle complet du duel passe ensuite par Socket.IO : invitation push, acceptation/refus, expiration, puis match_found si accepté.

Clans

Gestion des clans, membres, salon interne et leaderboard de groupe.

GETPOSTPATCHDELETE
GET/api/clans

Liste publique des clans avec membres, ELO moyen et état de recrutement.

GET/api/clans/leaderboard

Classement des clans par activité, victoires et niveau global.

GET/api/players/:id/clan

Retourne le clan actuel d’un joueur, son rôle et les permissions associées.

GET/api/clans/:id

Détail complet d’un clan : profil, membres, stats et paramètres visibles.

POST/api/clans

Crée un clan. Session joueur obligatoire et contrôles anti-spam via route guard.

PATCH/api/clans/:id

Modifie nom, description, visuel, recrutement ou options internes si le joueur possède les droits.

DELETE/api/clans/:id

Supprime un clan par son propriétaire ou un admin autorisé.

GET/api/clans/:id/messages

Historique du chat de clan, paginé et limité aux membres.

POST/api/clans/:id/messages

Envoie un message dans le salon du clan, aussi relayé en Socket.IO.

POST/api/clans/:id/join

Rejoint un clan ouvert ou demande l’accès selon sa configuration.

POST/api/clans/leave

Quitte le clan actuel du joueur.

POST/api/clans/:id/members/:playerId/remove

Expulse un membre si le rôle du demandeur le permet.

POST/api/clans/:id/members/:playerId/role

Modifie le rôle interne d’un membre du clan.

Discord

Liaison, connexion OAuth, refresh des rôles et déliaison sécurisée.

GET/auth/discord/link

Démarre la liaison Discord d’un compte existant.

GET/auth/discord/signin

Connexion ou création de compte directement via Discord.

GET/auth/discord/reset

Démarre le flow de reset mot de passe via Discord.

GET/auth/discord/callback

Callback OAuth. À ne pas appeler manuellement.

GET/api/me/discord-info

Retourne l’état Discord du compte courant.

POST/api/players/:id/refresh-discord

Resynchronise le profil et les rôles Discord du joueur.

POST/api/discord/unlink/request

Demande un code de déliaison Discord.

POST/api/discord/unlink/confirm

Confirme la déliaison avec le code reçu.

Bot API

API HTTP pour comptes robots. Les tokens sont secrets et doivent etre envoyés en Authorization: Bearer p4bot_xxx.

GETPOST
GET/downloads/p4-bot-client.js

Client Node.js officiel d'exemple : ping, file robot, lecture de grille et coup automatique.

curl -O http://localhost:8080/downloads/p4-bot-client.js
P4_BOT_TOKEN=p4bot_xxx node p4-bot-client.js
Télécharger le bot client JS
GET/api/bot/me

Retourne le bot authentifié, son runtime et sa partie active si elle existe.

curl -H "Authorization: Bearer p4bot_xxx" http://localhost:8080/api/bot/me
{ "bot": { "pseudo": "MonBot", "activeGame": null } }
POST/api/bot/ping

Marque le bot comme en ligne. A appeler toutes les 15-30 secondes depuis le programme local. Pour une activation rapide, status peut etre envoye en query string.

curl.exe -X POST -H "Authorization: Bearer p4bot_xxx" "https://puissance4.croustygame.fr/api/bot/ping?status=seeking"
{ "ok": true, "runtime": { "online": true, "status": "seeking" } }
POST/api/bot/queue/join

Entre en file robot. Si un robot est disponible, une partie ranked bot-vs-bot est créée. Peut matcher un bot préconfiguré.

POST/api/bot/queue/leave

Quitte la file robot.

GET/api/bot/game

Retourne la grille, le camp du bot, les colonnes légales, le joueur au trait et les deux joueurs.

POST/api/bot/move

Joue un coup pour le bot authentifié.

curl -X POST -H "Authorization: Bearer p4bot_xxx" -H "Content-Type: application/json" -d "{\"col\":3}" http://localhost:8080/api/bot/move
{ "ok": true, "game": { "isMyTurn": false } }
POST/api/bot/challenge/:id

Un bot API peut défier un autre bot disponible. Si la cible est un robot préconfiguré, il jouera automatiquement ; si c’est un bot externe, il doit etre en ligne via /api/bot/ping.

curl -X POST -H "Authorization: Bearer p4bot_xxx" http://localhost:8080/api/bot/challenge/7
{ "ok": true, "game": { "gameId": 42, "isMyTurn": true } }
POST/api/bot/token/rotate

Endpoint fermé volontairement : les tokens bot ne peuvent pas etre régénérés pour garder une logique stricte de secret affiché une seule fois.

GET/api/bots/preconfigured

Liste les robots préconfigurés du site avec leur force de jeu et leur état. Ces bots participent aussi à une arène automatique en arrière-plan : ils se défient entre eux tant qu’ils sont libres.

POST/api/bots/:id/challenge

Un joueur connecté lance une partie ranked contre le bot ciblé. Utilisé par le bouton Défier ce bot dans /players.

curl -X POST -H "x-session-token: SESSION" -H "Content-Type: application/json" -d "{\"token\":\"SESSION\"}" http://localhost:8080/api/bots/7/challenge
{ "ok": true, "gameUrl": "/game/42" }
POST/api/bots/preconfigured/match

Lance une partie automatique entre deux robots préconfigurés libres.

GET/api/bot-host/me

Retourne les bots associés au joueur connecté, son solde de Cristaux, le prix Host et l’état de chaque host.

POST/api/bot-host/:botId/code

Envoie le code JS du bot dans le panel host. Le host doit être actif. Taille maximale : 256 Ko. Le front peut remplir ce code depuis un fichier .js, .cjs ou .mjs avant transfert.

GET/api/bot-host/:botId/download

Télécharge le code stocké pour ce bot, depuis le profil du propriétaire.

POST/api/bot-host/:botId/action

Actions panel : start, restart, stop. Le serveur lance un process Node host avec P4_BASE_URL, P4_API_URL, P4_BOT_TOKEN, P4_BOT_ID et capture stdout/stderr dans les logs.

GET/api/bot-host/:botId/logs

Retourne les logs du panel host pour le bot appartenant au joueur connecté.

GET/api/bot-host/:botId/metrics

Retourne les métriques host du bot : statut, uptime, redémarrages, activité récente et informations utiles au panel.

Commandes Bot Discord

Commandes slash alignées avec l’API officielle du site. Le bot ne renvoie jamais d’IP ni de données réseau privées.

SlashPublicAdmin
Public/api

Ouvre la documentation API officielle : endpoints HTTP, Socket.IO, erreurs et exemples.

Public/profil pseudo

Miroir Discord de GET /api/players/by-pseudo/:pseudo et GET /api/players/:id. Retourne rang, ELO, coins, badges, stats, follow et dernier match.

Public/ui utilisateur

Carte Discord enrichie et francisée : identité, plateforme, serveur, rôles, permissions, activités, médias et liaison Puissance 4.

La traduction utilise un dictionnaire local dans le bot plutôt qu’une API distante : affichage immédiat, aucune donnée membre envoyée à un tiers et fonctionnement même si un service externe est indisponible. Les infos membre complètes demandent toujours que le bot soit présent sur le serveur concerné.
Public/classement

Top ELO rapide, compatible avec GET /api/leaderboard.

Public/leaderboard type

Classement officiel par elo ou victoires, relié à /api/leaderboard et /api/leaderboard/wins.

Public/stats

Vue Discord des stats globales : présence, parties, comptes, coins et boosts. Relié à /api/stats/overview et /api/site-stats.

Public/systeme

Lit GET /api/system-status et affiche maintenance, message serveur et présence.

Public/boosts

Affiche boost ELO global, boost coins global et nombre de boosts premium individuels actifs.

Public/cosmetiques type

Liste rapide des bibliothèques /api/decorations, /api/profile-banners ou /api/musics.

Public/replay id

Résumé d’une partie officielle avec joueurs, deltas ELO, vainqueur, durée et lien vers /replay/:id.

Public/duel-lien type

Génère un lien de duel ranked ou friendly valable 15 minutes. Cette commande utilise la même logique que POST /api/duels/link et demande un compte Discord lié.

Public/giveaway titre duree recompense

Crée un giveaway avec bouton de participation, tirage au sort et attribution automatique si le gagnant est lié à Puissance 4.

Public/drop titre recompense

Crée un drop instantané : le premier membre qui clique reçoit la récompense si son Discord est lié.

Public/live

Affiche les parties actives, relié à GET /api/live.

Public/boutique

Lien vers la boutique coins / boosters.

Admin/admin-role-generator

Génère les rôles Discord de rang ELO sans les recréer s’ils existent déjà. Retourne un résumé trouvés / manquants / créés.

Admin/admin-crystal

Give, retire ou prolonge le rang Crystal d’un joueur depuis Discord avec durée optionnelle.

Admin/admin action password ...

Commandes staff protégées par mot de passe admin + rôle Discord. Actions disponibles : stats, player, mute, unmute, ban, unban, coins, gems, elo, give-item, crystal, boost-elo, boost-coins, backups, maintenance-on, maintenance-off, reload.

Les actions sensibles demandent le rôle Admin Discord. Les actions de lecture/modération simples acceptent Admin ou Modo selon le cas.

Administration

Panel admin, joueurs, coins, boosters, boosts globaux et games.

POST/api/admin/login

Connexion admin / modération. Erreurs typiques : mot de passe invalide, droits insuffisants.

GET/api/admin/players

Liste enrichie des joueurs pour le panel admin.

GET/api/admin/me

Retourne l’état de la session admin courante.

GET/api/admin/security

Retourne l’état de la protection anti-raid : compteurs actifs, inscriptions récentes et derniers événements anonymisés.

Les IP ne sont jamais exposées : le backend stocke uniquement des empreintes hashées.
GET/api/admin/password

Retourne le mot de passe du panel admin pour les comptes autorisés.

PATCH/api/admin/players/:id/coins

Ajoute des coins à un joueur.

PATCH/api/admin/players/:id/gems

Ajoute ou retire des gemmes au joueur. Les gemmes sont surtout visibles si le compte est lié Discord.

PATCH/api/admin/players/:id/bot-crystals

Ajoute ou retire des Cristaux bot au créateur humain d’un bot. Refuse les comptes robots et les joueurs sans bot associé.

PATCH/api/admin/players/:id/bot-enabled

Active ou coupe la capacité bot API d’un compte robot.

POST/api/admin/coupons

Crée un coupon boutique : code, type de remise, valeur, nombre d’utilisations et expiration optionnelle.

GET/api/admin/coupons

Liste les coupons existants avec leurs usages et leur statut.

DELETE/api/admin/coupons/:code

Supprime ou désactive un coupon boutique ciblé.

PATCH/api/admin/players/:id/shop-item

Ajoute des boosters ELO / coins à l’inventaire d’un joueur.

await fetch('/api/admin/players/2/shop-item', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'x-admin-token': adminToken
  },
  body: JSON.stringify({ itemKey: 'elo_classic', quantity: 3 })
});
curl -X PATCH http://localhost:8080/api/admin/players/2/shop-item ^
  -H "Content-Type: application/json" ^
  -H "x-admin-token: ADMIN_TOKEN" ^
  -d "{\"itemKey\":\"elo_classic\",\"quantity\":3}"
PATCH/api/admin/players/:id/token-collection

Ajoute manuellement un pion secret à la collection d’un joueur depuis le panel admin.

Body
tokenKey, quantity
Source
tokenKey vient de /api/token-collection/catalog
PATCH/api/admin/players/:id/role

Modifie rôle, VIP, VIP+, Perso et durée VIP.

PATCH/api/admin/players/:id/crystal

Attribue, prolonge ou retire le rang Crystal avec durée optionnelle. Synchronise les avantages Crystal côté profil et boutique.

PATCH/api/admin/players/:id/custom-role

Définit le badge custom d’un profil Perso.

PATCH/api/admin/players/:id/pseudo

Force un changement de pseudo côté admin.

PATCH/api/admin/players/:id/elo

Force / reset l’ELO d’un joueur.

PATCH/api/admin/players/:id/mute

Mute standard ou custom en minutes.

PATCH/api/admin/players/:id/ban

Ban / unban un joueur.

PATCH/api/admin/players/:id/suspicious

Marque ou retire le flag suspicious d’un joueur.

GET/api/admin/games

Liste des parties pour le panel admin.

POST/api/admin/games/:id/revert

Revert d’une partie. Restaure les ELO d’avant match.

GET/api/admin/boost

Lit le boost ELO global actif.

POST/api/admin/boost

Active ou retire le boost ELO global.

GET/api/admin/coin-boost

Lit le boost coins global actif.

POST/api/admin/coin-boost

Active le boost coins global entre x1 et x10 avec durée custom.

POST/api/admin/limited-pack

Crée ou met à jour une offre limitée boutique avec coupon automatique, timer et nombre d’utilisations maximum.

Body
code, value, maxUses, durationHours, label
Effet
stocke un coupon discount + expose limitedOffer dans /api/shop/me
Erreurs
admin requis, code invalide, durée invalide, valeur hors limites
await fetch('/api/admin/limited-pack', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-admin-token': adminToken
  },
  body: JSON.stringify({
    code: 'FLASH20',
    value: 20,
    maxUses: 25,
    durationHours: 12,
    label: 'Pack week-end'
  })
});
curl -X POST http://localhost:8080/api/admin/limited-pack ^
  -H "Content-Type: application/json" ^
  -H "x-admin-token: ADMIN_TOKEN" ^
  -d "{\"code\":\"FLASH20\",\"value\":20,\"maxUses\":25,\"durationHours\":12,\"label\":\"Pack week-end\"}"
GET/api/admin/vip-boosts

Liste les boosts premium individuels actifs (VIP / VIP+ / Perso).

GET/api/admin/backups

Liste les bases / sauvegardes exportables depuis le panel admin.

GET/api/admin/backups/:key

Télécharge un backup ciblé (ex. base principale, WAL, SHM).

Langues et i18n

Bundle de textes, traduction automatique de page et sauvegarde de la langue choisie dans le menu global.

GETPOSTPATCH
GET/api/i18n?lang=fr|en|de...

Retourne le bundle i18n utilisé par /i18n.js : langue active, fallback français, textes source, traductions manuelles et liste des langues disponibles.

Provider
libretranslate si LIBRETRANSLATE_URL est configuré, sinon disabled.
Langues
La liste est filtrée depuis GET /languages de LibreTranslate. Sans provider joignable, seul fr est proposé.
const bundle = await fetch('/api/i18n?lang=de')
  .then(r => r.json());

console.log(bundle.languages.map(l => l.code));
{
  "language": "de",
  "fallbackLanguage": "fr",
  "provider": "libretranslate",
  "translationConfigured": true,
  "languages": [{ "code": "fr" }, { "code": "de" }],
  "source": { "common.save": "Enregistrer" },
  "translations": {}
}
POST/api/i18n/translate

Traduit les textes visibles d’une page en une seule requête navigateur. Le backend utilise LibreTranslate en batch, protège la marque Puissance 4, puis cache les résultats dans data/i18n-machine-cache.json.

Body
language ou lang, puis texts tableau de textes. Maximum serveur : 400 textes.
Erreurs
502 provider absent/down, langue non supportée, timeout LibreTranslate.
const res = await fetch('/api/i18n/translate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    language: 'de',
    texts: ['Connexion', 'Mot de passe', 'Se connecter']
  })
});
const data = await res.json();
{
  "language": "de",
  "provider": "libretranslate",
  "translations": {
    "Connexion": "Anmeldung",
    "Mot de passe": "Passwort"
  },
  "stats": { "total": 3, "translated": 3, "failed": 0 },
  "errors": []
}
Le front affiche un overlay plein écran pendant la traduction. Le français ne passe jamais par l’API externe.
PATCH/api/players/:id/language

Sauvegarde la langue préférée du joueur connecté. Le menu global l’utilise après validation de l’autocomplete.

Session
x-session-token ou token dans le body.
Body
language parmi les codes exposés par /api/i18n.
await fetch('/api/players/2/language', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'x-session-token': token
  },
  body: JSON.stringify({ language: 'de' })
});
{
  "ok": true,
  "language": "de",
  "player": { "id": 2, "language": "de" }
}
ConfigLibreTranslate serveur

Variables à renseigner sur le serveur Puissance 4 pour activer la traduction automatique.

TRANSLATION_PROVIDER=libretranslate
LIBRETRANSLATE_URL=http://IP_OU_HOST_LIBRETRANSLATE:5000
LIBRETRANSLATE_KEY=
libretranslate --host 0.0.0.0 --port 5000 \
  --load-only fr,en,es,de,it,pt,nl,pl,ro,sv,tr,ru,uk,ar,zh,ja,ko,el,cs,hu,id,hi \
  --disable-web-ui
Dans deux containers Pterodactyl différents, 127.0.0.1 pointe souvent vers le mauvais container. Utiliser l’IP ou le hostname joignable du serveur LibreTranslate.

Système

Endpoints transverses utilisés par l’UI, le live et les alertes.

GET/api/system-status

État manuel du serveur : maintenance / redémarrage / message flottant.

POST/api/admin/system-status

Met à jour l’alerte serveur affichée en front.

GET/api/site-stats

Retourne les stats globales rapides : joueurs en ligne, visiteurs, total de présence, parties live, boost global.

GET/api/stats/overview

Vue agrégée complète utilisée par stats.html : joueurs, visiteurs, parties, coins, boosters, Elo moyen, précision moyenne, suspicions, bot games, etc.

GET/api/stats/weekly

Rythme hebdomadaire sur 2 semaines : inscriptions, parties, parties terminées, joueurs actifs et moyenne quotidienne.

GET/api/leaderboard

Classement ELO principal.

GET/api/leaderboard/wins

Classement alternatif par victoires.

GET/api/leaderboard/bots

Classement spécifique des bots API et bots préconfigurés.

GET/api/bot-id

Retourne l’ID du bot joueur utilisé côté site.

Socket.IO

Événements utilisés par la file d’attente, les parties live et les alertes système.

SOCKET
Client → Serveuridentify

Identifie la socket avec playerId + token.

socket.emit('identify', {
  playerId: myPlayer.id,
  token: localStorage.getItem('token')
});
Serveur → Clientidentified

Réponse après identification réussie. Contient le joueur sanitizé.

Client → Serveurvisitor_presence

Annonce une présence anonyme sur le site pour distinguer les visiteurs des comptes connectés.

Client → Serveurpresence_ping

Heartbeat de présence utilisé hors partie pour maintenir le statut online / live.

Serveur → Clientcrystal_login

Alerte compacte en bas à gauche quand un membre Crystal vient de se connecter, avec message, emoji, couleur et animation.

Serveur → Clientprofile_changed

Notifie les pages ouvertes qu’un profil ou un rôle a changé : ELO, rang, badges, Crystal, Discord ou cosmétique.

Serveur → Clientpresence_counts

Push live des compteurs de présence : joueurs identifiés, visiteurs et total présent sur le site.

Client → Serveurjoin_clan_chat / clan_message_send

Rejoint le salon temps réel d’un clan puis envoie un message interne.

Serveur → Clientclan_message / clan_error

Push de message clan ou erreur ciblée : permissions, clan introuvable ou message invalide.

Client → Serveurqueue_join

Rejoint la file ranked classique.

Serveur → Clientqueue_joined

Confirmation d’entrée en file avec position.

Serveur → Clientqueue_left

Confirmation de sortie de file.

Client → Serveurqueue_leave

Quitte la file ranked.

Serveur → Clientmatch_found

Match trouvé, payload de partie à charger sur /game.

Serveur → Clientduel_invite / duel_invite_sent

Invitation de duel reçue côté cible et accusé d’envoi côté expéditeur.

Client → Serveurduel_accept / duel_decline

Accepte ou refuse un duel en attente.

Serveur → Clientduel_invite_accepted / duel_invite_declined / duel_invite_expired

Cycle complet de vie du duel avant le lancement d’une partie.

Serveur → Clientduel_invite_error

Erreur ciblée sur un duel: joueur hors ligne, duel expiré, joueur déjà occupé, etc.

Client → Serveurplay_move

Joue un coup en envoyant une colonne.

Client → Serveurgame_chat_send

Envoie un message de tchat à l’adversaire pendant la partie.

Serveur → Clientgame_chat_message

Message de tchat diffusé aux deux joueurs de la partie.

Client → Serveurgame_draw_offer / game_draw_response

Propose une nulle puis accepte ou refuse. Si accepté, la partie finit avec agreement_draw.

Client → Serveurgame_resign

Abandon volontaire. La partie se termine avec ELO appliqué et result_reason = resignation.

Client → Serveurgame_rematch_request / game_rematch_response

Demande de revanche après la partie, acceptée ou refusée en temps réel.

Serveur → Clientgame_action_offer / game_action_notice / game_action_error

Notifications communes pour nulle, revanche, refus, abandon et erreurs d’action.

Serveur → Clientmove_played

Un coup a été joué. Sert à mettre à jour la grille.

Serveur → Clientgame_over

Partie terminée. Résultat final, deltas ELO, coins, boosts, etc.

Client → Serveurrejoin_game

Rejoint une partie active après refresh ou reconnexion.

Serveur → Clientgame_rejoined

Réponse complète contenant l’état de la partie après rejoin.

Serveur → Clientopponent_disconnected / opponent_reconnected

Signaux de présence de l’adversaire pendant une partie.

Serveur → Clientcolor_updated

Mise à jour live d’une couleur de pion.

Client → Serveurjoin_live

Inscrit la socket au salon live pour recevoir les refreshs de parties.

Client → Serveurjoin_live_game / leave_live_game

Inscrit ou retire un spectateur d’une partie précise. Les connectés affichent leur pseudo, les autres apparaissent en Anonyme.

Serveur → Clientlive_update

Demande au client de relire /api/live.

Serveur → Clientsystem_status_update

Mise à jour push de l’alerte système / redémarrage.

Serveur → Clienterror

Erreur générique temps réel.

{ "message": "Session invalide. Reconnecte-toi." }
Cas fréquents : session invalide, compte banni, déjà en file, coup invalide, game not found.
Cette doc colle au backend actuel du projet. Elle couvre les routes utiles, les erreurs probables, les événements Socket.IO et des exemples d’intégration.
  • Headers privés : x-session-token pour le joueur, x-admin-token pour l’admin.
  • Beaucoup de routes front acceptent aussi token dans le body JSON.
  • Les pages HTML publiques restent accessibles via /, /profil, /game, /live, /boutique, etc.