Skip to content

Exemple — compteur persistant par viewer ​

Intention : chaque !points incrémente le compteur personnel du viewer, persistant entre les streams. Pas d'UI : l'appli tourne en fond.

Pars du bootstrap courant, conserve index.html, style.css et les configurations, fusionne le manifeste ci-dessous et remplace script.js. Le champ points est initialisé même si le stockage renvoie un objet vide. Cette version minimale suppose des commandes espacées ; des commandes simultanées demandent de sérialiser les écritures par viewer pour éviter une mise à jour perdue.

infos.json (extrait) ​

jsonc
{
  "app-index": "index.html",
  "scopes": ["chat:read", "chat:write"]
}

config/default_triggers.config.json ​

Cet exemple propose un processus à l'installation pour écouter les commandes. Le streamer pourra ensuite le modifier ou le retirer ; voir les déclencheurs d'installation.

json
[{"type":"PROCESSUS"}]

script.js ​

js
(async function () {
    kapp.chat.onCommand('points', async (user, ev) => {
        const data = await kapp.userDataStorageV2.get(user.id);   // état PAR viewer
        data.points = Number(data.points ?? 0) + 1;
        await kapp.userDataStorageV2.set(user.id, data);
        await ev.respond(`${user.display_name}, tu as ${data.points} points.`);
    });

    // Sans display() ni finish() ici : l’appli écoute tant que le streamer la garde ouverte.
})();

Pourquoi ​

  • Aucun visuel dans cet exemple : display() est inutile. L’appli reste ouverte pour écouter ; elle pourrait appeler finish() pour se terminer.
  • kapp.userDataStorageV2.get/set = persistance par viewer (appli-only). Les anciens User.getAppData/setAppData restent sur V1 et sont dépréciés.
  • Lis l'état, mute, réécris : pas de merge automatique côté serveur.