unhide and begin working on merged sources
This commit is contained in:
parent
5f94e230f9
commit
9ed7ee65c3
@ -1,22 +1,31 @@
|
|||||||
package eu.kanade.tachiyomi.source.online.all
|
package eu.kanade.tachiyomi.source.online.all
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.elvishew.xlog.XLog
|
||||||
import com.github.salomonbrys.kotson.fromJson
|
import com.github.salomonbrys.kotson.fromJson
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
import com.lvla.rxjava.interopkt.toV1Observable
|
|
||||||
import com.lvla.rxjava.interopkt.toV1Single
|
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
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.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import exh.MERGED_SOURCE_ID
|
import exh.MERGED_SOURCE_ID
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
|
import hu.akarnokd.rxjava.interop.RxJavaInterop
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.asFlow
|
||||||
|
import kotlinx.coroutines.flow.buffer
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.take
|
||||||
|
import kotlinx.coroutines.flow.toList
|
||||||
import kotlinx.coroutines.rx2.asFlowable
|
import kotlinx.coroutines.rx2.asFlowable
|
||||||
import kotlinx.coroutines.rx2.asSingle
|
import kotlinx.coroutines.rx2.asSingle
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
@ -43,63 +52,74 @@ class MergedSource : HttpSource() {
|
|||||||
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException()
|
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||||
return readMangaConfig(manga).load(db, sourceManager).take(1).map { loaded ->
|
return RxJavaInterop.toV1Observable(
|
||||||
SManga.create().apply {
|
readMangaConfig(manga).load(db, sourceManager).take(1).map { loaded ->
|
||||||
this.copyFrom(loaded.manga)
|
SManga.create().apply {
|
||||||
url = manga.url
|
this.copyFrom(loaded.manga)
|
||||||
}
|
url = manga.url
|
||||||
}.asFlowable().toV1Observable()
|
|
||||||
}
|
|
||||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
|
||||||
return GlobalScope.async(Dispatchers.IO) {
|
|
||||||
val loadedMangas = readMangaConfig(manga).load(db, sourceManager).buffer()
|
|
||||||
loadedMangas.map { loadedManga ->
|
|
||||||
async(Dispatchers.IO) {
|
|
||||||
loadedManga.source.fetchChapterList(loadedManga.manga).map { chapterList ->
|
|
||||||
chapterList.map { chapter ->
|
|
||||||
chapter.apply {
|
|
||||||
url = writeUrlConfig(UrlConfig(loadedManga.source.id, url, loadedManga.manga.url))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.toSingle().await(Schedulers.io())
|
|
||||||
}
|
}
|
||||||
}.buffer().map { it.await() }.toList().flatten()
|
}.asFlowable()
|
||||||
}.asSingle(Dispatchers.IO).toV1Single().toObservable()
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||||
|
return RxJavaInterop.toV1Single(
|
||||||
|
GlobalScope.async(Dispatchers.IO) {
|
||||||
|
val loadedMangas = readMangaConfig(manga).load(db, sourceManager).buffer()
|
||||||
|
loadedMangas.map { loadedManga ->
|
||||||
|
async(Dispatchers.IO) {
|
||||||
|
loadedManga.source.fetchChapterList(loadedManga.manga).map { chapterList ->
|
||||||
|
chapterList.map { chapter ->
|
||||||
|
chapter.apply {
|
||||||
|
url = writeUrlConfig(UrlConfig(loadedManga.source.id, url, loadedManga.manga.url))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.toSingle().await(Schedulers.io())
|
||||||
|
}
|
||||||
|
}.buffer().map { it.await() }.toList().flatten()
|
||||||
|
}.asSingle(Dispatchers.IO)
|
||||||
|
).toObservable()
|
||||||
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException()
|
override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException()
|
||||||
override fun chapterListParse(response: Response) = throw UnsupportedOperationException()
|
override fun chapterListParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||||
val config = readUrlConfig(chapter.url)
|
val config = readUrlConfig(chapter.url)
|
||||||
val source = sourceManager.getOrStub(config.source)
|
val source = sourceManager.getOrStub(config.source)
|
||||||
return source.fetchPageList(SChapter.create().apply {
|
return source.fetchPageList(
|
||||||
copyFrom(chapter)
|
SChapter.create().apply {
|
||||||
url = config.url
|
copyFrom(chapter)
|
||||||
}).map { pages ->
|
url = config.url
|
||||||
|
}
|
||||||
|
).map { pages ->
|
||||||
pages.map { page ->
|
pages.map { page ->
|
||||||
page.copyWithUrl(writeUrlConfig(UrlConfig(config.source, page.url, config.mangaUrl)))
|
page.copyWithUrl(writeUrlConfig(UrlConfig(config.source, page.url, config.mangaUrl)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchImageUrl(page: Page): Observable<String> {
|
override fun fetchImageUrl(page: Page): Observable<String> {
|
||||||
val config = readUrlConfig(page.url)
|
val config = readUrlConfig(page.url)
|
||||||
val source = sourceManager.getOrStub(config.source) as? HttpSource
|
val source = sourceManager.getOrStub(config.source) as? HttpSource
|
||||||
?: throw UnsupportedOperationException("This source does not support this operation!")
|
?: throw UnsupportedOperationException("This source does not support this operation!")
|
||||||
return source.fetchImageUrl(page.copyWithUrl(config.url))
|
return source.fetchImageUrl(page.copyWithUrl(config.url))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response) = throw UnsupportedOperationException()
|
override fun pageListParse(response: Response) = throw UnsupportedOperationException()
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun fetchImage(page: Page): Observable<Response> {
|
override fun fetchImage(page: Page): Observable<Response> {
|
||||||
val config = readUrlConfig(page.url)
|
val config = readUrlConfig(page.url)
|
||||||
val source = sourceManager.getOrStub(config.source) as? HttpSource
|
val source = sourceManager.getOrStub(config.source) as? HttpSource
|
||||||
?: throw UnsupportedOperationException("This source does not support this operation!")
|
?: throw UnsupportedOperationException("This source does not support this operation!")
|
||||||
return source.fetchImage(page.copyWithUrl(config.url))
|
return source.fetchImage(page.copyWithUrl(config.url))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareNewChapter(chapter: SChapter, manga: SManga) {
|
override fun prepareNewChapter(chapter: SChapter, manga: SManga) {
|
||||||
val chapterConfig = readUrlConfig(chapter.url)
|
val chapterConfig = readUrlConfig(chapter.url)
|
||||||
val source = sourceManager.getOrStub(chapterConfig.source) as? HttpSource
|
val source = sourceManager.getOrStub(chapterConfig.source) as? HttpSource
|
||||||
?: throw UnsupportedOperationException("This source does not support this operation!")
|
?: throw UnsupportedOperationException("This source does not support this operation!")
|
||||||
val copiedManga = SManga.create().apply {
|
val copiedManga = SManga.create().apply {
|
||||||
this.copyFrom(manga)
|
this.copyFrom(manga)
|
||||||
url = chapterConfig.mangaUrl
|
url = chapterConfig.mangaUrl
|
||||||
@ -107,40 +127,48 @@ class MergedSource : HttpSource() {
|
|||||||
chapter.url = chapterConfig.url
|
chapter.url = chapterConfig.url
|
||||||
source.prepareNewChapter(chapter, copiedManga)
|
source.prepareNewChapter(chapter, copiedManga)
|
||||||
chapter.url = writeUrlConfig(UrlConfig(source.id, chapter.url, chapterConfig.mangaUrl))
|
chapter.url = writeUrlConfig(UrlConfig(source.id, chapter.url, chapterConfig.mangaUrl))
|
||||||
chapter.scanlator = if(chapter.scanlator.isNullOrBlank()) source.name
|
chapter.scanlator = if (chapter.scanlator.isNullOrBlank()) source.name
|
||||||
else "$source: ${chapter.scanlator}"
|
else "$source: ${chapter.scanlator}"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readMangaConfig(manga: SManga): MangaConfig {
|
fun readMangaConfig(manga: SManga): MangaConfig {
|
||||||
return MangaConfig.readFromUrl(gson, manga.url)
|
return MangaConfig.readFromUrl(gson, manga.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readUrlConfig(url: String): UrlConfig {
|
fun readUrlConfig(url: String): UrlConfig {
|
||||||
return gson.fromJson(url)
|
return gson.fromJson(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeUrlConfig(urlConfig: UrlConfig): String {
|
fun writeUrlConfig(urlConfig: UrlConfig): String {
|
||||||
return gson.toJson(urlConfig)
|
return gson.toJson(urlConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class LoadedMangaSource(val source: Source, val manga: Manga)
|
data class LoadedMangaSource(val source: Source, val manga: Manga)
|
||||||
data class MangaSource(
|
data class MangaSource(
|
||||||
@SerializedName("s")
|
@SerializedName("s")
|
||||||
val source: Long,
|
val source: Long,
|
||||||
@SerializedName("u")
|
@SerializedName("u")
|
||||||
val url: String
|
val url: String
|
||||||
) {
|
) {
|
||||||
suspend fun load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource? {
|
suspend fun load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource? {
|
||||||
val manga = db.getManga(url, source).await() ?: return null
|
val manga = db.getManga(url, source).executeAsBlocking() ?: return null
|
||||||
val source = sourceManager.getOrStub(source)
|
val source = sourceManager.getOrStub(source)
|
||||||
return LoadedMangaSource(source, manga)
|
return LoadedMangaSource(source, manga)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class MangaConfig(
|
data class MangaConfig(
|
||||||
@SerializedName("c")
|
@SerializedName("c")
|
||||||
val children: List<MangaSource>
|
val children: List<MangaSource>
|
||||||
) {
|
) {
|
||||||
fun load(db: DatabaseHelper, sourceManager: SourceManager): Flow<LoadedMangaSource> {
|
fun load(db: DatabaseHelper, sourceManager: SourceManager): Flow<LoadedMangaSource> {
|
||||||
return children.asFlow().map { mangaSource ->
|
return children.asFlow().map { mangaSource ->
|
||||||
mangaSource.load(db, sourceManager)
|
mangaSource.load(db, sourceManager)
|
||||||
?: throw IllegalStateException("Missing source manga: $mangaSource")
|
?: run {
|
||||||
|
XLog.w("> Missing source manga: $mangaSource")
|
||||||
|
Log.d("MERGED", "> Missing source manga: $mangaSource")
|
||||||
|
throw IllegalStateException("Missing source manga: $mangaSource")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,23 +182,24 @@ class MergedSource : HttpSource() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class UrlConfig(
|
data class UrlConfig(
|
||||||
@SerializedName("s")
|
@SerializedName("s")
|
||||||
val source: Long,
|
val source: Long,
|
||||||
@SerializedName("u")
|
@SerializedName("u")
|
||||||
val url: String,
|
val url: String,
|
||||||
@SerializedName("m")
|
@SerializedName("m")
|
||||||
val mangaUrl: String
|
val mangaUrl: String
|
||||||
)
|
)
|
||||||
|
|
||||||
fun Page.copyWithUrl(newUrl: String) = Page(
|
fun Page.copyWithUrl(newUrl: String) = Page(
|
||||||
index,
|
index,
|
||||||
newUrl,
|
newUrl,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
uri
|
uri
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lang = "all"
|
override val lang = "all"
|
||||||
override val supportsLatest = false
|
override val supportsLatest = false
|
||||||
override val name = "MergedSource"
|
override val name = "MergedSource"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user