mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Support video counter queries for YouTube
This commit is contained in:
@@ -24,3 +24,7 @@ func makeEnclosure(feed *model.Feed, id string, lengthInBytes int64) (string, it
|
||||
url := fmt.Sprintf("http://podsync.net/download/%s/%s.%s", feed.HashID, id, ext)
|
||||
return url, contentType, lengthInBytes
|
||||
}
|
||||
|
||||
type VideoCounter interface {
|
||||
GetVideoCount(feed *model.Feed) (uint64, error)
|
||||
}
|
||||
+33
-9
@@ -25,6 +25,8 @@ const (
|
||||
highAudioBytesPerSecond = 128000 / 8
|
||||
)
|
||||
|
||||
var _ VideoCounter = (*YouTubeBuilder)(nil)
|
||||
|
||||
type apiKey string
|
||||
|
||||
func (key apiKey) Get() (string, string) {
|
||||
@@ -38,8 +40,8 @@ type YouTubeBuilder struct {
|
||||
|
||||
// Cost: 5 units (call method: 1, snippet: 2, contentDetails: 2)
|
||||
// See https://developers.google.com/youtube/v3/docs/channels/list#part
|
||||
func (yt *YouTubeBuilder) listChannels(linkType api.LinkType, id string) (*youtube.Channel, error) {
|
||||
req := yt.client.Channels.List("id,snippet,contentDetails")
|
||||
func (yt *YouTubeBuilder) listChannels(linkType api.LinkType, id string, parts string) (*youtube.Channel, error) {
|
||||
req := yt.client.Channels.List(parts)
|
||||
|
||||
switch linkType {
|
||||
case api.LinkTypeChannel:
|
||||
@@ -65,8 +67,8 @@ func (yt *YouTubeBuilder) listChannels(linkType api.LinkType, id string) (*youtu
|
||||
|
||||
// Cost: 3 units (call method: 1, snippet: 2)
|
||||
// See https://developers.google.com/youtube/v3/docs/playlists/list#part
|
||||
func (yt *YouTubeBuilder) listPlaylists(id, channelID string) (*youtube.Playlist, error) {
|
||||
req := yt.client.Playlists.List("id,snippet")
|
||||
func (yt *YouTubeBuilder) listPlaylists(id, channelID string, parts string) (*youtube.Playlist, error) {
|
||||
req := yt.client.Playlists.List(parts)
|
||||
|
||||
if id != "" {
|
||||
req = req.Id(id)
|
||||
@@ -132,9 +134,29 @@ func (yt *YouTubeBuilder) selectThumbnail(snippet *youtube.ThumbnailDetails, qua
|
||||
return snippet.Default.Url
|
||||
}
|
||||
|
||||
// Cost:
|
||||
// - 5 units for channel or user
|
||||
// - 3 units for playlist
|
||||
func (yt *YouTubeBuilder) GetVideoCount(feed *model.Feed) (uint64, error) {
|
||||
switch feed.LinkType {
|
||||
case api.LinkTypeChannel, api.LinkTypeUser:
|
||||
// Cost: 3 units
|
||||
if channel, err := yt.listChannels(feed.LinkType, feed.ItemID, "id,statistics"); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return channel.Statistics.VideoCount, nil
|
||||
}
|
||||
|
||||
case api.LinkTypePlaylist:
|
||||
// Cost: 3 units
|
||||
if playlist, err := yt.listPlaylists(feed.ItemID, "", "id,contentDetails"); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return uint64(playlist.ContentDetails.ItemCount), nil
|
||||
}
|
||||
|
||||
default:
|
||||
return 0, errors.New("unsupported link format")
|
||||
}
|
||||
}
|
||||
|
||||
func (yt *YouTubeBuilder) queryFeed(feed *model.Feed) (*itunes.Podcast, string, error) {
|
||||
var (
|
||||
title string
|
||||
@@ -147,7 +169,8 @@ func (yt *YouTubeBuilder) queryFeed(feed *model.Feed) (*itunes.Podcast, string,
|
||||
|
||||
switch feed.LinkType {
|
||||
case api.LinkTypeChannel, api.LinkTypeUser:
|
||||
channel, err := yt.listChannels(feed.LinkType, feed.ItemID)
|
||||
// Cost: 5 units for channel or user
|
||||
channel, err := yt.listChannels(feed.LinkType, feed.ItemID, "id,snippet,contentDetails")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -172,7 +195,8 @@ func (yt *YouTubeBuilder) queryFeed(feed *model.Feed) (*itunes.Podcast, string,
|
||||
thumbnails = channel.Snippet.Thumbnails
|
||||
|
||||
case api.LinkTypePlaylist:
|
||||
playlist, err := yt.listPlaylists(feed.ItemID, "")
|
||||
// Cost: 3 units for playlist
|
||||
playlist, err := yt.listPlaylists(feed.ItemID, "", "id,snippet")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
var ytKey = os.Getenv("YOUTUBE_TEST_API_KEY")
|
||||
|
||||
func TestQueryYTChannel(t *testing.T) {
|
||||
func TestYT_QueryChannel(t *testing.T) {
|
||||
if ytKey == "" {
|
||||
t.Skip("YouTube API key is not provided")
|
||||
}
|
||||
@@ -21,16 +21,16 @@ func TestQueryYTChannel(t *testing.T) {
|
||||
builder, err := NewYouTubeBuilder(ytKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
channel, err := builder.listChannels(api.LinkTypeChannel, "UC2yTVSttx7lxAOAzx1opjoA")
|
||||
channel, err := builder.listChannels(api.LinkTypeChannel, "UC2yTVSttx7lxAOAzx1opjoA", "id")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "UC2yTVSttx7lxAOAzx1opjoA", channel.Id)
|
||||
|
||||
channel, err = builder.listChannels(api.LinkTypeUser, "fxigr1")
|
||||
channel, err = builder.listChannels(api.LinkTypeUser, "fxigr1", "id")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "UCr_fwF-n-2_olTYd-m3n32g", channel.Id)
|
||||
}
|
||||
|
||||
func TestBuildYTFeed(t *testing.T) {
|
||||
func TestYT_BuildFeed(t *testing.T) {
|
||||
if ytKey == "" {
|
||||
t.Skip("YouTube API key is not provided")
|
||||
}
|
||||
@@ -82,3 +82,29 @@ func TestBuildYTFeed(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestYT_GetVideoCount(t *testing.T) {
|
||||
if ytKey == "" {
|
||||
t.Skip("YouTube API key is not provided")
|
||||
}
|
||||
|
||||
builder, err := NewYouTubeBuilder(ytKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
feeds := []*model.Feed{
|
||||
{Provider: api.ProviderYoutube, LinkType: api.LinkTypeUser, ItemID: "fxigr1"},
|
||||
{Provider: api.ProviderYoutube, LinkType: api.LinkTypeChannel, ItemID: "UCupvZG-5ko_eiXAupbDfxWw"},
|
||||
{Provider: api.ProviderYoutube, LinkType: api.LinkTypePlaylist, ItemID: "PLfVk3KMh3VX1yJShGRsJmsqAjvMIviJYQ"},
|
||||
{Provider: api.ProviderYoutube, LinkType: api.LinkTypeChannel, ItemID: "UCK9lZ2lHRBgx2LOcqPifukA"},
|
||||
{Provider: api.ProviderYoutube, LinkType: api.LinkTypeUser, ItemID: "WylsaLive"},
|
||||
{Provider: api.ProviderYoutube, LinkType: api.LinkTypePlaylist, ItemID: "PLUVl5pafUrBydT_gsCjRGeCy0hFHloec8"},
|
||||
}
|
||||
|
||||
for _, f := range feeds {
|
||||
t.Run(f.ItemID, func(t *testing.T) {
|
||||
count, err := builder.GetVideoCount(f)
|
||||
assert.NoError(t, err)
|
||||
assert.NotZero(t, count)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user