import { LooseObject } from "../../../types/looseTypes" import { StreamerData, StreamData, Social } from "../../../types/scraping/Streamer" /** * Class that interacts with the Twitch api */ export class TwitchAPI { public readonly twitchUrl = 'https://gql.twitch.tv/gql' public headers = { "Client-Id": "kimne78kx3ncx6brgo4mv6wki5h1ko" } constructor() {} /** * Gets information about a streamer, like socials, about, and more. * @see StreamerData * @param streamerName The username of the streamer * @returns Promise */ public getStreamerInfo = async (streamerName: string) => { const payload = [ { "operationName": "ChannelRoot_AboutPanel", "variables": { "channelLogin": streamerName, "skipSchedule": false }, "extensions": { "persistedQuery": { "version": 1, "sha256Hash": "6089531acef6c09ece01b440c41978f4c8dc60cb4fa0124c9a9d3f896709b6c6" } } }, { "operationName":"StreamMetadata", "variables":{ "channelLogin": streamerName }, "extensions":{ "persistedQuery":{ "version":1, "sha256Hash":"a647c2a13599e5991e175155f798ca7f1ecddde73f7f341f39009c14dbf59962" } } }, { "operationName": "StreamTagsTrackingChannel", "variables": { "channel": streamerName }, "extensions": { "persistedQuery": { "version": 1, "sha256Hash": "6aa3851aaaf88c320d514eb173563d430b28ed70fdaaf7eeef6ed4b812f48608" } } }, { "operationName": "VideoPreviewOverlay", "variables": { "login": streamerName }, "extensions": { "persistedQuery": { "version": 1, "sha256Hash": "9515480dee68a77e667cb19de634739d33f243572b007e98e67184b1a5d8369f" } } }, { "operationName": "UseViewCount", "variables": { "channelLogin": streamerName }, "extensions": { "persistedQuery": { "version": 1, "sha256Hash": "00b11c9c428f79ae228f30080a06ffd8226a1f068d6f52fbc057cbde66e994c2" } } }, ] const res = await fetch(this.twitchUrl, { method: 'POST', body: JSON.stringify(payload), headers: this.headers }) const data = await res.json() console.log(data[1].data, data[1].data.user.stream) const rawStreamerData = data[0].data // get socials const socials: LooseObject[] = [] if (rawStreamerData.user.channel && rawStreamerData.user.channel.socialMedias) { for (let social of rawStreamerData.user.channel.socialMedias) { socials.push({ type: social.name, name: social.title, link: social.url }) } } // check if is liver const rawStreamData = data[1].data.user.stream let parsedStream: StreamData | null; if(!rawStreamData) { parsedStream = null } else { const tags: string[] = [] for (let tagData of data[2].data.user.stream.freeformTags) { tags.push(tagData.name) } parsedStream = { title: data[1].data.user.lastBroadcast.title, topic: rawStreamData.game.name, startedAt: new Date(rawStreamData.createdAt).valueOf(), tags, viewers: Number(data[4].data.user.stream.viewersCount), preview: data[3].data.user.stream.previewImageURL } } const abbreviatedFollowers = Intl.NumberFormat('en-US', { notation: "compact", maximumFractionDigits: 1 }).format(rawStreamerData.user.followers.totalCount) const streamerData: StreamerData = { username: rawStreamerData.user.displayName, about: rawStreamerData.user.description, pfp: rawStreamerData.user.profileImageURL, followers: rawStreamerData.user.followers.totalCount, socials: socials as Social[], isLive: (!!parsedStream), isPartner: rawStreamerData.user.isPartner, followersAbbv: abbreviatedFollowers, colorHex: '#' + rawStreamerData.user.primaryColorHex, id: Number(rawStreamerData.user.id), stream: parsedStream } return Promise.resolve(streamerData) } /** * Gets the current viewers of a stream * @param streamerName The username of the streamer * @returns Promise */ public getViewers = async (streamerName: string) => { const payload = [ { "operationName": "UseViewCount", "variables": { "channelLogin": streamerName }, "extensions": { "persistedQuery": { "version": 1, "sha256Hash": "00b11c9c428f79ae228f30080a06ffd8226a1f068d6f52fbc057cbde66e994c2" } } }, ] const res = await fetch(this.twitchUrl, { method: 'POST', body: JSON.stringify(payload), headers: this.headers }) const rawData = await res.json() console.log(rawData) if(!rawData[0].data.user.stream) return Promise.reject(new Error(`Streamer ${streamerName} is not live`)) return Promise.resolve(rawData[0].data.user.stream.viewersCount) } }