mirror of
https://github.com/navidrome/navidrome.git
synced 2026-11-07 02:38:50 +01:00
Adds full support for the Podcasting 2.0 namespace (https://podcastindex.org/namespace/1.0) across RSS parsing, persistence, Subsonic API responses, and OpenSubsonic extensions. - podcast:guid: channel-level UUIDv5 for stable identity across feed URL changes - podcast:chapters: per-episode chapters URL + MIME type (chaptersUrl in API) - podcast:transcript: multiple transcripts per episode stored in a dedicated podcast_transcript table; attributes: url, type, language, rel - podcast:season: season number + optional name per episode - podcast:episode: episode number (decimal string) + optional display label - podcast:person: host/guest entries at both channel and episode level stored in a dedicated podcast_person table; attributes: name, role, group, img, href; role defaults to "host" and group defaults to "cast" per spec - podcast:locked: feed lock flag + optional owner email on channel - podcast:funding: first funding entry URL + display text on channel - podcast:medium: content type classification on channel - podcast:soundbite: startTime (float), duration (float), title per episode - podcast:updateFrequency: display text + rrule + complete flag on channel - podcast:podroll: creator-recommended feed list stored in podcast_podroll table (feedGuid, feedUrl, title, sort_order); returned as podroll[] in GetPodcasts - podcast:liveItem: live stream detection stored in podcast_live_item table (one row per channel, unique index); stores status, start/end times, enclosure URL/type, and contentLink for fallback playback; returned as liveItem object in GetPodcasts; Upsert preserves created_at on updates - podcast:podping: usesPodping boolean on channel; RefreshChannels skips channels with usesPodping=true (they receive updates via Podping WebSocket) - 20260428000000_add_podcast20.go: ALTER TABLE adds 9 columns to podcast_channel, 9 columns to podcast_episode; CREATE TABLE podcast_transcript (episode_id FK, url, mime_type, language, rel) and podcast_person (no FK constraints — put() serialises "" not NULL) - 20260428120000_add_podcast_tier3.go: ALTER TABLE adds uses_podping to podcast_channel; CREATE TABLE podcast_podroll and podcast_live_item (UNIQUE INDEX on channel_id) GetPodcasts response (PodcastChannel) gains: podcastGuid, locked, medium, fundingUrl, fundingText, updateFrequency, complete, usesPodping, person[], podroll[], liveItem{} GetPodcastEpisode response (PodcastEpisode) gains: season, seasonName, episode, episodeDisplay, chaptersUrl, soundbiteStart, soundbiteDur, transcript[], person[] GetPodcastEpisode now loads transcripts and persons from their repositories (previously only read the base episode row). New OpenSubsonic extensions declared: podcastChapters, podcastTranscripts, podcastSeason, podcastPerson, podcastFunding, podcastMedium, podcastPodroll, podcastLiveItem, podcastPodping - core/podcasts/rss_test.go: 41 new specs covering all namespace tags, default value handling (role→"host", group→"cast"), backward compatibility - core/podcasts/podcasts_test.go: 26 new service specs covering AddChannel field persistence, transcript/person saving, podroll/liveItem saving, RefreshChannels podping skip behaviour - persistence/podcast_transcript_repository_test.go: 10 specs - persistence/podcast_person_repository_test.go: 12 specs - persistence/podcast_podroll_repository_test.go: 10 specs - persistence/podcast_live_item_repository_test.go: 8 specs - server/subsonic/podcasts_test.go: 15 new handler specs for Tier 2 and Tier 3 fields in GetPodcasts and GetPodcastEpisode responses
57 lines
1.9 KiB
Go
57 lines
1.9 KiB
Go
package model
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/Masterminds/squirrel"
|
|
"github.com/deluan/rest"
|
|
)
|
|
|
|
type QueryOptions struct {
|
|
Sort string
|
|
Order string
|
|
Max int
|
|
Offset int
|
|
Filters squirrel.Sqlizer
|
|
Seed string // for random sorting
|
|
}
|
|
|
|
type ResourceRepository interface {
|
|
rest.Repository
|
|
}
|
|
|
|
type DataStore interface {
|
|
Library(ctx context.Context) LibraryRepository
|
|
Folder(ctx context.Context) FolderRepository
|
|
Album(ctx context.Context) AlbumRepository
|
|
Artist(ctx context.Context) ArtistRepository
|
|
MediaFile(ctx context.Context) MediaFileRepository
|
|
Genre(ctx context.Context) GenreRepository
|
|
Tag(ctx context.Context) TagRepository
|
|
Playlist(ctx context.Context) PlaylistRepository
|
|
PlayQueue(ctx context.Context) PlayQueueRepository
|
|
Transcoding(ctx context.Context) TranscodingRepository
|
|
Player(ctx context.Context) PlayerRepository
|
|
Radio(ctx context.Context) RadioRepository
|
|
Share(ctx context.Context) ShareRepository
|
|
Property(ctx context.Context) PropertyRepository
|
|
User(ctx context.Context) UserRepository
|
|
UserProps(ctx context.Context) UserPropsRepository
|
|
ScrobbleBuffer(ctx context.Context) ScrobbleBufferRepository
|
|
Scrobble(ctx context.Context) ScrobbleRepository
|
|
Plugin(ctx context.Context) PluginRepository
|
|
Artwork(ctx context.Context) ArtworkRepository
|
|
ArtworkQueue(ctx context.Context) ArtworkQueueRepository
|
|
PodcastChannel(ctx context.Context) PodcastChannelRepository
|
|
PodcastEpisode(ctx context.Context) PodcastEpisodeRepository
|
|
PodcastTranscript(ctx context.Context) PodcastTranscriptRepository
|
|
PodcastPerson(ctx context.Context) PodcastPersonRepository
|
|
PodcastPodroll(ctx context.Context) PodcastPodrollRepository
|
|
PodcastLiveItem(ctx context.Context) PodcastLiveItemRepository
|
|
|
|
Resource(ctx context.Context, model any) ResourceRepository
|
|
|
|
WithTx(block func(tx DataStore) error, scope ...string) error
|
|
WithTxImmediate(block func(tx DataStore) error, scope ...string) error
|
|
GC(ctx context.Context, libraryIDs ...int) error
|
|
}
|