diff --git a/config/config.go b/config/config.go index 28e0378..3bdbd98 100644 --- a/config/config.go +++ b/config/config.go @@ -5,7 +5,6 @@ import ( "os" "github.com/pelletier/go-toml/v2" - "golang.org/x/oauth2" ) type ( @@ -19,7 +18,6 @@ type ( Host string `toml:"host" comment:"Address to host OAuth2 redirect flow"` RedirectUri string `toml:"redirect_uri" comment:"URI to use in Google OAuth2 flow"` Google GoogleConfig `toml:"google"` - Token *oauth2.Token `toml:"token" comment:"This section is filled in automatically on a successful authentication flow."` } ) diff --git a/main.go b/main.go index b6cf248..9344d75 100644 --- a/main.go +++ b/main.go @@ -33,33 +33,6 @@ const MAX_DESCRIPTION_LEN = 5000 func main() { ctx := context.Background() - // config - userConfigDir, err := os.UserConfigDir() - if err != nil { - log.Fatalf("Could not determine user configuration directory: %v", err) - } - config.CONFIG_FILENAME = path.Join(userConfigDir, "vodular", "config.toml") - cfg, err := config.ReadConfig(config.CONFIG_FILENAME) - if err != nil { - log.Fatalf("Failed to read config: %v", err) - } - if cfg == nil { - err = os.MkdirAll(path.Dir(config.CONFIG_FILENAME), 0750) - if err != nil { - log.Fatalf("Failed to create config directory: %v", err) - } - err = config.GenerateConfig(config.CONFIG_FILENAME) - if err != nil { - log.Fatalf("Failed to generate config: %v", err) - } - log.Printf( - "New config file created (%s). " + - "Please edit this file before running again!", - config.CONFIG_FILENAME, - ) - os.Exit(0) - } - var verbose bool = false var initDirectory bool = false var logout bool = false @@ -110,6 +83,43 @@ func main() { } } + // config + userConfigDir, err := os.UserConfigDir() + if err != nil { + log.Fatalf("Could not determine user configuration directory: %v", err) + } + config.CONFIG_FILENAME = path.Join(userConfigDir, "vodular", "config.toml") + cfg, err := config.ReadConfig(config.CONFIG_FILENAME) + if err != nil { + log.Fatalf("Failed to read config: %v", err) + } + if cfg == nil { + if err = os.MkdirAll(path.Dir(config.CONFIG_FILENAME), 0750); err != nil { + log.Fatalf("Failed to create config directory: %v", err) + } + if err = config.GenerateConfig(config.CONFIG_FILENAME); err != nil { + log.Fatalf("Failed to generate config: %v", err) + } + log.Printf( + "New config file created (%s). " + + "Please edit this file before running again!", + config.CONFIG_FILENAME, + ) + os.Exit(0) + } + + oauthTokenFilepath := path.Join(userConfigDir, "vodular", "youtube-auth.json") + var token *oauth2.Token + if data, err := os.ReadFile(oauthTokenFilepath); err != nil { + if !os.IsNotExist(err) { + log.Fatalf("Failed to open %s: %v", oauthTokenFilepath, err) + } + } else { + if err := json.Unmarshal(data, &token); err != nil { + log.Fatalf("Failed to parse YouTube auth file: %v", err) + } + } + if !strings.HasPrefix(directory, "/") { if wd, err := os.Getwd(); err != nil { directory = path.Join(directory, wd) @@ -118,18 +128,16 @@ func main() { // logout (--logout) if logout { - cfg.Token = nil - err = config.WriteConfig(cfg, config.CONFIG_FILENAME) - if err != nil { - log.Fatalf("Failed to write config: %v", err) + if token == nil { log.Fatal("Not logged in.") } + if err := os.Remove(oauthTokenFilepath); err != nil { + log.Fatalf("Failed to delete %s: %v", oauthTokenFilepath, err) } log.Fatalf("Logged out successfully.") } // initialising directory (--init) if initDirectory { - err = scanner.InitialiseDirectory(directory) - if err != nil { + if err = scanner.InitialiseDirectory(directory); err != nil { log.Fatalf("Failed to initialise directory: %v", err) } log.Fatalf( @@ -139,6 +147,8 @@ func main() { ) } + + // good to have early on templates, err := yt.FetchTemplates(path.Join(userConfigDir, "vodular", "templates")) if err != nil { @@ -239,6 +249,8 @@ func main() { log.Printf("[ DESCRIPTION ]\n\n%s\n\n", description) } + + // youtube oauth flow oauth2Config := &oauth2.Config{ ClientID: cfg.Google.ClientID, @@ -247,16 +259,17 @@ func main() { Scopes: []string{ youtube.YoutubeScope }, RedirectURL: cfg.RedirectUri, } - var token *oauth2.Token - if cfg.Token != nil { - token = cfg.Token - } else { + + if token == nil { token, err = oauth.GenerateToken(&ctx, oauth2Config, cfg) - if err != nil { - log.Fatalf("OAuth flow failed: %v", err) + if err != nil { log.Fatalf("OAuth flow failed: %v", err) } + tokenFile, err := os.OpenFile(oauthTokenFilepath, os.O_RDWR | os.O_CREATE, 0600) + if err != nil { log.Fatalf("Failed to open %s: %v", oauthTokenFilepath, err) } + if err := json.NewEncoder(tokenFile).Encode(token); err != nil { + log.Fatalf("Failed to write %s: %v", oauthTokenFilepath, err) } - cfg.Token = token } + tokenSource := oauth2Config.TokenSource(ctx, token) if err != nil { log.Fatalf("Failed to create OAuth2 token source: %v", err) @@ -265,6 +278,8 @@ func main() { log.Fatalf("Failed to save OAuth token: %v", err) } + + service, err := youtube.NewService( ctx, option.WithScopes(youtube.YoutubeUploadScope), @@ -274,6 +289,8 @@ func main() { log.Fatalf("Failed to create youtube service: %v\n", err) } + + // skip uploading if already done if (metadata.Uploaded || len(metadata.UploadURL) > 0) && !forceUpload { if len(metadata.UploadURL) > 0 { @@ -312,6 +329,8 @@ func main() { os.Exit(0) } + + videoMeta.Filepath = path.Join(metadata.FootageDir, vodFiles[0]) // no need to concat if VOD is already one whole file @@ -352,6 +371,8 @@ func main() { } } + + if !dryRun { // okay actually upload now! ytVideo, err := yt.UploadVideo(ctx, tokenSource, service, videoMeta, templates) @@ -375,8 +396,7 @@ func main() { // update metadata to reflect VOD is uploaded metadata.UploadURL = yt.VIDEO_URL_BASE + ytVideo.Id - err = scanner.WriteMetadata(directory, metadata) - if err != nil { + if err = scanner.WriteMetadata(directory, metadata); err != nil { log.Fatalf("Failed to update metadata: %v", err) } diff --git a/oauth/oauth.go b/oauth/oauth.go index 4dee4a8..9102bb9 100644 --- a/oauth/oauth.go +++ b/oauth/oauth.go @@ -61,7 +61,7 @@ func GenerateToken( oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(verifier), ) - fmt.Printf("\nSign in to YouTube: %s\n\n", url) + log.Printf("Sign in to YouTube: %s\n\n", url) wg.Add(1) if err := server.ListenAndServe(); err != http.ErrServerClosed {