@mkody/twitch-emoticons 2.9.6 → 3.0.0-beta.2
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/README.md +530 -169
- package/dist/TwitchEmoticons.cjs +950 -0
- package/dist/TwitchEmoticons.esm.min.js +7 -0
- package/dist/TwitchEmoticons.esm.min.js.map +7 -0
- package/dist/TwitchEmoticons.min.js +2 -20
- package/dist/TwitchEmoticons.min.js.map +4 -4
- package/package.json +99 -72
- package/src/index.js +38 -12
- package/src/struct/BTTVEmote.js +72 -74
- package/src/struct/Channel.js +48 -48
- package/src/struct/Emote.js +71 -71
- package/src/struct/EmoteFetcher.js +358 -322
- package/src/struct/EmoteParser.js +95 -84
- package/src/struct/EmoteTypeMapper.js +9 -9
- package/src/struct/FFZEmote.js +91 -93
- package/src/struct/SevenTVEmote.js +88 -90
- package/src/struct/TwitchEmote.js +72 -71
- package/src/util/Collection.js +69 -55
- package/src/util/Constants.js +30 -30
- package/typings/index.d.cts +254 -0
- package/typings/index.d.ts +216 -99
- package/.jsdoc.json +0 -46
- package/.nvmrc +0 -1
- package/docs/BTTVEmote.html +0 -1532
- package/docs/Channel.html +0 -824
- package/docs/Collection.html +0 -798
- package/docs/Emote.html +0 -832
- package/docs/EmoteFetcher.html +0 -3741
- package/docs/EmoteParser.html +0 -1187
- package/docs/FFZEmote.html +0 -1686
- package/docs/SevenTVEmote.html +0 -1596
- package/docs/TwitchEmote.html +0 -1528
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -978
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -1049
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/index.html +0 -233
- package/docs/scripts/collapse.js +0 -39
- package/docs/scripts/commonNav.js +0 -28
- package/docs/scripts/linenumber.js +0 -25
- package/docs/scripts/nav.js +0 -12
- package/docs/scripts/polyfill.js +0 -4
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/scripts/prettify/lang-css.js +0 -2
- package/docs/scripts/prettify/prettify.js +0 -28
- package/docs/scripts/search.js +0 -99
- package/docs/struct_BTTVEmote.js.html +0 -162
- package/docs/struct_Channel.js.html +0 -132
- package/docs/struct_Emote.js.html +0 -159
- package/docs/struct_EmoteFetcher.js.html +0 -429
- package/docs/struct_EmoteParser.js.html +0 -172
- package/docs/struct_FFZEmote.js.html +0 -185
- package/docs/struct_SevenTVEmote.js.html +0 -180
- package/docs/struct_TwitchEmote.js.html +0 -159
- package/docs/styles/jsdoc.css +0 -776
- package/docs/styles/prettify.css +0 -80
- package/docs/util_Collection.js.html +0 -151
- package/eslint.config.mjs +0 -215
- package/jest.config.js +0 -198
- package/test/BTTV.test.js +0 -48
- package/test/FFZ.test.js +0 -71
- package/test/SevenTV.test.js +0 -71
- package/test/ToFromObject.test.js +0 -156
- package/test/Twitch.test.js +0 -64
- package/test/__snapshots__/ToFromObject.test.js.snap +0 -121
- package/test/other.test.js +0 -72
|
@@ -0,0 +1,950 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/index.js
|
|
20
|
+
var index_exports = {};
|
|
21
|
+
__export(index_exports, {
|
|
22
|
+
BTTVEmote: () => BTTVEmote_default,
|
|
23
|
+
Channel: () => Channel_default,
|
|
24
|
+
Collection: () => Collection_default,
|
|
25
|
+
Constants: () => Constants_default,
|
|
26
|
+
Emote: () => Emote_default,
|
|
27
|
+
EmoteFetcher: () => EmoteFetcher_default,
|
|
28
|
+
EmoteParser: () => EmoteParser_default,
|
|
29
|
+
FFZEmote: () => FFZEmote_default,
|
|
30
|
+
SevenTVEmote: () => SevenTVEmote_default,
|
|
31
|
+
TwitchEmote: () => TwitchEmote_default,
|
|
32
|
+
default: () => index_default
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
|
+
|
|
36
|
+
// src/struct/Emote.js
|
|
37
|
+
var Emote = class _Emote {
|
|
38
|
+
/**
|
|
39
|
+
* Base class for emotes.
|
|
40
|
+
* This constructor is not to be used.
|
|
41
|
+
* @param {Channel} channel - Channel this emote belongs to.
|
|
42
|
+
* @param {string} id - ID of the emote.
|
|
43
|
+
* @param {data} data - The raw emote data.
|
|
44
|
+
* @throws {Error} When trying to use the base Emote class directly.
|
|
45
|
+
*/
|
|
46
|
+
constructor(channel, id, data) {
|
|
47
|
+
if (new.target.name === _Emote.name) {
|
|
48
|
+
throw new Error("Base Emote class cannot be used");
|
|
49
|
+
}
|
|
50
|
+
this.fetcher = channel.fetcher;
|
|
51
|
+
this.channel = channel;
|
|
52
|
+
this.id = id;
|
|
53
|
+
this.type = null;
|
|
54
|
+
this._setup(data);
|
|
55
|
+
}
|
|
56
|
+
_setup(data) {
|
|
57
|
+
this.code = data.code;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets the image link of the emote.
|
|
61
|
+
* @param {number} size - The size of the image.
|
|
62
|
+
* @returns {string} - The URL to the emote.
|
|
63
|
+
*/
|
|
64
|
+
/* c8 ignore next 3 */
|
|
65
|
+
toLink() {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Override for `toString`.
|
|
70
|
+
* Will give the emote's name.
|
|
71
|
+
* @returns {string} - The emote code.
|
|
72
|
+
*/
|
|
73
|
+
/* c8 ignore next 3 */
|
|
74
|
+
toString() {
|
|
75
|
+
return this.code;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Override for `toObject`.
|
|
79
|
+
* Will result in an Object representation of an Emote
|
|
80
|
+
* @returns {object} - Object representation of the Emote.
|
|
81
|
+
*/
|
|
82
|
+
toObject() {
|
|
83
|
+
return {
|
|
84
|
+
code: this.code,
|
|
85
|
+
id: this.id,
|
|
86
|
+
channel_id: this.channel.channel_id
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var Emote_default = Emote;
|
|
91
|
+
|
|
92
|
+
// src/util/Constants.js
|
|
93
|
+
var Constants_default = {
|
|
94
|
+
Twitch: {
|
|
95
|
+
CDN: (id, size = 0, forceStatic = false, theme = "dark") => `https://static-cdn.jtvnw.net/emoticons/v2/${id}/${forceStatic ? "static" : "default"}/${theme}/${size + 1}.0`
|
|
96
|
+
},
|
|
97
|
+
BTTV: {
|
|
98
|
+
Global: "https://api.betterttv.net/3/cached/emotes/global",
|
|
99
|
+
Channel: (id) => `https://api.betterttv.net/3/cached/users/twitch/${id}`,
|
|
100
|
+
CDN: (id, size = 0, forceStatic = false) => `https://cdn.betterttv.net/emote/${id}/${size + 1}x.${forceStatic ? "png" : "webp"}`
|
|
101
|
+
},
|
|
102
|
+
SevenTV: {
|
|
103
|
+
Global: "https://7tv.io/v3/emote-sets/global",
|
|
104
|
+
Channel: (id) => `https://7tv.io/v3/users/twitch/${id}`,
|
|
105
|
+
CDN: (id, format, size = 1, forceStatic = false) => `https://cdn.7tv.app/emote/${id}/${size}x${forceStatic ? "_static" : ""}.${format}`
|
|
106
|
+
},
|
|
107
|
+
FFZ: {
|
|
108
|
+
sets: {
|
|
109
|
+
Global: 3,
|
|
110
|
+
Modifiers: 1532818
|
|
111
|
+
},
|
|
112
|
+
Set: (id) => `https://api.frankerfacez.com/v1/set/${id}`,
|
|
113
|
+
Channel: (id) => `https://api.frankerfacez.com/v1/room/id/${id}`,
|
|
114
|
+
CDN: (id, size = 1) => `https://cdn.frankerfacez.com/emote/${id}/${size}`,
|
|
115
|
+
CDNAnimated: (id, size = 1) => `https://cdn.frankerfacez.com/emote/${id}/animated/${size}.webp`
|
|
116
|
+
},
|
|
117
|
+
Templates: {
|
|
118
|
+
html: '<img alt="{name}" title="{name}" class="twitch-emote" src="{link}">',
|
|
119
|
+
markdown: '',
|
|
120
|
+
bbcode: "[img]{link}[/img]",
|
|
121
|
+
plain: "{link}"
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// src/struct/BTTVEmote.js
|
|
126
|
+
var BTTVEmote = class _BTTVEmote extends Emote_default {
|
|
127
|
+
/**
|
|
128
|
+
* A BTTV emote.
|
|
129
|
+
* @param {Channel} channel - Channel this emote belongs to.
|
|
130
|
+
* @param {string} id - ID of the emote.
|
|
131
|
+
* @param {data} data - The raw emote data.
|
|
132
|
+
*/
|
|
133
|
+
constructor(channel, id, data) {
|
|
134
|
+
super(channel, id, data);
|
|
135
|
+
this.type = "bttv";
|
|
136
|
+
}
|
|
137
|
+
_setup(data) {
|
|
138
|
+
super._setup(data);
|
|
139
|
+
this.ownerName = "user" in data ? data.user.name : null;
|
|
140
|
+
this.animated = data.animated;
|
|
141
|
+
this.imageType = "webp";
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Gets the image link of the emote.
|
|
145
|
+
* @param {object} [options] - Options for the link.
|
|
146
|
+
* @param {number} [options.size=0] - Size (scale) for the emote.
|
|
147
|
+
* @param {boolean} [options.forceStatic] - Whether to force the emote to be static (non-animated). Defaults to the fetcher's forceStatic or `false`.
|
|
148
|
+
* @returns {string} - The URL to the emote.
|
|
149
|
+
*/
|
|
150
|
+
toLink(options) {
|
|
151
|
+
const {
|
|
152
|
+
size = 0,
|
|
153
|
+
forceStatic = this.fetcher.forceStatic || false
|
|
154
|
+
} = options || {};
|
|
155
|
+
return Constants_default.BTTV.CDN(this.id, size, forceStatic);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Override for `toObject`.
|
|
159
|
+
* Will result in an Object representation of a BTTVEmote
|
|
160
|
+
* @returns {object} - Object representation of the BTTVEmote.
|
|
161
|
+
*/
|
|
162
|
+
toObject() {
|
|
163
|
+
return {
|
|
164
|
+
...super.toObject(),
|
|
165
|
+
animated: this.animated,
|
|
166
|
+
ownerName: this.ownerName,
|
|
167
|
+
type: this.type
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Converts an emote Object into a BTTVEmote
|
|
172
|
+
* @param {object} [emoteObject] - Object representation of this emote
|
|
173
|
+
* @param {Channel} [channel] - Channel this emote belongs to.
|
|
174
|
+
* @returns {BTTVEmote} - A BTTVEmote instance.
|
|
175
|
+
*/
|
|
176
|
+
static fromObject(emoteObject, channel) {
|
|
177
|
+
return new _BTTVEmote(
|
|
178
|
+
channel,
|
|
179
|
+
emoteObject.id,
|
|
180
|
+
{
|
|
181
|
+
code: emoteObject.code,
|
|
182
|
+
animated: emoteObject.animated,
|
|
183
|
+
user: {
|
|
184
|
+
name: emoteObject.ownerName
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
var BTTVEmote_default = BTTVEmote;
|
|
191
|
+
|
|
192
|
+
// src/util/Collection.js
|
|
193
|
+
var Collection = class extends Map {
|
|
194
|
+
/**
|
|
195
|
+
* Finds first matching value by property or function.
|
|
196
|
+
* Same as `Array#find`.
|
|
197
|
+
* @param {string|Function} propOrFunc - Property or function to test.
|
|
198
|
+
* @param {any} [value] - Value to find.
|
|
199
|
+
* @returns {any|null} - The found item or null if none found.
|
|
200
|
+
*/
|
|
201
|
+
find(propOrFunc, value) {
|
|
202
|
+
if (typeof propOrFunc === "string") {
|
|
203
|
+
if (value === void 0) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
for (const item of this.values()) {
|
|
207
|
+
if (item[propOrFunc] === value) {
|
|
208
|
+
return item;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
if (typeof propOrFunc === "function") {
|
|
214
|
+
let i = 0;
|
|
215
|
+
for (const item of this.values()) {
|
|
216
|
+
if (propOrFunc(item, i, this)) {
|
|
217
|
+
return item;
|
|
218
|
+
}
|
|
219
|
+
i++;
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Filters cache by function.
|
|
227
|
+
* Same as `Array#filter`.
|
|
228
|
+
* @param {Function} func - Function to test.
|
|
229
|
+
* @param {any} [thisArg] - The context for the function.
|
|
230
|
+
* @returns {Collection} - A new collection with the filtered items.
|
|
231
|
+
*/
|
|
232
|
+
filter(func, thisArg) {
|
|
233
|
+
if (thisArg) {
|
|
234
|
+
func = func.bind(thisArg);
|
|
235
|
+
}
|
|
236
|
+
const results = new this.constructor();
|
|
237
|
+
let i = 0;
|
|
238
|
+
for (const [key, item] of this) {
|
|
239
|
+
if (func(item, i, this)) {
|
|
240
|
+
results.set(key, item);
|
|
241
|
+
}
|
|
242
|
+
i++;
|
|
243
|
+
}
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Maps cache by function.
|
|
248
|
+
* Same as `Array#map`.
|
|
249
|
+
* @param {Function} func - Function to use.
|
|
250
|
+
* @param {any} [thisArg] - The context for the function.
|
|
251
|
+
* @returns {any[]} - An array with the mapped items.
|
|
252
|
+
*/
|
|
253
|
+
map(func, thisArg) {
|
|
254
|
+
if (thisArg) {
|
|
255
|
+
func = func.bind(thisArg);
|
|
256
|
+
}
|
|
257
|
+
const array = new Array(this.size);
|
|
258
|
+
let i = 0;
|
|
259
|
+
for (const item of this.values()) {
|
|
260
|
+
array[i] = func(item, i, this);
|
|
261
|
+
i++;
|
|
262
|
+
}
|
|
263
|
+
return array;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
var Collection_default = Collection;
|
|
267
|
+
|
|
268
|
+
// src/struct/Channel.js
|
|
269
|
+
var Channel = class {
|
|
270
|
+
/**
|
|
271
|
+
* A Twitch channel.
|
|
272
|
+
* @param {EmoteFetcher} fetcher - The emote fetcher.
|
|
273
|
+
* @param {number} id - ID of the channel.
|
|
274
|
+
*/
|
|
275
|
+
constructor(fetcher, id) {
|
|
276
|
+
this.fetcher = fetcher;
|
|
277
|
+
this.channel_id = id || null;
|
|
278
|
+
this.emotes = new Collection_default();
|
|
279
|
+
}
|
|
280
|
+
/* There are tests that those are returning Collections, but c8 doesn't get it. */
|
|
281
|
+
/* c8 ignore start */
|
|
282
|
+
/**
|
|
283
|
+
* Fetches the BTTV emotes for this channel.
|
|
284
|
+
* @returns {Promise<Collection<string, BTTVEmote>>} - A promise that resolves to a collection of BTTVEmotes.
|
|
285
|
+
*/
|
|
286
|
+
fetchBTTVEmotes() {
|
|
287
|
+
return this.fetcher.fetchBTTVEmotes(this.id);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Fetches the FFZ emotes for this channel.
|
|
291
|
+
* @returns {Promise<Collection<string, FFZEmote>>} - A promise that resolves to a collection of FFZEmotes.
|
|
292
|
+
*/
|
|
293
|
+
fetchFFZEmotes() {
|
|
294
|
+
return this.fetcher.fetchFFZEmotes(this.id);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Fetches the 7TV emotes for this channel.
|
|
298
|
+
* @returns {Promise<Collection<string, SevenTVEmote>>} - A promise that resolves to a collection of SevenTVEmotes.
|
|
299
|
+
*/
|
|
300
|
+
fetchSevenTVEmotes() {
|
|
301
|
+
return this.fetcher.fetchSevenTVEmotes(this.id);
|
|
302
|
+
}
|
|
303
|
+
/* c8 ignore end */
|
|
304
|
+
};
|
|
305
|
+
var Channel_default = Channel;
|
|
306
|
+
|
|
307
|
+
// src/struct/FFZEmote.js
|
|
308
|
+
var FFZEmote = class _FFZEmote extends Emote_default {
|
|
309
|
+
/**
|
|
310
|
+
* An FFZ emote.
|
|
311
|
+
* @param {Channel} channel - Channel this emote belongs to.
|
|
312
|
+
* @param {string} id - ID of the emote.
|
|
313
|
+
* @param {data} data - The raw emote data.
|
|
314
|
+
*/
|
|
315
|
+
constructor(channel, id, data) {
|
|
316
|
+
super(channel, id, data);
|
|
317
|
+
this.type = "ffz";
|
|
318
|
+
}
|
|
319
|
+
_setup(data) {
|
|
320
|
+
super._setup(data);
|
|
321
|
+
this.code = data.name;
|
|
322
|
+
this.ownerName = "owner" in data ? data.owner.name : null;
|
|
323
|
+
this.sizes = "animated" in data ? Object.keys(data.animated) : Object.keys(data.urls);
|
|
324
|
+
this.animated = "animated" in data;
|
|
325
|
+
this.imageType = "animated" in data ? "webp" : "png";
|
|
326
|
+
this.modifier = data.modifier && (data.modifier_flags & 1) !== 0;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Gets the image link of the emote.
|
|
330
|
+
* @param {object} [options] - Options for the link.
|
|
331
|
+
* @param {number} [options.size=0] - Size (scale) for the emote.
|
|
332
|
+
* @param {boolean} [options.forceStatic] - Whether to force the emote to be static (non-animated). Defaults to the fetcher's forceStatic or `false`.
|
|
333
|
+
* @returns {string} - The URL to the emote.
|
|
334
|
+
*/
|
|
335
|
+
toLink(options) {
|
|
336
|
+
const {
|
|
337
|
+
size = 0,
|
|
338
|
+
forceStatic = this.fetcher.forceStatic || false
|
|
339
|
+
} = options || {};
|
|
340
|
+
const sizeKey = this.sizes[size];
|
|
341
|
+
if (this.animated && !forceStatic) return Constants_default.FFZ.CDNAnimated(this.id, sizeKey);
|
|
342
|
+
return Constants_default.FFZ.CDN(this.id, sizeKey);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Override for `toObject`.
|
|
346
|
+
* Will result in an Object representation of a FFZEmote
|
|
347
|
+
* @returns {object} - Object representation of the FFZEmote.
|
|
348
|
+
*/
|
|
349
|
+
toObject() {
|
|
350
|
+
return {
|
|
351
|
+
...super.toObject(),
|
|
352
|
+
animated: this.animated,
|
|
353
|
+
sizes: this.sizes,
|
|
354
|
+
ownerName: this.ownerName,
|
|
355
|
+
type: this.type,
|
|
356
|
+
modifier: this.modifier
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Converts an emote Object into a FFZEmote
|
|
361
|
+
* @param {object} [emoteObject] - Object representation of this emote
|
|
362
|
+
* @param {Channel} [channel] - Channel this emote belongs to.
|
|
363
|
+
* @returns {FFZEmote} - A FFZEmote instance.
|
|
364
|
+
*/
|
|
365
|
+
static fromObject(emoteObject, channel) {
|
|
366
|
+
const sizesObj = emoteObject.sizes.reduce((acc, curr) => {
|
|
367
|
+
acc[curr] = curr;
|
|
368
|
+
return acc;
|
|
369
|
+
}, {});
|
|
370
|
+
return new _FFZEmote(
|
|
371
|
+
channel,
|
|
372
|
+
emoteObject.id,
|
|
373
|
+
{
|
|
374
|
+
code: emoteObject.code,
|
|
375
|
+
name: emoteObject.code,
|
|
376
|
+
urls: sizesObj,
|
|
377
|
+
...emoteObject.animated ? { animated: sizesObj } : {},
|
|
378
|
+
owner: { name: emoteObject.ownerName },
|
|
379
|
+
modifier: emoteObject.modifier,
|
|
380
|
+
modifier_flags: emoteObject.modifier
|
|
381
|
+
}
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
var FFZEmote_default = FFZEmote;
|
|
386
|
+
|
|
387
|
+
// src/struct/SevenTVEmote.js
|
|
388
|
+
var SevenTVEmote = class _SevenTVEmote extends Emote_default {
|
|
389
|
+
/**
|
|
390
|
+
* A 7TV emote.
|
|
391
|
+
* @param {Channel} channel - Channel this emote belongs to.
|
|
392
|
+
* @param {string} id - ID of the emote.
|
|
393
|
+
* @param {data} data - The raw emote data.
|
|
394
|
+
*/
|
|
395
|
+
constructor(channel, id, data) {
|
|
396
|
+
super(channel, id, data);
|
|
397
|
+
this.type = "7tv";
|
|
398
|
+
}
|
|
399
|
+
_setup(data) {
|
|
400
|
+
super._setup(data);
|
|
401
|
+
this.code = data.name;
|
|
402
|
+
this.ownerName = "owner" in data.data ? data.data.owner.display_name : null;
|
|
403
|
+
this.sizes = data.data.host.files.filter((el) => el.format === this.channel.format.toUpperCase()).map((el) => el.name.replace(/x\.(\w+)/, ""));
|
|
404
|
+
this.animated = data.data.animated;
|
|
405
|
+
this.imageType = this.channel.format;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Gets the image link of the emote.
|
|
409
|
+
* @param {object} [options] - Options for the link.
|
|
410
|
+
* @param {number} [options.size=0] - Size (scale) for the emote.
|
|
411
|
+
* @param {boolean} [options.forceStatic] - Whether to force the emote to be static (non-animated). Defaults to the fetcher's forceStatic or `false`.
|
|
412
|
+
* @returns {string} - The URL to the emote.
|
|
413
|
+
*/
|
|
414
|
+
toLink(options) {
|
|
415
|
+
const {
|
|
416
|
+
size = 0,
|
|
417
|
+
forceStatic = this.fetcher.forceStatic || false
|
|
418
|
+
} = options || {};
|
|
419
|
+
const sizeKey = this.sizes[size];
|
|
420
|
+
return Constants_default.SevenTV.CDN(this.id, this.imageType, sizeKey, forceStatic);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Override for `toObject`.
|
|
424
|
+
* Will result in an Object representation of a SevenTVEmote
|
|
425
|
+
* @returns {object} - Object representation of the SevenTVEmote.
|
|
426
|
+
*/
|
|
427
|
+
toObject() {
|
|
428
|
+
return {
|
|
429
|
+
...super.toObject(),
|
|
430
|
+
animated: this.animated,
|
|
431
|
+
sizes: this.sizes,
|
|
432
|
+
ownerName: this.ownerName,
|
|
433
|
+
type: this.type,
|
|
434
|
+
imageType: this.imageType
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Converts an emote Object into a SevenTVEmote
|
|
439
|
+
* @param {object} [emoteObject] - Object representation of this emote
|
|
440
|
+
* @param {Channel} [channel] - Channel this emote belongs to.
|
|
441
|
+
* @returns {SevenTVEmote} - A SevenTVEmote instance.
|
|
442
|
+
*/
|
|
443
|
+
static fromObject(emoteObject, channel) {
|
|
444
|
+
const sizes = emoteObject.sizes.map((size) => {
|
|
445
|
+
return { format: channel.format.toUpperCase(), name: size };
|
|
446
|
+
});
|
|
447
|
+
return new _SevenTVEmote(
|
|
448
|
+
channel,
|
|
449
|
+
emoteObject.id,
|
|
450
|
+
{
|
|
451
|
+
code: emoteObject.code,
|
|
452
|
+
name: emoteObject.code,
|
|
453
|
+
data: {
|
|
454
|
+
animated: emoteObject.animated,
|
|
455
|
+
owner: {
|
|
456
|
+
display_name: emoteObject.ownerName
|
|
457
|
+
},
|
|
458
|
+
host: {
|
|
459
|
+
files: sizes
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
var SevenTVEmote_default = SevenTVEmote;
|
|
467
|
+
|
|
468
|
+
// src/struct/TwitchEmote.js
|
|
469
|
+
var TwitchEmote = class _TwitchEmote extends Emote_default {
|
|
470
|
+
/**
|
|
471
|
+
* A Twitch emote.
|
|
472
|
+
* @param {Channel} channel - Channel this emote belongs to.
|
|
473
|
+
* @param {string} id - ID of the emote.
|
|
474
|
+
* @param {data} data - The raw emote data.
|
|
475
|
+
*/
|
|
476
|
+
constructor(channel, id, data) {
|
|
477
|
+
super(channel, id, data);
|
|
478
|
+
this.type = "twitch";
|
|
479
|
+
}
|
|
480
|
+
_setup(data) {
|
|
481
|
+
super._setup(data);
|
|
482
|
+
this.set = data.emoticon_set;
|
|
483
|
+
this.animated = "animated" in data.formats;
|
|
484
|
+
this.imageType = "animated" in data.formats ? "gif" : "png";
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Gets the image link of the emote.
|
|
488
|
+
* @param {object} [options] - Options for the link.
|
|
489
|
+
* @param {number} [options.size=0] - Size (scale) for the emote.
|
|
490
|
+
* @param {boolean} [options.forceStatic] - Whether to force the emote to be static (non-animated). Defaults to the fetcher's forceStatic or `false`.
|
|
491
|
+
* @param {'dark' | 'light'} [options.themeMode] - Only for Twitch: the preferred theme mode. Defaults to the fetcher's twitchThemeMode or `dark`.
|
|
492
|
+
* @returns {string} - The URL to the emote.
|
|
493
|
+
*/
|
|
494
|
+
toLink(options) {
|
|
495
|
+
const {
|
|
496
|
+
size = 0,
|
|
497
|
+
forceStatic = this.fetcher.forceStatic || false,
|
|
498
|
+
themeMode = this.fetcher.twitchThemeMode || "dark"
|
|
499
|
+
} = options || {};
|
|
500
|
+
return Constants_default.Twitch.CDN(this.id, size, forceStatic, themeMode);
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Override for `toObject`.
|
|
504
|
+
* Will result in an Object representation of a TwitchEmote
|
|
505
|
+
* @returns {object} - Object representation of the TwitchEmote.
|
|
506
|
+
*/
|
|
507
|
+
toObject() {
|
|
508
|
+
return {
|
|
509
|
+
...super.toObject(),
|
|
510
|
+
animated: this.animated,
|
|
511
|
+
set: this.set,
|
|
512
|
+
type: this.type
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Converts an emote Object into a TwitchEmote
|
|
517
|
+
* @param {object} [emoteObject] - Object representation of this emote
|
|
518
|
+
* @param {Channel} [channel] - Channel this emote belongs to.
|
|
519
|
+
* @returns {TwitchEmote} - A TwitchEmote instance.
|
|
520
|
+
*/
|
|
521
|
+
static fromObject(emoteObject, channel) {
|
|
522
|
+
return new _TwitchEmote(
|
|
523
|
+
channel,
|
|
524
|
+
emoteObject.id,
|
|
525
|
+
{
|
|
526
|
+
code: emoteObject.code,
|
|
527
|
+
animated: emoteObject.animated,
|
|
528
|
+
emoticon_set: emoteObject.set,
|
|
529
|
+
formats: emoteObject.animated ? { animated: emoteObject.animated } : {}
|
|
530
|
+
}
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
var TwitchEmote_default = TwitchEmote;
|
|
535
|
+
|
|
536
|
+
// src/struct/EmoteFetcher.js
|
|
537
|
+
var import_api = require("@twurple/api");
|
|
538
|
+
var import_auth = require("@twurple/auth");
|
|
539
|
+
var EmoteFetcher = class {
|
|
540
|
+
/**
|
|
541
|
+
* Fetches and caches emotes.
|
|
542
|
+
* @param {object} [options={}] Fetcher's options.
|
|
543
|
+
* @param {string} [options.twitchAppID] Your app ID for the Twitch API.
|
|
544
|
+
* @param {string} [options.twitchAppSecret] Your app secret for the Twitch API.
|
|
545
|
+
* @param {ApiClient} [options.apiClient] - Bring your own Twurple ApiClient.
|
|
546
|
+
* @param {boolean} [options.forceStatic=false] - Force emotes to be static (non-animated).
|
|
547
|
+
* @param {'dark' | 'light'} [options.twitchThemeMode='dark'] - Theme mode (background color) preference for Twitch emotes.
|
|
548
|
+
*/
|
|
549
|
+
constructor(options = {}) {
|
|
550
|
+
if (options.apiClient) {
|
|
551
|
+
this.apiClient = options.apiClient;
|
|
552
|
+
} else if (options.twitchAppID && options.twitchAppSecret) {
|
|
553
|
+
const authProvider = new import_auth.AppTokenAuthProvider(options.twitchAppID, options.twitchAppSecret);
|
|
554
|
+
this.apiClient = new import_api.ApiClient({ authProvider });
|
|
555
|
+
}
|
|
556
|
+
this.forceStatic = options.forceStatic || false;
|
|
557
|
+
this.twitchThemeMode = options.twitchThemeMode || "dark";
|
|
558
|
+
this.emotes = new Collection_default();
|
|
559
|
+
this.channels = new Collection_default();
|
|
560
|
+
this.ffzModifiersFetched = false;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* The global channel for Twitch, BTTV and 7TV.
|
|
564
|
+
* @readonly
|
|
565
|
+
* @type {?Channel}
|
|
566
|
+
*/
|
|
567
|
+
get globalChannel() {
|
|
568
|
+
return this.channels.get(null);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Sets up a channel
|
|
572
|
+
* @private
|
|
573
|
+
* @param {number} channelId - ID of the channel.
|
|
574
|
+
* @param {string} [format] - The type file format to use (webp/avif).
|
|
575
|
+
* @throws {Error} When Twitch Client ID or Client Secret were not provided.
|
|
576
|
+
* @returns {Channel} - A Channel instance.
|
|
577
|
+
*/
|
|
578
|
+
_setupChannel(channelId, format) {
|
|
579
|
+
let channel = this.channels.get(channelId);
|
|
580
|
+
if (!channel) {
|
|
581
|
+
channel = new Channel_default(this, channelId);
|
|
582
|
+
this.channels.set(channelId, channel);
|
|
583
|
+
}
|
|
584
|
+
if (format) channel.format = format.toLowerCase();
|
|
585
|
+
return channel;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Gets the raw Twitch emotes data for a channel.
|
|
589
|
+
* @private
|
|
590
|
+
* @param {number} id - ID of the channel.
|
|
591
|
+
* @returns {Promise<object[]>} - A promise that resolves to an array of raw Twitch emote data.
|
|
592
|
+
*/
|
|
593
|
+
_getRawTwitchEmotes(id) {
|
|
594
|
+
if (!this.apiClient) {
|
|
595
|
+
throw new Error("Client id or client secret not provided.");
|
|
596
|
+
}
|
|
597
|
+
if (id) {
|
|
598
|
+
return this.apiClient.chat.getChannelEmotes(id);
|
|
599
|
+
} else {
|
|
600
|
+
return this.apiClient.chat.getGlobalEmotes();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Converts and caches a raw twitch emote.
|
|
605
|
+
* @private
|
|
606
|
+
* @param {number} channelId - ID of the channel.
|
|
607
|
+
* @param {object} data - Raw data.
|
|
608
|
+
* @param {TwitchEmote} [existingEmote] - Existing emote to cache.
|
|
609
|
+
* @returns {TwitchEmote} - A TwitchEmote instance.
|
|
610
|
+
*/
|
|
611
|
+
_cacheTwitchEmote(channelId, data, existingEmote) {
|
|
612
|
+
const channel = this._setupChannel(channelId);
|
|
613
|
+
const emote = existingEmote || new TwitchEmote_default(channel, data.id, data);
|
|
614
|
+
this.emotes.set(emote.code, emote);
|
|
615
|
+
channel.emotes.set(emote.code, emote);
|
|
616
|
+
return emote;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Gets the raw BTTV emotes data for a channel.
|
|
620
|
+
* Use `null` for the global emotes channel.
|
|
621
|
+
* @private
|
|
622
|
+
* @param {number} [id] - ID of the channel.
|
|
623
|
+
* @returns {Promise<object[]>} - A promise that resolves to an array of raw BTTV emote data.
|
|
624
|
+
*/
|
|
625
|
+
_getRawBTTVEmotes(id) {
|
|
626
|
+
const endpoint = id ? Constants_default.BTTV.Channel(id) : Constants_default.BTTV.Global;
|
|
627
|
+
return fetch(endpoint).then((response) => response.json()).then((data) => {
|
|
628
|
+
if (Array.isArray(data)) return data;
|
|
629
|
+
if (data?.channelEmotes && data?.sharedEmotes) {
|
|
630
|
+
return [
|
|
631
|
+
...data.channelEmotes,
|
|
632
|
+
...data.sharedEmotes
|
|
633
|
+
];
|
|
634
|
+
}
|
|
635
|
+
return data || [];
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Converts and caches a raw BTTV emote.
|
|
640
|
+
* @private
|
|
641
|
+
* @param {number} channelId - ID of the channel.
|
|
642
|
+
* @param {object} data - Raw data.
|
|
643
|
+
* @param {BTTVEmote} [existingEmote] - Existing emote to cache.
|
|
644
|
+
* @returns {BTTVEmote} - A BTTVEmote instance.
|
|
645
|
+
*/
|
|
646
|
+
_cacheBTTVEmote(channelId, data, existingEmote) {
|
|
647
|
+
const channel = this._setupChannel(channelId);
|
|
648
|
+
const emote = existingEmote || new BTTVEmote_default(channel, data.id, data);
|
|
649
|
+
this.emotes.set(emote.code, emote);
|
|
650
|
+
channel.emotes.set(emote.code, emote);
|
|
651
|
+
return emote;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Gets the raw FFZ emote data from a set.
|
|
655
|
+
* @private
|
|
656
|
+
* @param {number} id - ID of the set.
|
|
657
|
+
* @returns {Promise<object[]>} - A promise that resolves to an array of raw FFZ emote data.
|
|
658
|
+
*/
|
|
659
|
+
_getRawFFZEmoteSet(id) {
|
|
660
|
+
const endpoint = Constants_default.FFZ.Set(id);
|
|
661
|
+
return fetch(endpoint).then((response) => response.json()).then((data) => {
|
|
662
|
+
return data.set.emoticons;
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Gets the raw FFZ emotes data for a channel.
|
|
667
|
+
* @private
|
|
668
|
+
* @param {number} id - ID of the channel.
|
|
669
|
+
* @returns {Promise<object[]>} - A promise that resolves to an array of raw FFZ emote data.
|
|
670
|
+
*/
|
|
671
|
+
_getRawFFZEmotes(id) {
|
|
672
|
+
const endpoint = Constants_default.FFZ.Channel(id);
|
|
673
|
+
return fetch(endpoint).then((response) => response.json()).then((data) => {
|
|
674
|
+
const emotes = [];
|
|
675
|
+
for (const key of Object.keys(data.sets)) {
|
|
676
|
+
const set = data.sets[key];
|
|
677
|
+
emotes.push(...set.emoticons);
|
|
678
|
+
}
|
|
679
|
+
return emotes;
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Converts and caches a raw FFZ emote.
|
|
684
|
+
* @private
|
|
685
|
+
* @param {number} channelId - ID of the channel.
|
|
686
|
+
* @param {object} data - Raw data.
|
|
687
|
+
* @param {FFZEmote} [existingEmote] - Existing emote to cache.
|
|
688
|
+
* @returns {FFZEmote} - A FFZEmote instance.
|
|
689
|
+
*/
|
|
690
|
+
_cacheFFZEmote(channelId, data, existingEmote) {
|
|
691
|
+
const channel = this._setupChannel(channelId);
|
|
692
|
+
const emote = existingEmote || new FFZEmote_default(channel, data.id, data);
|
|
693
|
+
this.emotes.set(emote.code, emote);
|
|
694
|
+
channel.emotes.set(emote.code, emote);
|
|
695
|
+
return emote;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Gets the raw 7TV emotes data for a channel.
|
|
699
|
+
* @private
|
|
700
|
+
* @param {number} [id] - ID of the channel.
|
|
701
|
+
* @returns {Promise<object[]>} - A promise that resolves to an array of raw 7TV emote data.
|
|
702
|
+
*/
|
|
703
|
+
_getRawSevenTVEmotes(id) {
|
|
704
|
+
const endpoint = id ? Constants_default.SevenTV.Channel(id) : Constants_default.SevenTV.Global;
|
|
705
|
+
return fetch(endpoint).then((response) => response.json());
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Converts and caches a raw 7TV emote.
|
|
709
|
+
* @private
|
|
710
|
+
* @param {number} channelId - ID of the channel.
|
|
711
|
+
* @param {object} data - Raw data.
|
|
712
|
+
* @param {string} format - The type file format to use (webp/avif).
|
|
713
|
+
* @param {SevenTVEmote} [existingEmote] - Existing emote to cache.
|
|
714
|
+
* @returns {SevenTVEmote} - A SevenTVEmote instance.
|
|
715
|
+
*/
|
|
716
|
+
_cacheSevenTVEmote(channelId, data, format, existingEmote) {
|
|
717
|
+
const channel = this._setupChannel(channelId, format);
|
|
718
|
+
const emote = existingEmote || new SevenTVEmote_default(channel, data.id, data);
|
|
719
|
+
this.emotes.set(emote.code, emote);
|
|
720
|
+
channel.emotes.set(emote.code, emote);
|
|
721
|
+
return emote;
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Fetches the Twitch emotes for a channel.
|
|
725
|
+
* Use `null` for the global emotes channel.
|
|
726
|
+
* @param {number} [channel] - ID of the channel.
|
|
727
|
+
* @returns {Promise<Collection<string, TwitchEmote>>} - A promise that resolves to a collection of TwitchEmotes.
|
|
728
|
+
*/
|
|
729
|
+
fetchTwitchEmotes(channel) {
|
|
730
|
+
return this._getRawTwitchEmotes(channel).then((rawEmotes) => {
|
|
731
|
+
for (const emote of rawEmotes) {
|
|
732
|
+
this._cacheTwitchEmote(channel, {
|
|
733
|
+
code: emote.name,
|
|
734
|
+
id: emote.id,
|
|
735
|
+
formats: emote.formats
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
return this.channels.get(channel).emotes.filter((e) => e.type === "twitch");
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Fetches the BTTV emotes for a channel.
|
|
743
|
+
* Use `null` for the global emotes channel.
|
|
744
|
+
* @param {number} [channel] - ID of the channel.
|
|
745
|
+
* @returns {Promise<Collection<string, BTTVEmote>>} - A promise that resolves to a collection of BTTVEmotes.
|
|
746
|
+
*/
|
|
747
|
+
fetchBTTVEmotes(channel) {
|
|
748
|
+
return this._getRawBTTVEmotes(channel).then((rawEmotes) => {
|
|
749
|
+
for (const data of rawEmotes) {
|
|
750
|
+
this._cacheBTTVEmote(channel, data);
|
|
751
|
+
}
|
|
752
|
+
return this.channels.get(channel).emotes.filter((e) => e.type === "bttv");
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Fetches the FFZ emotes for a channel.
|
|
757
|
+
* @param {number} [channel] - ID of the channel.
|
|
758
|
+
* @returns {Promise<Collection<string, FFZEmote>>} - A promise that resolves to a collection of FFZEmotes.
|
|
759
|
+
*/
|
|
760
|
+
async fetchFFZEmotes(channel) {
|
|
761
|
+
if (!this.ffzModifiersFetched) {
|
|
762
|
+
this.ffzModifiersFetched = true;
|
|
763
|
+
await this._getRawFFZEmoteSet(Constants_default.FFZ.sets.Modifiers).then((rawEmotes) => {
|
|
764
|
+
for (const data of rawEmotes) {
|
|
765
|
+
this._cacheFFZEmote(null, data);
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
if (!channel) {
|
|
770
|
+
return this._getRawFFZEmoteSet(Constants_default.FFZ.sets.Global).then((rawEmotes) => {
|
|
771
|
+
for (const data of rawEmotes) {
|
|
772
|
+
this._cacheFFZEmote(channel, data);
|
|
773
|
+
}
|
|
774
|
+
return this.channels.get(channel).emotes.filter((e) => e.type === "ffz");
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
return this._getRawFFZEmotes(channel).then((rawEmotes) => {
|
|
778
|
+
for (const data of rawEmotes) {
|
|
779
|
+
this._cacheFFZEmote(channel, data);
|
|
780
|
+
}
|
|
781
|
+
return this.channels.get(channel).emotes.filter((e) => e.type === "ffz");
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Fetches the 7TV emotes for a channel.
|
|
786
|
+
* @param {number} [channel] - ID of the channel.
|
|
787
|
+
* @param {object} [options] - Options for fetching.
|
|
788
|
+
* @param {('webp'|'avif')} [options.format] - The type file format to use (webp/avif).
|
|
789
|
+
* @returns {Promise<Collection<string, SevenTVEmote>>} - A promise that resolves to a collection of SevenTVEmotes.
|
|
790
|
+
*/
|
|
791
|
+
fetchSevenTVEmotes(channel, options) {
|
|
792
|
+
const {
|
|
793
|
+
format = "webp"
|
|
794
|
+
} = options || {};
|
|
795
|
+
return this._getRawSevenTVEmotes(channel).then((rawEmotes) => {
|
|
796
|
+
if (Object.hasOwn(rawEmotes, "emotes")) {
|
|
797
|
+
for (const data of rawEmotes.emotes) {
|
|
798
|
+
this._cacheSevenTVEmote(channel, data, format);
|
|
799
|
+
}
|
|
800
|
+
} else {
|
|
801
|
+
for (const data of rawEmotes.emote_set.emotes) {
|
|
802
|
+
this._cacheSevenTVEmote(channel, data, format);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
return this.channels.get(channel).emotes.filter((e) => e.type === "7tv");
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Converts emote Objects to emotes
|
|
810
|
+
* @param {object} [emotesArray] - An array of emote objects
|
|
811
|
+
* @throws {TypeError} When an emote has an unknown type.
|
|
812
|
+
* @returns {Emote[]} - An array of Emote instances.
|
|
813
|
+
*/
|
|
814
|
+
fromObject(emotesArray) {
|
|
815
|
+
const emotes = [];
|
|
816
|
+
const classMap = {
|
|
817
|
+
"bttv": { class: BTTVEmote_default, cache: (emoteObject, channelId, existingEmote) => this._cacheBTTVEmote(channelId, null, existingEmote) },
|
|
818
|
+
"ffz": { class: FFZEmote_default, cache: (emoteObject, channelId, existingEmote) => this._cacheFFZEmote(channelId, null, existingEmote) },
|
|
819
|
+
"7tv": { class: SevenTVEmote_default, cache: (emoteObject, channelId, existingEmote) => this._cacheSevenTVEmote(channelId, null, emoteObject.imageType, existingEmote) },
|
|
820
|
+
"twitch": { class: TwitchEmote_default, cache: (emoteObject, channelId, existingEmote) => this._cacheTwitchEmote(channelId, null, existingEmote) }
|
|
821
|
+
};
|
|
822
|
+
for (const emoteObject of emotesArray) {
|
|
823
|
+
const { type } = emoteObject;
|
|
824
|
+
if (!Object.keys(classMap).includes(type)) {
|
|
825
|
+
throw new TypeError(`Unknown type: ${type}`);
|
|
826
|
+
}
|
|
827
|
+
const emoteClass = classMap[type].class;
|
|
828
|
+
this._setupChannel(emoteObject.channel_id, type === "7tv" ? emoteObject.imageType : null);
|
|
829
|
+
const emote = emoteClass.fromObject(emoteObject, this.channels.get(emoteObject.channel_id));
|
|
830
|
+
classMap[type].cache(emoteObject, emoteObject.channel_id, emote);
|
|
831
|
+
emotes.push(emote);
|
|
832
|
+
}
|
|
833
|
+
return emotes;
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
var EmoteFetcher_default = EmoteFetcher;
|
|
837
|
+
|
|
838
|
+
// src/struct/EmoteParser.js
|
|
839
|
+
var EmoteParser = class {
|
|
840
|
+
/**
|
|
841
|
+
* A parser to replace text with emotes.
|
|
842
|
+
* @param {EmoteFetcher} fetcher - The fetcher to use the cache of.
|
|
843
|
+
* @param {object} [options={}] - Options for the parser.
|
|
844
|
+
* @param {string} [options.template=''] - The template to be used.
|
|
845
|
+
* The strings that can be interpolated are:
|
|
846
|
+
* - `{link}` The link of the emote.
|
|
847
|
+
* - `{name}` The name of the emote.
|
|
848
|
+
* - `{size}` The size index of the image.
|
|
849
|
+
* - `{creator}` The channel/owner name of the emote.
|
|
850
|
+
* @param {'html' | 'markdown' | 'bbcode' | 'plain'} [options.type='html'] - The type of the parser.
|
|
851
|
+
* Can be one of `html`, `markdown`, `bbcode`, or `plain`.
|
|
852
|
+
* If the `template` option is provided, this is ignored.
|
|
853
|
+
* @param {RegExp} [options.match=/(\w+)/g] - The regular expression that matches an emote.
|
|
854
|
+
* Must be a global regex, with one capture group for the emote code.
|
|
855
|
+
*/
|
|
856
|
+
constructor(fetcher, options = {}) {
|
|
857
|
+
this.fetcher = fetcher;
|
|
858
|
+
this.options = {
|
|
859
|
+
template: "",
|
|
860
|
+
type: "html",
|
|
861
|
+
match: /(\w+)/g,
|
|
862
|
+
...options
|
|
863
|
+
};
|
|
864
|
+
this._validateOptions(this.options);
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Validates the parser options.
|
|
868
|
+
* @private
|
|
869
|
+
* @param {object} [options] - Options for the parser.
|
|
870
|
+
* @param {string} [options.template] - The template to be used.
|
|
871
|
+
* The strings that can be interpolated are:
|
|
872
|
+
* - `{link}` The link of the emote.
|
|
873
|
+
* - `{name}` The name of the emote.
|
|
874
|
+
* - `{size}` The size of the image.
|
|
875
|
+
* - `{creator}` The channel/owner name of the emote.
|
|
876
|
+
* @param {'html' | 'markdown' | 'bbcode' | 'plain'} [options.type] - The type of the parser.
|
|
877
|
+
* Can be one of `html`, `markdown`, `bbcode`, or `plain`.
|
|
878
|
+
* If the `template` option is provided, this is ignored.
|
|
879
|
+
* @param {RegExp} [options.match] - The regular expression that matches an emote.
|
|
880
|
+
* Must be a global regex, with one capture group for the emote code.
|
|
881
|
+
* @throws {TypeError} When template is not a string.
|
|
882
|
+
* @throws {TypeError} When type is not one of the supported types.
|
|
883
|
+
* @throws {TypeError} When match is not a global RegExp.
|
|
884
|
+
*/
|
|
885
|
+
_validateOptions(options) {
|
|
886
|
+
if (options.template && typeof options.template !== "string") {
|
|
887
|
+
throw new TypeError("Template must be a string");
|
|
888
|
+
}
|
|
889
|
+
if (!["html", "markdown", "bbcode", "plain"].includes(options.type)) {
|
|
890
|
+
throw new TypeError("Parse type must be one of `html`, `markdown`, `bbcode`, or `plain`");
|
|
891
|
+
}
|
|
892
|
+
if (!(options.match instanceof RegExp) || !options.match.global) {
|
|
893
|
+
throw new TypeError("Match must be a global RegExp.");
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Parses text.
|
|
898
|
+
* @param {string} text - Text to parse.
|
|
899
|
+
* @param {object} [options] - Parameters for parsing.
|
|
900
|
+
* @param {number} [options.size] - Size (scale) for emotes.
|
|
901
|
+
* @param {boolean} [options.forceStatic] - Whether to force the emote to be static (non-animated). Defaults to the fetcher's forceStatic or `false`.
|
|
902
|
+
* @param {'dark' | 'light'} [options.themeMode] - Only for Twitch: the preferred theme mode. Defaults to the fetcher's twitchThemeMode or `dark`.
|
|
903
|
+
* @returns {string} - The parsed text.
|
|
904
|
+
*/
|
|
905
|
+
parse(text, options) {
|
|
906
|
+
const {
|
|
907
|
+
size,
|
|
908
|
+
forceStatic,
|
|
909
|
+
themeMode
|
|
910
|
+
} = options || {};
|
|
911
|
+
const parsed = text.replace(this.options.match, (matched, id) => {
|
|
912
|
+
const emote = this.fetcher.emotes.get(id);
|
|
913
|
+
if (!emote) return matched;
|
|
914
|
+
if (emote.modifier) return "";
|
|
915
|
+
const template = this.options.template || Constants_default.Templates[this.options.type];
|
|
916
|
+
const link = emote.toLink({ size, forceStatic, themeMode });
|
|
917
|
+
const res = template.replaceAll("{link}", link).replaceAll("{name}", emote.code).replaceAll("{size}", size).replaceAll("{creator}", emote.ownerName || "global");
|
|
918
|
+
return res;
|
|
919
|
+
});
|
|
920
|
+
return parsed;
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
var EmoteParser_default = EmoteParser;
|
|
924
|
+
|
|
925
|
+
// src/index.js
|
|
926
|
+
var index_default = {
|
|
927
|
+
BTTVEmote: BTTVEmote_default,
|
|
928
|
+
Channel: Channel_default,
|
|
929
|
+
Collection: Collection_default,
|
|
930
|
+
Constants: Constants_default,
|
|
931
|
+
Emote: Emote_default,
|
|
932
|
+
EmoteFetcher: EmoteFetcher_default,
|
|
933
|
+
EmoteParser: EmoteParser_default,
|
|
934
|
+
FFZEmote: FFZEmote_default,
|
|
935
|
+
SevenTVEmote: SevenTVEmote_default,
|
|
936
|
+
TwitchEmote: TwitchEmote_default
|
|
937
|
+
};
|
|
938
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
939
|
+
0 && (module.exports = {
|
|
940
|
+
BTTVEmote,
|
|
941
|
+
Channel,
|
|
942
|
+
Collection,
|
|
943
|
+
Constants,
|
|
944
|
+
Emote,
|
|
945
|
+
EmoteFetcher,
|
|
946
|
+
EmoteParser,
|
|
947
|
+
FFZEmote,
|
|
948
|
+
SevenTVEmote,
|
|
949
|
+
TwitchEmote
|
|
950
|
+
});
|