mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	unhide and begin working on merged sources
This commit is contained in:
		| @@ -1,22 +1,31 @@ | ||||
| package eu.kanade.tachiyomi.source.online.all | ||||
|  | ||||
| import android.util.Log | ||||
| import com.elvishew.xlog.XLog | ||||
| import com.github.salomonbrys.kotson.fromJson | ||||
| import com.google.gson.Gson | ||||
| 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.models.Manga | ||||
| import eu.kanade.tachiyomi.source.Source | ||||
| 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 exh.MERGED_SOURCE_ID | ||||
| import exh.util.await | ||||
| import hu.akarnokd.rxjava.interop.RxJavaInterop | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.GlobalScope | ||||
| 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.asSingle | ||||
| import okhttp3.Response | ||||
| @@ -43,63 +52,74 @@ class MergedSource : HttpSource() { | ||||
|     override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException() | ||||
|  | ||||
|     override fun fetchMangaDetails(manga: SManga): Observable<SManga> { | ||||
|         return readMangaConfig(manga).load(db, sourceManager).take(1).map { loaded -> | ||||
|             SManga.create().apply { | ||||
|                 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()) | ||||
|         return RxJavaInterop.toV1Observable( | ||||
|             readMangaConfig(manga).load(db, sourceManager).take(1).map { loaded -> | ||||
|                 SManga.create().apply { | ||||
|                     this.copyFrom(loaded.manga) | ||||
|                     url = manga.url | ||||
|                 } | ||||
|             }.buffer().map { it.await() }.toList().flatten() | ||||
|         }.asSingle(Dispatchers.IO).toV1Single().toObservable() | ||||
|             }.asFlowable() | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     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 chapterListParse(response: Response) = throw UnsupportedOperationException() | ||||
|  | ||||
|     override fun fetchPageList(chapter: SChapter): Observable<List<Page>> { | ||||
|         val config = readUrlConfig(chapter.url) | ||||
|         val source = sourceManager.getOrStub(config.source) | ||||
|         return source.fetchPageList(SChapter.create().apply { | ||||
|             copyFrom(chapter) | ||||
|             url = config.url | ||||
|         }).map { pages -> | ||||
|         return source.fetchPageList( | ||||
|             SChapter.create().apply { | ||||
|                 copyFrom(chapter) | ||||
|                 url = config.url | ||||
|             } | ||||
|         ).map { pages -> | ||||
|             pages.map { page -> | ||||
|                 page.copyWithUrl(writeUrlConfig(UrlConfig(config.source, page.url, config.mangaUrl))) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun fetchImageUrl(page: Page): Observable<String> { | ||||
|         val config = readUrlConfig(page.url) | ||||
|         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)) | ||||
|     } | ||||
|  | ||||
|     override fun pageListParse(response: Response) = throw UnsupportedOperationException() | ||||
|     override fun imageUrlParse(response: Response) = throw UnsupportedOperationException() | ||||
|  | ||||
|     override fun fetchImage(page: Page): Observable<Response> { | ||||
|         val config = readUrlConfig(page.url) | ||||
|         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)) | ||||
|     } | ||||
|  | ||||
|     override fun prepareNewChapter(chapter: SChapter, manga: SManga) { | ||||
|         val chapterConfig = readUrlConfig(chapter.url) | ||||
|         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 { | ||||
|             this.copyFrom(manga) | ||||
|             url = chapterConfig.mangaUrl | ||||
| @@ -107,40 +127,48 @@ class MergedSource : HttpSource() { | ||||
|         chapter.url = chapterConfig.url | ||||
|         source.prepareNewChapter(chapter, copiedManga) | ||||
|         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}" | ||||
|     } | ||||
|  | ||||
|     fun readMangaConfig(manga: SManga): MangaConfig { | ||||
|         return MangaConfig.readFromUrl(gson, manga.url) | ||||
|     } | ||||
|  | ||||
|     fun readUrlConfig(url: String): UrlConfig { | ||||
|         return gson.fromJson(url) | ||||
|     } | ||||
|  | ||||
|     fun writeUrlConfig(urlConfig: UrlConfig): String { | ||||
|         return gson.toJson(urlConfig) | ||||
|     } | ||||
|  | ||||
|     data class LoadedMangaSource(val source: Source, val manga: Manga) | ||||
|     data class MangaSource( | ||||
|             @SerializedName("s") | ||||
|             val source: Long, | ||||
|             @SerializedName("u") | ||||
|             val url: String | ||||
|         @SerializedName("s") | ||||
|         val source: Long, | ||||
|         @SerializedName("u") | ||||
|         val url: String | ||||
|     ) { | ||||
|         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) | ||||
|             return LoadedMangaSource(source, manga) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     data class MangaConfig( | ||||
|             @SerializedName("c") | ||||
|             val children: List<MangaSource> | ||||
|         @SerializedName("c") | ||||
|         val children: List<MangaSource> | ||||
|     ) { | ||||
|         fun load(db: DatabaseHelper, sourceManager: SourceManager): Flow<LoadedMangaSource> { | ||||
|             return children.asFlow().map { mangaSource -> | ||||
|                 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( | ||||
|             @SerializedName("s") | ||||
|             val source: Long, | ||||
|             @SerializedName("u") | ||||
|             val url: String, | ||||
|             @SerializedName("m") | ||||
|             val mangaUrl: String | ||||
|         @SerializedName("s") | ||||
|         val source: Long, | ||||
|         @SerializedName("u") | ||||
|         val url: String, | ||||
|         @SerializedName("m") | ||||
|         val mangaUrl: String | ||||
|     ) | ||||
|  | ||||
|     fun Page.copyWithUrl(newUrl: String) = Page( | ||||
|             index, | ||||
|             newUrl, | ||||
|             imageUrl, | ||||
|             uri | ||||
|         index, | ||||
|         newUrl, | ||||
|         imageUrl, | ||||
|         uri | ||||
|     ) | ||||
|  | ||||
|     override val lang = "all" | ||||
|     override val supportsLatest = false | ||||
|     override val name = "MergedSource" | ||||
| } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user