Skip to content

Commit acc3f34

Browse files
committed
Add support for PC2.0 <podcast:remoteItem> tag.
1 parent 842dd96 commit acc3f34

File tree

6 files changed

+172
-13
lines changed

6 files changed

+172
-13
lines changed

CHANGELOG.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1+
## 0.7.0
2+
3+
- Add support for PC2.0 `<podcast:remoteItem>` tag (at channel level).
4+
15
## 0.6.9
26

37
- Bug fix: handle empty fields from iTunes and PodcastIndex API call results.
48

59
## 0.6.8
610

7-
- BREAKING CHANGE: Language is now a text parameter (2-3 letter code) rather than enum. This is because iTunes largely ignores language, but PodcastIndex can use it for trending podcasts.
11+
- BREAKING CHANGE: Language is now a text parameter (2-3 letter code) rather than enum. This is because iTunes largely
12+
ignores language, but PodcastIndex can use it for trending podcasts.
813

914
## 0.6.7
1015

1116
- Update example to handle null feed.
12-
- Default podcast image to take iTunes version if available and fallback to channel version to be consistent with episode image handling.
17+
- Default podcast image to take iTunes version if available and fallback to channel version to be consistent with
18+
episode image handling.
1319

1420
## 0.6.6
1521

@@ -63,7 +69,8 @@
6369

6470
## 0.5.1
6571

66-
- Breaking change: Search provider is now passed when instantiating a Search object, rather than passing one at search time.
72+
- Breaking change: Search provider is now passed when instantiating a Search object, rather than passing one at search
73+
time.
6774
- Support for genres across iTunes & PodcastIndex.
6875

6976
## 0.5.0
@@ -128,15 +135,15 @@
128135

129136
## 0.3.1
130137

131-
- Add support for returning podcast chart.
138+
- Add support for returning podcast chart.
132139

133140
## 0.3.0
134141

135-
- Fix formatting.
142+
- Fix formatting.
136143

137144
## 0.2.9
138145

139-
- Fix lints for newer version of Pedantic.
146+
- Fix lints for newer version of Pedantic.
140147

141148
## 0.2.8
142149

lib/src/model/podcast.dart

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@ import 'dart:async';
55
import 'dart:convert';
66
import 'dart:io';
77

8-
import 'package:podcast_search/src/model/block.dart';
9-
import 'package:podcast_search/src/model/value_recipient.dart';
10-
import 'package:rss_dart/dart_rss.dart';
118
import 'package:dio/dio.dart';
129
import 'package:podcast_search/podcast_search.dart';
10+
import 'package:podcast_search/src/model/block.dart';
1311
import 'package:podcast_search/src/model/chapter.dart';
1412
import 'package:podcast_search/src/model/chapter_headers.dart';
1513
import 'package:podcast_search/src/model/locked.dart';
1614
import 'package:podcast_search/src/model/person.dart';
15+
import 'package:podcast_search/src/model/remote_item.dart';
16+
import 'package:podcast_search/src/model/value_recipient.dart';
1717
import 'package:podcast_search/src/search/base_search.dart';
1818
import 'package:podcast_search/src/utils/json_parser.dart';
1919
import 'package:podcast_search/src/utils/srt_parser.dart';
2020
import 'package:podcast_search/src/utils/utils.dart';
21+
import 'package:rss_dart/dart_rss.dart';
2122

2223
/// This class represents a podcast and its episodes. The Podcast is instantiated with a feed URL which is
2324
/// then parsed and the episode list generated.
@@ -64,6 +65,9 @@ class Podcast {
6465
/// A list of current episodes.
6566
final List<Episode> episodes;
6667

68+
/// A list of remote items at the channel level
69+
final List<RemoteItem> remoteItems;
70+
6771
Podcast._({
6872
this.guid,
6973
this.url,
@@ -78,6 +82,7 @@ class Podcast {
7882
this.value = const <Value>[],
7983
this.block = const <Block>[],
8084
this.episodes = const <Episode>[],
85+
this.remoteItems = const <RemoteItem>[],
8186
});
8287

8388
/// This method takes a Url pointing to an RSS feed containing the Podcast details and episodes. You
@@ -167,6 +172,7 @@ class Podcast {
167172
static Podcast _loadFeed(RssFeed rssFeed, String url) {
168173
// Parse the episodes
169174
var episodes = <Episode>[];
175+
var remoteItems = <RemoteItem>[];
170176
var author = rssFeed.itunes!.author;
171177
var locked = Locked(
172178
locked: rssFeed.podcastIndex!.locked?.locked ?? false,
@@ -189,6 +195,19 @@ class Podcast {
189195
}
190196
}
191197

198+
if (rssFeed.podcastIndex!.remoteItem != null) {
199+
for (var r in rssFeed.podcastIndex!.remoteItem!) {
200+
if (r != null) {
201+
remoteItems.add(RemoteItem(
202+
feedGuid: r.feedGuid,
203+
itemGuid: r.itemGuid,
204+
feedUrl: r.feedUrl,
205+
medium: r.medium,
206+
));
207+
}
208+
}
209+
}
210+
192211
if (rssFeed.podcastIndex!.persons != null) {
193212
for (var p in rssFeed.podcastIndex!.persons!) {
194213
persons.add(Person(
@@ -253,6 +272,7 @@ class Podcast {
253272
block: block,
254273
value: value,
255274
episodes: episodes,
275+
remoteItems: remoteItems,
256276
);
257277
}
258278

lib/src/model/remote_item.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2019 Ben Hills and the project contributors. Use of this source
2+
// code is governed by a MIT license that can be found in the LICENSE file.
3+
4+
/// This class represents a PC2.0 [remote item](https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#remote-item)
5+
class RemoteItem {
6+
String feedGuid;
7+
String? itemGuid;
8+
String? feedUrl;
9+
String? medium;
10+
11+
RemoteItem({
12+
required this.feedGuid,
13+
this.itemGuid,
14+
this.feedUrl,
15+
this.medium,
16+
});
17+
}

pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: podcast_search
22
description: A library for searching for podcasts and parsing podcast RSS feeds. Supports iTunes and PodcastIndex directories, and newer features such as chapters and transcripts.
33

4-
version: 0.6.9
4+
version: 0.7.0
55
homepage: https://github.com/amugofjava/podcast_search
66

77
environment:
@@ -12,7 +12,7 @@ dependencies:
1212
convert: ^3.0.1
1313
crypto: ^3.0.1
1414
dio: ^5.4.3+1
15-
rss_dart: ^1.0.6
15+
rss_dart: ^1.0.7
1616
meta: ^1.15.0
1717

1818
dev_dependencies:

test/podcast_load_test.dart

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,46 @@ void main() {
6969
});
7070

7171
test('Load podcast with no block tags', () async {
72-
var podcast =
73-
await Podcast.loadFeedFile(file: 'test_resources/podcast-no-block.rss');
72+
var podcast = await Podcast.loadFeedFile(
73+
file: 'test_resources/podcast-no-block.rss');
7474

7575
expect(podcast.block.length, 0);
7676
});
7777
});
78+
79+
group('Remote item test', () {
80+
test('No remote items', () async {
81+
var podcast = await Podcast.loadFeedFile(
82+
file: 'test_resources/podcast-no-block.rss');
83+
84+
expect(podcast.remoteItems.length, 0);
85+
});
86+
87+
test('Load podcast 3 remote items', () async {
88+
var podcast = await Podcast.loadFeedFile(
89+
file: 'test_resources/podcast-remote-item.rss');
90+
91+
expect(podcast.remoteItems.length, 3);
92+
93+
var item1 = podcast.remoteItems[0];
94+
var item2 = podcast.remoteItems[1];
95+
var item3 = podcast.remoteItems[2];
96+
97+
expect(item1.feedGuid, '917393e3-1b1e-5cef-ace4-edaa54e1f810');
98+
expect(item1.itemGuid, null);
99+
expect(item1.feedUrl, null);
100+
expect(item1.medium, null);
101+
102+
expect(item2.feedGuid, '917393e3-1b1e-5cef-ace4-edaa54e1f811');
103+
expect(item2.itemGuid, 'asdf089j0-ep240-20230510');
104+
expect(item2.feedUrl, null);
105+
expect(item2.medium, null);
106+
107+
expect(item3.feedGuid, '917393e3-1b1e-5cef-ace4-edaa54e1f812');
108+
expect(item3.itemGuid, 'asdf089j0-ep240-20230511');
109+
expect(item3.feedUrl,
110+
'https://feeds.example.org/917393e3-1b1e-5cef-ace4-edaa54e1f811/rss.xml');
111+
expect(item3.medium, 'music');
112+
});
113+
});
78114
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/" xmlns:georss="http://www.georss.org/georss" xmlns:audioboom="https://audioboom.com/rss/1.0" version="2.0" xml:base="https://audioboom.com/">
3+
<channel>
4+
<title>Podcast Load Test 2</title>
5+
<description>Unit test podcast test 1</description>
6+
<link>https://nowhere.com/podcastsearchtest1</link>
7+
<pubDate>Thu, 24 Jun 2021 18:00:20 +0000</pubDate>
8+
<language>en</language>
9+
<image>
10+
<url>https://nowhere.com/podcastsearchtest1/image1.png</url>
11+
<title>Podcast Load Test 1</title>
12+
<link>https://nowhere.com/podcastsearchtest1</link>
13+
</image>
14+
<itunes:image href="https://nowhere.com/podcastsearchtest1/image1.png" />
15+
<itunes:category text="Comedy"><itunes:category text="Comedy Interviews" /></itunes:category>
16+
<itunes:category text="Society &amp; Culture"><itunes:category text="Relationships" /></itunes:category>
17+
<itunes:category text="TV &amp; Film"><itunes:category text="After Shows" /></itunes:category>
18+
<itunes:explicit>no</itunes:explicit>
19+
<itunes:summary>Unit test podcast test 1</itunes:summary>
20+
<itunes:author>Podcast Search Author</itunes:author>
21+
<itunes:owner>
22+
<itunes:name>Ben Hills</itunes:name>
23+
<itunes:email>[email protected]</itunes:email>
24+
</itunes:owner>
25+
<itunes:new-feed-url>podcast1.rss</itunes:new-feed-url>
26+
<itunes:type>episodic</itunes:type>
27+
<podcast:value type="lightning" method="keysend" suggested="0.00000005000">
28+
<podcast:valueRecipient name="channel recipient1" type="node" address="03ae9f91a0cb8ff43840e3c322c55341a19d8c1c3cea15a25cfc425ac60a34e14a" split="80"/>
29+
<podcast:valueRecipient name="channel recipient2" type="node" address="03ae9f91a0cb8ff43840e3c322c55341a19d8c1c3cea15a25cfc425ac60a34e14b" split="20"/>
30+
</podcast:value>
31+
32+
<podcast:remoteItem feedGuid="917393e3-1b1e-5cef-ace4-edaa54e1f810" />
33+
34+
<podcast:remoteItem
35+
feedGuid="917393e3-1b1e-5cef-ace4-edaa54e1f811"
36+
itemGuid="asdf089j0-ep240-20230510" />
37+
38+
<podcast:remoteItem
39+
feedGuid="917393e3-1b1e-5cef-ace4-edaa54e1f812"
40+
feedUrl="https://feeds.example.org/917393e3-1b1e-5cef-ace4-edaa54e1f811/rss.xml"
41+
itemGuid="asdf089j0-ep240-20230511"
42+
medium="music" />
43+
44+
<item>
45+
<title>Episode 001</title>
46+
<link>https://nowhere.com/podcastsearchtest1/podcast1</link>
47+
<enclosure url="https://nowhere.com/podcastsearchtest1/podcast1/episode001.mp3" length="0" type="audio/mpeg" />
48+
<itunes:duration>1200</itunes:duration>
49+
<itunes:explicit>yes</itunes:explicit>
50+
<itunes:episodeType>full</itunes:episodeType>
51+
<description><![CDATA[<div>Test of episode 001</div>]]></description>
52+
<itunes:summary>Episode summary 001</itunes:summary>
53+
<pubDate>Thu, 24 Jun 2021 18:00:00 +0000</pubDate>
54+
<guid isPermaLink="true"></guid>
55+
<itunes:author>Ben Hills</itunes:author>
56+
<dc:creator>Ben Hills</dc:creator>
57+
<itunes:keywords>Podcast, NowPlaying, Listen, Test</itunes:keywords>
58+
<media:keywords>Podcast, NowPlaying, Listen, Test</media:keywords>
59+
<media:rights status="userCreated" />
60+
</item>
61+
62+
<item>
63+
<title>Episode 002</title>
64+
<link>https://nowhere.com/podcastsearchtest1/podcast2</link>
65+
<enclosure url="https://nowhere.com/podcastsearchtest1/podcast1/episode002.mp3" length="0" type="audio/mpeg" />
66+
<itunes:duration>1200</itunes:duration>
67+
<itunes:explicit>no</itunes:explicit>
68+
<itunes:episodeType>full</itunes:episodeType>
69+
<description><![CDATA[<div>Test of episode 002</div>]]></description>
70+
<itunes:summary>Episode summary 002</itunes:summary>
71+
<guid isPermaLink="true"></guid>
72+
<itunes:author>Ben Hills</itunes:author>
73+
<dc:creator>Ben Hills</dc:creator>
74+
<itunes:keywords>Podcast, NowPlaying, Listen, Test</itunes:keywords>
75+
<media:keywords>Podcast, NowPlaying, Listen, Test</media:keywords>
76+
<media:rights status="userCreated" />
77+
</item>
78+
</channel>
79+
</rss>

0 commit comments

Comments
 (0)