AtlatestRepositorysigil-youtube
sigil-youtube / tree / src / youtubeoauth.sgl
1
;;; (youtube oauth) - OAuth 2.0 integration for sigil-youtube.2
;;;3
;;; Provides convenience functions for creating YouTube clients4
;;; with OAuth token management via sigil-oauth. Uses the Google5
;;; provider preset with standard YouTube scopes.6
;;;7
;;; This module adds OAuth support alongside the existing manual8
;;; token-passing API — callers can still construct a youtube-client9
;;; directly with an access-token string.11
(define-library (youtube oauth)12
(import (sigil core)13
(sigil dict)14
(sigil struct)15
(sigil oauth)16
(sigil oauth store)17
(youtube))19
(export ;; Config helpers20
youtube-oauth-config22
;; Client construction from tokens23
youtube-oauth-client25
;; Auto-refresh: config + tokens + time → client + tokens26
youtube-ensure-client28
;; Token storage helpers29
youtube-save-tokens30
youtube-load-tokens31
youtube-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 YouTube/Google scopes for System Crafters use.61
;; Covers video management, uploads, analytics, and live streaming.62
(define youtube-default-scopes63
(list "https://www.googleapis.com/auth/youtube"64
"https://www.googleapis.com/auth/yt-analytics.readonly"65
"https://www.googleapis.com/auth/yt-analytics-monetary.readonly"))67
(define youtube-service-name "youtube")69
;; ---------------------------------------------------------------70
;; Config71
;; ---------------------------------------------------------------73
;;; Create an oauth-config for YouTube/Google OAuth2.74
;;;75
;;; client-id: Google Cloud OAuth2 client ID76
;;; client-secret: Google Cloud OAuth2 client secret77
;;;78
;;; Optional keyword args via opts dict:79
;;; scopes: list of scope strings (default: youtube-default-scopes)80
;;; redirect-uri: override redirect URI81
(define (youtube-oauth-config client-id client-secret . rest)82
(let ((opts (if (null? rest) #{} (car rest))))83
(let ((scopes (dict-ref opts scopes: youtube-default-scopes)))84
(oauth-google-config client-id client-secret scopes85
(if (dict-ref opts redirect-uri: #f)86
#{ redirect-uri: (dict-ref opts redirect-uri:) }87
#{})))))89
;; ---------------------------------------------------------------90
;; Client construction91
;; ---------------------------------------------------------------93
;;; Build a youtube-client from an oauth-tokens record.94
;;;95
;;; The access token is extracted from the tokens record.96
;;; An optional api-key can be provided for fallback read-only97
;;; access when the OAuth token is not available.98
(define (youtube-oauth-client tokens . rest)99
(let ((opts (if (null? rest) #{} (car rest))))100
(youtube-client101
access-token: (oauth-tokens-access-token tokens)102
api-key: (dict-ref opts api-key: #f))))104
;; ---------------------------------------------------------------105
;; Auto-refresh106
;; ---------------------------------------------------------------108
;;; Ensure tokens are valid (refreshing if needed) and return109
;;; both a ready-to-use youtube-client and the (possibly updated)110
;;; oauth-tokens record.111
;;;112
;;; config: oauth-config from youtube-oauth-config113
;;; tokens: current oauth-tokens record114
;;; current-time: unix timestamp (from current-second)115
;;;116
;;; Optional keyword args via opts dict:117
;;; api-key: YouTube API key for read-only fallback118
;;; save?: whether to persist refreshed tokens (default: #t)119
;;;120
;;; Returns: (values youtube-client oauth-tokens)121
(define (youtube-ensure-client config tokens current-time . rest)122
(let* ((opts (if (null? rest) #{} (car rest)))123
(save? (dict-ref opts save?: #t))124
(fresh-tokens (oauth-ensure-valid-token config tokens current-time))125
(client (youtube-oauth-client fresh-tokens opts)))126
;; Persist if tokens were refreshed127
(if (and save?128
(not (eq? fresh-tokens tokens)))129
(youtube-save-tokens fresh-tokens))130
(values client fresh-tokens)))132
;; ---------------------------------------------------------------133
;; Token storage (thin wrappers)134
;; ---------------------------------------------------------------136
;;; Save YouTube OAuth tokens to persistent storage.137
(define (youtube-save-tokens tokens)138
(oauth-save-tokens youtube-service-name tokens))140
;;; Load YouTube OAuth tokens from persistent storage.141
;;; Returns oauth-tokens or #f if not found.142
(define (youtube-load-tokens)143
(oauth-load-tokens youtube-service-name))145
;;; Clear stored YouTube OAuth tokens.146
(define (youtube-clear-tokens)147
(oauth-clear-tokens youtube-service-name))149
))