Skip to content

Commit

Permalink
add follows status sync into library update services and change the s…
Browse files Browse the repository at this point in the history
…ettings under advanced to be more accurate
  • Loading branch information
nonproto committed Oct 21, 2019
1 parent b0eb822 commit ccca657
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.*
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import rx.Observable
import rx.Subscription
import rx.schedulers.Schedulers
Expand Down Expand Up @@ -97,6 +100,7 @@ class LibraryUpdateService(
enum class Target {
CHAPTERS, // Manga chapters
FOLLOW_STATUSES, // Manga follow status
SYNC_FOLLOWS, //Manga in reading, rereading
DETAILS, // Manga metadata
TRACKING // Tracking metadata
}
Expand Down Expand Up @@ -207,21 +211,34 @@ class LibraryUpdateService(
val mangaList = getMangaToUpdate(intent, target)
.sortedWith(relevanceRanking())

val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception)
stopSelf(startId)
}
// Update either chapter list or manga details.
when (target) {
Target.CHAPTERS -> updateChapterList(mangaList)
Target.FOLLOW_STATUSES -> updateFollowStatuses()
Target.DETAILS -> updateDetails(mangaList)
Target.TRACKING -> updateTrackings(mangaList)
}.subscribeOn(Schedulers.io())
.subscribe({
}, {
Timber.e(it)
stopSelf(startId)
}, {
stopSelf(startId)
})
if (target == Target.FOLLOW_STATUSES) {
GlobalScope.launch(handler) {
syncFollowsStatus()
}.invokeOnCompletion { stopSelf(startId) }
} else if (target == Target.SYNC_FOLLOWS) {
GlobalScope.launch(handler) {
syncFollows()
}.invokeOnCompletion { stopSelf(startId) }
} else {
when (target) {
Target.CHAPTERS -> updateChapterList(mangaList)
Target.DETAILS -> updateDetails(mangaList)
else -> updateTrackings(mangaList)
}.subscribeOn(Schedulers.io())
.subscribe({
}, {
Timber.e(it)
stopSelf(startId)
}, {
stopSelf(startId)
})

}
return Service.START_REDELIVER_INTENT
}

Expand Down Expand Up @@ -342,52 +359,58 @@ class LibraryUpdateService(
* @return a pair of the inserted and removed chapters.
*/
fun updateManga(manga: Manga): Observable<Pair<List<Chapter>, List<Chapter>>> {
val source = sourceManager.get(manga.source) as? HttpSource ?: return Observable.empty()
val source = sourceManager.getMangadex() as? HttpSource ?: return Observable.empty()
return source.fetchChapterList(manga)
.map { syncChaptersWithSource(db, it, manga, source) }
}

/**
* Method that updates the FollowStatus of the given list of manga. It's called in a background
* thread, so it's safe to do heavy operations or network calls here.
*
* @return an observable delivering the progress of each update.
*/
private fun updateFollowStatuses(): Observable<SManga?> {
return Observable.just(null)
// Initialize the variables holding the progress of the updates.
/* val count = AtomicInteger(0)
val estimatedTotalFollowedManga = AtomicInteger(-1)
val source = sourceManager.getMangadex()
val pager = FollowsPager(source)
pager.results()
// Emit each manga and update it sequentially.
return Observable.from(pager)
// Expand extract Mangas from MangaPages
.concatMap {
it.estimatedTotalSeries
?.let { it1 -> estimatedTotalFollowedManga.set(it1) } // Update estimate
?: estimatedTotalFollowedManga.compareAndSet(-1, -1) // Don't overwrite if there's no estimate
Observable.from(it.mangas)
}
// Notify manga that will update.
.doOnNext { showProgressNotification(it, count.andIncrement, estimatedTotalFollowedManga.get()) }
// Update the details of the manga.
.map<SManga> { networkManga ->
db.getManga(networkManga.url, source.id)
.executeAsBlocking()
?.let { dbManga ->
dbManga.copyFrom(networkManga)
db.insertManga(dbManga).executeAsBlocking()
dbManga
}
}.doOnCompleted {
cancelProgressNotification()
}*/
private suspend fun syncFollows() {
val count = AtomicInteger(0)
val listManga = sourceManager.getMangadex().fetchAllFollows()
//filter all follows from Mangadex and only add reading or rereading manga to library
listManga.filter { it ->
it.follow_status == SManga.FollowStatus.RE_READING || it.follow_status == SManga.FollowStatus.READING
}
.forEach { networkManga ->
showProgressNotification(networkManga, count.andIncrement, listManga.size)

var dbManga = db.getManga(networkManga.url, sourceManager.getMangadex().id)
.executeAsBlocking()
if (dbManga == null) {
dbManga = Manga.Companion.create(sourceManager.getMangadex().id)
dbManga.favorite = true
}

dbManga.copyFrom(networkManga)
db.insertManga(dbManga).executeAsBlocking()

}
cancelProgressNotification()
}

/**
* Method that updates the syncs reading and rereading manga into neko library
*/
private suspend fun syncFollowsStatus() {
val count = AtomicInteger(0)
val listManga = sourceManager.getMangadex().fetchAllFollows()
listManga.forEach { networkManga ->
showProgressNotification(networkManga, count.andIncrement, listManga.size)
db.getManga(networkManga.url, sourceManager.getMangadex().id)
.executeAsBlocking()
?.let {
it.copyFrom(networkManga)
db.insertManga(it).executeAsBlocking()
}
}
cancelProgressNotification()
}


/**
* Method that updates the details of the given list of manga. It's called in a background
* thread, so it's safe to do heavy operations or network calls here.
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/eu/kanade/tachiyomi/source/Source.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ interface Source {
*/
fun fetchFollows(page: Int): Observable<MangasPage>

/**
* Returns a list of all Follows retrieved by Coroutines
*
* @param SManga all smanga found for user
*/
suspend fun fetchAllFollows(): List<SManga>

/**
* Returns the list of filters for the source.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ open class Mangadex(override val lang: String, private val internalLang: String,
return PageHandler(client, headers, preferences.imageServer().toString()).fetchPageList(chapter)
}

override suspend fun fetchAllFollows(): List<SManga> {
return FollowsHandler(clientBuilder(), headers).fetchAllFollows()
}


override fun isLogged(): Boolean {
val httpUrl = baseUrl.toHttpUrlOrNull()!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import eu.kanade.tachiyomi.source.online.handlers.serializers.Result
import eu.kanade.tachiyomi.source.online.utils.MdUtil
import eu.kanade.tachiyomi.source.online.utils.MdUtil.Companion.baseUrl
import eu.kanade.tachiyomi.source.online.utils.MdUtil.Companion.getMangaId
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
Expand Down Expand Up @@ -67,12 +69,28 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers) {
.map { it.body!!.string().isEmpty() }
}

suspend fun fetchAllFollows(): List<SManga> {
return withContext(Dispatchers.IO) {
val listManga = mutableListOf<SManga>()
loop@ for (i in 1..10000) {
val response = client.newCall(followsListRequest(i))
.execute()
val mangasPage = followsParse(response)

if (mangasPage.mangas.isNotEmpty()) {
listManga.addAll(mangasPage.mangas)
}
if (!mangasPage.hasNextPage) {
break@loop
}
}
listManga
}
}


companion object {
const val followsAllApi = "/api/?type=manga_follows"
const val followSelector = "div.manga-entry"
const val estimatedTotalFollowsSelector = "div.manga-entry:last-of-type + *" // The element immediately following the last follow entry
const val followsNextPageSelector = ".pagination li:not(.disabled) span[title*=last page]:not(disabled)"
private val FOLLOW_STATUS_LIST = listOf(
Triple(0, SManga.FollowStatus.UNFOLLOWED, "Unfollowed"),
Triple(1, SManga.FollowStatus.READING, "Reading"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class SettingsAdvancedController : SettingsController() {
titleRes = R.string.pref_sync_library_follows
summaryRes = R.string.pref_refresh_library_follows_summary

onClick { LibraryUpdateService.start(context, target = Target.FOLLOW_STATUSES) }
onClick { LibraryUpdateService.start(context, target = Target.SYNC_FOLLOWS) }
}
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@
<string name="pref_refresh_library_metadata_summary">Updates covers, genres, description and manga status information</string>
<string name="pref_refresh_library_tracking">Refresh tracking metadata</string>
<string name="pref_refresh_library_tracking_summary">Updates status, score and last chapter read from the tracking services</string>
<string name="pref_sync_library_follows">Sync Mangadex follows into Neko</string>
<string name="pref_refresh_library_follows_summary">Pulls reading follows from Mangadex into your Neko Library</string>
<string name="pref_sync_library_follows">Sync Mangadex Manga into Neko</string>
<string name="pref_refresh_library_follows_summary">Pulls reading/rereading manga from Mangadex into your Neko Library</string>

<!-- About section -->
<string name="version">Version</string>
Expand Down

0 comments on commit ccca657

Please sign in to comment.