GANMA: remove unused code (#1407)

This commit is contained in:
stevenyomi 2024-02-20 02:45:16 +08:00 committed by GitHub
parent 2f8abf78b3
commit f56a1e1bcb
5 changed files with 7 additions and 236 deletions

View File

@ -1,6 +1,6 @@
ext {
extName = 'GANMA!'
extClass = '.GanmaFactory'
extClass = '.Ganma'
extVersionCode = 2
}

View File

@ -1,11 +1,8 @@
package eu.kanade.tachiyomi.extension.ja.ganma
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservable
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
@ -13,16 +10,16 @@ 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.json.Json
import kotlinx.serialization.json.decodeFromStream
import okhttp3.Request
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.injectLazy
open class Ganma : HttpSource(), ConfigurableSource {
override val id = sourceId
override val name = sourceName
override val lang = sourceLang
override val versionId = sourceVersionId
class Ganma : HttpSource() {
override val name = "GANMA!"
override val lang = "ja"
override val baseUrl = "https://ganma.jp"
override val supportsLatest = true
@ -112,11 +109,5 @@ open class Ganma : HttpSource(), ConfigurableSource {
json.decodeFromStream<Result<T>>(it.body.byteStream()).root
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
EditTextPreference(screen.context).apply {
key = METADATA_PREF
title = "Metadata (Debug)"
setDefaultValue("")
}.let { screen.addPreference(it) }
}
val json: Json by injectLazy()
}

View File

@ -1,133 +0,0 @@
package eu.kanade.tachiyomi.extension.ja.ganma
import android.widget.Toast
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
class GanmaApp(private val metadata: Metadata) : Ganma() {
override val client = network.client.newBuilder()
.cookieJar(Cookies(metadata.baseUrl.toHttpUrl().host, metadata.cookieName))
.build()
private val appHeaders: Headers = Headers.Builder().apply {
add("User-Agent", metadata.userAgent)
add("X-From", metadata.baseUrl)
}.build()
override fun chapterListRequest(manga: SManga): Request {
checkSession()
return GET(metadata.baseUrl + String.format(metadata.magazineUrl, manga.url.mangaId()), appHeaders)
}
override fun List<SChapter>.sortedDescending() = this
override fun pageListRequest(chapter: SChapter): Request {
checkSession()
val (mangaId, chapterId) = chapter.url.chapterDir()
return GET(metadata.baseUrl + String.format(metadata.storyUrl, mangaId, chapterId), appHeaders)
}
override fun pageListParse(chapter: SChapter, response: Response): List<Page> =
try {
response.parseAs<AppStory>().toPageList()
} catch (e: Exception) {
throw Exception("Chapter not available!")
}
private fun checkSession() {
val expiration = preferences.getLong(SESSION_EXPIRATION_PREF, 0)
if (System.currentTimeMillis() + 60 * 1000 <= expiration) return // at least 1 minute
var field1 = preferences.getString(TOKEN_FIELD1_PREF, "")!!
var field2 = preferences.getString(TOKEN_FIELD2_PREF, "")!!
if (field1.isEmpty() || field2.isEmpty()) {
val response = client.newCall(POST(metadata.baseUrl + metadata.tokenUrl, appHeaders)).execute()
val token: Map<String, String> = response.parseAs()
field1 = token[metadata.tokenField1]!!
field2 = token[metadata.tokenField2]!!
}
val requestBody = FormBody.Builder().apply {
add(metadata.tokenField1, field1)
add(metadata.tokenField2, field2)
}.build()
val response = client.newCall(POST(metadata.baseUrl + metadata.sessionUrl, appHeaders, requestBody)).execute()
val session: Session = response.parseAs()
preferences.edit().apply {
putString(TOKEN_FIELD1_PREF, field1)
putString(TOKEN_FIELD2_PREF, field2)
putLong(SESSION_EXPIRATION_PREF, session.expire)
}.apply()
}
private fun clearSession(clearToken: Boolean) {
preferences.edit().apply {
putString(SESSION_PREF, "")
putLong(SESSION_EXPIRATION_PREF, 0)
if (clearToken) {
putString(TOKEN_FIELD1_PREF, "")
putString(TOKEN_FIELD2_PREF, "")
}
}.apply()
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
super.setupPreferenceScreen(screen)
SwitchPreferenceCompat(screen.context).apply {
title = "Clear session"
setOnPreferenceChangeListener { _, _ ->
clearSession(clearToken = false)
Toast.makeText(screen.context, "Session cleared", Toast.LENGTH_SHORT).show()
false
}
}.let { screen.addPreference(it) }
SwitchPreferenceCompat(screen.context).apply {
title = "Clear token"
setOnPreferenceChangeListener { _, _ ->
clearSession(clearToken = true)
Toast.makeText(screen.context, "Token cleared", Toast.LENGTH_SHORT).show()
false
}
}.let { screen.addPreference(it) }
}
class Cookies(private val host: String, private val name: String) : CookieJar {
override fun loadForRequest(url: HttpUrl): List<Cookie> {
if (url.host != host) return emptyList()
val cookie = Cookie.Builder().apply {
name(name)
value(preferences.getString(SESSION_PREF, "")!!)
domain(host)
}.build()
return listOf(cookie)
}
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
if (url.host != host) return
for (cookie in cookies) {
if (cookie.name == name) {
preferences.edit().putString(SESSION_PREF, cookie.value).apply()
}
}
}
}
companion object {
private const val TOKEN_FIELD1_PREF = "TOKEN_FIELD1"
private const val TOKEN_FIELD2_PREF = "TOKEN_FIELD2"
private const val SESSION_PREF = "SESSION"
private const val SESSION_EXPIRATION_PREF = "SESSION_EXPIRATION"
}
}

View File

@ -166,42 +166,3 @@ class Directory(
Page(i, imageUrl = "$baseUrl$file?$token")
}
}
@Serializable
class AppStory(val pages: List<AppPage>) {
fun toPageList(): List<Page> {
val result = ArrayList<Page>(pages.size)
pages.forEach {
if (it.imageURL != null) {
result.add(Page(result.size, imageUrl = it.imageURL.url))
} else if (it.afterwordImageURL != null) {
result.add(Page(result.size, imageUrl = it.afterwordImageURL.url))
}
}
return result
}
}
@Serializable
class AppPage(
val imageURL: File? = null,
val afterwordImageURL: File? = null,
)
// Please keep the data private to support the site,
// otherwise they might change their APIs.
@Serializable
class Metadata(
val userAgent: String,
val baseUrl: String,
val tokenUrl: String,
val tokenField1: String,
val tokenField2: String,
val sessionUrl: String,
val cookieName: String,
val magazineUrl: String,
val storyUrl: String,
)
@Serializable
class Session(val expire: Long)

View File

@ -1,48 +0,0 @@
package eu.kanade.tachiyomi.extension.ja.ganma
import android.app.Application
import android.content.SharedPreferences
import android.util.Base64
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.security.MessageDigest
// source ID needed before class construction
// generated by running main() below
const val sourceId = 8045942616403978870
const val sourceName = "GANMA!"
const val sourceLang = "ja"
const val sourceVersionId = 1 // != extension version code
const val METADATA_PREF = "METADATA"
val json: Json = Injekt.get()
val preferences: SharedPreferences =
Injekt.get<Application>().getSharedPreferences("source_$sourceId", 0x0000)
class GanmaFactory : SourceFactory {
override fun createSources(): List<Source> {
val source = try {
val metadata = preferences.getString(METADATA_PREF, "")!!
.also { if (it.isEmpty()) throw Exception() }
.let { Base64.decode(it.toByteArray(), Base64.DEFAULT) }
GanmaApp(json.decodeFromString(String(metadata)))
} catch (e: Exception) {
Ganma()
}
return listOf(source)
}
}
fun main() {
println(getSourceId()) // unfortunately there's no constexpr in Kotlin
}
fun getSourceId() = run { // copied from HttpSource
val key = "${sourceName.lowercase()}/$sourceLang/$sourceVersionId"
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
}