Migrate Nextcloud News API to v1.3

This commit is contained in:
Shinokuni 2024-06-30 19:50:31 +02:00
parent a98ef5c449
commit 3f43d2219c
7 changed files with 38 additions and 72 deletions

View File

@ -1,9 +1,9 @@
package com.readrops.api.services
import com.readrops.api.services.freshrss.FreshRSSCredentials
import com.readrops.api.services.freshrss.FreshRSSService
import com.readrops.api.services.freshrss.NewFreshRSSService
import com.readrops.api.services.nextcloudnews.NewNextcloudNewsService
import com.readrops.api.services.nextcloudnews.NextNewsCredentials
import com.readrops.api.services.nextcloudnews.NextNewsService
import com.readrops.db.entities.account.Account
import com.readrops.db.entities.account.AccountType
@ -23,8 +23,8 @@ abstract class Credentials(val authorization: String?, val url: String) {
private fun getEndPoint(accountType: AccountType): String {
return when (accountType) {
AccountType.FRESHRSS -> FreshRSSService.END_POINT
AccountType.NEXTCLOUD_NEWS -> NextNewsService.END_POINT
AccountType.FRESHRSS -> NewFreshRSSService.END_POINT
AccountType.NEXTCLOUD_NEWS -> NewNextcloudNewsService.END_POINT
else -> throw IllegalArgumentException("Unknown account type")
}
}

View File

@ -8,7 +8,6 @@ import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.entities.account.Account
import com.readrops.db.pojo.StarItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@ -50,8 +49,7 @@ class NewNextcloudNewsDataSource(private val service: NewNextcloudNewsService) {
} else {
listOf(
async { setItemsReadState(syncData) },
async { setItemsStarState(StateType.STAR, syncData.starredIds) },
async { setItemsStarState(StateType.UNSTAR, syncData.unstarredIds) }
async { setItemsStarState(syncData) },
).awaitAll()
SyncResult().apply {
@ -108,32 +106,30 @@ class NewNextcloudNewsDataSource(private val service: NewNextcloudNewsService) {
if (unreadIds.isNotEmpty()) {
service.setReadState(
StateType.UNREAD.name.lowercase(),
mapOf("items" to unreadIds)
mapOf("itemIds" to unreadIds)
)
}
if (readIds.isNotEmpty()) {
service.setReadState(
StateType.READ.name.lowercase(),
mapOf("items" to readIds)
mapOf("itemIds" to readIds)
)
}
}
suspend fun setItemsStarState(stateType: StateType, itemIds: List<StarItem>) {
if (itemIds.isNotEmpty()) {
val body = arrayListOf<Map<String, String>>()
for (item in itemIds) {
body += mapOf(
"feedId" to item.feedRemoteId,
"guidHash" to item.guidHash
)
}
suspend fun setItemsStarState(syncData: NextcloudNewsSyncData) = with(syncData) {
if (starredIds.isNotEmpty()) {
service.setStarState(
stateType.name.lowercase(),
mapOf("items" to body)
StateType.STAR.name.lowercase(),
mapOf("itemIds" to starredIds)
)
}
if (unstarredIds.isNotEmpty()) {
service.setStarState(
StateType.UNSTAR.name.lowercase(),
mapOf("itemIds" to unstarredIds)
)
}
}

View File

@ -32,18 +32,18 @@ interface NewNextcloudNewsService {
@Query("type") type: Int
): List<Item>
@PUT("items/{stateType}/multiple")
@POST("items/{stateType}/multiple")
@JvmSuppressWildcards
suspend fun setReadState(
@Path("stateType") stateType: String,
@Body itemIdsMap: Map<String, List<Int>>
)
@PUT("items/{starType}/multiple")
@POST("items/{starType}/multiple")
@JvmSuppressWildcards
suspend fun setStarState(
@Path("starType") starType: String?,
@Body body: Map<String?, List<Map<String, String>>>
@Body body: Map<String, List<Int>>
)
@POST("feeds")
@ -68,6 +68,6 @@ interface NewNextcloudNewsService {
suspend fun renameFolder(@Path("folderId") folderId: Int, @Body folderName: Map<String, String>)
companion object {
const val END_POINT = "/index.php/apps/news/api/v1-2/"
const val END_POINT = "/index.php/apps/news/api/v1-3/"
}
}

View File

@ -1,11 +1,9 @@
package com.readrops.api.services.nextcloudnews
import com.readrops.db.pojo.StarItem
data class NextcloudNewsSyncData(
val lastModified: Long = 0,
val readIds: List<Int> = listOf(),
val unreadIds: List<Int> = listOf(),
val starredIds: List<StarItem> = listOf(),
val unstarredIds: List<StarItem> = listOf(),
val starredIds: List<Int> = listOf(),
val unstarredIds: List<Int> = listOf(),
)

View File

@ -6,7 +6,6 @@ import com.readrops.api.enqueueOK
import com.readrops.api.enqueueStream
import com.readrops.api.services.nextcloudnews.NextNewsDataSource.ItemQueryType
import com.readrops.db.entities.account.Account
import com.readrops.db.pojo.StarItem
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import kotlinx.coroutines.test.runTest
@ -251,8 +250,8 @@ class NextcloudNewsDataSourceTest : KoinTest {
val unreadBody = adapter.fromJson(unreadRequest.body)!!
val readBody = adapter.fromJson(readRequest.body)!!
assertEquals(data.readIds, readBody["items"])
assertEquals(data.unreadIds, unreadBody["items"])
assertEquals(data.readIds, readBody["itemIds"])
assertEquals(data.unreadIds, unreadBody["itemIds"])
}
@Test
@ -260,47 +259,27 @@ class NextcloudNewsDataSourceTest : KoinTest {
mockServer.enqueueOK()
mockServer.enqueueOK()
val starList = listOf(
StarItem("remote1", "guid1"),
StarItem("remote2", "guid2")
)
nextcloudNewsDataSource.setItemsStarState(
NewNextcloudNewsDataSource.StateType.STAR,
starList
val data = NextcloudNewsSyncData(
starredIds = listOf(15, 16, 17),
unstarredIds = listOf(18, 19, 20)
)
nextcloudNewsDataSource.setItemsStarState(data)
val starRequest = mockServer.takeRequest()
val unstarList = listOf(
StarItem("remote3", "guid3"),
StarItem("remote4", "guid4")
)
nextcloudNewsDataSource.setItemsStarState(
NewNextcloudNewsDataSource.StateType.UNSTAR,
unstarList
)
val unstarRequest = mockServer.takeRequest()
val type =
Types.newParameterizedType(
Map::class.java,
String::class.java,
Types.newParameterizedType(
List::class.java,
Types.newParameterizedType(
Map::class.java,
String::class.java,
String::class.java
)
)
Types.newParameterizedType(List::class.java, Int::class.javaObjectType)
)
val adapter = moshi.adapter<Map<String, List<Map<String, String>>>>(type)
val adapter = moshi.adapter<Map<String, List<Int>>>(type)
val starBody = adapter.fromJson(starRequest.body)!!
val unstarBody = adapter.fromJson(unstarRequest.body)!!
assertEquals(starList[0].feedRemoteId, starBody.values.first().first()["feedId"])
assertEquals(unstarList[0].feedRemoteId, unstarBody.values.first().first()["feedId"])
assertEquals(data.starredIds, starBody["itemIds"])
assertEquals(data.unstarredIds, unstarBody["itemIds"])
}
}

View File

@ -40,19 +40,16 @@ class NextcloudNewsRepository(
val itemStateChanges = database.newItemStateChangeDao()
.selectItemStateChanges(account.id)
val starredIds = itemStateChanges.filter { it.starChange && it.starred }
.map { it.remoteId }
val unstarredIds = itemStateChanges.filter { it.starChange && !it.starred }
.map { it.remoteId }
val syncData = NextcloudNewsSyncData(
lastModified = account.lastModified,
readIds = itemStateChanges.filter { it.readChange && it.read }
.map { it.remoteId.toInt() },
unreadIds = itemStateChanges.filter { it.readChange && !it.read }
.map { it.remoteId.toInt() },
starredIds = database.newItemDao().selectStarChanges(starredIds, account.id),
unstarredIds = database.newItemDao().selectStarChanges(unstarredIds, account.id)
starredIds = itemStateChanges.filter { it.starChange && it.starred }
.map { it.remoteId.toInt() },
unstarredIds = itemStateChanges.filter { it.starChange && !it.starred }
.map { it.remoteId.toInt() }
)
val syncType = if (account.lastModified != 0L) {

View File

@ -11,7 +11,6 @@ import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.entities.ItemState
import com.readrops.db.pojo.ItemWithFeed
import com.readrops.db.pojo.StarItem
import kotlinx.coroutines.flow.Flow
@Dao
@ -67,7 +66,4 @@ abstract class NewItemDao : NewBaseDao<Item> {
@Query("Select case When :guid In (Select guid From Item Inner Join Feed on Item.feed_id = Feed.id and account_id = :accountId) Then 1 else 0 end")
abstract suspend fun itemExists(guid: String, accountId: Int): Boolean
@Query("Select Item.guid, Feed.remoteId as feedRemoteId From Item Inner Join Feed On Item.feed_id = Feed.id Where Item.remoteId In (:remoteIds) And account_id = :accountId")
abstract suspend fun selectStarChanges(remoteIds: List<String>, accountId: Int): List<StarItem>
}