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 clients
4;;; with OAuth token management via sigil-oauth. Uses the Twitch
5;;; provider preset with configurable scopes.
6;;;
7;;; This module adds OAuth support alongside the existing manual
8;;; token-passing API — callers can still construct a twitch-client
9;;; 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 helpers
20 twitch-oauth-config
22 ;; Client construction from tokens
23 twitch-oauth-client
25 ;; Auto-refresh: config + tokens + time → client + tokens
26 twitch-ensure-client
28 ;; Token storage helpers
29 twitch-save-tokens
30 twitch-load-tokens
31 twitch-clear-tokens
33 ;; Re-exported from (sigil oauth) for convenience
34 oauth-config
35 oauth-config?
36 oauth-config-client-id
37 oauth-config-client-secret
38 oauth-config-auth-url
39 oauth-config-token-url
40 oauth-config-scopes
41 oauth-config-redirect-uri
42 oauth-config-extra-params
43 oauth-tokens
44 oauth-tokens?
45 oauth-tokens-access-token
46 oauth-tokens-refresh-token
47 oauth-tokens-expires-at
48 oauth-tokens-token-type
49 oauth-tokens-scopes
50 oauth-ensure-valid-token
51 oauth-token-expired?
52 oauth-authorization-url
53 oauth-generate-state
54 oauth-generate-pkce
55 oauth-exchange-code
56 oauth-refresh-token)
58 (begin
60 ;; Default Twitch scopes for stream management + analytics + chat.
61 (define twitch-default-scopes
62 (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 ;; Config
76 ;; ---------------------------------------------------------------
78 ;;; Create an oauth-config for Twitch OAuth2.
79 ;;;
80 ;;; client-id: Twitch application client ID
81 ;;; client-secret: Twitch application client secret
82 ;;;
83 ;;; Optional keyword args via opts dict:
84 ;;; scopes: list of scope strings (default: twitch-default-scopes)
85 ;;; redirect-uri: override redirect URI
86 (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 scopes
90 (if (dict-ref opts redirect-uri: #f)
91 #{ redirect-uri: (dict-ref opts redirect-uri:) }
92 #{})))))
94 ;; ---------------------------------------------------------------
95 ;; Client construction
96 ;; ---------------------------------------------------------------
98 ;;; Build a twitch-client from an oauth-tokens record.
99 ;;;
100 ;;; client-id is required because Twitch requires it in every
101 ;;; API request header alongside the Bearer token.
102 (define (twitch-oauth-client client-id tokens)
103 (twitch-client
104 client-id: client-id
105 access-token: (oauth-tokens-access-token tokens)))
107 ;; ---------------------------------------------------------------
108 ;; Auto-refresh
109 ;; ---------------------------------------------------------------
111 ;;; Ensure tokens are valid (refreshing if needed) and return
112 ;;; both a ready-to-use twitch-client and the (possibly updated)
113 ;;; oauth-tokens record.
114 ;;;
115 ;;; config: oauth-config from twitch-oauth-config
116 ;;; tokens: current oauth-tokens record
117 ;;; 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-client
128 (oauth-config-client-id config)
129 fresh-tokens)))
130 ;; Persist if tokens were refreshed
131 (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 ))