From 791587417abf4d4989af6bde58218a2ba556356f Mon Sep 17 00:00:00 2001 From: Victor Hang Date: Tue, 22 Oct 2024 10:04:21 +0200 Subject: [PATCH] =?UTF-8?q?feat=20=E2=9C=A8(cmd):=20add=20msg=20output=20t?= =?UTF-8?q?o=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Hang --- cmd/query_history.go | 30 ++++++++++++++++++++--- cmd/query_search.go | 31 ++++++++++++++++++++--- cmd/query_subscribed.go | 33 ++++++++++++++++++++++--- cmd/show_suscribed.go | 54 +++++++++++++++++++++++++++++------------ 4 files changed, 123 insertions(+), 25 deletions(-) diff --git a/cmd/query_history.go b/cmd/query_history.go index 5eb93b3..cd63ce3 100644 --- a/cmd/query_history.go +++ b/cmd/query_history.go @@ -1,6 +1,3 @@ -/* -Copyright © 2024 Victor Hang -*/ package cmd import ( @@ -29,34 +26,52 @@ ytui will feed and store its own history in a json file in the configuration dir will be stored in there.`, Run: func(cmd *cobra.Command, args []string) { utils.Logger.Info("History command initiated.") + fmt.Println("Fetching video history...") + // Get the config directory configDir, err := config.GetConfigDirPath() if err != nil { utils.Logger.Error("Failed to get config path.", zap.Error(err)) + fmt.Println("Error: Unable to retrieve configuration path.") os.Exit(1) } utils.Logger.Debug("Configuration directory obtained.", zap.String("config_dir", configDir)) + // Get the history file path historyFile := filepath.Join(configDir, "watched_history.json") utils.Logger.Debug("Reading watched history from file.", zap.String("history_file", historyFile)) + // Fetch the watched videos from the history file result, err := youtube.GetWatchedVideos(historyFile) if err != nil { utils.Logger.Error("Failed to read history from file.", zap.Error(err)) + fmt.Println("Error: Unable to read video history.") os.Exit(1) } + + // Handle the case of no videos found if len(result) == 0 { utils.Logger.Info("No videos found in history.") - fmt.Println("No videos found.") + fmt.Println("No videos found in history.") os.Exit(0) } + utils.Logger.Info("Videos found in history.", zap.Int("video_count", len(result))) + fmt.Printf("Found %d videos in your history.\n", len(result)) + + // Show the FZF menu to select a video selectedVideo, err := youtube.YoutubeResultMenu(result, viper.GetString("invidious.instance"), viper.GetString("invidious.proxy")) if err != nil { utils.Logger.Info("FZF menu closed.") + fmt.Println("History search cancelled.") os.Exit(0) } + + // Construct the video URL for the selected video videoURL := "https://www.youtube.com/watch?v=" + selectedVideo.VideoID + fmt.Printf("Selected video: %s\n", selectedVideo.VideoID) + + // Handle download or playback if downloadFlag { var downloadDirStr string if downloadDirFlag != "" { @@ -66,14 +81,21 @@ will be stored in there.`, } utils.Logger.Info("Downloading selected video with yt-dlp.", zap.String("video_url", videoURL)) downloadDir := downloadDirStr + fmt.Println("Downloading selected video...") download.RunYTDLP(videoURL, downloadDir) + fmt.Println("Download completed.") } else { utils.Logger.Info("Playing selected video in MPV.", zap.String("video_url", videoURL)) + fmt.Println("Playing selected video in MPV...") + player.RunMPV(videoURL) + + // Add to watch history if history is enabled if viper.GetBool("history.enable") { historyFilePath := filepath.Join(configDir, "watched_history.json") youtube.FeedHistory(selectedVideo, historyFilePath) utils.Logger.Info("Video added to watch history.", zap.String("video_id", selectedVideo.VideoID)) + fmt.Println("Video added to watch history.") } } }, diff --git a/cmd/query_search.go b/cmd/query_search.go index 742560b..35477bf 100644 --- a/cmd/query_search.go +++ b/cmd/query_search.go @@ -1,9 +1,7 @@ -/* -Copyright © 2024 Victor Hang -*/ package cmd import ( + "fmt" "os" "path/filepath" @@ -30,40 +28,60 @@ Press enter to run any of the videos.`, if len(args) != 1 { cmd.Help() //nolint:all utils.Logger.Error("Invalid number of arguments provided for 'search' command.") + fmt.Println("Error: Please provide a single search query.") os.Exit(0) } + query := args[0] utils.Logger.Info("Search command initiated.", zap.String("query", query)) + fmt.Printf("Searching for videos with query: %s\n", query) + configDir, err := config.GetConfigDirPath() if err != nil { utils.Logger.Fatal("Failed to get config path.", zap.Error(err)) + fmt.Println("Error: Failed to retrieve configuration path.") os.Exit(1) } utils.Logger.Debug("Config directory retrieved.", zap.String("config_dir", configDir)) + configPath := filepath.Join(configDir, "config.yaml") if err := config.ReadConfig(configPath); err != nil { utils.Logger.Fatal("Failed to read config.", zap.Error(err)) + fmt.Println("Error: Failed to read configuration file.") + os.Exit(1) } utils.Logger.Debug("Config file read successfully.", zap.String("config_file", configPath)) + // Search for videos result, err := youtube.SearchVideos(query, viper.GetString("invidious.instance"), viper.GetString("invidious.proxy"), false) if err != nil { utils.Logger.Fatal("Error searching for videos.", zap.Error(err)) + fmt.Println("Error: Failed to search for videos.") os.Exit(1) } if len(*result) == 0 { utils.Logger.Info("No videos found for the query.", zap.String("query", query)) + fmt.Printf("No videos found for query: %s\n", query) os.Exit(0) } utils.Logger.Info("Videos found.", zap.Int("video_count", len(*result))) + fmt.Printf("Found %d videos for query: %s\n", len(*result), query) + + // Display search results in FZF menu selectedVideo, err := youtube.YoutubeResultMenu(*result, viper.GetString("invidious.instance"), viper.GetString("invidious.proxy")) if err != nil { utils.Logger.Info("FZF menu closed.") + fmt.Println("Search cancelled.") os.Exit(0) } + + // Build the video URL videoURL := "https://www.youtube.com/watch?v=" + selectedVideo.VideoID + fmt.Printf("Selected video: %s\n", selectedVideo.VideoID) + + // Handle video playback or download if downloadFlag { var downloadDirStr string if downloadDirFlag != "" { @@ -73,14 +91,21 @@ Press enter to run any of the videos.`, } utils.Logger.Info("Downloading selected video with yt-dlp.", zap.String("video_url", videoURL)) downloadDir := downloadDirStr + fmt.Println("Downloading selected video...") download.RunYTDLP(videoURL, downloadDir) + fmt.Println("Download completed.") } else { utils.Logger.Info("Playing selected video in MPV.", zap.String("video_url", videoURL)) + fmt.Println("Playing selected video in MPV...") + player.RunMPV(videoURL) + + // Add to watch history if enabled if viper.GetBool("history.enable") { historyFilePath := filepath.Join(configDir, "watched_history.json") youtube.FeedHistory(selectedVideo, historyFilePath) utils.Logger.Info("Video added to watch history.", zap.String("video_id", selectedVideo.VideoID)) + fmt.Println("Video added to watch history.") } } }, diff --git a/cmd/query_subscribed.go b/cmd/query_subscribed.go index 5f6c08b..afb3f6d 100644 --- a/cmd/query_subscribed.go +++ b/cmd/query_subscribed.go @@ -1,9 +1,7 @@ -/* -Copyright © 2024 Victor Hang -*/ package cmd import ( + "fmt" "os" "path/filepath" @@ -30,52 +28,75 @@ to retrieve your user informations. You must also configure your OAuth2 client i It will also only pick from the 50 most relevants subscribed channels in your Youtube account.`, Run: func(cmd *cobra.Command, args []string) { utils.Logger.Info("Command 'subscribed' executed.") + fmt.Println("Executing 'subscribed' command...") // Print a simple status message. + var result *[]youtube.SearchResultItem var err error + // Read the config file configDir, err := config.GetConfigDirPath() if err != nil { utils.Logger.Fatal("Failed to get config path.", zap.Error(err)) + fmt.Println("Error: Failed to get config path.") os.Exit(1) } utils.Logger.Debug("Config directory retrieved.", zap.String("config_dir", configDir)) configPath := filepath.Join(configDir, "config.yaml") if err := config.ReadConfig(configPath); err != nil { utils.Logger.Fatal("Failed to read config.", zap.Error(err)) + fmt.Println("Error: Failed to read config.") + os.Exit(1) } utils.Logger.Debug("Config file read successfully.", zap.String("config_file", configPath)) + clientID := viper.GetString("youtube.clientid") secretID := viper.GetString("youtube.secretid") utils.Logger.Debug("Retrieved YouTube API credentials.", zap.String("client_id", clientID)) + if !viper.GetBool("channels.local") { utils.Logger.Info("Local configuration is false. Starting YouTube API authentication.") + fmt.Println("Authenticating with YouTube API...") + apiChan, err := youtube.NewYouTubeAPI(clientID, secretID) if err != nil { utils.Logger.Fatal("Failed to authenticate to YouTube API.", zap.Error(err)) + fmt.Println("Error: Failed to authenticate with YouTube API.") os.Exit(1) } yt := <-apiChan utils.Logger.Info("YouTube API authenticated successfully.") + fmt.Println("YouTube API authenticated successfully.") + result, err = yt.GetAllSubscribedChannelsVideos(viper.GetString("invidious.instance"), viper.GetString("invidious.proxy")) if err != nil { utils.Logger.Fatal("Failed to get all subscribed channels videos.", zap.Error(err)) + fmt.Println("Error: Failed to retrieve subscribed channels videos.") os.Exit(1) } } else { utils.Logger.Info("Using local configuration for subscribed channels.") + fmt.Println("Retrieving subscribed channels from local configuration...") + result, err = youtube.GetLocalSubscribedChannelsVideos(viper.GetString("invidious.instance"), viper.GetString("invidious.proxy"), viper.GetStringSlice("channels.subscribed")) if err != nil { utils.Logger.Fatal("Failed to get local subscribed channels videos.", zap.Error(err)) + fmt.Println("Error: Failed to retrieve local subscribed channels videos.") os.Exit(1) } } + utils.Logger.Info("Retrieved videos from subscribed channels.", zap.Int("video_count", len(*result))) + fmt.Printf("Found %d videos from subscribed channels.\n", len(*result)) + selectedVideo, err := youtube.YoutubeResultMenu(*result, viper.GetString("invidious.instance"), viper.GetString("invidious.proxy")) if err != nil { utils.Logger.Info("FZF menu closed.") + fmt.Println("Video selection cancelled.") os.Exit(0) } utils.Logger.Info("Selected video for playback.", zap.String("video_id", selectedVideo.VideoID)) + fmt.Printf("Selected video: %s\n", selectedVideo.VideoID) + videoURL := "https://www.youtube.com/watch?v=" + selectedVideo.VideoID if downloadFlag { var downloadDirStr string @@ -86,14 +107,20 @@ It will also only pick from the 50 most relevants subscribed channels in your Yo } utils.Logger.Info("Downloading selected video with yt-dlp.", zap.String("video_url", videoURL)) downloadDir := downloadDirStr + fmt.Println("Downloading selected video...") download.RunYTDLP(videoURL, downloadDir) + fmt.Println("Download completed.") } else { utils.Logger.Info("Playing selected video in MPV.", zap.String("video_url", videoURL)) + fmt.Println("Playing selected video in MPV...") + player.RunMPV(videoURL) + if viper.GetBool("history.enable") { historyFilePath := filepath.Join(configDir, "watched_history.json") youtube.FeedHistory(selectedVideo, historyFilePath) utils.Logger.Info("Video added to watch history.", zap.String("video_id", selectedVideo.VideoID)) + fmt.Println("Video added to watch history.") } } }, diff --git a/cmd/show_suscribed.go b/cmd/show_suscribed.go index 6fa0b9f..d795bc4 100644 --- a/cmd/show_suscribed.go +++ b/cmd/show_suscribed.go @@ -1,6 +1,3 @@ -/* -Copyright © 2024 Victor Hang -*/ package cmd import ( @@ -25,63 +22,90 @@ const ( // subscribedCmd represents the subscribed command var showSubscribedCmd = &cobra.Command{ Use: "subscribed", - Short: "show subscribed channels", + Short: "Show subscribed channels", Long: ` -show your subscribed channels. -If you set the configuration "local: false" in the configuration file, it will prompt you to google login, -to retrieve your user informations. You must also configure your OAuth2 client in Google Dev Console first. +Show your subscribed channels. +If you set the configuration "local: false" in the configuration file, it will prompt you to Google login +to retrieve your user information. You must also configure your OAuth2 client in Google Dev Console first. -It will also only pick from the 50 most relevants subscribed channels in your Youtube account.`, +It will also only pick from the 50 most relevant subscribed channels in your Youtube account.`, Run: func(cmd *cobra.Command, args []string) { utils.Logger.Info("Command 'subscribed' executed.") + fmt.Println("Retrieving your subscribed channels...") + var channelList []string var err error - // Read the config file + + // Get the config directory configDir, err := config.GetConfigDirPath() if err != nil { - utils.Logger.Fatal("Failed to get config path.", zap.Error(err)) + utils.Logger.Error("Failed to get config path.", zap.Error(err)) + fmt.Println("Error: Unable to retrieve configuration path.") os.Exit(1) } utils.Logger.Debug("Config directory retrieved.", zap.String("config_dir", configDir)) + + // Read the config file configPath := filepath.Join(configDir, "config.yaml") if err := config.ReadConfig(configPath); err != nil { - utils.Logger.Fatal("Failed to read config.", zap.Error(err)) + utils.Logger.Error("Failed to read config.", zap.Error(err)) + fmt.Println("Error: Unable to read configuration.") + os.Exit(1) } utils.Logger.Debug("Config file read successfully.", zap.String("config_file", configPath)) + + // Retrieve YouTube API credentials clientID := viper.GetString("youtube.clientid") secretID := viper.GetString("youtube.secretid") - utils.Logger.Debug("Retrieved YouTube API credentials.", zap.String("client_id", clientID)) + utils.Logger.Debug("YouTube API credentials retrieved.", zap.String("client_id", clientID)) + + // Check if local or remote API should be used if !viper.GetBool("channels.local") { + utils.Logger.Info("Using YouTube API to fetch subscribed channels.") + fmt.Println("Authenticating with YouTube API...") + + // Authenticate with YouTube API apiChan, err := youtube.NewYouTubeAPI(clientID, secretID) if err != nil { - utils.Logger.Fatal("Failed to authenticate to YouTube API.", zap.Error(err)) + utils.Logger.Error("Failed to authenticate to YouTube API.", zap.Error(err)) + fmt.Println("Error: Authentication with YouTube API failed.") os.Exit(1) } yt := <-apiChan utils.Logger.Info("YouTube API authenticated successfully.") + // Get the list of subscribed channels channelList, err = yt.GetSubscribedChannels(YoutubeSubscriptionsURL) if err != nil { - utils.Logger.Fatal("Failed to retrieve channels list.", zap.Error(err)) + utils.Logger.Error("Failed to retrieve channels list.", zap.Error(err)) + fmt.Println("Error: Unable to retrieve subscribed channels.") os.Exit(1) } utils.Logger.Info("Retrieved subscribed channels list.", zap.Int("channel_count", len(channelList))) } else { + utils.Logger.Info("Using local configuration for subscribed channels.") channelList = viper.GetStringSlice("channels.subscribed") utils.Logger.Info("Retrieved local subscribed channels.", zap.Int("channel_count", len(channelList))) } + + // Get detailed information on channels + fmt.Println("Fetching subscribed channels information...") channels, err := youtube.GetAllChannelsInfo(channelList, viper.GetString("invidious.instance"), viper.GetString("invidious.proxy")) if err != nil { - utils.Logger.Fatal("Failed to get all channels data.", zap.Error(err)) + utils.Logger.Error("Failed to get channels data.", zap.Error(err)) + fmt.Println("Error: Unable to retrieve channel information.") os.Exit(1) } utils.Logger.Info("Retrieved all channels information.", zap.Int("channel_count", len(channels))) + + // Display the list of channels for _, channel := range channels { fmt.Printf("\n") fmt.Printf("Author: %s\n", channel.Author) fmt.Printf("Author URL: %s\n", channel.AuthorUrl) fmt.Println(strings.Repeat("-", 30)) } + fmt.Println("Successfully retrieved and displayed your subscribed channels.") }, }