| |
| |
| |
| |
| |
| |
|
|
| import { ApiClient } from "@twurple/api"; |
| import { StaticAuthProvider } from "@twurple/auth"; |
| import type { ChannelResolveKind, ChannelResolveResult } from "./types.js"; |
| import type { ChannelLogSink, TwitchAccountConfig } from "./types.js"; |
| import { normalizeToken } from "./utils/twitch.js"; |
|
|
| |
| |
| |
| function normalizeUsername(input: string): string { |
| const trimmed = input.trim(); |
| if (trimmed.startsWith("@")) { |
| return trimmed.slice(1).toLowerCase(); |
| } |
| return trimmed.toLowerCase(); |
| } |
|
|
| |
| |
| |
| function createLogger(logger?: ChannelLogSink): ChannelLogSink { |
| return { |
| info: (msg: string) => logger?.info(msg), |
| warn: (msg: string) => logger?.warn(msg), |
| error: (msg: string) => logger?.error(msg), |
| debug: (msg: string) => logger?.debug?.(msg) ?? (() => {}), |
| }; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export async function resolveTwitchTargets( |
| inputs: string[], |
| account: TwitchAccountConfig, |
| kind: ChannelResolveKind, |
| logger?: ChannelLogSink, |
| ): Promise<ChannelResolveResult[]> { |
| const log = createLogger(logger); |
|
|
| if (!account.clientId || !account.token) { |
| log.error("Missing Twitch client ID or token"); |
| return inputs.map((input) => ({ |
| input, |
| resolved: false, |
| note: "missing Twitch credentials", |
| })); |
| } |
|
|
| const normalizedToken = normalizeToken(account.token); |
|
|
| const authProvider = new StaticAuthProvider(account.clientId, normalizedToken); |
| const apiClient = new ApiClient({ authProvider }); |
|
|
| const results: ChannelResolveResult[] = []; |
|
|
| for (const input of inputs) { |
| const normalized = normalizeUsername(input); |
|
|
| if (!normalized) { |
| results.push({ |
| input, |
| resolved: false, |
| note: "empty input", |
| }); |
| continue; |
| } |
|
|
| const looksLikeUserId = /^\d+$/.test(normalized); |
|
|
| try { |
| if (looksLikeUserId) { |
| const user = await apiClient.users.getUserById(normalized); |
|
|
| if (user) { |
| results.push({ |
| input, |
| resolved: true, |
| id: user.id, |
| name: user.name, |
| }); |
| log.debug?.(`Resolved user ID ${normalized} -> ${user.name}`); |
| } else { |
| results.push({ |
| input, |
| resolved: false, |
| note: "user ID not found", |
| }); |
| log.warn(`User ID ${normalized} not found`); |
| } |
| } else { |
| const user = await apiClient.users.getUserByName(normalized); |
|
|
| if (user) { |
| results.push({ |
| input, |
| resolved: true, |
| id: user.id, |
| name: user.name, |
| note: user.displayName !== user.name ? `display: ${user.displayName}` : undefined, |
| }); |
| log.debug?.(`Resolved username ${normalized} -> ${user.id} (${user.name})`); |
| } else { |
| results.push({ |
| input, |
| resolved: false, |
| note: "username not found", |
| }); |
| log.warn(`Username ${normalized} not found`); |
| } |
| } |
| } catch (error) { |
| const errorMessage = error instanceof Error ? error.message : String(error); |
| results.push({ |
| input, |
| resolved: false, |
| note: `API error: ${errorMessage}`, |
| }); |
| log.error(`Failed to resolve ${input}: ${errorMessage}`); |
| } |
| } |
|
|
| return results; |
| } |
|
|