Appearance
kapp.users
Récupérer et manipuler les viewers (User) du channel : pseudo, avatar, monnaie interne, modération.
Service partagé appli + widget. La persistance par viewer et les scopes applicatifs dépendent du contexte. En appli, utiliser
kapp.userDataStorageV2.get(user.id)/set(user.id, data).user.getAppData()/user.setAppData()sont dépréciés et restent sur V1. En widget, persiste viakapp.variables. Pour une appli avec plugins, migrer ensemble ces getters, les écrituresuserDataStorageV2et le helper V3 : sonKappappsHost.data()retourne les données viewers V2 dansappli_data. Les helpers V1/V2 et les objetsUserhistoriques ne basculent pas automatiquement. V1 et V2 ne sont plus synchronisés après la copie initiale.
Quand l'utiliser (vs alternative)
- Côté widget,
kapp.triggerRequest.setterte donne déjà leUserqui a déclenché — pas besoin deget()pour lui. kapp.users.get(login): récupérer un viewer par son login (ex. argument d'une commande).
Méthodes
get(login: string, method = 'login'): Promise<User | null>— un viewer par login. async.get(logins: string[]): Promise<User[]>— plusieurs viewers. async.get(id: number, 'id'): Promise<User | null>— par id Twitch. async.getActiveUsers(options): User[]— viewers actifs récemment. sync.getViewersDashboardUrl(): string: URL publique de la page viewers du channel, à citer dans le chat. sync.moderation: versions par login des actions de l'objetUser, par exempleawait kapp.users.moderation.timeout(login, durée, raison). Méthodes :timeout/untimeout,warn,vip(login, durée?)/unvip,mod(login, durée?)/unmod,blacklist/unblacklist,ban/unban. Mêmes scopes que les méthodesUserci-dessous.items.use(login, user_item_id, args = ''): utilise un item possédé par le viewer (identifiant de l'instance possédée, pas de l'item du catalogue). Scope d'appliitems:manage. async.
Objet User
Synchrones (propriétés / getters, pas d'await) :
.id,.login,.display_name;getId(),getLogin(),getDisplayName(),isModerator(),getRole(),isGranted(role),isActive().onUpdate(callback):callback(user)à chaque mise à jour de ce viewer par le serveur (monnaie, rôle, items…).
Async (touchent le réseau → await) :
getProfileImageUrl(): Promise<string>,getCurrency(): Promise<number>,getRankingPoints(): Promise<number>,getBroadcasterType(): Promise<string>,getItems(),getAvatarData().- Chargés depuis le serveur au premier appel :
getGamesPlayed(),getGamesWon()(parties Kappapps),getBanTime()(durée restante de timeout),isBlacklist(),getFollowAnnounce()(annonce de follow activée),getAiBotContext()(contexte personnalisé du bot IA),isDeveloper(),isOfficialDeveloper(). getSubscriptionStatus(): Promise<{ subscribed, tier, is_gift }>— statut d'abonnement Twitch live (tier: 1|2|3|null).getFollowStatus(): Promise<{ following, followed_at }>— statut de follow Twitch live (followed_atISO-8601 ounull).getAvatarPng(options?): Promise<string>— avatar Kappapps (le perso customisé, pas la pdp Twitch) rendu en PNG, renvoyé en data URL utilisable en<img src>dans l'appli (ou convertie enBlobviakapp.Utils.Media.base64ToBlob). Options :width/height(512),animation('Idle'),equip: ['weapon'|'bow'|'shield'],flipX,trim(true),padding,settleDelay(300 ms),timeout.- Actions monnaie :
addCurrency(n),removeCurrency(n),setCurrency(n)(renvoientthis). Scope d'applicurrency:manage. - Items :
addItem(item, quantité?),removeItem(item). Scope d'appliitems:manage. - Avertissement :
setWarning(raison)avecmoderation:manage. VIP/modérateur :setVip()/setModerator()et leurs retraits avecchat-roles:manage. - Blacklist Kappapps du channel :
await user.setBlacklist(true)ajoute le viewer ;await user.setBlacklist(false)le retire. Sans argument (ou avecundefined),setBlacklist()ajoute le viewer.user.removeBlacklist()etkapp.users.moderation.unblacklist(login)permettent aussi le retrait ;kapp.users.moderation.blacklist(login)permet l'ajout. Les méthodesUserrenvoient leUseret les refus du backend rejettent la Promise. Scope d'appli :blacklist:manage; les widgets ne déclarent pas de scopes applicatifs. - Ban définitif du chat Twitch :
setBan(raison?)oukapp.users.moderation.ban(login, raison), accessibles aux widgets et à toutes les applis. Les applis déclarentmoderation:bandès le contrat de manifeste 4 ; les versions antérieures restent exemptées jusqu'à leur prochaine nouvelle version. Ce scope est distinct demoderation:manageethard-moderation:manage. Les autorisations Twitch et les protections du viewer restent applicables. - Débannissement Twitch :
await user.removeBan()ouawait kapp.users.moderation.unban(login), avec le même scopemoderation:banet les mêmes exemptions que le ban. Ces méthodes utilisentDELETE /ban/v1et retirent la sanction Twitch active, même sans timeout enregistré dans Kappapps. Twitch retire aussi un timeout par cette opération.removeBan()renvoie leUser;unban()ne renvoie pas de valeur. Un refus du backend ou de Twitch rejette la Promise. - Timeouts :
setTimeout(durée, raison?)/removeTimeout()etkapp.users.moderation.timeout()/untimeout()utilisentmoderation:managepour les applis (exemption des contrats antérieurs à 2). Les widgets ne déclarent pas de scopes. La route historiqueDELETE /timeout/v1reste compatible : elle peut aussi lever un ban permanent, avec cette permission historique. - Rôle Kappapps du channel :
setRole(role)oukapp.users.role.set(login, role), accessibles aux widgets et aux applis officielles uniquement. Une appli tierce reçoit 403 quels que soient ses scopes et son ancienneté. Valeurs attribuables :admin,animator, ounullpour retirer le rôle ; le rôlesuperadmindu streamer ne s'attribue pas par cet appel. - Les widgets sont configurés par le streamer ou ses administrateurs et ne déclarent pas de scopes applicatifs : leurs droits de bannissement et de gestion des rôles sont conservés.
- Appli uniquement, déprécié :
getAppData()/setAppData()(V1). Pour V2, lire/écrire explicitementkapp.userDataStorageV2.
Exemple (V2, exécutable)
js
const user = await kapp.users.get('toto');
if (user) {
const [avatar, coins, sub, follow] = await Promise.all([ // getters réseau en parallèle
user.getProfileImageUrl(),
user.getCurrency(),
user.getSubscriptionStatus(),
user.getFollowStatus(),
]);
console.log(user.display_name, avatar, coins, sub, follow);
}Pièges
getProfileImageUrl()= photo de profil Twitch ;getAvatarPng()= avatar Kappapps (perso Spine). Ne pas confondre les deux.- Le PNG de
getAvatarPng()reste dans l'appli : levisualdes annonces/notifications n'accepte ni data URL ni URL externe (seulement médiathèque, asset d'appli, CDN Twitch) — il sera retiré silencieusement. getAvatarPng()charge Phaser + le module avatar au premier appel (quelques centaines de Ko) et rend une frame hors écran : garde le résultat en variable plutôt que de rappeler la méthode, et ne l'appelle pas dans une boucle sur tous les viewers.get(x, 'id')avec un id non numérique (NaN,undefined, string non chiffrée) ne part pas en réseau : unitaire → résoutnull, batch → entrées invalides ignorées (warn console). Assainis quand même tes ids (Number.isFinite) avant l'appel.- Ne fais pas
await user.getDisplayName(): c'est synchrone. À l'inverse,getProfileImageUrl/getCurrencySONT async. - Parallélise les getters réseau avec
Promise.allplutôt que desawaiten série. getSubscriptionStatus()/getFollowStatus()ne sont jamais cachés : chaque appel interroge Twitch. Ne les appelle pas en boucle sur tous les viewers. En appli, ils exigentchannel-stats:readdans le manifeste ; en widget, il n'y a pas de scope applicatif. Dans les deux cas, la Promise est rejetée si le streamer doit reconnecter sa chaîne pour accorder le scope Twitch correspondant.getAppData/setAppData= anciennes données V1, même si l'appli utilise la V2 ailleurs.Userne bascule pas automatiquement.- Anciennes API :
kapp.getUsers(login)→await kapp.users.get(login);kapp.updateUsersData(...)→ actionsUser/kapp.userDataStorageV2(appli) /kapp.variables(widget).