Skip to content

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 via getActive()/getRunning().
  • Le contrôle (terminate/cancel/lock/resolve) est réservé à l'exécution émettrice : 403 sinon. 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_command défaut "!vote" (→ !vote 2 dans 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

  • dataPollData à 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_enabled défaut true) : chat !predict <choix> <montant>, débit immédiat, pot partagé au prorata entre gagnants au resolve(), remboursement intégral au cancel().
    • 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 de prediction_window si 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.choices pour les retrouver.
  • betting_enabled: true exige la monnaie activée sur le channel, sinon start() échoue.
  • Un viewer ne mise qu'une fois par prediction (pas de changement) ; pour les polls, allow_vote_change contrô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 le start()).
  • start() est rejeté si le channel tourne sur un core legacy (legacy_core_unsupported).