Skip to content

Commit

Permalink
Filter podcast episodes when finding them by ID
Browse files Browse the repository at this point in the history
If a podcast feed contains an <item> node without a valid title or
enclosure URL but that has an ID which is the same as a later <item>
which is valid, the Podcast Provider will match the episode ID to the
first invalid node instead of the later valid one.

Add a test for this situation and then resolve the problem by applying
the same filtering when finding an episode by ID as when building the
list of available episodes.

Fixes #241.
  • Loading branch information
ribbons committed Aug 23, 2020
1 parent c979b2c commit d6758c1
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 16 deletions.
44 changes: 28 additions & 16 deletions Providers/PodcastProvider/Classes/PodcastProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,22 +185,7 @@ public override AvailableEpisodes GetAvailableEpisodes(string progExtId, Program
continue;
}

if (itemNode.SelectSingleNode("./title[text()]") == null)
{
continue;
}

var urlAttrib = itemNode.SelectSingleNode("./enclosure/@url") as XmlAttribute;

if (urlAttrib == null)
{
continue;
}

Uri uri;
Uri.TryCreate(urlAttrib.Value, UriKind.Absolute, out uri);

if (uri == null)
if (this.FilterItemNode(itemNode))
{
continue;
}
Expand Down Expand Up @@ -507,6 +492,11 @@ private XmlNode ItemNodeFromEpisodeID(XmlDocument rss, string episodeExtId)

foreach (XmlNode itemNode in itemNodes)
{
if (this.FilterItemNode(itemNode))
{
continue;
}

string itemId = this.ItemNodeToEpisodeID(itemNode);

if (itemId == episodeExtId)
Expand All @@ -518,6 +508,28 @@ private XmlNode ItemNodeFromEpisodeID(XmlDocument rss, string episodeExtId)
return null;
}

private bool FilterItemNode(XmlNode itemNode)
{
if (itemNode.SelectSingleNode("./title[text()]") == null)
{
return true;
}

if (!(itemNode.SelectSingleNode("./enclosure/@url") is XmlAttribute urlAttrib))
{
return true;
}

Uri.TryCreate(urlAttrib.Value, UriKind.Absolute, out Uri uri);

if (uri == null)
{
return true;
}

return false;
}

private CompressedImage FetchImage(XmlNode parent, string xpath, XmlNamespaceManager namespaceMgr)
{
var urlNode = parent.SelectSingleNode(xpath, namespaceMgr);
Expand Down
16 changes: 16 additions & 0 deletions Test/Providers/PodcastProvider/Classes/TestGetInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,21 @@ public void EpisodeFiltering()
Assert.Contains("nofilter-valid", available);
Assert.Contains("nofilter-enclosure-encoded-url", available);
}

/// <summary>
/// Test that correct podcast information can be retrieved for episodes
/// with the same id as a previous filtered episode.
/// </summary>
[Fact]
public void EpisodeSameIdAsFilteredInfo()
{
var instance = TestCommon.CreateInstance();
string extId = "http://example.com/EpisodeFiltering.xml";

var programme = instance.GetProgrammeInfo(extId);
var episode = instance.GetEpisodeInfo(extId, programme, "filter-nofilter-sameid");

Assert.Equal("NOT FILTERED", episode.Name);
}
}
}
29 changes: 29 additions & 0 deletions Test/Providers/PodcastProvider/TestData/EpisodeFiltering.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,34 @@
<guid isPermaLink="false">nofilter-enclosure-encoded-url</guid>
<enclosure url="http://example.com/redir/http%3A%2F%2Fexample.com%2Fepisode.mp3" length="12345" type="audio/mpeg" />
</item>

<item>
<guid isPermaLink="false">filter-nofilter-sameid</guid>
<enclosure url="http://example.com/" length="12345" type="audio/mpeg" />
</item>
<item>
<title></title>
<guid isPermaLink="false">filter-nofilter-sameid</guid>
<enclosure url="http://example.com/" length="12345" type="audio/mpeg" />
</item>
<item>
<title>FILTERED</title>
<guid isPermaLink="false">filter-nofilter-sameid</guid>
</item>
<item>
<title>FILTERED</title>
<guid isPermaLink="false">filter-nofilter-sameid</guid>
<enclosure />
</item>
<item>
<title>FILTERED</title>
<guid isPermaLink="false">filter-enclosure-invalid-url</guid>
<enclosure url="INVALID" />
</item>
<item>
<title>NOT FILTERED</title>
<guid isPermaLink="false">filter-nofilter-sameid</guid>
<enclosure url="http://example.com/" length="12345" type="audio/mpeg" />
</item>
</channel>
</rss>

0 comments on commit d6758c1

Please sign in to comment.