Rm BrMangas close #454

rm PowerManga close #462
Add MangaNinja close #897
Add Grimelek close #375
Add OpiaToon close#374
Add login on madara
Fix ManhwaFreak
master
devi 2 years ago
parent dceedf019a
commit fadf8861e7

@ -1,10 +1,12 @@
package org.koitharu.kotatsu.parsers.site.foolslide.it package org.koitharu.kotatsu.parsers.site.foolslide.it
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@Broken
@MangaSourceParser("POWERMANGA", "PowerManga", "it") @MangaSourceParser("POWERMANGA", "PowerManga", "it")
internal class PowerManga(context: MangaLoaderContext) : internal class PowerManga(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.POWERMANGA, "reader.powermanga.org") { FoolSlideParser(context, MangaSource.POWERMANGA, "reader.powermanga.org") {

@ -7,8 +7,11 @@ import org.json.JSONObject
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.PagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat import java.text.DateFormat
@ -20,7 +23,7 @@ internal abstract class MadaraParser(
source: MangaSource, source: MangaSource,
domain: String, domain: String,
pageSize: Int = 12, pageSize: Int = 12,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize), MangaParserAuthProvider {
override val configKeyDomain = ConfigKey.Domain(domain) override val configKeyDomain = ConfigKey.Domain(domain)
@ -31,6 +34,28 @@ internal abstract class MadaraParser(
keys.add(userAgentKey) keys.add(userAgentKey)
} }
override val authUrl: String
get() = "https://${domain}"
override val isAuthorized: Boolean
get() {
return context.cookieJar.getCookies(domain).any {
it.name.contains("wordpress_logged_in")
}
}
override suspend fun getUsername(): String {
val body = webClient.httpGet("https://${domain}/").parseHtml().body()
return body.selectFirst(".c-user_name")?.text()
?: run {
throw if (body.selectFirst("#loginform") != null) {
AuthRequiredException(source)
} else {
body.parseFailed("Cannot find username")
}
}
}
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
@ -557,7 +582,8 @@ internal abstract class MadaraParser(
val doc = webClient.httpGet(fullUrl).parseHtml() val doc = webClient.httpGet(fullUrl).parseHtml()
val chapterProtector = doc.getElementById("chapter-protector-data") val chapterProtector = doc.getElementById("chapter-protector-data")
if (chapterProtector == null) { if (chapterProtector == null) {
val root = doc.body().selectFirstOrThrow(selectBodyPage) val root = doc.body().selectFirst(selectBodyPage)
?: throw ParseException("No image found, try to log in", fullUrl)
return root.select(selectPage).map { div -> return root.select(selectPage).map { div ->
val img = div.selectFirstOrThrow("img") val img = div.selectFirstOrThrow("img")
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found") val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")

@ -0,0 +1,12 @@
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.MangaSource
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
@MangaSourceParser("MANGANINJA", "MangaNinja", "pt")
internal class MangaNinja(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.MANGANINJA, "manganinja.com", 10) {
override val datePattern: String = "dd/MM/yyyy"
}

@ -5,6 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
//This source requires an account.
@MangaSourceParser("GLORYMANGA", "GloryManga", "tr") @MangaSourceParser("GLORYMANGA", "GloryManga", "tr")
internal class GloryManga(context: MangaLoaderContext) : internal class GloryManga(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.GLORYMANGA, "glorymanga.com", 18) { MadaraParser(context, MangaSource.GLORYMANGA, "glorymanga.com", 18) {

@ -0,0 +1,14 @@
package org.koitharu.kotatsu.parsers.site.madara.tr
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
//This source requires an account.
@MangaSourceParser("GRIMELEK", "Grimelek", "tr")
internal class Grimelek(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.GRIMELEK, "glorymanga.com", 20) {
override val datePattern = "d MMMM yyyy"
override val listUrl = "seri/"
}

@ -0,0 +1,13 @@
package org.koitharu.kotatsu.parsers.site.madara.tr
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
//This source requires an account.
@MangaSourceParser("OPIATOON", "OpiaToon", "tr")
internal class OpiaToon(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.OPIATOON, "opiatoon.biz", 20) {
override val datePattern = "d MMMM"
}

@ -1,10 +1,12 @@
package org.koitharu.kotatsu.parsers.site.mangareader.en package org.koitharu.kotatsu.parsers.site.mangareader.en
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@Broken
@MangaSourceParser("FREAKSCANS", "FreakScans", "en") @MangaSourceParser("FREAKSCANS", "FreakScans", "en")
internal class FreakScans(context: MangaLoaderContext) : internal class FreakScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.FREAKSCANS, "freakscans.com", pageSize = 20, searchPageSize = 20) { MangaReaderParser(context, MangaSource.FREAKSCANS, "freakscans.com", pageSize = 20, searchPageSize = 20) {

@ -1,216 +1,10 @@
package org.koitharu.kotatsu.parsers.site.mangareader.en package org.koitharu.kotatsu.parsers.site.mangareader.en
import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Calendar
@MangaSourceParser("MANHWA_FREAK", "ManhwaFreak", "en")
@MangaSourceParser("MANHWA_FREAK", "Manhwa-Freak.com", "en")
internal class ManhwaFreak(context: MangaLoaderContext) : internal class ManhwaFreak(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.MANHWA_FREAK, "manhwa-freak.com", pageSize = 0, searchPageSize = 10) { MangaReaderParser(context, MangaSource.MANHWA_FREAK, "manhwafreak.site", pageSize = 20, searchPageSize = 10)
override val selectMangaList = ".listupd .lastest-serie"
override val selectMangaListImg = "img"
override val availableStates: Set<MangaState> = emptySet()
override val isMultipleTagsSupported = false
override val isTagsExclusionSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString {
append("https://")
append(domain)
when (filter) {
is MangaListFilter.Search -> {
append("/page/")
append(page.toString())
append("/?s=")
append(filter.query.urlEncoded())
}
is MangaListFilter.Advanced -> {
if (page > 1) {
return emptyList()
}
if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
append("/genres/?genre=")
append(it.key)
}
} else {
append(listUrl)
append("/?order=")
append(
when (filter.sortOrder) {
SortOrder.ALPHABETICAL -> "az"
SortOrder.NEWEST -> "new"
SortOrder.POPULARITY -> "views"
SortOrder.UPDATED -> ""
else -> ""
},
)
}
}
null -> {
append(listUrl)
}
}
}
return parseMangaList(webClient.httpGet(url).parseHtml())
}
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/genres/").parseHtml()
return doc.select("ul.genre-list li a").mapNotNullToSet { a ->
val href = a.attr("href").substringAfterLast("=")
MangaTag(
key = href,
title = a.text(),
source = source,
)
}
}
override suspend fun getDetails(manga: Manga): Manga {
val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
val chapters = docs.select("div.chapter-li a").mapChapters(reversed = true) { index, a ->
val url = a.attrAsRelativeUrl("href")
val dateText = a.selectFirst(".chapter-info p.new")?.text() ?: a.select(".chapter-info p")[1].text()
MangaChapter(
id = generateUid(url),
name = a.selectFirst(".chapter-info p:contains(Chapter)")?.text() ?: "Chapter ${index + 1}",
url = url,
number = index + 1f,
volume = 0,
scanlator = null,
uploadDate = if (dateText == "NEW") {
parseChapterDate(
dateFormat,
"today",
)
} else {
parseChapterDate(
dateFormat,
dateText,
)
},
branch = null,
source = source,
)
}
return parseInfo(docs, manga, chapters)
}
override suspend fun parseInfo(docs: Document, manga: Manga, chapters: List<MangaChapter>): Manga {
val tagMap = getOrCreateTagMap()
val selectTag = docs.requireElementById("info").select("div:contains(Genre) > p:last-child").text().split(",")
val tags = selectTag.mapNotNullToSet { tagMap[it] }
val mangaState = docs.requireElementById("info").select("div:contains(Status) > p:last-child").text().let {
when (it) {
"Ongoing" -> MangaState.ONGOING
"Completed" -> MangaState.FINISHED
else -> null
}
}
val author = docs.requireElementById("info").select("div:contains(Author(s)) > p:last-child").text()
return manga.copy(
altTitle = docs.requireElementById("info").select("div:contains(Alternative) > p:last-child").text(),
description = docs.requireElementById("summary").html(),
state = mangaState,
author = author,
isNsfw = manga.isNsfw,
tags = tags,
chapters = chapters,
)
}
private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
// Clean date (e.g. 5th December 2019 to 5 December 2019) before parsing it
val d = date?.lowercase() ?: return 0
return when {
d.endsWith(" ago") -> parseRelativeDate(date)
// Handle 'yesterday' and 'today', using midnight
d.startsWith("year") -> Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, -1) // yesterday
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
d.startsWith("today") -> Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
date.contains(Regex("""\d(st|nd|rd|th)""")) -> date.split(" ").map {
if (it.contains(Regex("""\d\D\D"""))) {
it.replace(Regex("""\D"""), "")
} else {
it
}
}.let { dateFormat.tryParse(it.joinToString(" ")) }
else -> dateFormat.tryParse(date)
}
}
// Parses dates in this form:
// 21 hours ago
private fun parseRelativeDate(date: String): Long {
val number = Regex("""(\d+)""").find(date)?.value?.toIntOrNull() ?: return 0
val cal = Calendar.getInstance()
return when {
WordSet(
"day",
"days",
"d",
).anyWordIn(date) -> cal.apply { add(Calendar.DAY_OF_MONTH, -number) }.timeInMillis
WordSet(
"hour",
"hours",
"h",
).anyWordIn(date) -> cal.apply {
add(
Calendar.HOUR,
-number,
)
}.timeInMillis
WordSet(
"minute",
"minutes",
"mins",
).anyWordIn(date) -> cal.apply {
add(
Calendar.MINUTE,
-number,
)
}.timeInMillis
WordSet("second").anyWordIn(date) -> cal.apply {
add(
Calendar.SECOND,
-number,
)
}.timeInMillis
WordSet("month", "months").anyWordIn(date) -> cal.apply { add(Calendar.MONTH, -number) }.timeInMillis
WordSet("year").anyWordIn(date) -> cal.apply { add(Calendar.YEAR, -number) }.timeInMillis
else -> 0
}
}
}

@ -1,11 +1,13 @@
package org.koitharu.kotatsu.parsers.site.mmrcms.es package org.koitharu.kotatsu.parsers.site.mmrcms.es
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.site.mmrcms.MmrcmsParser import org.koitharu.kotatsu.parsers.site.mmrcms.MmrcmsParser
import java.util.Locale import java.util.Locale
@Broken
@MangaSourceParser("MANGADOOR", "MangaDoor", "es") @MangaSourceParser("MANGADOOR", "MangaDoor", "es")
internal class MangaDoor(context: MangaLoaderContext) : internal class MangaDoor(context: MangaLoaderContext) :
MmrcmsParser(context, MangaSource.MANGADOOR, "mangadoor.com") { MmrcmsParser(context, MangaSource.MANGADOOR, "mangadoor.com") {

@ -1,6 +1,7 @@
package org.koitharu.kotatsu.parsers.site.pt package org.koitharu.kotatsu.parsers.site.pt
import okhttp3.Headers import okhttp3.Headers
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.PagedMangaParser
@ -10,6 +11,7 @@ import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import java.util.* import java.util.*
@Broken
@MangaSourceParser("BRMANGAS", "BrMangas", "pt") @MangaSourceParser("BRMANGAS", "BrMangas", "pt")
internal class BrMangas(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.BRMANGAS, 25) { internal class BrMangas(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.BRMANGAS, 25) {

Loading…
Cancel
Save