MMRCMS update (#1789)

MMRCMS update
This commit is contained in:
Mike 2019-11-16 10:06:54 -05:00 committed by arkon
parent 97ac680c51
commit 77ed2e844b
4 changed files with 103 additions and 82 deletions

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: My Manga Reader CMS (Many sources)'
pkgNameSuffix = 'all.mmrcms'
extClass = '.MyMangaReaderCMSSources'
extVersionCode = 22
extVersionCode = 23
libVersion = '1.2'
}

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.extension.all.mmrcms
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.os.Build
import com.google.gson.Gson
@ -34,7 +35,7 @@ class Generator {
var number = 1
sources.forEach {
try {
var map = mutableMapOf<String, Any>()
val map = mutableMapOf<String, Any>()
map["language"] = it.first
map["name"] = it.second
map["base_url"] = it.third
@ -47,7 +48,7 @@ class Generator {
parseCategories = parseCategories(advancedSearchDocument)
}
val homePageDocument = getDocument("${it.third}")!!
val homePageDocument = getDocument(it.third)!!
val itemUrl = getItemUrl(homePageDocument)
@ -109,11 +110,28 @@ class Generator {
}
private fun getDocument(url: String, printStackTrace: Boolean = true): Document? {
try {
val serverCheck = arrayOf("cloudflare-nginx", "cloudflare")
val response = getOkHttpClient().newCall(Request.Builder().url(url).build()).execute()
if (response.code() == 200) {
return Jsoup.parse(response.body()?.string())
try {
val request = Request.Builder().url(url)
getOkHttpClient().newCall(request.build()).execute().let { response ->
// Bypass Cloudflare ("Please wait 5 seconds" page)
if (response.code() == 503 && response.header("Server") in serverCheck) {
var cookie = "${response.header("Set-Cookie")!!.substringBefore(";")}; "
Jsoup.parse(response.body()!!.string()).let { document ->
val path = document.select("[id=\"challenge-form\"]").attr("action")
val chk = document.select("[name=\"s\"]").attr("value")
getOkHttpClient().newCall(Request.Builder().url("$url/$path?s=$chk").build()).execute().let { solved ->
cookie += solved.header("Set-Cookie")!!.substringBefore(";")
request.addHeader("Cookie", cookie).build().let {
return Jsoup.parse(getOkHttpClient().newCall(it).execute().body()?.string())
}
}
}
}
if (response.code() == 200) {
return Jsoup.parse(response.body()?.string())
}
}
} catch (e: Exception) {
if (printStackTrace) {
@ -129,9 +147,9 @@ class Generator {
if (elements.isEmpty()) {
return mutableListOf()
}
var array = mutableListOf<Map<String, String>>()
val array = mutableListOf<Map<String, String>>()
elements.forEach {
var map = mutableMapOf<String, String>()
val map = mutableMapOf<String, String>()
map["id"] = it.attr("href").substringAfterLast("/")
map["name"] = it.text()
array.add(map)
@ -148,19 +166,19 @@ class Generator {
}
private fun supportsLatest(third: String): Boolean {
getDocument("$third/filterList?page=1&sortBy=last_release&asc=false", false) ?: return false
return true
val document = getDocument("$third/filterList?page=1&sortBy=last_release&asc=false", false) ?: return false
return document.select("div[class^=col-sm], div.col-xs-6").isNotEmpty()
}
private fun parseCategories(document: Document): MutableList<Map<String, String>> {
var array = mutableListOf<Map<String, String>>()
var elements = document.select("select[name^=categories] option")
val array = mutableListOf<Map<String, String>>()
val elements = document.select("select[name^=categories] option")
if (elements.size == 0) {
return mutableListOf()
}
var id = 1
elements.forEach {
var map = mutableMapOf<String, String>()
val map = mutableMapOf<String, String>()
map["id"] = id.toString()
map["name"] = it.text()
array.add(map)
@ -173,10 +191,12 @@ class Generator {
@Throws(Exception::class)
private fun getOkHttpClient(): OkHttpClient {
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
}
@SuppressLint("TrustAllX509TrustManager")
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
}
@ -211,10 +231,7 @@ class Generator {
Triple("en", "Fallen Angels", "http://manga.fascans.com"),
Triple("en", "Hatigarm Scans", "https://hatigarmscans.net"),
Triple("en", "Mangawww Reader", "http://mangawww.club"),
Triple("en", "ZXComic", "http://zxcomic.com"),
Triple("en", "White Cloud Pavilion", "http://www.whitecloudpavilion.com/manga/free"),
Triple("en", "MangaTreat Scans", "http://www.mangatreat.com"),
Triple("es", "SOS Scanlation", "https://sosscanlation.com"),
Triple("fr", "Scan FR", "http://www.scan-fr.io"),
Triple("fr", "Scan VF", "https://www.scan-vf.co"),
Triple("id", "Komikid", "http://www.komikid.com"),
@ -227,16 +244,20 @@ class Generator {
Triple("tr", "MangaHanta", "http://mangahanta.com"),
Triple("vi", "Fallen Angels Scans", "http://truyen.fascans.com"),
Triple("es", "LeoManga", "https://leomanga.me"),
Triple("es", "submanga", "https://submanga.online"),
Triple("es", "submanga", "https://submanga.li"),
Triple("es", "Mangadoor", "https://mangadoor.com"),
Triple("es", "Mangas.pw", "https://mangas.pw"),
Triple("es", "Tumangaonline.co", "http://tumangaonline.co"),
Triple("bg", "Utsukushii", "https://manga.utsukushii-bg.com"),
//NOTE: THIS SOURCE CONTAINS A CUSTOM LANGUAGE SYSTEM (which will be ignored)!
Triple("other", "HentaiShark", "https://www.hentaishark.com"))
//Now uses wpmanga
//Changed CMS
//Triple("en", "MangaTreat Scans", "http://www.mangatreat.com"),
//Triple("en", "Chibi Manga Reader", "http://www.cmreader.info"),
//Blocks bots (like this one)
//Triple("tr", "Epikmanga", "http://www.epikmanga.com"),
//Went offline
//Triple("en", "ZXComic", "http://zxcomic.com"),
//Triple("es", "SOS Scanlation", "https://sosscanlation.com"),
//Triple("es", "MangaCasa", "https://mangacasa.com"))
//Triple("ja", "RAW MANGA READER", "https://rawmanga.site"),
//Triple("ar", "Manga FYI", "http://mangafyi.com/manga/arabic"),

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.extension.all.mmrcms
import android.annotation.SuppressLint
import android.net.Uri
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.get
@ -31,7 +32,12 @@ class MyMangaReaderCMSSource(override val lang: String,
override val client: OkHttpClient = network.cloudflareClient
override fun popularMangaRequest(page: Int) = GET("$baseUrl/filterList?page=$page&sortBy=views&asc=false", headers)
override fun popularMangaRequest(page: Int): Request {
return when (name) {
"Utsukushii" -> GET("$baseUrl/manga-list", headers)
else -> GET("$baseUrl/filterList?page=$page&sortBy=views&asc=false", headers)
}
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
//Query overrides everything
val url: Uri.Builder
@ -74,7 +80,11 @@ class MyMangaReaderCMSSource(override val lang: String,
private fun internalMangaParse(response: Response): MangasPage {
val document = response.asJsoup()
return MangasPage(document.select("div[class^=col-sm], div.col-xs-6").map {
val internalMangaSelector = when (name) {
"Utsukushii" -> "div.content div.col-sm-6"
else -> "div[class^=col-sm], div.col-xs-6"
}
return MangasPage(document.select(internalMangaSelector).map {
SManga.create().apply {
val urlElement = it.getElementsByClass("chart-title")
if (urlElement.size == 0) {
@ -86,34 +96,24 @@ class MyMangaReaderCMSSource(override val lang: String,
title = urlElement.text().trim()
}
val cover = it.select(".media-left img").attr("src")
thumbnail_url =
if (cover.isEmpty()) {
coverGuess(it.select("img").attr("src"), url)
} else {
coverGuess(cover, url)
}
it.select("img").let { img ->
thumbnail_url = when {
it.hasAttr("data-background-image") -> it.attr("data-background-image") // Utsukushii
img.hasAttr("data-src") -> coverGuess(img.attr("abs:data-src"), url)
else -> coverGuess(img.attr("abs:src"), url)
}
}
}
}, document.select(".pagination a[rel=next]").isNotEmpty())
}
// Guess thumbnails on broken websites
private fun coverGuess(url: String?, mangaUrl: String): String {
// Guess thumbnails on broken websites
if (url != null && url.isNotBlank()) {
if (url.startsWith("//")) {
return "$baseUrl/uploads/manga/${url.substringBeforeLast("/cover/").substringAfter("/manga/")}/cover/cover_250x350.jpg"
}
if (url.endsWith("no-image.png")) {
return "$baseUrl/uploads/manga/${mangaUrl?.substringAfterLast('/')}/cover/cover_250x350.jpg"
}
if (url.startsWith("/uploads/")) {
return "$baseUrl$url"
}
return url
private fun coverGuess(url: String, mangaUrl: String): String {
return if (url.endsWith("no-image.png")) {
"$baseUrl/uploads/manga/${mangaUrl.substringAfterLast('/')}/cover/cover_250x350.jpg"
} else {
url
}
return ""
}
private fun getUrlWithoutBaseUrl(newUrl: String): String {
@ -129,7 +129,7 @@ class MyMangaReaderCMSSource(override val lang: String,
val builtUrl = parsedNewUrl.buildUpon().path("/")
newPathSegments.forEach { builtUrl.appendPath(it) }
var out = builtUrl.build().encodedPath
var out = builtUrl.build().encodedPath!!
if (parsedNewUrl.encodedQuery != null)
out += "?" + parsedNewUrl.encodedQuery
if (parsedNewUrl.encodedFragment != null)
@ -138,19 +138,20 @@ class MyMangaReaderCMSSource(override val lang: String,
return out
}
@SuppressLint("DefaultLocale")
override fun mangaDetailsParse(response: Response) = SManga.create().apply {
val document = response.asJsoup()
title = document.getElementsByClass("widget-title").text().trim()
thumbnail_url = coverGuess(document.select(".row .img-responsive").attr("src"), document.location())
thumbnail_url = coverGuess(document.select(".row .img-responsive").attr("abs:src"), document.location())
description = document.select(".row .well p").text().trim()
val detailAuthor = setOf<String>("author(s)","autor(es)","auteur(s)","著作","yazar(lar)","mangaka(lar)","pengarang/penulis","pengarang","penulis","autor","المؤلف","перевод")
val detailArtist = setOf<String>("artist(s)","artiste(s)","sanatçi(lar)","artista(s)","artist(s)/ilustrator","الرسام","seniman")
val detailGenre = setOf<String>("categories","categorías","catégories","ジャンル","kategoriler","categorias","kategorie","التصنيفات","жанр","kategori" )
val detailStatus = setOf<String>("status","statut","estado","状態","durum","الحالة","статус")
val detailStatusComplete = setOf<String>("complete","مكتملة","complet","completo")
val detailStatusOngoing = setOf<String>("ongoing","مستمرة","en cours","em lançamento")
val detailDescription = setOf<String>("description","resumen")
val detailAuthor = setOf("author(s)","autor(es)","auteur(s)","著作","yazar(lar)","mangaka(lar)","pengarang/penulis","pengarang","penulis","autor","المؤلف","перевод")
val detailArtist = setOf("artist(s)","artiste(s)","sanatçi(lar)","artista(s)","artist(s)/ilustrator","الرسام","seniman")
val detailGenre = setOf("categories","categorías","catégories","ジャンル","kategoriler","categorias","kategorie","التصنيفات","жанр","kategori" )
val detailStatus = setOf("status","statut","estado","状態","durum","الحالة","статус")
val detailStatusComplete = setOf("complete","مكتملة","complet","completo")
val detailStatusOngoing = setOf("ongoing","مستمرة","en cours","em lançamento")
val detailDescription = setOf("description","resumen")
var cur: String? = null
for (element in document.select(".row .dl-horizontal").select("dt,dd")) {
@ -203,7 +204,7 @@ class MyMangaReaderCMSSource(override val lang: String,
/**
* Returns the Jsoup selector that returns a list of [Element] corresponding to each chapter.
*/
fun chapterListSelector() = "ul[class^=chapters] > li:not(.btn), table.table tr"
private fun chapterListSelector() = "ul[class^=chapters] > li:not(.btn), table.table tr"
//Some websites add characters after "chapters" thus the need of checking classes that starts with "chapters"
/**
@ -322,8 +323,8 @@ class MyMangaReaderCMSSource(override val lang: String,
* If `firstIsUnspecified` is set to true, if the first entry is selected, nothing will be appended on the the URI.
*/
//vals: <name, display>
open class UriSelectFilter(displayName: String, val uriParam: String, val vals: Array<Pair<String, String>>,
val firstIsUnspecified: Boolean = true,
open class UriSelectFilter(displayName: String, private val uriParam: String, private val vals: Array<Pair<String, String>>,
private val firstIsUnspecified: Boolean = true,
defaultValue: Int = 0) :
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray(), defaultValue), UriFilter {
override fun addToUri(uri: Uri.Builder) {
@ -340,7 +341,7 @@ class MyMangaReaderCMSSource(override val lang: String,
class SortFilter : Filter.Sort("Sort",
sortables.map { it.second }.toTypedArray(),
Filter.Sort.Selection(0, true)), UriFilter {
Selection(0, true)), UriFilter {
override fun addToUri(uri: Uri.Builder) {
uri.appendQueryParameter("sortBy", sortables[state!!.index].first)
uri.appendQueryParameter("asc", state!!.ascending.toString())