mirror of
https://github.com/qwerinope/qweribot.git
synced 2025-12-19 08:41:39 +01:00
117 lines
3.9 KiB
TypeScript
117 lines
3.9 KiB
TypeScript
import { chatterApi, streamerId } from "..";
|
|
import logger from "../lib/logger";
|
|
import type { twitchEventData } from "./websockettypes";
|
|
import chatWidget from "./www/index.html";
|
|
|
|
type badgeObject = {
|
|
[key: string]: {
|
|
[key: string]: string;
|
|
};
|
|
};
|
|
|
|
type emoteObject = {
|
|
[key: string]: string;
|
|
}
|
|
|
|
const port = Number(process.env.CHATWIDGET_PORT);
|
|
if (isNaN(port)) { logger.enverr("CHATWIDGET_PORT"); process.exit(1); };
|
|
|
|
const server = Bun.serve({
|
|
port,
|
|
fetch(request, server) {
|
|
if (server.upgrade(request)) return;
|
|
return new Response('oops', { status: 500 });
|
|
},
|
|
routes: {
|
|
"/": chatWidget,
|
|
"/getBadges": async () => {
|
|
const globalBadges = chatterApi.chat.getGlobalBadges();
|
|
const channelBadges = chatterApi.chat.getChannelBadges(streamerId);
|
|
const rawBadges = await Promise.all([globalBadges, channelBadges]);
|
|
|
|
const newObj: badgeObject = {};
|
|
parseRawBadges(newObj, rawBadges[0]);
|
|
parseRawBadges(newObj, rawBadges[1]);
|
|
|
|
return Response.json(newObj);
|
|
},
|
|
"/getEmotes": async () => {
|
|
const [bttvglobal, bttvuser, ffzglobal, ffzuser, seventvglobal, seventvuser] = await Promise.all([
|
|
fetch("https://api.betterttv.net/3/cached/emotes/global").then(a => a.json() as any),
|
|
fetch("https://api.betterttv.net/3/cached/users/twitch/" + streamerId).then(a => a.json() as any),
|
|
fetch("https://api.frankerfacez.com/v1/set/global").then(a => a.json() as any),
|
|
fetch("https://api.frankerfacez.com/v1/room/id/" + streamerId).then(a => a.json() as any),
|
|
fetch("https://7tv.io/v3/emote-sets/global").then(a => a.json() as any),
|
|
fetch("https://7tv.io/v3/users/twitch/" + streamerId).then(a => a.json() as any)
|
|
]);
|
|
const emotes: emoteObject = {};
|
|
for (const a of bttvglobal) {
|
|
emotes[a.code] = `https://cdn.betterttv.net/emote/${a.id}/3x.${a.imageType}`;
|
|
};
|
|
for (const a of bttvuser.sharedEmotes) {
|
|
emotes[a.code] = `https://cdn.betterttv.net/emote/${a.id}/3x.${a.imageType}`;
|
|
};
|
|
for (const a of ffzglobal.default_sets) {
|
|
for (const b of ffzglobal.sets[a].emoticons) {
|
|
emotes[b.name] = `https://cdn.frankerfacez.com/emote/${b.id}/4`;
|
|
};
|
|
};
|
|
for (const a of ffzuser.sets[ffzuser.room.set].emoticons) {
|
|
emotes[a.name] = `https://cdn.frankerfacez.com/emote/${a.id}/4`;
|
|
}
|
|
for (const a of seventvglobal.emotes) {
|
|
emotes[a.name] = `https://cdn.7tv.app/emote/${a.id}/4x.avif`;
|
|
};
|
|
for (const a of seventvuser.emote_set.emotes) {
|
|
emotes[a.name] = `https://cdn.7tv.app/emote/${a.id}/4x.avif`;
|
|
};
|
|
return Response.json(emotes);
|
|
}
|
|
},
|
|
websocket: {
|
|
open(_ws) {
|
|
sendTwitchEvent({
|
|
function: 'serverNotification',
|
|
message: 'Sucessfully opened websocket connection'
|
|
});
|
|
},
|
|
message(ws, omessage) {
|
|
const message = JSON.parse(omessage.toString());
|
|
if (!message.type) return;
|
|
switch (message.type) {
|
|
case 'subscribe':
|
|
if (!message.target) return;
|
|
ws.subscribe(message.target);
|
|
sendTwitchEvent({
|
|
function: 'serverNotification',
|
|
message: `Successfully subscribed to all ${message.target} events`
|
|
});
|
|
break;
|
|
};
|
|
},
|
|
close(ws) {
|
|
ws.close();
|
|
}
|
|
},
|
|
development: true,
|
|
error(error) {
|
|
logger.err(`Error at chatwidget server: ${error}`);
|
|
return new Response("Internal Server Error", { status: 500 })
|
|
},
|
|
});
|
|
|
|
export async function sendTwitchEvent(event: twitchEventData) {
|
|
server.publish('twitch', JSON.stringify(event));
|
|
};
|
|
|
|
import { HelixChatBadgeSet } from "@twurple/api";
|
|
|
|
function parseRawBadges(returnobj: badgeObject, data: HelixChatBadgeSet[]) {
|
|
for (const badge of data) {
|
|
if (!returnobj[badge.id]) returnobj[badge.id] = {};
|
|
for (const version of badge.versions) {
|
|
returnobj[badge.id]![version.id] = version.getImageUrl(4);
|
|
};
|
|
};
|
|
};
|