Map Fever folders to feeds with feeds_groups content parsing

This commit is contained in:
Shinokuni 2021-12-27 15:59:31 +01:00
parent 64b6fb0b4d
commit 701c188cfa
7 changed files with 91 additions and 35 deletions

View File

@ -107,7 +107,7 @@ val apiModule = module {
single(named("feverMoshi")) { single(named("feverMoshi")) {
Moshi.Builder() Moshi.Builder()
.add(FeverFoldersAdapter()) .add(FeverFoldersAdapter())
.add(FeverFeedsAdapter()) .add(FeverFeeds::class.java, FeverFeedsAdapter())
.add(FeverItemsAdapter()) .add(FeverItemsAdapter())
.add(FeverFaviconsAdapter()) .add(FeverFaviconsAdapter())
.add(Boolean::class.java, FeverAPIAdapter()) .add(Boolean::class.java, FeverAPIAdapter())

View File

@ -1,6 +1,5 @@
package com.readrops.api.services.fever package com.readrops.api.services.fever
import com.readrops.api.services.SyncResult
import com.readrops.api.services.fever.adapters.FeverAPIAdapter import com.readrops.api.services.fever.adapters.FeverAPIAdapter
import com.readrops.api.utils.ApiUtils import com.readrops.api.utils.ApiUtils
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
@ -26,13 +25,14 @@ class FeverDataSource(private val service: FeverService) {
adapter.fromJson(response.source())!! adapter.fromJson(response.source())!!
} }
suspend fun sync(body: MultipartBody): SyncResult { suspend fun sync(body: MultipartBody): FeverSyncResult {
return SyncResult( return FeverSyncResult(
feeds = service.getFeeds(body), feverFeeds = service.getFeeds(body),
folders = service.getFolders(body), folders = service.getFolders(body),
items = service.getItems(body), items = service.getItems(body),
unreadIds = service.getUnreadItemsIds(body), unreadIds = service.getUnreadItemsIds(body),
starredIds = service.getStarredItemsIds(body), starredIds = service.getStarredItemsIds(body),
favicons = listOf(),
) )
} }
} }

View File

@ -1,6 +1,7 @@
package com.readrops.api.services.fever package com.readrops.api.services.fever
import com.readrops.api.services.fever.adapters.Favicon import com.readrops.api.services.fever.adapters.Favicon
import com.readrops.api.services.fever.adapters.FeverFeeds
import com.readrops.db.entities.Feed import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item import com.readrops.db.entities.Item
@ -16,7 +17,7 @@ interface FeverService {
suspend fun login(@Body body: MultipartBody): ResponseBody suspend fun login(@Body body: MultipartBody): ResponseBody
@POST("?feeds") @POST("?feeds")
suspend fun getFeeds(@Body body: MultipartBody): List<Feed> suspend fun getFeeds(@Body body: MultipartBody): FeverFeeds
@POST("?groups") @POST("?groups")
suspend fun getFolders(@Body body: MultipartBody): List<Folder> suspend fun getFolders(@Body body: MultipartBody): List<Folder>

View File

@ -0,0 +1,15 @@
package com.readrops.api.services.fever
import com.readrops.api.services.fever.adapters.Favicon
import com.readrops.api.services.fever.adapters.FeverFeeds
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
data class FeverSyncResult(
val feverFeeds: FeverFeeds,
val folders: List<Folder>,
val items: List<Item>,
val unreadIds: List<String>,
val starredIds: List<String>,
val favicons: List<Favicon>,
)

View File

@ -7,24 +7,28 @@ import com.readrops.api.utils.extensions.nextNullableString
import com.readrops.api.utils.extensions.skipField import com.readrops.api.utils.extensions.skipField
import com.readrops.api.utils.extensions.skipToEnd import com.readrops.api.utils.extensions.skipToEnd
import com.readrops.db.entities.Feed import com.readrops.db.entities.Feed
import com.squareup.moshi.FromJson import com.squareup.moshi.*
import com.squareup.moshi.JsonReader
import com.squareup.moshi.ToJson
class FeverFeedsAdapter { data class FeverFeeds(
val feeds: List<Feed>,
val feedsGroups: Map<Int, List<Int>>
)
@ToJson class FeverFeedsAdapter : JsonAdapter<FeverFeeds>() {
fun toJson(feeds: List<Feed>) = ""
override fun toJson(writer: JsonWriter, value: FeverFeeds?) {
// not useful here
}
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
@FromJson override fun fromJson(reader: JsonReader): FeverFeeds = with(reader) {
fun fromJson(reader: JsonReader): List<Feed> = with(reader) {
return try { return try {
val feeds = arrayListOf<Feed>() val feeds = arrayListOf<Feed>()
val feedsGroups = mutableMapOf<Int, List<Int>>()
beginObject() beginObject()
// skip basic fields (api_version, auth, last_refreshed...) // skip based fields (api_version, auth, last_refreshed...)
repeat(3) { repeat(3) {
skipField() skipField()
} }
@ -38,7 +42,7 @@ class FeverFeedsAdapter {
val feed = Feed() val feed = Feed()
while (hasNext()) { while (hasNext()) {
with(feed) { with(feed) {
when(selectName(NAMES)) { when (selectName(NAMES)) {
0 -> remoteId = nextInt().toString() 0 -> remoteId = nextInt().toString()
1 -> name = nextNonEmptyString() 1 -> name = nextNonEmptyString()
2 -> url = nextNonEmptyString() 2 -> url = nextNonEmptyString()
@ -53,10 +57,31 @@ class FeverFeedsAdapter {
} }
endArray() endArray()
skipToEnd()
nextName()
beginArray()
while (hasNext()) {
beginObject()
var folderId: Int? = null
val feedsIds = mutableListOf<Int>()
while (hasNext()) {
when (selectName(JsonReader.Options.of("group_id", "feed_ids"))) {
0 -> folderId = nextInt()
1 -> feedsIds += nextNonEmptyString().split(",").map { it.toInt() }
else -> skipValue()
}
}
folderId?.let { feedsGroups[it] = feedsIds }
endObject()
}
endArray()
endObject() endObject()
feeds FeverFeeds(feeds, feedsGroups)
} catch (e: Exception) { } catch (e: Exception) {
throw ParseException(e.message) throw ParseException(e.message)
} }

View File

@ -1,9 +1,7 @@
package com.readrops.api.services.fever.adapters package com.readrops.api.services.fever.adapters
import com.readrops.api.TestUtils import com.readrops.api.TestUtils
import com.readrops.db.entities.Feed
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import okio.Buffer import okio.Buffer
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -11,23 +9,28 @@ import kotlin.test.assertEquals
class FeverFeedsAdapterTest { class FeverFeedsAdapterTest {
val adapter = Moshi.Builder() val adapter = Moshi.Builder()
.add(FeverFeedsAdapter()) .add(FeverFeeds::class.java, FeverFeedsAdapter())
.build() .build()
.adapter<List<Feed>>(Types.newParameterizedType(List::class.java, Feed::class.java))!! .adapter(FeverFeeds::class.java)!!
@Test @Test
fun validFeedsTest() { fun validFeedsTest() {
val stream = TestUtils.loadResource("services/fever/feeds.json") val stream = TestUtils.loadResource("services/fever/feeds.json")
val feeds = adapter.fromJson(Buffer().readFrom(stream))!! val feverFeeds = adapter.fromJson(Buffer().readFrom(stream))!!
assertEquals(feeds.size, 1) assertEquals(feverFeeds.feeds.size, 1)
with(feeds[0]) { with(feverFeeds.feeds[0]) {
assertEquals(name, "xda-developers") assertEquals(name, "xda-developers")
assertEquals(url, "https://www.xda-developers.com/feed/") assertEquals(url, "https://www.xda-developers.com/feed/")
assertEquals(siteUrl, "https://www.xda-developers.com/") assertEquals(siteUrl, "https://www.xda-developers.com/")
assertEquals(remoteId, "32") assertEquals(remoteId, "32")
} }
with(feverFeeds.feedsGroups.entries.first()) {
assertEquals(key, 3)
assertEquals(value, listOf(5, 4))
}
} }
} }

View File

@ -3,13 +3,16 @@ package com.readrops.app.repositories
import android.content.Context import android.content.Context
import com.readrops.api.services.SyncType import com.readrops.api.services.SyncType
import com.readrops.api.services.fever.FeverDataSource import com.readrops.api.services.fever.FeverDataSource
import com.readrops.api.services.fever.adapters.FeverFeeds
import com.readrops.api.utils.ApiUtils import com.readrops.api.utils.ApiUtils
import com.readrops.app.addfeed.FeedInsertionResult import com.readrops.app.addfeed.FeedInsertionResult
import com.readrops.app.addfeed.ParsingResult import com.readrops.app.addfeed.ParsingResult
import com.readrops.app.utils.Utils
import com.readrops.db.Database import com.readrops.db.Database
import com.readrops.db.entities.Feed import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item import com.readrops.db.entities.Item
import com.readrops.db.entities.ItemState
import com.readrops.db.entities.account.Account import com.readrops.db.entities.account.Account
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Single import io.reactivex.Single
@ -60,7 +63,10 @@ class FeverRepository(
val syncResult = feverDataSource.sync(requestBody) val syncResult = feverDataSource.sync(requestBody)
insertFolders(syncResult.folders) insertFolders(syncResult.folders)
insertFeeds(syncResult.feeds) insertFeeds(syncResult.feverFeeds)
//insertItems(syncResult.items)
//insertItemsIds(syncResult.unreadIds!!, syncResult.starredIds!!.toMutableList())
} catch (e: Exception) { } catch (e: Exception) {
error(e.message!!) error(e.message!!)
} }
@ -76,7 +82,13 @@ class FeverRepository(
database.folderDao().foldersUpsert(folders, account) database.folderDao().foldersUpsert(folders, account)
} }
private fun insertFeeds(feeds: List<Feed>) { private fun insertFeeds(feverFeeds: FeverFeeds) = with(feverFeeds) {
for (feed in feeds) {
for ((folderId, feedsIds) in feedsGroups) {
if (feedsIds.contains(feed.remoteId!!.toInt())) feed.remoteFolderId = folderId.toString()
}
}
feeds.forEach { it.accountId = account.id } feeds.forEach { it.accountId = account.id }
database.feedDao().feedsUpsert(feeds, account) database.feedDao().feedsUpsert(feeds, account)
} }