parent
b8caf8e572
commit
a1a17c02d7
@ -1,13 +1,52 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.ar
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.generateUid
|
||||
import org.koitharu.kotatsu.parsers.util.mapChapters
|
||||
import org.koitharu.kotatsu.parsers.util.parseFailed
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.removeSuffix
|
||||
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
@MangaSourceParser("MANGA_LEK", "Manga-Lek", "ar")
|
||||
internal class MangaLekCom(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGA_LEK, "manga-lek.com") {
|
||||
override val listUrl = "mangalek/"
|
||||
override val postReq = true
|
||||
|
||||
override suspend fun loadChapters(mangaUrl: String, document: Document): List<MangaChapter> {
|
||||
val mangaId = document.select("div#manga-chapters-holder").attr("data-id")
|
||||
val url = "https://$domain/wp-admin/admin-ajax.php"
|
||||
val postData = "action=manga_get_chapters&manga=$mangaId"
|
||||
val doc = webClient.httpPost(url, postData).parseHtml()
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return doc.select(selectChapter).mapChapters { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = link,
|
||||
name = name,
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
dateText,
|
||||
),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@MangaSourceParser("FIRESCANS", "FireScans", "en")
|
||||
internal class FireScans(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.FIRESCANS, "firescans.xyz", 10) {
|
||||
|
||||
override fun parseMangaList(doc: Document): List<Manga> {
|
||||
return doc.select("div.row.c-tabs-item__content").ifEmpty {
|
||||
doc.select("div.page-item-detail")
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("h3 a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
|
||||
coverUrl = div.selectFirst("img")?.src().orEmpty(),
|
||||
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
|
||||
?: div.selectFirst(".manga-name"))?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
|
||||
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
in finished -> MangaState.FINISHED
|
||||
in abandoned -> MangaState.ABANDONED
|
||||
in paused -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val chapterProtector = doc.requireElementById("chapter-protector-data")
|
||||
val chapterProtectorHtml =
|
||||
context.decodeBase64(chapterProtector.attr("src").removePrefix("data:text/javascript;base64,"))
|
||||
.toString(Charsets.UTF_8)
|
||||
val password = chapterProtectorHtml.substringAfter("wpmangaprotectornonce='").substringBefore("';")
|
||||
val chapterData = JSONObject(
|
||||
chapterProtectorHtml.substringAfter("chapter_data='").substringBefore("';").replace("\\/", "/"),
|
||||
)
|
||||
val unsaltedCiphertext = context.decodeBase64(chapterData.getString("ct"))
|
||||
val salt = chapterData.getString("s").toString().decodeHex()
|
||||
val ciphertext = "Salted__".toByteArray(Charsets.UTF_8) + salt + unsaltedCiphertext
|
||||
val rawImgArray = CryptoAES(context).decrypt(context.encodeBase64(ciphertext), password)
|
||||
val imgArrayString = rawImgArray.filterNot { c -> c == '[' || c == ']' || c == '\\' || c == '"' }
|
||||
|
||||
return imgArrayString.split(",").map { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun String.decodeHex(): ByteArray {
|
||||
check(length % 2 == 0) { "Must have an even length" }
|
||||
|
||||
return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.es
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HOUSEMANGAS", "HouseMangas", "es")
|
||||
internal class HouseMangas(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HOUSEMANGAS, "housemangas.com")
|
||||
@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.es
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("LECTORUNM", "Lectorunm.life", "es")
|
||||
internal class Lectorunm(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.LECTORUNM, "lectorunm.life") {
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.es
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("RICHTOSCAN", "RichtoScan", "es")
|
||||
internal class RichtoScan(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.RICHTOSCAN, "richtoscan.com") {
|
||||
override val tagPrefix = "manga-generos/"
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("CVNSCAN", "CvnScan", "pt", ContentType.HENTAI)
|
||||
internal class CvnScan(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.CVNSCAN, "cvnscan.com")
|
||||
@ -0,0 +1,42 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.vi
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.generateUid
|
||||
import org.koitharu.kotatsu.parsers.util.mapChapters
|
||||
import org.koitharu.kotatsu.parsers.util.parseFailed
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
|
||||
@MangaSourceParser("TRUYENTRANHDAMMYY", "TruyenTranhDamMyy", "vi")
|
||||
internal class TruyenTranhDamMyy(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.TRUYENTRANHDAMMYY, "truyentranhdammyy.com") {
|
||||
override val postReq = true
|
||||
override suspend fun loadChapters(mangaUrl: String, document: Document): List<MangaChapter> {
|
||||
val mangaId = document.select("div#manga-chapters-holder").attr("data-id")
|
||||
val url = "https://$domain/wp-admin/admin-ajax.php"
|
||||
val postData = "action=manga_get_chapters&manga=$mangaId"
|
||||
val doc = webClient.httpPost(url, postData).parseHtml()
|
||||
return doc.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylePage
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = link,
|
||||
name = name,
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = 0, // Correct datePattern not found.
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.parsers.site.mangareader.en
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
|
||||
@MangaSourceParser("AGSCOMICS", "AgsComics", "en")
|
||||
internal class AgsComics(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.AGSCOMICS, "agscomics.com", pageSize = 20, searchPageSize = 10) {
|
||||
override val listUrl = "/series"
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.mangareader.en
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
|
||||
@MangaSourceParser("ASCALONSCANS", "AscalonScans", "en")
|
||||
internal class AscalonScans(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.ASCALONSCANS, "ascalonscans.com", pageSize = 20, searchPageSize = 10)
|
||||
@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.parsers.site.mangareader.en
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
|
||||
@MangaSourceParser("READERSPOINT", "ReadersPoint", "en")
|
||||
internal class ReadersPoint(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.READERSPOINT, "readers-point.space", pageSize = 20, searchPageSize = 10) {
|
||||
override val listUrl = "/series"
|
||||
}
|
||||
Loading…
Reference in New Issue