Skip to content

Commit 35d3b31

Browse files
committed
Improve Fever adapters reliability (fixes #229 and should also fix #228)
1 parent 383aea0 commit 35d3b31

11 files changed

+169
-168
lines changed

api/src/main/java/com/readrops/api/services/fever/adapters/FeverAPIAdapter.kt

+7-13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package com.readrops.api.services.fever.adapters
22

33
import com.readrops.api.utils.exceptions.ParseException
4-
import com.readrops.api.utils.extensions.skipField
54
import com.readrops.api.utils.extensions.toBoolean
65
import com.squareup.moshi.FromJson
76
import com.squareup.moshi.JsonAdapter
87
import com.squareup.moshi.JsonReader
9-
import com.squareup.moshi.JsonReader.Token
108
import com.squareup.moshi.JsonWriter
119
import com.squareup.moshi.ToJson
1210

@@ -21,21 +19,17 @@ class FeverAPIAdapter : JsonAdapter<Boolean>() {
2119
override fun fromJson(reader: JsonReader): Boolean = with(reader) {
2220
return try {
2321
beginObject()
24-
skipField()
2522

26-
var authenticated = 0
27-
if (nextName() == "auth") {
28-
authenticated = nextInt()
29-
} else {
30-
skipValue()
31-
}
32-
33-
while (peek() == Token.NAME) {
34-
skipField()
23+
var authenticated = false
24+
while (hasNext()) {
25+
when (nextName()) {
26+
"auth" -> authenticated = nextInt().toBoolean()
27+
else -> skipValue()
28+
}
3529
}
3630

3731
endObject()
38-
authenticated.toBoolean()
32+
authenticated
3933
} catch (e: Exception) {
4034
throw ParseException(e.message)
4135
}

api/src/main/java/com/readrops/api/services/fever/adapters/FeverFaviconsAdapter.kt

+34-29
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.readrops.api.services.fever.adapters
22

33
import android.annotation.SuppressLint
44
import com.readrops.api.utils.exceptions.ParseException
5-
import com.readrops.api.utils.extensions.skipField
65
import com.squareup.moshi.FromJson
76
import com.squareup.moshi.JsonReader
87
import com.squareup.moshi.ToJson
@@ -19,55 +18,61 @@ class FeverFaviconsAdapter {
1918
@ToJson
2019
fun toJson(favicons: List<Favicon>) = ""
2120

22-
@OptIn(ExperimentalEncodingApi::class)
2321
@SuppressLint("CheckResult")
2422
@FromJson
2523
fun fromJson(reader: JsonReader): List<Favicon> = with(reader) {
2624
return try {
2725
val favicons = arrayListOf<Favicon>()
2826

2927
beginObject()
30-
31-
repeat(3) {
32-
skipField()
33-
}
34-
35-
nextName() // beginning of favicon array
36-
beginArray()
37-
3828
while (hasNext()) {
39-
beginObject()
29+
when (nextName()) {
30+
"favicons" -> {
31+
beginArray()
4032

41-
var id = 0
42-
var data: ByteArray? = null
33+
while (hasNext()) {
34+
beginObject()
35+
parseFavicon(reader)?.let { favicons += it }
4336

44-
while (hasNext()) {
45-
when (selectName(NAMES)) {
46-
0 -> id = nextInt()
47-
1 -> data = Base64.decode(nextString().substringAfter("base64,"))
48-
else -> skipValue()
49-
}
50-
}
37+
endObject()
38+
}
5139

52-
if (id > 0 && data != null) {
53-
favicons += Favicon(
54-
id = id,
55-
data = data,
56-
)
40+
endArray()
41+
}
42+
else -> skipValue()
5743
}
58-
59-
endObject()
6044
}
6145

62-
endArray()
6346
endObject()
64-
6547
favicons
6648
} catch (e: Exception) {
6749
throw ParseException(e.message)
6850
}
6951
}
7052

53+
@OptIn(ExperimentalEncodingApi::class)
54+
private fun parseFavicon(reader: JsonReader): Favicon? = with(reader) {
55+
var id = 0
56+
var data: ByteArray? = null
57+
58+
while (hasNext()) {
59+
when (selectName(NAMES)) {
60+
0 -> id = nextInt()
61+
1 -> data = Base64.decode(nextString().substringAfter("base64,"))
62+
else -> skipValue()
63+
}
64+
}
65+
66+
if (id > 0 && data != null) {
67+
return Favicon(
68+
id = id,
69+
data = data,
70+
)
71+
} else {
72+
null
73+
}
74+
}
75+
7176
companion object {
7277
val NAMES: JsonReader.Options = JsonReader.Options.of("id", "data")
7378
}

api/src/main/java/com/readrops/api/services/fever/adapters/FeverFeedsAdapter.kt

+53-50
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
44
import com.readrops.api.utils.exceptions.ParseException
55
import com.readrops.api.utils.extensions.nextNonEmptyString
66
import com.readrops.api.utils.extensions.nextNullableString
7-
import com.readrops.api.utils.extensions.skipField
87
import com.readrops.db.entities.Feed
98
import com.squareup.moshi.JsonAdapter
109
import com.squareup.moshi.JsonReader
@@ -30,63 +29,34 @@ class FeverFeedsAdapter : JsonAdapter<FeverFeeds>() {
3029
val feedsGroups = mutableMapOf<Int, List<Int>>()
3130

3231
beginObject()
33-
34-
while (nextName() != "feeds") {
35-
skipValue()
36-
}
37-
38-
// feeds array
39-
beginArray()
4032
while (hasNext()) {
41-
beginObject()
42-
43-
val feed = Feed()
44-
while (hasNext()) {
45-
with(feed) {
46-
when (selectName(NAMES)) {
47-
0 -> remoteId = nextInt().toString()
48-
1 -> favicons[nextInt()] = remoteId!!
49-
2 -> name = nextNonEmptyString()
50-
3 -> url = nextNonEmptyString()
51-
4 -> siteUrl = nextNullableString()
52-
else -> skipValue()
33+
when (nextName()) {
34+
"feeds" -> {
35+
beginArray()
36+
while (hasNext()) {
37+
beginObject()
38+
feeds += parseFeed(reader, favicons)
39+
40+
endObject()
5341
}
54-
}
55-
}
5642

57-
feeds += feed
58-
endObject()
59-
}
43+
endArray()
44+
}
45+
"feeds_groups" -> {
46+
beginArray()
47+
while (hasNext()) {
48+
beginObject()
6049

61-
endArray()
50+
val (folderId, feedsIds) = parseFeedsGroups(reader)
51+
folderId?.let { feedsGroups[it] = feedsIds }
6252

63-
while (nextName() != "feeds_groups") {
64-
skipValue()
65-
}
53+
endObject()
54+
}
6655

67-
// feeds_groups array
68-
beginArray()
69-
while (hasNext()) {
70-
beginObject()
71-
72-
var folderId: Int? = null
73-
val feedsIds = mutableListOf<Int>()
74-
while (hasNext()) {
75-
when (selectName(JsonReader.Options.of("group_id", "feed_ids"))) {
76-
0 -> folderId = nextInt()
77-
1 -> feedsIds += nextNonEmptyString().split(",").map { it.toInt() }
78-
else -> skipValue()
56+
endArray()
7957
}
58+
else -> skipValue()
8059
}
81-
82-
folderId?.let { feedsGroups[it] = feedsIds }
83-
endObject()
84-
}
85-
86-
endArray()
87-
88-
while (peek() != JsonReader.Token.END_OBJECT) {
89-
skipField()
9060
}
9161

9262
endObject()
@@ -101,6 +71,39 @@ class FeverFeedsAdapter : JsonAdapter<FeverFeeds>() {
10171
}
10272
}
10373

74+
private fun parseFeed(reader: JsonReader, favicons: MutableMap<Int, String>): Feed = with(reader) {
75+
val feed = Feed()
76+
while (hasNext()) {
77+
with(feed) {
78+
when (selectName(NAMES)) {
79+
0 -> remoteId = nextInt().toString()
80+
1 -> favicons[nextInt()] = remoteId!!
81+
2 -> name = nextNonEmptyString()
82+
3 -> url = nextNonEmptyString()
83+
4 -> siteUrl = nextNullableString()
84+
else -> skipValue()
85+
}
86+
}
87+
}
88+
89+
return feed
90+
}
91+
92+
private fun parseFeedsGroups(reader: JsonReader): Pair<Int?, List<Int>> = with(reader) {
93+
var folderId: Int? = null
94+
val feedsIds = mutableListOf<Int>()
95+
96+
while (hasNext()) {
97+
when (selectName(JsonReader.Options.of("group_id", "feed_ids"))) {
98+
0 -> folderId = nextInt()
99+
1 -> feedsIds += nextNonEmptyString().split(",").map { it.toInt() }
100+
else -> skipValue()
101+
}
102+
}
103+
104+
folderId to feedsIds
105+
}
106+
104107
companion object {
105108
val NAMES: JsonReader.Options =
106109
JsonReader.Options.of("id", "favicon_id", "title", "url", "site_url")

api/src/main/java/com/readrops/api/services/fever/adapters/FeverFoldersAdapter.kt

+22-24
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package com.readrops.api.services.fever.adapters
33
import android.annotation.SuppressLint
44
import com.readrops.api.utils.exceptions.ParseException
55
import com.readrops.api.utils.extensions.nextNonEmptyString
6-
import com.readrops.api.utils.extensions.skipField
7-
import com.readrops.api.utils.extensions.skipToEnd
86
import com.readrops.db.entities.Folder
97
import com.squareup.moshi.FromJson
108
import com.squareup.moshi.JsonReader
@@ -22,35 +20,35 @@ class FeverFoldersAdapter {
2220
val folders = arrayListOf<Folder>()
2321

2422
beginObject()
25-
26-
repeat(3) {
27-
skipField()
28-
}
29-
30-
nextName() // beginning of folders array
31-
beginArray()
32-
3323
while (hasNext()) {
34-
beginObject()
35-
36-
val folder = Folder()
37-
while (hasNext()) {
38-
with(folder) {
39-
when (selectName(NAMES)) {
40-
0 -> remoteId = nextInt().toString()
41-
1 -> name = nextNonEmptyString()
24+
when (nextName()) {
25+
"groups" -> {
26+
beginArray()
27+
28+
while (hasNext()) {
29+
beginObject()
30+
31+
val folder = Folder()
32+
while (hasNext()) {
33+
with(folder) {
34+
when (selectName(NAMES)) {
35+
0 -> remoteId = nextInt().toString()
36+
1 -> name = nextNonEmptyString()
37+
}
38+
}
39+
}
40+
41+
folders += folder
42+
endObject()
4243
}
44+
45+
endArray()
4346
}
47+
else -> skipValue()
4448
}
45-
46-
folders += folder
47-
endObject()
4849
}
4950

50-
endArray()
51-
skipToEnd()
5251
endObject()
53-
5452
folders
5553
} catch (e: Exception) {
5654
throw ParseException(e.message)

0 commit comments

Comments
 (0)