Remove CatManga (#9800)

This commit is contained in:
Ivan Iskandar 2021-11-12 20:41:19 +07:00 committed by GitHub
parent 4b45240f36
commit ad0c8e2fec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 0 additions and 309 deletions

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="eu.kanade.tachiyomi.extension">
<application>
<activity
android:name=".en.catmanga.CatMangaUrlActivity"
android:excludeFromRecents="true"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="catmanga.org"
android:pathPattern="/series/..*"
android:scheme="https" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,12 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlinx-serialization'
ext {
extName = 'CatManga'
pkgNameSuffix = "en.catmanga"
extClass = '.CatManga'
extVersionCode = 7
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,57 +0,0 @@
package eu.kanade.tachiyomi.extension.en.catmanga
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.serialization.Serializable
@Serializable
data class CatSeries(
val alt_titles: List<String>,
val authors: List<String>,
val genres: List<String>,
val chapters: List<CatSeriesChapter>? = null,
val title: String,
val series_id: String,
val description: String,
val status: String,
val cover_art: CatSeriesCover,
val all_covers: List<CatSeriesCover>? = null
) {
fun toSManga() = this.let { series ->
SManga.create().apply {
url = "/series/${series.series_id}"
title = series.title
thumbnail_url = series.cover_art.source
author = series.authors.joinToString(", ")
description = series.description
genre = series.genres.joinToString(", ")
status = when (series.status) {
"ongoing" -> SManga.ONGOING
"completed" -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
if (alt_titles.isNotEmpty()) {
description += "\n\nAlternative titles:\n"
alt_titles.forEach {
description += "$it\n"
}
}
}
}
}
@Serializable
data class CatSeriesChapter(
val title: String? = null,
val groups: List<String>,
val number: Float,
val display_number: String? = null,
val volume: Int? = null
)
@Serializable
data class CatSeriesCover(
val source: String,
val width: Int,
val height: Int
)

View File

@ -1,179 +0,0 @@
package eu.kanade.tachiyomi.extension.en.catmanga
import android.app.Application
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 eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import rx.Observable
import uy.kohesive.injekt.injectLazy
@ExperimentalSerializationApi
class CatManga : HttpSource() {
private val application: Application by injectLazy()
override val name = "CatManga"
override val baseUrl = "https://catmanga.org"
override val supportsLatest = false
override val lang = "en"
private val json: Json by injectLazy()
private val allSeriesRequest = GET("$baseUrl/api/series/allSeries")
override fun popularMangaRequest(page: Int) = allSeriesRequest
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = allSeriesRequest
override fun chapterListRequest(manga: SManga): Request {
val seriesId = manga.url.substringAfter("/series/")
return GET("$baseUrl/api/series/$seriesId")
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return client.newCall(searchMangaRequest(page, query, filters))
.asObservableSuccess()
.map { response ->
val manga = json.decodeFromString<List<CatSeries>>(response.body!!.string())
.filter {
if (query.startsWith(SERIES_ID_SEARCH_PREFIX)) {
return@filter it.series_id.contains(query.removePrefix(SERIES_ID_SEARCH_PREFIX), true)
}
sequence { yieldAll(it.alt_titles); yield(it.title) }
.any { title -> title.contains(query, true) }
}
.map { it.toSManga() }
.toList()
MangasPage(manga, false)
}
}
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
val seriesId = manga.url.substringAfter("/series/")
return client.newCall(allSeriesRequest)
.asObservableSuccess()
.map { response ->
json.decodeFromString<List<CatSeries>>(response.body!!.string())
.find { it.series_id == seriesId }
?.toSManga() ?: manga
}
}
override fun chapterListParse(response: Response): List<SChapter> {
val series = json.decodeFromString<CatSeries>(response.body!!.string())
val seriesPrefs = application.getSharedPreferences("source_${id}_time_found:${series.series_id}", 0)
val seriesPrefsEditor = seriesPrefs.edit()
val chapters = series.chapters!!
.asReversed()
.map { chapter ->
val title = chapter.title ?: ""
val groups = chapter.groups.joinToString(", ")
val numberUrl = chapter.number.chapterNumberToUrlPath()
val displayNumber = chapter.display_number ?: numberUrl
SChapter.create().apply {
url = "/series/${series.series_id}/$numberUrl"
chapter_number = chapter.number
scanlator = groups
name = if (chapter.volume != null) {
"Vol.${chapter.volume} "
} else {
""
}
name += "Ch.$displayNumber"
if (title.isNotBlank()) {
name += " - $title"
}
// Save current time when a chapter is found for the first time, and reuse it on future
// checks to prevent manga entry without any new chapter bumped to the top of
// "Latest chapter" list when the library is updated.
val currentTimeMillis = System.currentTimeMillis()
if (!seriesPrefs.contains(numberUrl)) {
seriesPrefsEditor.putLong(numberUrl, currentTimeMillis)
}
date_upload = seriesPrefs.getLong(numberUrl, currentTimeMillis)
}
}
seriesPrefsEditor.apply()
return chapters
}
override fun popularMangaParse(response: Response): MangasPage {
val mangas = json.decodeFromString<List<CatSeries>>(response.body!!.string()).map { it.toSManga() }
return MangasPage(mangas, false)
}
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
return client.newCall(pageListRequest(chapter))
.asObservableSuccess()
.map {
val doc = it.asJsoup().getDataJsonObject()
val pages = if (doc["isFallback"]!!.jsonPrimitive.boolean) {
val buildId = doc["buildId"]!!.jsonPrimitive.content
val directRequest = GET("$baseUrl/_next/data/$buildId/${chapter.url}.json")
val directResponse = client.newCall(directRequest).execute()
json.parseToJsonElement(directResponse.body!!.string())
} else {
doc["props"]!!
}.jsonObject["pageProps"]!!.jsonObject["pages"]!!
json.decodeFromJsonElement<List<String>>(pages)
.mapIndexed { index, s -> Page(index, "", s) }
}
}
/**
* Returns json object of site data
*/
private fun Document.getDataJsonObject() = json.parseToJsonElement(getElementById("__NEXT_DATA__").html()).jsonObject
/**
* Returns string without decimal when it is not relevant
*/
private fun Float.chapterNumberToUrlPath(): String {
return if (toInt().toFloat() == this) toInt().toString() else toString()
}
override fun pageListParse(response: Response): List<Page> {
throw UnsupportedOperationException("Not used.")
}
override fun latestUpdatesRequest(page: Int): Request {
throw UnsupportedOperationException("Not used.")
}
override fun latestUpdatesParse(response: Response): MangasPage {
throw UnsupportedOperationException("Not used.")
}
override fun mangaDetailsParse(response: Response): SManga {
throw UnsupportedOperationException("Not used.")
}
override fun searchMangaParse(response: Response): MangasPage {
throw UnsupportedOperationException("Not used.")
}
override fun imageUrlParse(response: Response): String {
throw UnsupportedOperationException("Not used.")
}
companion object {
const val SERIES_ID_SEARCH_PREFIX = "series_id:"
}
}

View File

@ -1,38 +0,0 @@
package eu.kanade.tachiyomi.extension.en.catmanga
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.os.Bundle
import android.util.Log
import kotlin.system.exitProcess
/**
* Springboard that accepts https://catmanga.org/series/xxxxxx intents and redirects them to
* the main Tachiyomi process.
*/
class CatMangaUrlActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val pathSegments = intent?.data?.pathSegments
if (pathSegments != null && pathSegments.size > 1) {
val id = pathSegments[1]
val mainIntent = Intent().apply {
action = "eu.kanade.tachiyomi.SEARCH"
putExtra("query", "${CatManga.SERIES_ID_SEARCH_PREFIX}$id")
putExtra("filter", packageName)
}
try {
startActivity(mainIntent)
} catch (e: ActivityNotFoundException) {
Log.e("CatMangaUrlActivity", e.toString())
}
} else {
Log.e("CatMangaUrlActivity", "could not parse uri from intent $intent")
}
finish()
exitProcess(0)
}
}