AtlatestRepositorysigil-twitch
sigil-twitch / tree / src / twitchoauth.sgl
1
;;; (twitch oauth) - OAuth 2.0 integration for sigil-twitch.2
;;;3
;;; Provides convenience functions for creating Twitch clients4
;;; with OAuth token management via sigil-oauth. Uses the Twitch5
;;; provider preset with configurable scopes.6
;;;7
;;; This module adds OAuth support alongside the existing manual8
;;; token-passing API — callers can still construct a twitch-client9
;;; directly with client-id and access-token strings.11
(define-library (twitch oauth)12
(import (sigil core)13
(sigil dict)14
(sigil struct)15
(sigil oauth)16
(sigil oauth store)17
(twitch))19
(export ;; Config helpers20
twitch-oauth-config22
;; Client construction from tokens23
twitch-oauth-client25
;; Auto-refresh: config + tokens + time → client + tokens26
twitch-ensure-client28
;; Token storage helpers29
twitch-save-tokens30
twitch-load-tokens31
twitch-clear-tokens33
;; Re-exported from (sigil oauth) for convenience34
oauth-config35
oauth-config?36
oauth-config-client-id37
oauth-config-client-secret38
oauth-config-auth-url39
oauth-config-token-url40
oauth-config-scopes41
oauth-config-redirect-uri42
oauth-config-extra-params43
oauth-tokens44
oauth-tokens?45
oauth-tokens-access-token46
oauth-tokens-refresh-token47
oauth-tokens-expires-at48
oauth-tokens-token-type49
oauth-tokens-scopes50
oauth-ensure-valid-token51
oauth-token-expired?52
oauth-authorization-url53
oauth-generate-state54
oauth-generate-pkce55
oauth-exchange-code56
oauth-refresh-token)58
(begin60
;; Default Twitch scopes for stream management + analytics + chat.61
(define twitch-default-scopes62
(list "channel:manage:broadcast"63
"channel:manage:schedule"64
"channel:read:stream_key"65
"clips:edit"66
"moderator:read:followers"67
"channel:read:subscriptions"68
"user:read:chat"69
"user:write:chat"70
"analytics:read:games"))72
(define twitch-service-name "twitch")74
;; ---------------------------------------------------------------75
;; Config76
;; ---------------------------------------------------------------78
;;; Create an oauth-config for Twitch OAuth2.79
;;;80
;;; client-id: Twitch application client ID81
;;; client-secret: Twitch application client secret82
;;;83
;;; Optional keyword args via opts dict:84
;;; scopes: list of scope strings (default: twitch-default-scopes)85
;;; redirect-uri: override redirect URI86
(define (twitch-oauth-config client-id client-secret . rest)87
(let ((opts (if (null? rest) #{} (car rest))))88
(let ((scopes (dict-ref opts scopes: twitch-default-scopes)))89
(oauth-twitch-config client-id client-secret scopes90
(if (dict-ref opts redirect-uri: #f)91
#{ redirect-uri: (dict-ref opts redirect-uri:) }92
#{})))))94
;; ---------------------------------------------------------------95
;; Client construction96
;; ---------------------------------------------------------------98
;;; Build a twitch-client from an oauth-tokens record.99
;;;100
;;; client-id is required because Twitch requires it in every101
;;; API request header alongside the Bearer token.102
(define (twitch-oauth-client client-id tokens)103
(twitch-client104
client-id: client-id105
access-token: (oauth-tokens-access-token tokens)))107
;; ---------------------------------------------------------------108
;; Auto-refresh109
;; ---------------------------------------------------------------111
;;; Ensure tokens are valid (refreshing if needed) and return112
;;; both a ready-to-use twitch-client and the (possibly updated)113
;;; oauth-tokens record.114
;;;115
;;; config: oauth-config from twitch-oauth-config116
;;; tokens: current oauth-tokens record117
;;; current-time: unix timestamp (from current-second)118
;;;119
;;; Optional keyword args via opts dict:120
;;; save?: whether to persist refreshed tokens (default: #t)121
;;;122
;;; Returns: (values twitch-client oauth-tokens)123
(define (twitch-ensure-client config tokens current-time . rest)124
(let* ((opts (if (null? rest) #{} (car rest)))125
(save? (dict-ref opts save?: #t))126
(fresh-tokens (oauth-ensure-valid-token config tokens current-time))127
(client (twitch-oauth-client128
(oauth-config-client-id config)129
fresh-tokens)))130
;; Persist if tokens were refreshed131
(if (and save?132
(not (eq? fresh-tokens tokens)))133
(twitch-save-tokens fresh-tokens))134
(values client fresh-tokens)))136
;; ---------------------------------------------------------------137
;; Token storage (thin wrappers)138
;; ---------------------------------------------------------------140
;;; Save Twitch OAuth tokens to persistent storage.141
(define (twitch-save-tokens tokens)142
(oauth-save-tokens twitch-service-name tokens))144
;;; Load Twitch OAuth tokens from persistent storage.145
;;; Returns oauth-tokens or #f if not found.146
(define (twitch-load-tokens)147
(oauth-load-tokens twitch-service-name))149
;;; Clear stored Twitch OAuth tokens.150
(define (twitch-clear-tokens)151
(oauth-clear-tokens twitch-service-name))153
))