streamer-emotes 0.1.0 → 0.1.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 +48 -0
- package/dist/index.d.mts +56 -12
- package/dist/index.mjs +36 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
# streamer-emotes
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
|
|
2
6
|
A library to get Twitch, BTTV, FFZ and 7TV emotes for a given Twitch channel.
|
|
3
7
|
|
|
4
8
|
## Usage
|
|
@@ -15,3 +19,47 @@ const emotes = await getStreamerEmotes("rubius", {
|
|
|
15
19
|
|
|
16
20
|
console.info(emotes);
|
|
17
21
|
```
|
|
22
|
+
|
|
23
|
+
## Output example
|
|
24
|
+
```jsonc
|
|
25
|
+
{
|
|
26
|
+
"<provider>": { // Provider prop
|
|
27
|
+
"channel": [ // Channel Emotes
|
|
28
|
+
{
|
|
29
|
+
"animated": true,
|
|
30
|
+
"id": "string",
|
|
31
|
+
"images": [
|
|
32
|
+
{
|
|
33
|
+
"url": "string",
|
|
34
|
+
"version": "string"
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"name": "string",
|
|
38
|
+
"provider": "string",
|
|
39
|
+
"zeroWidth": true // 7TV zero width emotes only
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"global": [ // Global Emotes
|
|
43
|
+
{
|
|
44
|
+
"animated": false,
|
|
45
|
+
"id": "string",
|
|
46
|
+
"images": [
|
|
47
|
+
{
|
|
48
|
+
"url": "string",
|
|
49
|
+
"version": "string"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"name": "string",
|
|
53
|
+
"provider": "string",
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
<!-- Badges -->
|
|
61
|
+
[npm-version-src]: https://img.shields.io/npm/v/streamer-emotes.svg?style=flat
|
|
62
|
+
[npm-version-href]: https://npmjs.com/package/streamer-emotes
|
|
63
|
+
|
|
64
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/streamer-emotes.svg?style=flat
|
|
65
|
+
[npm-downloads-href]: https://npmjs.com/package/streamer-emotes
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/types/index.d.ts
|
|
2
|
-
interface StreamerEmotesProps {
|
|
2
|
+
interface StreamerEmotesProps<T> {
|
|
3
3
|
animated: boolean;
|
|
4
4
|
id: string;
|
|
5
5
|
images: {
|
|
@@ -7,18 +7,62 @@ interface StreamerEmotesProps {
|
|
|
7
7
|
version: string;
|
|
8
8
|
}[];
|
|
9
9
|
name: string;
|
|
10
|
-
provider:
|
|
10
|
+
provider: T;
|
|
11
11
|
zeroWidth?: boolean;
|
|
12
12
|
}
|
|
13
|
-
interface StreamerEmotesProviderResponse {
|
|
14
|
-
channel: StreamerEmotesProps[];
|
|
15
|
-
global?: StreamerEmotesProps[];
|
|
13
|
+
interface StreamerEmotesProviderResponse<T> {
|
|
14
|
+
channel: StreamerEmotesProps<T>[];
|
|
15
|
+
global?: StreamerEmotesProps<T>[];
|
|
16
16
|
}
|
|
17
17
|
//#endregion
|
|
18
|
-
//#region src/
|
|
18
|
+
//#region src/providers/7tv.d.ts
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param twitchLogin Twitch channel login.
|
|
22
|
+
* @param {boolean} options.globals Include global Twitch emotes in the response. Defaults to `true`.
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
declare const get7tvEmotes: (channelLogin: string, options?: {
|
|
26
|
+
globals?: boolean;
|
|
27
|
+
}) => Promise<StreamerEmotesProviderResponse<"7tv">>;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/providers/bttv.d.ts
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param twitchLogin Twitch channel login.
|
|
33
|
+
* @param {boolean} options.globals Include global Twitch emotes in the response. Defaults to `true`.
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
declare const getBttvEmotes: (channelLogin: string, options?: {
|
|
37
|
+
globals?: boolean;
|
|
38
|
+
}) => Promise<StreamerEmotesProviderResponse<"bttv">>;
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/providers/ffz.d.ts
|
|
19
41
|
/**
|
|
20
42
|
*
|
|
21
|
-
* @param
|
|
43
|
+
* @param twitchLogin Twitch channel login.
|
|
44
|
+
* @param {boolean} options.globals Include global Twitch emotes in the response. Defaults to `true`.
|
|
45
|
+
* @returns
|
|
46
|
+
*/
|
|
47
|
+
declare const getFfzEmotes: (channelLogin: string, options?: {
|
|
48
|
+
globals?: boolean;
|
|
49
|
+
}) => Promise<StreamerEmotesProviderResponse<"ffz">>;
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/providers/twitch.d.ts
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param twitchLogin Twitch channel login.
|
|
55
|
+
* @param {boolean} options.globals Include global Twitch emotes in the response. Defaults to `true`.
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
declare const getTwitchEmotes: (channelLogin: string, options?: {
|
|
59
|
+
globals?: boolean;
|
|
60
|
+
}) => Promise<StreamerEmotesProviderResponse<"twitch">>;
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/index.d.ts
|
|
63
|
+
/**
|
|
64
|
+
* Get Twitch channel emotes from multiple providers.
|
|
65
|
+
* @param channelLogin Twitch channel login.
|
|
22
66
|
* @param options.bttv Get emotes from BetterTTV if `true`. Defaults to `false`.
|
|
23
67
|
* @param options.ffz Get emotes from FrankerFaceZ if `true`. Defaults to `false`.
|
|
24
68
|
* @param options.sevenTV Get emotes from 7TV if `true`. Defaults to `false`.
|
|
@@ -32,13 +76,13 @@ declare const getStreamerEmotes: (channelLogin: string, options: {
|
|
|
32
76
|
sevenTV?: boolean | StreamerEmotesProviderOptions;
|
|
33
77
|
twitch?: boolean | StreamerEmotesProviderOptions;
|
|
34
78
|
}) => Promise<{
|
|
35
|
-
bttv?: StreamerEmotesProviderResponse
|
|
36
|
-
ffz?: StreamerEmotesProviderResponse
|
|
37
|
-
sevenTV?: StreamerEmotesProviderResponse
|
|
38
|
-
twitch?: StreamerEmotesProviderResponse
|
|
79
|
+
bttv?: StreamerEmotesProviderResponse<"bttv">;
|
|
80
|
+
ffz?: StreamerEmotesProviderResponse<"ffz">;
|
|
81
|
+
sevenTV?: StreamerEmotesProviderResponse<"7tv">;
|
|
82
|
+
twitch?: StreamerEmotesProviderResponse<"twitch">;
|
|
39
83
|
}>;
|
|
40
84
|
interface StreamerEmotesProviderOptions {
|
|
41
85
|
globals: boolean;
|
|
42
86
|
}
|
|
43
87
|
//#endregion
|
|
44
|
-
export { getStreamerEmotes };
|
|
88
|
+
export { get7tvEmotes, getBttvEmotes, getFfzEmotes, getStreamerEmotes, getTwitchEmotes };
|
package/dist/index.mjs
CHANGED
|
@@ -7,24 +7,27 @@ const providersURL = {
|
|
|
7
7
|
ffz: "https://api.frankerfacez.com/v1",
|
|
8
8
|
twitch: "https://gql.twitch.tv/gql"
|
|
9
9
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
login = login.toLowerCase();
|
|
13
|
-
if (twitchIdMemory[login]) return twitchIdMemory[login];
|
|
14
|
-
const { data } = await $fetch(providersURL.twitch, {
|
|
10
|
+
const callTwitchGQL = async (...args) => {
|
|
11
|
+
return $fetch(providersURL.twitch, {
|
|
15
12
|
method: "POST",
|
|
16
13
|
headers: {
|
|
17
14
|
"Client-ID": "kimne78kx3ncx6brgo4mv6wki5h1ko",
|
|
18
15
|
"Content-Type": "application/json"
|
|
19
16
|
},
|
|
20
|
-
body: gqlQuery(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
body: gqlQuery(...args)
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
let twitchIdMemory = {};
|
|
21
|
+
const getTwitchIdByLogin = async (login) => {
|
|
22
|
+
login = login.toLowerCase();
|
|
23
|
+
if (twitchIdMemory[login]) return twitchIdMemory[login];
|
|
24
|
+
const { data } = await callTwitchGQL({
|
|
25
|
+
operation: "user",
|
|
26
|
+
variables: { login: {
|
|
27
|
+
value: login,
|
|
28
|
+
type: "String!"
|
|
29
|
+
} },
|
|
30
|
+
fields: ["id"]
|
|
28
31
|
});
|
|
29
32
|
const channelId = data?.user?.id;
|
|
30
33
|
if (!channelId) throw new Error(`Twitch channel with login '${login}' not found.`);
|
|
@@ -45,15 +48,9 @@ const get7tvEmotes = async (channelLogin, options) => {
|
|
|
45
48
|
const channelId = await getTwitchIdByLogin(channelLogin);
|
|
46
49
|
const channel = [];
|
|
47
50
|
const global = [];
|
|
48
|
-
const channelDataPromise = $fetch(`/users/twitch/${channelId}`, {
|
|
49
|
-
baseURL: providersURL.sevenTV,
|
|
50
|
-
method: "GET"
|
|
51
|
-
}).catch(() => null);
|
|
51
|
+
const channelDataPromise = $fetch(`/users/twitch/${channelId}`, { baseURL: providersURL.sevenTV }).catch(() => null);
|
|
52
52
|
let globalDataPromise;
|
|
53
|
-
if (globals) globalDataPromise = $fetch("/emote-sets/global", {
|
|
54
|
-
baseURL: providersURL.sevenTV,
|
|
55
|
-
method: "GET"
|
|
56
|
-
});
|
|
53
|
+
if (globals) globalDataPromise = $fetch("/emote-sets/global", { baseURL: providersURL.sevenTV });
|
|
57
54
|
const [channelData, globalData] = await Promise.all([channelDataPromise, globalDataPromise]);
|
|
58
55
|
if (channelData) channel.push(...channelData.emote_set.emotes);
|
|
59
56
|
if (globalData) global.push(...globalData.emotes);
|
|
@@ -93,34 +90,29 @@ const getBttvEmotes = async (channelLogin, options) => {
|
|
|
93
90
|
const channelId = await getTwitchIdByLogin(channelLogin);
|
|
94
91
|
const channel = [];
|
|
95
92
|
const global = [];
|
|
96
|
-
const channelDataPromise = $fetch(`/cached/users/twitch/${channelId}`, {
|
|
97
|
-
baseURL: providersURL.bttv,
|
|
98
|
-
method: "GET"
|
|
99
|
-
}).catch(() => null);
|
|
93
|
+
const channelDataPromise = $fetch(`/cached/users/twitch/${channelId}`, { baseURL: providersURL.bttv }).catch(() => null);
|
|
100
94
|
let globalDataPromise;
|
|
101
|
-
if (globals) globalDataPromise = $fetch("/cached/emotes/global", {
|
|
102
|
-
baseURL: providersURL.bttv,
|
|
103
|
-
method: "GET"
|
|
104
|
-
});
|
|
95
|
+
if (globals) globalDataPromise = $fetch("/cached/emotes/global", { baseURL: providersURL.bttv });
|
|
105
96
|
const [channelData, globalData] = await Promise.all([channelDataPromise, globalDataPromise]);
|
|
106
97
|
if (channelData) channel.push(...channelData.channelEmotes, ...channelData.sharedEmotes);
|
|
107
98
|
if (globalData) global.push(...globalData);
|
|
108
99
|
const normalizeData = (data) => {
|
|
109
100
|
if (!data?.length) return [];
|
|
101
|
+
const getBTTVEmoticonsURL = (id, version) => `https://cdn.betterttv.net/emote/${id}/${version}`;
|
|
110
102
|
return data.map((emote) => ({
|
|
111
103
|
animated: emote.animated,
|
|
112
104
|
id: emote.id,
|
|
113
105
|
images: [
|
|
114
106
|
{
|
|
115
|
-
url:
|
|
107
|
+
url: getBTTVEmoticonsURL(emote.id, "1x"),
|
|
116
108
|
version: "1x"
|
|
117
109
|
},
|
|
118
110
|
{
|
|
119
|
-
url:
|
|
111
|
+
url: getBTTVEmoticonsURL(emote.id, "2x"),
|
|
120
112
|
version: "2x"
|
|
121
113
|
},
|
|
122
114
|
{
|
|
123
|
-
url:
|
|
115
|
+
url: getBTTVEmoticonsURL(emote.id, "3x"),
|
|
124
116
|
version: "3x"
|
|
125
117
|
}
|
|
126
118
|
],
|
|
@@ -147,15 +139,9 @@ const getFfzEmotes = async (channelLogin, options) => {
|
|
|
147
139
|
const channelId = await getTwitchIdByLogin(channelLogin);
|
|
148
140
|
const channel = [];
|
|
149
141
|
const global = [];
|
|
150
|
-
const channelDataPromise = $fetch(`/room/id/${channelId}`, {
|
|
151
|
-
baseURL: providersURL.ffz,
|
|
152
|
-
method: "GET"
|
|
153
|
-
}).catch(() => null);
|
|
142
|
+
const channelDataPromise = $fetch(`/room/id/${channelId}`, { baseURL: providersURL.ffz }).catch(() => null);
|
|
154
143
|
let globalDataPromise;
|
|
155
|
-
if (globals) globalDataPromise = $fetch("/set/global", {
|
|
156
|
-
baseURL: providersURL.ffz,
|
|
157
|
-
method: "GET"
|
|
158
|
-
});
|
|
144
|
+
if (globals) globalDataPromise = $fetch("/set/global", { baseURL: providersURL.ffz });
|
|
159
145
|
const [channelData, globalData] = await Promise.all([channelDataPromise, globalDataPromise]);
|
|
160
146
|
if (channelData) channel.push(...channelData.sets[channelData.room.set].emoticons);
|
|
161
147
|
if (globalData) global.push(...globalData.default_sets.flatMap((setId) => globalData.sets[setId].emoticons));
|
|
@@ -226,30 +212,24 @@ const getTwitchEmotes = async (channelLogin, options) => {
|
|
|
226
212
|
if (globals) toQuery.push(globalQuery);
|
|
227
213
|
toQuery.push(channelQuery);
|
|
228
214
|
toQuery.push(localEmotesQuery);
|
|
229
|
-
const { data } = await
|
|
230
|
-
method: "POST",
|
|
231
|
-
headers: {
|
|
232
|
-
"Client-ID": "kimne78kx3ncx6brgo4mv6wki5h1ko",
|
|
233
|
-
"Content-Type": "application/json"
|
|
234
|
-
},
|
|
235
|
-
body: gqlQuery(toQuery)
|
|
236
|
-
});
|
|
215
|
+
const { data } = await callTwitchGQL(toQuery);
|
|
237
216
|
const normalizeData = (data) => {
|
|
238
217
|
if (!data?.length) return [];
|
|
218
|
+
const getTwitchEmoticonsURL = (id, version) => `https://static-cdn.jtvnw.net/emoticons/v2/${id}/default/dark/${version}`;
|
|
239
219
|
return data.map((emote) => ({
|
|
240
220
|
animated: emote.assetType === "ANIMATED",
|
|
241
221
|
id: emote.id,
|
|
242
222
|
images: [
|
|
243
223
|
{
|
|
244
|
-
url:
|
|
224
|
+
url: getTwitchEmoticonsURL(emote.id, "1.0"),
|
|
245
225
|
version: "1.0"
|
|
246
226
|
},
|
|
247
227
|
{
|
|
248
|
-
url:
|
|
228
|
+
url: getTwitchEmoticonsURL(emote.id, "2.0"),
|
|
249
229
|
version: "2.0"
|
|
250
230
|
},
|
|
251
231
|
{
|
|
252
|
-
url:
|
|
232
|
+
url: getTwitchEmoticonsURL(emote.id, "3.0"),
|
|
253
233
|
version: "3.0"
|
|
254
234
|
}
|
|
255
235
|
],
|
|
@@ -265,8 +245,8 @@ const getTwitchEmotes = async (channelLogin, options) => {
|
|
|
265
245
|
//#endregion
|
|
266
246
|
//#region src/index.ts
|
|
267
247
|
/**
|
|
268
|
-
*
|
|
269
|
-
* @param channelLogin
|
|
248
|
+
* Get Twitch channel emotes from multiple providers.
|
|
249
|
+
* @param channelLogin Twitch channel login.
|
|
270
250
|
* @param options.bttv Get emotes from BetterTTV if `true`. Defaults to `false`.
|
|
271
251
|
* @param options.ffz Get emotes from FrankerFaceZ if `true`. Defaults to `false`.
|
|
272
252
|
* @param options.sevenTV Get emotes from 7TV if `true`. Defaults to `false`.
|
|
@@ -275,15 +255,15 @@ const getTwitchEmotes = async (channelLogin, options) => {
|
|
|
275
255
|
* @returns
|
|
276
256
|
*/
|
|
277
257
|
const getStreamerEmotes = async (channelLogin, options) => {
|
|
278
|
-
if (!Object.keys(options).length) throw new Error("At least one provider must be enabled");
|
|
258
|
+
if (!Object.keys(options).length || !Object.values(options).some((value) => value)) throw new Error("At least one provider must be enabled.");
|
|
279
259
|
const { bttv, ffz, sevenTV, twitch } = options;
|
|
280
260
|
const data = {};
|
|
281
261
|
let bttvPromise, ffzPromise, sevenTvPromise, twitchPromise;
|
|
282
|
-
if (bttv || ffz || sevenTV || twitch) await getTwitchIdByLogin(channelLogin);
|
|
283
262
|
if (bttv) bttvPromise = getBttvEmotes(channelLogin, { globals: typeof bttv === "boolean" ? true : bttv?.globals ?? true }).catch(() => null);
|
|
284
263
|
if (ffz) ffzPromise = getFfzEmotes(channelLogin, { globals: typeof ffz === "boolean" ? true : ffz?.globals ?? true }).catch(() => null);
|
|
285
264
|
if (sevenTV) sevenTvPromise = get7tvEmotes(channelLogin, { globals: typeof sevenTV === "boolean" ? true : sevenTV?.globals ?? true }).catch(() => null);
|
|
286
265
|
if (twitch) twitchPromise = getTwitchEmotes(channelLogin, { globals: typeof twitch === "boolean" ? true : twitch?.globals ?? true }).catch(() => null);
|
|
266
|
+
await getTwitchIdByLogin(channelLogin);
|
|
287
267
|
const [bttvEmotes, ffzEmotes, sevenTvEmotes, twitchEmotes] = await Promise.all([
|
|
288
268
|
bttvPromise,
|
|
289
269
|
ffzPromise,
|
|
@@ -297,4 +277,4 @@ const getStreamerEmotes = async (channelLogin, options) => {
|
|
|
297
277
|
return data;
|
|
298
278
|
};
|
|
299
279
|
//#endregion
|
|
300
|
-
export { getStreamerEmotes };
|
|
280
|
+
export { get7tvEmotes, getBttvEmotes, getFfzEmotes, getStreamerEmotes, getTwitchEmotes };
|