All files / src/scripts authorizeBot.ts

100% Statements 35/35
100% Branches 5/5
100% Functions 2/2
100% Lines 35/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 361x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 2x 2x 2x 2x 2x 2x 3x  
import { resolveTwitchOperatorEnv } from "@workspace/env/twitch"
import { createLogger, serializeLogError } from "@workspace/logger"
 
import { TwitchApiService } from "../services/TwitchApiService"
import { authorizeBot } from "../auth/authorization"
import { GrantStore } from "../auth/grantStore"
 
export async function main(): Promise<void> {
  const logger = createLogger("twitch-bot-authorization")
  try {
    const config = resolveTwitchOperatorEnv()
    if (!process.stdout.isTTY)
      throw new Error(
        "Bot authorization requires an interactive operator terminal."
      )
    await authorizeBot(config, {
      api: new TwitchApiService(config),
      store: new GrantStore(config.TWITCH_BOT_GRANT_PATH),
      showUrl: (url) => {
        process.stdout.write(
          `Open this URL while signed in as the dedicated Cleo bot:\n${url}\n`
        )
      },
    })
    logger.info(
      "Verified bot grant saved privately. Transfer it through your secure operator channel; tokens are not printed."
    )
  } catch (error) {
    logger.error(
      "Bot authorization failed. Check the expected account, scopes, redirect URI and private output directory. Existing grants are never overwritten.",
      { error: serializeLogError(error) }
    )
    process.exitCode = 1
  }
}