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")) {
Moshi.Builder()
.add(FeverFoldersAdapter())
.add(FeverFeedsAdapter())
.add(FeverFeeds::class.java, FeverFeedsAdapter())
.add(FeverItemsAdapter())
.add(FeverFaviconsAdapter())
.add(Boolean::class.java, FeverAPIAdapter())

View File

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

View File

@ -1,6 +1,7 @@
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.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
@ -16,7 +17,7 @@ interface FeverService {
suspend fun login(@Body body: MultipartBody): ResponseBody
@POST("?feeds")
suspend fun getFeeds(@Body body: MultipartBody): List<Feed>
suspend fun getFeeds(@Body body: MultipartBody): FeverFeeds
@POST("?groups")
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.skipToEnd
import com.readrops.db.entities.Feed
import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonReader
import com.squareup.moshi.ToJson
import com.squareup.moshi.*
class FeverFeedsAdapter {
data class FeverFeeds(
val feeds: List<Feed>,
val feedsGroups: Map<Int, List<Int>>
)
@ToJson
fun toJson(feeds: List<Feed>) = ""
class FeverFeedsAdapter : JsonAdapter<FeverFeeds>() {
override fun toJson(writer: JsonWriter, value: FeverFeeds?) {
// not useful here
}
@SuppressLint("CheckResult")
@FromJson
fun fromJson(reader: JsonReader): List<Feed> = with(reader) {
override fun fromJson(reader: JsonReader): FeverFeeds = with(reader) {
return try {
val feeds = arrayListOf<Feed>()
val feedsGroups = mutableMapOf<Int, List<Int>>()
beginObject()
// skip basic fields (api_version, auth, last_refreshed...)
// skip based fields (api_version, auth, last_refreshed...)
repeat(3) {
skipField()
}
@ -38,7 +42,7 @@ class FeverFeedsAdapter {
val feed = Feed()
while (hasNext()) {
with(feed) {
when(selectName(NAMES)) {
when (selectName(NAMES)) {
0 -> remoteId = nextInt().toString()
1 -> name = nextNonEmptyString()
2 -> url = nextNonEmptyString()
@ -53,10 +57,31 @@ class FeverFeedsAdapter {
}
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()
feeds
FeverFeeds(feeds, feedsGroups)
} catch (e: Exception) {
throw ParseException(e.message)
}

View File

@ -1,9 +1,7 @@
package com.readrops.api.services.fever.adapters
import com.readrops.api.TestUtils
import com.readrops.db.entities.Feed
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import okio.Buffer
import org.junit.Test
import kotlin.test.assertEquals
@ -11,23 +9,28 @@ import kotlin.test.assertEquals
class FeverFeedsAdapterTest {
val adapter = Moshi.Builder()
.add(FeverFeedsAdapter())
.build()
.adapter<List<Feed>>(Types.newParameterizedType(List::class.java, Feed::class.java))!!
.add(FeverFeeds::class.java, FeverFeedsAdapter())
.build()
.adapter(FeverFeeds::class.java)!!
@Test
fun validFeedsTest() {
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(url, "https://www.xda-developers.com/feed/")
assertEquals(siteUrl, "https://www.xda-developers.com/")
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 com.readrops.api.services.SyncType
import com.readrops.api.services.fever.FeverDataSource
import com.readrops.api.services.fever.adapters.FeverFeeds
import com.readrops.api.utils.ApiUtils
import com.readrops.app.addfeed.FeedInsertionResult
import com.readrops.app.addfeed.ParsingResult
import com.readrops.app.utils.Utils
import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.entities.ItemState
import com.readrops.db.entities.account.Account
import io.reactivex.Completable
import io.reactivex.Single
@ -19,11 +22,11 @@ import kotlinx.coroutines.rx2.rxCompletable
import okhttp3.MultipartBody
class FeverRepository(
private val feverDataSource: FeverDataSource,
private val dispatcher: CoroutineDispatcher,
database: Database,
context: Context,
account: Account?,
private val feverDataSource: FeverDataSource,
private val dispatcher: CoroutineDispatcher,
database: Database,
context: Context,
account: Account?,
) : ARepository(database, context, account) {
override fun login(account: Account, insert: Boolean): Completable {
@ -33,8 +36,8 @@ class FeverRepository(
account.displayedName = account.accountType!!.name
database.accountDao().insert(account)
.doOnSuccess { account.id = it.toInt() }
.await()
.doOnSuccess { account.id = it.toInt() }
.await()
} catch (e: Exception) {
error(e.message!!)
}
@ -60,7 +63,10 @@ class FeverRepository(
val syncResult = feverDataSource.sync(requestBody)
insertFolders(syncResult.folders)
insertFeeds(syncResult.feeds)
insertFeeds(syncResult.feverFeeds)
//insertItems(syncResult.items)
//insertItemsIds(syncResult.unreadIds!!, syncResult.starredIds!!.toMutableList())
} catch (e: Exception) {
error(e.message!!)
}
@ -76,7 +82,13 @@ class FeverRepository(
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 }
database.feedDao().feedsUpsert(feeds, account)
}