package oauth import ( "context" "fmt" "log" "net/http" "sync" "arimelody.space/vodular/config" "golang.org/x/oauth2" ) func GenerateToken( ctx *context.Context, oauth2Config *oauth2.Config, cfg *config.Config, ) (*oauth2.Token, error) { verifier := oauth2.GenerateVerifier() var token *oauth2.Token wg := sync.WaitGroup{} var server http.Server server.Addr = cfg.Host server.Handler = http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { if !r.URL.Query().Has("code") { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } code := r.URL.Query().Get("code") t, err := oauth2Config.Exchange(*ctx, code, oauth2.VerifierOption(verifier)) if err != nil { log.Fatalf("Could not exchange OAuth2 code: %v", err) http.Error( w, fmt.Sprintf("Could not exchange OAuth2 code: %v", err), http.StatusBadRequest, ) return } token = t http.Error( w, "Authentication successful! You may now close this tab.", http.StatusOK, ) if f, ok := w.(http.Flusher); ok { f.Flush() } wg.Done() server.Close() }, ) url := oauth2Config.AuthCodeURL( "state", oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(verifier), ) fmt.Printf("\nSign in to YouTube: %s\n\n", url) wg.Add(1) if err := server.ListenAndServe(); err != http.ErrServerClosed { return nil, fmt.Errorf("http: %v", err) } wg.Wait() return token, nil }