mirror of https://github.com/readrops/Readrops.git
Migrate Nextcloud News API to v1.3
This commit is contained in:
parent
a98ef5c449
commit
3f43d2219c
|
@ -1,9 +1,9 @@
|
||||||
package com.readrops.api.services
|
package com.readrops.api.services
|
||||||
|
|
||||||
import com.readrops.api.services.freshrss.FreshRSSCredentials
|
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.NextNewsCredentials
|
||||||
import com.readrops.api.services.nextcloudnews.NextNewsService
|
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import com.readrops.db.entities.account.AccountType
|
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 {
|
private fun getEndPoint(accountType: AccountType): String {
|
||||||
return when (accountType) {
|
return when (accountType) {
|
||||||
AccountType.FRESHRSS -> FreshRSSService.END_POINT
|
AccountType.FRESHRSS -> NewFreshRSSService.END_POINT
|
||||||
AccountType.NEXTCLOUD_NEWS -> NextNewsService.END_POINT
|
AccountType.NEXTCLOUD_NEWS -> NewNextcloudNewsService.END_POINT
|
||||||
else -> throw IllegalArgumentException("Unknown account type")
|
else -> throw IllegalArgumentException("Unknown account type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ 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.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import com.readrops.db.pojo.StarItem
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
|
@ -50,8 +49,7 @@ class NewNextcloudNewsDataSource(private val service: NewNextcloudNewsService) {
|
||||||
} else {
|
} else {
|
||||||
listOf(
|
listOf(
|
||||||
async { setItemsReadState(syncData) },
|
async { setItemsReadState(syncData) },
|
||||||
async { setItemsStarState(StateType.STAR, syncData.starredIds) },
|
async { setItemsStarState(syncData) },
|
||||||
async { setItemsStarState(StateType.UNSTAR, syncData.unstarredIds) }
|
|
||||||
).awaitAll()
|
).awaitAll()
|
||||||
|
|
||||||
SyncResult().apply {
|
SyncResult().apply {
|
||||||
|
@ -108,32 +106,30 @@ class NewNextcloudNewsDataSource(private val service: NewNextcloudNewsService) {
|
||||||
if (unreadIds.isNotEmpty()) {
|
if (unreadIds.isNotEmpty()) {
|
||||||
service.setReadState(
|
service.setReadState(
|
||||||
StateType.UNREAD.name.lowercase(),
|
StateType.UNREAD.name.lowercase(),
|
||||||
mapOf("items" to unreadIds)
|
mapOf("itemIds" to unreadIds)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readIds.isNotEmpty()) {
|
if (readIds.isNotEmpty()) {
|
||||||
service.setReadState(
|
service.setReadState(
|
||||||
StateType.READ.name.lowercase(),
|
StateType.READ.name.lowercase(),
|
||||||
mapOf("items" to readIds)
|
mapOf("itemIds" to readIds)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setItemsStarState(stateType: StateType, itemIds: List<StarItem>) {
|
suspend fun setItemsStarState(syncData: NextcloudNewsSyncData) = with(syncData) {
|
||||||
if (itemIds.isNotEmpty()) {
|
if (starredIds.isNotEmpty()) {
|
||||||
val body = arrayListOf<Map<String, String>>()
|
|
||||||
|
|
||||||
for (item in itemIds) {
|
|
||||||
body += mapOf(
|
|
||||||
"feedId" to item.feedRemoteId,
|
|
||||||
"guidHash" to item.guidHash
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
service.setStarState(
|
service.setStarState(
|
||||||
stateType.name.lowercase(),
|
StateType.STAR.name.lowercase(),
|
||||||
mapOf("items" to body)
|
mapOf("itemIds" to starredIds)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unstarredIds.isNotEmpty()) {
|
||||||
|
service.setStarState(
|
||||||
|
StateType.UNSTAR.name.lowercase(),
|
||||||
|
mapOf("itemIds" to unstarredIds)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,18 +32,18 @@ interface NewNextcloudNewsService {
|
||||||
@Query("type") type: Int
|
@Query("type") type: Int
|
||||||
): List<Item>
|
): List<Item>
|
||||||
|
|
||||||
@PUT("items/{stateType}/multiple")
|
@POST("items/{stateType}/multiple")
|
||||||
@JvmSuppressWildcards
|
@JvmSuppressWildcards
|
||||||
suspend fun setReadState(
|
suspend fun setReadState(
|
||||||
@Path("stateType") stateType: String,
|
@Path("stateType") stateType: String,
|
||||||
@Body itemIdsMap: Map<String, List<Int>>
|
@Body itemIdsMap: Map<String, List<Int>>
|
||||||
)
|
)
|
||||||
|
|
||||||
@PUT("items/{starType}/multiple")
|
@POST("items/{starType}/multiple")
|
||||||
@JvmSuppressWildcards
|
@JvmSuppressWildcards
|
||||||
suspend fun setStarState(
|
suspend fun setStarState(
|
||||||
@Path("starType") starType: String?,
|
@Path("starType") starType: String?,
|
||||||
@Body body: Map<String?, List<Map<String, String>>>
|
@Body body: Map<String, List<Int>>
|
||||||
)
|
)
|
||||||
|
|
||||||
@POST("feeds")
|
@POST("feeds")
|
||||||
|
@ -68,6 +68,6 @@ interface NewNextcloudNewsService {
|
||||||
suspend fun renameFolder(@Path("folderId") folderId: Int, @Body folderName: Map<String, String>)
|
suspend fun renameFolder(@Path("folderId") folderId: Int, @Body folderName: Map<String, String>)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val END_POINT = "/index.php/apps/news/api/v1-2/"
|
const val END_POINT = "/index.php/apps/news/api/v1-3/"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,9 @@
|
||||||
package com.readrops.api.services.nextcloudnews
|
package com.readrops.api.services.nextcloudnews
|
||||||
|
|
||||||
import com.readrops.db.pojo.StarItem
|
|
||||||
|
|
||||||
data class NextcloudNewsSyncData(
|
data class NextcloudNewsSyncData(
|
||||||
val lastModified: Long = 0,
|
val lastModified: Long = 0,
|
||||||
val readIds: List<Int> = listOf(),
|
val readIds: List<Int> = listOf(),
|
||||||
val unreadIds: List<Int> = listOf(),
|
val unreadIds: List<Int> = listOf(),
|
||||||
val starredIds: List<StarItem> = listOf(),
|
val starredIds: List<Int> = listOf(),
|
||||||
val unstarredIds: List<StarItem> = listOf(),
|
val unstarredIds: List<Int> = listOf(),
|
||||||
)
|
)
|
|
@ -6,7 +6,6 @@ import com.readrops.api.enqueueOK
|
||||||
import com.readrops.api.enqueueStream
|
import com.readrops.api.enqueueStream
|
||||||
import com.readrops.api.services.nextcloudnews.NextNewsDataSource.ItemQueryType
|
import com.readrops.api.services.nextcloudnews.NextNewsDataSource.ItemQueryType
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import com.readrops.db.pojo.StarItem
|
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
@ -251,8 +250,8 @@ class NextcloudNewsDataSourceTest : KoinTest {
|
||||||
val unreadBody = adapter.fromJson(unreadRequest.body)!!
|
val unreadBody = adapter.fromJson(unreadRequest.body)!!
|
||||||
val readBody = adapter.fromJson(readRequest.body)!!
|
val readBody = adapter.fromJson(readRequest.body)!!
|
||||||
|
|
||||||
assertEquals(data.readIds, readBody["items"])
|
assertEquals(data.readIds, readBody["itemIds"])
|
||||||
assertEquals(data.unreadIds, unreadBody["items"])
|
assertEquals(data.unreadIds, unreadBody["itemIds"])
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -260,47 +259,27 @@ class NextcloudNewsDataSourceTest : KoinTest {
|
||||||
mockServer.enqueueOK()
|
mockServer.enqueueOK()
|
||||||
mockServer.enqueueOK()
|
mockServer.enqueueOK()
|
||||||
|
|
||||||
val starList = listOf(
|
val data = NextcloudNewsSyncData(
|
||||||
StarItem("remote1", "guid1"),
|
starredIds = listOf(15, 16, 17),
|
||||||
StarItem("remote2", "guid2")
|
unstarredIds = listOf(18, 19, 20)
|
||||||
)
|
|
||||||
nextcloudNewsDataSource.setItemsStarState(
|
|
||||||
NewNextcloudNewsDataSource.StateType.STAR,
|
|
||||||
starList
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
nextcloudNewsDataSource.setItemsStarState(data)
|
||||||
val starRequest = mockServer.takeRequest()
|
val starRequest = mockServer.takeRequest()
|
||||||
|
|
||||||
val unstarList = listOf(
|
|
||||||
StarItem("remote3", "guid3"),
|
|
||||||
StarItem("remote4", "guid4")
|
|
||||||
)
|
|
||||||
nextcloudNewsDataSource.setItemsStarState(
|
|
||||||
NewNextcloudNewsDataSource.StateType.UNSTAR,
|
|
||||||
unstarList
|
|
||||||
)
|
|
||||||
|
|
||||||
val unstarRequest = mockServer.takeRequest()
|
val unstarRequest = mockServer.takeRequest()
|
||||||
|
|
||||||
val type =
|
val type =
|
||||||
Types.newParameterizedType(
|
Types.newParameterizedType(
|
||||||
Map::class.java,
|
Map::class.java,
|
||||||
String::class.java,
|
String::class.java,
|
||||||
Types.newParameterizedType(
|
Types.newParameterizedType(List::class.java, Int::class.javaObjectType)
|
||||||
List::class.java,
|
|
||||||
Types.newParameterizedType(
|
|
||||||
Map::class.java,
|
|
||||||
String::class.java,
|
|
||||||
String::class.java
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
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 starBody = adapter.fromJson(starRequest.body)!!
|
||||||
val unstarBody = adapter.fromJson(unstarRequest.body)!!
|
val unstarBody = adapter.fromJson(unstarRequest.body)!!
|
||||||
|
|
||||||
assertEquals(starList[0].feedRemoteId, starBody.values.first().first()["feedId"])
|
assertEquals(data.starredIds, starBody["itemIds"])
|
||||||
assertEquals(unstarList[0].feedRemoteId, unstarBody.values.first().first()["feedId"])
|
assertEquals(data.unstarredIds, unstarBody["itemIds"])
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -40,19 +40,16 @@ class NextcloudNewsRepository(
|
||||||
val itemStateChanges = database.newItemStateChangeDao()
|
val itemStateChanges = database.newItemStateChangeDao()
|
||||||
.selectItemStateChanges(account.id)
|
.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(
|
val syncData = NextcloudNewsSyncData(
|
||||||
lastModified = account.lastModified,
|
lastModified = account.lastModified,
|
||||||
readIds = itemStateChanges.filter { it.readChange && it.read }
|
readIds = itemStateChanges.filter { it.readChange && it.read }
|
||||||
.map { it.remoteId.toInt() },
|
.map { it.remoteId.toInt() },
|
||||||
unreadIds = itemStateChanges.filter { it.readChange && !it.read }
|
unreadIds = itemStateChanges.filter { it.readChange && !it.read }
|
||||||
.map { it.remoteId.toInt() },
|
.map { it.remoteId.toInt() },
|
||||||
starredIds = database.newItemDao().selectStarChanges(starredIds, account.id),
|
starredIds = itemStateChanges.filter { it.starChange && it.starred }
|
||||||
unstarredIds = database.newItemDao().selectStarChanges(unstarredIds, account.id)
|
.map { it.remoteId.toInt() },
|
||||||
|
unstarredIds = itemStateChanges.filter { it.starChange && !it.starred }
|
||||||
|
.map { it.remoteId.toInt() }
|
||||||
)
|
)
|
||||||
|
|
||||||
val syncType = if (account.lastModified != 0L) {
|
val syncType = if (account.lastModified != 0L) {
|
||||||
|
|
|
@ -11,7 +11,6 @@ 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.ItemState
|
||||||
import com.readrops.db.pojo.ItemWithFeed
|
import com.readrops.db.pojo.ItemWithFeed
|
||||||
import com.readrops.db.pojo.StarItem
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@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")
|
@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
|
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>
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue