package eu.kanade.tachiyomi.multisrc.monochrome import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage 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 kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import okhttp3.Headers import okhttp3.Response import rx.Observable import uy.kohesive.injekt.injectLazy open class MonochromeCMS( override val name: String, override val baseUrl: String, override val lang: String, ) : HttpSource() { override val supportsLatest = false protected open val apiUrl by lazy { baseUrl.replaceFirst("://", "://api.") } private val json by injectLazy() override fun headersBuilder() = Headers.Builder().set("Referer", "$baseUrl/") override fun fetchPopularManga(page: Int) = fetchSearchManga(page, "", FilterList()) override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$apiUrl/manga?limit=10&offset=${10 * (page - 1)}&title=$query", headers) override fun searchMangaParse(response: Response) = response.decode().let { MangasPage(it.map(::mangaFromAPI), it.hasNext) } override fun fetchSearchManga( page: Int, query: String, filters: FilterList, ): Observable { if (!query.startsWith(UUID_QUERY)) { return super.fetchSearchManga(page, query, filters) } val req = GET("$apiUrl/manga/${query.substringAfter(UUID_QUERY)}") return client.newCall(req).asObservableSuccess().map { MangasPage(listOf(mangaFromAPI(it.decode())), false) } } override fun fetchMangaDetails(manga: SManga) = Observable.just(manga.apply { initialized = true })!! override fun chapterListRequest(manga: SManga) = GET("$apiUrl/manga/${manga.url}/chapters", headers) override fun fetchChapterList(manga: SManga) = client.newCall(chapterListRequest(manga)).asObservableSuccess().map { it.decode>().map { ch -> SChapter.create().apply { name = ch.title url = manga.url + ch.parts chapter_number = ch.number date_upload = ch.timestamp scanlator = ch.scanGroup } } }!! override fun fetchPageList(chapter: SChapter): Observable> { val (uuid, version, length) = chapter.url.split('|') val pages = IntRange(1, length.toInt()).map { Page(it, "", "$apiUrl/media/$uuid/$it.jpg?version=$version") } return Observable.just(pages) } override fun getMangaUrl(manga: SManga) = "$baseUrl/manga/${manga.url}" override fun getChapterUrl(chapter: SChapter) = "$baseUrl/chapters/${chapter.url.subSequence(37, 73)}" private fun mangaFromAPI(manga: Manga) = SManga.create().apply { url = manga.id title = manga.title author = manga.author artist = manga.artist description = manga.description thumbnail_url = apiUrl + manga.cover status = when (manga.status) { "ongoing", "hiatus" -> SManga.ONGOING "completed", "cancelled" -> SManga.COMPLETED else -> SManga.UNKNOWN } } private inline fun Response.decode() = json.decodeFromString(body.string()) override fun popularMangaRequest(page: Int) = throw UnsupportedOperationException() override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() override fun mangaDetailsRequest(manga: SManga) = throw UnsupportedOperationException() override fun popularMangaParse(response: Response) = throw UnsupportedOperationException() override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException() override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException() override fun chapterListParse(response: Response) = throw UnsupportedOperationException() override fun pageListRequest(chapter: SChapter) = throw UnsupportedOperationException() override fun pageListParse(response: Response) = throw UnsupportedOperationException() override fun imageUrlParse(response: Response) = throw UnsupportedOperationException() }