import type { AccessTokenMaybeWithUserId, AccessTokenWithUserId, AuthProvider } from "@twurple/auth"; import type { UserIdResolvable } from "@twurple/api" import * as TwitchAuth from "./TwitchAuth"; async function getTwurpleProxy(token: TwitchAuth.TwitchToken): Promise { if (!token.user_id) { const refresh_token=token.refresh_token token = await TwitchAuth.validateToken(token.access_token) token.refresh_token=refresh_token } return new Proxy(token, { get(target, name, receiver) { return target[name.toString().replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`) as keyof TwitchAuth.TwitchToken] } }) as unknown as AccessTokenWithUserId } export class SugoiAuthProvider implements AuthProvider { #token: TwitchAuth.TwitchToken | Promise | null = null; clientId: string; constructor(clientId:string,proxyOrigin?:string) { this.clientId = clientId; if (proxyOrigin) TwitchAuth.setProxyOrigin(proxyOrigin); this.#token=TwitchAuth.getUserTokenPassive(clientId).catch() } #authorize(scopes: string[]) { const promise = TwitchAuth.requestAuthCode(this.clientId, ...scopes) this.#token = promise return promise } /** * Checks cached token for given scopes, and redirects to authorization page on failure. * You should only call this from your configured redirect uri. * * https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#get-the-user-to-authorize-your-app */ async getAuthorization(...scopes: string[]): Promise { const token = await this.#token if(!token) return this.#authorize(scopes) for (const scope of scopes) { if (!token.scope!.includes(scope)) { return this.#authorize(scopes) } } } getCurrentScopesForUser(user: UserIdResolvable):string[] { if (!this.#token || this.#token instanceof Promise) throw new Error("unauthorized") return this.#token.scope || [] } async getAccessTokenForUser(user: UserIdResolvable, ...scopeSets: (string[] | undefined)[]): Promise { const token = await this.#token if (!token) return null return getTwurpleProxy(token) } async getAnyAccessToken(user?: UserIdResolvable): Promise { const token = await this.#token if (!token) throw new Error("unauthorized") return getTwurpleProxy(token) } async refreshAccessTokenForUser(user: UserIdResolvable): Promise { const token=await this.#token if (!token) throw new Error("unauthorized") if (!token.refresh_token) throw new Error("missing refresh token") this.#token = await TwitchAuth.refreshToken(this.clientId, token.refresh_token) return getTwurpleProxy(this.#token) } } export default SugoiAuthProvider