@mkody/twitch-emoticons 2.7.0 → 2.8.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.
Files changed (45) hide show
  1. package/.eslintrc.json +143 -143
  2. package/.github/codeql/codeql-config.yml +4 -4
  3. package/.github/workflows/codeql.yml +50 -50
  4. package/.github/workflows/eslint.yml +50 -50
  5. package/.github/workflows/release.yml +22 -0
  6. package/.github/workflows/yarn-test.yml +17 -17
  7. package/.jsdoc.json +39 -39
  8. package/.nvmrc +1 -0
  9. package/LICENSE +22 -22
  10. package/README.md +36 -4
  11. package/docs/BTTVEmote.html +1641 -1319
  12. package/docs/Channel.html +823 -823
  13. package/docs/Collection.html +797 -797
  14. package/docs/Emote.html +906 -801
  15. package/docs/EmoteFetcher.html +3680 -2946
  16. package/docs/EmoteParser.html +811 -811
  17. package/docs/FFZEmote.html +1795 -1473
  18. package/docs/SevenTV.html +1190 -1190
  19. package/docs/SevenTVEmote.html +1705 -1395
  20. package/docs/TwitchEmote.html +1637 -1315
  21. package/docs/index.html +230 -206
  22. package/docs/struct_BTTVEmote.js.html +162 -132
  23. package/docs/struct_Channel.js.html +127 -127
  24. package/docs/struct_Emote.js.html +151 -138
  25. package/docs/struct_EmoteFetcher.js.html +427 -399
  26. package/docs/struct_EmoteParser.js.html +153 -153
  27. package/docs/struct_FFZEmote.js.html +185 -146
  28. package/docs/struct_SevenTVEmote.js.html +178 -141
  29. package/docs/struct_TwitchEmote.js.html +159 -130
  30. package/docs/util_Collection.js.html +150 -150
  31. package/package.json +57 -57
  32. package/src/index.js +12 -12
  33. package/src/struct/BTTVEmote.js +90 -60
  34. package/src/struct/Channel.js +55 -55
  35. package/src/struct/Emote.js +79 -66
  36. package/src/struct/EmoteFetcher.js +355 -327
  37. package/src/struct/EmoteParser.js +81 -81
  38. package/src/struct/EmoteTypeMapper.js +13 -0
  39. package/src/struct/FFZEmote.js +113 -74
  40. package/src/struct/SevenTVEmote.js +106 -69
  41. package/src/struct/TwitchEmote.js +87 -58
  42. package/src/util/Collection.js +78 -78
  43. package/src/util/Constants.js +31 -31
  44. package/test/index.js +482 -174
  45. package/typings/index.d.ts +115 -98
@@ -1,399 +1,427 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
-
5
- <meta charset="utf-8">
6
- <title>struct/EmoteFetcher.js - Documentation</title>
7
-
8
-
9
- <script src="scripts/prettify/prettify.js"></script>
10
- <script src="scripts/prettify/lang-css.js"></script>
11
- <!--[if lt IE 9]>
12
- <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13
- <![endif]-->
14
- <link type="text/css" rel="stylesheet" href="styles/prettify.css">
15
- <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
16
- <script src="scripts/nav.js" defer></script>
17
-
18
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
19
- </head>
20
- <body>
21
-
22
- <input type="checkbox" id="nav-trigger" class="nav-trigger" />
23
- <label for="nav-trigger" class="navicon-button x">
24
- <div class="navicon"></div>
25
- </label>
26
-
27
- <label for="nav-trigger" class="overlay"></label>
28
-
29
- <nav >
30
-
31
-
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="BTTVEmote.html">BTTVEmote</a><ul class='methods'><li data-type='method'><a href="BTTVEmote.html#toLink">toLink</a></li><li data-type='method'><a href="BTTVEmote.html#toString">toString</a></li></ul></li><li><a href="Channel.html">Channel</a><ul class='methods'><li data-type='method'><a href="Channel.html#fetchBTTVEmotes">fetchBTTVEmotes</a></li><li data-type='method'><a href="Channel.html#fetchFFZEmotes">fetchFFZEmotes</a></li><li data-type='method'><a href="Channel.html#fetchSevenTVEmotes">fetchSevenTVEmotes</a></li></ul></li><li><a href="Collection.html">Collection</a><ul class='methods'><li data-type='method'><a href="Collection.html#filter">filter</a></li><li data-type='method'><a href="Collection.html#find">find</a></li><li data-type='method'><a href="Collection.html#map">map</a></li></ul></li><li><a href="Emote.html">Emote</a><ul class='methods'><li data-type='method'><a href="Emote.html#toString">toString</a></li></ul></li><li><a href="EmoteFetcher.html">EmoteFetcher</a><ul class='methods'><li data-type='method'><a href="EmoteFetcher.html#_cacheBTTVEmote">_cacheBTTVEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_cacheFFZEmote">_cacheFFZEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_cacheSevenTVEmote">_cacheSevenTVEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_cacheTwitchEmote">_cacheTwitchEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawBTTVEmotes">_getRawBTTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawFFZEmoteSet">_getRawFFZEmoteSet</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawFFZEmotes">_getRawFFZEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawSevenTVEmotes">_getRawSevenTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawTwitchEmotes">_getRawTwitchEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchBTTVEmotes">fetchBTTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchFFZEmotes">fetchFFZEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchSevenTVEmotes">fetchSevenTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchTwitchEmotes">fetchTwitchEmotes</a></li></ul></li><li><a href="EmoteParser.html">EmoteParser</a><ul class='methods'><li data-type='method'><a href="EmoteParser.html#parse">parse</a></li></ul></li><li><a href="FFZEmote.html">FFZEmote</a><ul class='methods'><li data-type='method'><a href="FFZEmote.html#toLink">toLink</a></li><li data-type='method'><a href="FFZEmote.html#toString">toString</a></li></ul></li><li><a href="SevenTVEmote.html">SevenTVEmote</a><ul class='methods'><li data-type='method'><a href="SevenTVEmote.html#toLink">toLink</a></li><li data-type='method'><a href="SevenTVEmote.html#toString">toString</a></li></ul></li><li><a href="TwitchEmote.html">TwitchEmote</a><ul class='methods'><li data-type='method'><a href="TwitchEmote.html#toLink">toLink</a></li><li data-type='method'><a href="TwitchEmote.html#toString">toString</a></li></ul></li></ul>
33
-
34
- </nav>
35
-
36
- <div id="main">
37
-
38
- <h1 class="page-title">struct/EmoteFetcher.js</h1>
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
- <section>
47
- <article>
48
- <pre class="prettyprint source linenums"><code>const BTTVEmote = require('./BTTVEmote');
49
- const Channel = require('./Channel');
50
- const Collection = require('../util/Collection');
51
- const Constants = require('../util/Constants');
52
- const FFZEmote = require('./FFZEmote');
53
- const SevenTVEmote = require('./SevenTVEmote');
54
-
55
- const got = require('got');
56
- const TwitchEmote = require('./TwitchEmote');
57
- const { ApiClient } = require('@twurple/api');
58
- const { AppTokenAuthProvider } = require('@twurple/auth');
59
-
60
- const options = {
61
- responseType: 'json'
62
- };
63
-
64
- class EmoteFetcher {
65
- /**
66
- * Fetches and caches emotes.
67
- * @param {string} clientId The client id for the twitch api.
68
- * @param {string} clientSecret The client secret for the twitch api.
69
- */
70
- constructor(clientId, clientSecret) {
71
- if (clientId !== undefined &amp;&amp; clientSecret !== undefined) {
72
- const authProvider = new AppTokenAuthProvider(clientId, clientSecret);
73
-
74
- /**
75
- * Twitch api client.
76
- */
77
- this.apiClient = new ApiClient({ authProvider });
78
- }
79
-
80
- /**
81
- * Cached emotes.
82
- * Collectionped by emote code to Emote instance.
83
- * @type {Collection&lt;string, Emote>}
84
- */
85
- this.emotes = new Collection();
86
-
87
- /**
88
- * Cached channels.
89
- * Collectionped by name to Channel instance.
90
- * @type {Collection&lt;string, Channel>}
91
- */
92
- this.channels = new Collection();
93
-
94
- /**
95
- * Save if we fetched FFZ's modifier emotes once.
96
- * @type {boolean}
97
- */
98
- this.ffzModifiersFetched = false;
99
- }
100
-
101
- /**
102
- * The global channel for Twitch, BTTV and 7TV.
103
- * @readonly
104
- * @type {?Channel}
105
- */
106
- get globalChannel() {
107
- return this.channels.get(null);
108
- }
109
-
110
- /**
111
- * Gets the raw Twitch emotes data for a channel.
112
- * @private
113
- * @param {int} id - ID of the channel.
114
- * @returns {Promise&lt;Object[]>}
115
- */
116
- _getRawTwitchEmotes(id) {
117
- if (!this.apiClient) {
118
- throw new Error('Client id or client secret not provided.');
119
- }
120
-
121
- if (id) {
122
- return this.apiClient.chat.getChannelEmotes(id);
123
- } else {
124
- return this.apiClient.chat.getGlobalEmotes();
125
- }
126
- }
127
-
128
- /**
129
- * Converts and caches a raw twitch emote.
130
- * @private
131
- * @param {int} channel_id - ID of the channel.
132
- * @param {Object} data - Raw data.
133
- * @returns {TwitchEmote}
134
- */
135
- _cacheTwitchEmote(channel_id, data) {
136
- let channel = this.channels.get(channel_id);
137
- if (!channel) {
138
- channel = new Channel(this, channel_id);
139
- this.channels.set(channel_id, channel);
140
- }
141
-
142
- const emote = new TwitchEmote(channel, data.id, data);
143
- this.emotes.set(emote.code, emote);
144
- channel.emotes.set(emote.code, emote);
145
- return emote;
146
- }
147
-
148
- /**
149
- * Gets the raw BTTV emotes data for a channel.
150
- * Use `null` for the global emotes channel.
151
- * @private
152
- * @param {int} [id=null] - ID of the channel.
153
- * @returns {Promise&lt;Object[]>}
154
- */
155
- _getRawBTTVEmotes(id) {
156
- const endpoint = !id
157
- ? Constants.BTTV.Global
158
- : Constants.BTTV.Channel(id); // eslint-disable-line new-cap
159
-
160
- return got(endpoint, options).then(req => {
161
- // Global emotes
162
- if (req.body instanceof Array) return req.body;
163
- // Channel emotes
164
- return [...req.body.channelEmotes, ...req.body.sharedEmotes];
165
- });
166
- }
167
-
168
- /**
169
- * Converts and caches a raw BTTV emote.
170
- * @private
171
- * @param {int} channel_id - ID of the channel.
172
- * @param {Object} data - Raw data.
173
- * @returns {BTTVEmote}
174
- */
175
- _cacheBTTVEmote(channel_id, data) {
176
- let channel = this.channels.get(channel_id);
177
- if (!channel) {
178
- channel = new Channel(this, channel_id);
179
- this.channels.set(channel_id, channel);
180
- }
181
-
182
- const emote = new BTTVEmote(channel, data.id, data);
183
- this.emotes.set(emote.code, emote);
184
- channel.emotes.set(emote.code, emote);
185
- return emote;
186
- }
187
-
188
- /**
189
- * Gets the raw FFZ emote data from a set.
190
- * @private
191
- * @param {int} id - ID of the set.
192
- * @returns {Promise&lt;Object[]>}
193
- */
194
- _getRawFFZEmoteSet(id) {
195
- const endpoint = Constants.FFZ.Set(id); // eslint-disable-line new-cap
196
-
197
- return got(endpoint, options).then(req => {
198
- return req.body.set.emoticons;
199
- });
200
- }
201
-
202
- /**
203
- * Gets the raw FFZ emotes data for a channel.
204
- * @private
205
- * @param {int} id - ID of the channel.
206
- * @returns {Promise&lt;Object[]>}
207
- */
208
- _getRawFFZEmotes(id) {
209
- const endpoint = Constants.FFZ.Channel(id); // eslint-disable-line new-cap
210
-
211
- return got(endpoint, options).then(req => {
212
- const emotes = [];
213
- for (const key of Object.keys(req.body.sets)) {
214
- const set = req.body.sets[key];
215
- emotes.push(...set.emoticons);
216
- }
217
-
218
- return emotes;
219
- });
220
- }
221
-
222
- /**
223
- * Converts and caches a raw FFZ emote.
224
- * @private
225
- * @param {int} channel_id - ID of the channel.
226
- * @param {Object} data - Raw data.
227
- * @returns {FFZEmote}
228
- */
229
- _cacheFFZEmote(channel_id, data) {
230
- let channel = this.channels.get(channel_id);
231
- if (!channel) {
232
- channel = new Channel(this, channel_id);
233
- this.channels.set(channel_id, channel);
234
- }
235
-
236
- const emote = new FFZEmote(channel, data.id, data);
237
- this.emotes.set(emote.code, emote);
238
- channel.emotes.set(emote.code, emote);
239
- return emote;
240
- }
241
-
242
- /**
243
- * Gets the raw 7TV emotes data for a channel.
244
- * @private
245
- * @param {int} [id=null] - ID of the channel.
246
- * @returns {Promise&lt;Object[]>}
247
- */
248
- _getRawSevenTVEmotes(id) {
249
- const endpoint = !id
250
- ? Constants.SevenTV.Global
251
- : Constants.SevenTV.Channel(id); // eslint-disable-line new-cap
252
-
253
- return got(endpoint, options).then(req => req.body);
254
- }
255
-
256
- /**
257
- * Converts and caches a raw 7TV emote.
258
- * @private
259
- * @param {int} channel_id - ID of the channel.
260
- * @param {Object} data - Raw data.
261
- * @param {string} format - The type file format to use (webp/avif).
262
- * @returns {SevenTVEmote}
263
- */
264
- _cacheSevenTVEmote(channel_id, data, format) {
265
- let channel = this.channels.get(channel_id);
266
- if (!channel) {
267
- channel = new Channel(this, channel_id);
268
- this.channels.set(channel_id, channel);
269
- }
270
- channel.format = format;
271
-
272
- const emote = new SevenTVEmote(channel, data.id, data);
273
- this.emotes.set(emote.code, emote);
274
- channel.emotes.set(emote.code, emote);
275
- return emote;
276
- }
277
-
278
- /**
279
- * Fetches the Twitch emotes for a channel.
280
- * Use `null` for the global emotes channel.
281
- * @param {int} [channel=null] - ID of the channel.
282
- * @returns {Promise&lt;Collection&lt;string, TwitchEmote>>}
283
- */
284
- fetchTwitchEmotes(channel = null) {
285
- return this._getRawTwitchEmotes(channel).then(rawEmotes => {
286
- for (const emote of rawEmotes) {
287
- this._cacheTwitchEmote(channel, {
288
- code: emote.name, id: emote.id, formats: emote.formats
289
- });
290
- }
291
-
292
- return this.channels.get(channel).emotes.filter(e => e.type === 'twitch');
293
- });
294
- }
295
-
296
- /**
297
- * Fetches the BTTV emotes for a channel.
298
- * Use `null` for the global emotes channel.
299
- * @param {int} [channel=null] - ID of the channel.
300
- * @returns {Promise&lt;Collection&lt;string, BTTVEmote>>}
301
- */
302
- fetchBTTVEmotes(channel = null) {
303
- return this._getRawBTTVEmotes(channel).then(rawEmotes => {
304
- for (const data of rawEmotes) {
305
- this._cacheBTTVEmote(channel, data);
306
- }
307
-
308
- return this.channels.get(channel).emotes.filter(e => e.type === 'bttv');
309
- });
310
- }
311
-
312
- /**
313
- * Fetches the FFZ emotes for a channel.
314
- * @param {int} [channel=null] - ID of the channel.
315
- * @returns {Promise&lt;Collection&lt;string, FFZEmote>>}
316
- */
317
- async fetchFFZEmotes(channel) {
318
- // Fetch modifier emotes at least once
319
- if (!this.ffzModifiersFetched) {
320
- this.ffzModifiersFetched = true;
321
-
322
- await this._getRawFFZEmoteSet(Constants.FFZ.sets.Modifiers).then(rawEmotes => {
323
- for (const data of rawEmotes) {
324
- this._cacheFFZEmote(null, data);
325
- }
326
- });
327
- }
328
-
329
- // If no channel specified, fetch the Global set
330
- if (!channel) {
331
- return this._getRawFFZEmoteSet(Constants.FFZ.sets.Global).then(rawEmotes => {
332
- for (const data of rawEmotes) {
333
- this._cacheFFZEmote(channel, data);
334
- }
335
-
336
- return this.channels.get(channel).emotes.filter(e => e.type === 'ffz');
337
- });
338
- }
339
-
340
- return this._getRawFFZEmotes(channel).then(rawEmotes => {
341
- for (const data of rawEmotes) {
342
- this._cacheFFZEmote(channel, data);
343
- }
344
-
345
- return this.channels.get(channel).emotes.filter(e => e.type === 'ffz');
346
- });
347
- }
348
-
349
- /**
350
- * Fetches the 7TV emotes for a channel.
351
- * @param {int} [channel=null] - ID of the channel.
352
- * @param {('webp'|'avif')} [format='webp'] - The type file format to use (webp/avif).
353
- * @returns {Promise&lt;Collection&lt;string, SevenTVEmote>>}
354
- */
355
- fetchSevenTVEmotes(channel = null, format = 'webp') {
356
- return this._getRawSevenTVEmotes(channel).then(rawEmotes => {
357
- if ('emotes' in rawEmotes) {
358
- // From an emote set (like "global")
359
- for (const data of rawEmotes.emotes) {
360
- this._cacheSevenTVEmote(channel, data.data, format);
361
- }
362
- } else {
363
- // From users
364
- for (const data of rawEmotes.emote_set.emotes) {
365
- this._cacheSevenTVEmote(channel, data.data, format);
366
- }
367
- }
368
-
369
- return this.channels.get(channel).emotes.filter(e => e.type === '7tv');
370
- });
371
- }
372
- }
373
-
374
- module.exports = EmoteFetcher;
375
- </code></pre>
376
- </article>
377
- </section>
378
-
379
-
380
-
381
-
382
-
383
-
384
- </div>
385
-
386
- <br class="clear">
387
-
388
- <footer>
389
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
390
- </footer>
391
-
392
- <script>prettyPrint();</script>
393
- <script src="scripts/polyfill.js"></script>
394
- <script src="scripts/linenumber.js"></script>
395
-
396
-
397
-
398
- </body>
399
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+
5
+ <meta charset="utf-8">
6
+ <title>struct/EmoteFetcher.js - Documentation</title>
7
+
8
+
9
+ <script src="scripts/prettify/prettify.js"></script>
10
+ <script src="scripts/prettify/lang-css.js"></script>
11
+ <!--[if lt IE 9]>
12
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13
+ <![endif]-->
14
+ <link type="text/css" rel="stylesheet" href="styles/prettify.css">
15
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
16
+ <script src="scripts/nav.js" defer></script>
17
+
18
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
19
+ </head>
20
+ <body>
21
+
22
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
23
+ <label for="nav-trigger" class="navicon-button x">
24
+ <div class="navicon"></div>
25
+ </label>
26
+
27
+ <label for="nav-trigger" class="overlay"></label>
28
+
29
+ <nav >
30
+
31
+
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="BTTVEmote.html">BTTVEmote</a><ul class='methods'><li data-type='method'><a href="BTTVEmote.html#toLink">toLink</a></li><li data-type='method'><a href="BTTVEmote.html#toObject">toObject</a></li><li data-type='method'><a href="BTTVEmote.html#toString">toString</a></li><li data-type='method'><a href="BTTVEmote.html#.fromObject">fromObject</a></li></ul></li><li><a href="Channel.html">Channel</a><ul class='methods'><li data-type='method'><a href="Channel.html#fetchBTTVEmotes">fetchBTTVEmotes</a></li><li data-type='method'><a href="Channel.html#fetchFFZEmotes">fetchFFZEmotes</a></li><li data-type='method'><a href="Channel.html#fetchSevenTVEmotes">fetchSevenTVEmotes</a></li></ul></li><li><a href="Collection.html">Collection</a><ul class='methods'><li data-type='method'><a href="Collection.html#filter">filter</a></li><li data-type='method'><a href="Collection.html#find">find</a></li><li data-type='method'><a href="Collection.html#map">map</a></li></ul></li><li><a href="Emote.html">Emote</a><ul class='methods'><li data-type='method'><a href="Emote.html#toObject">toObject</a></li><li data-type='method'><a href="Emote.html#toString">toString</a></li></ul></li><li><a href="EmoteFetcher.html">EmoteFetcher</a><ul class='methods'><li data-type='method'><a href="EmoteFetcher.html#_cacheBTTVEmote">_cacheBTTVEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_cacheFFZEmote">_cacheFFZEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_cacheSevenTVEmote">_cacheSevenTVEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_cacheTwitchEmote">_cacheTwitchEmote</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawBTTVEmotes">_getRawBTTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawFFZEmoteSet">_getRawFFZEmoteSet</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawFFZEmotes">_getRawFFZEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawSevenTVEmotes">_getRawSevenTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#_getRawTwitchEmotes">_getRawTwitchEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#_setupChannel">_setupChannel</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchBTTVEmotes">fetchBTTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchFFZEmotes">fetchFFZEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchSevenTVEmotes">fetchSevenTVEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fetchTwitchEmotes">fetchTwitchEmotes</a></li><li data-type='method'><a href="EmoteFetcher.html#fromObject">fromObject</a></li></ul></li><li><a href="EmoteParser.html">EmoteParser</a><ul class='methods'><li data-type='method'><a href="EmoteParser.html#parse">parse</a></li></ul></li><li><a href="FFZEmote.html">FFZEmote</a><ul class='methods'><li data-type='method'><a href="FFZEmote.html#toLink">toLink</a></li><li data-type='method'><a href="FFZEmote.html#toObject">toObject</a></li><li data-type='method'><a href="FFZEmote.html#toString">toString</a></li><li data-type='method'><a href="FFZEmote.html#.fromObject">fromObject</a></li></ul></li><li><a href="SevenTVEmote.html">SevenTVEmote</a><ul class='methods'><li data-type='method'><a href="SevenTVEmote.html#toLink">toLink</a></li><li data-type='method'><a href="SevenTVEmote.html#toObject">toObject</a></li><li data-type='method'><a href="SevenTVEmote.html#toString">toString</a></li><li data-type='method'><a href="SevenTVEmote.html#.fromObject">fromObject</a></li></ul></li><li><a href="TwitchEmote.html">TwitchEmote</a><ul class='methods'><li data-type='method'><a href="TwitchEmote.html#toLink">toLink</a></li><li data-type='method'><a href="TwitchEmote.html#toObject">toObject</a></li><li data-type='method'><a href="TwitchEmote.html#toString">toString</a></li><li data-type='method'><a href="TwitchEmote.html#.fromObject">fromObject</a></li></ul></li></ul>
33
+
34
+ </nav>
35
+
36
+ <div id="main">
37
+
38
+ <h1 class="page-title">struct/EmoteFetcher.js</h1>
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+ <section>
47
+ <article>
48
+ <pre class="prettyprint source linenums"><code>const BTTVEmote = require('./BTTVEmote');
49
+ const Channel = require('./Channel');
50
+ const Collection = require('../util/Collection');
51
+ const Constants = require('../util/Constants');
52
+ const FFZEmote = require('./FFZEmote');
53
+ const SevenTVEmote = require('./SevenTVEmote');
54
+ const TwitchEmote = require('./TwitchEmote');
55
+
56
+ const axios = require('axios');
57
+ const { ApiClient } = require('@twurple/api');
58
+ const { AppTokenAuthProvider } = require('@twurple/auth');
59
+
60
+ class EmoteFetcher {
61
+ /**
62
+ * Fetches and caches emotes.
63
+ * @param {string} clientId The client id for the twitch api.
64
+ * @param {string} clientSecret The client secret for the twitch api.
65
+ * @param {Object} options Additional options.
66
+ * @param {ApiClient} options.apiClient - Bring your own Twurple ApiClient.
67
+ */
68
+ constructor(clientId, clientSecret, options) {
69
+ if (options &amp;&amp; options.apiClient) {
70
+ this.apiClient = options.apiClient;
71
+ } else if (clientId !== undefined &amp;&amp; clientSecret !== undefined) {
72
+ const authProvider = new AppTokenAuthProvider(clientId, clientSecret);
73
+
74
+ /**
75
+ * Twitch api client.
76
+ */
77
+ this.apiClient = new ApiClient({ authProvider });
78
+ }
79
+
80
+ /**
81
+ * Cached emotes.
82
+ * Collectionped by emote code to Emote instance.
83
+ * @type {Collection&lt;string, Emote>}
84
+ */
85
+ this.emotes = new Collection();
86
+
87
+ /**
88
+ * Cached channels.
89
+ * Collectionped by name to Channel instance.
90
+ * @type {Collection&lt;string, Channel>}
91
+ */
92
+ this.channels = new Collection();
93
+
94
+ /**
95
+ * Save if we fetched FFZ's modifier emotes once.
96
+ * @type {boolean}
97
+ */
98
+ this.ffzModifiersFetched = false;
99
+ }
100
+
101
+ /**
102
+ * The global channel for Twitch, BTTV and 7TV.
103
+ * @readonly
104
+ * @type {?Channel}
105
+ */
106
+ get globalChannel() {
107
+ return this.channels.get(null);
108
+ }
109
+
110
+ /**
111
+ * Sets up a channel
112
+ * @private
113
+ * @param {int} channel_id - ID of the channel.
114
+ * @param {string} [format=null] - The type file format to use (webp/avif).
115
+ * @returns {Channel}
116
+ */
117
+ _setupChannel(channel_id, format = null) {
118
+ let channel = this.channels.get(channel_id);
119
+ if (!channel) {
120
+ channel = new Channel(this, channel_id);
121
+ this.channels.set(channel_id, channel);
122
+ }
123
+ if (format) channel.format = format;
124
+ return channel;
125
+ }
126
+
127
+ /**
128
+ * Gets the raw Twitch emotes data for a channel.
129
+ * @private
130
+ * @param {int} id - ID of the channel.
131
+ * @returns {Promise&lt;Object[]>}
132
+ */
133
+ _getRawTwitchEmotes(id) {
134
+ if (!this.apiClient) {
135
+ throw new Error('Client id or client secret not provided.');
136
+ }
137
+
138
+ if (id) {
139
+ return this.apiClient.chat.getChannelEmotes(id);
140
+ } else {
141
+ return this.apiClient.chat.getGlobalEmotes();
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Converts and caches a raw twitch emote.
147
+ * @private
148
+ * @param {int} channel_id - ID of the channel.
149
+ * @param {Object} data - Raw data.
150
+ * @param {TwitchEmote} [existing_emote=null] - Existing emote to cache.
151
+ * @returns {TwitchEmote}
152
+ */
153
+ _cacheTwitchEmote(channel_id, data, existing_emote = null) {
154
+ const channel = this._setupChannel(channel_id);
155
+ const emote = existing_emote || new TwitchEmote(channel, data.id, data);
156
+ this.emotes.set(emote.code, emote);
157
+ channel.emotes.set(emote.code, emote);
158
+ return emote;
159
+ }
160
+
161
+ /**
162
+ * Gets the raw BTTV emotes data for a channel.
163
+ * Use `null` for the global emotes channel.
164
+ * @private
165
+ * @param {int} [id=null] - ID of the channel.
166
+ * @returns {Promise&lt;Object[]>}
167
+ */
168
+ _getRawBTTVEmotes(id) {
169
+ const endpoint = !id
170
+ ? Constants.BTTV.Global
171
+ : Constants.BTTV.Channel(id); // eslint-disable-line new-cap
172
+
173
+ return axios.get(endpoint).then(req => {
174
+ // Global emotes
175
+ if (req.data instanceof Array) return req.data;
176
+ // Channel emotes
177
+ return [...req.data.channelEmotes, ...req.data.sharedEmotes];
178
+ });
179
+ }
180
+
181
+ /**
182
+ * Converts and caches a raw BTTV emote.
183
+ * @private
184
+ * @param {int} channel_id - ID of the channel.
185
+ * @param {Object} data - Raw data.
186
+ * @param {BTTVEmote} [existing_emote=null] - Existing emote to cache.
187
+ * @returns {BTTVEmote}
188
+ */
189
+ _cacheBTTVEmote(channel_id, data, existing_emote = null) {
190
+ const channel = this._setupChannel(channel_id);
191
+ const emote = existing_emote || new BTTVEmote(channel, data.id, data);
192
+ this.emotes.set(emote.code, emote);
193
+ channel.emotes.set(emote.code, emote);
194
+ return emote;
195
+ }
196
+
197
+ /**
198
+ * Gets the raw FFZ emote data from a set.
199
+ * @private
200
+ * @param {int} id - ID of the set.
201
+ * @returns {Promise&lt;Object[]>}
202
+ */
203
+ _getRawFFZEmoteSet(id) {
204
+ const endpoint = Constants.FFZ.Set(id); // eslint-disable-line new-cap
205
+
206
+ return axios.get(endpoint).then(req => {
207
+ return req.data.set.emoticons;
208
+ });
209
+ }
210
+
211
+ /**
212
+ * Gets the raw FFZ emotes data for a channel.
213
+ * @private
214
+ * @param {int} id - ID of the channel.
215
+ * @returns {Promise&lt;Object[]>}
216
+ */
217
+ _getRawFFZEmotes(id) {
218
+ const endpoint = Constants.FFZ.Channel(id); // eslint-disable-line new-cap
219
+
220
+ return axios.get(endpoint).then(req => {
221
+ const emotes = [];
222
+ for (const key of Object.keys(req.data.sets)) {
223
+ const set = req.data.sets[key];
224
+ emotes.push(...set.emoticons);
225
+ }
226
+
227
+ return emotes;
228
+ });
229
+ }
230
+
231
+ /**
232
+ * Converts and caches a raw FFZ emote.
233
+ * @private
234
+ * @param {int} channel_id - ID of the channel.
235
+ * @param {Object} data - Raw data.
236
+ * @param {FFZEmote} [existing_emote=null] - Existing emote to cache.
237
+ * @returns {FFZEmote}
238
+ */
239
+ _cacheFFZEmote(channel_id, data, existing_emote = null) {
240
+ const channel = this._setupChannel(channel_id);
241
+ const emote = existing_emote || new FFZEmote(channel, data.id, data);
242
+ this.emotes.set(emote.code, emote);
243
+ channel.emotes.set(emote.code, emote);
244
+ return emote;
245
+ }
246
+
247
+ /**
248
+ * Gets the raw 7TV emotes data for a channel.
249
+ * @private
250
+ * @param {int} [id=null] - ID of the channel.
251
+ * @returns {Promise&lt;Object[]>}
252
+ */
253
+ _getRawSevenTVEmotes(id) {
254
+ const endpoint = !id
255
+ ? Constants.SevenTV.Global
256
+ : Constants.SevenTV.Channel(id); // eslint-disable-line new-cap
257
+
258
+ return axios.get(endpoint).then(req => req.data);
259
+ }
260
+
261
+ /**
262
+ * Converts and caches a raw 7TV emote.
263
+ * @private
264
+ * @param {int} channel_id - ID of the channel.
265
+ * @param {Object} data - Raw data.
266
+ * @param {string} format - The type file format to use (webp/avif).
267
+ * @param {SevenTVEmote} [existing_emote=null] - Existing emote to cache.
268
+ * @returns {SevenTVEmote}
269
+ */
270
+ _cacheSevenTVEmote(channel_id, data, format, existing_emote = null) {
271
+ const channel = this._setupChannel(channel_id, format);
272
+ const emote = existing_emote || new SevenTVEmote(channel, data.id, data);
273
+ this.emotes.set(emote.code, emote);
274
+ channel.emotes.set(emote.code, emote);
275
+ return emote;
276
+ }
277
+
278
+ /**
279
+ * Fetches the Twitch emotes for a channel.
280
+ * Use `null` for the global emotes channel.
281
+ * @param {int} [channel=null] - ID of the channel.
282
+ * @returns {Promise&lt;Collection&lt;string, TwitchEmote>>}
283
+ */
284
+ fetchTwitchEmotes(channel = null) {
285
+ return this._getRawTwitchEmotes(channel).then(rawEmotes => {
286
+ for (const emote of rawEmotes) {
287
+ this._cacheTwitchEmote(channel, {
288
+ code: emote.name, id: emote.id, formats: emote.formats
289
+ });
290
+ }
291
+
292
+ return this.channels.get(channel).emotes.filter(e => e.type === 'twitch');
293
+ });
294
+ }
295
+
296
+ /**
297
+ * Fetches the BTTV emotes for a channel.
298
+ * Use `null` for the global emotes channel.
299
+ * @param {int} [channel=null] - ID of the channel.
300
+ * @returns {Promise&lt;Collection&lt;string, BTTVEmote>>}
301
+ */
302
+ fetchBTTVEmotes(channel = null) {
303
+ return this._getRawBTTVEmotes(channel).then(rawEmotes => {
304
+ for (const data of rawEmotes) {
305
+ this._cacheBTTVEmote(channel, data);
306
+ }
307
+
308
+ return this.channels.get(channel).emotes.filter(e => e.type === 'bttv');
309
+ });
310
+ }
311
+
312
+ /**
313
+ * Fetches the FFZ emotes for a channel.
314
+ * @param {int} [channel=null] - ID of the channel.
315
+ * @returns {Promise&lt;Collection&lt;string, FFZEmote>>}
316
+ */
317
+ async fetchFFZEmotes(channel) {
318
+ // Fetch modifier emotes at least once
319
+ if (!this.ffzModifiersFetched) {
320
+ this.ffzModifiersFetched = true;
321
+
322
+ await this._getRawFFZEmoteSet(Constants.FFZ.sets.Modifiers).then(rawEmotes => {
323
+ for (const data of rawEmotes) {
324
+ this._cacheFFZEmote(null, data);
325
+ }
326
+ });
327
+ }
328
+
329
+ // If no channel specified, fetch the Global set
330
+ if (!channel) {
331
+ return this._getRawFFZEmoteSet(Constants.FFZ.sets.Global).then(rawEmotes => {
332
+ for (const data of rawEmotes) {
333
+ this._cacheFFZEmote(channel, data);
334
+ }
335
+
336
+ return this.channels.get(channel).emotes.filter(e => e.type === 'ffz');
337
+ });
338
+ }
339
+
340
+ return this._getRawFFZEmotes(channel).then(rawEmotes => {
341
+ for (const data of rawEmotes) {
342
+ this._cacheFFZEmote(channel, data);
343
+ }
344
+
345
+ return this.channels.get(channel).emotes.filter(e => e.type === 'ffz');
346
+ });
347
+ }
348
+
349
+ /**
350
+ * Fetches the 7TV emotes for a channel.
351
+ * @param {int} [channel=null] - ID of the channel.
352
+ * @param {('webp'|'avif')} [format='webp'] - The type file format to use (webp/avif).
353
+ * @returns {Promise&lt;Collection&lt;string, SevenTVEmote>>}
354
+ */
355
+ fetchSevenTVEmotes(channel = null, format = 'webp') {
356
+ return this._getRawSevenTVEmotes(channel).then(rawEmotes => {
357
+ if ('emotes' in rawEmotes) {
358
+ // From an emote set (like "global")
359
+ for (const data of rawEmotes.emotes) {
360
+ this._cacheSevenTVEmote(channel, data.data, format);
361
+ }
362
+ } else {
363
+ // From users
364
+ for (const data of rawEmotes.emote_set.emotes) {
365
+ this._cacheSevenTVEmote(channel, data.data, format);
366
+ }
367
+ }
368
+
369
+ return this.channels.get(channel).emotes.filter(e => e.type === '7tv');
370
+ });
371
+ }
372
+
373
+ /**
374
+ * Converts emote Objects to emotes
375
+ * @param {Object} [json] - Emote Object
376
+ * @returns {Emote[]}
377
+ */
378
+ fromObject(json) {
379
+ const emotes = [];
380
+ const classMap = {
381
+ bttv: { class: BTTVEmote, cache: (emoteObject, channel_id, existing_emote) => this._cacheBTTVEmote(channel_id, null, existing_emote) },
382
+ ffz: { class: FFZEmote, cache: (emoteObject, channel_id, existing_emote) => this._cacheFFZEmote(channel_id, null, existing_emote) },
383
+ '7tv': { class: SevenTVEmote, cache: (emoteObject, channel_id, existing_emote) => this._cacheSevenTVEmote(channel_id, null, emoteObject.imageType, existing_emote) },
384
+ twitch: { class: TwitchEmote, cache: (emoteObject, channel_id, existing_emote) => this._cacheTwitchEmote(channel_id, null, existing_emote) }
385
+ };
386
+ for (const emoteObject of json) {
387
+ const { type } = emoteObject;
388
+ if (!Object.keys(classMap).includes(type)) {
389
+ throw new TypeError(`Unknown type: ${type}`);
390
+ }
391
+
392
+ const emoteClass = classMap[type].class;
393
+ this._setupChannel(emoteObject.channel_id, type === '7tv' ? emoteObject.imageType : null);
394
+ const emote = emoteClass.fromObject(emoteObject, this.channels.get(emoteObject.channel_id));
395
+ classMap[type].cache(emoteObject, emoteObject.channel_id, emote);
396
+ emotes.push(emote);
397
+ }
398
+ return emotes;
399
+ }
400
+ }
401
+
402
+ module.exports = EmoteFetcher;
403
+ </code></pre>
404
+ </article>
405
+ </section>
406
+
407
+
408
+
409
+
410
+
411
+
412
+ </div>
413
+
414
+ <br class="clear">
415
+
416
+ <footer>
417
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
418
+ </footer>
419
+
420
+ <script>prettyPrint();</script>
421
+ <script src="scripts/polyfill.js"></script>
422
+ <script src="scripts/linenumber.js"></script>
423
+
424
+
425
+
426
+ </body>
427
+ </html>