@ix-xs/twitch.api 1.0.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -0
- package/LICENSE +21 -0
- package/README.md +504 -99
- package/dist/index.cjs +3792 -0
- package/dist/index.d.cts +11315 -0
- package/dist/index.d.ts +11315 -0
- package/dist/index.js +3738 -0
- package/dist/node.cjs +57 -0
- package/dist/node.d.cts +36 -0
- package/dist/node.d.ts +36 -0
- package/dist/node.js +55 -0
- package/dist/tokens-DlOL0kjk.d.cts +97 -0
- package/dist/tokens-DlOL0kjk.d.ts +97 -0
- package/package.json +101 -20
- package/Token.json +0 -6
- package/twitchapi.js +0 -1381
package/twitchapi.js
DELETED
|
@@ -1,1381 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-trailing-spaces */
|
|
2
|
-
|
|
3
|
-
const { writeFileSync } = require("node:fs");
|
|
4
|
-
const TwitchTokenPath = process.cwd() + "/node_modules/@ix-xs/twitch.api/Token.json";
|
|
5
|
-
let TwitchToken = require(TwitchTokenPath);
|
|
6
|
-
|
|
7
|
-
module.exports = class {
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* **Instance client**
|
|
11
|
-
*
|
|
12
|
-
* ---
|
|
13
|
-
* @param {{
|
|
14
|
-
* client_id:string,
|
|
15
|
-
* client_secret:string,
|
|
16
|
-
* }} config - Vos identifiants client Twitch
|
|
17
|
-
*
|
|
18
|
-
* ---
|
|
19
|
-
* @example
|
|
20
|
-
* const client = new twitchAPI({ client_id:"votre_client_id", client_secret:"votre_client_secret" });
|
|
21
|
-
*/
|
|
22
|
-
constructor(config) {
|
|
23
|
-
|
|
24
|
-
this.clientId = config.client_id;
|
|
25
|
-
this.clientSecret = config.client_secret;
|
|
26
|
-
this.token = TwitchToken;
|
|
27
|
-
this.validateInterval = null;
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* 👀 **Démarre le client**
|
|
33
|
-
* 💡 **Note** : Cette fonction est requise afin de démarrer la surveillance du token qui doit maintenant être valider toutes les heures
|
|
34
|
-
*
|
|
35
|
-
* ---
|
|
36
|
-
* @example
|
|
37
|
-
* await client.initialize();
|
|
38
|
-
*/
|
|
39
|
-
async initialize() {
|
|
40
|
-
if (this.isExpiredToken()) {
|
|
41
|
-
await this.refreshToken();
|
|
42
|
-
}
|
|
43
|
-
await this.validateToken();
|
|
44
|
-
this.startPeriodicValidation();
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* 👀 **Génère un nouveau token**
|
|
48
|
-
* 💡 **Note** : Le token se gère de façon automatique, cette fonction sert uniquement a son auto-gestion
|
|
49
|
-
*
|
|
50
|
-
* ---
|
|
51
|
-
* @returns {Promise<{
|
|
52
|
-
* ok:boolean,
|
|
53
|
-
* statusText?:string,
|
|
54
|
-
* error?:string,
|
|
55
|
-
* result?:{
|
|
56
|
-
* created_at:number,
|
|
57
|
-
* access_token:string,
|
|
58
|
-
* expires_in:number,
|
|
59
|
-
* token_type:string,
|
|
60
|
-
* }
|
|
61
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
62
|
-
*
|
|
63
|
-
* • `ok` : État de la requête (true ou false)
|
|
64
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
65
|
-
* • `error?` : Erreur lors de la génération du token
|
|
66
|
-
* • `result?` : Résultat
|
|
67
|
-
* > • `created_at` : Date de la création du token
|
|
68
|
-
* > • `access_token` : Le code (token) généré
|
|
69
|
-
* > • `expires_in` : Délais (en secondes) de l'expiration du token
|
|
70
|
-
* > • `token_type` : Le type du token ("Bearer")
|
|
71
|
-
*
|
|
72
|
-
* ---
|
|
73
|
-
* @example
|
|
74
|
-
* client.generateToken().then(console.log);
|
|
75
|
-
*
|
|
76
|
-
* // Exemple de réponse :
|
|
77
|
-
* // {
|
|
78
|
-
* // ok: true,
|
|
79
|
-
* // result: {
|
|
80
|
-
* // created_at: 1637167088,
|
|
81
|
-
* // access_token: "abcdefgh123456789",
|
|
82
|
-
* // expires_in: 3600,
|
|
83
|
-
* // token_type: "Bearer",
|
|
84
|
-
* // },
|
|
85
|
-
* // }
|
|
86
|
-
*/
|
|
87
|
-
async generateToken() {
|
|
88
|
-
try {
|
|
89
|
-
const response = await fetch(`https://id.twitch.tv/oauth2/token?client_id=${this.clientId}&client_secret=${this.clientSecret}&grant_type=client_credentials`, {
|
|
90
|
-
method: "POST",
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
if (!response.ok) {
|
|
94
|
-
return { ok: false, statusText: response.statusText };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const result = await response.json();
|
|
98
|
-
result.token_type = "Bearer";
|
|
99
|
-
result.created_at = new Date().getTime();
|
|
100
|
-
this.updateTokenFile(result);
|
|
101
|
-
return { ok: true, result };
|
|
102
|
-
} catch (error) {
|
|
103
|
-
return { ok: false, error: error.stack };
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* 👀 **Renvoi la validité du token actuel**
|
|
108
|
-
*
|
|
109
|
-
* ---
|
|
110
|
-
* @returns {boolean} **Renvoi `true` si le token a expiré, sinon `false`**
|
|
111
|
-
*
|
|
112
|
-
* ---
|
|
113
|
-
* @example
|
|
114
|
-
* console.log(client.isExpiredToken());
|
|
115
|
-
*
|
|
116
|
-
* // Exemple de réponse :
|
|
117
|
-
* // true
|
|
118
|
-
*/
|
|
119
|
-
isExpiredToken() {
|
|
120
|
-
if (!this.token.access_token || this.token.access_token === "") {
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const now = Math.floor(Date.now() / 1000);
|
|
125
|
-
const createdAt = Math.floor(this.token.created_at / 1000);
|
|
126
|
-
const expiresIn = this.token.expires_in;
|
|
127
|
-
const expirationTime = createdAt + expiresIn;
|
|
128
|
-
|
|
129
|
-
return now >= expirationTime;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* 👀 **Génère un nouveau token**
|
|
133
|
-
* 💡 **Note** : Le token se gère de façon automatique, cette fonction sert uniquement a son auto-gestion
|
|
134
|
-
*
|
|
135
|
-
* ---
|
|
136
|
-
* @returns {Promise<{
|
|
137
|
-
* ok:boolean,
|
|
138
|
-
* statusText?:string,
|
|
139
|
-
* error?:string,
|
|
140
|
-
* result?:{
|
|
141
|
-
* created_at:number,
|
|
142
|
-
* access_token:string,
|
|
143
|
-
* expires_in:number,
|
|
144
|
-
* token_type:string,
|
|
145
|
-
* }
|
|
146
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
147
|
-
*
|
|
148
|
-
* • `ok` : État de la requête (true ou false)
|
|
149
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
150
|
-
* • `error?` : Erreur lors de la génération du token
|
|
151
|
-
* • `result?` : Résultat
|
|
152
|
-
* > • `created_at` : Date de la création du token
|
|
153
|
-
* > • `access_token` : Le code (token) généré
|
|
154
|
-
* > • `expires_in` : Délais (en secondes) de l'expiration du token
|
|
155
|
-
* > • `token_type` : Le type du token ("Bearer")
|
|
156
|
-
*
|
|
157
|
-
* ---
|
|
158
|
-
* @example
|
|
159
|
-
* client.refreshToken().then(console.log);
|
|
160
|
-
*
|
|
161
|
-
* // Exemple de réponse :
|
|
162
|
-
* // {
|
|
163
|
-
* // ok: true,
|
|
164
|
-
* // result: {
|
|
165
|
-
* // created_at: 1637167088,
|
|
166
|
-
* // access_token: "abcdefgh123456789",
|
|
167
|
-
* // expires_in: 3600,
|
|
168
|
-
* // token_type: "Bearer",
|
|
169
|
-
* // },
|
|
170
|
-
* // }
|
|
171
|
-
*/
|
|
172
|
-
async refreshToken() {
|
|
173
|
-
try {
|
|
174
|
-
const newToken = await this.generateToken();
|
|
175
|
-
|
|
176
|
-
if (!newToken.ok) {
|
|
177
|
-
return { ok: false, error: newToken.error ?? newToken.statusText };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
this.updateTokenFile(newToken.result);
|
|
181
|
-
return { ok: true, result: newToken.result };
|
|
182
|
-
} catch (error) {
|
|
183
|
-
return { ok: false, error: error.stack };
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* 👀 **Valide le token**
|
|
188
|
-
* 💡 **Note** : Le token se gère de façon automatique, cette fonction sert uniquement a son auto-gestion
|
|
189
|
-
*
|
|
190
|
-
* ---
|
|
191
|
-
* @example
|
|
192
|
-
* await client.validateToken();
|
|
193
|
-
*/
|
|
194
|
-
async validateToken() {
|
|
195
|
-
try {
|
|
196
|
-
if (!this.token.access_token || this.token.access_token === "") {
|
|
197
|
-
await this.refreshToken();
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const response = await fetch(`https://id.twitch.tv/oauth2/validate`, {
|
|
201
|
-
headers: {
|
|
202
|
-
Authorization: `Bearer ${this.token.access_token}`
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
if (!response.ok) {
|
|
207
|
-
if (response.status === 401) {
|
|
208
|
-
await this.refreshToken();
|
|
209
|
-
return this.validateToken();
|
|
210
|
-
}
|
|
211
|
-
return { ok: false, statusText: response.statusText };
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const result = await response.json();
|
|
215
|
-
return { ok: true, result };
|
|
216
|
-
} catch (error) {
|
|
217
|
-
return { ok: false, error: error.stack };
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* 👀 **Met à jour le token**
|
|
222
|
-
* 💡 **Note** : Le token se gère de façon automatique, cette fonction sert uniquement a son auto-gestion
|
|
223
|
-
*
|
|
224
|
-
* ---
|
|
225
|
-
* @example
|
|
226
|
-
* await client.updateTokenFile();
|
|
227
|
-
*/
|
|
228
|
-
updateTokenFile(tokenData) {
|
|
229
|
-
writeFileSync(TwitchTokenPath, JSON.stringify(tokenData, null, 4));
|
|
230
|
-
this.token = tokenData;
|
|
231
|
-
TwitchToken = tokenData;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* 👀 **Démarre la surveillance pour la validation periodique du token (toutes les heures)**
|
|
235
|
-
* 💡 **Note** : Le token se gère de façon automatique, cette fonction sert uniquement a son auto-gestion
|
|
236
|
-
*
|
|
237
|
-
* ---
|
|
238
|
-
* @example
|
|
239
|
-
* await client.startPeriodicValidation();
|
|
240
|
-
*/
|
|
241
|
-
startPeriodicValidation() {
|
|
242
|
-
if (this.validateInterval) {
|
|
243
|
-
clearInterval(this.validateInterval);
|
|
244
|
-
}
|
|
245
|
-
this.validateInterval = setInterval(async () => {
|
|
246
|
-
const validation = await this.validateToken();
|
|
247
|
-
if (!validation.ok) {
|
|
248
|
-
console.error("Token validation failed:", validation.error || validation.statusText);
|
|
249
|
-
}
|
|
250
|
-
}, 3600000); // 1 hour in milliseconds
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* 👀 **Renvoi une liste des streams**
|
|
254
|
-
* 💡 **Note** : La liste est classée par ordre décroissant du nombre de téléspectateurs regardant le flux. Étant donné que les spectateurs vont et viennent pendant un flux, il est possible de trouver des flux en double ou manquants dans la liste au fur et à mesure que vous parcourez les résultats.
|
|
255
|
-
*
|
|
256
|
-
* ---
|
|
257
|
-
* @param {{
|
|
258
|
-
* users_names?:Array<string>,
|
|
259
|
-
* games_names?:Array<string>,
|
|
260
|
-
* type?:"all"|"live",
|
|
261
|
-
* languages?:Array<string>,
|
|
262
|
-
* first?:number,
|
|
263
|
-
* before?:string,
|
|
264
|
-
* after?:string,
|
|
265
|
-
* }} [params] **Paramètres de filtrage** :
|
|
266
|
-
*
|
|
267
|
-
* • `users_names` : Les noms d'utilisateurs utilisés pour filtrer la liste des flux. Renvoie uniquement les flux des utilisateurs qui diffusent. Vous pouvez spécifier un maximum de 100 noms d'utilisateurs.
|
|
268
|
-
* • `games_names` : Les noms des jeux (catégories) utilisés pour filtrer la liste des flux. Renvoie uniquement les flux qui diffusent les jeux (catégories). Vous pouvez spécifier un maximum de 100 noms.
|
|
269
|
-
* • `type` : Type de flux par lequel filtrer la liste des flux. Par défaut : "all".
|
|
270
|
-
* • `languages` : Un code de langue utilisé pour filtrer la liste des flux. Renvoie uniquement les flux diffusés dans la langue spécifiée. Spécifiez la langue à l'aide d'un code de langue à deux lettres ISO 639-1 ou autre si la diffusion utilise une langue ne figurant pas dans la liste des [langues de diffusion prises en charge](https://help.twitch.tv/s/article/linguals-on-twitch?langue=en_US#streamlang). Vous pouvez spécifier un maximum de 100 codes de langue.
|
|
271
|
-
* • `first` : Nombre maximum d'éléments à renvoyer par page dans la réponse. La taille minimale de la page est de 1 élément par page et la taille maximale est de 100 éléments par page. La valeur par défaut est 20.
|
|
272
|
-
* • `before` : Le curseur utilisé pour obtenir la page de résultats précédente. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
273
|
-
* • `after` : Le curseur utilisé pour obtenir la page suivante de résultats. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
274
|
-
*
|
|
275
|
-
* ---
|
|
276
|
-
* @returns {Promise<{
|
|
277
|
-
* ok:boolean,
|
|
278
|
-
* statusText?:string,
|
|
279
|
-
* error?:string,
|
|
280
|
-
* result?:Array<{
|
|
281
|
-
* id:string,
|
|
282
|
-
* user_id:string,
|
|
283
|
-
* user_login:string,
|
|
284
|
-
* user_name:string,
|
|
285
|
-
* game_id:string,
|
|
286
|
-
* game_name:string,
|
|
287
|
-
* type:"live"|"",
|
|
288
|
-
* title:string|"",
|
|
289
|
-
* tags:Array<string>,
|
|
290
|
-
* viewer_count:number,
|
|
291
|
-
* started_at:string,
|
|
292
|
-
* language:string,
|
|
293
|
-
* thumbnail_url:string,
|
|
294
|
-
* tag_ids:[],
|
|
295
|
-
* is_mature:boolean
|
|
296
|
-
* }>
|
|
297
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
298
|
-
*
|
|
299
|
-
* • `ok` : État de la requête (true ou false)
|
|
300
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
301
|
-
* • `error?` : Erreur lors de la récupération des streams
|
|
302
|
-
* • `result?` La liste des flux.
|
|
303
|
-
* > • `id` Un identifiant qui identifie le flux. Vous pourrez utiliser cet identifiant ultérieurement pour rechercher la vidéo à la demande (VOD).
|
|
304
|
-
* > • `user_id` L'ID de l'utilisateur qui diffuse le flux.
|
|
305
|
-
* > • `user_login` Le nom de connexion de l'utilisateur.
|
|
306
|
-
* > • `user_name` Le nom d'affichage de l'utilisateur.
|
|
307
|
-
* > • `game_id` L'ID de la catégorie ou du jeu en cours de lecture.
|
|
308
|
-
* > • `game_name` Le nom de la catégorie ou du jeu en cours.
|
|
309
|
-
* > • `type` Le type de flux. Si une erreur se produit, ce champ est défini sur une chaîne vide.
|
|
310
|
-
* > • `title` Le titre du flux. Est une chaîne vide si elle n'est pas définie.
|
|
311
|
-
* > • `tags` Les balises appliquées au flux.
|
|
312
|
-
* > • `viewer_count` Le nombre d'utilisateurs regardant le flux.
|
|
313
|
-
* > • `started_at` La date et l'heure UTC (au format RFC3339) du début de la diffusion.
|
|
314
|
-
* > • `langue` La langue utilisée par le flux. Il s'agit d'un code de langue à deux lettres ISO 639-1 ou autre si le flux utilise une langue qui ne figure pas dans la liste des [langues de flux prises en charge](https://help.twitch.tv/s/article/linguals-on-twitch?langue=en_US#streamlang).
|
|
315
|
-
* > • `thumbnail_url` Une URL vers une image d'une image des 5 dernières minutes du flux. Remplacez les espaces réservés de largeur et de hauteur dans l'URL (**{width}x{height}**) par la taille de l'image souhaitée, en pixels.
|
|
316
|
-
* > • `tag_ids` **IMPORTANT** Depuis le 28 février 2023, ce champ est obsolète et renvoie uniquement un tableau vide.
|
|
317
|
-
* > • `is_mature` Une valeur booléenne qui indique si le flux est destiné à un public adulte.
|
|
318
|
-
*
|
|
319
|
-
* ---
|
|
320
|
-
* @example
|
|
321
|
-
* client.getStreams().then(console.log); // Obtient des informations sur les 20 flux les plus actifs.
|
|
322
|
-
*
|
|
323
|
-
* client.getStreams({
|
|
324
|
-
users_names:["twitchdev"]
|
|
325
|
-
}).then(console.log); // Obtient les flux pour les connexions spécifiées. Si l’utilisateur n’est pas en direct, la réponse ne l’inclut pas.
|
|
326
|
-
*/
|
|
327
|
-
async getStreams(params) {
|
|
328
|
-
|
|
329
|
-
try {
|
|
330
|
-
|
|
331
|
-
let link = `https://api.twitch.tv/helix/streams`;
|
|
332
|
-
const linkParams = [];
|
|
333
|
-
|
|
334
|
-
if (params) {
|
|
335
|
-
|
|
336
|
-
if (params.after) {
|
|
337
|
-
linkParams.push(`after=${params.after}`);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (params.before) {
|
|
341
|
-
linkParams.push(`before=${params.before}`);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (params.first) {
|
|
345
|
-
linkParams.push(`first=${params.first}`);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
if (params.games_names) {
|
|
349
|
-
const games = await this.getGames(params.games_names);
|
|
350
|
-
if (!games.ok) {
|
|
351
|
-
return { ok:false, error:games.error ?? games.statusText };
|
|
352
|
-
}
|
|
353
|
-
const ids = games.result.map(game => game.id);
|
|
354
|
-
linkParams.push(`game_id=${ids.slice(0, 100).join('&game_id=')}`);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (params.languages) {
|
|
358
|
-
linkParams.push(`language=${params.languages.slice(0, 100).join('&language=')}`);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (params.type) {
|
|
362
|
-
linkParams.push(`type=${params.type}`);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (params.users_names) {
|
|
366
|
-
const users = await this.getUsers(params.users_names);
|
|
367
|
-
if (!users.ok) {
|
|
368
|
-
return { ok:false, error:users.error ?? users.statusText };
|
|
369
|
-
}
|
|
370
|
-
const userIds = users.result.map(user => user.id);
|
|
371
|
-
linkParams.push(`user_id=${userIds.slice(0, 100).join('&user_id=')}`);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (this.isExpiredToken()) {
|
|
377
|
-
await this.refreshToken();
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
link += "?" + linkParams.join("&");
|
|
381
|
-
|
|
382
|
-
const _ = await fetch(link, {
|
|
383
|
-
method:"GET",
|
|
384
|
-
headers:{
|
|
385
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
386
|
-
"Client-Id":this.clientId,
|
|
387
|
-
},
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
if (!_.ok) {
|
|
391
|
-
return { ok:false, statusText:_.statusText };
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const result = await _.json();
|
|
395
|
-
return { ok:true, result:result.data };
|
|
396
|
-
|
|
397
|
-
}
|
|
398
|
-
catch (error) {
|
|
399
|
-
return { ok:false, error:error.stack };
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* 👀 **Renvoi les informations d'un ou plusieurs utilisateur(s)**
|
|
404
|
-
*
|
|
405
|
-
* ---
|
|
406
|
-
* @param {Array<string>} usernames Les noms d'utilisateur des utilisateurs à obtenir. Le nombre maximum de noms d'utilisateur que vous pouvez spécifier est de 100.
|
|
407
|
-
*
|
|
408
|
-
* ---
|
|
409
|
-
* @returns {Promise<{
|
|
410
|
-
* ok:boolean,
|
|
411
|
-
* statusText?:string,
|
|
412
|
-
* result?:Array<{
|
|
413
|
-
* id:string,
|
|
414
|
-
* display_name:string,
|
|
415
|
-
* broadcaster_type:""|"affiliate"|"partner",
|
|
416
|
-
* description:string,
|
|
417
|
-
* profile_image_url:string,
|
|
418
|
-
* offline_image_url:string,
|
|
419
|
-
* view_count:number,
|
|
420
|
-
* created_at:string
|
|
421
|
-
* }>
|
|
422
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
423
|
-
*
|
|
424
|
-
* • `ok` : État de la requête (true ou false)
|
|
425
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
426
|
-
* • `error?` : Erreur lors de la récupération des utilisateurs
|
|
427
|
-
* • `result?` La liste des utilisateurs.
|
|
428
|
-
* > • `id` Un identifiant qui identifie l'utilisateur.
|
|
429
|
-
* > • `login` Le nom d'affichage de l'utilisateur.
|
|
430
|
-
* > • `type` Le type d'utilisateur.
|
|
431
|
-
* > • `broadcaster_type` Le type de diffuseur.
|
|
432
|
-
* > • `description` La description de l'utilisateur sur sa chaîne.
|
|
433
|
-
* > • `profile_image_url` Une URL vers l'image de profil de l'utilisateur.
|
|
434
|
-
* > • `offline_image_url` Une URL vers l'image hors ligne de l'utilisateur.
|
|
435
|
-
* > • `view_count` **REMARQUE** : ce champ est obsolète (voir [Point de terminaison de l'API Get Users – Dépréciation de « view_count »)](https://discuss.dev.twitch.tv/t/get-users-api -endpoint-view-count-deprecation/37777)). Toutes les données contenues dans ce champ ne sont pas valides et ne doivent pas être utilisées.
|
|
436
|
-
* > • `created_at` La date et l'heure UTC auxquelles le compte de l'utilisateur a été créé. L'horodatage est au format RFC3339.
|
|
437
|
-
*
|
|
438
|
-
* ---
|
|
439
|
-
* @example
|
|
440
|
-
client.getUsers(["twitchdev"]).then(console.log);
|
|
441
|
-
*/
|
|
442
|
-
async getUsers(usernames) {
|
|
443
|
-
|
|
444
|
-
try {
|
|
445
|
-
|
|
446
|
-
const map = usernames.splice(0, 100).join('&login=');
|
|
447
|
-
const link = `https://api.twitch.tv/helix/users?login=${map}`;
|
|
448
|
-
|
|
449
|
-
if (this.isExpiredToken()) {
|
|
450
|
-
await this.refreshToken();
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const _ = await fetch(link, {
|
|
454
|
-
method:"GET",
|
|
455
|
-
headers:{
|
|
456
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
457
|
-
"Client-Id":this.clientId,
|
|
458
|
-
},
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
if (!_.ok) {
|
|
462
|
-
return { ok:false, statusText:_.statusText };
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const result = await _.json();
|
|
466
|
-
return { ok:true, result:result.data };
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
catch (error) {
|
|
470
|
-
return { ok:false, error:error.stack };
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* 👀 **Renvoi une liste de Cheermotes que les utilisateurs peuvent utiliser pour encourager Bits dans la salle de discussion de n'importe quelle chaîne compatible Bits.**
|
|
476
|
-
* 💡 **Note** : Les cheermotes sont des émoticônes animées auxquelles les spectateurs peuvent attribuer des Bits.
|
|
477
|
-
*
|
|
478
|
-
* ---
|
|
479
|
-
* @returns {Promise<{
|
|
480
|
-
* ok:boolean,
|
|
481
|
-
* statusText?:string,
|
|
482
|
-
* error?:string,
|
|
483
|
-
* result?:Array<{
|
|
484
|
-
* prefix:string,
|
|
485
|
-
* tiers:Array<{
|
|
486
|
-
* min_bits:number,
|
|
487
|
-
* id:"1"|"100"|"500"|"1000"|"5000"|"10000"|"100000",
|
|
488
|
-
* color:string,
|
|
489
|
-
* images:{
|
|
490
|
-
* dark:{
|
|
491
|
-
* animated:{
|
|
492
|
-
* "1":string,
|
|
493
|
-
* "1.5":string,
|
|
494
|
-
* "2":string,
|
|
495
|
-
* "3":string,
|
|
496
|
-
* "4":string,
|
|
497
|
-
* },
|
|
498
|
-
* static:{
|
|
499
|
-
* "1":string,
|
|
500
|
-
* "1.5":string,
|
|
501
|
-
* "2":string,
|
|
502
|
-
* "3":string,
|
|
503
|
-
* "4":string,
|
|
504
|
-
* },
|
|
505
|
-
* },
|
|
506
|
-
* light:{
|
|
507
|
-
* animated:{
|
|
508
|
-
* "1":string,
|
|
509
|
-
* "1.5":string,
|
|
510
|
-
* "2":string,
|
|
511
|
-
* "3":string,
|
|
512
|
-
* "4":string,
|
|
513
|
-
* },
|
|
514
|
-
* static:{
|
|
515
|
-
* "1":string,
|
|
516
|
-
* "1.5":string,
|
|
517
|
-
* "2":string,
|
|
518
|
-
* "3":string,
|
|
519
|
-
* "4":string,
|
|
520
|
-
* },
|
|
521
|
-
* },
|
|
522
|
-
* },
|
|
523
|
-
* can_cheer:boolean,
|
|
524
|
-
* show_in_bits_card:boolean,
|
|
525
|
-
* }>,
|
|
526
|
-
* type:"global_first_party"|"global_third_party"|"channel_custom"|"display_only"|"sponsored",
|
|
527
|
-
* order:number,
|
|
528
|
-
* last_updated:string,
|
|
529
|
-
* is_charitable:boolean,
|
|
530
|
-
* }>
|
|
531
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
532
|
-
*
|
|
533
|
-
* • `ok` : État de la requête (true ou false)
|
|
534
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
535
|
-
* • `error?` : Erreur lors de la récupération des cheermotes
|
|
536
|
-
* • `result ?` La liste des Cheermotes. La liste est classée par ordre croissant de la valeur du champ de commande.
|
|
537
|
-
* > • `prefix` La partie nom de la chaîne Cheermote que vous utilisez dans le chat pour encourager Bits. La chaîne Cheermote complète est la concaténation de {préfixe} + {nombre de bits}. Par exemple, si le préfixe est « Cheer » et que vous souhaitez encourager 100 bits, la chaîne Cheermote complète est Cheer100. Lorsque la chaîne Cheermote est saisie dans le chat, Twitch la convertit en l'image associée au niveau Bits qui a été acclamé.
|
|
538
|
-
* > • `tiers`
|
|
539
|
-
* > > • `min_bits` Le nombre minimum de Bits que vous devez encourager à ce niveau. Le nombre maximum de Bits que vous pouvez encourager à ce niveau est déterminé par le nombre minimum de Bits requis du niveau suivant moins 1. Par exemple, si min_bits est 1 et min_bits pour le niveau suivant est 100, la plage de Bits pour ce niveau. est compris entre 1 et 99. La valeur minimale de bits du dernier niveau est le nombre maximum de bits que vous pouvez encourager en utilisant ce Cheermote. Par exemple, 10 000.
|
|
540
|
-
* > > • `id` Le niveau.
|
|
541
|
-
* > > • `color` Le code hexadécimal de la couleur associée à ce niveau (par exemple, #979797).
|
|
542
|
-
* > > • `images` Les ensembles d'images animées et statiques pour le Cheermote. Le dictionnaire d'images est organisé par thème, format et taille. Les touches de thème sont sombres et claires. Chaque thème est un dictionnaire de formats : animés et statiques. Chaque format est un dictionnaire de tailles : 1, 1,5, 2, 3 et 4. La valeur de chaque taille contient l'URL de l'image.
|
|
543
|
-
* > > • `can_cheer` Une valeur booléenne qui détermine si les utilisateurs peuvent encourager à ce niveau.
|
|
544
|
-
* > > • `show_in_bits_card` Une valeur booléenne qui détermine si ce niveau est affiché dans la carte Bits. Est vrai si ce niveau est affiché dans la carte Bits.
|
|
545
|
-
*
|
|
546
|
-
* > • `type` Le type de Cheermote.
|
|
547
|
-
* > • `order` L'ordre dans lequel les Cheermotes sont affichés dans la carte Bits. Les numéros ne peuvent pas être consécutifs. Par exemple, les nombres peuvent passer de 1 à 7 puis à 13. Les numéros de commande sont uniques au sein d'un type de Cheermote (par exemple, global_first_party) mais peuvent ne pas être uniques parmi tous les Cheermotes de la réponse.
|
|
548
|
-
* > • `last_updated` La date et l'heure, au format RFC3339, de la dernière mise à jour de ce Cheermote.
|
|
549
|
-
* > • `is_charitable` Une valeur booléenne qui indique si ce Cheermote fournit une contribution caritative lors des campagnes caritatives.
|
|
550
|
-
*
|
|
551
|
-
* ---
|
|
552
|
-
* @example
|
|
553
|
-
client.getCheermotes().then(console.log);
|
|
554
|
-
*/
|
|
555
|
-
async getCheermotes() {
|
|
556
|
-
|
|
557
|
-
try {
|
|
558
|
-
|
|
559
|
-
const link = "https://api.twitch.tv/helix/bits/cheermotes";
|
|
560
|
-
|
|
561
|
-
if (this.isExpiredToken()) {
|
|
562
|
-
await this.refreshToken();
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
const _ = await fetch(link, {
|
|
566
|
-
method:"GET",
|
|
567
|
-
headers:{
|
|
568
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
569
|
-
"Client-Id":this.clientId,
|
|
570
|
-
},
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
if (!_.ok) {
|
|
574
|
-
return { ok:false, statusText:_.statusText };
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
const result = await _.json();
|
|
578
|
-
return { ok:true, result:result.data };
|
|
579
|
-
|
|
580
|
-
}
|
|
581
|
-
catch (error) {
|
|
582
|
-
return { ok:false, error:error.stack };
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* 👀 **Obtient la liste des [émotes globales](https://www.twitch.tv/creatorcamp/fr-fr/paths/getting-started-on-twitch/emotes/) ou la liste des émotes personnalisées du diffuseur.**
|
|
588
|
-
* 💡 **Note** : Les émotes globales sont des émoticônes créées par Twitch que les utilisateurs peuvent utiliser dans n'importe quel chat Twitch.
|
|
589
|
-
* Les diffuseurs créent ces émotes personnalisées pour les utilisateurs qui s'abonnent ou suivent la chaîne ou encouragent Bits dans la fenêtre de discussion de la chaîne. [En savoir plus](https://dev.twitch.tv/docs/irc/emotes/).
|
|
590
|
-
* 💡 **Note** : À l'exception des émoticônes personnalisées, les utilisateurs peuvent utiliser des émoticônes personnalisées dans n'importe quel chat Twitch.
|
|
591
|
-
*
|
|
592
|
-
* ---
|
|
593
|
-
* @param {string} [username] Le nom d'utilisateur qui identifie le diffuseur dont vous souhaitez obtenir les émoticônes.
|
|
594
|
-
*
|
|
595
|
-
* ---
|
|
596
|
-
* @returns {Promise<{
|
|
597
|
-
* ok:boolean,
|
|
598
|
-
* statusText?:string,
|
|
599
|
-
* error?:string,
|
|
600
|
-
* result?:Array<{
|
|
601
|
-
* id:string,
|
|
602
|
-
* name:string,
|
|
603
|
-
* images:{
|
|
604
|
-
* url_1x:string,
|
|
605
|
-
* url_2x:string,
|
|
606
|
-
* url_4x:string,
|
|
607
|
-
* },
|
|
608
|
-
* tier?:string,
|
|
609
|
-
* emote_type?:"bitstier"|"follower"|"subscriptions",
|
|
610
|
-
* emote_set_id?:string,
|
|
611
|
-
* format:Array<"static"|"animated">,
|
|
612
|
-
* scale:Array<"1.0"|"2.0"|"3.0">,
|
|
613
|
-
* theme_mode:Array<"dark"|"light">,
|
|
614
|
-
* template:string,
|
|
615
|
-
* }>
|
|
616
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
617
|
-
*
|
|
618
|
-
* • `ok` : État de la requête (true ou false)
|
|
619
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
620
|
-
* • `error?` : Erreur lors de la récupération des emotes
|
|
621
|
-
* • `result?` La liste des émoticônes globales. ou la liste des émoticônes créées par le diffuseur spécifié. Si le diffuseur n’a pas créé d’émoticônes personnalisées, la liste est vide.
|
|
622
|
-
* > • `id` Un identifiant qui identifie cette emote.
|
|
623
|
-
* > • `name` Le nom de l'emote. Il s'agit du nom que les téléspectateurs saisissent dans la fenêtre de discussion pour faire apparaître l'émote.
|
|
624
|
-
* > • `images` Les URL des images pour l'emote. Ces URL d’images fournissent toujours une image d’émoticône statique et non animée avec un arrière-plan clair. **Note** : Vous devez utiliser l'URL modélisée dans le champ du modèle pour récupérer l'image au lieu d'utiliser ces URL.
|
|
625
|
-
* > > • `url_1x` Une URL vers la petite version (28px x 28px) de l'emote.
|
|
626
|
-
* > > • `url_2x` Une URL vers la version moyenne (56px x 56px) de l'emote.
|
|
627
|
-
* > > • `url_4x` Une URL vers la grande version (112px x 112px) de l'emote.
|
|
628
|
-
*
|
|
629
|
-
* > • `tier?` Le niveau d'abonné auquel l'emote est déverrouillée. Ce champ contient les informations de niveau uniquement si emote_type est défini sur abonnements, sinon il s'agit d'une chaîne vide.
|
|
630
|
-
* > • `emote_type?` Le type d'emote.
|
|
631
|
-
* > • `emote_set_id?` Un identifiant qui identifie l'ensemble d'émotes auquel appartient l'émote.
|
|
632
|
-
* > • `format` Les formats dans lesquels l'émote est disponible. Par exemple, si l'émote est disponible uniquement au format PNG statique, le tableau ne contient que du statique. Mais si l'emote est disponible sous forme de PNG statique et de GIF animé, le tableau contient des éléments statiques et animés.
|
|
633
|
-
* > • `scale` Les tailles dans lesquelles l'emote est disponible. Par exemple, si l'emote est disponible en petites et moyennes tailles, le tableau contient 1.0 et 2.0.
|
|
634
|
-
* > • `theme_mode` Les thèmes d'arrière-plan dans lesquels l'emote est disponible.
|
|
635
|
-
* > • `template` Une URL basée sur un modèle. Utilisez les valeurs des champs id, format, scale et theme_mode pour remplacer les chaînes d'espace réservé de même nom dans l'URL modélisée afin de créer une URL CDN (réseau de diffusion de contenu) que vous utilisez pour récupérer l'emote. Pour plus d'informations sur l'apparence du modèle et comment l'utiliser pour récupérer des émoticônes, consultez [Format d'URL Emote CDN](https://dev.twitch.tv/docs/irc/emotes/#cdn-template). Vous devez utiliser ce modèle au lieu d'utiliser les URL dans l'objet images.
|
|
636
|
-
*
|
|
637
|
-
* ---
|
|
638
|
-
* @example
|
|
639
|
-
client.getChatEmotes().then(console.log); // Obtient toutes les émoticônes globales.
|
|
640
|
-
client.getChatEmotes("twitchdev").then(console.log); // Obtient les émoticônes personnalisées créées par la chaîne TwitchDev.
|
|
641
|
-
*/
|
|
642
|
-
async getChatEmotes(username) {
|
|
643
|
-
|
|
644
|
-
try {
|
|
645
|
-
|
|
646
|
-
let link = `https://api.twitch.tv/helix/chat/emotes/global`;
|
|
647
|
-
|
|
648
|
-
if (username) {
|
|
649
|
-
|
|
650
|
-
const user = await this.getUsers([username]);
|
|
651
|
-
|
|
652
|
-
if (!user.ok) {
|
|
653
|
-
return { ok:false, error:user.error ?? user.statusText };
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
const broadcaster_id = user.result[0]?.id;
|
|
657
|
-
|
|
658
|
-
link = `https://api.twitch.tv/helix/chat/emotes/?broadcaster_id=${broadcaster_id}`;
|
|
659
|
-
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
if (this.isExpiredToken()) {
|
|
663
|
-
await this.refreshToken();
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
const _ = await fetch(link, {
|
|
667
|
-
method:"GET",
|
|
668
|
-
headers:{
|
|
669
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
670
|
-
"Client-Id":this.clientId,
|
|
671
|
-
},
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
if (!_.ok) {
|
|
675
|
-
return { ok:false, statusText:_.statusText };
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
const result = await _.json();
|
|
679
|
-
return { ok:true, result:result.data };
|
|
680
|
-
|
|
681
|
-
}
|
|
682
|
-
catch (error) {
|
|
683
|
-
return { ok:false, error:error.stack };
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
}
|
|
687
|
-
/**
|
|
688
|
-
* 👀 **Obtient la liste des badges de discussion de Twitch, que les utilisateurs peuvent utiliser dans la salle de discussion de n'importe quelle chaîne, ou la liste des badges de discussion personnalisés du diffuseur.**
|
|
689
|
-
* 💡 **Note** : Pour plus d'informations sur les badges de chat, consultez le [Guide des badges de chat Twitch](https://help.twitch.tv/s/article/twitch-chat-badges-guide?langue=en_US).
|
|
690
|
-
* 💡 **Note** : La liste est vide si le diffuseur n'a pas créé de badges de discussion personnalisés. Pour plus d'informations sur les badges personnalisés, consultez [badges d'abonné](https://help.twitch.tv/s/article/subscriber-badge-guide?langue=en_US) et [badges Bits](https://help.twitch. tv/s/article/custom-bit-badges-guide?langue=en_US).
|
|
691
|
-
*
|
|
692
|
-
* ---
|
|
693
|
-
* @param {string} [username] Le nom d'utilisateur
|
|
694
|
-
*
|
|
695
|
-
* ---
|
|
696
|
-
* @returns {Promise<{
|
|
697
|
-
* ok:boolean,
|
|
698
|
-
* statusText?:string,
|
|
699
|
-
* error?:string,
|
|
700
|
-
* result?:Array<{
|
|
701
|
-
* set_id:string,
|
|
702
|
-
* versions:Array<{
|
|
703
|
-
* id:string,
|
|
704
|
-
* image_url_1x:string,
|
|
705
|
-
* image_url_2x:string,
|
|
706
|
-
* image_url_4x:string,
|
|
707
|
-
* title:string,
|
|
708
|
-
* description:string,
|
|
709
|
-
* click_action:string|null,
|
|
710
|
-
* click_url:string|null,
|
|
711
|
-
* }>
|
|
712
|
-
* }>
|
|
713
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
714
|
-
*
|
|
715
|
-
* • `ok` : État de la requête (true ou false)
|
|
716
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
717
|
-
* • `error?` : Erreur lors de la récupération des badges
|
|
718
|
-
* • `result?` La liste des badges de chat. La liste est triée par ordre croissant par set_id, et au sein d'un ensemble, la liste est triée par ordre croissant par id.
|
|
719
|
-
* > • `set_id` Un identifiant qui identifie cet ensemble de badges de discussion. Par exemple, Bits ou Abonné.
|
|
720
|
-
* > • `versions` La liste des badges de discussion dans cet ensemble.
|
|
721
|
-
* > > • `id` Un identifiant qui identifie cette version du badge. L'ID peut être n'importe quelle valeur. Par exemple, pour Bits, l'ID correspond au niveau de Bits, mais pour World of Warcraft, il peut s'agir d'Alliance ou de Horde.
|
|
722
|
-
* > > • `image_url_1x` Une URL vers la petite version (18px x 18px) du badge.
|
|
723
|
-
* > > • `image_url_2x` Une URL vers la version moyenne (36px x 36px) du badge.
|
|
724
|
-
* > > • `image_url_4x` Une URL vers la version grande (72px x 72px) du badge.
|
|
725
|
-
* > > • `title` Le titre du badge.
|
|
726
|
-
* > > • `description` La description du badge.
|
|
727
|
-
* > > • `click_action` L'action à entreprendre en cliquant sur le badge. Défini sur null si aucune action n'est spécifiée.
|
|
728
|
-
* > > • `click_url` L'URL vers laquelle accéder lorsque vous cliquez sur le badge. Défini sur null si aucune URL n'est spécifiée.
|
|
729
|
-
*
|
|
730
|
-
* ---
|
|
731
|
-
* @example
|
|
732
|
-
client.getChatBadges().then(console.log); // Obtient la liste des badges de discussion globaux.
|
|
733
|
-
client.getChatBadges("twitchdev").then(console.log); // Obtenez la liste des badges de discussion personnalisés créés par la chaîne TwitchDev Twitch.
|
|
734
|
-
*/
|
|
735
|
-
async getChatBadges(username) {
|
|
736
|
-
|
|
737
|
-
try {
|
|
738
|
-
|
|
739
|
-
let link = `https://api.twitch.tv/helix/chat/badges/global`;
|
|
740
|
-
|
|
741
|
-
if (username) {
|
|
742
|
-
|
|
743
|
-
const user = await this.getUsers([username]);
|
|
744
|
-
|
|
745
|
-
if (!user.ok) {
|
|
746
|
-
return { ok:false, error:user.error ?? user.statusText };
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
const broadcaster_id = user.result[0]?.id;
|
|
750
|
-
|
|
751
|
-
link = `https://api.twitch.tv/helix/chat/badges/?broadcaster_id=${broadcaster_id}`;
|
|
752
|
-
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
if (this.isExpiredToken()) {
|
|
756
|
-
await this.refreshToken();
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
const _ = await fetch(link, {
|
|
760
|
-
method:"GET",
|
|
761
|
-
headers:{
|
|
762
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
763
|
-
"Client-Id":this.clientId,
|
|
764
|
-
},
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
if (!_.ok) {
|
|
768
|
-
return { ok:false, statusText:_.statusText };
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
const result = await _.json();
|
|
772
|
-
return { ok:true, result:result.data };
|
|
773
|
-
|
|
774
|
-
}
|
|
775
|
-
catch (error) {
|
|
776
|
-
return { ok:false, error:error.stack };
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
}
|
|
780
|
-
/**
|
|
781
|
-
* 👀 **Renvoi les paramètres de discussion du diffuseur**
|
|
782
|
-
*
|
|
783
|
-
* ---
|
|
784
|
-
* @param {string} username Le nom d'utilisateur du diffuseur dont vous souhaitez obtenir les paramètres de discussion.
|
|
785
|
-
*
|
|
786
|
-
* ---
|
|
787
|
-
* @returns {Promise<{
|
|
788
|
-
* ok:boolean,
|
|
789
|
-
* statusText?:string,
|
|
790
|
-
* error?:string,
|
|
791
|
-
* result?:Array<{
|
|
792
|
-
* broadcaster_id:string,
|
|
793
|
-
* emote_mode:boolean,
|
|
794
|
-
* follower_mode:boolean,
|
|
795
|
-
* follower_mode_duration:number|null,
|
|
796
|
-
* slow_mode:boolean,
|
|
797
|
-
* slow_mode_wait_time:number|null,
|
|
798
|
-
* subscriber_mode:boolean,
|
|
799
|
-
* unique_chat_mode:boolean,
|
|
800
|
-
* }>
|
|
801
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
802
|
-
*
|
|
803
|
-
* • `ok` : État de la requête (true ou false)
|
|
804
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
805
|
-
* • `error?` : Erreur lors de la récupération des paramètres
|
|
806
|
-
* • `result?` La liste des paramètres de discussion. La liste contient un seul objet avec tous les paramètres.
|
|
807
|
-
* > • `broadcaster_id` L'ID du diffuseur spécifié dans la requête.
|
|
808
|
-
* > • `emote_mode` Une valeur booléenne qui détermine si les messages de discussion doivent contenir uniquement des émoticônes. Est vrai si les messages de discussion ne peuvent contenir que des émoticônes ; sinon, faux.
|
|
809
|
-
* > • `follower_mode` Une valeur booléenne qui détermine si le diffuseur restreint la salle de discussion aux abonnés uniquement. Est vrai si le diffuseur restreint la salle de discussion aux abonnés uniquement ; sinon, faux. Consultez le champ follower_mode_duration pour connaître la durée pendant laquelle les utilisateurs doivent suivre le diffuseur avant de pouvoir participer au salon de discussion.
|
|
810
|
-
* > • `follower_mode_duration` La durée, en minutes, pendant laquelle les utilisateurs doivent suivre le diffuseur avant de pouvoir participer au salon de discussion. Est nul si follower_mode est faux.
|
|
811
|
-
* > • `slow_mode` Une valeur booléenne qui détermine si le diffuseur limite la fréquence à laquelle les utilisateurs de la salle de discussion sont autorisés à envoyer des messages. Est vrai si le diffuseur applique un délai ; sinon, faux. Voir le champ slow_mode_wait_time pour le délai.
|
|
812
|
-
* > • `slow_mode_wait_time` Le temps, en secondes, pendant lequel les utilisateurs doivent attendre entre l'envoi de messages. Est nul si slow_mode est faux.
|
|
813
|
-
* > • `subscriber_mode` Une valeur booléenne qui détermine si seuls les utilisateurs abonnés à la chaîne du diffuseur peuvent parler dans la salle de discussion. Est vrai si le diffuseur restreint le salon de discussion aux abonnés uniquement ; sinon, faux.
|
|
814
|
-
* > • `unique_chat_mode` Une valeur booléenne qui détermine si le diffuseur demande aux utilisateurs de publier uniquement des messages uniques dans la salle de discussion. Est vrai si le diffuseur exige uniquement des messages uniques ; sinon, faux.
|
|
815
|
-
*
|
|
816
|
-
* ---
|
|
817
|
-
* @example
|
|
818
|
-
client.getChatSettings("twitchdev").then(console.log);
|
|
819
|
-
*/
|
|
820
|
-
async getChatSettings(username) {
|
|
821
|
-
|
|
822
|
-
try {
|
|
823
|
-
|
|
824
|
-
const user = await this.getUsers([username]);
|
|
825
|
-
|
|
826
|
-
if (!user.ok) {
|
|
827
|
-
return { ok:false, error:user.error ?? user.statusText };
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
const broadcaster_id = user.result[0]?.id;
|
|
831
|
-
|
|
832
|
-
const link = `https://api.twitch.tv/helix/chat/settings/?broadcaster_id=${broadcaster_id}`;
|
|
833
|
-
|
|
834
|
-
if (this.isExpiredToken()) {
|
|
835
|
-
await this.refreshToken();
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
const _ = await fetch(link, {
|
|
839
|
-
method:"GET",
|
|
840
|
-
headers:{
|
|
841
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
842
|
-
"Client-Id":this.clientId,
|
|
843
|
-
},
|
|
844
|
-
});
|
|
845
|
-
|
|
846
|
-
if (!_.ok) {
|
|
847
|
-
return { ok:false, statusText:_.statusText };
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
const result = await _.json();
|
|
851
|
-
return { ok:true, result:result.data };
|
|
852
|
-
|
|
853
|
-
}
|
|
854
|
-
catch (error) {
|
|
855
|
-
return { ok:false, error:error.stack };
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
}
|
|
859
|
-
/**
|
|
860
|
-
* 👀 **Renvoi la couleur utilisée pour le nom de l'utilisateur dans le chat.**
|
|
861
|
-
*
|
|
862
|
-
* ---
|
|
863
|
-
* @param {Array<string>} usernames L'ID de l'utilisateur dont vous souhaitez obtenir la couleur du nom d'utilisateur. L'API ignore les noms en double et les noms introuvables.
|
|
864
|
-
*
|
|
865
|
-
* ---
|
|
866
|
-
* @returns {Promise<{
|
|
867
|
-
* ok:boolean,
|
|
868
|
-
* statusText?:string,
|
|
869
|
-
* error?:string,
|
|
870
|
-
* result?:Array<{
|
|
871
|
-
* user_id:string,
|
|
872
|
-
* user_name:string,
|
|
873
|
-
* user_login:string,
|
|
874
|
-
* color:string,
|
|
875
|
-
* }>
|
|
876
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
877
|
-
*
|
|
878
|
-
* • `ok` : État de la requête (true ou false)
|
|
879
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
880
|
-
* • `error?` : Erreur lors de la récupération des couleurs
|
|
881
|
-
* • `result?` La liste des utilisateurs et le code couleur qu'ils utilisent pour leur nom.
|
|
882
|
-
* > • `user_id` Un identifiant qui identifie de manière unique l'utilisateur.
|
|
883
|
-
* > • `user_login` Le nom de connexion de l'utilisateur.
|
|
884
|
-
* > • `user_name` Le nom d'affichage de l'utilisateur.
|
|
885
|
-
* > • `color` Le code couleur hexadécimal que l'utilisateur utilise dans le chat pour son nom. Si l'utilisateur n'a pas spécifié de couleur dans ses paramètres, la chaîne est vide.
|
|
886
|
-
*
|
|
887
|
-
* ---
|
|
888
|
-
* @example
|
|
889
|
-
client.getUsersChatColor(["twitchdev"]).then(console.log);
|
|
890
|
-
*/
|
|
891
|
-
async getUsersChatColor(usernames) {
|
|
892
|
-
|
|
893
|
-
try {
|
|
894
|
-
|
|
895
|
-
const users = await this.getUsers(usernames);
|
|
896
|
-
|
|
897
|
-
if (!users.ok) {
|
|
898
|
-
return { ok:false, error:users.error ?? users.statusText };
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
const ids = users.result.map(user => user.id);
|
|
902
|
-
|
|
903
|
-
const map = ids.join('&user_id=');
|
|
904
|
-
const link = `https://api.twitch.tv/helix/chat/color?user_id=${map}`;
|
|
905
|
-
|
|
906
|
-
if (this.isExpiredToken()) {
|
|
907
|
-
await this.refreshToken();
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
const _ = await fetch(link, {
|
|
911
|
-
method:"GET",
|
|
912
|
-
headers:{
|
|
913
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
914
|
-
"Client-Id":this.clientId,
|
|
915
|
-
},
|
|
916
|
-
});
|
|
917
|
-
|
|
918
|
-
if (!_.ok) {
|
|
919
|
-
return { ok:false, statusText:_.statusText };
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
const result = await _.json();
|
|
923
|
-
return { ok:true, result:result.data };
|
|
924
|
-
|
|
925
|
-
}
|
|
926
|
-
catch (error) {
|
|
927
|
-
return { ok:false, error:error.stack };
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
}
|
|
931
|
-
/**
|
|
932
|
-
* 👀 **Obtient un ou plusieurs clips vidéo capturés à partir de flux**
|
|
933
|
-
* 💡 **Note** : Pour plus d'informations sur les clips, consultez [Comment utiliser les clips](https://help.twitch.tv/s/article/how-to-use-clips?langage=en_US).
|
|
934
|
-
*
|
|
935
|
-
* ---
|
|
936
|
-
* @param {string} username Un nom d'utilisateur qui identifie le diffuseur dont vous souhaitez obtenir les clips vidéo. Utilisez ce paramètre pour obtenir des clips capturés à partir des flux du diffuseur.
|
|
937
|
-
*
|
|
938
|
-
* ---
|
|
939
|
-
* @param {{
|
|
940
|
-
* started_at?:string,
|
|
941
|
-
* ended_at?:string,
|
|
942
|
-
* first?:number,
|
|
943
|
-
* before?:string,
|
|
944
|
-
* after?:string
|
|
945
|
-
* }} [params] **Paramètres de filtrage** :
|
|
946
|
-
*
|
|
947
|
-
* • `started_at?` La date de début utilisée pour filtrer les clips. L'API renvoie uniquement les clips situés dans la fenêtre de date de début et de fin. Spécifiez la date et l'heure au format RFC3339.
|
|
948
|
-
* • `ended_at?` La date de fin utilisée pour filtrer les clips. Si elle n’est pas spécifiée, la fenêtre horaire correspond à la date de début plus une semaine. Spécifiez la date et l'heure au format RFC3339.
|
|
949
|
-
* • `first?` Le nombre maximum de clips à renvoyer par page dans la réponse. La taille de page minimale est de 1 clip par page et la taille maximale est de 100. La valeur par défaut est de 20.
|
|
950
|
-
* • `before ?` Le curseur utilisé pour obtenir la page de résultats précédente. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
951
|
-
* • `after` Le curseur utilisé pour obtenir la page suivante de résultats. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
952
|
-
*
|
|
953
|
-
* ---
|
|
954
|
-
* @returns {Promise<{
|
|
955
|
-
* ok:boolean,
|
|
956
|
-
* statusText?:string,
|
|
957
|
-
* error?:string,
|
|
958
|
-
* result?:Array<{
|
|
959
|
-
* id:string,
|
|
960
|
-
* url:string,
|
|
961
|
-
* embed_url:string,
|
|
962
|
-
* broadcaster_id:string,
|
|
963
|
-
* broadcaster_name:string,
|
|
964
|
-
* creator_id:string,
|
|
965
|
-
* creator_name:string,
|
|
966
|
-
* video_id:string,
|
|
967
|
-
* game_id:string,
|
|
968
|
-
* language:string,
|
|
969
|
-
* title:string,
|
|
970
|
-
* view_count:number,
|
|
971
|
-
* created_at:string,
|
|
972
|
-
* thumbnail_url:string,
|
|
973
|
-
* duration:number,
|
|
974
|
-
* vod_offset:number|null,
|
|
975
|
-
* }>
|
|
976
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
977
|
-
*
|
|
978
|
-
* • `ok` : État de la requête (true ou false)
|
|
979
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
980
|
-
* • `error?` : Erreur lors de la récupération des clips
|
|
981
|
-
* • `result?` La liste des clips vidéo. Pour les clips renvoyés par game_id ou Broadcaster_id, la liste est classée par ordre décroissant du nombre de vues. Pour les listes renvoyées par id, la liste est dans le même ordre que les ID d'entrée.
|
|
982
|
-
* > • `id` Un identifiant qui identifie de manière unique le clip.
|
|
983
|
-
* > • `url` Une URL vers le clip.
|
|
984
|
-
* > • `embed_url` Une URL que vous pouvez utiliser dans une iframe pour intégrer le clip (voir [Intégration de vidéos et de clips](https://dev.twitch.tv/docs/embed/video-and-clips/)).
|
|
985
|
-
* > • `broadcaster_id` Un identifiant qui identifie le diffuseur à partir duquel la vidéo a été extraite.
|
|
986
|
-
* > • `broadcaster_name` Le nom d'affichage du diffuseur.
|
|
987
|
-
* > • `creator_id` Un identifiant qui identifie l'utilisateur qui a créé le clip.
|
|
988
|
-
* > • `creator_name` Le nom d'affichage de l'utilisateur.
|
|
989
|
-
* > • `video_id` Un identifiant qui identifie la vidéo d'où provient le clip. Ce champ contient une chaîne vide si la vidéo n'est pas disponible.
|
|
990
|
-
* > • `game_id` L'ID du jeu en cours de lecture lors de la création du clip.
|
|
991
|
-
* > • `langue` Le code de langue à deux lettres ISO 639-1 dans lequel le diffuseur diffuse. Par exemple, en pour l'anglais. La valeur est différente si le diffuseur utilise une langue que Twitch ne prend pas en charge.
|
|
992
|
-
* > • `title` Le titre du clip.
|
|
993
|
-
* > • `view_count` Le nombre de fois que le clip a été visionné.
|
|
994
|
-
* > • `created_at` La date et l'heure de création du clip. La date et l'heure sont au format RFC3339.
|
|
995
|
-
* > • `thumbnail_url` Une URL vers une image miniature du clip.
|
|
996
|
-
* > • `duration` La durée du clip, en secondes. La précision est de 0,1.
|
|
997
|
-
* > • `vod_offset` Le décalage de base zéro, en secondes, par rapport à l'endroit où le clip commence dans la vidéo (VOD). Est nul si la vidéo n'est pas disponible ou n'a pas encore été créée à partir du flux en direct (voir video_id). Notez qu’il existe un délai entre le moment où un clip est créé lors d’une diffusion et le moment où le décalage est défini. Pendant la période de retard, vod_offset est nul. Le délai est indéterminé mais dure généralement quelques minutes.
|
|
998
|
-
*
|
|
999
|
-
* ---
|
|
1000
|
-
* @example
|
|
1001
|
-
client.getClips("twitchdev").then(console.log);
|
|
1002
|
-
*/
|
|
1003
|
-
async getClips(username, params = {}) {
|
|
1004
|
-
|
|
1005
|
-
try {
|
|
1006
|
-
|
|
1007
|
-
const user = await this.getUsers([username]);
|
|
1008
|
-
|
|
1009
|
-
if (!user.ok) {
|
|
1010
|
-
return { ok:false, error:user.error ?? user.statusText };
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
const broadcaster_id = user.result[0]?.id;
|
|
1014
|
-
|
|
1015
|
-
let link = `https://api.twitch.tv/helix/clips?broadcaster_id=${broadcaster_id}`;
|
|
1016
|
-
const linkParams = [];
|
|
1017
|
-
|
|
1018
|
-
if (params) {
|
|
1019
|
-
|
|
1020
|
-
if (params.started_at) {
|
|
1021
|
-
linkParams.push(`started_at=${params.started_at}`);
|
|
1022
|
-
}
|
|
1023
|
-
if (params.ended_at) {
|
|
1024
|
-
linkParams.push(`ended_at=${params.ended_at}`);
|
|
1025
|
-
}
|
|
1026
|
-
if (params.after) {
|
|
1027
|
-
linkParams.push(`after=${params.after}`);
|
|
1028
|
-
}
|
|
1029
|
-
if (params.before) {
|
|
1030
|
-
linkParams.push(`before=${params.before}`);
|
|
1031
|
-
}
|
|
1032
|
-
if (params.first) {
|
|
1033
|
-
linkParams.push(`first=${params.first}`);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
if (this.isExpiredToken()) {
|
|
1039
|
-
await this.refreshToken();
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
link += "?" + linkParams.join("&");
|
|
1043
|
-
|
|
1044
|
-
const _ = await fetch(link, {
|
|
1045
|
-
method:"GET",
|
|
1046
|
-
headers:{
|
|
1047
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
1048
|
-
"Client-Id":this.clientId,
|
|
1049
|
-
},
|
|
1050
|
-
});
|
|
1051
|
-
|
|
1052
|
-
if (!_.ok) {
|
|
1053
|
-
return { ok:false, statusText:_.statusText };
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
const result = await _.json();
|
|
1057
|
-
return { ok:true, result:result.data };
|
|
1058
|
-
|
|
1059
|
-
}
|
|
1060
|
-
catch (error) {
|
|
1061
|
-
return { ok:false, error:error.stack };
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
}
|
|
1065
|
-
/**
|
|
1066
|
-
* 👀 **Renvoi des informations sur toutes les diffusions sur Twitch**
|
|
1067
|
-
*
|
|
1068
|
-
* ---
|
|
1069
|
-
* @param {{
|
|
1070
|
-
* first?:number,
|
|
1071
|
-
* after?:string,
|
|
1072
|
-
* before?:string,
|
|
1073
|
-
* }} [params] **Paramètres de filtrage** :
|
|
1074
|
-
*
|
|
1075
|
-
* > • `first?` Le nombre maximum d'éléments à renvoyer par page dans la réponse. La taille minimale de la page est de 1 élément par page et la taille maximale est de 100 éléments par page. La valeur par défaut est 20.
|
|
1076
|
-
* > • `after?` Le curseur utilisé pour obtenir la page suivante de résultats. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
1077
|
-
* > • `before ?` Le curseur utilisé pour obtenir la page de résultats précédente. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
1078
|
-
*
|
|
1079
|
-
* ---
|
|
1080
|
-
* @returns {Promise<{
|
|
1081
|
-
* ok:boolean,
|
|
1082
|
-
* statusText?:string,
|
|
1083
|
-
* error?:string,
|
|
1084
|
-
* result?Array<{
|
|
1085
|
-
* id:string,
|
|
1086
|
-
* name:string,
|
|
1087
|
-
* box_art_url:string,
|
|
1088
|
-
* igdb_id:string
|
|
1089
|
-
* }>
|
|
1090
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
1091
|
-
*
|
|
1092
|
-
* • `ok` : État de la requête (true ou false)
|
|
1093
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
1094
|
-
* • `error?` : Erreur lors de la récupération des jeux
|
|
1095
|
-
* • `result?` La liste des diffusions. Les émissions sont classées par nombre de téléspectateurs, les plus populaires en premier.
|
|
1096
|
-
* > • `id` Un identifiant qui identifie la catégorie ou le jeu.
|
|
1097
|
-
* > • `name` Le nom de la catégorie ou du jeu.
|
|
1098
|
-
* > • `box_art_url` Une URL vers la pochette de la catégorie ou du jeu. Vous devez remplacer l'espace réservé {width}x{height} par la taille d'image souhaitée.
|
|
1099
|
-
* > `igdb_id` L'ID que [IGDB](https://www.igdb.com) utilise pour identifier ce jeu. Si l'ID IGDB n'est pas disponible pour Twitch, ce champ est défini sur une chaîne vide.
|
|
1100
|
-
*
|
|
1101
|
-
* ---
|
|
1102
|
-
* @example
|
|
1103
|
-
client.getTopGames().then(console.log);
|
|
1104
|
-
*/
|
|
1105
|
-
async getTopGames(params) {
|
|
1106
|
-
|
|
1107
|
-
try {
|
|
1108
|
-
|
|
1109
|
-
let link = `https://api.twitch.tv/helix/games/top`;
|
|
1110
|
-
const linkParams = [];
|
|
1111
|
-
|
|
1112
|
-
if (params) {
|
|
1113
|
-
|
|
1114
|
-
if (params.after) {
|
|
1115
|
-
linkParams.push(`after=${params.after}`);
|
|
1116
|
-
}
|
|
1117
|
-
if (params.before) {
|
|
1118
|
-
linkParams.push(`before=${params.before}`);
|
|
1119
|
-
}
|
|
1120
|
-
if (params.first) {
|
|
1121
|
-
linkParams.push(`first=${params.first}`);
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
if (this.isExpiredToken()) {
|
|
1127
|
-
await this.refreshToken();
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
link += "?" + linkParams.join("&");
|
|
1131
|
-
|
|
1132
|
-
const _ = await fetch(link, {
|
|
1133
|
-
method:"GET",
|
|
1134
|
-
headers:{
|
|
1135
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
1136
|
-
"Client-Id":this.clientId,
|
|
1137
|
-
},
|
|
1138
|
-
});
|
|
1139
|
-
|
|
1140
|
-
if (!_.ok) {
|
|
1141
|
-
return { ok:false, statusText:_.statusText };
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
const result = await _.json();
|
|
1145
|
-
return { ok:true, result:result.data };
|
|
1146
|
-
|
|
1147
|
-
}
|
|
1148
|
-
catch (error) {
|
|
1149
|
-
return { ok:false, error:error.stack };
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
}
|
|
1153
|
-
/**
|
|
1154
|
-
* 👀 **Renvoi des informations sur les catégories ou les jeux spécifiés.**
|
|
1155
|
-
* 💡 **Note** : Vous pouvez obtenir jusqu'à 100 catégories ou jeux en spécifiant leur identifiant ou leur nom. Vous pouvez spécifier tous les identifiants, tous les noms ou une combinaison d'identifiants et de noms. Si vous spécifiez une combinaison d'ID et de noms, le nombre total d'ID et de noms ne doit pas dépasser 100.
|
|
1156
|
-
*
|
|
1157
|
-
* ---
|
|
1158
|
-
* @param {Array<string>} gameNames Le nom de la catégorie ou du jeu à obtenir. Le nom doit correspondre exactement au titre de la catégorie ou du jeu. Incluez ce paramètre pour chaque catégorie ou jeu que vous souhaitez obtenir. Vous pouvez spécifier un maximum de 100 noms. Le point de terminaison ignore les noms en double et les noms introuvables.
|
|
1159
|
-
*
|
|
1160
|
-
* ---
|
|
1161
|
-
* @returns {Promise<{
|
|
1162
|
-
* ok:boolean,
|
|
1163
|
-
* statusText?:string,
|
|
1164
|
-
* error?:string,
|
|
1165
|
-
* result?:Array<{
|
|
1166
|
-
* id:string,
|
|
1167
|
-
* name:string,
|
|
1168
|
-
* box_art_url:string,
|
|
1169
|
-
* igdb_id:string
|
|
1170
|
-
* }>
|
|
1171
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
1172
|
-
*
|
|
1173
|
-
* • `ok` : État de la requête (true ou false)
|
|
1174
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
1175
|
-
* • `error?` : Erreur lors de la récupération des jeux
|
|
1176
|
-
* • `result?` La liste des catégories et des jeux. La liste est vide si les catégories et jeux spécifiés n’ont pas été trouvés.
|
|
1177
|
-
* > • `id` Un identifiant qui identifie la catégorie ou le jeu.
|
|
1178
|
-
* > • `name` Le nom de la catégorie ou du jeu.
|
|
1179
|
-
* > • `box_art_url` Une URL vers la pochette de la catégorie ou du jeu. Vous devez remplacer l'espace réservé {width}x{height} par la taille d'image souhaitée.
|
|
1180
|
-
* > • `igdb_id` L'ID que [IGDB](https://www.igdb.com) utilise pour identifier ce jeu. Si l'ID IGDB n'est pas disponible pour Twitch, ce champ est défini sur une chaîne vide.
|
|
1181
|
-
*
|
|
1182
|
-
* ---
|
|
1183
|
-
* @example
|
|
1184
|
-
client.getGames(["Fortnite"]).then(console.log);
|
|
1185
|
-
*/
|
|
1186
|
-
async getGames(gameNames) {
|
|
1187
|
-
|
|
1188
|
-
try {
|
|
1189
|
-
|
|
1190
|
-
const map = gameNames.join('&name=');
|
|
1191
|
-
const link = `https://api.twitch.tv/helix/games?name=${map}`;
|
|
1192
|
-
|
|
1193
|
-
if (this.isExpiredToken()) {
|
|
1194
|
-
await this.refreshToken();
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
const _ = await fetch(link, {
|
|
1198
|
-
method:"GET",
|
|
1199
|
-
headers:{
|
|
1200
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
1201
|
-
"Client-Id":this.clientId,
|
|
1202
|
-
},
|
|
1203
|
-
});
|
|
1204
|
-
|
|
1205
|
-
if (!_.ok) {
|
|
1206
|
-
return { ok:false, statusText:_.statusText };
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
const result = await _.json();
|
|
1210
|
-
return { ok:true, result:result.data };
|
|
1211
|
-
|
|
1212
|
-
}
|
|
1213
|
-
catch (error) {
|
|
1214
|
-
return { ok:false, error:error.stack };
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
}
|
|
1218
|
-
/**
|
|
1219
|
-
* 👀 **Obtient des informations sur une ou plusieurs vidéos publiées. Vous pouvez obtenir des vidéos par identifiant, par utilisateur ou par jeu/catégorie.**
|
|
1220
|
-
* 💡 **Note** : Vous pouvez appliquer plusieurs filtres pour obtenir un sous-ensemble de vidéos. Les filtres sont appliqués sous forme d’opération ET à chaque vidéo. Par exemple, si la langue est définie sur « de » et que game_id est défini sur 21779, la réponse inclut uniquement les vidéos montrant des utilisateurs jouant à League of Legends en allemand. Les filtres s'appliquent uniquement si vous obtenez des vidéos par ID utilisateur ou ID de jeu.
|
|
1221
|
-
*
|
|
1222
|
-
* ---
|
|
1223
|
-
* @param {string} username Le nom d'utilisateur de l'utilisateur dont vous souhaitez obtenir la liste des vidéos.
|
|
1224
|
-
*
|
|
1225
|
-
* ---
|
|
1226
|
-
* @param {{
|
|
1227
|
-
* game_name?:string,
|
|
1228
|
-
* language?:string,
|
|
1229
|
-
* period?:"all"|"day"|"month"|"week",
|
|
1230
|
-
* sort?:"time"|"trending"|"views",
|
|
1231
|
-
* type?:"all"|"archive"|"highlight"|"upload",
|
|
1232
|
-
* first?:number,
|
|
1233
|
-
* after?:string,
|
|
1234
|
-
* before?:string,
|
|
1235
|
-
* }} [params] **Paramètres de filtrage** :
|
|
1236
|
-
*
|
|
1237
|
-
* > • `game_name?` Un nom de catégorie ou de jeu. La réponse contient un maximum de 500 vidéos montrant ce contenu. Pour obtenir les noms de catégories/de jeux, utilisez le point de terminaison Rechercher des catégories.
|
|
1238
|
-
* > • `language?` Un filtre utilisé pour filtrer la liste des vidéos en fonction de la langue dans laquelle le propriétaire de la vidéo diffuse. Par exemple, pour obtenir des vidéos diffusées en allemand, définissez ce paramètre sur les deux lettres ISO 639-1. code pour l’allemand (c’est-à-dire DE). Pour obtenir la liste des langues prises en charge, consultez [Langues de flux prises en charge](https://help.twitch.tv/s/article/linguals-on-twitch?lingual=en_US#streamlang). Si la langue n’est pas prise en charge, utilisez « autre ». Spécifiez ce paramètre uniquement si vous spécifiez le paramètre de requête game_name.
|
|
1239
|
-
* > • `period?` Un filtre utilisé pour filtrer la liste des vidéos selon leur date de publication. Par exemple, les vidéos publiées la semaine dernière. La valeur par défaut est « tout », qui renvoie les vidéos publiées dans toutes les périodes.
|
|
1240
|
-
* > • `sort?` L'ordre dans lequel trier les vidéos renvoyées. La valeur par défaut est « heure ».
|
|
1241
|
-
* > • `type?` Un filtre utilisé pour filtrer la liste des vidéos par type de vidéo. La valeur par défaut est « all », qui renvoie tous les types de vidéo.
|
|
1242
|
-
* > • `first?` Le nombre maximum d'éléments à renvoyer par page dans la réponse. La taille minimale de la page est de 1 élément par page et la taille maximale est de 100. La valeur par défaut est de 20.
|
|
1243
|
-
* > • `after?` Le curseur utilisé pour obtenir la page suivante de résultats. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
1244
|
-
* > • `before?` Le curseur utilisé pour obtenir la page de résultats précédente. L'objet Pagination dans la réponse contient la valeur du curseur. [Lire la suite](https://dev.twitch.tv/docs/api/guide/#pagination)
|
|
1245
|
-
*
|
|
1246
|
-
* ---
|
|
1247
|
-
* @returns {Promise<{
|
|
1248
|
-
* ok:boolean,
|
|
1249
|
-
* statusText?:string,
|
|
1250
|
-
* error?:string,
|
|
1251
|
-
* result?:Array<{
|
|
1252
|
-
* id:string,
|
|
1253
|
-
* stream_id:string,
|
|
1254
|
-
* user_id:string,
|
|
1255
|
-
* user_login:string,
|
|
1256
|
-
* user_name:string,
|
|
1257
|
-
* title:string,
|
|
1258
|
-
* description:string,
|
|
1259
|
-
* created_at:string,
|
|
1260
|
-
* published_at:string,
|
|
1261
|
-
* utl:string,
|
|
1262
|
-
* thumbnail_url:string,
|
|
1263
|
-
* viewable:string,
|
|
1264
|
-
* view_count:number,
|
|
1265
|
-
* language:string,
|
|
1266
|
-
* type:"archive"|"highlight"|"upload",
|
|
1267
|
-
* duration:string,
|
|
1268
|
-
* muted_segments:Array<{
|
|
1269
|
-
* duration:number,
|
|
1270
|
-
* offset:number,
|
|
1271
|
-
* }>|null,
|
|
1272
|
-
* }>
|
|
1273
|
-
* }>} **Renvoi une promesse d'objet** :
|
|
1274
|
-
*
|
|
1275
|
-
* • `ok` : État de la requête (true ou false)
|
|
1276
|
-
* • `statusText?` : État de la requête (similaire à error)
|
|
1277
|
-
* • `error?` : Erreur lors de la récupération des vidéos
|
|
1278
|
-
* • `result?` La liste des vidéos publiées qui correspondent aux critères de filtre.
|
|
1279
|
-
* > • `id` Un identifiant qui identifie la vidéo.
|
|
1280
|
-
* > • `stream_id` L'ID du flux d'où provient la vidéo si le type de la vidéo est « archive » ; sinon, nul.
|
|
1281
|
-
* > • `user_id` L'ID du diffuseur propriétaire de la vidéo.
|
|
1282
|
-
* > • `user_login` Le nom de connexion du diffuseur.
|
|
1283
|
-
* > • `user_name` Le nom d'affichage du diffuseur.
|
|
1284
|
-
* > • `title` Le titre de la vidéo.
|
|
1285
|
-
* > • `description` La description de la vidéo.
|
|
1286
|
-
* > • `created_at` La date et l'heure, en UTC, de la création de la vidéo. L'horodatage est au format RFC3339.
|
|
1287
|
-
* > • `published_at` La date et l'heure, en UTC, de la publication de la vidéo. L'horodatage est au format RFC3339.
|
|
1288
|
-
* > • `url` L'URL de la vidéo.
|
|
1289
|
-
* > • `thumbnail_url` Une URL vers une image miniature de la vidéo. Avant d'utiliser l'URL, vous devez remplacer les espaces réservés %{width} et %{height} par la largeur et la hauteur de la vignette que vous souhaitez renvoyer. Spécifiez la largeur et la hauteur en pixels. Étant donné que le CDN conserve le rapport de la vignette, celle-ci peut ne pas avoir la taille exacte que vous avez demandée.
|
|
1290
|
-
* > • `visible` L'état visible de la vidéo. Toujours défini sur public.
|
|
1291
|
-
* > • `view_count` Le nombre de fois que les utilisateurs ont regardé la vidéo.
|
|
1292
|
-
* > • `langue` Le code de langue à deux lettres ISO 639-1 dans lequel la vidéo a été diffusée. Par exemple, le code de langue est DE si la vidéo a été diffusée en allemand. Pour obtenir la liste des langues prises en charge, consultez [Langues de flux prises en charge](https://help.twitch.tv/s/article/linguals-on-twitch?lingual=en_US#streamlang). La valeur de langue est « autre » si la vidéo a été diffusée dans une langue ne figurant pas dans la liste des langues prises en charge.
|
|
1293
|
-
* > • `type` Le type de la vidéo.
|
|
1294
|
-
* > • `durée` La durée de la vidéo au format de durée ISO 8601. Par exemple, 3 min 21 s représente 3 minutes 21 secondes.
|
|
1295
|
-
* > • `muted_segments` Les segments que la reconnaissance audio Twitch a désactivés ; sinon, nul.
|
|
1296
|
-
* > > • `duration` La durée du segment muet, en secondes.
|
|
1297
|
-
* > > • `offset` Le décalage, en secondes, depuis le début de la vidéo jusqu'à l'endroit où commence le segment coupé.
|
|
1298
|
-
*
|
|
1299
|
-
* ---
|
|
1300
|
-
* @example
|
|
1301
|
-
client.getVideos("twitchdev").then(console.log);
|
|
1302
|
-
*/
|
|
1303
|
-
async getVideos(username, params = {}) {
|
|
1304
|
-
|
|
1305
|
-
try {
|
|
1306
|
-
|
|
1307
|
-
const user = await this.getUsers([username]);
|
|
1308
|
-
|
|
1309
|
-
if (!user.ok) {
|
|
1310
|
-
return { ok:false, error:user.error ?? user.statusText };
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
const user_id = user.result[0]?.id;
|
|
1314
|
-
|
|
1315
|
-
let link = `https://api.twitch.tv/helix/videos?user_id=${user_id}`;
|
|
1316
|
-
const linkParams = [];
|
|
1317
|
-
|
|
1318
|
-
if (params) {
|
|
1319
|
-
|
|
1320
|
-
if (params.after) {
|
|
1321
|
-
linkParams.push(`after=${params.after}`);
|
|
1322
|
-
}
|
|
1323
|
-
if (params.before) {
|
|
1324
|
-
linkParams.push(`before=${params.before}`);
|
|
1325
|
-
}
|
|
1326
|
-
if (params.first) {
|
|
1327
|
-
linkParams.push(`first=${params.first}`);
|
|
1328
|
-
}
|
|
1329
|
-
if (params.game_name) {
|
|
1330
|
-
const game = await this.getGames([params.game_name]);
|
|
1331
|
-
if (!game.ok) {
|
|
1332
|
-
return { ok:false, error:game.error ?? game.statusText };
|
|
1333
|
-
}
|
|
1334
|
-
const id = game.result[0].id;
|
|
1335
|
-
linkParams.push(`game_id=${id}`);
|
|
1336
|
-
}
|
|
1337
|
-
if (params.language) {
|
|
1338
|
-
linkParams.push(`language=${params.language}`);
|
|
1339
|
-
}
|
|
1340
|
-
if (params.period) {
|
|
1341
|
-
linkParams.push(`period=${params.period}`);
|
|
1342
|
-
}
|
|
1343
|
-
if (params.sort) {
|
|
1344
|
-
linkParams.push(`sort=${params.sort}`);
|
|
1345
|
-
}
|
|
1346
|
-
if (params.type) {
|
|
1347
|
-
linkParams.push(`type=${params.type}`);
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
if (this.isExpiredToken()) {
|
|
1353
|
-
await this.refreshToken();
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
link += "?" + linkParams.join("&");
|
|
1357
|
-
|
|
1358
|
-
const _ = await fetch(link, {
|
|
1359
|
-
method:"GET",
|
|
1360
|
-
headers:{
|
|
1361
|
-
"Authorization":`${TwitchToken.token_type} ${TwitchToken.access_token}`,
|
|
1362
|
-
"Client-Id":this.clientId,
|
|
1363
|
-
},
|
|
1364
|
-
});
|
|
1365
|
-
|
|
1366
|
-
if (!_.ok) {
|
|
1367
|
-
return { ok:false, statusText:_.statusText };
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
const result = await _.json();
|
|
1371
|
-
return { ok:true, result:result.data };
|
|
1372
|
-
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
catch (error) {
|
|
1376
|
-
return { ok:false, error:error.stack };
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
};
|