From 575e4a947cfbe698af25b0221050b18c14344b64 Mon Sep 17 00:00:00 2001 From: OpenWaygate <27287694+OpenWaygate@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:54:30 +0800 Subject: [PATCH] :goal_net: Improve err handling --- cmd/activity/list.go | 2 +- cmd/caption/download.go | 2 +- cmd/caption/insert.go | 2 +- cmd/caption/list.go | 2 +- cmd/caption/update.go | 2 +- cmd/channel/list.go | 7 +- cmd/channel/update.go | 7 +- cmd/channelBanner/insert.go | 7 +- cmd/channelSection/delete.go | 7 +- cmd/channelSection/list.go | 7 +- cmd/comment/delete.go | 7 +- cmd/comment/insert.go | 7 +- cmd/comment/list.go | 7 +- cmd/comment/markAsSpam.go | 7 +- cmd/comment/setModerationStatus.go | 7 +- cmd/comment/update.go | 7 +- cmd/commentThread/insert.go | 7 +- cmd/commentThread/list.go | 7 +- cmd/i18nLanguage/list.go | 7 +- cmd/i18nRegion/list.go | 7 +- cmd/member/list.go | 7 +- cmd/membershipsLevel/list.go | 7 +- cmd/playlist/delete.go | 7 +- cmd/playlist/insert.go | 7 +- cmd/playlist/list.go | 7 +- cmd/playlist/update.go | 7 +- cmd/playlistImage/delete.go | 7 +- cmd/playlistImage/insert.go | 7 +- cmd/playlistImage/list.go | 7 +- cmd/playlistImage/update.go | 7 +- cmd/playlistItem/delete.go | 7 +- cmd/playlistItem/insert.go | 7 +- cmd/playlistItem/list.go | 7 +- cmd/playlistItem/update.go | 7 +- cmd/search/list.go | 7 +- cmd/subscription/delete.go | 7 +- cmd/subscription/insert.go | 7 +- cmd/subscription/list.go | 7 +- cmd/superChatEvent/list.go | 7 +- cmd/thumbnail/set.go | 7 +- cmd/video/delete.go | 7 +- cmd/video/getRating.go | 7 +- cmd/video/insert.go | 7 +- cmd/video/list.go | 7 +- cmd/video/rate.go | 7 +- cmd/video/reportAbuse.go | 7 +- cmd/video/update.go | 7 +- cmd/videoAbuseReportReason/list.go | 7 +- cmd/videoCategory/list.go | 7 +- cmd/watermark/set.go | 7 +- cmd/watermark/unset.go | 7 +- pkg/BUILD.bazel | 8 ++ pkg/activity/activity.go | 6 +- pkg/caption/caption.go | 10 +- pkg/channel/channel.go | 55 +++++--- pkg/channelBanner/channelBanner.go | 19 ++- pkg/channelSection/channelSection.go | 46 ++++--- pkg/comment/comment.go | 110 ++++++++------- pkg/commentThread/commentThread.go | 49 ++++--- pkg/i18nLanguage/i18nLanguage.go | 34 +++-- pkg/i18nRegion/i18nRegion.go | 34 +++-- pkg/interface.go | 29 ++++ pkg/member/member.go | 32 +++-- pkg/membershipsLevel/membershipsLevel.go | 36 +++-- pkg/playlist/playlist.go | 79 ++++++----- pkg/playlistImage/playlistImage.go | 87 +++++++----- pkg/playlistItem/playlistItem.go | 84 +++++++----- pkg/search/search.go | 32 +++-- pkg/subscription/subscription.go | 58 ++++---- pkg/superChatEvent/superChatEvent.go | 34 +++-- pkg/thumbnail/thumbnail.go | 20 +-- pkg/video/video.go | 127 ++++++++++-------- .../videoAbuseReportReason.go | 38 +++--- pkg/videoCategory/videoCategory.go | 35 ++--- pkg/watermark/BUILD.bazel | 1 - pkg/watermark/watermark.go | 27 ++-- 76 files changed, 918 insertions(+), 504 deletions(-) create mode 100644 pkg/BUILD.bazel create mode 100644 pkg/interface.go diff --git a/cmd/activity/list.go b/cmd/activity/list.go index c37c454..5aa8053 100644 --- a/cmd/activity/list.go +++ b/cmd/activity/list.go @@ -72,7 +72,7 @@ var listCmd = &cobra.Command{ err := run(cmd.OutOrStdout()) if err != nil { _ = cmd.Help() - cmd.PrintErrf("Error: %s\n", err.Error()) + cmd.PrintErrf("Error: %v\n", err) } }, } diff --git a/cmd/caption/download.go b/cmd/caption/download.go index 72270f2..74766ff 100644 --- a/cmd/caption/download.go +++ b/cmd/caption/download.go @@ -29,7 +29,7 @@ var downloadCmd = &cobra.Command{ err := c.Download(cmd.OutOrStdout()) if err != nil { _ = cmd.Help() - cmd.PrintErrf("Error: %s\n", err.Error()) + cmd.PrintErrf("Error: %v\n", err) } }, } diff --git a/cmd/caption/insert.go b/cmd/caption/insert.go index c768fc9..6b786bd 100644 --- a/cmd/caption/insert.go +++ b/cmd/caption/insert.go @@ -36,7 +36,7 @@ var insertCmd = &cobra.Command{ err := c.Insert(output, cmd.OutOrStdout()) if err != nil { _ = cmd.Help() - cmd.PrintErrf("Error: %s\n", err.Error()) + cmd.PrintErrf("Error: %v\n", err) } }, } diff --git a/cmd/caption/list.go b/cmd/caption/list.go index 5dce270..759f337 100644 --- a/cmd/caption/list.go +++ b/cmd/caption/list.go @@ -28,7 +28,7 @@ var listCmd = &cobra.Command{ err := c.List(parts, output, cmd.OutOrStdout()) if err != nil { _ = cmd.Help() - cmd.PrintErrf("Error: %s\n", err.Error()) + cmd.PrintErrf("Error: %v\n", err) } }, } diff --git a/cmd/caption/update.go b/cmd/caption/update.go index fcefe11..c92675b 100644 --- a/cmd/caption/update.go +++ b/cmd/caption/update.go @@ -36,7 +36,7 @@ var updateCmd = &cobra.Command{ err := c.Update(output, cmd.OutOrStdout()) if err != nil { _ = cmd.Help() - cmd.PrintErrf("Error: %s\n", err.Error()) + cmd.PrintErrf("Error: %v\n", err) } }, } diff --git a/cmd/channel/list.go b/cmd/channel/list.go index 20af1d9..afc88e5 100644 --- a/cmd/channel/list.go +++ b/cmd/channel/list.go @@ -30,7 +30,12 @@ var listCmd = &cobra.Command{ channel.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), channel.WithService(nil), ) - c.List(parts, output) + + err := c.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/channel/update.go b/cmd/channel/update.go index 3c6cebc..2dfd822 100644 --- a/cmd/channel/update.go +++ b/cmd/channel/update.go @@ -26,7 +26,12 @@ var updateCmd = &cobra.Command{ channel.WithTitle(title), channel.WithService(nil), ) - c.Update(output) + + err := c.Update(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/channelBanner/insert.go b/cmd/channelBanner/insert.go index 1140721..0054884 100644 --- a/cmd/channelBanner/insert.go +++ b/cmd/channelBanner/insert.go @@ -17,7 +17,12 @@ var insertCmd = &cobra.Command{ channelBanner.WithOnBehalfOfContentOwnerChannel(onBehalfOfContentOwnerChannel), channelBanner.WithService(nil), ) - cb.Insert(output) + + err := cb.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/channelSection/delete.go b/cmd/channelSection/delete.go index e8a90bc..bc01b77 100644 --- a/cmd/channelSection/delete.go +++ b/cmd/channelSection/delete.go @@ -21,7 +21,12 @@ var deleteCmd = &cobra.Command{ channelSection.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), channelSection.WithService(nil), ) - cs.Delete() + + err := cs.Delete(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/channelSection/list.go b/cmd/channelSection/list.go index 7c5980a..90ef486 100644 --- a/cmd/channelSection/list.go +++ b/cmd/channelSection/list.go @@ -24,7 +24,12 @@ var listCmd = &cobra.Command{ channelSection.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), channelSection.WithService(nil), ) - cs.List(parts, output) + + err := cs.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/comment/delete.go b/cmd/comment/delete.go index 53fab51..d48767f 100644 --- a/cmd/comment/delete.go +++ b/cmd/comment/delete.go @@ -19,7 +19,12 @@ var deleteCmd = &cobra.Command{ comment.WithIDs(ids), comment.WithService(nil), ) - c.Delete() + + err := c.Delete(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/comment/insert.go b/cmd/comment/insert.go index 5b4ef89..05a61b5 100644 --- a/cmd/comment/insert.go +++ b/cmd/comment/insert.go @@ -26,7 +26,12 @@ var insertCmd = &cobra.Command{ comment.WithVideoId(videoId), comment.WithService(nil), ) - c.Insert(output) + + err := c.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/comment/list.go b/cmd/comment/list.go index 8a3cfa1..5bbdd0c 100644 --- a/cmd/comment/list.go +++ b/cmd/comment/list.go @@ -24,7 +24,12 @@ var listCmd = &cobra.Command{ comment.WithTextFormat(textFormat), comment.WithService(nil), ) - c.List(parts, output) + + err := c.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/comment/markAsSpam.go b/cmd/comment/markAsSpam.go index 91274c0..98ed58d 100644 --- a/cmd/comment/markAsSpam.go +++ b/cmd/comment/markAsSpam.go @@ -20,7 +20,12 @@ var markAsSpamCmd = &cobra.Command{ comment.WithIDs(ids), comment.WithService(nil), ) - c.MarkAsSpam(output) + + err := c.MarkAsSpam(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/comment/setModerationStatus.go b/cmd/comment/setModerationStatus.go index 218be6a..c85d961 100644 --- a/cmd/comment/setModerationStatus.go +++ b/cmd/comment/setModerationStatus.go @@ -21,7 +21,12 @@ var setModerationStatusCmd = &cobra.Command{ comment.WithModerationStatus(moderationStatus), comment.WithBanAuthor(banAuthor), ) - c.SetModerationStatus(output) + + err := c.SetModerationStatus(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/comment/update.go b/cmd/comment/update.go index 1efd264..0b871bc 100644 --- a/cmd/comment/update.go +++ b/cmd/comment/update.go @@ -24,7 +24,12 @@ var updateCmd = &cobra.Command{ comment.WithViewerRating(viewerRating), comment.WithService(nil), ) - c.Update(output) + + err := c.Update(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/commentThread/insert.go b/cmd/commentThread/insert.go index 3604d00..f560b7a 100644 --- a/cmd/commentThread/insert.go +++ b/cmd/commentThread/insert.go @@ -23,7 +23,12 @@ var insertCmd = &cobra.Command{ commentThread.WithVideoId(videoId), commentThread.WithService(nil), ) - ct.Insert(output) + + err := ct.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/commentThread/list.go b/cmd/commentThread/list.go index 4cc53db..16e27cd 100644 --- a/cmd/commentThread/list.go +++ b/cmd/commentThread/list.go @@ -28,7 +28,12 @@ var listCmd = &cobra.Command{ commentThread.WithVideoId(videoId), commentThread.WithService(nil), ) - ct.List(parts, output) + + err := ct.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/i18nLanguage/list.go b/cmd/i18nLanguage/list.go index 4495b59..b0f8125 100644 --- a/cmd/i18nLanguage/list.go +++ b/cmd/i18nLanguage/list.go @@ -13,7 +13,12 @@ var listCmd = &cobra.Command{ i := i18nLanguage.NewI18nLanguage( i18nLanguage.WithHl(hl), i18nLanguage.WithService(nil), ) - i.List(parts, output) + + err := i.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/i18nRegion/list.go b/cmd/i18nRegion/list.go index 785dd8c..ca79e02 100644 --- a/cmd/i18nRegion/list.go +++ b/cmd/i18nRegion/list.go @@ -13,7 +13,12 @@ var listCmd = &cobra.Command{ i := i18nRegion.NewI18nRegion( i18nRegion.WithHl(hl), i18nRegion.WithService(nil), ) - i.List(parts, output) + + err := i.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/member/list.go b/cmd/member/list.go index d7b84ee..126b054 100644 --- a/cmd/member/list.go +++ b/cmd/member/list.go @@ -17,7 +17,12 @@ var listCmd = &cobra.Command{ member.WithMode(mode), member.WithService(nil), ) - m.List(parts, output) + + err := m.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/membershipsLevel/list.go b/cmd/membershipsLevel/list.go index fb7e05e..52730fd 100644 --- a/cmd/membershipsLevel/list.go +++ b/cmd/membershipsLevel/list.go @@ -11,7 +11,12 @@ var listCmd = &cobra.Command{ Long: long, Run: func(cmd *cobra.Command, args []string) { m := membershipsLevel.NewMembershipsLevel(membershipsLevel.WithService(nil)) - m.List(parts, output) + + err := m.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlist/delete.go b/cmd/playlist/delete.go index 5933f8e..7cae50a 100644 --- a/cmd/playlist/delete.go +++ b/cmd/playlist/delete.go @@ -21,7 +21,12 @@ var deleteCmd = &cobra.Command{ playlist.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), playlist.WithService(nil), ) - p.Delete() + + err := p.Delete(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlist/insert.go b/cmd/playlist/insert.go index 158e6b2..dd1a97a 100644 --- a/cmd/playlist/insert.go +++ b/cmd/playlist/insert.go @@ -26,7 +26,12 @@ var insertCmd = &cobra.Command{ playlist.WithPrivacy(privacy), playlist.WithService(nil), ) - p.Insert(output) + + err := p.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlist/list.go b/cmd/playlist/list.go index 611e012..3b88a77 100644 --- a/cmd/playlist/list.go +++ b/cmd/playlist/list.go @@ -28,7 +28,12 @@ var listCmd = &cobra.Command{ playlist.WithOnBehalfOfContentOwnerChannel(onBehalfOfContentOwnerChannel), playlist.WithService(nil), ) - p.List(parts, output) + + err := p.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlist/update.go b/cmd/playlist/update.go index 9914973..c9bdeb5 100644 --- a/cmd/playlist/update.go +++ b/cmd/playlist/update.go @@ -26,7 +26,12 @@ var updateCmd = &cobra.Command{ playlist.WithPrivacy(privacy), playlist.WithService(nil), ) - p.Update(output) + + err := p.Update(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistImage/delete.go b/cmd/playlistImage/delete.go index 533697b..209ff18 100644 --- a/cmd/playlistImage/delete.go +++ b/cmd/playlistImage/delete.go @@ -20,7 +20,12 @@ var deleteCmd = &cobra.Command{ playlistImage.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), playlistImage.WithService(nil), ) - pi.Delete() + + err := pi.Delete(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistImage/insert.go b/cmd/playlistImage/insert.go index 4d8c1c1..d646d52 100644 --- a/cmd/playlistImage/insert.go +++ b/cmd/playlistImage/insert.go @@ -24,7 +24,12 @@ var insertCmd = &cobra.Command{ playlistImage.WithWidth(width), playlistImage.WithService(nil), ) - pi.Insert(output) + + err := pi.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistImage/list.go b/cmd/playlistImage/list.go index 05e1d60..903fdb2 100644 --- a/cmd/playlistImage/list.go +++ b/cmd/playlistImage/list.go @@ -23,7 +23,12 @@ var listCmd = &cobra.Command{ playlistImage.WithMaxResults(maxResults), playlistImage.WithService(nil), ) - pi.List(parts, output) + + err := pi.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistImage/update.go b/cmd/playlistImage/update.go index cb00f1b..50b40b9 100644 --- a/cmd/playlistImage/update.go +++ b/cmd/playlistImage/update.go @@ -23,7 +23,12 @@ var updateCmd = &cobra.Command{ playlistImage.WithWidth(width), playlistImage.WithService(nil), ) - pi.Update(output) + + err := pi.Update(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistItem/delete.go b/cmd/playlistItem/delete.go index 331c71e..4283768 100644 --- a/cmd/playlistItem/delete.go +++ b/cmd/playlistItem/delete.go @@ -21,7 +21,12 @@ var deleteCmd = &cobra.Command{ playlistItem.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), playlistItem.WithService(nil), ) - pi.Delete() + + err := pi.Delete(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistItem/insert.go b/cmd/playlistItem/insert.go index 9f9df52..4808e67 100644 --- a/cmd/playlistItem/insert.go +++ b/cmd/playlistItem/insert.go @@ -30,7 +30,12 @@ var insertCmd = &cobra.Command{ playlistItem.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), playlistItem.WithService(nil), ) - pi.Insert(output) + + err := pi.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistItem/list.go b/cmd/playlistItem/list.go index 5faa143..8e69769 100644 --- a/cmd/playlistItem/list.go +++ b/cmd/playlistItem/list.go @@ -26,7 +26,12 @@ var listCmd = &cobra.Command{ playlistItem.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), playlistItem.WithService(nil), ) - pi.List(parts, output) + + err := pi.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/playlistItem/update.go b/cmd/playlistItem/update.go index 83ad6c2..d47573a 100644 --- a/cmd/playlistItem/update.go +++ b/cmd/playlistItem/update.go @@ -25,7 +25,12 @@ var updateCmd = &cobra.Command{ playlistItem.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), playlistItem.WithService(nil), ) - pi.Update(output) + + err := pi.Update(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/search/list.go b/cmd/search/list.go index 029b7b6..7f7745a 100644 --- a/cmd/search/list.go +++ b/cmd/search/list.go @@ -42,7 +42,12 @@ var listCmd = &cobra.Command{ search.WithVideoType(videoType), search.WithService(nil), ) - s.List(parts, output) + + err := s.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/subscription/delete.go b/cmd/subscription/delete.go index edc813d..1361db3 100644 --- a/cmd/subscription/delete.go +++ b/cmd/subscription/delete.go @@ -19,7 +19,12 @@ var deleteCmd = &cobra.Command{ s := subscription.NewSubscription( subscription.WithIDs(ids), subscription.WithService(nil), ) - s.Delete() + + err := s.Delete(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/subscription/insert.go b/cmd/subscription/insert.go index 1d0febf..990d14a 100644 --- a/cmd/subscription/insert.go +++ b/cmd/subscription/insert.go @@ -24,7 +24,12 @@ var insertCmd = &cobra.Command{ subscription.WithTitle(title), subscription.WithService(nil), ) - s.Insert(output) + + err := s.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/subscription/list.go b/cmd/subscription/list.go index 64c54d4..5f13547 100644 --- a/cmd/subscription/list.go +++ b/cmd/subscription/list.go @@ -31,7 +31,12 @@ var listCmd = &cobra.Command{ subscription.WithOrder(order), subscription.WithService(nil), ) - s.List(parts, output) + + err := s.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/superChatEvent/list.go b/cmd/superChatEvent/list.go index 6c9a7f2..59cd88a 100644 --- a/cmd/superChatEvent/list.go +++ b/cmd/superChatEvent/list.go @@ -15,7 +15,12 @@ var listCmd = &cobra.Command{ superChatEvent.WithMaxResults(maxResults), superChatEvent.WithService(nil), ) - sc.List(parts, output) + + err := sc.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/thumbnail/set.go b/cmd/thumbnail/set.go index 0bf8127..560c4d1 100644 --- a/cmd/thumbnail/set.go +++ b/cmd/thumbnail/set.go @@ -15,7 +15,12 @@ var setCmd = &cobra.Command{ thumbnail.WithVideoId(videoId), thumbnail.WithService(nil), ) - t.Set(output) + + err := t.Set(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/video/delete.go b/cmd/video/delete.go index 3a3d5a0..cf9d4f4 100644 --- a/cmd/video/delete.go +++ b/cmd/video/delete.go @@ -17,7 +17,12 @@ var deleteCmd = &cobra.Command{ Long: deleteLong, Run: func(cmd *cobra.Command, args []string) { v := video.NewVideo(video.WithIDs(ids)) - v.Delete() + + err := v.Delete(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/video/getRating.go b/cmd/video/getRating.go index a4e04de..eca8561 100644 --- a/cmd/video/getRating.go +++ b/cmd/video/getRating.go @@ -22,7 +22,12 @@ var getRatingCmd = &cobra.Command{ video.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), video.WithService(nil), ) - v.GetRating(output) + + err := v.GetRating(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/video/insert.go b/cmd/video/insert.go index f9e5657..708ed33 100644 --- a/cmd/video/insert.go +++ b/cmd/video/insert.go @@ -40,7 +40,12 @@ var insertCmd = &cobra.Command{ video.WithOnBehalfOfContentOwnerChannel(onBehalfOfContentOwnerChannel), video.WithService(nil), ) - v.Insert(output) + + err := v.Insert(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/video/list.go b/cmd/video/list.go index 50fd08e..25f02f0 100644 --- a/cmd/video/list.go +++ b/cmd/video/list.go @@ -32,7 +32,12 @@ var listCmd = &cobra.Command{ video.WithRating(rating), video.WithService(nil), ) - v.List(parts, output) + + err := v.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/video/rate.go b/cmd/video/rate.go index 7dd3e57..11dc664 100644 --- a/cmd/video/rate.go +++ b/cmd/video/rate.go @@ -22,7 +22,12 @@ var rateCmd = &cobra.Command{ video.WithRating(rating), video.WithService(nil), ) - v.Rate() + + err := v.Rate(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/video/reportAbuse.go b/cmd/video/reportAbuse.go index 17d71c8..cae1965 100644 --- a/cmd/video/reportAbuse.go +++ b/cmd/video/reportAbuse.go @@ -26,7 +26,12 @@ var reportAbuseCmd = &cobra.Command{ video.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), video.WithService(nil), ) - v.ReportAbuse() + + err := v.ReportAbuse(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/video/update.go b/cmd/video/update.go index 05e6aed..e292b59 100644 --- a/cmd/video/update.go +++ b/cmd/video/update.go @@ -32,7 +32,12 @@ var updateCmd = &cobra.Command{ video.WithEmbeddable(embeddable), video.WithService(nil), ) - v.Update(output) + + err := v.Update(output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/videoAbuseReportReason/list.go b/cmd/videoAbuseReportReason/list.go index 7fc1e84..916e874 100644 --- a/cmd/videoAbuseReportReason/list.go +++ b/cmd/videoAbuseReportReason/list.go @@ -14,7 +14,12 @@ var listCmd = &cobra.Command{ videoAbuseReportReason.WithHL(hl), videoAbuseReportReason.WithService(nil), ) - va.List(parts, output) + + err := va.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/videoCategory/list.go b/cmd/videoCategory/list.go index 860d7f5..4aff06e 100644 --- a/cmd/videoCategory/list.go +++ b/cmd/videoCategory/list.go @@ -16,7 +16,12 @@ var listCmd = &cobra.Command{ videoCategory.WithRegionCode(regionCode), videoCategory.WithService(nil), ) - vc.List(parts, output) + + err := vc.List(parts, output, cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/watermark/set.go b/cmd/watermark/set.go index 15b7095..439dff1 100644 --- a/cmd/watermark/set.go +++ b/cmd/watermark/set.go @@ -25,7 +25,12 @@ var setCmd = &cobra.Command{ watermark.WithOnBehalfOfContentOwner(onBehalfOfContentOwner), watermark.WithService(nil), ) - w.Set() + + err := w.Set(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/cmd/watermark/unset.go b/cmd/watermark/unset.go index 138fbd1..35c372b 100644 --- a/cmd/watermark/unset.go +++ b/cmd/watermark/unset.go @@ -19,7 +19,12 @@ var unsetCmd = &cobra.Command{ watermark.WithChannelId(channelId), watermark.WithService(nil), ) - w.Unset() + + err := w.Unset(cmd.OutOrStdout()) + if err != nil { + _ = cmd.Help() + cmd.PrintErrf("Error: %v\n", err) + } }, } diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel new file mode 100644 index 0000000..aeab027 --- /dev/null +++ b/pkg/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "pkg", + srcs = ["interface.go"], + importpath = "github.com/eat-pray-ai/yutu/pkg", + visibility = ["//visibility:public"], +) diff --git a/pkg/activity/activity.go b/pkg/activity/activity.go index 081680e..c51c21e 100644 --- a/pkg/activity/activity.go +++ b/pkg/activity/activity.go @@ -26,7 +26,7 @@ type activity struct { type Activity interface { List([]string, string, io.Writer) error - get([]string) ([]*youtube.Activity, error) + Get([]string) ([]*youtube.Activity, error) } type Option func(*activity) @@ -41,7 +41,7 @@ func NewActivity(opts ...Option) Activity { return a } -func (a *activity) get(parts []string) ([]*youtube.Activity, error) { +func (a *activity) Get(parts []string) ([]*youtube.Activity, error) { call := service.Activities.List(parts) if a.ChannelId != "" { call = call.ChannelId(a.ChannelId) @@ -83,7 +83,7 @@ func (a *activity) get(parts []string) ([]*youtube.Activity, error) { func (a *activity) List( parts []string, output string, writer io.Writer, ) error { - activities, err := a.get(parts) + activities, err := a.Get(parts) if err != nil { return err } diff --git a/pkg/caption/caption.go b/pkg/caption/caption.go index e1c3d2c..7d7ebb4 100644 --- a/pkg/caption/caption.go +++ b/pkg/caption/caption.go @@ -39,7 +39,7 @@ type caption struct { } type Caption interface { - get(parts []string) ([]*youtube.Caption, error) // todo: return error + Get(parts []string) ([]*youtube.Caption, error) // todo: return error List(parts []string, output string, writer io.Writer) error Insert(output string, writer io.Writer) error Update(output string, writer io.Writer) error @@ -57,7 +57,7 @@ func NewCation(opts ...Option) Caption { return c } -func (c *caption) get(parts []string) ([]*youtube.Caption, error) { +func (c *caption) Get(parts []string) ([]*youtube.Caption, error) { call := service.Captions.List(parts, c.VideoId) if len(c.IDs) > 0 { call = call.Id(c.IDs...) @@ -78,7 +78,7 @@ func (c *caption) get(parts []string) ([]*youtube.Caption, error) { } func (c *caption) List(parts []string, output string, writer io.Writer) error { - captions, err := c.get(parts) + captions, err := c.Get(parts) if err != nil { return err } @@ -145,7 +145,7 @@ func (c *caption) Insert(output string, writer io.Writer) error { } func (c *caption) Update(output string, writer io.Writer) error { - captions, err := c.get([]string{"snippet"}) + captions, err := c.Get([]string{"snippet"}) if err != nil { return errors.Join(errUpdateCaption, err) } @@ -275,7 +275,7 @@ func (c *caption) Download(writer io.Writer) error { return errors.Join(errDownloadCaption, err) } - fmt.Printf("Caption %s downloaded to %s\n", c.IDs[0], c.File) + _, _ = fmt.Fprintf(writer, "Caption %s downloaded to %s\n", c.IDs[0], c.File) return nil } diff --git a/pkg/channel/channel.go b/pkg/channel/channel.go index d546396..f8ecfd6 100644 --- a/pkg/channel/channel.go +++ b/pkg/channel/channel.go @@ -3,10 +3,9 @@ package channel import ( "errors" "fmt" - "log" - "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" + "io" "google.golang.org/api/youtube/v3" ) @@ -37,9 +36,9 @@ type channel struct { } type Channel interface { - List([]string, string) - Update(output string) - get([]string) []*youtube.Channel + List([]string, string, io.Writer) error + Update(string, io.Writer) error + Get([]string) ([]*youtube.Channel, error) } type Option func(*channel) @@ -54,7 +53,7 @@ func NewChannel(opts ...Option) Channel { return c } -func (c *channel) get(parts []string) []*youtube.Channel { +func (c *channel) Get(parts []string) ([]*youtube.Channel, error) { call := service.Channels.List(parts) if c.CategoryId != "" { call = call.CategoryId(c.CategoryId) @@ -99,31 +98,43 @@ func (c *channel) get(parts []string) []*youtube.Channel { res, err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errGetChannel, err)) + return nil, errors.Join(errGetChannel, err) } - return res.Items + return res.Items, nil } -func (c *channel) List(parts []string, output string) { - channels := c.get(parts) +func (c *channel) List(parts []string, output string, writer io.Writer) error { + channels, err := c.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(channels, nil) + utils.PrintJSON(channels, writer) case "yaml": - utils.PrintYAML(channels, nil) + utils.PrintYAML(channels, writer) default: - fmt.Println("ID\tTitle") + _, _ = fmt.Fprintln(writer, "ID\tTitle") for _, channel := range channels { - fmt.Printf("%s\t%s\n", channel.Id, channel.Snippet.Title) + _, _ = fmt.Fprintf(writer, "%s\t%s\n", channel.Id, channel.Snippet.Title) } } + return nil } -func (c *channel) Update(output string) { +func (c *channel) Update(output string, writer io.Writer) error { parts := []string{"snippet"} - cha := c.get(parts)[0] + channels, err := c.Get(parts) + if err != nil { + return errors.Join(errUpdateChannel, err) + } + if len(channels) == 0 { + return errGetChannel + } + + cha := channels[0] if c.Country != "" { cha.Snippet.Country = c.Country } @@ -143,19 +154,19 @@ func (c *channel) Update(output string) { call := service.Channels.Update(parts, cha) res, err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errUpdateChannel, err)) + return errors.Join(errUpdateChannel, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Channel updated: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Channel updated: %s\n", res.Id) } + return nil } func WithCategoryId(categoryId string) Option { diff --git a/pkg/channelBanner/channelBanner.go b/pkg/channelBanner/channelBanner.go index 3d77ea3..6a1ece2 100644 --- a/pkg/channelBanner/channelBanner.go +++ b/pkg/channelBanner/channelBanner.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" "os" ) @@ -24,7 +24,7 @@ type channelBanner struct { } type ChannelBanner interface { - Insert(output string) + Insert(string, io.Writer) error } type Option func(banner *channelBanner) @@ -39,11 +39,10 @@ func NewChannelBanner(opts ...Option) ChannelBanner { return cb } -func (cb *channelBanner) Insert(output string) { +func (cb *channelBanner) Insert(output string, writer io.Writer) error { file, err := os.Open(cb.File) if err != nil { - utils.PrintJSON(cb, nil) - log.Fatalln(errors.Join(errInsertChannelBanner, err)) + return errors.Join(errInsertChannelBanner, err) } defer file.Close() cbr := &youtube.ChannelBannerResource{} @@ -58,19 +57,19 @@ func (cb *channelBanner) Insert(output string) { res, err := call.Do() if err != nil { - utils.PrintJSON(cb, nil) - log.Fatalln(errors.Join(errInsertChannelBanner, err)) + return errors.Join(errInsertChannelBanner, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("ChannelBanner inserted: %s\n", res.Url) + _, _ = fmt.Fprintf(writer, "ChannelBanner inserted: %s\n", res.Url) } + return nil } func WithChannelId(channelId string) Option { diff --git a/pkg/channelSection/channelSection.go b/pkg/channelSection/channelSection.go index 330a0c6..1812a80 100644 --- a/pkg/channelSection/channelSection.go +++ b/pkg/channelSection/channelSection.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -24,11 +24,11 @@ type channelSection struct { } type ChannelSection interface { - get(parts []string) []*youtube.ChannelSection - List(parts []string, output string) + Get([]string) ([]*youtube.ChannelSection, error) + List([]string, string, io.Writer) error + Delete(writer io.Writer) error // Update() // Insert() - Delete() } type Option func(*channelSection) @@ -42,7 +42,9 @@ func NewChannelSection(opts ...Option) ChannelSection { return cs } -func (cs *channelSection) get(parts []string) []*youtube.ChannelSection { +func (cs *channelSection) Get(parts []string) ( + []*youtube.ChannelSection, error, +) { call := service.ChannelSections.List(parts) if len(cs.IDs) > 0 { call = call.Id(cs.IDs...) @@ -62,31 +64,37 @@ func (cs *channelSection) get(parts []string) []*youtube.ChannelSection { res, err := call.Do() if err != nil { - utils.PrintJSON(cs, nil) - log.Fatalln(errors.Join(errGetChannelSection, err)) + return nil, errors.Join(errGetChannelSection, err) } - return res.Items + return res.Items, nil } -func (cs *channelSection) List(parts []string, output string) { - channelSections := cs.get(parts) +func (cs *channelSection) List( + parts []string, output string, writer io.Writer, +) error { + channelSections, err := cs.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(channelSections, nil) + utils.PrintJSON(channelSections, writer) case "yaml": - utils.PrintYAML(channelSections, nil) + utils.PrintYAML(channelSections, writer) default: - fmt.Println("ID\tChannelID\tTitle") + _, _ = fmt.Fprintln(writer, "ID\tChannelID\tTitle") for _, channelSection := range channelSections { - fmt.Printf( - "%s\t%s\t%s\n", channelSection.Id, + _, _ = fmt.Fprintf( + writer, "%s\t%s\t%s\n", channelSection.Id, channelSection.Snippet.ChannelId, channelSection.Snippet.Title, ) } } + return nil } -func (cs *channelSection) Delete() { +func (cs *channelSection) Delete(writer io.Writer) error { for _, id := range cs.IDs { call := service.ChannelSections.Delete(id) if cs.OnBehalfOfContentOwner != "" { @@ -95,12 +103,12 @@ func (cs *channelSection) Delete() { err := call.Do() if err != nil { - utils.PrintJSON(cs, nil) - log.Fatalln(errors.Join(errDeleteChannelSection, err)) + return errors.Join(errDeleteChannelSection, err) } - fmt.Printf("Channel section %s deleted\n", id) + _, _ = fmt.Fprintf(writer, "Channel section %s deleted\n", id) } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/comment/comment.go b/pkg/comment/comment.go index bc31543..b76f88c 100644 --- a/pkg/comment/comment.go +++ b/pkg/comment/comment.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -35,13 +35,13 @@ type comment struct { } type Comment interface { - get([]string) []*youtube.Comment - List([]string, string) - Insert(output string) - Update(output string) - Delete() - MarkAsSpam(output string) - SetModerationStatus(output string) + Get([]string) ([]*youtube.Comment, error) + List([]string, string, io.Writer) error + Insert(string, io.Writer) error + Update(string, io.Writer) error + Delete(io.Writer) error + MarkAsSpam(string, io.Writer) error + SetModerationStatus(string, io.Writer) error } type Option func(*comment) @@ -56,7 +56,7 @@ func NewComment(opts ...Option) Comment { return c } -func (c *comment) get(parts []string) []*youtube.Comment { +func (c *comment) Get(parts []string) ([]*youtube.Comment, error) { call := service.Comments.List(parts) if c.IDs[0] != "" { @@ -78,29 +78,35 @@ func (c *comment) get(parts []string) []*youtube.Comment { res, err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errGetComment, err)) + return nil, errors.Join(errGetComment, err) } - return res.Items + return res.Items, nil } -func (c *comment) List(parts []string, output string) { - comments := c.get(parts) +func (c *comment) List(parts []string, output string, writer io.Writer) error { + comments, err := c.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(comments, nil) + utils.PrintJSON(comments, writer) case "yaml": - utils.PrintYAML(comments, nil) + utils.PrintYAML(comments, writer) default: - fmt.Println("ID\tTextDisplay") + _, _ = fmt.Fprintln(writer, "ID\tTextDisplay") for _, comment := range comments { - fmt.Printf("%s\t%s\n", comment.Id, comment.Snippet.TextDisplay) + _, _ = fmt.Fprintf( + writer, "%s\t%s\n", comment.Id, comment.Snippet.TextDisplay, + ) } } + return nil } -func (c *comment) Insert(output string) { +func (c *comment) Insert(output string, writer io.Writer) error { comment := &youtube.Comment{ Snippet: &youtube.CommentSnippet{ AuthorChannelId: &youtube.CommentSnippetAuthorChannelId{ @@ -120,24 +126,31 @@ func (c *comment) Insert(output string) { call := service.Comments.Insert([]string{"snippet"}, comment) res, err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errInsertComment, err)) + return errors.Join(errInsertComment, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Comment inserted: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Comment inserted: %s\n", res.Id) } + return nil } -func (c *comment) Update(output string) { - comment := c.get([]string{"id", "snippet"})[0] +func (c *comment) Update(output string, writer io.Writer) error { + comments, err := c.Get([]string{"id", "snippet"}) + if err != nil { + return errors.Join(errUpdateComment, err) + } + if len(comments) == 0 { + return errGetComment + } + comment := comments[0] if c.CanRate != nil { comment.Snippet.CanRate = *c.CanRate } @@ -153,41 +166,41 @@ func (c *comment) Update(output string) { call := service.Comments.Update([]string{"snippet"}, comment) res, err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errUpdateComment, err)) + return errors.Join(errUpdateComment, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Comment updated: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Comment updated: %s\n", res.Id) } + return nil } -func (c *comment) MarkAsSpam(output string) { +func (c *comment) MarkAsSpam(output string, writer io.Writer) error { call := service.Comments.MarkAsSpam(c.IDs) err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errMarkAsSpam, err)) + return errors.Join(errMarkAsSpam, err) } switch output { case "json": - utils.PrintJSON(c, nil) + utils.PrintJSON(c, writer) case "yaml": - utils.PrintYAML(c, nil) + utils.PrintYAML(c, writer) case "silent": default: - fmt.Printf("Comment marked as spam: %s\n", c.IDs) + _, _ = fmt.Fprintf(writer, "Comment marked as spam: %s\n", c.IDs) } + return nil } -func (c *comment) SetModerationStatus(output string) { +func (c *comment) SetModerationStatus(output string, writer io.Writer) error { call := service.Comments.SetModerationStatus(c.IDs, c.ModerationStatus) if c.BanAuthor != nil { @@ -196,33 +209,34 @@ func (c *comment) SetModerationStatus(output string) { err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errSetModerationStatus, err)) + return errors.Join(errSetModerationStatus, err) } switch output { case "json": - utils.PrintJSON(c, nil) + utils.PrintJSON(c, writer) case "yaml": - utils.PrintYAML(c, nil) + utils.PrintYAML(c, writer) case "silent": default: - fmt.Printf( - "Comment moderation status set to %s: %s\n", c.ModerationStatus, c.IDs, + _, _ = fmt.Fprintf( + writer, "Comment moderation status set to %s: %s\n", + c.ModerationStatus, c.IDs, ) } + return nil } -func (c *comment) Delete() { +func (c *comment) Delete(writer io.Writer) error { for _, id := range c.IDs { call := service.Comments.Delete(id) err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errDeleteComment, err)) + return errors.Join(errDeleteComment, err) } - fmt.Printf("Comment %s deleted\n", id) + _, _ = fmt.Fprintf(writer, "Comment %s deleted\n", id) } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/commentThread/commentThread.go b/pkg/commentThread/commentThread.go index 4486f2e..4222455 100644 --- a/pkg/commentThread/commentThread.go +++ b/pkg/commentThread/commentThread.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -30,9 +30,9 @@ type commentThread struct { } type CommentThread interface { - get([]string) []*youtube.CommentThread - List([]string, string) - Insert(output string) + Get([]string) ([]*youtube.CommentThread, error) + List([]string, string, io.Writer) error + Insert(output string, writer io.Writer) error } type Option func(*commentThread) @@ -47,7 +47,7 @@ func NewCommentThread(opts ...Option) CommentThread { return c } -func (c *commentThread) get(parts []string) []*youtube.CommentThread { +func (c *commentThread) Get(parts []string) ([]*youtube.CommentThread, error) { call := service.CommentThreads.List(parts) if len(c.IDs) > 0 { @@ -89,31 +89,38 @@ func (c *commentThread) get(parts []string) []*youtube.CommentThread { res, err := call.Do() if err != nil { - utils.PrintJSON(c, nil) - log.Fatalln(errors.Join(errGetCommentThread, err)) + return nil, errors.Join(errGetCommentThread, err) } - return res.Items + return res.Items, nil } -func (c *commentThread) List(parts []string, output string) { - commentThreads := c.get(parts) +func (c *commentThread) List( + parts []string, output string, writer io.Writer, +) error { + commentThreads, err := c.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(commentThreads, nil) + utils.PrintJSON(commentThreads, writer) case "yaml": - utils.PrintYAML(commentThreads, nil) + utils.PrintYAML(commentThreads, writer) default: - fmt.Println("ID\tTopLevelCommentID") + _, _ = fmt.Fprintln(writer, "ID\tTopLevelCommentID") for _, commentThread := range commentThreads { - fmt.Printf( - "%s\t%s\n", commentThread.Id, commentThread.Snippet.TopLevelComment.Id, + _, _ = fmt.Fprintf( + writer, "%s\t%s\n", + commentThread.Id, commentThread.Snippet.TopLevelComment.Id, ) } } + return nil } -func (c *commentThread) Insert(output string) { +func (c *commentThread) Insert(output string, writer io.Writer) error { ct := &youtube.CommentThread{ Snippet: &youtube.CommentThreadSnippet{ ChannelId: c.ChannelId, @@ -132,19 +139,19 @@ func (c *commentThread) Insert(output string) { res, err := service.CommentThreads.Insert([]string{"snippet"}, ct).Do() if err != nil { - utils.PrintJSON(ct, nil) - log.Fatalln(errors.Join(errInsertCommentThread, err)) + return errors.Join(errInsertCommentThread, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("CommentThread inserted: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "CommentThread inserted: %s\n", res.Id) } + return nil } func WithAllThreadsRelatedToChannelId(allThreadsRelatedToChannelId string) Option { diff --git a/pkg/i18nLanguage/i18nLanguage.go b/pkg/i18nLanguage/i18nLanguage.go index ba45bd2..718628e 100644 --- a/pkg/i18nLanguage/i18nLanguage.go +++ b/pkg/i18nLanguage/i18nLanguage.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -19,8 +19,8 @@ type i18nLanguage struct { } type I18nLanguage interface { - get(parts []string) []*youtube.I18nLanguage - List(parts []string, output string) + Get([]string) ([]*youtube.I18nLanguage, error) + List([]string, string, io.Writer) error } type Option func(*i18nLanguage) @@ -35,7 +35,7 @@ func NewI18nLanguage(opts ...Option) I18nLanguage { return i } -func (i *i18nLanguage) get(parts []string) []*youtube.I18nLanguage { +func (i *i18nLanguage) Get(parts []string) ([]*youtube.I18nLanguage, error) { call := service.I18nLanguages.List(parts) if i.Hl != "" { call = call.Hl(i.Hl) @@ -43,29 +43,35 @@ func (i *i18nLanguage) get(parts []string) []*youtube.I18nLanguage { res, err := call.Do() if err != nil { - utils.PrintJSON(i, nil) - log.Fatalln(errors.Join(errGetI18nLanguage, err)) + return nil, errors.Join(errGetI18nLanguage, err) } - return res.Items + return res.Items, nil } -func (i *i18nLanguage) List(parts []string, output string) { - i18nLanguages := i.get(parts) +func (i *i18nLanguage) List( + parts []string, output string, writer io.Writer, +) error { + i18nLanguages, err := i.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(i18nLanguages, nil) + utils.PrintJSON(i18nLanguages, writer) case "yaml": - utils.PrintYAML(i18nLanguages, nil) + utils.PrintYAML(i18nLanguages, writer) default: - fmt.Println("id\thl\tname") + _, _ = fmt.Fprintln(writer, "id\thl\tname") for _, i18nLanguage := range i18nLanguages { - fmt.Printf( - "%v\t%v\t%v\n", + _, _ = fmt.Fprintf( + writer, "%v\t%v\t%v\n", i18nLanguage.Id, i18nLanguage.Snippet.Hl, i18nLanguage.Snippet.Name, ) } } + return nil } func WithHl(hl string) Option { diff --git a/pkg/i18nRegion/i18nRegion.go b/pkg/i18nRegion/i18nRegion.go index 3d8d053..ab2df98 100644 --- a/pkg/i18nRegion/i18nRegion.go +++ b/pkg/i18nRegion/i18nRegion.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -19,8 +19,8 @@ type i18nRegion struct { } type I18nRegion interface { - get(parts []string) []*youtube.I18nRegion - List(parts []string, output string) + Get([]string) ([]*youtube.I18nRegion, error) + List([]string, string, io.Writer) error } type Option func(*i18nRegion) @@ -35,7 +35,7 @@ func NewI18nRegion(opts ...Option) I18nRegion { return i } -func (i *i18nRegion) get(parts []string) []*youtube.I18nRegion { +func (i *i18nRegion) Get(parts []string) ([]*youtube.I18nRegion, error) { call := service.I18nRegions.List(parts) if i.Hl != "" { call = call.Hl(i.Hl) @@ -43,29 +43,35 @@ func (i *i18nRegion) get(parts []string) []*youtube.I18nRegion { res, err := call.Do() if err != nil { - utils.PrintJSON(i, nil) - log.Fatalln(errors.Join(errGetI18nRegion, err)) + return nil, errors.Join(errGetI18nRegion, err) } - return res.Items + return res.Items, nil } -func (i *i18nRegion) List(parts []string, output string) { - i18nRegions := i.get(parts) +func (i *i18nRegion) List( + parts []string, output string, writer io.Writer, +) error { + i18nRegions, err := i.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(i18nRegions, nil) + utils.PrintJSON(i18nRegions, writer) case "yaml": - utils.PrintYAML(i18nRegions, nil) + utils.PrintYAML(i18nRegions, writer) default: - fmt.Println("ID\tgl\tname") + _, _ = fmt.Fprintln(writer, "ID\tgl\tname") for _, i18nRegion := range i18nRegions { - fmt.Printf( - "%v\t%v\t%v\n", + _, _ = fmt.Fprintf( + writer, "%v\t%v\t%v\n", i18nRegion.Id, i18nRegion.Snippet.Gl, i18nRegion.Snippet.Name, ) } } + return nil } func WithHl(hl string) Option { diff --git a/pkg/interface.go b/pkg/interface.go new file mode 100644 index 0000000..bc8fb29 --- /dev/null +++ b/pkg/interface.go @@ -0,0 +1,29 @@ +package pkg + +import ( + "io" +) + +type Lister interface { + List([]string, string, io.Writer) error +} + +type Inserter interface { + Insert(string, io.Writer) error +} + +type Deleter interface { + Delete(writer io.Writer) error +} + +type Updater interface { + Update(string, io.Writer) error +} + +type Setter interface { + Set(writer io.Writer) error +} + +type Unsetter interface { + Unset(writer io.Writer) error +} diff --git a/pkg/member/member.go b/pkg/member/member.go index 75dcec8..448ed08 100644 --- a/pkg/member/member.go +++ b/pkg/member/member.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -22,8 +22,8 @@ type member struct { } type Member interface { - List([]string, string) - get([]string) []*youtube.Member + List([]string, string, io.Writer) error + Get([]string) ([]*youtube.Member, error) } type Option func(*member) @@ -38,7 +38,7 @@ func NewMember(opts ...Option) Member { return m } -func (m *member) get(parts []string) []*youtube.Member { +func (m *member) Get(parts []string) ([]*youtube.Member, error) { call := service.Members.List(parts) if m.MemberChannelId != "" { call = call.FilterByMemberChannelId(m.MemberChannelId) @@ -56,30 +56,34 @@ func (m *member) get(parts []string) []*youtube.Member { res, err := call.Do() if err != nil { - utils.PrintJSON(m, nil) - log.Fatalln(errors.Join(errGetMember, err)) + return nil, errors.Join(errGetMember, err) } - return res.Items + return res.Items, nil } -func (m *member) List(parts []string, output string) { - members := m.get(parts) +func (m *member) List(parts []string, output string, writer io.Writer) error { + members, err := m.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(members, nil) + utils.PrintJSON(members, writer) case "yaml": - utils.PrintYAML(members, nil) + utils.PrintYAML(members, writer) default: - fmt.Println("channelId\tdisplayName") + _, _ = fmt.Fprintln(writer, "channelId\tdisplayName") for _, member := range members { - fmt.Printf( - "%s\t%s\n", + _, _ = fmt.Fprintf( + writer, "%s\t%s\n", member.Snippet.MemberDetails.ChannelId, member.Snippet.MemberDetails.DisplayName, ) } } + return nil } func WithMemberChannelId(channelId string) Option { diff --git a/pkg/membershipsLevel/membershipsLevel.go b/pkg/membershipsLevel/membershipsLevel.go index 98387e6..7ad983d 100644 --- a/pkg/membershipsLevel/membershipsLevel.go +++ b/pkg/membershipsLevel/membershipsLevel.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -17,8 +17,8 @@ var ( type membershipsLevel struct{} type MembershipsLevel interface { - List([]string, string) - get([]string) []*youtube.MembershipsLevel + List([]string, string, io.Writer) error + Get([]string) ([]*youtube.MembershipsLevel, error) } type Option func(*membershipsLevel) @@ -33,33 +33,41 @@ func NewMembershipsLevel(opts ...Option) MembershipsLevel { return m } -func (m *membershipsLevel) get(parts []string) []*youtube.MembershipsLevel { +func (m *membershipsLevel) Get(parts []string) ( + []*youtube.MembershipsLevel, error, +) { call := service.MembershipsLevels.List(parts) res, err := call.Do() if err != nil { - utils.PrintJSON(m, nil) - log.Fatalln(errors.Join(errGetMembershipsLevel, err)) + return nil, errors.Join(errGetMembershipsLevel, err) } - return res.Items + return res.Items, nil } -func (m *membershipsLevel) List(parts []string, output string) { - membershipsLevels := m.get(parts) +func (m *membershipsLevel) List( + parts []string, output string, writer io.Writer, +) error { + membershipsLevels, err := m.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(membershipsLevels, nil) + utils.PrintJSON(membershipsLevels, writer) case "yaml": - utils.PrintYAML(membershipsLevels, nil) + utils.PrintYAML(membershipsLevels, writer) default: - fmt.Println("id\tdisplayName") + _, _ = fmt.Fprintln(writer, "id\tdisplayName") for _, membershipsLevel := range membershipsLevels { - fmt.Printf( - "%v\t%v\n", membershipsLevel.Id, + _, _ = fmt.Fprintf( + writer, "%v\t%v\n", membershipsLevel.Id, membershipsLevel.Snippet.LevelDetails.DisplayName, ) } } + return nil } func WithService(svc *youtube.Service) Option { diff --git a/pkg/playlist/playlist.go b/pkg/playlist/playlist.go index 3efa9a8..5f861a7 100644 --- a/pkg/playlist/playlist.go +++ b/pkg/playlist/playlist.go @@ -5,9 +5,8 @@ import ( "fmt" "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" - "log" - "google.golang.org/api/youtube/v3" + "io" ) var ( @@ -35,11 +34,11 @@ type playlist struct { } type Playlist interface { - List([]string, string) - Insert(output string) - Update(output string) - Delete() - get([]string) []*youtube.Playlist + List([]string, string, io.Writer) error + Insert(string, io.Writer) error + Update(string, io.Writer) error + Delete(io.Writer) error + Get([]string) ([]*youtube.Playlist, error) } type Option func(*playlist) @@ -54,7 +53,7 @@ func NewPlaylist(opts ...Option) Playlist { return p } -func (p *playlist) get(parts []string) []*youtube.Playlist { +func (p *playlist) Get(parts []string) ([]*youtube.Playlist, error) { call := service.Playlists.List(parts) if len(p.IDs) > 0 { @@ -79,29 +78,33 @@ func (p *playlist) get(parts []string) []*youtube.Playlist { res, err := call.Do() if err != nil { - utils.PrintJSON(p, nil) - log.Fatalln(errors.Join(errGetPlaylist, err)) + return nil, errors.Join(errGetPlaylist, err) } - return res.Items + return res.Items, nil } -func (p *playlist) List(parts []string, output string) { - playlists := p.get(parts) +func (p *playlist) List(parts []string, output string, writer io.Writer) error { + playlists, err := p.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(playlists, nil) + utils.PrintJSON(playlists, writer) case "yaml": - utils.PrintYAML(playlists, nil) + utils.PrintYAML(playlists, writer) default: - fmt.Println("ID\tTitle") + _, _ = fmt.Fprintln(writer, "ID\tTitle") for _, playlist := range playlists { - fmt.Printf("%s\t%s\n", playlist.Id, playlist.Snippet.Title) + _, _ = fmt.Fprintf(writer, "%s\t%s\n", playlist.Id, playlist.Snippet.Title) } } + return nil } -func (p *playlist) Insert(output string) { +func (p *playlist) Insert(output string, writer io.Writer) error { upload := &youtube.Playlist{ Snippet: &youtube.PlaylistSnippet{ Title: p.Title, @@ -118,23 +121,31 @@ func (p *playlist) Insert(output string) { call := service.Playlists.Insert([]string{"snippet", "status"}, upload) res, err := call.Do() if err != nil { - utils.PrintJSON(p, nil) - log.Fatalln(errors.Join(errInsertPlaylist, err)) + return errors.Join(errInsertPlaylist, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Playlist inserted: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Playlist inserted: %s\n", res.Id) } + return nil } -func (p *playlist) Update(output string) { - playlist := p.get([]string{"id", "snippet", "status"})[0] +func (p *playlist) Update(output string, writer io.Writer) error { + playlists, err := p.Get([]string{"id", "snippet", "status"}) + if err != nil { + return errors.Join(errUpdatePlaylist, err) + } + if len(playlists) == 0 { + return errGetPlaylist + } + + playlist := playlists[0] if p.Title != "" { playlist.Snippet.Title = p.Title } @@ -154,22 +165,22 @@ func (p *playlist) Update(output string) { call := service.Playlists.Update([]string{"snippet", "status"}, playlist) res, err := call.Do() if err != nil { - utils.PrintJSON(p, nil) - log.Fatalln(errors.Join(errUpdatePlaylist, err)) + return errors.Join(errUpdatePlaylist, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Playlist updated: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Playlist updated: %s\n", res.Id) } + return nil } -func (p *playlist) Delete() { +func (p *playlist) Delete(writer io.Writer) error { for _, id := range p.IDs { call := service.Playlists.Delete(id) if p.OnBehalfOfContentOwner != "" { @@ -178,11 +189,11 @@ func (p *playlist) Delete() { err := call.Do() if err != nil { - utils.PrintJSON(p, nil) - log.Fatalln(errors.Join(errDeletePlaylist, err)) + return errors.Join(errDeletePlaylist, err) } - fmt.Printf("Playlist %s deleted", id) + _, _ = fmt.Fprintf(writer, "Playlist %s deleted", id) } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/playlistImage/playlistImage.go b/pkg/playlistImage/playlistImage.go index bc3a879..bc7a68f 100644 --- a/pkg/playlistImage/playlistImage.go +++ b/pkg/playlistImage/playlistImage.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" "os" ) @@ -34,11 +34,11 @@ type playlistImage struct { } type PlaylistImage interface { - get([]string) []*youtube.PlaylistImage - List([]string, string) - Insert(string) - Update(string) - Delete() + Get([]string) ([]*youtube.PlaylistImage, error) + List([]string, string, io.Writer) error + Insert(string, io.Writer) error + Update(string, io.Writer) error + Delete(io.Writer) error } type Option func(*playlistImage) @@ -51,7 +51,7 @@ func NewPlaylistImage(opts ...Option) PlaylistImage { return pi } -func (pi *playlistImage) get(parts []string) []*youtube.PlaylistImage { +func (pi *playlistImage) Get(parts []string) ([]*youtube.PlaylistImage, error) { call := service.PlaylistImages.List() call = call.Part(parts...) @@ -71,36 +71,42 @@ func (pi *playlistImage) get(parts []string) []*youtube.PlaylistImage { res, err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errGetPlaylistImage, err)) + return nil, errors.Join(errGetPlaylistImage, err) } - return res.Items + return res.Items, nil } -func (pi *playlistImage) List(parts []string, output string) { - playlistImages := pi.get(parts) +func (pi *playlistImage) List( + parts []string, output string, writer io.Writer, +) error { + playlistImages, err := pi.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(playlistImages, nil) + utils.PrintJSON(playlistImages, writer) case "yaml": - utils.PrintYAML(playlistImages, nil) + utils.PrintYAML(playlistImages, writer) default: - fmt.Println("ID\tKind\tPlaylistID\tType") + _, _ = fmt.Fprintln(writer, "ID\tKind\tPlaylistID\tType") for _, image := range playlistImages { - fmt.Printf( + _, _ = fmt.Fprintf( + writer, "%s\t%s\t%s\t%s\n", image.Id, image.Kind, image.Snippet.PlaylistId, image.Snippet.Type, ) } } + return nil } -func (pi *playlistImage) Insert(output string) { +func (pi *playlistImage) Insert(output string, writer io.Writer) error { file, err := os.Open(pi.File) if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errInsertPlaylistImage, err)) + return errors.Join(errInsertPlaylistImage, err) } defer file.Close() @@ -125,23 +131,31 @@ func (pi *playlistImage) Insert(output string) { call = call.Part("kind", "snippet") res, err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errInsertPlaylistImage, err)) + return errors.Join(errInsertPlaylistImage, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("PlaylistImage inserted: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "PlaylistImage inserted: %s\n", res.Id) } + return nil } -func (pi *playlistImage) Update(output string) { - playlistImage := pi.get([]string{"id", "kind", "snippet"})[0] +func (pi *playlistImage) Update(output string, writer io.Writer) error { + playlistImages, err := pi.Get([]string{"id", "kind", "snippet"}) + if err != nil { + return errors.Join(errUpdatePlaylistImage, err) + } + if len(playlistImages) == 0 { + return errGetPlaylistImage + } + + playlistImage := playlistImages[0] if pi.PlaylistID != "" { playlistImage.Snippet.PlaylistId = pi.PlaylistID } @@ -162,8 +176,7 @@ func (pi *playlistImage) Update(output string) { if pi.File != "" { file, err := os.Open(pi.File) if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errUpdatePlaylistImage, err)) + return errors.Join(errUpdatePlaylistImage, err) } defer file.Close() call = call.Media(file) @@ -172,22 +185,22 @@ func (pi *playlistImage) Update(output string) { res, err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errUpdatePlaylistImage, err)) + return errors.Join(errUpdatePlaylistImage, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("PlaylistImage updated: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "PlaylistImage updated: %s\n", res.Id) } + return nil } -func (pi *playlistImage) Delete() { +func (pi *playlistImage) Delete(writer io.Writer) error { for _, id := range pi.IDs { call := service.PlaylistImages.Delete() call = call.Id(id) @@ -197,11 +210,11 @@ func (pi *playlistImage) Delete() { err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errDeletePlaylistImage, err)) + return errors.Join(errDeletePlaylistImage, err) } - fmt.Printf("PlaylistImage %s deleted\n", id) + _, _ = fmt.Fprintf(writer, "PlaylistImage %s deleted\n", id) } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/playlistItem/playlistItem.go b/pkg/playlistItem/playlistItem.go index 977b8d5..bf6fda5 100644 --- a/pkg/playlistItem/playlistItem.go +++ b/pkg/playlistItem/playlistItem.go @@ -4,10 +4,9 @@ import ( "errors" "fmt" "github.com/eat-pray-ai/yutu/pkg/auth" - "log" - "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" + "io" ) var ( @@ -36,11 +35,11 @@ type playlistItem struct { } type PlaylistItem interface { - List([]string, string) - Insert(output string) - Update(output string) - Delete() - get([]string) []*youtube.PlaylistItem + List([]string, string, io.Writer) error + Insert(string, io.Writer) error + Update(string, io.Writer) error + Delete(io.Writer) error + Get([]string) ([]*youtube.PlaylistItem, error) } type Option func(*playlistItem) @@ -55,7 +54,7 @@ func NewPlaylistItem(opts ...Option) PlaylistItem { return p } -func (pi *playlistItem) get(parts []string) []*youtube.PlaylistItem { +func (pi *playlistItem) Get(parts []string) ([]*youtube.PlaylistItem, error) { call := service.PlaylistItems.List(parts) if len(pi.IDs) > 0 { call = call.Id(pi.IDs...) @@ -75,29 +74,38 @@ func (pi *playlistItem) get(parts []string) []*youtube.PlaylistItem { call = call.MaxResults(pi.MaxResults) res, err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errGetPlaylistItem, err)) + return nil, errors.Join(errGetPlaylistItem, err) } - return res.Items + return res.Items, nil } -func (pi *playlistItem) List(parts []string, output string) { - playlistItems := pi.get(parts) +func (pi *playlistItem) List( + parts []string, output string, writer io.Writer, +) error { + playlistItems, err := pi.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(playlistItems, nil) + utils.PrintJSON(playlistItems, writer) case "yaml": - utils.PrintYAML(playlistItems, nil) + utils.PrintYAML(playlistItems, writer) default: - fmt.Println("ID\tTitle") + _, _ = fmt.Fprintln(writer, "ID\tTitle") for _, playlistItem := range playlistItems { - fmt.Printf("%s\t%s\n", playlistItem.Id, playlistItem.Snippet.Title) + _, _ = fmt.Fprintf( + writer, "%s\t%s\n", + playlistItem.Id, playlistItem.Snippet.Title, + ) } } + return nil } -func (pi *playlistItem) Insert(output string) { +func (pi *playlistItem) Insert(output string, writer io.Writer) error { var resourceId *youtube.ResourceId switch pi.Kind { case "video": @@ -139,23 +147,31 @@ func (pi *playlistItem) Insert(output string) { res, err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errInsertPlaylistItem, err)) + return errors.Join(errInsertPlaylistItem, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Playlist Item inserted: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Playlist Item inserted: %s\n", res.Id) } + return nil } -func (pi *playlistItem) Update(output string) { - playlistItem := pi.get([]string{"id", "snippet", "status"})[0] +func (pi *playlistItem) Update(output string, writer io.Writer) error { + playlistItems, err := pi.Get([]string{"id", "snippet", "status"}) + if err != nil { + return errors.Join(errUpdatePlaylistItem, err) + } + if len(playlistItems) == 0 { + return errGetPlaylistItem + } + + playlistItem := playlistItems[0] if pi.Title != "" { playlistItem.Snippet.Title = pi.Title } @@ -175,22 +191,22 @@ func (pi *playlistItem) Update(output string) { res, err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errUpdatePlaylistItem, err)) + return errors.Join(errUpdatePlaylistItem, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Playlist Item updated: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Playlist Item updated: %s\n", res.Id) } + return nil } -func (pi *playlistItem) Delete() { +func (pi *playlistItem) Delete(writer io.Writer) error { for _, id := range pi.IDs { call := service.PlaylistItems.Delete(id) if pi.OnBehalfOfContentOwner != "" { @@ -199,12 +215,12 @@ func (pi *playlistItem) Delete() { err := call.Do() if err != nil { - utils.PrintJSON(pi, nil) - log.Fatalln(errors.Join(errDeletePlaylistItem, err)) + return errors.Join(errDeletePlaylistItem, err) } - fmt.Printf("Playlsit Item %s deleted", id) + _, _ = fmt.Fprintf(writer, "Playlsit Item %s deleted", id) } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/search/search.go b/pkg/search/search.go index 4a1da04..54f3edb 100644 --- a/pkg/search/search.go +++ b/pkg/search/search.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -47,8 +47,8 @@ type search struct { } type Search interface { - get([]string) []*youtube.SearchResult - List([]string, string) + Get([]string) ([]*youtube.SearchResult, error) + List([]string, string, io.Writer) error } type Option func(*search) @@ -63,7 +63,7 @@ func NewSearch(opts ...Option) Search { return s } -func (s *search) get(parts []string) []*youtube.SearchResult { +func (s *search) Get(parts []string) ([]*youtube.SearchResult, error) { call := service.Search.List(parts) if s.ChannelId != "" { call.ChannelId(s.ChannelId) @@ -184,26 +184,32 @@ func (s *search) get(parts []string) []*youtube.SearchResult { res, err := call.Do() if err != nil { - utils.PrintJSON(s, nil) - log.Fatalln(errors.Join(errGetSearch, err)) + return nil, errors.Join(errGetSearch, err) } - return res.Items + return res.Items, nil } -func (s *search) List(parts []string, output string) { - results := s.get(parts) +func (s *search) List(parts []string, output string, writer io.Writer) error { + results, err := s.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(results, nil) + utils.PrintJSON(results, writer) case "yaml": - utils.PrintYAML(results, nil) + utils.PrintYAML(results, writer) default: - fmt.Println("Kind\tTitle") + _, _ = fmt.Fprintln(writer, "Kind\tTitle") for _, result := range results { - fmt.Printf("%v\t%v\n", result.Id.Kind, result.Snippet.Title) + _, _ = fmt.Fprintf( + writer, "%v\t%v\n", result.Id.Kind, result.Snippet.Title, + ) } } + return nil } func WithChannelId(channelId string) Option { diff --git a/pkg/subscription/subscription.go b/pkg/subscription/subscription.go index 2c61bb8..63b97f0 100644 --- a/pkg/subscription/subscription.go +++ b/pkg/subscription/subscription.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -33,10 +33,10 @@ type subscription struct { } type Subscription interface { - get([]string) []*youtube.Subscription - List([]string, string) - Insert(output string) - Delete() + Get([]string) ([]*youtube.Subscription, error) + List([]string, string, io.Writer) error + Insert(string, io.Writer) error + Delete(io.Writer) error } type Option func(*subscription) @@ -51,7 +51,7 @@ func NewSubscription(opts ...Option) Subscription { return s } -func (s *subscription) get(parts []string) []*youtube.Subscription { +func (s *subscription) Get(parts []string) ([]*youtube.Subscription, error) { call := service.Subscriptions.List(parts) if len(s.IDs) > 0 { call = call.Id(s.IDs...) @@ -89,32 +89,38 @@ func (s *subscription) get(parts []string) []*youtube.Subscription { res, err := call.Do() if err != nil { - utils.PrintJSON(s, nil) - log.Fatalln(errors.Join(errGetSubscription, err)) + return nil, errors.Join(errGetSubscription, err) } - return res.Items + return res.Items, nil } -func (s *subscription) List(parts []string, output string) { - subscriptions := s.get(parts) +func (s *subscription) List( + parts []string, output string, writer io.Writer, +) error { + subscriptions, err := s.Get(parts) + if err != nil { + return errors.Join(errGetSubscription, err) + } + switch output { case "json": - utils.PrintJSON(subscriptions, nil) + utils.PrintJSON(subscriptions, writer) case "yaml": - utils.PrintYAML(subscriptions, nil) + utils.PrintYAML(subscriptions, writer) default: - fmt.Println("ID\tChannel ID\tChannel Title") + _, _ = fmt.Fprintln(writer, "ID\tChannel ID\tChannel Title") for _, subscription := range subscriptions { - fmt.Printf( - "%s\t%s\t%s\n", subscription.Id, + _, _ = fmt.Fprintf( + writer, "%s\t%s\t%s\n", subscription.Id, subscription.Snippet.ResourceId.ChannelId, subscription.Snippet.Title, ) } } + return nil } -func (s *subscription) Insert(output string) { +func (s *subscription) Insert(output string, writer io.Writer) error { subscription := &youtube.Subscription{ Snippet: &youtube.SubscriptionSnippet{ ChannelId: s.SubscriberChannelId, @@ -129,31 +135,31 @@ func (s *subscription) Insert(output string) { call := service.Subscriptions.Insert([]string{"snippet"}, subscription) res, err := call.Do() if err != nil { - utils.PrintJSON(s, nil) - log.Fatalln(errors.Join(errInsertSubscription, err)) + return errors.Join(errInsertSubscription, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) default: - fmt.Printf("Subscription inserted: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Subscription inserted: %s\n", res.Id) } + return nil } -func (s *subscription) Delete() { +func (s *subscription) Delete(writer io.Writer) error { for _, id := range s.IDs { call := service.Subscriptions.Delete(id) err := call.Do() if err != nil { - utils.PrintJSON(s, nil) - log.Fatalln(errors.Join(errDeleteSubscription, err)) + return errors.Join(errDeleteSubscription, err) } - fmt.Printf("Subscription %s deleted", id) + _, _ = fmt.Fprintf(writer, "Subscription %s deleted", id) } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/superChatEvent/superChatEvent.go b/pkg/superChatEvent/superChatEvent.go index fff0630..a8b7678 100644 --- a/pkg/superChatEvent/superChatEvent.go +++ b/pkg/superChatEvent/superChatEvent.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -20,8 +20,8 @@ type superChatEvent struct { } type SuperChatEvent interface { - get([]string) []*youtube.SuperChatEvent - List([]string, string) + Get([]string) ([]*youtube.SuperChatEvent, error) + List([]string, string, io.Writer) error } type Option func(*superChatEvent) @@ -36,7 +36,7 @@ func NewSuperChatEvent(opts ...Option) SuperChatEvent { return s } -func (s *superChatEvent) get(parts []string) []*youtube.SuperChatEvent { +func (s *superChatEvent) Get(parts []string) ([]*youtube.SuperChatEvent, error) { call := service.SuperChatEvents.List(parts) if s.Hl != "" { call = call.Hl(s.Hl) @@ -48,26 +48,34 @@ func (s *superChatEvent) get(parts []string) []*youtube.SuperChatEvent { res, err := call.Do() if err != nil { - utils.PrintJSON(s, nil) - log.Fatalln(errors.Join(errGetSuperChatEvent, err)) + return nil, errors.Join(errGetSuperChatEvent, err) } - return res.Items + return res.Items, nil } -func (s *superChatEvent) List(parts []string, output string) { - events := s.get(parts) +func (s *superChatEvent) List( + parts []string, output string, writer io.Writer, +) error { + events, err := s.Get(parts) + if err != nil { + return errors.Join(errGetSuperChatEvent, err) + } + switch output { case "json": - utils.PrintJSON(events, nil) + utils.PrintJSON(events, writer) case "yaml": - utils.PrintYAML(events, nil) + utils.PrintYAML(events, writer) default: - fmt.Println("ID\tAmount") + _, _ = fmt.Fprintln(writer, "ID\tAmount") for _, event := range events { - fmt.Printf("%v\t%v\n", event.Id, event.Snippet.AmountMicros) + _, _ = fmt.Fprintf( + writer, "%v\t%v\n", event.Id, event.Snippet.AmountMicros, + ) } } + return nil } func WithHl(hl string) Option { diff --git a/pkg/thumbnail/thumbnail.go b/pkg/thumbnail/thumbnail.go index 229b8e0..da6d9da 100644 --- a/pkg/thumbnail/thumbnail.go +++ b/pkg/thumbnail/thumbnail.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" "os" ) @@ -21,7 +21,7 @@ type thumbnail struct { } type Thumbnail interface { - Set(output string) + Set(string, io.Writer) error } type Option func(*thumbnail) @@ -34,28 +34,28 @@ func NewThumbnail(opts ...Option) Thumbnail { return t } -func (t *thumbnail) Set(output string) { +func (t *thumbnail) Set(output string, writer io.Writer) error { file, err := os.Open(t.File) if err != nil { - utils.PrintJSON(t, nil) - log.Fatalln(errors.Join(errSetThumbnail, err)) + return errors.Join(errSetThumbnail, err) } + call := service.Thumbnails.Set(t.VideoId).Media(file) res, err := call.Do() if err != nil { - utils.PrintJSON(t, nil) - log.Fatalln(errors.Join(errSetThumbnail, err)) + return errors.Join(errSetThumbnail, err) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Println("Thumbnail set done") + _, _ = fmt.Fprintf(writer, "Thumbnail set for video %s", t.VideoId) } + return nil } func WithVideoId(videoId string) Option { diff --git a/pkg/video/video.go b/pkg/video/video.go index a406c2f..02ec446 100644 --- a/pkg/video/video.go +++ b/pkg/video/video.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/playlistItem" "github.com/eat-pray-ai/yutu/pkg/thumbnail" - "log" + "io" "os" "slices" @@ -62,14 +62,14 @@ type video struct { } type Video interface { - List([]string, string) - Insert(string) - Update(string) - Rate() - GetRating(string) - Delete() - ReportAbuse() - get([]string) []*youtube.Video + List([]string, string, io.Writer) error + Insert(string, io.Writer) error + Update(string, io.Writer) error + Rate(io.Writer) error + GetRating(string, io.Writer) error + Delete(io.Writer) error + ReportAbuse(io.Writer) error + Get([]string) ([]*youtube.Video, error) } type Option func(*video) @@ -84,7 +84,7 @@ func NewVideo(opts ...Option) Video { return v } -func (v *video) get(parts []string) []*youtube.Video { +func (v *video) Get(parts []string) ([]*youtube.Video, error) { call := service.Videos.List(parts) if len(v.IDs) > 0 { call = call.Id(v.IDs...) @@ -124,33 +124,36 @@ func (v *video) get(parts []string) []*youtube.Video { res, err := call.Do() if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errGetVideo, err)) + return nil, errors.Join(errGetVideo, err) } - return res.Items + return res.Items, nil } -func (v *video) List(parts []string, output string) { - videos := v.get(parts) +func (v *video) List(parts []string, output string, writer io.Writer) error { + videos, err := v.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(videos, nil) + utils.PrintJSON(videos, writer) case "yaml": - utils.PrintYAML(videos, nil) + utils.PrintYAML(videos, writer) default: - fmt.Println("ID\tTitle") + _, _ = fmt.Fprintln(writer, "ID\tTitle") for _, video := range videos { - fmt.Printf("%s\t%s\n", video.Id, video.Snippet.Title) + _, _ = fmt.Fprintf(writer, "%s\t%s\n", video.Id, video.Snippet.Title) } } + return nil } -func (v *video) Insert(output string) { +func (v *video) Insert(output string, writer io.Writer) error { file, err := os.Open(v.File) if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errInsertVideo, err)) + return errors.Join(errInsertVideo, err) } defer file.Close() @@ -210,8 +213,7 @@ func (v *video) Insert(output string) { res, err := call.Media(file).Do() if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errInsertVideo, err)) + return errors.Join(errInsertVideo, err) } if v.Thumbnail != "" { @@ -220,7 +222,7 @@ func (v *video) Insert(output string) { thumbnail.WithFile(v.Thumbnail), thumbnail.WithService(service), ) - t.Set("silent") + t.Set("silent", nil) } if v.PlaylistId != "" { @@ -234,22 +236,32 @@ func (v *video) Insert(output string) { playlistItem.WithPrivacy(res.Status.PrivacyStatus), playlistItem.WithService(service), ) - pi.Insert("silent") + + _ = pi.Insert("silent", writer) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Video inserted: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Video inserted: %s\n", res.Id) } + return nil } -func (v *video) Update(output string) { - video := v.get([]string{"id", "snippet", "status"})[0] +func (v *video) Update(output string, writer io.Writer) error { + videos, err := v.Get([]string{"id", "snippet", "status"}) + if err != nil { + return errors.Join(errUpdateVideo, err) + } + if len(videos) == 0 { + return errGetVideo + } + + video := videos[0] if v.Title != "" { video.Snippet.Title = v.Title } @@ -286,8 +298,7 @@ func (v *video) Update(output string) { res, err := call.Do() if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errUpdateVideo, err)) + return errors.Join(errUpdateVideo, err) } if v.Thumbnail != "" { @@ -296,7 +307,7 @@ func (v *video) Update(output string) { thumbnail.WithFile(v.Thumbnail), thumbnail.WithService(service), ) - t.Set("silent") + t.Set("silent", nil) } if v.PlaylistId != "" { @@ -310,57 +321,59 @@ func (v *video) Update(output string) { playlistItem.WithPrivacy(res.Status.PrivacyStatus), playlistItem.WithService(service), ) - pi.Insert("silent") + + _ = pi.Insert("silent", writer) } switch output { case "json": - utils.PrintJSON(res, nil) + utils.PrintJSON(res, writer) case "yaml": - utils.PrintYAML(res, nil) + utils.PrintYAML(res, writer) case "silent": default: - fmt.Printf("Video updated: %s\n", res.Id) + _, _ = fmt.Fprintf(writer, "Video updated: %s\n", res.Id) } + return nil } -func (v *video) Rate() { +func (v *video) Rate(writer io.Writer) error { for _, id := range v.IDs { call := service.Videos.Rate(id, v.Rating) err := call.Do() if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errRating, err)) + return errors.Join(errRating, err) } - fmt.Printf("Video %s rated %s\n", id, v.Rating) + _, _ = fmt.Fprintf(writer, "Video %s rated %s\n", id, v.Rating) } + return nil } -func (v *video) GetRating(output string) { +func (v *video) GetRating(output string, writer io.Writer) error { call := service.Videos.GetRating(v.IDs) if v.OnBehalfOfContentOwner != "" { call = call.OnBehalfOfContentOwner(v.OnBehalfOfContentOwnerChannel) } res, err := call.Do() if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errGetRating, err)) + return errors.Join(errGetRating, err) } switch output { case "json": - utils.PrintJSON(res.Items, nil) + utils.PrintJSON(res.Items, writer) case "yaml": - utils.PrintYAML(res.Items, nil) + utils.PrintYAML(res.Items, writer) default: - fmt.Println("ID\tRating") + _, _ = fmt.Fprintln(writer, "ID\tRating") for _, item := range res.Items { - fmt.Printf("%s\t%s\n", item.VideoId, item.Rating) + _, _ = fmt.Fprintf(writer, "%s\t%s\n", item.VideoId, item.Rating) } } + return nil } -func (v *video) Delete() { +func (v *video) Delete(writer io.Writer) error { for _, id := range v.IDs { call := service.Videos.Delete(id) if v.OnBehalfOfContentOwner != "" { @@ -369,14 +382,14 @@ func (v *video) Delete() { err := call.Do() if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errDeleteVideo, err)) + return errors.Join(errDeleteVideo, err) } - fmt.Printf("Video %s deleted", id) + _, _ = fmt.Fprintf(writer, "Video %s deleted", id) } + return nil } -func (v *video) ReportAbuse() { +func (v *video) ReportAbuse(writer io.Writer) error { for _, id := range v.IDs { videoAbuseReport := &youtube.VideoAbuseReport{ Comments: v.Comments, @@ -393,12 +406,12 @@ func (v *video) ReportAbuse() { err := call.Do() if err != nil { - utils.PrintJSON(v, nil) - log.Fatalln(errors.Join(errReportAbuse, err)) + return errors.Join(errReportAbuse, err) } - fmt.Printf("Video %s reported for abuse", id) + _, _ = fmt.Fprintf(writer, "Video %s reported for abuse", id) } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/videoAbuseReportReason/videoAbuseReportReason.go b/pkg/videoAbuseReportReason/videoAbuseReportReason.go index f883363..fcf66d8 100644 --- a/pkg/videoAbuseReportReason/videoAbuseReportReason.go +++ b/pkg/videoAbuseReportReason/videoAbuseReportReason.go @@ -6,7 +6,7 @@ import ( "github.com/eat-pray-ai/yutu/pkg/auth" "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" ) var ( @@ -19,8 +19,8 @@ type videoAbuseReportReason struct { } type VideoAbuseReportReason interface { - get([]string) []*youtube.VideoAbuseReportReason - List([]string, string) + Get([]string) ([]*youtube.VideoAbuseReportReason, error) + List([]string, string, io.Writer) error } type Option func(*videoAbuseReportReason) @@ -33,7 +33,9 @@ func NewVideoAbuseReportReason(opt ...Option) VideoAbuseReportReason { return va } -func (va *videoAbuseReportReason) get(parts []string) []*youtube.VideoAbuseReportReason { +func (va *videoAbuseReportReason) Get(parts []string) ( + []*youtube.VideoAbuseReportReason, error, +) { call := service.VideoAbuseReportReasons.List(parts) if va.Hl != "" { call = call.Hl(va.Hl) @@ -41,29 +43,35 @@ func (va *videoAbuseReportReason) get(parts []string) []*youtube.VideoAbuseRepor res, err := call.Do() if err != nil { - utils.PrintJSON(va, nil) - log.Fatalln(errors.Join(errGetVideoAbuseReportReason, err)) + return nil, errors.Join(errGetVideoAbuseReportReason, err) } - return res.Items + return res.Items, nil } -func (va *videoAbuseReportReason) List(parts []string, output string) { - videoAbuseReportReasons := va.get(parts) +func (va *videoAbuseReportReason) List( + parts []string, output string, writer io.Writer, +) error { + videoAbuseReportReasons, err := va.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(videoAbuseReportReasons, nil) + utils.PrintJSON(videoAbuseReportReasons, writer) case "yaml": - utils.PrintYAML(videoAbuseReportReasons, nil) + utils.PrintYAML(videoAbuseReportReasons, writer) default: - fmt.Println("ID\tTitle") + _, _ = fmt.Fprintln(writer, "ID\tTitle") for _, videoAbuseReportReason := range videoAbuseReportReasons { - fmt.Printf( - "%s\t%s\n", videoAbuseReportReason.Id, - videoAbuseReportReason.Snippet.Label, + _, _ = fmt.Fprintf( + writer, "%s\t%s\n", + videoAbuseReportReason.Id, videoAbuseReportReason.Snippet.Label, ) } } + return nil } func WithHL(hl string) Option { diff --git a/pkg/videoCategory/videoCategory.go b/pkg/videoCategory/videoCategory.go index 08319d2..44134d2 100644 --- a/pkg/videoCategory/videoCategory.go +++ b/pkg/videoCategory/videoCategory.go @@ -4,10 +4,9 @@ import ( "errors" "fmt" "github.com/eat-pray-ai/yutu/pkg/auth" - "log" - "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" + "io" ) var ( @@ -22,8 +21,8 @@ type videoCategory struct { } type VideoCategory interface { - get([]string) []*youtube.VideoCategory - List([]string, string) + Get([]string) ([]*youtube.VideoCategory, error) + List([]string, string, io.Writer) error } type Option func(*videoCategory) @@ -36,7 +35,7 @@ func NewVideoCategory(opt ...Option) VideoCategory { return vc } -func (vc *videoCategory) get(parts []string) []*youtube.VideoCategory { +func (vc *videoCategory) Get(parts []string) ([]*youtube.VideoCategory, error) { call := service.VideoCategories.List(parts) if len(vc.IDs) > 0 { call = call.Id(vc.IDs...) @@ -50,29 +49,35 @@ func (vc *videoCategory) get(parts []string) []*youtube.VideoCategory { res, err := call.Do() if err != nil { - utils.PrintJSON(vc, nil) - log.Fatalln(errors.Join(errGetVideoCategory, err)) + return nil, errors.Join(errGetVideoCategory, err) } - return res.Items + return res.Items, nil } -func (vc *videoCategory) List(parts []string, output string) { - videoCategories := vc.get(parts) +func (vc *videoCategory) List( + parts []string, output string, writer io.Writer, +) error { + videoCategories, err := vc.Get(parts) + if err != nil { + return err + } + switch output { case "json": - utils.PrintJSON(videoCategories, nil) + utils.PrintJSON(videoCategories, writer) case "yaml": - utils.PrintYAML(videoCategories, nil) + utils.PrintYAML(videoCategories, writer) default: - fmt.Println("ID\tTitle\tAssignable") + _, _ = fmt.Fprintln(writer, "ID\tTitle\tAssignable") for _, videoCategory := range videoCategories { - fmt.Printf( - "%s\t%s\t%t\n", videoCategory.Id, + _, _ = fmt.Fprintf( + writer, "%s\t%s\t%t\n", videoCategory.Id, videoCategory.Snippet.Title, videoCategory.Snippet.Assignable, ) } } + return nil } func WithIDs(ids []string) Option { diff --git a/pkg/watermark/BUILD.bazel b/pkg/watermark/BUILD.bazel index bfb4a73..da86dc0 100644 --- a/pkg/watermark/BUILD.bazel +++ b/pkg/watermark/BUILD.bazel @@ -7,7 +7,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/auth", - "//pkg/utils", "@org_golang_google_api//youtube/v3:youtube", ], ) diff --git a/pkg/watermark/watermark.go b/pkg/watermark/watermark.go index 9173e6d..d2cdce8 100644 --- a/pkg/watermark/watermark.go +++ b/pkg/watermark/watermark.go @@ -4,9 +4,8 @@ import ( "errors" "fmt" "github.com/eat-pray-ai/yutu/pkg/auth" - "github.com/eat-pray-ai/yutu/pkg/utils" "google.golang.org/api/youtube/v3" - "log" + "io" "os" ) @@ -27,8 +26,8 @@ type watermark struct { } type Watermark interface { - Set() - Unset() + Set(io.Writer) error + Unset(io.Writer) error } type Option func(*watermark) @@ -43,12 +42,12 @@ func NewWatermark(opts ...Option) Watermark { return w } -func (w *watermark) Set() { +func (w *watermark) Set(writer io.Writer) error { file, err := os.Open(w.File) if err != nil { - utils.PrintJSON(w, nil) - log.Fatalln(errors.Join(errSetWatermark, err)) + return errors.Join(errSetWatermark, err) } + defer file.Close() inVideoBranding := &youtube.InvideoBranding{ Position: &youtube.InvideoPosition{}, @@ -75,14 +74,14 @@ func (w *watermark) Set() { err = call.Do() if err != nil { - utils.PrintJSON(w, nil) - log.Fatalln(errors.Join(errSetWatermark, err)) + return errors.Join(errSetWatermark, err) } - fmt.Printf("Watermark set for channel %s\n", w.ChannelId) + _, _ = fmt.Fprintf(writer, "Watermark set for channel %s\n", w.ChannelId) + return nil } -func (w *watermark) Unset() { +func (w *watermark) Unset(writer io.Writer) error { call := service.Watermarks.Unset(w.ChannelId) if w.OnBehalfOfContentOwner != "" { call = call.OnBehalfOfContentOwner(w.OnBehalfOfContentOwner) @@ -90,11 +89,11 @@ func (w *watermark) Unset() { err := call.Do() if err != nil { - utils.PrintJSON(w, nil) - log.Fatalln(errors.Join(errUnsetWatermark, err)) + return errors.Join(errUnsetWatermark, err) } - fmt.Printf("Watermark unset for channel %s\n", w.ChannelId) + _, _ = fmt.Fprintf(writer, "Watermark unset for channel %s\n", w.ChannelId) + return nil } func WithChannelId(channelId string) Option {