Démarrage rapide en Node.js
Un programme Node.js qui rafraîchit un token, liste vos écrans et place une playlist sur un écran. Les blocs de cette page forment un seul fichier.
1 Obtenez un token
Ouvrez le CMS dans Paramètres, Applications connectées et cliquez sur Générer un token. Un membre sans droits d’administrateur ne voit pas cet onglet.
Choisissez ensuite l’organisation, qui détermine les écrans que le programme voit, et cliquez sur Autoriser. La page suivante affiche l’identifiant client et le token de rafraîchissement, une seule fois. Copiez les deux.
Dans votre terminal, définissez l’identifiant client et le chemin du fichier de token, puis écrivez le token de rafraîchissement dans ce fichier. read -rs attend sans rien afficher : collez le token de rafraîchissement et appuyez sur Entrée, il reste ainsi hors de l’historique du shell :
export GIBEON_CLIENT_ID=CLIENT_ID export GIBEON_REFRESH_TOKEN_FILE=./gibeon-refresh-token touch "$GIBEON_REFRESH_TOKEN_FILE" chmod 600 "$GIBEON_REFRESH_TOKEN_FILE" read -rs GIBEON_REFRESH_TOKEN && printf '%s' "$GIBEON_REFRESH_TOKEN" > "$GIBEON_REFRESH_TOKEN_FILE"
Le programme nécessite Node.js 18 ou plus récent, pour le fetch intégré. Il n’y a rien à installer. Placez les blocs ci-dessous dans l’ordre dans gibeon.mjs et lancez node gibeon.mjs.
2 Rafraîchissez le token
Un token d’accès est valable 60 minutes. Chaque rafraîchissement renvoie aussi un nouveau token de rafraîchissement : une valeur dans l’environnement est donc périmée après une exécution.
Le programme écrit le nouveau token dans un fichier temporaire du même répertoire, applique chmod 600 et le renomme par-dessus le fichier de GIBEON_REFRESH_TOKEN_FILE. Il n’utilise le token d’accès qu’ensuite. Un processus qui s’arrête pendant cette utilisation conserve ainsi un token de rafraîchissement valide.
Chaque requête vérifie le statut : en cas d’erreur, check lève une exception qui arrête le programme avec un code de sortie non nul.
import { randomUUID } from 'node:crypto';
import { chmod, readFile, rename, writeFile } from 'node:fs/promises';
// An uncaught error stops the program with a non-zero exit code.
function check(response) {
if (!response.ok) {
throw new Error(`${response.status} from ${response.url}`);
}
}
const tokenFile = process.env.GIBEON_REFRESH_TOKEN_FILE;
const refreshToken = (await readFile(tokenFile, 'utf8')).trim();
let response = await fetch('https://id.gibeon.io/auth/v1/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: process.env.GIBEON_CLIENT_ID,
refresh_token: refreshToken,
}),
signal: AbortSignal.timeout(30_000),
});
check(response);
const tokens = await response.json();
// Store the new refresh token before anything uses the access token.
const tmpPath = `${tokenFile}.${randomUUID()}.tmp`;
await writeFile(tmpPath, tokens.refresh_token, { mode: 0o600 });
await chmod(tmpPath, 0o600);
await rename(tmpPath, tokenFile);
const headers = { Authorization: `Bearer ${tokens.access_token}` }; 3 Listez vos écrans
Cet appel renvoie tous les écrans de votre tenant. Le programme affiche l’id, le name et le status de chaque écran, et jamais un token.
response = await fetch('https://www.gibeon.io/v1/players', {
headers,
signal: AbortSignal.timeout(30_000),
});
check(response);
for (const player of (await response.json()).data) {
console.log(player.id, player.name, player.status);
} 4 Assignez une playlist et publiez
Cette étape ne s’exécute que si GIBEON_PLAYER_ID et GIBEON_PLAYLIST_ID sont définis. L’id de l’écran figure dans la liste de l’étape précédente. L’id de la playlist figure dans la barre d’adresse du CMS quand vous ouvrez une playlist : /playlists/PLAYLIST_ID/content. Exportez les deux et relancez le programme.
Un écran avec des zones joue celles-ci ; sinon sa séquence ; sinon son planning ; sinon sa propre playlist. Le corps de la requête vide la séquence et le planning : la playlist joue donc, sauf si l’écran a des zones.
Le PATCH seul ne change rien à l’écran : tant que vous ne publiez pas, il continue d’afficher l’ancienne affectation. La publication construit un nouveau snapshot et prévient l’écran immédiatement.
const playerId = process.env.GIBEON_PLAYER_ID;
const playlistId = process.env.GIBEON_PLAYLIST_ID;
if (playerId && playlistId) {
response = await fetch(`https://www.gibeon.io/v1/players/${playerId}`, {
method: 'PATCH',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify({ playlist_id: playlistId, sequence_id: null, planning_id: null }),
signal: AbortSignal.timeout(30_000),
});
check(response);
const player = (await response.json()).data;
response = await fetch(`https://www.gibeon.io/v1/players/${playerId}/publish`, {
method: 'POST',
headers,
signal: AbortSignal.timeout(30_000),
});
check(response);
console.log(player.id, player.name, player.status);
}