Sync FreshRSS items star state
This commit is contained in:
parent
c449a94260
commit
cfa764e78b
@ -6,6 +6,7 @@ import com.readrops.api.services.freshrss.FreshRSSService
|
||||
import com.readrops.api.services.freshrss.adapters.FreshRSSFeedsAdapter
|
||||
import com.readrops.api.services.freshrss.adapters.FreshRSSFoldersAdapter
|
||||
import com.readrops.api.services.freshrss.adapters.FreshRSSItemsAdapter
|
||||
import com.readrops.api.services.freshrss.adapters.FreshRSSItemsIdsAdapter
|
||||
import com.readrops.api.services.nextcloudnews.NextNewsDataSource
|
||||
import com.readrops.api.services.nextcloudnews.NextNewsService
|
||||
import com.readrops.api.services.nextcloudnews.adapters.NextNewsFeedsAdapter
|
||||
@ -60,6 +61,7 @@ val apiModule = module {
|
||||
single(named("freshrssMoshi")) {
|
||||
Moshi.Builder()
|
||||
.add(Types.newParameterizedType(List::class.java, Item::class.java), FreshRSSItemsAdapter())
|
||||
.add(Types.newParameterizedType(List::class.java, String::class.java), FreshRSSItemsIdsAdapter())
|
||||
.add(FreshRSSFeedsAdapter())
|
||||
.add(FreshRSSFoldersAdapter())
|
||||
.build()
|
||||
|
@ -8,9 +8,13 @@ class SyncResult {
|
||||
|
||||
var items: List<Item> = mutableListOf()
|
||||
|
||||
var starredItems: List<Item> = mutableListOf()
|
||||
|
||||
var feeds: List<Feed> = listOf()
|
||||
|
||||
var folders: List<Folder> = listOf()
|
||||
|
||||
var starredIds: List<String>? = null
|
||||
|
||||
var isError: Boolean = false
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import com.readrops.db.entities.Folder;
|
||||
import com.readrops.db.entities.Item;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@ -22,9 +24,11 @@ import okhttp3.RequestBody;
|
||||
public class FreshRSSDataSource {
|
||||
|
||||
private static final int MAX_ITEMS = 5000;
|
||||
private static final int MAX_STARRED_ITEMS = 999;
|
||||
|
||||
public static final String GOOGLE_READ = "user/-/state/com.google/read";
|
||||
public static final String GOOGLE_STARRED = "user/-/state/com.google/starred";
|
||||
public static final String GOOGLE_READING_LIST = "user/-/state/com.google/reading-list";
|
||||
|
||||
private static final String FEED_PREFIX = "feed/";
|
||||
|
||||
@ -99,14 +103,22 @@ public class FreshRSSDataSource {
|
||||
syncResult.setFeeds(freshRSSFeeds);
|
||||
|
||||
if (syncType == SyncType.INITIAL_SYNC) {
|
||||
return getItems(GOOGLE_READ, MAX_ITEMS, null);
|
||||
return getItems(Arrays.asList(GOOGLE_READ, GOOGLE_STARRED), MAX_ITEMS, null);
|
||||
} else {
|
||||
return getItems(null, MAX_ITEMS, syncData.getLastModified());
|
||||
return getItems(Collections.singletonList(GOOGLE_STARRED), MAX_ITEMS, syncData.getLastModified());
|
||||
}
|
||||
})
|
||||
.flatMap(freshRSSItems -> {
|
||||
syncResult.setItems(freshRSSItems);
|
||||
|
||||
return getStarredItems(MAX_STARRED_ITEMS);
|
||||
}).flatMap(starredItems -> {
|
||||
syncResult.setStarredItems(starredItems);
|
||||
|
||||
return getItemsIds(null, GOOGLE_STARRED, MAX_STARRED_ITEMS);
|
||||
}).flatMap(starredIds -> {
|
||||
syncResult.setStarredIds(starredIds);
|
||||
|
||||
return Single.just(syncResult);
|
||||
}));
|
||||
}
|
||||
@ -132,13 +144,27 @@ public class FreshRSSDataSource {
|
||||
/**
|
||||
* Fetch the items
|
||||
*
|
||||
* @param excludeTarget type of items to exclude (currently only read items)
|
||||
* @param max max number of items to fetch
|
||||
* @param lastModified fetch only items created after this timestamp
|
||||
* @param excludeTargets type of items to exclude (read items and starred items)
|
||||
* @param max max number of items to fetch
|
||||
* @param lastModified fetch only items created after this timestamp
|
||||
* @return the items
|
||||
*/
|
||||
public Single<List<Item>> getItems(@Nullable String excludeTarget, int max, @Nullable Long lastModified) {
|
||||
return api.getItems(excludeTarget, max, lastModified);
|
||||
public Single<List<Item>> getItems(@Nullable List<String> excludeTargets, int max, @Nullable Long lastModified) {
|
||||
return api.getItems(excludeTargets, max, lastModified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch starred items
|
||||
*
|
||||
* @param max max number of items to fetch
|
||||
* @return items
|
||||
*/
|
||||
public Single<List<Item>> getStarredItems(int max) {
|
||||
return api.getStarredItems(max);
|
||||
}
|
||||
|
||||
public Single<List<String>> getItemsIds(String excludeTarget, String includeTarget, int max) {
|
||||
return api.getItemsIds(excludeTarget, includeTarget, max);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.readrops.api.services.freshrss;
|
||||
|
||||
import com.readrops.api.services.freshrss.json.FreshRSSUserInfo;
|
||||
import com.readrops.db.entities.Feed;
|
||||
import com.readrops.db.entities.Folder;
|
||||
import com.readrops.db.entities.Item;
|
||||
import com.readrops.api.services.freshrss.json.FreshRSSUserInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -35,7 +35,13 @@ public interface FreshRSSService {
|
||||
Single<List<Feed>> getFeeds();
|
||||
|
||||
@GET("reader/api/0/stream/contents/user/-/state/com.google/reading-list")
|
||||
Single<List<Item>> getItems(@Query("xt") String excludeTarget, @Query("n") int max, @Query("ot") Long lastModified);
|
||||
Single<List<Item>> getItems(@Query("xt") List<String> excludeTarget, @Query("n") int max, @Query("ot") Long lastModified);
|
||||
|
||||
@GET("reader/api/0/stream/contents/user/-/state/com.google/starred")
|
||||
Single<List<Item>> getStarredItems(@Query("n") int max);
|
||||
|
||||
@GET("reader/api/0/stream/items/ids")
|
||||
Single<List<String>> getItemsIds(@Query("xt") String excludeTarget, @Query("s") String includeTarget, @Query("n") int max);
|
||||
|
||||
@GET("reader/api/0/tag/list?output=json")
|
||||
Single<List<Folder>> getFolders();
|
||||
|
@ -0,0 +1,51 @@
|
||||
package com.readrops.api.services.freshrss.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.readrops.api.utils.exceptions.ParseException
|
||||
import com.readrops.api.utils.extensions.nextNonEmptyString
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.JsonReader
|
||||
import com.squareup.moshi.JsonWriter
|
||||
|
||||
class FreshRSSItemsIdsAdapter : JsonAdapter<List<String>>() {
|
||||
|
||||
override fun toJson(writer: JsonWriter, value: List<String>?) {
|
||||
// not useful here
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun fromJson(reader: JsonReader): List<String>? = with(reader) {
|
||||
val ids = arrayListOf<String>()
|
||||
|
||||
return try {
|
||||
beginObject()
|
||||
nextName()
|
||||
beginArray()
|
||||
|
||||
while (hasNext()) {
|
||||
beginObject()
|
||||
|
||||
when (nextName()) {
|
||||
"id" -> {
|
||||
val value = nextNonEmptyString()
|
||||
ids += "tag:google.com,2005:reader/item/${
|
||||
value.toLong()
|
||||
.toString(16).padStart(value.length, '0')
|
||||
}"
|
||||
}
|
||||
else -> skipValue()
|
||||
}
|
||||
|
||||
endObject()
|
||||
}
|
||||
|
||||
endArray()
|
||||
endObject()
|
||||
|
||||
ids
|
||||
} catch (e: Exception) {
|
||||
throw ParseException(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.readrops.api.services.freshrss.adapters
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import okio.Buffer
|
||||
import org.junit.Test
|
||||
|
||||
class FreshRSSItemsIdsAdapterTest {
|
||||
|
||||
private val adapter = Moshi.Builder()
|
||||
.add(Types.newParameterizedType(List::class.java, String::class.java), FreshRSSItemsIdsAdapter())
|
||||
.build()
|
||||
.adapter<List<String>>(Types.newParameterizedType(List::class.java, String::class.java))
|
||||
|
||||
@Test
|
||||
fun validIdsTest() {
|
||||
val stream = javaClass.classLoader!!.getResourceAsStream("services/freshrss/adapters/items_starred_ids.json")
|
||||
|
||||
val ids = adapter.fromJson(Buffer().readFrom(stream))!!
|
||||
|
||||
assertEquals(ids, listOf(
|
||||
"tag:google.com,2005:reader/item/0005b2c17277b383",
|
||||
"tag:google.com,2005:reader/item/0005b2c12d328ae4",
|
||||
"tag:google.com,2005:reader/item/0005b2c0781d0737",
|
||||
"tag:google.com,2005:reader/item/0005b2bf3852c293",
|
||||
"tag:google.com,2005:reader/item/0005b2bebeed9f7f"
|
||||
))
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"itemRefs": [
|
||||
{
|
||||
"id": "1603918802432899"
|
||||
},
|
||||
{
|
||||
"id": "1603917640272612"
|
||||
},
|
||||
{
|
||||
"id": "1603914602186551"
|
||||
},
|
||||
{
|
||||
"id": "1603909236998803"
|
||||
},
|
||||
{
|
||||
"id": "1603907200327551"
|
||||
}
|
||||
]
|
||||
}
|
@ -107,6 +107,10 @@ public class FreshRSSRepository extends ARepository {
|
||||
insertItems(syncResult.getItems(), syncType == SyncType.INITIAL_SYNC);
|
||||
logger.addSplit("items insertion");
|
||||
|
||||
insertItems(syncResult.getStarredItems(), syncType == SyncType.INITIAL_SYNC);
|
||||
|
||||
updateItemsStarState(syncResult.getStarredIds());
|
||||
|
||||
account.setLastModified(newLastModified);
|
||||
database.accountDao().updateLastModified(account.getId(), newLastModified);
|
||||
|
||||
@ -216,6 +220,8 @@ public class FreshRSSRepository extends ARepository {
|
||||
}
|
||||
|
||||
private void insertItems(List<Item> items, boolean initialSync) {
|
||||
List<Item> itemsToInsert = new ArrayList<>();
|
||||
|
||||
for (Item item : items) {
|
||||
int feedId = database.feedDao().getFeedIdByRemoteId(item.getFeedRemoteId(), account.getId());
|
||||
|
||||
@ -226,9 +232,21 @@ public class FreshRSSRepository extends ARepository {
|
||||
|
||||
item.setFeedId(feedId);
|
||||
item.setReadTime(Utils.readTimeFromString(item.getContent()));
|
||||
itemsToInsert.add(item);
|
||||
}
|
||||
|
||||
Collections.sort(items, Item::compareTo);
|
||||
database.itemDao().insert(items);
|
||||
if (!itemsToInsert.isEmpty()) {
|
||||
Collections.sort(itemsToInsert, Item::compareTo);
|
||||
database.itemDao().insert(itemsToInsert);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateItemsStarState(List<String> itemsIds) {
|
||||
if (itemsIds != null && !itemsIds.isEmpty()) {
|
||||
database.itemDao().unstarItems(itemsIds, account.getId());
|
||||
database.itemDao().starItems(itemsIds, account.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -94,4 +94,10 @@ public interface ItemDao extends BaseDao<Item> {
|
||||
|
||||
@Query("Update Item set starred = :starred, starred_changed = :starredChanged Where id = :itemId")
|
||||
Completable setStarState(int itemId, boolean starred, boolean starredChanged);
|
||||
|
||||
@Query("Update Item set starred = 1 Where remoteId In (:ids) And feed_id In (Select id From Feed Where account_id = :accountId)")
|
||||
void starItems(List<String> ids, int accountId);
|
||||
|
||||
@Query("Update Item set starred = 0 Where remoteId Not In (:ids) And feed_id In (Select id From Feed Where account_id = :accountId)")
|
||||
void unstarItems(List<String> ids, int accountId);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user