Appearance
kapp.poll & kapp.prediction
Sondages et prédictions natifs Kappapps : indépendants de la plateforme, votes par chat (parsés côté serveur, indépendamment de l'exécution et de l'overlay) et/ou par API, mises en monnaie interne du channel, display natif à l'écran (désactivable).
Service partagé appli + widget : API identique.
Quand l'utiliser (vs alternative)
- Sondage/prédiction multi-canal (chat + UI custom) avec décompte live :
kapp.poll/kapp.prediction. - Sondage/prédiction natif Twitch (channel points, encart Twitch) :
kapp.twitch.poll()/kapp.twitch.prediction(). - Un seul poll actif et une seule prediction en cours à la fois par channel.
Cycle de vie (fire-and-forget)
- Un poll/une prédiction survit à la fin de l'exécution émettrice : les votes chat continuent d'être comptés côté serveur, la clôture/le lock auto s'exécutent, le display natif et le dashboard streamer restent à jour. On peut donc lancer un sondage puis terminer immédiatement.
- Les events (
begin/progress/lock/end) ne sont reçus que par l'exécution qui a lancé le poll/la prédiction. Les autres apps/widgets (et une instance relancée = nouvelle exécution) ne reçoivent rien — lecture seule viagetActive()/getRunning(). - Le contrôle (
terminate/cancel/lock/resolve) est réservé à l'exécution émettrice :403sinon. Pas de reprise après relance : une prédiction orpheline se résout depuis le dashboard streamer (ou est auto-annulée + remboursée après ~24 h verrouillée).
kapp.poll
start(data): Promise<Poll>— crée et démarre un sondage. async.data:{ title, choices: string[], duration, chat_voting_enabled?, chat_command?, allow_vote_change?, show_display? }chat_commanddéfaut"!vote"(→!vote 2dans le chat) ;null= un numéro seul vote.show_display: false= pas d'encart natif, tu dessines ta propre UI.
getActive(): Promise<PollData|null>— le sondage actif du channel. async.
Modèle Poll
data—PollDataà jour (tallies= votes live par choix,resultsà la clôture).vote(user, choice_id, method = 'id'): Promise<void>— vote au nom d'un viewer (canal « in-app »). async.terminate()/cancel()— clôture avec résultats / annulation. async.getData(): Promise<PollData>— refresh tallies. async.events:poll.EVENTS.PROGRESS(votes live),poll.EVENTS.END.
kapp.prediction
start(data): Promise<Prediction>— crée et ouvre une prédiction. async.data:{ title, outcomes: string[], prediction_window?, betting_enabled?, min_bet?, max_bet?, fixed_reward?, chat_betting_enabled?, chat_command?, show_display? }- Mises en monnaie du channel (
betting_enableddéfauttrue) : chat!predict <choix> <montant>, débit immédiat, pot partagé au prorata entre gagnants auresolve(), remboursement intégral aucancel(). - Sans mise (
betting_enabled: false) : participation libre,fixed_rewardéventuel aux gagnants.
getRunning(): Promise<PredictionData|null>— la prédiction en cours (ACTIVE ou LOCKED). async.
Modèle Prediction
bet(user, outcome_id, amount = 0, method = 'id'): Promise<void>— participation au nom d'un viewer. async.lock()— verrouille les participations (auto à la fin deprediction_windowsi fourni). async.resolve(outcome_id)— désigne l'issue gagnante et paie les gagnants. async.cancel()— annule et rembourse toutes les mises. async.events:EVENTS.PROGRESS,EVENTS.LOCK,EVENTS.END.
Exemple (V2, exécutable)
js
let poll;
try {
poll = await kapp.poll.start({ title: 'On joue à quoi ?', choices: ['Minecraft', 'Valorant'], duration: 60 });
} catch (err) {
console.error('Sondage impossible : ' + (err?.message || err));
return;
}
await new Promise(resolve => poll.events.on(poll.EVENTS.END, resolve));
const winner = (poll.data.results || []).reduce((a, b) => (b.votes > (a?.votes ?? -1) ? b : a), null);
if (winner) await kapp.chat.say(`Résultat : « ${winner.title} » avec ${winner.votes} votes !`);Pièges
start()échoue (throw côté API) si un poll/une prediction est déjà en cours sur le channel →try/catch.- Les ids de choix/issues sont attribués à la création (1..N, ordre du tableau) — utilise
poll.data.choicespour les retrouver. betting_enabled: trueexige la monnaie activée sur le channel, sinonstart()échoue.- Un viewer ne mise qu'une fois par prediction (pas de changement) ; pour les polls,
allow_vote_changecontrôle le re-vote. - Si tu attends le résultat (
await ... EVENTS.END) et que l'exécution se termine avant la fin, ton code ne reprendra pas : le sondage continue sans toi (résultats au dashboard). Choisis : attendre le END (exécution vivante jusqu'au bout) OU fire-and-forget (terminer après lestart()). start()est rejeté si le channel tourne sur un core legacy (legacy_core_unsupported).