Some Nextcloud News item fields can be null

This commit is contained in:
Shinokuni 2024-11-19 18:14:57 +01:00
parent 49ab7d5a04
commit a7416db1b7
6 changed files with 71 additions and 20 deletions

View File

@ -3,13 +3,14 @@ package com.readrops.api.services.nextcloudnews.adapters
import android.annotation.SuppressLint import android.annotation.SuppressLint
import com.readrops.api.utils.ApiUtils import com.readrops.api.utils.ApiUtils
import com.readrops.api.utils.exceptions.ParseException import com.readrops.api.utils.exceptions.ParseException
import com.readrops.api.utils.extensions.nextNonEmptyString import com.readrops.api.utils.extensions.nextNullableLong
import com.readrops.api.utils.extensions.nextNullableString import com.readrops.api.utils.extensions.nextNullableString
import com.readrops.db.entities.Item import com.readrops.db.entities.Item
import com.readrops.db.util.DateUtils import com.readrops.db.util.DateUtils
import com.squareup.moshi.JsonAdapter import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter import com.squareup.moshi.JsonWriter
import java.time.LocalDateTime
class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() { class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() {
@ -39,9 +40,18 @@ class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() {
when (reader.selectName(NAMES)) { when (reader.selectName(NAMES)) {
0 -> remoteId = reader.nextInt().toString() 0 -> remoteId = reader.nextInt().toString()
1 -> link = reader.nextNullableString() 1 -> link = reader.nextNullableString()
2 -> title = reader.nextNonEmptyString() 2 -> title = reader.nextNullableString()
3 -> author = reader.nextNullableString() 3 -> author = reader.nextNullableString()
4 -> pubDate = DateUtils.fromEpochSeconds(reader.nextLong()) 4 -> {
val value = reader.nextNullableLong()
pubDate = if (value != null) {
DateUtils.fromEpochSeconds(value)
} else {
LocalDateTime.now()
}
}
5 -> content = reader.nextNullableString() 5 -> content = reader.nextNullableString()
6 -> enclosureMime = reader.nextNullableString() 6 -> enclosureMime = reader.nextNullableString()
7 -> enclosureLink = reader.nextNullableString() 7 -> enclosureLink = reader.nextNullableString()
@ -53,10 +63,14 @@ class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() {
} }
} }
if (enclosureMime != null && ApiUtils.isMimeImage(enclosureMime!!)) if (enclosureMime != null && ApiUtils.isMimeImage(enclosureMime!!)) {
item.imageLink = enclosureLink item.imageLink = enclosureLink
}
if (item.title != null) {
items += item
}
items += item
reader.endObject() reader.endObject()
} }
@ -70,7 +84,9 @@ class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() {
} }
companion object { companion object {
val NAMES: JsonReader.Options = JsonReader.Options.of("id", "url", "title", "author", val NAMES: JsonReader.Options = JsonReader.Options.of(
"pubDate", "body", "enclosureMime", "enclosureLink", "feedId", "unread", "starred") "id", "url", "title", "author",
"pubDate", "body", "enclosureMime", "enclosureLink", "feedId", "unread", "starred"
)
} }
} }

View File

@ -14,6 +14,9 @@ fun JsonReader.nextNonEmptyString(): String {
fun JsonReader.nextNullableInt(): Int? = fun JsonReader.nextNullableInt(): Int? =
if (peek() != JsonReader.Token.NULL) nextInt() else nextNull() if (peek() != JsonReader.Token.NULL) nextInt() else nextNull()
fun JsonReader.nextNullableLong(): Long? =
if (peek() != JsonReader.Token.NULL) nextLong() else nextNull()
fun JsonReader.skipField() { fun JsonReader.skipField() {
skipName() skipName()
skipValue() skipValue()

View File

@ -107,7 +107,7 @@ class NextcloudNewsDataSourceTest : KoinTest {
) )
val request = mockServer.takeRequest() val request = mockServer.takeRequest()
assertTrue { items.size == 3 } assertTrue { items.size == 2 }
with(request.requestUrl!!) { with(request.requestUrl!!) {
assertEquals("$type", queryParameter("type")) assertEquals("$type", queryParameter("type"))
assertEquals("false", queryParameter("getRead")) assertEquals("false", queryParameter("getRead"))
@ -124,7 +124,7 @@ class NextcloudNewsDataSourceTest : KoinTest {
nextcloudNewsDataSource.getNewItems(1512, NextcloudNewsDataSource.ItemQueryType.ALL) nextcloudNewsDataSource.getNewItems(1512, NextcloudNewsDataSource.ItemQueryType.ALL)
val request = mockServer.takeRequest() val request = mockServer.takeRequest()
assertTrue { items.size == 3 } assertTrue { items.size == 2 }
with(request.requestUrl!!) { with(request.requestUrl!!) {
assertEquals("1512", queryParameter("lastModified")) assertEquals("1512", queryParameter("lastModified"))
assertEquals("3", queryParameter("type")) assertEquals("3", queryParameter("type"))
@ -323,8 +323,8 @@ class NextcloudNewsDataSourceTest : KoinTest {
with(result) { with(result) {
assertEquals(1, folders.size) assertEquals(1, folders.size)
assertEquals(3, feeds.size) assertEquals(3, feeds.size)
assertEquals(3, items.size) assertEquals(2, items.size)
assertEquals(3, starredItems.size) assertEquals(2, starredItems.size)
} }
} }
@ -383,7 +383,7 @@ class NextcloudNewsDataSourceTest : KoinTest {
assertEquals(4, setItemState) assertEquals(4, setItemState)
assertEquals(1, folders.size) assertEquals(1, folders.size)
assertEquals(3, feeds.size) assertEquals(3, feeds.size)
assertEquals(3, items.size) assertEquals(2, items.size)
} }
} }
} }

View File

@ -21,7 +21,9 @@ class NextcloudNewsItemsAdapterTest {
val stream = TestUtils.loadResource("services/nextcloudnews/adapters/items.json") val stream = TestUtils.loadResource("services/nextcloudnews/adapters/items.json")
val items = adapter.fromJson(Buffer().readFrom(stream))!! val items = adapter.fromJson(Buffer().readFrom(stream))!!
val item = items[0] val item = items.first()
assertEquals(2, items.size)
with(item) { with(item) {
assertEquals(remoteId, "3443") assertEquals(remoteId, "3443")
@ -33,11 +35,11 @@ class NextcloudNewsItemsAdapterTest {
assertEquals(isRead, false) assertEquals(isRead, false)
assertEquals(isStarred, false) assertEquals(isStarred, false)
assertEquals(pubDate, DateUtils.fromEpochSeconds(1367270544)) assertEquals(pubDate, DateUtils.fromEpochSeconds(1367270544))
assertEquals(imageLink, null) assertEquals(imageLink, "https://test.org/image.jpg")
} }
with(items[1]) { with(items[1]) {
assertEquals(imageLink, "https://test.org/image.jpg") assertEquals(imageLink, null)
} }
} }

View File

@ -2,6 +2,7 @@ package com.readrops.api.utils
import com.readrops.api.utils.exceptions.ParseException import com.readrops.api.utils.exceptions.ParseException
import com.readrops.api.utils.extensions.nextNonEmptyString import com.readrops.api.utils.extensions.nextNonEmptyString
import com.readrops.api.utils.extensions.nextNullableLong
import com.readrops.api.utils.extensions.nextNullableString import com.readrops.api.utils.extensions.nextNullableString
import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonReader
import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertEquals
@ -85,4 +86,33 @@ class JsonReaderExtensionsTest {
reader.nextNonEmptyString() reader.nextNonEmptyString()
} }
@Test
fun nextNullableLongNormalCaseTest() {
val reader = JsonReader.of(Buffer().readFrom("""
{
"field": "5555555555555555555"
}
""".trimIndent().byteInputStream()))
reader.beginObject()
reader.nextName()
assertEquals(5555555555555555555L, reader.nextNullableLong())
reader.endObject()
}
@Test
fun nextNullableLongNullCaseTest() {
val reader = JsonReader.of(Buffer().readFrom("""
{
"field": null
}
""".trimIndent().byteInputStream()))
reader.beginObject()
reader.nextName()
assertNull(reader.nextNullableLong())
reader.endObject()
}
} }

View File

@ -9,8 +9,8 @@
"author": "Jan Grulich (grulja)", "author": "Jan Grulich (grulja)",
"pubDate": 1367270544, "pubDate": 1367270544,
"body": "<p>At first I have to say...</p>", "body": "<p>At first I have to say...</p>",
"enclosureMime": null, "enclosureMime": "image",
"enclosureLink": null, "enclosureLink": "https://test.org/image.jpg",
"mediaThumbnail": null, "mediaThumbnail": null,
"mediaDescription": null, "mediaDescription": null,
"feedId": 67, "feedId": 67,
@ -25,12 +25,12 @@
"guid": "http://grulja.wordpress.com/?p=76", "guid": "http://grulja.wordpress.com/?p=76",
"guidHash": "3059047a572cd9cd5d0bf645faffd077", "guidHash": "3059047a572cd9cd5d0bf645faffd077",
"url": "http://grulja.wordpress.com/2013/04/29/plasma-nm-after-the-solid-sprint/", "url": "http://grulja.wordpress.com/2013/04/29/plasma-nm-after-the-solid-sprint/",
"title": "Plasma-nm after the solid sprint", "title": "",
"author": "Jan Grulich (grulja)", "author": "Jan Grulich (grulja)",
"pubDate": 1367270544, "pubDate": 1367270544,
"body": "<p>At first I have to say...</p>", "body": "<p>At first I have to say...</p>",
"enclosureMime": "image", "enclosureMime": null,
"enclosureLink": "https://test.org/image.jpg", "enclosureLink": null,
"mediaThumbnail": null, "mediaThumbnail": null,
"mediaDescription": null, "mediaDescription": null,
"feedId": 67, "feedId": 67,