From acd6469435034b3e91d446a81cc4626edeef3a9d Mon Sep 17 00:00:00 2001 From: Dovydas Date: Wed, 25 Oct 2023 00:06:18 +0100 Subject: [PATCH] add support for value time splits --- go.mod | 2 ++ go.sum | 2 ++ namespace_podcast.go | 48 +++++++++++++++++++++++++++++++++++++++----- types_test.go | 30 +++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 97f7083..c7329f4 100644 --- a/go.mod +++ b/go.mod @@ -3,3 +3,5 @@ module github.com/rssblue/types go 1.18 require github.com/google/go-cmp v0.5.9 + +require github.com/google/uuid v1.3.1 // indirect diff --git a/go.sum b/go.sum index 62841cd..c67106b 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/namespace_podcast.go b/namespace_podcast.go index 674362c..15df186 100644 --- a/namespace_podcast.go +++ b/namespace_podcast.go @@ -3,9 +3,12 @@ package types import ( "encoding/xml" "fmt" + "math" "strconv" "strings" "time" + + "github.com/google/uuid" ) // NamespacePodcast is the Podcasting 2.0 namespace. @@ -36,11 +39,12 @@ type PodcastChapters struct { // PodcastValue enables to describe Value 4 Value payments. Read more at // https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#value type PodcastValue struct { - XMLName xml.Name `xml:"podcast:value"` - Type string `xml:"type,attr"` - Method string `xml:"method,attr"` - Suggested *float64 `xml:"suggested,attr,omitempty"` - Recipients []PodcastValueRecipient + XMLName xml.Name `xml:"podcast:value"` + Type string `xml:"type,attr"` + Method string `xml:"method,attr"` + Suggested *float64 `xml:"suggested,attr,omitempty"` + Recipients []PodcastValueRecipient + ValueTimeSplits []PodcastValueTimeSplit } // PodcastValueRecipient describes the recipient of Value 4 Value payments. @@ -57,6 +61,29 @@ type PodcastValueRecipient struct { Fee *bool `xml:"bool,attr"` } +// PodcastValueTimeSplit describes value splits that are valid for a certain period of time +// Read more at +// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#value-time-split +type PodcastValueTimeSplit struct { + XMLName xml.Name `xml:"podcast:valueTimeSplit"` + StartTime DurationInteger `xml:"startTime,attr"` + Duration DurationInteger `xml:"duration,attr"` + RemoteStartTime *DurationInteger `xml:"remoteStartTime,attr,omitempty"` + RemotePercentage *uint `xml:"remotePercentage,attr,omitempty"` + Recipients []PodcastValueRecipient + RemoteItem PodcastRemoteItem +} + +// PodcastRemoteItem provides a way to "point" to another feed or item in it. +// Read more at +// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#remote-item +type PodcastRemoteItem struct { + XMLName xml.Name `xml:"podcast:remoteItem"` + ItemGUID *string `xml:"itemGuid,attr"` + FeedGUID uuid.UUID `xml:"feedGuid,attr"` + Medium *PodcastMedium `xml:"medium,attr"` +} + // PodcastLocked tells podcast hosting platforms whether they are allowed to import // the feed. Read more at // https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#locked @@ -170,6 +197,17 @@ func (duration Duration) MarshalXMLAttr(name xml.Name) (xml.Attr, error) { return xml.Attr{Name: xml.Name{Local: name.Local}, Value: s}, nil } +// DurationInteger denotes timestamps and durations during a podcast episode, but which are converted to integer seconds. +type DurationInteger time.Duration + +func (duration DurationInteger) MarshalXMLAttr(name xml.Name) (xml.Attr, error) { + seconds := time.Duration(duration).Seconds() + seconds = math.Round(seconds) + s := strconv.Itoa(int(seconds)) + + return xml.Attr{Name: xml.Name{Local: name.Local}, Value: s}, nil +} + // PodcastPerson specifies a person of interest to the podcast. Read more at // https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#person type PodcastPerson struct { diff --git a/types_test.go b/types_test.go index 8593216..772c140 100644 --- a/types_test.go +++ b/types_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "github.com/google/uuid" "github.com/rssblue/types" ) @@ -91,6 +92,29 @@ func TestMarshal(t *testing.T) { Split: 10, }, }, + ValueTimeSplits: []types.PodcastValueTimeSplit{ + { + StartTime: types.DurationInteger(60 * time.Second), + Duration: types.DurationInteger(237 * time.Second), + RemoteItem: types.PodcastRemoteItem{ + ItemGUID: pointer("https://podcastindex.org/podcast/4148683#1"), + FeedGUID: uuid.MustParse("a94f5cc9-8c58-55fc-91fe-a324087a655b"), + Medium: pointer(types.PodcastMediumMusic), + }, + RemotePercentage: pointer[uint](95), + }, + { + StartTime: types.DurationInteger(330 * time.Second), + Duration: types.DurationInteger(53 * time.Second), + RemoteItem: types.PodcastRemoteItem{ + ItemGUID: pointer("https://podcastindex.org/podcast/4148683#3"), + FeedGUID: uuid.MustParse("a94f5cc9-8c58-55fc-91fe-a324087a655b"), + Medium: pointer(types.PodcastMediumMusic), + }, + RemoteStartTime: pointer(types.DurationInteger(174 * time.Second)), + RemotePercentage: pointer[uint](95), + }, + }, }, PodcastGUID: pointer(types.PodcastGUID("cda647ce-56b8-5d7c-9448-ba1993ab46b7")), PodcastMedium: &types.PodcastMediumPodcast, @@ -375,6 +399,12 @@ func TestMarshal(t *testing.T) { + + + + + + This is a simple episode & its description.