mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
add support for descengind playlists
This commit is contained in:
@@ -78,6 +78,7 @@ vimeo = [ # Multiple keys will be rotated.
|
||||
update_period = "12h" # How often query for updates, examples: "60m", "4h", "2h45m"
|
||||
quality = "high" # or "low"
|
||||
format = "video" # or "audio"
|
||||
playlist_sort = "asc" # or "desc", which will fetch playlist items from the end
|
||||
# custom.cover_art_quality use "high" or "low" to special cover image quality from channel cover default is equal with "quality" and disable when custom.cover_art was set.
|
||||
# custom = { title = "Level1News", description = "News sections of Level1Techs, in a podcast feed!", author = "Level1Tech", cover_art = "{IMAGE_URL}", cover_art_quality = "high", category = "TV", subcategories = ["Documentary", "Tech News"], explicit = true, lang = "en" } # Optional feed customizations
|
||||
# max_height = 720 # Optional maximal height of video, example: 720, 1080, 1440, 2160, ...
|
||||
|
@@ -330,11 +330,14 @@ func (yt *YouTubeBuilder) queryVideoDescriptions(ctx context.Context, playlist m
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cost: (3 units + 5 units) * X pages = 8 units per page
|
||||
// Cost:
|
||||
// ASC mode = (3 units + 5 units) * X pages = 8 units per page
|
||||
// DESC mode = 3 units * (number of pages in the entire playlist) + 5 units
|
||||
func (yt *YouTubeBuilder) queryItems(ctx context.Context, feed *model.Feed) error {
|
||||
var (
|
||||
token string
|
||||
count int
|
||||
token string
|
||||
count int
|
||||
allSnippets []*youtube.PlaylistItemSnippet
|
||||
)
|
||||
|
||||
for {
|
||||
@@ -346,25 +349,39 @@ func (yt *YouTubeBuilder) queryItems(ctx context.Context, feed *model.Feed) erro
|
||||
token = pageToken
|
||||
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
break
|
||||
}
|
||||
|
||||
// Extract playlist snippets
|
||||
snippets := map[string]*youtube.PlaylistItemSnippet{}
|
||||
for _, item := range items {
|
||||
snippets[item.Snippet.ResourceId.VideoId] = item.Snippet
|
||||
allSnippets = append(allSnippets, item.Snippet)
|
||||
count++
|
||||
}
|
||||
|
||||
// Query video descriptions from the list of ids
|
||||
if err := yt.queryVideoDescriptions(ctx, snippets, feed); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count >= feed.PageSize || token == "" {
|
||||
return nil
|
||||
if (feed.PlaylistSort != model.SortingDesc && count >= feed.PageSize) || token == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(allSnippets) > feed.PageSize {
|
||||
if feed.PlaylistSort != model.SortingDesc {
|
||||
allSnippets = allSnippets[:feed.PageSize]
|
||||
} else {
|
||||
allSnippets = allSnippets[len(allSnippets)-feed.PageSize:]
|
||||
}
|
||||
}
|
||||
|
||||
snippets := map[string]*youtube.PlaylistItemSnippet{}
|
||||
for _, snippet := range allSnippets {
|
||||
snippets[snippet.ResourceId.VideoId] = snippet
|
||||
}
|
||||
|
||||
// Query video descriptions from the list of ids
|
||||
if err := yt.queryVideoDescriptions(ctx, snippets, feed); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (yt *YouTubeBuilder) Build(ctx context.Context, cfg *config.Feed) (*model.Feed, error) {
|
||||
@@ -374,13 +391,14 @@ func (yt *YouTubeBuilder) Build(ctx context.Context, cfg *config.Feed) (*model.F
|
||||
}
|
||||
|
||||
feed := &model.Feed{
|
||||
ItemID: info.ItemID,
|
||||
Provider: info.Provider,
|
||||
LinkType: info.LinkType,
|
||||
Format: cfg.Format,
|
||||
Quality: cfg.Quality,
|
||||
PageSize: cfg.PageSize,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
ItemID: info.ItemID,
|
||||
Provider: info.Provider,
|
||||
LinkType: info.LinkType,
|
||||
Format: cfg.Format,
|
||||
Quality: cfg.Quality,
|
||||
PageSize: cfg.PageSize,
|
||||
PlaylistSort: cfg.PlaylistSort,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
}
|
||||
|
||||
if feed.PageSize == 0 {
|
||||
|
@@ -45,6 +45,8 @@ type Feed struct {
|
||||
YouTubeDLArgs []string `toml:"youtube_dl_args"`
|
||||
// Included in OPML file
|
||||
OPML bool `toml:"opml"`
|
||||
// Playlist sort
|
||||
PlaylistSort model.Sorting `toml:"playlist_sort"`
|
||||
}
|
||||
|
||||
type Filters struct {
|
||||
@@ -237,5 +239,9 @@ func (c *Config) applyDefaults(configPath string) {
|
||||
if feed.PageSize == 0 {
|
||||
feed.PageSize = model.DefaultPageSize
|
||||
}
|
||||
|
||||
if feed.PlaylistSort == "" {
|
||||
feed.PlaylistSort = model.SortingAsc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ timeout = 15
|
||||
format = "audio"
|
||||
quality = "low"
|
||||
filters = { title = "regex for title here" }
|
||||
playlist_sort = "desc"
|
||||
clean = { keep_last = 10 }
|
||||
[feeds.XYZ.custom]
|
||||
cover_art = "http://img"
|
||||
@@ -80,6 +81,7 @@ timeout = 15
|
||||
assert.EqualValues(t, "low", feed.Quality)
|
||||
assert.EqualValues(t, "regex for title here", feed.Filters.Title)
|
||||
assert.EqualValues(t, 10, feed.Clean.KeepLast)
|
||||
assert.EqualValues(t, model.SortingDesc, feed.PlaylistSort)
|
||||
|
||||
assert.EqualValues(t, "http://img", feed.Custom.CoverArt)
|
||||
assert.EqualValues(t, "high", feed.Custom.CoverArtQuality)
|
||||
|
@@ -20,6 +20,14 @@ const (
|
||||
FormatVideo = Format("video")
|
||||
)
|
||||
|
||||
// Playlist sorting style
|
||||
type Sorting string
|
||||
|
||||
const (
|
||||
SortingDesc = Sorting("desc")
|
||||
SortingAsc = Sorting("asc")
|
||||
)
|
||||
|
||||
type Episode struct {
|
||||
// ID of episode
|
||||
ID string `json:"id"`
|
||||
@@ -54,6 +62,7 @@ type Feed struct {
|
||||
ItemURL string `json:"item_url"` // Platform specific URL
|
||||
Episodes []*Episode `json:"-"` // Array of episodes
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
PlaylistSort Sorting `json:"playlist_sort"`
|
||||
}
|
||||
|
||||
type EpisodeStatus string
|
||||
|
Reference in New Issue
Block a user