@allior/wmake-emotes 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -0
- package/dist/provider-CDtB3U-Z.js +62 -0
- package/dist/provider-CDtB3U-Z.js.map +1 -0
- package/dist/react/hooks/index.d.ts +2 -0
- package/dist/react/hooks/index.d.ts.map +1 -0
- package/dist/react/hooks/useEmotes.d.ts +17 -0
- package/dist/react/hooks/useEmotes.d.ts.map +1 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.iife.js +2 -0
- package/dist/react/index.iife.js.map +1 -0
- package/dist/react/index.js +55 -0
- package/dist/react/index.js.map +1 -0
- package/dist/root/7tv/index.d.ts +4 -0
- package/dist/root/7tv/index.d.ts.map +1 -0
- package/dist/root/7tv/set.d.ts +4 -0
- package/dist/root/7tv/set.d.ts.map +1 -0
- package/dist/root/7tv/types/emote.d.ts +5 -0
- package/dist/root/7tv/types/emote.d.ts.map +1 -0
- package/dist/root/7tv/types/index.d.ts +6 -0
- package/dist/root/7tv/types/index.d.ts.map +1 -0
- package/dist/root/7tv/types/seven-tv.d.ts +91 -0
- package/dist/root/7tv/types/seven-tv.d.ts.map +1 -0
- package/dist/root/7tv/utils.d.ts +3 -0
- package/dist/root/7tv/utils.d.ts.map +1 -0
- package/dist/root/betterttv/index.d.ts +3 -0
- package/dist/root/betterttv/index.d.ts.map +1 -0
- package/dist/root/betterttv/set.d.ts +5 -0
- package/dist/root/betterttv/set.d.ts.map +1 -0
- package/dist/root/betterttv/types/cached-user-response.d.ts +62 -0
- package/dist/root/betterttv/types/cached-user-response.d.ts.map +1 -0
- package/dist/root/betterttv/types/index.d.ts +5 -0
- package/dist/root/betterttv/types/index.d.ts.map +1 -0
- package/dist/root/common/enums/index.d.ts +2 -0
- package/dist/root/common/enums/index.d.ts.map +1 -0
- package/dist/root/common/enums/provider.d.ts +5 -0
- package/dist/root/common/enums/provider.d.ts.map +1 -0
- package/dist/root/common/index.d.ts +3 -0
- package/dist/root/common/index.d.ts.map +1 -0
- package/dist/root/common/types/emote.d.ts +9 -0
- package/dist/root/common/types/emote.d.ts.map +1 -0
- package/dist/root/common/types/index.d.ts +3 -0
- package/dist/root/common/types/index.d.ts.map +1 -0
- package/dist/root/frankerfacez/index.d.ts +4 -0
- package/dist/root/frankerfacez/index.d.ts.map +1 -0
- package/dist/root/frankerfacez/set.d.ts +10 -0
- package/dist/root/frankerfacez/set.d.ts.map +1 -0
- package/dist/root/frankerfacez/types/frankerfacez.d.ts +104 -0
- package/dist/root/frankerfacez/types/frankerfacez.d.ts.map +1 -0
- package/dist/root/frankerfacez/types/index.d.ts +5 -0
- package/dist/root/frankerfacez/types/index.d.ts.map +1 -0
- package/dist/root/frankerfacez/utils.d.ts +2 -0
- package/dist/root/frankerfacez/utils.d.ts.map +1 -0
- package/dist/root/index.d.ts +5 -0
- package/dist/root/index.d.ts.map +1 -0
- package/dist/root/index.iife.js +2 -0
- package/dist/root/index.iife.js.map +1 -0
- package/dist/root/index.js +16 -0
- package/dist/root/index.js.map +1 -0
- package/package.json +41 -0
- package/src/react/hooks/index.ts +1 -0
- package/src/react/hooks/useEmotes.ts +105 -0
- package/src/react/index.ts +1 -0
- package/src/root/7tv/index.ts +3 -0
- package/src/root/7tv/set.ts +16 -0
- package/src/root/7tv/types/emote.ts +4 -0
- package/src/root/7tv/types/index.ts +6 -0
- package/src/root/7tv/types/seven-tv.ts +100 -0
- package/src/root/7tv/utils.ts +5 -0
- package/src/root/betterttv/index.ts +2 -0
- package/src/root/betterttv/set.ts +49 -0
- package/src/root/betterttv/types/cached-user-response.ts +62 -0
- package/src/root/betterttv/types/index.ts +6 -0
- package/src/root/common/enums/index.ts +1 -0
- package/src/root/common/enums/provider.ts +4 -0
- package/src/root/common/index.ts +2 -0
- package/src/root/common/types/emote.ts +8 -0
- package/src/root/common/types/index.ts +2 -0
- package/src/root/frankerfacez/index.ts +3 -0
- package/src/root/frankerfacez/set.ts +46 -0
- package/src/root/frankerfacez/types/frankerfacez.ts +113 -0
- package/src/root/frankerfacez/types/index.ts +6 -0
- package/src/root/frankerfacez/utils.ts +6 -0
- package/src/root/index.ts +4 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FrankerFaceZ } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Получить набор эмоутов пользователя FrankerFaceZ
|
|
4
|
+
*/
|
|
5
|
+
export declare const getFrankerFaceZUserEmoteSet: (username: string) => Promise<FrankerFaceZ.Emote[]>;
|
|
6
|
+
/**
|
|
7
|
+
* Получить глобальные эмоуты FrankerFaceZ
|
|
8
|
+
*/
|
|
9
|
+
export declare const getFrankerFaceZGlobalEmoteSet: () => Promise<FrankerFaceZ.Emote[]>;
|
|
10
|
+
//# sourceMappingURL=set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/root/frankerfacez/set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAe5C;;GAEG;AACH,eAAO,MAAM,2BAA2B,GACtC,UAAU,MAAM,KACf,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,CAU9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,6BAA6B,QAAa,OAAO,CAC5D,YAAY,CAAC,KAAK,EAAE,CASrB,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Типы для FrankerFaceZ API
|
|
3
|
+
*/
|
|
4
|
+
export declare namespace FrankerFaceZ {
|
|
5
|
+
/**
|
|
6
|
+
* Размеры эмоута
|
|
7
|
+
*/
|
|
8
|
+
type EmoteSize = "1" | "2" | "4";
|
|
9
|
+
/**
|
|
10
|
+
* URL-адреса эмоута в разных размерах
|
|
11
|
+
*/
|
|
12
|
+
interface EmoteUrls {
|
|
13
|
+
"1": string;
|
|
14
|
+
"2": string;
|
|
15
|
+
"4": string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Владелец эмоута
|
|
19
|
+
*/
|
|
20
|
+
interface EmoteOwner {
|
|
21
|
+
_id: number;
|
|
22
|
+
name: string;
|
|
23
|
+
display_name: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Эмоут FrankerFaceZ
|
|
27
|
+
*/
|
|
28
|
+
interface Emote {
|
|
29
|
+
id: number;
|
|
30
|
+
name: string;
|
|
31
|
+
height: number;
|
|
32
|
+
width: number;
|
|
33
|
+
public: boolean;
|
|
34
|
+
hidden: boolean;
|
|
35
|
+
modifier: boolean;
|
|
36
|
+
modifier_flags: number;
|
|
37
|
+
offset: string | null;
|
|
38
|
+
margins: string | null;
|
|
39
|
+
css: string | null;
|
|
40
|
+
owner: EmoteOwner;
|
|
41
|
+
urls: EmoteUrls;
|
|
42
|
+
status: number;
|
|
43
|
+
usage_count: number;
|
|
44
|
+
created_at: string;
|
|
45
|
+
last_updated: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Набор эмоутов
|
|
49
|
+
*/
|
|
50
|
+
interface EmoteSet {
|
|
51
|
+
id: number;
|
|
52
|
+
_type: number;
|
|
53
|
+
icon: string | null;
|
|
54
|
+
title: string;
|
|
55
|
+
css: string | null;
|
|
56
|
+
emoticons: Emote[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Информация о пользователе
|
|
60
|
+
*/
|
|
61
|
+
interface User {
|
|
62
|
+
id: number;
|
|
63
|
+
name: string;
|
|
64
|
+
display_name: string;
|
|
65
|
+
avatar: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Информация о комнате пользователя
|
|
69
|
+
*/
|
|
70
|
+
interface Room {
|
|
71
|
+
_id: number;
|
|
72
|
+
twitch_id: number;
|
|
73
|
+
youtube_id: string | null;
|
|
74
|
+
id: string;
|
|
75
|
+
is_group: boolean;
|
|
76
|
+
display_name: string;
|
|
77
|
+
set: number;
|
|
78
|
+
moderator_badge: string | null;
|
|
79
|
+
vip_badge: string | null;
|
|
80
|
+
mod_urls: Record<string, string> | null;
|
|
81
|
+
[key: string]: unknown;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Ответ API для комнаты пользователя
|
|
85
|
+
*/
|
|
86
|
+
interface RoomResponse {
|
|
87
|
+
room: Room;
|
|
88
|
+
sets: Record<string, EmoteSet>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Ответ API для глобальных эмоутов
|
|
92
|
+
*/
|
|
93
|
+
interface GlobalEmotesResponse {
|
|
94
|
+
sets: Record<string, EmoteSet>;
|
|
95
|
+
default_sets: number[];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Ответ API для конкретного эмоута
|
|
99
|
+
*/
|
|
100
|
+
interface EmoteResponse {
|
|
101
|
+
emote: Emote;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=frankerfacez.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frankerfacez.d.ts","sourceRoot":"","sources":["../../../../src/root/frankerfacez/types/frankerfacez.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,yBAAiB,YAAY,CAAC;IAC5B;;OAEG;IACH,KAAY,SAAS,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAExC;;OAEG;IACH,UAAiB,SAAS;QACxB,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;KACb;IAED;;OAEG;IACH,UAAiB,UAAU;QACzB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;KACtB;IAED;;OAEG;IACH,UAAiB,KAAK;QACpB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,OAAO,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QACnB,KAAK,EAAE,UAAU,CAAC;QAClB,IAAI,EAAE,SAAS,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB;IAED;;OAEG;IACH,UAAiB,QAAQ;QACvB,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QACnB,SAAS,EAAE,KAAK,EAAE,CAAC;KACpB;IAED;;OAEG;IACH,UAAiB,IAAI;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;KAChB;IAED;;OAEG;IACH,UAAiB,IAAI;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,OAAO,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;QACxC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB;IAED;;OAEG;IACH,UAAiB,YAAY;QAC3B,IAAI,EAAE,IAAI,CAAC;QACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;KAChC;IAED;;OAEG;IACH,UAAiB,oBAAoB;QACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB;IAED;;OAEG;IACH,UAAiB,aAAa;QAC5B,KAAK,EAAE,KAAK,CAAC;KACd;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/root/frankerfacez/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/root/frankerfacez/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/root/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(s){"use strict";const h=async t=>(await(await fetch(`https://7tv.io/v3/users/twitch/${t}`)).json()).emote_set.emotes,l=async()=>(await(await fetch("https://7tv.io/v3/emote-sets/global")).json()).emotes,u=t=>t.filter(e=>e.flags===1&&e.id),n=new Map,f=async(t,e)=>{const a=`user:${t}:${e}`;let o=n.get(a);return o||(o=(async()=>{const i=await fetch(`https://api.betterttv.net/3/${t}/${e}`);if(!i.ok)return{id:"",bots:[],avatar:"",channelEmotes:[],sharedEmotes:[]};const r=await i.json();return{...r,channelEmotes:r.channelEmotes??[],sharedEmotes:r.sharedEmotes??[]}})(),n.set(a,o),o)},E=async()=>{const t="global";let e=n.get(t);return e||(e=fetch("https://api.betterttv.net/3/cached/emotes/global").then(a=>a.json()),n.set(t,e),e)},c=t=>{const e=[];for(const a of Object.values(t))e.push(...a.emoticons||[]);return e},g=async t=>{try{const a=await(await fetch(`https://api.frankerfacez.com/v1/room/twitch/${t}`)).json();return c(a.sets)}catch{return[]}},b=async()=>{try{const e=await(await fetch("https://api.frankerfacez.com/v1/set/global")).json();return c(e.sets)}catch{return[]}};function p(t){return t.includes("cdn.frankerfacez.com")?t.replace("https:https:","https:"):t}var m=(t=>(t.Twitch="twitch",t.Youtube="youtube",t))(m||{});s.EmotesProvider=m,s.extractZeroWidthEmotes=u,s.fixFrankerFaceZDoubleHttps=p,s.get7TVGlobalEmoteSet=l,s.get7TVUserEmoteSet=h,s.getBetterTTVGlobalEmoteSet=E,s.getBetterTTVUserEmoteCacheResponse=f,s.getFrankerFaceZGlobalEmoteSet=b,s.getFrankerFaceZUserEmoteSet=g,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})})(this.WmakeEmotes=this.WmakeEmotes||{});
|
|
2
|
+
//# sourceMappingURL=index.iife.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.iife.js","sources":["../../src/root/7tv/set.ts","../../src/root/7tv/utils.ts","../../src/root/betterttv/set.ts","../../src/root/frankerfacez/set.ts","../../src/root/frankerfacez/utils.ts","../../src/root/common/enums/provider.ts"],"sourcesContent":["import type { SevenTV } from \"./types\";\r\n\r\nexport const get7TVUserEmoteSet = async (\r\n providerId: string,\r\n): Promise<SevenTV.Emote[]> => {\r\n const response = await fetch(`https://7tv.io/v3/users/twitch/${providerId}`);\r\n const data = await response.json();\r\n return data.emote_set.emotes;\r\n};\r\n\r\nexport const get7TVGlobalEmoteSet = async (): Promise<SevenTV.Emote[]> => {\r\n const emotesUrl = \"https://7tv.io/v3/emote-sets/global\";\r\n const response = await fetch(emotesUrl);\r\n const data = await response.json();\r\n return data.emotes;\r\n};\r\n","import type { SevenTV } from \"./types\";\r\n\r\nexport const extractZeroWidthEmotes = (\r\n emotes: SevenTV.Emote[],\r\n): SevenTV.Emote[] => emotes.filter((e) => e.flags === 1 && e.id);\r\n","import type { EmotesProvider } from \"../common\";\r\nimport type { BetterTTV } from \"./types\";\r\n\r\n/** Один запрос на URL — повторные вызовы получают тот же промис. */\r\nconst byKey = new Map<string, Promise<unknown>>();\r\n\r\nexport const getBetterTTVUserEmoteCacheResponse = async (\r\n provider: EmotesProvider,\r\n providerId: string,\r\n): Promise<BetterTTV.CachedUserResponse> => {\r\n const key = `user:${provider}:${providerId}`;\r\n let p = byKey.get(key);\r\n if (p) return p as Promise<BetterTTV.CachedUserResponse>;\r\n p = (async () => {\r\n const res = await fetch(\r\n `https://api.betterttv.net/3/${provider}/${providerId}`,\r\n );\r\n if (!res.ok) {\r\n return {\r\n id: \"\",\r\n bots: [],\r\n avatar: \"\",\r\n channelEmotes: [],\r\n sharedEmotes: [],\r\n };\r\n }\r\n const data = await res.json();\r\n return {\r\n ...data,\r\n channelEmotes: data.channelEmotes ?? [],\r\n sharedEmotes: data.sharedEmotes ?? [],\r\n };\r\n })();\r\n byKey.set(key, p);\r\n return p as Promise<BetterTTV.CachedUserResponse>;\r\n};\r\n\r\nexport const getBetterTTVGlobalEmoteSet = async (): Promise<\r\n BetterTTV.Emote[]\r\n> => {\r\n const key = \"global\";\r\n let p = byKey.get(key);\r\n if (p) return p as Promise<BetterTTV.Emote[]>;\r\n p = fetch(\"https://api.betterttv.net/3/cached/emotes/global\").then((r) =>\r\n r.json(),\r\n );\r\n byKey.set(key, p);\r\n return p as Promise<BetterTTV.Emote[]>;\r\n};\r\n","import type { FrankerFaceZ } from \"./types\";\r\n\r\n/**\r\n * Получить все эмоуты из наборов\r\n */\r\nconst getEmotesFromSets = (\r\n sets: Record<string, FrankerFaceZ.EmoteSet>,\r\n): FrankerFaceZ.Emote[] => {\r\n const emotes: FrankerFaceZ.Emote[] = [];\r\n for (const set of Object.values(sets)) {\r\n emotes.push(...(set.emoticons || []));\r\n }\r\n return emotes;\r\n};\r\n\r\n/**\r\n * Получить набор эмоутов пользователя FrankerFaceZ\r\n */\r\nexport const getFrankerFaceZUserEmoteSet = async (\r\n username: string,\r\n): Promise<FrankerFaceZ.Emote[]> => {\r\n try {\r\n const response = await fetch(\r\n `https://api.frankerfacez.com/v1/room/twitch/${username}`,\r\n );\r\n const data: FrankerFaceZ.RoomResponse = await response.json();\r\n return getEmotesFromSets(data.sets);\r\n } catch {\r\n return [];\r\n }\r\n};\r\n\r\n/**\r\n * Получить глобальные эмоуты FrankerFaceZ\r\n */\r\nexport const getFrankerFaceZGlobalEmoteSet = async (): Promise<\r\n FrankerFaceZ.Emote[]\r\n> => {\r\n try {\r\n const response = await fetch(\"https://api.frankerfacez.com/v1/set/global\");\r\n const data: FrankerFaceZ.GlobalEmotesResponse = await response.json();\r\n return getEmotesFromSets(data.sets);\r\n } catch {\r\n return [];\r\n }\r\n};\r\n","export function fixFrankerFaceZDoubleHttps(url: string): string {\r\n if (url.includes(\"cdn.frankerfacez.com\")) {\r\n return url.replace(\"https:https:\", \"https:\");\r\n }\r\n return url;\r\n }","export enum EmotesProvider {\r\n Twitch = \"twitch\",\r\n Youtube = \"youtube\",\r\n}\r\n"],"names":["get7TVUserEmoteSet","providerId","get7TVGlobalEmoteSet","extractZeroWidthEmotes","emotes","byKey","getBetterTTVUserEmoteCacheResponse","provider","key","p","res","data","getBetterTTVGlobalEmoteSet","r","getEmotesFromSets","sets","set","getFrankerFaceZUserEmoteSet","username","getFrankerFaceZGlobalEmoteSet","fixFrankerFaceZDoubleHttps","url","EmotesProvider"],"mappings":"0BAEO,MAAMA,EAAqB,MAChCC,IAGa,MADI,MAAM,MAAM,kCAAkCA,CAAU,EAAE,GAC/C,KAAA,GAChB,UAAU,OAGXC,EAAuB,UAGrB,MADI,MAAM,MADL,qCACoB,GACV,KAAA,GAChB,OCZDC,EACXC,GACoBA,EAAO,OAAQ,GAAM,EAAE,QAAU,GAAK,EAAE,EAAE,ECA1DC,MAAY,IAELC,EAAqC,MAChDC,EACAN,IAC0C,CAC1C,MAAMO,EAAM,QAAQD,CAAQ,IAAIN,CAAU,GAC1C,IAAIQ,EAAIJ,EAAM,IAAIG,CAAG,EACrB,OAAIC,IACJA,GAAK,SAAY,CACf,MAAMC,EAAM,MAAM,MAChB,+BAA+BH,CAAQ,IAAIN,CAAU,EAAA,EAEvD,GAAI,CAACS,EAAI,GACP,MAAO,CACL,GAAI,GACJ,KAAM,CAAA,EACN,OAAQ,GACR,cAAe,CAAA,EACf,aAAc,CAAA,CAAC,EAGnB,MAAMC,EAAO,MAAMD,EAAI,KAAA,EACvB,MAAO,CACL,GAAGC,EACH,cAAeA,EAAK,eAAiB,CAAA,EACrC,aAAcA,EAAK,cAAgB,CAAA,CAAC,CAExC,GAAA,EACAN,EAAM,IAAIG,EAAKC,CAAC,EACTA,EACT,EAEaG,EAA6B,SAErC,CACH,MAAMJ,EAAM,SACZ,IAAIC,EAAIJ,EAAM,IAAIG,CAAG,EACrB,OAAIC,IACJA,EAAI,MAAM,kDAAkD,EAAE,KAAMI,GAClEA,EAAE,KAAA,CAAK,EAETR,EAAM,IAAIG,EAAKC,CAAC,EACTA,EACT,EC3CMK,EACJC,GACyB,CACzB,MAAMX,EAA+B,CAAA,EACrC,UAAWY,KAAO,OAAO,OAAOD,CAAI,EAClCX,EAAO,KAAK,GAAIY,EAAI,WAAa,CAAA,CAAG,EAEtC,OAAOZ,CACT,EAKaa,EAA8B,MACzCC,GACkC,CAClC,GAAI,CAIF,MAAMP,EAAkC,MAHvB,MAAM,MACrB,+CAA+CO,CAAQ,EAAA,GAEF,KAAA,EACvD,OAAOJ,EAAkBH,EAAK,IAAI,CACpC,MAAQ,CACN,MAAO,CAAA,CACT,CACF,EAKaQ,EAAgC,SAExC,CACH,GAAI,CAEF,MAAMR,EAA0C,MAD/B,MAAM,MAAM,4CAA4C,GACV,KAAA,EAC/D,OAAOG,EAAkBH,EAAK,IAAI,CACpC,MAAQ,CACN,MAAO,CAAA,CACT,CACF,EC7CO,SAASS,EAA2BC,EAAqB,CAC5D,OAAIA,EAAI,SAAS,sBAAsB,EAC9BA,EAAI,QAAQ,eAAgB,QAAQ,EAEtCA,CACT,CCLK,IAAKC,GAAAA,IACVA,EAAA,OAAS,SACTA,EAAA,QAAU,UAFAA,IAAAA,GAAA,CAAA,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { E as o, e as s, a as c, g as n, c as m, b as E, f as p, d as f } from "../provider-CDtB3U-Z.js";
|
|
2
|
+
function t(e) {
|
|
3
|
+
return e.includes("cdn.frankerfacez.com") ? e.replace("https:https:", "https:") : e;
|
|
4
|
+
}
|
|
5
|
+
export {
|
|
6
|
+
o as EmotesProvider,
|
|
7
|
+
s as extractZeroWidthEmotes,
|
|
8
|
+
t as fixFrankerFaceZDoubleHttps,
|
|
9
|
+
c as get7TVGlobalEmoteSet,
|
|
10
|
+
n as get7TVUserEmoteSet,
|
|
11
|
+
m as getBetterTTVGlobalEmoteSet,
|
|
12
|
+
E as getBetterTTVUserEmoteCacheResponse,
|
|
13
|
+
p as getFrankerFaceZGlobalEmoteSet,
|
|
14
|
+
f as getFrankerFaceZUserEmoteSet
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/root/frankerfacez/utils.ts"],"sourcesContent":["export function fixFrankerFaceZDoubleHttps(url: string): string {\r\n if (url.includes(\"cdn.frankerfacez.com\")) {\r\n return url.replace(\"https:https:\", \"https:\");\r\n }\r\n return url;\r\n }"],"names":["fixFrankerFaceZDoubleHttps","url"],"mappings":";AAAO,SAASA,EAA2BC,GAAqB;AAC5D,SAAIA,EAAI,SAAS,sBAAsB,IAC9BA,EAAI,QAAQ,gBAAgB,QAAQ,IAEtCA;AACT;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@allior/wmake-emotes",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Emote providers: 7TV, BetterTTV, FrankerFaceZ.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"types": "./dist/root/index.d.ts",
|
|
7
|
+
"main": "./dist/root/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/root/index.d.ts",
|
|
11
|
+
"import": "./dist/root/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./react": {
|
|
14
|
+
"types": "./dist/react/index.d.ts",
|
|
15
|
+
"import": "./dist/react/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./src/*": "./src/*"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "rimraf dist && vite build && cross-env VITE_IIFE_ENTRY=root vite build --config vite.iife.config.ts && cross-env VITE_IIFE_ENTRY=react vite build --config vite.iife.config.ts && tsc -p tsconfig.types.json",
|
|
26
|
+
"build:iife": "cross-env VITE_IIFE_ENTRY=root vite build --config vite.iife.config.ts && cross-env VITE_IIFE_ENTRY=react vite build --config vite.iife.config.ts",
|
|
27
|
+
"clean": "rimraf dist",
|
|
28
|
+
"prepublishOnly": "pnpm run build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [],
|
|
31
|
+
"author": "An1by",
|
|
32
|
+
"license": "ISC",
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"cross-env": "^10.1.0",
|
|
35
|
+
"rimraf": "^6.0.1"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"react": "^19.2.0",
|
|
39
|
+
"react-dom": "^19.2.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useEmotes";
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EmotesProvider,
|
|
3
|
+
extractZeroWidthEmotes,
|
|
4
|
+
get7TVGlobalEmoteSet,
|
|
5
|
+
get7TVUserEmoteSet,
|
|
6
|
+
getBetterTTVGlobalEmoteSet,
|
|
7
|
+
getBetterTTVUserEmoteCacheResponse,
|
|
8
|
+
getFrankerFaceZGlobalEmoteSet,
|
|
9
|
+
getFrankerFaceZUserEmoteSet,
|
|
10
|
+
type BetterTTV,
|
|
11
|
+
type EmoteReference,
|
|
12
|
+
type FrankerFaceZ,
|
|
13
|
+
type SevenTV,
|
|
14
|
+
} from "@/root";
|
|
15
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
16
|
+
|
|
17
|
+
const DEFAULT_PROVIDERS: EmotesProvider[] = [EmotesProvider.Twitch];
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
username?: string;
|
|
21
|
+
providerId?: string;
|
|
22
|
+
providers?: EmotesProvider[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const useEmotes = ({
|
|
26
|
+
username,
|
|
27
|
+
providerId,
|
|
28
|
+
providers = DEFAULT_PROVIDERS,
|
|
29
|
+
}: Props) => {
|
|
30
|
+
const [sevenTvEmotes, setSevenTv] = useState<SevenTV.Emote[]>([]);
|
|
31
|
+
const [zeroWidthEmotes, setZeroWidthEmotes] = useState<EmoteReference[]>([]);
|
|
32
|
+
const [frankerfacezEmotes, setFrankerFacezEmotes] = useState<
|
|
33
|
+
FrankerFaceZ.Emote[]
|
|
34
|
+
>([]);
|
|
35
|
+
const [betterttvEmotes, setBetterttvEmotes] = useState<BetterTTV.Emote[]>([]);
|
|
36
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
37
|
+
|
|
38
|
+
const loadedRef = useRef(false);
|
|
39
|
+
|
|
40
|
+
const loadEmotes = useCallback(async () => {
|
|
41
|
+
if (providers.length === 0) {
|
|
42
|
+
setIsLoaded(true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
setIsLoaded(false);
|
|
46
|
+
try {
|
|
47
|
+
const betterttvEmotes: BetterTTV.Emote[] =
|
|
48
|
+
await getBetterTTVGlobalEmoteSet();
|
|
49
|
+
if (providerId) {
|
|
50
|
+
for (const provider of providers) {
|
|
51
|
+
try {
|
|
52
|
+
const cache = await getBetterTTVUserEmoteCacheResponse(
|
|
53
|
+
provider,
|
|
54
|
+
providerId,
|
|
55
|
+
);
|
|
56
|
+
betterttvEmotes.push(
|
|
57
|
+
...(cache.channelEmotes ?? []),
|
|
58
|
+
...(cache.sharedEmotes ?? []),
|
|
59
|
+
);
|
|
60
|
+
} catch {
|
|
61
|
+
// 404 or network error
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (providers.includes(EmotesProvider.Twitch)) {
|
|
67
|
+
const sevenTv = await get7TVGlobalEmoteSet();
|
|
68
|
+
if (providerId) {
|
|
69
|
+
sevenTv.push(...(await get7TVUserEmoteSet(providerId)));
|
|
70
|
+
}
|
|
71
|
+
setZeroWidthEmotes(extractZeroWidthEmotes(sevenTv));
|
|
72
|
+
|
|
73
|
+
const frankerfacez = await getFrankerFaceZGlobalEmoteSet();
|
|
74
|
+
if (username) {
|
|
75
|
+
frankerfacez.push(...(await getFrankerFaceZUserEmoteSet(username)));
|
|
76
|
+
}
|
|
77
|
+
setFrankerFacezEmotes(frankerfacez);
|
|
78
|
+
setSevenTv(sevenTv);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
setBetterttvEmotes(betterttvEmotes);
|
|
82
|
+
} finally {
|
|
83
|
+
setIsLoaded(true);
|
|
84
|
+
}
|
|
85
|
+
}, [username, providerId, providers]);
|
|
86
|
+
|
|
87
|
+
const isZeroWidthEmote = (emote: EmoteReference) =>
|
|
88
|
+
zeroWidthEmotes.includes(emote);
|
|
89
|
+
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (loadedRef.current) return;
|
|
92
|
+
loadedRef.current = true;
|
|
93
|
+
void loadEmotes();
|
|
94
|
+
}, [loadEmotes]);
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
BetterTTVEmotes: betterttvEmotes,
|
|
98
|
+
FrankerFaceZEmotes: frankerfacezEmotes,
|
|
99
|
+
SevenTVEmotes: sevenTvEmotes,
|
|
100
|
+
SevenTVZeroWidthEmotes: zeroWidthEmotes,
|
|
101
|
+
isLoaded,
|
|
102
|
+
isZeroWidthEmote,
|
|
103
|
+
reloadEmotes: loadEmotes,
|
|
104
|
+
};
|
|
105
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SevenTV } from "./types";
|
|
2
|
+
|
|
3
|
+
export const get7TVUserEmoteSet = async (
|
|
4
|
+
providerId: string,
|
|
5
|
+
): Promise<SevenTV.Emote[]> => {
|
|
6
|
+
const response = await fetch(`https://7tv.io/v3/users/twitch/${providerId}`);
|
|
7
|
+
const data = await response.json();
|
|
8
|
+
return data.emote_set.emotes;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const get7TVGlobalEmoteSet = async (): Promise<SevenTV.Emote[]> => {
|
|
12
|
+
const emotesUrl = "https://7tv.io/v3/emote-sets/global";
|
|
13
|
+
const response = await fetch(emotesUrl);
|
|
14
|
+
const data = await response.json();
|
|
15
|
+
return data.emotes;
|
|
16
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Типы для событий 7TV API, связанных с эмоутами
|
|
3
|
+
*/
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
5
|
+
export namespace SevenTV {
|
|
6
|
+
/**
|
|
7
|
+
* Формат файла эмоута
|
|
8
|
+
*/
|
|
9
|
+
export type EmoteFileFormat = "WEBP" | "AVIF" | "GIF";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Платформа подключения
|
|
13
|
+
*/
|
|
14
|
+
export type ConnectionPlatform = "TWITCH" | "DISCORD";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Состояние эмоута
|
|
18
|
+
*/
|
|
19
|
+
export type EmoteState = "PERSONAL" | "LISTED" | "GLOBAL";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Файл эмоута
|
|
23
|
+
*/
|
|
24
|
+
export interface EmoteFile {
|
|
25
|
+
name: string;
|
|
26
|
+
static_name: string;
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
frame_count: number;
|
|
30
|
+
size: number;
|
|
31
|
+
format: EmoteFileFormat;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Хост эмоута (CDN информация)
|
|
36
|
+
*/
|
|
37
|
+
export interface EmoteHost {
|
|
38
|
+
url: string;
|
|
39
|
+
files: EmoteFile[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Стиль пользователя (может быть пустым объектом)
|
|
44
|
+
*/
|
|
45
|
+
export type UserStyle = Record<string, unknown>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Подключение к платформе
|
|
49
|
+
*/
|
|
50
|
+
export interface Connection {
|
|
51
|
+
id: string;
|
|
52
|
+
platform: ConnectionPlatform;
|
|
53
|
+
username: string;
|
|
54
|
+
display_name: string;
|
|
55
|
+
linked_at: number;
|
|
56
|
+
emote_capacity: number;
|
|
57
|
+
emote_set_id: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Владелец эмоута
|
|
62
|
+
*/
|
|
63
|
+
export interface EmoteOwner {
|
|
64
|
+
id: string;
|
|
65
|
+
username: string;
|
|
66
|
+
display_name: string;
|
|
67
|
+
avatar_url: string;
|
|
68
|
+
style: UserStyle;
|
|
69
|
+
role_ids: string[];
|
|
70
|
+
connections: Connection[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Данные эмоута
|
|
75
|
+
*/
|
|
76
|
+
export interface EmoteData {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
flags: number;
|
|
80
|
+
lifecycle: number;
|
|
81
|
+
state: EmoteState[];
|
|
82
|
+
listed: boolean;
|
|
83
|
+
animated: boolean;
|
|
84
|
+
owner: EmoteOwner;
|
|
85
|
+
host: EmoteHost;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Событие эмоута из 7TV API
|
|
90
|
+
*/
|
|
91
|
+
export interface Emote {
|
|
92
|
+
id: string;
|
|
93
|
+
name: string;
|
|
94
|
+
flags: number;
|
|
95
|
+
timestamp: number;
|
|
96
|
+
actor_id: string;
|
|
97
|
+
data: EmoteData;
|
|
98
|
+
origin_id: string | null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { EmotesProvider } from "../common";
|
|
2
|
+
import type { BetterTTV } from "./types";
|
|
3
|
+
|
|
4
|
+
/** Один запрос на URL — повторные вызовы получают тот же промис. */
|
|
5
|
+
const byKey = new Map<string, Promise<unknown>>();
|
|
6
|
+
|
|
7
|
+
export const getBetterTTVUserEmoteCacheResponse = async (
|
|
8
|
+
provider: EmotesProvider,
|
|
9
|
+
providerId: string,
|
|
10
|
+
): Promise<BetterTTV.CachedUserResponse> => {
|
|
11
|
+
const key = `user:${provider}:${providerId}`;
|
|
12
|
+
let p = byKey.get(key);
|
|
13
|
+
if (p) return p as Promise<BetterTTV.CachedUserResponse>;
|
|
14
|
+
p = (async () => {
|
|
15
|
+
const res = await fetch(
|
|
16
|
+
`https://api.betterttv.net/3/${provider}/${providerId}`,
|
|
17
|
+
);
|
|
18
|
+
if (!res.ok) {
|
|
19
|
+
return {
|
|
20
|
+
id: "",
|
|
21
|
+
bots: [],
|
|
22
|
+
avatar: "",
|
|
23
|
+
channelEmotes: [],
|
|
24
|
+
sharedEmotes: [],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const data = await res.json();
|
|
28
|
+
return {
|
|
29
|
+
...data,
|
|
30
|
+
channelEmotes: data.channelEmotes ?? [],
|
|
31
|
+
sharedEmotes: data.sharedEmotes ?? [],
|
|
32
|
+
};
|
|
33
|
+
})();
|
|
34
|
+
byKey.set(key, p);
|
|
35
|
+
return p as Promise<BetterTTV.CachedUserResponse>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const getBetterTTVGlobalEmoteSet = async (): Promise<
|
|
39
|
+
BetterTTV.Emote[]
|
|
40
|
+
> => {
|
|
41
|
+
const key = "global";
|
|
42
|
+
let p = byKey.get(key);
|
|
43
|
+
if (p) return p as Promise<BetterTTV.Emote[]>;
|
|
44
|
+
p = fetch("https://api.betterttv.net/3/cached/emotes/global").then((r) =>
|
|
45
|
+
r.json(),
|
|
46
|
+
);
|
|
47
|
+
byKey.set(key, p);
|
|
48
|
+
return p as Promise<BetterTTV.Emote[]>;
|
|
49
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Типы для BetterTTV API
|
|
3
|
+
*/
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
5
|
+
export namespace BetterTTV {
|
|
6
|
+
/**
|
|
7
|
+
* Тип изображения эмоута
|
|
8
|
+
*/
|
|
9
|
+
export type ImageType = "png" | "gif" | "webp";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Пользователь, создавший общий эмоут
|
|
13
|
+
*/
|
|
14
|
+
export interface SharedEmoteUser {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
displayName: string;
|
|
18
|
+
providerId: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Универсальный тип эмоута BetterTTV
|
|
23
|
+
* Может иметь либо userId, либо user объект
|
|
24
|
+
*/
|
|
25
|
+
export interface Emote {
|
|
26
|
+
id: string;
|
|
27
|
+
code: string;
|
|
28
|
+
imageType: ImageType;
|
|
29
|
+
animated: boolean;
|
|
30
|
+
userId?: string;
|
|
31
|
+
user?: SharedEmoteUser;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Эмоут канала
|
|
36
|
+
* @deprecated Используйте Emote
|
|
37
|
+
*/
|
|
38
|
+
export type ChannelEmote = Emote & { userId: string };
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Глобальный эмоут
|
|
42
|
+
* @deprecated Используйте Emote
|
|
43
|
+
*/
|
|
44
|
+
export type GlobalEmote = Emote & { userId: string };
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Общий эмоут
|
|
48
|
+
* @deprecated Используйте Emote
|
|
49
|
+
*/
|
|
50
|
+
export type SharedEmote = Emote & { user: SharedEmoteUser };
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Ответ API для кэшированных данных пользователя
|
|
54
|
+
*/
|
|
55
|
+
export interface CachedUserResponse {
|
|
56
|
+
id: string;
|
|
57
|
+
bots: string[];
|
|
58
|
+
avatar: string;
|
|
59
|
+
channelEmotes: Emote[];
|
|
60
|
+
sharedEmotes: Emote[];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./provider";
|