Manga Cross, Comic Gamma: refactor (#12186)

* Manga Cross: refactor

* Comic Gamma: refactor
This commit is contained in:
kasperskier 2022-06-13 22:43:54 +08:00 committed by GitHub
parent 5086c99911
commit 08fd67eff6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 39 deletions

View File

@ -22,7 +22,7 @@ open class ComicGamma(
) : ParsedHttpSource() { ) : ParsedHttpSource() {
override val supportsLatest = true override val supportsLatest = true
override val client = network.client.newBuilder().addInterceptor(PtImgInterceptor()).build() override val client = network.client.newBuilder().addInterceptor(PtImgInterceptor).build()
override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/", headers) override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/", headers)
override fun popularMangaNextPageSelector(): String? = null override fun popularMangaNextPageSelector(): String? = null
@ -99,13 +99,12 @@ open class ComicGamma(
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.") override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
// for thread-safety (of subclasses) // for thread-safety
private val JST_FORMAT_DESC = getJSTFormat() private val JST_FORMAT_DESC = getJSTFormat()
private val JST_FORMAT_LIST = getJSTFormat() private val JST_FORMAT_LIST = getJSTFormat()
private val LOCAL_FORMAT_DESC = getDateTimeInstance() private val LOCAL_FORMAT_DESC = getDateTimeInstance()
private val LOCAL_FORMAT_LIST = getDateTimeInstance() private val LOCAL_FORMAT_LIST = getDateTimeInstance()
companion object {
private fun SimpleDateFormat.parseJST(date: String) = parse(date)?.apply { private fun SimpleDateFormat.parseJST(date: String) = parse(date)?.apply {
time += 12 * 3600 * 1000 // updates at 12 noon time += 12 * 3600 * 1000 // updates at 12 noon
} }
@ -114,5 +113,4 @@ open class ComicGamma(
SimpleDateFormat("yyyy年M月dd日(E)", Locale.JAPANESE).apply { SimpleDateFormat("yyyy年M月dd日(E)", Locale.JAPANESE).apply {
timeZone = TimeZone.getTimeZone("GMT+09:00") timeZone = TimeZone.getTimeZone("GMT+09:00")
} }
}
} }

View File

@ -6,7 +6,7 @@ import generator.ThemeSourceGenerator
class ComicGammaGenerator : ThemeSourceGenerator { class ComicGammaGenerator : ThemeSourceGenerator {
override val themeClass = "ComicGamma" override val themeClass = "ComicGamma"
override val themePkg = "comicgamma" override val themePkg = "comicgamma"
override val baseVersionCode = 2 override val baseVersionCode = 3
override val sources = listOf( override val sources = listOf(
SingleLang( SingleLang(
name = "Web Comic Gamma", name = "Web Comic Gamma",

View File

@ -13,7 +13,7 @@ import okhttp3.ResponseBody.Companion.toResponseBody
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
class PtImgInterceptor : Interceptor { object PtImgInterceptor : Interceptor {
private val json: Json by injectLazy() private val json: Json by injectLazy()
@ -40,7 +40,9 @@ class PtImgInterceptor : Interceptor {
val output = ByteArrayOutputStream() val output = ByteArrayOutputStream()
result.compress(Bitmap.CompressFormat.JPEG, 90, output) result.compress(Bitmap.CompressFormat.JPEG, 90, output)
val responseBody = output.toByteArray().toResponseBody("image/jpeg".toMediaType()) val responseBody = output.toByteArray().toResponseBody(jpegMediaType)
return imgResponse.newBuilder().body(responseBody).build() return imgResponse.newBuilder().body(responseBody).build()
} }
private val jpegMediaType = "image/jpeg".toMediaType()
} }

View File

@ -6,7 +6,7 @@ ext {
extName = 'Manga Cross' extName = 'Manga Cross'
pkgNameSuffix = 'ja.mangacross' pkgNameSuffix = 'ja.mangacross'
extClass = '.MangaCross' extClass = '.MangaCross'
extVersionCode = 4 extVersionCode = 5
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -10,15 +10,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.serialization.SerializationException import kotlinx.serialization.SerializationException
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import okhttp3.Response import okhttp3.Response
import rx.Observable import rx.Observable
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import kotlin.concurrent.thread import kotlin.concurrent.thread
const val maxEntries = 9999
class MangaCross : HttpSource() { class MangaCross : HttpSource() {
override val name = "Manga Cross" override val name = "Manga Cross"
override val lang = "ja" override val lang = "ja"
@ -27,17 +25,14 @@ class MangaCross : HttpSource() {
private val json: Json by injectLazy() private val json: Json by injectLazy()
override fun popularMangaRequest(page: Int) = GET("$baseUrl/api/comics.json?count=$maxEntries", headers) // Pagination does not work. 9999 is a dummy large number.
override fun popularMangaRequest(page: Int) = GET("$baseUrl/api/comics.json?count=9999", headers)
override fun popularMangaParse(response: Response) = MangasPage( override fun popularMangaParse(response: Response) =
json.decodeFromString<MCComicList>(response.body!!.string()).comics.map(MCComic::toSManga), MangasPage(response.parseAs<MCComicList>().comics.map { it.toSManga() }, false)
false // pagination does not work
)
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/api/episodes.json?page=$page", headers) override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/api/episodes.json?page=$page", headers)
override fun latestUpdatesParse(response: Response): MangasPage { override fun latestUpdatesParse(response: Response): MangasPage {
val result = json.decodeFromString<MCEpisodeList>(response.body!!.string()) val result: MCEpisodeList = response.parseAs()
return MangasPage(result.episodes.map { it.comic!!.toSManga() }, result.current_page < result.total_pages) return MangasPage(result.episodes.map { it.comic!!.toSManga() }, result.current_page < result.total_pages)
} }
@ -53,24 +48,21 @@ class MangaCross : HttpSource() {
override fun searchMangaParse(response: Response) = popularMangaParse(response) override fun searchMangaParse(response: Response) = popularMangaParse(response)
override fun fetchMangaDetails(manga: SManga): Observable<SManga> = override fun fetchMangaDetails(manga: SManga): Observable<SManga> =
client.newCall(chapterListRequest(manga)) client.newCall(chapterListRequest(manga)).asObservableSuccess()
.asObservableSuccess()
.map { mangaDetailsParse(it).apply { initialized = true } } .map { mangaDetailsParse(it).apply { initialized = true } }
// mangaDetailsRequest untouched in order to let WebView open web page instead of json // mangaDetailsRequest untouched in order to let WebView open web page instead of json
override fun mangaDetailsParse(response: Response) = override fun mangaDetailsParse(response: Response) = response.parseAs<MCComicDetails>().comic.toSManga()
json.decodeFromString<MCComicDetails>(response.body!!.string()).comic.toSManga()
override fun chapterListRequest(manga: SManga) = GET("$baseUrl/api${manga.url}.json", headers) override fun chapterListRequest(manga: SManga) = GET("$baseUrl/api${manga.url}.json", headers)
override fun chapterListParse(response: Response) = override fun chapterListParse(response: Response) = response.parseAs<MCComicDetails>().comic.toSChapterList()
json.decodeFromString<MCComicDetails>(response.body!!.string()).comic.toSChapterList()
override fun pageListParse(response: Response): List<Page> { override fun pageListParse(response: Response): List<Page> {
return try { return try {
json.decodeFromString<MCViewer>(response.body!!.string()).episode_pages.mapIndexed { i, it -> response.parseAs<MCViewer>().episode_pages.mapIndexed { i, it ->
Page(i, "", it.image.original_url) Page(i, imageUrl = it.image.original_url)
} }
} catch (e: SerializationException) { } catch (e: SerializationException) {
throw Exception("Chapter is no longer available!") throw Exception("Chapter is no longer available!")
@ -88,8 +80,8 @@ class MangaCross : HttpSource() {
thread { thread {
try { try {
val response = client.newCall(GET("$baseUrl/api/menus.json", headers)).execute() val response = client.newCall(GET("$baseUrl/api/menus.json", headers)).execute()
val filterList = json.decodeFromString<MCMenu>(response.body!!.string()).toFilterList() val filterList = response.parseAs<MCMenu>().toFilterList()
tags = listOf(Pair("None", null)) + filterList tags = listOf(Pair("All", null)) + filterList
} catch (e: Exception) { } catch (e: Exception) {
Log.e("MangaCross", "Failed to fetch filters ($e)") Log.e("MangaCross", "Failed to fetch filters ($e)")
} finally { } finally {
@ -105,12 +97,15 @@ class MangaCross : HttpSource() {
) else { ) else {
fetchTags() fetchTags()
FilterList( FilterList(
Filter.Header("Tags not fetched yet. Go back and retry."), Filter.Header("Fetching tags..."),
Filter.Header("Go back to previous screen and retry.")
) )
} }
private class TagFilter(displayName: String, private val tags: List<Pair<String, MCComicTag?>>) : private class TagFilter(name: String, private val tags: List<Pair<String, MCComicTag?>>) :
Filter.Select<String>(displayName, tags.map { it.first }.toTypedArray()) { Filter.Select<String>(name, tags.map { it.first }.toTypedArray()) {
fun getTag() = tags[state].second fun getTag() = tags[state].second
} }
private inline fun <reified T> Response.parseAs(): T = json.decodeFromStream(this.body!!.byteStream())
} }