Ignore non-existent galleries during favorites sync
This commit is contained in:
parent
98ac8a69c2
commit
77c07d13c0
@ -10,7 +10,11 @@ import rx.Producer
|
|||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
fun Call.asObservable(): Observable<Response> {
|
fun Call.asObservableWithAsyncStacktrace(): Observable<Pair<Exception, Response>> {
|
||||||
|
// Record stacktrace at creation time for easier debugging
|
||||||
|
// asObservable is involved in a lot of crashes so this is worth the performance hit
|
||||||
|
val asyncStackTrace = Exception("Async stacktrace")
|
||||||
|
|
||||||
return Observable.unsafeCreate { subscriber ->
|
return Observable.unsafeCreate { subscriber ->
|
||||||
// Since Call is a one-shot type, clone it for each new subscriber.
|
// Since Call is a one-shot type, clone it for each new subscriber.
|
||||||
val call = clone()
|
val call = clone()
|
||||||
@ -23,12 +27,12 @@ fun Call.asObservable(): Observable<Response> {
|
|||||||
try {
|
try {
|
||||||
val response = call.execute()
|
val response = call.execute()
|
||||||
if (!subscriber.isUnsubscribed) {
|
if (!subscriber.isUnsubscribed) {
|
||||||
subscriber.onNext(response)
|
subscriber.onNext(asyncStackTrace to response)
|
||||||
subscriber.onCompleted()
|
subscriber.onCompleted()
|
||||||
}
|
}
|
||||||
} catch (error: Exception) {
|
} catch (error: Exception) {
|
||||||
if (!subscriber.isUnsubscribed) {
|
if (!subscriber.isUnsubscribed) {
|
||||||
subscriber.onError(error)
|
subscriber.onError(error.withRootCause(asyncStackTrace))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,19 +51,14 @@ fun Call.asObservable(): Observable<Response> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Call.asObservableSuccess(): Observable<Response> {
|
fun Call.asObservable() = asObservableWithAsyncStacktrace().map { it.second }
|
||||||
// Record stacktrace at creation time for easier debugging
|
|
||||||
// asObservable is involved in a lot of crashes so this is worth the performance hit
|
|
||||||
val asyncStackTrace = Exception("Async stacktrace")
|
|
||||||
|
|
||||||
return asObservable().doOnNext { response ->
|
fun Call.asObservableSuccess(): Observable<Response> {
|
||||||
|
return asObservableWithAsyncStacktrace().map { (asyncStacktrace, response) ->
|
||||||
if (!response.isSuccessful) {
|
if (!response.isSuccessful) {
|
||||||
response.close()
|
response.close()
|
||||||
throw Exception("HTTP error ${response.code()}")
|
throw Exception("HTTP error ${response.code()}", asyncStacktrace)
|
||||||
}
|
} else response
|
||||||
}.onErrorReturn {
|
|
||||||
// Set root cause to async stacktrace and throw again
|
|
||||||
throw it.withRootCause(asyncStackTrace)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.asObservableWithAsyncStacktrace
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
import eu.kanade.tachiyomi.source.model.*
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
@ -32,6 +33,7 @@ import uy.kohesive.injekt.injectLazy
|
|||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
|
import java.lang.RuntimeException
|
||||||
|
|
||||||
class EHentai(override val id: Long,
|
class EHentai(override val id: Long,
|
||||||
val exh: Boolean,
|
val exh: Boolean,
|
||||||
@ -236,11 +238,21 @@ class EHentai(override val id: Long,
|
|||||||
*/
|
*/
|
||||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||||
return client.newCall(mangaDetailsRequest(manga))
|
return client.newCall(mangaDetailsRequest(manga))
|
||||||
.asObservableSuccess()
|
.asObservableWithAsyncStacktrace()
|
||||||
.flatMap {
|
.flatMap { (stacktrace, response) ->
|
||||||
parseToManga(manga, it).andThen(Observable.just(manga.apply {
|
if(response.isSuccessful) {
|
||||||
|
parseToManga(manga, response).andThen(Observable.just(manga.apply {
|
||||||
initialized = true
|
initialized = true
|
||||||
}))
|
}))
|
||||||
|
} else {
|
||||||
|
response.close()
|
||||||
|
|
||||||
|
if(response.code() == 404) {
|
||||||
|
throw GalleryNotFoundException(stacktrace)
|
||||||
|
} else {
|
||||||
|
throw Exception("HTTP error ${response.code()}", stacktrace)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,6 +534,8 @@ class EHentai(override val id: Long,
|
|||||||
else
|
else
|
||||||
"E-Hentai"
|
"E-Hentai"
|
||||||
|
|
||||||
|
class GalleryNotFoundException(cause: Throwable): RuntimeException("Gallery not found!", cause)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val QUERY_PREFIX = "?f_apply=Apply+Filter"
|
private const val QUERY_PREFIX = "?f_apply=Apply+Filter"
|
||||||
private const val TR_SUFFIX = "TR"
|
private const val TR_SUFFIX = "TR"
|
||||||
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
|
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||||
import eu.kanade.tachiyomi.util.syncChaptersWithSource
|
import eu.kanade.tachiyomi.util.syncChaptersWithSource
|
||||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
@ -186,6 +187,11 @@ class GalleryAdder {
|
|||||||
return GalleryAddEvent.Success(url, manga)
|
return GalleryAddEvent.Success(url, manga)
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
XLog.w("Could not add gallery!", e)
|
XLog.w("Could not add gallery!", e)
|
||||||
|
|
||||||
|
if(e is EHentai.GalleryNotFoundException) {
|
||||||
|
return GalleryAddEvent.Fail.NotFound(url)
|
||||||
|
}
|
||||||
|
|
||||||
return GalleryAddEvent.Fail.Error(url,
|
return GalleryAddEvent.Fail.Error(url,
|
||||||
((e.message ?: "Unknown error!") + " (Gallery: $url)").trim())
|
((e.message ?: "Unknown error!") + " (Gallery: $url)").trim())
|
||||||
}
|
}
|
||||||
@ -223,7 +229,10 @@ sealed class GalleryAddEvent {
|
|||||||
override val logMessage = "Unknown gallery type for gallery: $galleryUrl"
|
override val logMessage = "Unknown gallery type for gallery: $galleryUrl"
|
||||||
}
|
}
|
||||||
|
|
||||||
class Error(override val galleryUrl: String,
|
open class Error(override val galleryUrl: String,
|
||||||
override val logMessage: String): Fail()
|
override val logMessage: String): Fail()
|
||||||
|
|
||||||
|
class NotFound(galleryUrl: String):
|
||||||
|
Error(galleryUrl, "Gallery does not exist: $galleryUrl")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -323,6 +323,12 @@ class FavoritesSyncHelper(val context: Context) {
|
|||||||
EXH_SOURCE_ID)
|
EXH_SOURCE_ID)
|
||||||
|
|
||||||
if(result is GalleryAddEvent.Fail) {
|
if(result is GalleryAddEvent.Fail) {
|
||||||
|
if(result is GalleryAddEvent.Fail.NotFound) {
|
||||||
|
XLog.e("Remote gallery does not exist, skipping: %s!", it.getUrl())
|
||||||
|
// Skip this gallery, it no longer exists
|
||||||
|
return@forEachIndexed
|
||||||
|
}
|
||||||
|
|
||||||
val errorString = "Failed to add gallery to local database: " + when (result) {
|
val errorString = "Failed to add gallery to local database: " + when (result) {
|
||||||
is GalleryAddEvent.Fail.Error -> "'${it.title}' ${result.logMessage}"
|
is GalleryAddEvent.Fail.Error -> "'${it.title}' ${result.logMessage}"
|
||||||
is GalleryAddEvent.Fail.UnknownType -> "'${it.title}' (${result.galleryUrl}) is not a valid gallery!"
|
is GalleryAddEvent.Fail.UnknownType -> "'${it.title}' (${result.galleryUrl}) is not a valid gallery!"
|
||||||
|
@ -43,7 +43,6 @@ class BatchAddPresenter: BasePresenter<BatchAddController>() {
|
|||||||
eventRelay?.call((when (result) {
|
eventRelay?.call((when (result) {
|
||||||
is GalleryAddEvent.Success -> "[OK]"
|
is GalleryAddEvent.Success -> "[OK]"
|
||||||
is GalleryAddEvent.Fail -> "[ERROR]"
|
is GalleryAddEvent.Fail -> "[ERROR]"
|
||||||
else -> "[???]"
|
|
||||||
}) + " " + result.logMessage)
|
}) + " " + result.logMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user