ffz, bttv, twitch APIs init

This commit is contained in:
3zachm 2023-01-21 02:36:29 -08:00
parent 37636cd583
commit 18137632f6
9 changed files with 972 additions and 24 deletions

58
misc/BTTVAPI.tsx Normal file
View file

@ -0,0 +1,58 @@
import type RedisInstance from "ioredis";
async function applyCache(
redis: RedisInstance,
key: string,
query: string,
cacheTime: number
) {
if (await redis.get(key)) {
return JSON.parse((await redis.get(key)) as string);
} else {
const response = await fetchEndpoint(redis, query);
if (response != null) {
await redis.set(key, JSON.stringify(response), "EX", cacheTime);
}
return response;
}
}
async function fetchEndpoint(redis: RedisInstance, query: string) {
if (await redis.get("BTTV.RATE_LIMIT")) {
await new Promise((resolve) => setTimeout(resolve, 1000));
} else {
await redis.set("BTTV.RATE_LIMIT", "1", "EX", 1);
}
const requestHeaders = new Headers();
requestHeaders.append("Content-Type", "application/json");
requestHeaders.append("User-Agent", "toffee-web/indev");
const response = await fetch(query, {
headers: requestHeaders,
});
const json = await response.json();
return json;
}
async function getGlobalEmotes(redis: RedisInstance) {
return await applyCache(
redis,
"BTTV.GLOBAL_EMOTES",
"https://api.betterttv.net/3/cached/emotes/global",
3600
);
}
async function getUserByID(redis: RedisInstance, channelID: string) {
return await applyCache(
redis,
`BTTV.CHANNEL_EMOTES.${channelID}`,
`https://api.betterttv.net/3/cached/users/twitch/${channelID}`,
3600
);
}
export { getGlobalEmotes, getUserByID };

58
misc/FFZAPI.tsx Normal file
View file

@ -0,0 +1,58 @@
import type RedisInstance from "ioredis";
async function applyCache(
redis: RedisInstance,
key: string,
query: string,
cacheTime: number
) {
if (await redis.get(key)) {
return JSON.parse((await redis.get(key)) as string);
} else {
const response = await fetchEndpoint(redis, query);
if (response != null) {
await redis.set(key, JSON.stringify(response), "EX", cacheTime);
}
return response;
}
}
async function fetchEndpoint(redis: RedisInstance, query: string) {
if (await redis.get("FFZ.RATE_LIMIT")) {
await new Promise((resolve) => setTimeout(resolve, 1000));
} else {
await redis.set("FFZ.RATE_LIMIT", "1", "EX", 1);
}
const requestHeaders = new Headers();
requestHeaders.append("Content-Type", "application/json");
requestHeaders.append("User-Agent", "toffee-web/indev");
const response = await fetch(query, {
headers: requestHeaders,
});
const json = await response.json();
return json;
}
async function getGlobalEmotes(redis: RedisInstance) {
return await applyCache(
redis,
"FFZ.GLOBAL_EMOTES",
"https://api.frankerfacez.com/v1/set/global",
3600
);
}
async function getEmoteSet(redis: RedisInstance, setID: string) {
return await applyCache(
redis,
`FFZ.EMOTE_SET.${setID}`,
`https://api.frankerfacez.com/v1/set/${setID}`,
3600
);
}
export { getGlobalEmotes, getEmoteSet };

View file

@ -3,7 +3,13 @@ const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
domains: ["cdn.discordapp.com", "static-cdn.jtvnw.net", "cdn.7tv.app"],
domains: [
"cdn.discordapp.com",
"static-cdn.jtvnw.net",
"cdn.7tv.app",
"cdn.betterttv.net",
"cdn.frankerfacez.com",
],
},
};

30
pages/api/bttv/emotes.ts Normal file
View file

@ -0,0 +1,30 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { createRedisInstance } from "../../../misc/redis";
import { getUserByID, getGlobalEmotes } from "../../../misc/BTTVAPI";
type Data = {
[key: string]: any;
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const redis = createRedisInstance();
try {
const channel = req.query.c
? (await getUserByID(redis, req.query.c as string)).channelEmotes
: undefined;
const global = await getGlobalEmotes(redis);
redis.quit();
res.status(200).json({ channel, global });
} catch (e) {
console.log(e);
res
.status(500)
.json({
error: { message: "BTTV or internal API is down", code: 10200 },
});
}
}

View file

@ -335,6 +335,470 @@ const fakePrices: { [key: string]: number } = {
yoshiJAM: 137,
zSpooky: 350,
zyzzBass: 680,
// bttv
":tf:": 325,
CiGrip: 697,
DatSauce: 903,
ForeverAlone: 663,
GabeN: 497,
HailHelix: 447,
ShoopDaWhoop: 502,
"M&Mjc": 196,
bttvNice: 558,
TwaT: 176,
WatChuSay: 947,
tehPoleCat: 611,
TaxiBro: 527,
BroBalt: 384,
CandianRage: 431,
"D:": 192,
VisLaud: 966,
KaRappa: 247,
FishMoley: 276,
Hhhehehe: 945,
KKona: 596,
PoleDoge: 485,
sosGame: 473,
CruW: 591,
RarePepe: 866,
haHAA: 979,
FeelsBirthdayMan: 536,
RonSmug: 776,
KappaCool: 777,
FeelsBadMan: 483,
bUrself: 934,
ConcernDoge: 520,
FeelsGoodMan: 202,
FireSpeed: 82,
NaM: 412,
SourPls: 231,
FeelsSnowMan: 639,
FeelsSnowyMan: 929,
LuL: 603,
SoSnowy: 647,
SaltyCorn: 486,
monkaS: 189,
VapeNation: 570,
ariW: 926,
notsquishY: 438,
FeelsAmazingMan: 92,
DuckerZ: 417,
IceCold: 21,
SqShy: 84,
Wowee: 533,
WubTF: 494,
cvR: 913,
cvL: 337,
cvHazmat: 599,
cvMask: 423,
DogChamp: 947,
annytfBanana: 730,
annySaur: 236,
annytfBlink: 108,
AnnySilly: 469,
annyBlankies: 747,
annyHop: 861,
annyHopper: 941,
annyTeaTime: 398,
annyD: 530,
annyDVibe: 907,
annyDHyper: 451,
annyDFast: 117,
KissaVei: 158,
Annie: 597,
annyPls: 91,
// ffz
monkaW: 969,
"5Head": 750,
Prayge: 434,
PauseChamp: 903,
Pepega: 817,
TWINGO: 256,
PepeHands: 190,
monkaTOS: 146,
monkaHmm: 549,
Dolan: 536,
SmileW: 166,
ABABABABA: 95,
peepoBlanket: 798,
pikachuS: 715,
AYAYAHyper: 164,
YEP: 371,
widepeepoBlanket: 100,
HandsUp: 684,
peepoSad: 167,
HyperKorone: 456,
AYAYA: 503,
forsenCD: 344,
Hahaa: 291,
LULW: 463,
WICKED: 133,
EZY: 494,
OkayChamp: 950,
PepegaPig: 217,
POGGIES: 487,
peepoWTF: 734,
ConfusedCat: 508,
PainPeko: 433,
KKrikey: 235,
COPIUM: 582,
Madge: 595,
Catge: 811,
stopbeingMean: 522,
NOPE: 262,
OMEGALUL: 648,
AYAYAY: 725,
PogO: 548,
Sadge: 41,
PepegaPhone: 800,
Widega: 543,
ZrehplaR: 23,
YooHoo: 617,
ManChicken: 588,
BeanieHipster: 480,
CatBag: 253,
ZreknarF: 143,
LilZ: 952,
ZliL: 662,
LaterSooner: 375,
BORT: 738,
OBOY: 942,
OiMinna: 354,
AndKnuckles: 828,
// twitch
annytfRaid: 493,
annytfNote: 893,
annytfPout: 971,
annytfAyaya: 180,
annytfPika: 328,
annytfPrime: 830,
annytfLewd: 314,
annytfRave: 615,
annytfLurk: 898,
annytfPog: 958,
annytfD: 759,
annytfCry: 399,
annytfHeart: 472,
annytfSad: 390,
annytfMelt: 157,
annytfWICKED: 94,
annytfCheer: 780,
annytfREEE: 272,
annytfLUL: 122,
annytfScuffed: 318,
annytfAngy: 677,
annytfHug: 826,
annytfCool: 121,
annytfPain: 16,
annytfBonk: 949,
annytfKnuckles: 182,
annytfSigh: 220,
annytfWoah: 582,
annytfBite: 580,
annytfSilly: 837,
annytfWow: 381,
annytfPray: 438,
annytfPats: 410,
annytfGasm: 822,
annytfSit: 39,
annytfFlower: 137,
annytfLeave: 819,
annytfGamba: 847,
annytfLuv: 483,
annytfHarucchiHug: 142,
annytfAnnE: 324,
annytfDinkDonk: 380,
annytfAhriluv: 232,
annytfW: 101,
annytfWoke: 145,
annytfBedge: 409,
annytfBusiness: 142,
annytfPeek: 98,
annytfDonowall: 581,
NewRecord: 836,
Awwdible: 794,
Lechonk: 567,
Getcamped: 378,
SUBprise: 580,
FallHalp: 95,
FallCry: 450,
FallWinning: 261,
MechaRobot: 984,
ImTyping: 993,
Shush: 506,
MyAvatar: 41,
PizzaTime: 330,
LaundryBasket: 852,
ModLove: 683,
PotFriend: 605,
Jebasted: 72,
PogBones: 761,
PoroSad: 357,
KEKHeim: 290,
CaitlynS: 874,
HarleyWink: 244,
WhySoSerious: 705,
DarkKnight: 101,
FamilyMan: 278,
RyuChamp: 814,
HungryPaimon: 920,
TransgenderPride: 409,
PansexualPride: 707,
NonbinaryPride: 866,
LesbianPride: 763,
IntersexPride: 136,
GenderFluidPride: 73,
GayPride: 471,
BisexualPride: 163,
AsexualPride: 533,
PogChamp: 898,
GlitchNRG: 877,
GlitchLit: 45,
StinkyGlitch: 697,
GlitchCat: 208,
FootGoal: 542,
FootYellow: 297,
FootBall: 679,
BlackLivesMatter: 637,
ExtraLife: 394,
VirtualHug: 452,
"R-)": 779,
"R)": 242,
";-p": 911,
";p": 168,
";-P": 584,
";P": 571,
":-p": 758,
":p": 709,
":-P": 137,
":P": 602,
";-)": 349,
";)": 745,
":-\\": 30,
":\\": 725,
":-/": 403,
":/": 187,
"<3": 51,
":-o": 622,
":o": 384,
":-O": 994,
":O": 629,
"8-)": 881,
"B-)": 390,
"B)": 489,
"o.o": 570,
o_o: 738,
"o.O": 287,
o_O: 168,
"O.O": 452,
O_O: 33,
"O.o": 187,
O_o: 513,
":-Z": 729,
":Z": 762,
":-z": 658,
":z": 526,
":-|": 978,
":|": 224,
">(": 141,
":-D": 699,
":D": 926,
":-(": 864,
":-)": 141,
BOP: 826,
SingsNote: 46,
SingsMic: 347,
TwitchSings: 419,
SoonerLater: 187,
HolidayTree: 822,
HolidaySanta: 340,
HolidayPresent: 830,
HolidayLog: 251,
HolidayCookie: 105,
GunRun: 899,
PixelBob: 829,
FBPenalty: 123,
FBChallenge: 645,
FBCatch: 769,
FBBlock: 284,
FBSpiral: 633,
FBPass: 365,
FBRun: 688,
MaxLOL: 17,
TwitchRPG: 258,
PinkMercy: 369,
MercyWing2: 2,
MercyWing1: 546,
PartyHat: 581,
EarthDay: 649,
TombRaid: 904,
PopCorn: 485,
FBtouchdown: 621,
TPFufun: 321,
TwitchVotes: 858,
DarkMode: 90,
HSWP: 729,
HSCheers: 802,
PowerUpL: 88,
PowerUpR: 616,
LUL: 958,
EntropyWins: 639,
TPcrunchyroll: 286,
TwitchUnity: 349,
Squid4: 548,
Squid3: 113,
Squid2: 768,
Squid1: 649,
CrreamAwk: 186,
CarlSmile: 822,
TwitchLit: 125,
TehePelo: 124,
TearGlove: 354,
SabaPing: 94,
PunOko: 145,
KonCha: 656,
Kappu: 597,
InuyoFace: 434,
BigPhish: 169,
BegWan: 621,
ThankEgg: 391,
MorphinTime: 106,
TheIlluminati: 531,
TBAngel: 925,
MVGame: 873,
NinjaGrumpy: 345,
PartyTime: 773,
RlyTho: 830,
UWot: 265,
YouDontSay: 744,
KAPOW: 757,
ItsBoshyTime: 605,
CoolStoryBob: 193,
TriHard: 121,
SuperVinlin: 500,
FreakinStinkin: 860,
Poooound: 411,
CurseLit: 318,
BatChest: 642,
BrainSlug: 48,
PrimeMe: 619,
StrawBeary: 813,
RaccAttack: 172,
UncleNox: 583,
WTRuck: 118,
TooSpicy: 761,
Jebaited: 363,
DogFace: 911,
BlargNaut: 148,
TakeNRG: 27,
GivePLZ: 581,
imGlitch: 514,
pastaThat: 48,
copyThis: 426,
UnSane: 97,
DatSheffy: 289,
TheTarFu: 818,
PicoMause: 570,
TinyFace: 31,
DxCat: 538,
RuleFive: 903,
VoteNay: 113,
VoteYea: 223,
PJSugar: 11,
DoritosChip: 187,
OpieOP: 977,
FutureMan: 893,
ChefFrank: 481,
StinkyCheese: 419,
NomNom: 162,
SmoocherZ: 863,
cmonBruh: 93,
KappaWealth: 776,
MikeHogu: 497,
VoHiYo: 646,
KomodoHype: 295,
SeriousSloth: 379,
OSFrog: 807,
OhMyDog: 124,
KappaClaus: 209,
KappaRoss: 298,
MingLee: 338,
SeemsGood: 89,
twitchRaid: 258,
bleedPurple: 949,
duDudu: 442,
riPepperonis: 192,
NotLikeThis: 838,
DendiFace: 534,
CoolCat: 995,
KappaPride: 915,
ShadyLulu: 372,
ArgieB8: 267,
CorgiDerp: 511,
PraiseIt: 557,
TTours: 122,
mcaT: 154,
NotATK: 388,
HeyGuys: 453,
Mau5: 421,
PRChase: 443,
WutFace: 20,
BuddhaBar: 622,
PermaSmug: 769,
panicBasket: 285,
BabyRage: 315,
HassaanChop: 246,
TheThing: 890,
EleGiggle: 284,
RitzMitz: 671,
YouWHY: 796,
PipeHype: 343,
BrokeBack: 440,
ANELE: 156,
PanicVis: 865,
GrammarKing: 77,
PeoplesChamp: 634,
SoBayed: 700,
BigBrother: 657,
Keepo: 800,
Kippa: 835,
RalpherZ: 322,
TF2John: 862,
ThunBeast: 408,
WholeWheat: 193,
DAESuppy: 787,
FailFish: 395,
HotPokket: 399,
ResidentSleeper: 460,
FUNgineer: 747,
PMSTwin: 830,
ShazBotstix: 315,
BibleThump: 278,
AsianGlow: 461,
DBstyle: 968,
BloodTrail: 687,
OneHand: 801,
FrankerZ: 893,
SMOrc: 727,
ArsonNoSexy: 99,
PunchTrees: 762,
SSSsss: 800,
Kreygasm: 413,
KevinTurtle: 111,
PJSalt: 115,
SwiftRage: 251,
DansGame: 46,
GingerPower: 762,
BCWarrior: 409,
MrDestructoid: 811,
JonCarnage: 359,
Kappa: 40,
RedCoat: 789,
TheRinger: 669,
StoneLightning: 867,
OptimizePrime: 654,
JKanStyle: 655,
":)": 594,
};
export { fakePrices };

View file

@ -175,15 +175,25 @@ const fakeData: fakeDataEntry[] = [
{
name: "annykiss",
count: 8,
provider: "ttv",
provider: "7tv",
},
{
name: "HUH",
count: 1,
provider: "7tv",
},
{
name: "annytfSigh",
count: 1,
provider: "ttv",
},
{
name: "GabeN",
count: 3,
provider: "bttv",
},
{
name: "widepeepoMASTURBATION77769420GANGSHITNOMOREFORTNITE19DOLLERFORTNITECARD",
name: "widepeepoBlanket",
count: 1,
provider: "ffz",
},
@ -212,6 +222,21 @@ const fakeData: fakeDataEntry[] = [
count: 727,
provider: "7tv",
},
{
name: "AnnySilly",
count: 4,
provider: "bttv",
},
{
name: "annytfHeart",
count: 98,
provider: "ttv",
},
{
name: "Catge",
count: 4,
provider: "ffz",
},
],
badges: [adminBadge, botDevBadge],
},
@ -232,11 +257,26 @@ const fakeData: fakeDataEntry[] = [
count: 92,
provider: "7tv",
},
{
name: "KissaVei",
count: 1,
provider: "bttv",
},
{
name: "SNIFFA",
count: 1219,
provider: "7tv",
},
{
name: "FeelsBirthdayMan",
count: 1,
provider: "ffz",
},
{
name: "annytfRave",
count: 5,
provider: "ttv",
},
],
badges: [adminBadge, botDevBadge],
},
@ -252,6 +292,11 @@ const fakeData: fakeDataEntry[] = [
count: 46,
provider: "7tv",
},
{
name: "GabeN",
count: 3,
provider: "bttv",
},
{
name: "ThisStream",
count: 210,
@ -262,6 +307,11 @@ const fakeData: fakeDataEntry[] = [
count: 91,
provider: "7tv",
},
{
name: "annytfMelt",
count: 16,
provider: "ttv",
},
],
badges: [CEOBadge, adminBadge],
},
@ -278,9 +328,9 @@ const fakeData: fakeDataEntry[] = [
provider: "7tv",
},
{
name: "golive",
count: 90,
provider: "7tv",
name: "annyHop",
count: 61,
provider: "bttv",
},
{
name: "annyExcitedHug",
@ -292,6 +342,16 @@ const fakeData: fakeDataEntry[] = [
count: 65,
provider: "7tv",
},
{
name: "peepoWTF",
count: 60,
provider: "ffz",
},
{
name: "annytfAngy",
count: 90,
provider: "ttv",
},
],
badges: [adminBadge, botDevBadge],
},
@ -331,6 +391,11 @@ const fakeData: fakeDataEntry[] = [
count: 10,
provider: "7tv",
},
{
name: "annySaur",
count: 7,
provider: "bttv",
},
{
name: "BAND",
count: 49,
@ -341,6 +406,16 @@ const fakeData: fakeDataEntry[] = [
count: 78,
provider: "7tv",
},
{
name: "PepegaPhone",
count: 142,
provider: "ffz",
},
{
name: "annytfHug",
count: 19,
provider: "ttv",
},
],
},
{
@ -356,9 +431,9 @@ const fakeData: fakeDataEntry[] = [
provider: "7tv",
},
{
name: "peepoTalk",
count: 73,
provider: "7tv",
name: "annytfLUL",
count: 9,
provider: "ttv",
},
{
name: "peepoSnow",
@ -371,9 +446,14 @@ const fakeData: fakeDataEntry[] = [
provider: "7tv",
},
{
name: "xdd666",
count: 53,
provider: "7tv",
name: "annyBlankies",
count: 88,
provider: "bttv",
},
{
name: "TWINGO",
count: 98,
provider: "ffz",
},
],
},
@ -394,11 +474,21 @@ const fakeData: fakeDataEntry[] = [
count: 64,
provider: "7tv",
},
{
name: "annytfBanana",
count: 15,
provider: "bttv",
},
{
name: "ewLeague",
count: 64,
provider: "7tv",
},
{
name: "annytfPain",
count: 37,
provider: "ttv",
},
],
},
{
@ -418,6 +508,11 @@ const fakeData: fakeDataEntry[] = [
count: 47,
provider: "7tv",
},
{
name: "GabeN",
count: 52,
provider: "bttv",
},
{
name: "GroupWankge",
count: 38,
@ -428,6 +523,11 @@ const fakeData: fakeDataEntry[] = [
count: 90,
provider: "7tv",
},
{
name: "annytfKnuckles",
count: 2,
provider: "ttv",
},
],
},
{
@ -447,11 +547,26 @@ const fakeData: fakeDataEntry[] = [
count: 5,
provider: "7tv",
},
{
name: "annyPls",
count: 5,
provider: "bttv",
},
{
name: "golive",
count: 46,
provider: "7tv",
},
{
name: "COPIUM",
count: 82,
provider: "ffz",
},
{
name: "annytfCheer",
count: 54,
provider: "ttv",
},
],
},
{
@ -481,6 +596,16 @@ const fakeData: fakeDataEntry[] = [
count: 13,
provider: "7tv",
},
{
name: "annytfBlink",
count: 10,
provider: "bttv",
},
{
name: "annytfBonk",
count: 77,
provider: "ttv",
},
],
},
{
@ -500,6 +625,16 @@ const fakeData: fakeDataEntry[] = [
count: 100,
provider: "7tv",
},
{
name: "annyHop",
count: 16,
provider: "bttv",
},
{
name: "AndKnuckles",
count: 17,
provider: "ffz",
},
{
name: "yoshiJAM",
count: 67,
@ -510,6 +645,11 @@ const fakeData: fakeDataEntry[] = [
count: 59,
provider: "7tv",
},
{
name: "annytfSit",
count: 53,
provider: "ttv",
},
],
},
{
@ -529,6 +669,11 @@ const fakeData: fakeDataEntry[] = [
count: 82,
provider: "7tv",
},
{
name: "annyDFast",
count: 22,
provider: "bttv",
},
{
name: "PeepoKittyHug",
count: 7,
@ -553,11 +698,21 @@ const fakeData: fakeDataEntry[] = [
count: 62,
provider: "7tv",
},
{
name: "annyBlankies",
count: 74,
provider: "bttv",
},
{
name: "anyatf",
count: 24,
provider: "7tv",
},
{
name: "annytfGamba",
count: 32,
provider: "ttv",
},
],
},
{
@ -577,11 +732,21 @@ const fakeData: fakeDataEntry[] = [
count: 61,
provider: "7tv",
},
{
name: "Annie",
count: 24,
provider: "bttv",
},
{
name: "Lagging",
count: 92,
provider: "7tv",
},
{
name: "annytfFlower",
count: 33,
provider: "ttv",
},
],
},
{
@ -606,6 +771,16 @@ const fakeData: fakeDataEntry[] = [
count: 7,
provider: "7tv",
},
{
name: "annyHopper",
count: 24,
provider: "bttv",
},
{
name: "annytfFlower",
count: 79,
provider: "ttv",
},
],
},
{
@ -630,6 +805,16 @@ const fakeData: fakeDataEntry[] = [
count: 32,
provider: "7tv",
},
{
name: "AngelThump",
count: 41,
provider: "bttv",
},
{
name: "annytfSad",
count: 2,
provider: "ttv",
},
],
},
{
@ -654,6 +839,16 @@ const fakeData: fakeDataEntry[] = [
count: 99,
provider: "7tv",
},
{
name: "annyBlankies",
count: 42,
provider: "bttv",
},
{
name: "annytfHeart",
count: 63,
provider: "ttv",
},
],
},
];

30
pages/api/ffz/emotes.ts Normal file
View file

@ -0,0 +1,30 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { createRedisInstance } from "../../../misc/redis";
import { getEmoteSet, getGlobalEmotes } from "../../../misc/FFZAPI";
type Data = {
[key: string]: any;
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const redis = createRedisInstance();
try {
const channel = req.query.s
? (await getEmoteSet(redis, req.query.s as string)).set.emoticons
: undefined;
let global = await getGlobalEmotes(redis);
// set global emotes to be the three sets within the global object ("3", "4330")
global = global.sets["3"].emoticons.concat(global.sets["4330"].emoticons);
redis.quit();
res.status(200).json({ channel, global });
} catch (e) {
console.log(e);
res
.status(500)
.json({ error: { message: "FFZ or internal API is down", code: 10300 } });
}
}

View file

@ -0,0 +1,30 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { createRedisInstance } from "../../../misc/redis";
import { getChannelEmotes, getGlobalEmotes } from "../../../misc/TwitchAPI";
type Data = {
[key: string]: any;
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const redis = createRedisInstance();
try {
const channel = req.query.c
? (await getChannelEmotes(redis, req.query.c as string)).data
: undefined;
const global = (await getGlobalEmotes(redis)).data;
redis.quit();
res.status(200).json({ channel, global });
} catch (e) {
console.log(e);
res
.status(500)
.json({
error: { message: "Twitch or internal API is down", code: 10100 },
});
}
}

View file

@ -9,9 +9,9 @@ import Loading from "../../../components/common/Loading";
// TODO: Animations
function UserPage() {
const [channelEmotes, setChannelEmotes] = useState<{ [key: string]: string }>(
{}
);
const [channelEmotes, setChannelEmotes] = useState<{
[key: string]: { [key: string]: string };
}>({});
const [userData, setUserData] = useState<{ [key: string]: any }>({});
const [errorCode, setErrorCode] = useState<number | null>(null);
const router = useRouter();
@ -36,7 +36,74 @@ function UserPage() {
let largest = emote.data.host.files[emote.data.host.files.length - 1];
emotes[emote.data.name] = `https:${base_url}/${largest.name}`;
});
setChannelEmotes(emotes);
// same for global emotes
data.global.namedEmoteSet.emotes.forEach((emote: any) => {
let base_url = emote.data.host.url;
let largest = emote.data.host.files[emote.data.host.files.length - 1];
emotes[emote.data.name] = `https:${base_url}/${largest.name}`;
});
// set 7tv key to channelEmotes
setChannelEmotes((prev) => ({ ...prev, "7tv": emotes }));
});
fetch("/api/bttv/emotes?c=56418014")
.then((res) => res.json())
.then((data) => {
if (data.error) {
setErrorCode(data.error.code);
return;
}
let emotes: { [key: string]: string } = {};
data.channel.forEach((emote: any) => {
emotes[emote.code] = `https://cdn.betterttv.net/emote/${emote.id}/3x`;
});
data.global.forEach((emote: any) => {
emotes[emote.code] = `https://cdn.betterttv.net/emote/${emote.id}/3x`;
});
// add as bttv key to channelEmotes
setChannelEmotes((prev) => ({ ...prev, bttv: emotes }));
});
fetch("/api/ffz/emotes?s=341402")
.then((res) => res.json())
.then((data) => {
if (data.error) {
setErrorCode(data.error.code);
return;
}
let emotes: { [key: string]: string } = {};
data.channel.forEach((emote: any) => {
// ffz emotes don't have all sizes available, so we need to get the largest one by taking the largest key in the urls object
emotes[emote.name] = `https:${
emote.urls[
Math.max(...Object.keys(emote.urls).map((k) => parseInt(k)))
]
}`;
});
data.global.forEach((emote: any) => {
emotes[emote.name] = `https:${
emote.urls[
Math.max(...Object.keys(emote.urls).map((k) => parseInt(k)))
]
}`;
});
// add as ffz key to channelEmotes
setChannelEmotes((prev) => ({ ...prev, ffz: emotes }));
});
fetch("/api/twitch/emotes?c=56418014")
.then((res) => res.json())
.then((data) => {
if (data.error) {
setErrorCode(data.error.code);
return;
}
let emotes: { [key: string]: string } = {};
data.channel.forEach((emote: any) => {
emotes[emote.name] = emote.images["url_4x"];
});
data.global.forEach((emote: any) => {
emotes[emote.name] = emote.images["url_4x"];
});
// add as twitch key to channelEmotes
setChannelEmotes((prev) => ({ ...prev, ttv: emotes }));
});
fetch(`/api/fakeUsers?u=${username}`)
.then((res) => res.json())
@ -53,6 +120,8 @@ function UserPage() {
// 20000 = user not found
// 10000 = 7tv api error
// 10100 = Twitch api error
// 10200 = BTTV api error
// 10300 = FFZ api error
const errorMsg = errorCode === 20000 ? "User not found" : "API error";
return (
<m.div
@ -66,9 +135,9 @@ function UserPage() {
);
}
// if json is empty
// if json is empty, and if channelEmotes is incomplete, show loading screen
if (
Object.keys(channelEmotes).length === 0 ||
Object.keys(channelEmotes).length < 4 ||
!userData ||
Object.keys(userData).length === 0
) {
@ -78,7 +147,7 @@ function UserPage() {
</div>
);
}
console.log(channelEmotes);
return (
<>
<Head>
@ -100,6 +169,7 @@ function UserPage() {
alt="User avatar"
width={140}
height={140}
priority
className="absolute rounded-lg border-4"
style={{
borderColor: userData.badges[0]
@ -217,14 +287,21 @@ function UserPage() {
>
<div className="flex h-44 w-full max-w-[256px] flex-col items-center rounded-xl bg-zinc-900 bg-opacity-80 p-2">
<div className="mt-2 mb-2 h-24 w-24">
<div className="flex h-full w-full items-center justify-center p-2">
<div className="flex h-full w-full items-center justify-start p-2">
{
// if error code is 10000, show placeholder image
errorCode === 10000 ? (
// if error code is 10000 or emote does not exist, show placeholder image
errorCode === 10000 ||
channelEmotes[asset.provider] === undefined ||
channelEmotes[asset.provider][asset.name] ===
undefined ? (
<h1 className="text-center text-zinc-400">{`404 :(`}</h1>
) : (
<Image
src={channelEmotes[asset.name]}
src={
channelEmotes[asset.provider][
asset.name
] ?? ""
}
alt={asset.name}
width={100}
height={100}
@ -245,7 +322,7 @@ function UserPage() {
</div>
<div className="flex w-full flex-row items-center justify-center">
{
// show provider logo (7tv, bttv, ffz, twitch)
// show provider logo (7tv, bttv, ffz, ttv)
asset.provider === "7tv" ? (
<div className="mr-1 pt-[1px] text-7tv ">
<SevenTVLogo />