Appearance
Exemple — mini-jeu avec résultat et rewards
Intention : un tirage au sort express. Le streamer lance l'appli, les viewers tapent !join pendant 20 s, un gagnant est tiré, récompensé, l'appli se termine.
Pars du bootstrap courant. Conserve son index.html (SDK V2 puis script.js après AppliLoaded), style.css et les fichiers de configuration. Fusionne l'extrait de manifeste ci-dessous et remplace script.js. Cet exemple accepte 100 participants distincts au maximum, gagnant et perdants compris, pour respecter la limite de distribution des récompenses.
infos.json (extrait)
jsonc
{
"app-index": "index.html",
"scopes": ["chat:read", "chat:write", "rewards:distrib"],
"overlay-formats": ["16:9"]
}script.js
js
(async function () {
const participants = new Map(); // id Twitch -> User
let registrationsOpen = true;
kapp.chat.onCommand('join', (user) => {
if (!registrationsOpen || participants.has(user.id) || participants.size >= 100) return;
participants.set(user.id, user);
});
kapp.display();
document.body.innerHTML = '<h1 id="t">Tapez !join — 20s</h1>';
for (let s = 20; s > 0; s--) {
document.getElementById('t').textContent = `Tapez !join — ${s}s`;
await wait(1000);
}
registrationsOpen = false;
const list = [...participants.values()];
if (list.length === 0) {
await kapp.chat.say('Personne n\'a joué 😢');
return kapp.abort('aucun participant');
}
const winner = list[Math.floor(Math.random() * list.length)];
document.getElementById('t').textContent = `🎉 ${winner.display_name} gagne !`;
await kapp.chat.say(`🎉 Bravo ${winner.display_name} !`);
kapp.rewards.winner(winner); // accumulé...
list.filter(u => u !== winner).forEach(u => kapp.rewards.loser(u));
await wait(4000);
await kapp.finish(); // ...envoyé ici
})().catch(async error => {
console.error('Tirage interrompu', error);
await kapp.abort('Échec du tirage ou de la distribution');
});Pourquoi
kapp.finish()explicite : l'appli se ferme d'elle-même à la fin.kapp.rewards.winner/loseraccumulent ;finish()déclenche l'envoi (sendRewards()).kapp.display()une fois, puis on met à jour le DOM ; décompte viaawait wait(1000).scopescontient les permissions de l'appli ; le scope de récompenses n'est pas une autorisation OAuth Twitch.- Les inscriptions tardives et au-delà de 100 sont ignorées. En cas d'erreur de distribution, le code abandonne sans renvoyer les récompenses automatiquement.
Vérifier
Lance l'appli depuis le DEV HUB, envoie !join avant la fermeture des inscriptions, puis vérifie le gagnant et la fin de l'appli. Ce scénario envoie de vrais messages Twitch et peut attribuer les récompenses configurées sur le channel ; pour vérifier les doublons et la limite de 100 sans ces effets, utilise des doublures du chat et du service de récompenses.