Skip to content

Commit 213d01d

Browse files
committed
Improve support of media namespace for RSS and ATOM feeds
* improve Youtube support * improve ATOM date handling
1 parent 42cc2ec commit 213d01d

File tree

6 files changed

+101
-31
lines changed

6 files changed

+101
-31
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.readrops.api.localfeed
2+
3+
import com.gitlab.mvysny.konsumexml.Konsumer
4+
import com.gitlab.mvysny.konsumexml.Names
5+
import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
6+
import com.readrops.api.utils.extensions.nullableTextRecursively
7+
import com.readrops.db.entities.Item
8+
9+
object RSSMedia {
10+
11+
fun parseMediaContent(konsumer: Konsumer, item: Item) = with(konsumer) {
12+
val url = attributes.getValueOrNull("url")
13+
14+
if (url != null && isUrlImage(url) && item.imageLink == null) {
15+
item.imageLink = url
16+
}
17+
18+
konsumer.skipContents() // ignore media content sub elements
19+
}
20+
21+
fun parseMediaGroup(konsumer: Konsumer, item: Item) = with(konsumer) {
22+
allChildrenAutoIgnore(Names.of("content", "thumbnail", "description")) {
23+
when (tagName) {
24+
"media:content" -> parseMediaContent(this, item)
25+
"media:thumbnail"-> parseMediaContent(this, item)
26+
"media:description" -> {
27+
// Youtube case, might be useful for others
28+
val description = nullableTextRecursively()
29+
if (item.text == null) {
30+
item.content = description
31+
}
32+
}
33+
else -> skipContents()
34+
}
35+
}
36+
}
37+
38+
private fun isUrlImage(url: String): Boolean = with(url) {
39+
return endsWith(".jpg") || endsWith(".jpeg") || endsWith(".png")
40+
}
41+
}

api/src/main/java/com/readrops/api/localfeed/atom/ATOMItemAdapter.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.readrops.api.localfeed.atom
33
import com.gitlab.mvysny.konsumexml.Konsumer
44
import com.gitlab.mvysny.konsumexml.Names
55
import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
6+
import com.readrops.api.localfeed.RSSMedia
67
import com.readrops.api.localfeed.XmlAdapter
78
import com.readrops.api.utils.exceptions.ParseException
89
import com.readrops.api.utils.extensions.nonNullText
@@ -23,11 +24,18 @@ class ATOMItemAdapter : XmlAdapter<Item> {
2324
when (tagName) {
2425
"title" -> title = nonNullText()
2526
"id" -> remoteId = nullableText()
26-
"updated" -> pubDate = DateUtils.parse(nullableText())
27+
"published" -> pubDate = DateUtils.parse(nullableText())
28+
"updated" -> {
29+
val updated = nullableText()
30+
if (pubDate == null) {
31+
pubDate = DateUtils.parse(updated)
32+
}
33+
}
2734
"link" -> parseLink(this, this@apply)
2835
"author" -> allChildrenAutoIgnore("name") { author = nullableText() }
2936
"summary" -> description = nullableTextRecursively()
3037
"content" -> content = nullableTextRecursively()
38+
"media:group" -> RSSMedia.parseMediaGroup(this, item)
3139
else -> skipContents()
3240
}
3341
}
@@ -57,6 +65,7 @@ class ATOMItemAdapter : XmlAdapter<Item> {
5765
}
5866

5967
companion object {
60-
val names = Names.of("title", "id", "updated", "link", "author", "summary", "content")
68+
val names = Names.of("title", "id", "updated", "link", "author", "summary",
69+
"content", "group", "published")
6170
}
6271
}

api/src/main/java/com/readrops/api/localfeed/rss2/RSS2ItemAdapter.kt

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.gitlab.mvysny.konsumexml.Konsumer
44
import com.gitlab.mvysny.konsumexml.KonsumerException
55
import com.gitlab.mvysny.konsumexml.Names
66
import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
7+
import com.readrops.api.localfeed.RSSMedia
78
import com.readrops.api.localfeed.XmlAdapter
89
import com.readrops.api.localfeed.XmlAdapter.Companion.AUTHORS_MAX
910
import com.readrops.api.utils.ApiUtils
@@ -35,9 +36,9 @@ class RSS2ItemAdapter : XmlAdapter<Item> {
3536
"guid" -> remoteId = nullableText()
3637
"description" -> description = nullableTextRecursively()
3738
"content:encoded" -> content = nullableTextRecursively()
38-
"enclosure" -> parseMediaContent(this, item = this@apply)
39-
"media:content" -> parseMediaContent(this, item = this@apply)
40-
"media:group" -> parseMediaGroup(this, item = this@apply)
39+
"enclosure" -> RSSMedia.parseMediaContent(this, item = this@apply)
40+
"media:content" -> RSSMedia.parseMediaContent(this, item = this@apply)
41+
"media:group" -> RSSMedia.parseMediaGroup(this, item = this@apply)
4142
else -> skipContents() // for example media:description
4243
}
4344
}
@@ -50,29 +51,6 @@ class RSS2ItemAdapter : XmlAdapter<Item> {
5051
}
5152
}
5253

53-
private fun isUrlImage(url: String): Boolean = with(url) {
54-
return endsWith(".jpg") || endsWith(".jpeg") || endsWith(".png")
55-
}
56-
57-
private fun parseMediaContent(konsumer: Konsumer, item: Item) = with(konsumer) {
58-
val url = attributes.getValueOrNull("url")
59-
60-
if (url != null && isUrlImage(url) && item.imageLink == null) {
61-
item.imageLink = url
62-
}
63-
64-
konsumer.skipContents() // ignore media content sub elements
65-
}
66-
67-
private fun parseMediaGroup(konsumer: Konsumer, item: Item) = with(konsumer) {
68-
allChildrenAutoIgnore("content") {
69-
when (tagName) {
70-
"media:content" -> parseMediaContent(this, item)
71-
else -> skipContents()
72-
}
73-
}
74-
}
75-
7654
private fun finalizeItem(item: Item, creators: List<String?>) = with(item) {
7755
validateItem(this)
7856

api/src/test/java/com/readrops/api/localfeed/atom/ATOMAdapterTest.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.readrops.api.localfeed.atom
33
import com.gitlab.mvysny.konsumexml.konsumeXml
44
import com.readrops.api.TestUtils
55
import com.readrops.api.utils.exceptions.ParseException
6-
import com.readrops.db.util.DateUtils
76
import junit.framework.TestCase
87
import junit.framework.TestCase.assertEquals
98
import org.junit.Assert.assertThrows
@@ -30,11 +29,11 @@ class ATOMAdapterTest {
3029
assertEquals(imageUrl, "https://github.com/readrops/Readrops/blob/develop/images/readrops_logo.png")
3130
}
3231

33-
with(items[0]) {
32+
with(items.first()) {
3433
assertEquals(items.size, 4)
3534
assertEquals(title, "Add an option to open item url in custom tab")
3635
assertEquals(link, "https://github.com/readrops/Readrops/commit/c15f093a1bc4211e85f8d1817c9073e307afe5ac")
37-
assertEquals(pubDate, DateUtils.parse("2020-09-06T21:09:59Z"))
36+
assertEquals(pubDate!!.year, 2019)
3837
assertEquals(author, "Shinokuni")
3938
assertEquals(description, "Summary")
4039
assertEquals(remoteId, "tag:github.com,2008:Grit::Commit/c15f093a1bc4211e85f8d1817c9073e307afe5ac")
@@ -71,4 +70,15 @@ class ATOMAdapterTest {
7170

7271
assertTrue(exception.message!!.contains("Item link is required"))
7372
}
73+
74+
@Test
75+
fun mediaGroupTest() {
76+
val stream = TestUtils.loadResource("localfeed/atom/atom_item_media_group.xml")
77+
val pair = adapter.fromXml(stream.konsumeXml())
78+
79+
with(pair.second.first()) {
80+
assertEquals("description", text)
81+
assertEquals("https://i3.ytimg.com/vi/.../hqdefault.jpg", imageLink)
82+
}
83+
}
7484
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xml:lang="en-US">
3+
<id>tag:github.com,2008:/readrops/Readrops/commits/develop</id>
4+
<link type="text/html" rel="alternate" href="https://github.com/readrops/Readrops/commits/develop"/>
5+
<link type="application/atom+xml" rel="self" href="https://github.com/readrops/Readrops/commits/develop.atom"/>
6+
<title>Recent Commits to Readrops:develop</title>
7+
<updated>2020-09-06T21:09:59Z</updated>
8+
<subtitle>Here is a subtitle</subtitle>
9+
<logo>https://github.com/readrops/Readrops/blob/develop/images/readrops_logo.png</logo>
10+
<entry>
11+
<id>tag:github.com,2008:Grit::Commit/c15f093a1bc4211e85f8d1817c9073e307afe5ac</id>
12+
<link type="text/html" rel="alternate" href="https://github.com/readrops/Readrops/commit/c15f093a1bc4211e85f8d1817c9073e307afe5ac"/>
13+
<title>Add an option to open item url in custom tab</title>
14+
<updated>2020-09-06T21:09:59Z</updated>
15+
<media:thumbnail height="30" width="30" url="https://avatars2.githubusercontent.com/u/18555673?s=30&amp;u=c56b216e8d128d0ec217062feeace9faca4dc893&amp;v=4"/>
16+
<author>
17+
<name>Shinokuni</name>
18+
<uri>https://github.com/Shinokuni</uri>
19+
</author>
20+
<media:group>
21+
<media:title>media title</media:title>
22+
<media:content url="https://www.youtube.com/v/...?version=3" type="application/x-shockwave-flash" width="640" height="390"/>
23+
<media:thumbnail url="https://i3.ytimg.com/vi/.../hqdefault.jpg" width="480" height="360"/>
24+
<media:description>description</media:description>
25+
<media:community>
26+
<media:starRating count="947923" average="5.00" min="1" max="5"/>
27+
<media:statistics views="10761364"/>
28+
</media:community>
29+
</media:group>
30+
</entry>
31+
</feed>

api/src/test/resources/localfeed/atom/atom_items.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<id>tag:github.com,2008:Grit::Commit/c15f093a1bc4211e85f8d1817c9073e307afe5ac</id>
1212
<link type="text/html" rel="alternate" href="https://github.com/readrops/Readrops/commit/c15f093a1bc4211e85f8d1817c9073e307afe5ac"/>
1313
<title>Add an option to open item url in custom tab</title>
14+
<published>2019-09-06T21:09:59Z</published>
1415
<updated>2020-09-06T21:09:59Z</updated>
1516
<media:thumbnail height="30" width="30" url="https://avatars2.githubusercontent.com/u/18555673?s=30&amp;u=c56b216e8d128d0ec217062feeace9faca4dc893&amp;v=4"/>
1617
<author>

0 commit comments

Comments
 (0)