Skip to content

Instantly share code, notes, and snippets.

@ZerGo0
Last active January 28, 2024 15:04
Show Gist options
  • Save ZerGo0/aed00b6c51bf7a88b3267f20bafa736b to your computer and use it in GitHub Desktop.
Save ZerGo0/aed00b6c51bf7a88b3267f20bafa736b to your computer and use it in GitHub Desktop.
YouTube OAuth 2 golang
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/youtube/v3"
)
func redirectionHandler(w http.ResponseWriter, req *http.Request) {
code := req.FormValue("code")
if code != "" {
w.Write([]byte("Copy the following auth code and paste it to the terminal:\n\n" + code))
} else {
w.Write([]byte("Error: " + req.FormValue("error")))
}
}
func main() {
srv := &http.Server{Addr: ":8090"}
http.HandleFunc("/", redirectionHandler)
go func() {
err := srv.ListenAndServe()
fmt.Println(err)
}()
// Only needed in first try
fmt.Println("Creating OAuth 2 token file...")
err := CreateOauthToken()
if err != nil {
fmt.Println(err)
os.Exit(1)
} else {
fmt.Println("Create the oauth 2 token file at ~/.credentials successfully")
}
srv.Close()
}
func CreateOauthToken() error {
b, err := os.ReadFile("client_secret.json")
if err != nil {
return err
}
// If modifying the scope, delete your previously saved credentials
// at ./yt-token.json
config, err := google.ConfigFromJSON(b, youtube.YoutubeReadonlyScope, youtube.YoutubeUploadScope, youtube.YoutubeScope)
if err != nil {
return err
}
// Use a redirect URI like this for a web app. The redirect URI must be a
// valid one for your OAuth2 credentials.
config.RedirectURL = "http://localhost:8090"
tok := getTokenFromWeb(config)
_, err = saveToken("yt-token.json", tok)
return err
}
// getTokenFromWeb uses Config to request a Token.
// It returns the retrieved Token.
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser then type the "+
"authorization code: \n%v\n", authURL)
var code string
if _, err := fmt.Scan(&code); err != nil {
log.Fatalf("Unable to read authorization code %v", err)
}
tok, err := config.Exchange(context.Background(), code)
if err != nil {
log.Fatalf("Unable to retrieve token from web %v", err)
}
return tok
}
// tokenFromFile retrieves a Token from a given file path.
// It returns the retrieved Token and any read error encountered.
func tokenFromFile(file string) (*oauth2.Token, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
t := &oauth2.Token{}
err = json.NewDecoder(f).Decode(t)
defer f.Close()
return t, err
}
// saveToken uses a file path to create a file and store the
// token in it.
func saveToken(file string, token *oauth2.Token) (string, error) {
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return "", err
}
defer f.Close()
err = json.NewEncoder(f).Encode(token)
return fmt.Sprintf("Saving credential file to: %s", file), err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment