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 36 37 38 39 40 41 42 43 44 45 46 47 48 | 3x 3x 3x 3x 3x 1x 1x 1x 13x 13x 13x 13x 1x 23x 23x 19x 19x 19x 19x 19x 19x 23x 1x 19x 19x 7x 7x 7x 7x 4x 4x 4x 4x 4x 2x 2x 7x 19x 15x 19x 1x 8x 8x 1x 2x 2x 1x | import type { TwitchRuntimeEnv } from "@workspace/env/twitch"
import { ensureBotGrant, GrantStore } from "../auth/grantStore"
import { TwitchApiService, TwitchFailure } from "./TwitchApiService"
export class TwitchAuthService {
private token?: string
private inFlight?: Promise<string>
constructor(
private readonly api: TwitchApiService,
private readonly store: GrantStore,
private readonly config: TwitchRuntimeEnv
) {}
async maintain(): Promise<string> {
if (this.inFlight) return this.inFlight
const work = this.maintainToken()
this.inFlight = work
try {
return await work
} finally {
this.inFlight = undefined
}
}
private async maintainToken(): Promise<string> {
await ensureBotGrant(this.api, this.store, this.config)
if (this.token) {
try {
await this.api.validateAppToken(this.token)
return this.token
} catch (error) {
if (
!(error instanceof TwitchFailure) ||
!["unauthorized", "expiredToken"].includes(error.code)
)
throw error
this.token = undefined
}
}
this.token = await this.api.acquireAppToken()
return this.token
}
async appToken(): Promise<string> {
return this.token ?? this.maintain()
}
botToken(): Promise<string> {
return ensureBotGrant(this.api, this.store, this.config)
}
}
|