From c102cdbb713b3eb28b8bda92cd69e7dc7f668d07 Mon Sep 17 00:00:00 2001 From: chaoqun <27287694+OpenWaygate@users.noreply.github.com> Date: Tue, 20 Feb 2024 23:34:37 +0800 Subject: [PATCH] :sparkles: Support video update --- cmd/video/update.go | 38 ++++++++++++++++++++++++++++++++++++++ cmd/video/video.go | 4 ++-- pkg/yutuber/channel.go | 33 +++++++++++++++++++-------------- pkg/yutuber/video.go | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 cmd/video/update.go diff --git a/cmd/video/update.go b/cmd/video/update.go new file mode 100644 index 0000000..7217f59 --- /dev/null +++ b/cmd/video/update.go @@ -0,0 +1,38 @@ +package video + +import ( + "github.com/eat-pray-ai/yutu/pkg/yutuber" + "github.com/spf13/cobra" +) + +var updateCmd = &cobra.Command{ + Use: "update", + Short: "update a video on YouTube", + Long: `update a video on YouTube, with the specified title, description, tags, etc.`, + Run: func(cmd *cobra.Command, args []string) { + v := yutuber.NewVideo( + yutuber.WithVideoId(id), + yutuber.WithVideoTitle(title), + yutuber.WithVideoDesc(desc), + yutuber.WithVideoTags(tags), + yutuber.WithVideoLanguage(language), + yutuber.WithVideoCategory(category), + yutuber.WithVideoPrivacy(privacy), + yutuber.WithVideoEmbeddable(embeddable), + ) + v.Update() + }, +} + +func init() { + videoCmd.AddCommand(updateCmd) + + updateCmd.Flags().StringVarP(&id, "id", "i", "", "ID of the video") + updateCmd.Flags().StringVarP(&title, "title", "t", "", "Title of the video") + updateCmd.Flags().StringVarP(&desc, "desc", "d", "", "Description of the video") + updateCmd.Flags().StringVarP(&tags, "tags", "g", "", "Comma separated tags") + updateCmd.Flags().StringVarP(&language, "language", "l", "", "Language of the video") + updateCmd.Flags().StringVarP(&category, "category", "c", "", "Category of the video") + updateCmd.Flags().StringVarP(&privacy, "privacy", "v", "", "Privacy status of the video") + updateCmd.Flags().BoolVarP(&embeddable, "embeddable", "b", true, "Whether the video is embeddable") +} diff --git a/cmd/video/video.go b/cmd/video/video.go index d779812..1e5c1a0 100644 --- a/cmd/video/video.go +++ b/cmd/video/video.go @@ -10,13 +10,13 @@ import ( var ( id string - path string + file string title string desc string tags string language string // thumbnails string //TODO - channelId string + channel string category string privacy string forKids bool diff --git a/pkg/yutuber/channel.go b/pkg/yutuber/channel.go index 37a6cb9..9cb7455 100644 --- a/pkg/yutuber/channel.go +++ b/pkg/yutuber/channel.go @@ -42,19 +42,21 @@ func NewChannel(opts ...ChannelOption) *Channel { } func (c *Channel) List() { - channel := c.get() - fmt.Printf(" ID: %s\n", channel.Id) - fmt.Printf(" Title: %s\n", channel.Snippet.Title) - fmt.Printf(" Description: %s\n", channel.Snippet.Description) - fmt.Printf("Published At: %s\n", channel.Snippet.PublishedAt) - fmt.Printf(" Country: %s\n\n", channel.Snippet.Country) - fmt.Printf(" View Count: %d\n", channel.Statistics.ViewCount) - fmt.Printf("Subscriber Count: %d\n", channel.Statistics.SubscriberCount) - fmt.Printf(" Video Count: %d\n", channel.Statistics.VideoCount) + channels := c.get() + for _, channel := range channels { + fmt.Printf(" ID: %s\n", channel.Id) + fmt.Printf(" Title: %s\n", channel.Snippet.Title) + fmt.Printf(" Description: %s\n", channel.Snippet.Description) + fmt.Printf("Published At: %s\n", channel.Snippet.PublishedAt) + fmt.Printf(" Country: %s\n\n", channel.Snippet.Country) + fmt.Printf(" View Count: %d\n", channel.Statistics.ViewCount) + fmt.Printf("Subscriber Count: %d\n", channel.Statistics.SubscriberCount) + fmt.Printf(" Video Count: %d\n\n", channel.Statistics.VideoCount) + } } func (c *Channel) Update() { - channel := c.get() + channel := c.get()[0] // TODO: is there a better way to check and update? if c.title != "" { channel.Snippet.Title = c.title @@ -69,21 +71,24 @@ func (c *Channel) Update() { if err != nil { log.Fatalln(errors.Join(errUpdateChannel, err), c.id) } - fmt.Println("Channel updated:") c.List() } -func (c *Channel) get() *youtube.Channel { +func (c *Channel) get() []*youtube.Channel { service := auth.NewY2BService(youtube.YoutubeReadonlyScope) call := service.Channels.List(part) - call = call.Id(c.id) + if c.id != "" { + call = call.Id(c.id) + } else { + call = call.Mine(true) + } resp, err := call.Do() if err != nil { log.Fatalln(errors.Join(errGetChannel, err), c.id) } - return resp.Items[0] + return resp.Items } func WithChannelID(id string) ChannelOption { diff --git a/pkg/yutuber/video.go b/pkg/yutuber/video.go index e8a16a9..f849ee9 100644 --- a/pkg/yutuber/video.go +++ b/pkg/yutuber/video.go @@ -36,6 +36,7 @@ type Video struct { type VideoService interface { List() Insert() + Update() get() *youtube.Video validate() } @@ -55,7 +56,9 @@ func NewVideo(opts ...VideoOption) *Video { func (v *Video) get() *youtube.Video { service := auth.NewY2BService(youtube.YoutubeReadonlyScope) call := service.Videos.List([]string{"id", "snippet", "status", "statistics"}) - call = call.Id(v.id) + if v.id == "" { + call = call.Id(v.id) + } response, err := call.Do() if err != nil { log.Fatalln(errors.Join(errGetVideo, err), v.id) @@ -120,6 +123,39 @@ func (v *Video) Insert() { fmt.Printf("Upload successful! Video ID: %v\n", video.Id) } +func (v *Video) Update() { + video := v.get() + if v.title != "" { + video.Snippet.Title = v.title + } + if v.desc != "" { + video.Snippet.Description = v.desc + } + if v.tags != nil { + video.Snippet.Tags = v.tags + } + if v.language != "" { + video.Snippet.DefaultLanguage = v.language + video.Snippet.DefaultAudioLanguage = v.language + } + if v.category != "" { + video.Snippet.CategoryId = v.category + } + if v.privacy != "" { + video.Status.PrivacyStatus = v.privacy + } + video.Status.Embeddable = v.embeddable + + service := auth.NewY2BService(youtube.YoutubeScope) + call := service.Videos.Update([]string{"snippet,status"}, video) + _, err := call.Do() + if err != nil { + log.Fatalln(errors.Join(errUpdateVideo, err), v.id) + } + fmt.Println("Video updated:") + v.List() +} + func (v *Video) validate() { if v.forKids && v.restricted { log.Fatalln("Video cannot be both for kids and restricted")