import {z} from 'zod' export type GetApiBotModulesChannelArgs = {channel: string, Accept: string}; export type GetApiBotModulesChannelOptions = {baseUrl?: string | undefined, JWTBearer?: string | undefined, fetch?: typeof fetch | undefined}; export const cooldown = z.object({user: z.number().int(), global: z.number().int()}); export const raffleMessages = z.object({win: z.string(), lose: z.string(), allinWin: z.string(), allinLose: z.string()}); export const roulette = z.object({cooldown: cooldown, messages: raffleMessages, enabled: z.boolean(), luck: z.number().int(), minAmount: z.number().int()}); export const singleRaffleMessages = z.object({start: z.string(), running: z.string(), end: z.string()}); export const single = z.object({messages: singleRaffleMessages, duration: z.number().int(), maxAmount: z.number().int()}); export const multi = z.object({messages: singleRaffleMessages, duration: z.number().int(), maxAmount: z.number().int()}); export const raffle = z.object({single: single, multi: multi, enabled: z.boolean()}); export const pyramidMessages = z.object({_id: z.string(), width: z.number().int(), message: z.string()}); export const pyramid = z.object({enabled: z.boolean(), messages: z.array(pyramidMessages)}); export const bingo = z.object({enabled: z.boolean(), maxAmount: z.number().int()}); export const slotsMessages = z.object({win: z.string(), lose: z.string()}); export const slotmachine = z.object({cooldown: cooldown, messages: slotsMessages, enabled: z.boolean(), returnAmount: z.number().int(), minAmount: z.number().int(), emotes: z.array(z.string())}); export const messages5 = z.object({win: z.string(), pointsWin: z.string()}); export const duel = z.object({cooldown: cooldown, messages: messages5, enabled: z.boolean()}); export const eightball = z.object({cooldown: cooldown, enabled: z.boolean(), messages: z.array(z.string()), emotes: z.array(z.string())}); export const messages6 = z.object({_id: z.string(), count: z.number().int(), message: z.string()}); export const emotecombo = z.object({enabled: z.boolean(), minCount: z.number().int(), cooldown: z.number().int(), messages: z.array(messages6)}); export const twitter = z.object({enabled: z.boolean(), replies: z.boolean(), retweets: z.boolean(), template: z.string(), followed: z.array(z.string())}); export const followBot = z.object({enabled: z.boolean(), messages: z.array(z.string())}); export const additionalMessagesBot = z.object({_id: z.string(), amount: z.number().int(), message: z.string()}); export const tipBot = z.object({enabled: z.boolean(), messages: z.array(additionalMessagesBot)}); export const hostBot = z.object({enabled: z.boolean(), messages: z.array(additionalMessagesBot)}); export const subscriberBot = z.object({enabled: z.boolean(), messages: z.array(additionalMessagesBot)}); export const cheerBot = z.object({enabled: z.boolean(), messages: z.array(additionalMessagesBot)}); export const redemptionBot = z.object({enabled: z.boolean(), message: z.string()}); export const raidBot = z.object({enabled: z.boolean(), messages: z.array(additionalMessagesBot)}); export const chatalerts = z.object({follow: followBot, tip: tipBot, host: hostBot, subscriber: subscriberBot, cheer: cheerBot, redemption: redemptionBot, raid: raidBot, enabled: z.boolean(), delay: z.number().int()}); export const voteskip = z.object({enabled: z.boolean(), votesRequired: z.number().int()}); export const songrequest = z.object({voteskip: voteskip, enabled: z.boolean(), moderation: z.boolean(), minUserLevel: z.number().int(), cost: z.number().int(), subscriberDiscount: z.number().int(), exemptUserLevel: z.number().int()}); export const streamStart = z.object({enabled: z.boolean(), message: z.string()}); export const announcements = z.object({streamStart: streamStart, enabled: z.boolean()}); export const botModules = z.object({roulette: roulette, raffle: raffle, pyramid: pyramid, bingo: bingo, slotmachine: slotmachine, duel: duel, eightball: eightball, emotecombo: emotecombo, twitter: twitter, chatalerts: chatalerts, songrequest: songrequest, announcements: announcements}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * /:channel * * GET /bot/modules/{channel} * * Also accepts auth: OAuth2, ApiKeyBearer */ export const getApiBotModulesChannel = async (args: GetApiBotModulesChannelArgs, options?: GetApiBotModulesChannelOptions) => { const {baseUrl = "https://api.streamelements.com/kappa/v2", fetch: fetchFn = fetch, JWTBearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json; charset=utf-8") if (args.Accept != null) headers.set("Accept", String(args.Accept)) if (JWTBearer !== undefined) headers.set('authorization', `Bearer ${JWTBearer}`) const url = `${baseUrl.replace(/\/+$/, '')}/bot/modules/${encodeURIComponent(String(args.channel))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(botModules, await res.json()) };