diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 9a55c2de..fbd3b0a1 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -3,4 +3,4 @@ - \ No newline at end of file + diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/InternalParsersApi.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/InternalParsersApi.kt index 676dae33..0cb69136 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/InternalParsersApi.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/InternalParsersApi.kt @@ -11,4 +11,4 @@ package org.koitharu.kotatsu.parsers @SinceKotlin("1.3") @RequiresOptIn @MustBeDocumented -annotation class InternalParsersApi() \ No newline at end of file +annotation class InternalParsersApi diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContext.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContext.kt index fc661cce..dc6ce96f 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContext.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContext.kt @@ -12,7 +12,7 @@ abstract class MangaLoaderContext { abstract val cookieJar: CookieJar - fun newParserInstance(source: MangaSource): MangaParser = source.newParser(this) + fun newParserInstance(source: MangaSource): MangaParser = this.newParserInstance(source) open fun encodeBase64(data: ByteArray): String = Base64.getEncoder().encodeToString(data) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/AstralManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/AstralManga.kt index 43411e6a..88520796 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/AstralManga.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/AstralManga.kt @@ -3,8 +3,14 @@ package org.koitharu.kotatsu.parsers.site.madara import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.util.assertNotNull +import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow @MangaSourceParser("ASTRALMANGA", "AstralManga", "fr") internal class AstralManga(context: MangaLoaderContext) : diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Atlantisscan.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Atlantisscan.kt index 4645a1d4..38287ce0 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Atlantisscan.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Atlantisscan.kt @@ -3,8 +3,14 @@ package org.koitharu.kotatsu.parsers.site.madara import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.util.assertNotNull +import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow @MangaSourceParser("ATLANTISSCAN", "Atlantisscan", "pt") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/FrScan.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/FrScan.kt index bb836c46..86f46179 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/FrScan.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/FrScan.kt @@ -3,8 +3,14 @@ package org.koitharu.kotatsu.parsers.site.madara import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.util.assertNotNull +import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow import java.util.* @MangaSourceParser("FRSCAN", "FrScan", "fr") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaiteca.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaiteca.kt index 723a05eb..a92c7ba3 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaiteca.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaiteca.kt @@ -3,8 +3,14 @@ package org.koitharu.kotatsu.parsers.site.madara import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.util.assertNotNull +import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow @MangaSourceParser("HENTAITECA", "Hentaiteca", "pt") internal class Hentaiteca(context: MangaLoaderContext) : diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaizone.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaizone.kt index ff1b86f1..3fcd44bf 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaizone.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hentaizone.kt @@ -4,11 +4,13 @@ import org.jsoup.nodes.Document import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState import org.koitharu.kotatsu.parsers.util.* import java.text.SimpleDateFormat import java.util.* -import java.time.LocalDate; @MangaSourceParser("HENTAIZONE", "Hentaizone", "fr") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/HhentaiFr.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/HhentaiFr.kt index c079acb6..1b2ce041 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/HhentaiFr.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/HhentaiFr.kt @@ -3,8 +3,14 @@ package org.koitharu.kotatsu.parsers.site.madara import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.util.domain +import org.koitharu.kotatsu.parsers.util.insertCookies +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow import java.util.* diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hipercool.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hipercool.kt index e5168d3a..6944ac47 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hipercool.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/Hipercool.kt @@ -3,8 +3,13 @@ package org.koitharu.kotatsu.parsers.site.madara import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow import java.util.* diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt index f6a5b13f..077a4c99 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt @@ -193,7 +193,7 @@ internal abstract class MadaraParser( parseRelativeDate(date) } // Handle translated 'ago' in french. - date.startsWith("il y a", ignoreCase = true)-> { + date.startsWith("il y a", ignoreCase = true) -> { parseRelativeDate(date) } // Handle 'yesterday' and 'today', using midnight diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaScantrad.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaScantrad.kt index 3c871d34..0c2f8eb7 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaScantrad.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaScantrad.kt @@ -3,8 +3,14 @@ package org.koitharu.kotatsu.parsers.site.madara import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.util.assertNotNull +import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow import java.util.* @MangaSourceParser("MANGA_SCANTRAD", "Manga Scantrad", "fr") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangalinkParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangalinkParser.kt index 25404f35..fdbe6369 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangalinkParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangalinkParser.kt @@ -12,35 +12,35 @@ import org.koitharu.kotatsu.parsers.util.* @MangaSourceParser("MANGALINK_AR", "Mangalink", "ar") internal class MangalinkParser(context: MangaLoaderContext) : - MadaraParser(context, MangaSource.MANGALINK_AR, "mangalink.online") { + MadaraParser(context, MangaSource.MANGALINK_AR, "mangalink.online") { - override suspend fun getDetails(manga: Manga): Manga = coroutineScope { - val fullUrl = manga.url.toAbsoluteUrl(domain) - val doc = webClient.httpGet(fullUrl).parseHtml() - val chaptersDeferred = async { getChapters(manga, doc) } - val root = doc.body().selectFirst("div.profile-manga") - ?.selectFirst("div.summary_content") - ?.selectFirst("div.post-content") - ?: throw ParseException("Root not found", fullUrl) - val root2 = doc.body().selectFirst("div.content-area") - ?.selectFirst("div.c-page") - ?: throw ParseException("Root2 not found", fullUrl) - manga.copy( - tags = root.selectFirst("div.genres-content")?.select("a") - ?.mapNotNullToSet { a -> - MangaTag( - key = a.attr("href").removeSuffix("/").substringAfterLast('/'), - title = a.text().toTitleCase(), - source = source, - ) - } ?: manga.tags, - description = root2.selectFirst("div.description-summary") - ?.selectFirst("div.summary__content") - ?.select("p") - ?.filterNot { it.ownText().startsWith("A brief description") } - ?.joinToString { it.html() }, - chapters = chaptersDeferred.await(), - ) - } + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val chaptersDeferred = async { getChapters(manga, doc) } + val root = doc.body().selectFirst("div.profile-manga") + ?.selectFirst("div.summary_content") + ?.selectFirst("div.post-content") + ?: throw ParseException("Root not found", fullUrl) + val root2 = doc.body().selectFirst("div.content-area") + ?.selectFirst("div.c-page") + ?: throw ParseException("Root2 not found", fullUrl) + manga.copy( + tags = root.selectFirst("div.genres-content")?.select("a") + ?.mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix("/").substringAfterLast('/'), + title = a.text().toTitleCase(), + source = source, + ) + } ?: manga.tags, + description = root2.selectFirst("div.description-summary") + ?.selectFirst("div.summary__content") + ?.select("p") + ?.filterNot { it.ownText().startsWith("A brief description") } + ?.joinToString { it.html() }, + chapters = chaptersDeferred.await(), + ) + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansFr.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansFr.kt index 931912c3..1f39412d 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansFr.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansFr.kt @@ -4,8 +4,9 @@ import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.exception.ParseException -import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.util.* @MangaSourceParser("REAPERSCANS_FR", "ReaperScansFr", "fr") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansParser.kt index d613607d..ad8d5be5 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ReaperScansParser.kt @@ -9,78 +9,78 @@ import java.util.* @MangaSourceParser("REAPER_SCANS_ID", "ReaperScansID", "in") internal class ReaperScansParser(context: MangaLoaderContext) : - Madara6Parser(context, MangaSource.REAPER_SCANS_ID, "reaperscans.id") { + Madara6Parser(context, MangaSource.REAPER_SCANS_ID, "reaperscans.id") { - override val datePattern = "MMMM dd, yyyy" - override val tagPrefix = "genre/" - override val sourceLocale: Locale = Locale.ENGLISH + override val datePattern = "MMMM dd, yyyy" + override val tagPrefix = "genre/" + override val sourceLocale: Locale = Locale.ENGLISH - override fun String.asMangaState(): MangaState? = when (this) { - "OnGoing", - "Upcoming", - -> MangaState.ONGOING + override fun String.asMangaState(): MangaState? = when (this) { + "OnGoing", + "Upcoming", + -> MangaState.ONGOING - "Completed", - "Dropped", - -> MangaState.FINISHED + "Completed", + "Dropped", + -> MangaState.FINISHED - else -> null - } + else -> null + } - override fun parseDetails(manga: Manga, body: Element, chapters: List): Manga { - val root = body.selectFirstOrThrow(".site-content") - val postContent = root.requireElementById("nav-info") - val tags = postContent.getElementsContainingOwnText("GĂȘnero") - .firstOrNull()?.tableValue() - ?.getElementsByAttributeValueContaining("href", tagPrefix) - ?.mapToSet { a -> a.asMangaTag() } ?: manga.tags - return manga.copy( - rating = postContent.selectFirstOrThrow(".post-rating") - .selectFirstOrThrow(".total_votes").text().toFloat() / 5f, - largeCoverUrl = root.selectFirst(".summary_image") - ?.selectFirst("img[data-src]") - ?.attrAsAbsoluteUrlOrNull("data-src") - .assertNotNull("largeCoverUrl"), - description = root.requireElementById("nav-profile") - .selectFirstOrThrow(".description-summary") - .firstElementChild()?.html(), - author = postContent.getElementsContainingOwnText("Author(s)") - .firstOrNull()?.tableValue()?.text()?.trim(), - altTitle = postContent.getElementsContainingOwnText("Alternative") - .firstOrNull()?.tableValue()?.text()?.trim(), - state = postContent.getElementsContainingOwnText("Status") - .firstOrNull()?.tableValue()?.text()?.asMangaState(), - tags = tags, - isNsfw = body.hasClass("adult-content"), - chapters = chapters, - ) - } + override fun parseDetails(manga: Manga, body: Element, chapters: List): Manga { + val root = body.selectFirstOrThrow(".site-content") + val postContent = root.requireElementById("nav-info") + val tags = postContent.getElementsContainingOwnText("GĂȘnero") + .firstOrNull()?.tableValue() + ?.getElementsByAttributeValueContaining("href", tagPrefix) + ?.mapToSet { a -> a.asMangaTag() } ?: manga.tags + return manga.copy( + rating = postContent.selectFirstOrThrow(".post-rating") + .selectFirstOrThrow(".total_votes").text().toFloat() / 5f, + largeCoverUrl = root.selectFirst(".summary_image") + ?.selectFirst("img[data-src]") + ?.attrAsAbsoluteUrlOrNull("data-src") + .assertNotNull("largeCoverUrl"), + description = root.requireElementById("nav-profile") + .selectFirstOrThrow(".description-summary") + .firstElementChild()?.html(), + author = postContent.getElementsContainingOwnText("Author(s)") + .firstOrNull()?.tableValue()?.text()?.trim(), + altTitle = postContent.getElementsContainingOwnText("Alternative") + .firstOrNull()?.tableValue()?.text()?.trim(), + state = postContent.getElementsContainingOwnText("Status") + .firstOrNull()?.tableValue()?.text()?.asMangaState(), + tags = tags, + isNsfw = body.hasClass("adult-content"), + chapters = chapters, + ) + } - override suspend fun getTags(): Set { - val doc = webClient.httpGet("https://${domain}/semua-komik/").parseHtml() - val body = doc.body() - val root1 = body.selectFirst("header")?.selectFirst("ul.second-menu") - val root2 = body.selectFirst("div.genres_wrap")?.selectFirst("ul.list-unstyled") - if (root1 == null && root2 == null) { - doc.parseFailed("Root not found") - } - val list = root1?.select("li").orEmpty() + root2?.select("li").orEmpty() - val keySet = HashSet(list.size) - return list.mapNotNullToSet { li -> - val a = li.selectFirst("a") ?: return@mapNotNullToSet null - val href = a.attr("href").removeSuffix("/") - .substringAfterLast(tagPrefix, "") - if (href.isEmpty() || !keySet.add(href)) { - return@mapNotNullToSet null - } - MangaTag( - key = href, - title = a.ownText().trim().ifEmpty { - a.selectFirst(".menu-image-title")?.text()?.trim() ?: return@mapNotNullToSet null - }.toTitleCase(), - source = source, - ) - } - } + override suspend fun getTags(): Set { + val doc = webClient.httpGet("https://${domain}/semua-komik/").parseHtml() + val body = doc.body() + val root1 = body.selectFirst("header")?.selectFirst("ul.second-menu") + val root2 = body.selectFirst("div.genres_wrap")?.selectFirst("ul.list-unstyled") + if (root1 == null && root2 == null) { + doc.parseFailed("Root not found") + } + val list = root1?.select("li").orEmpty() + root2?.select("li").orEmpty() + val keySet = HashSet(list.size) + return list.mapNotNullToSet { li -> + val a = li.selectFirst("a") ?: return@mapNotNullToSet null + val href = a.attr("href").removeSuffix("/") + .substringAfterLast(tagPrefix, "") + if (href.isEmpty() || !keySet.add(href)) { + return@mapNotNullToSet null + } + MangaTag( + key = href, + title = a.ownText().trim().ifEmpty { + a.selectFirst(".menu-image-title")?.text()?.trim() ?: return@mapNotNullToSet null + }.toTitleCase(), + source = source, + ) + } + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ScantradVf.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ScantradVf.kt index ee12fc4a..d7a87554 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ScantradVf.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ScantradVf.kt @@ -5,7 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.util.* -import java.util.* @MangaSourceParser("SCANTRADVF", "ScantradVf", "fr") internal class ScantradVf(context: MangaLoaderContext) : diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt index 012e8ad6..7211c931 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt @@ -535,7 +535,7 @@ internal abstract class MangaReaderParser( } @MangaSourceParser("PHENIXSCANS", "Phenixscans", "fr") - class PhenixscansParser(context: MangaLoaderContext) : + class PhenixscansParser(context: MangaLoaderContext) : MangaReaderParser(context, MangaSource.PHENIXSCANS, pageSize = 20, searchPageSize = 10) { override val configKeyDomain: ConfigKey.Domain get() = ConfigKey.Domain("phenixscans.fr") @@ -561,7 +561,7 @@ internal abstract class MangaReaderParser( } @MangaSourceParser("EPSILONSCAN", "Epsilonscan", "fr") - class EpsilonscanParser(context: MangaLoaderContext) : + class EpsilonscanParser(context: MangaLoaderContext) : MangaReaderParser(context, MangaSource.EPSILONSCAN, pageSize = 20, searchPageSize = 10) { override val configKeyDomain: ConfigKey.Domain get() = ConfigKey.Domain("epsilonscan.fr") @@ -570,7 +570,7 @@ internal abstract class MangaReaderParser( get() = "/manga" override val tableMode: Boolean get() = false - override val isNsfwSource: Boolean = true + override val isNsfwSource: Boolean = true override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.FRENCH) @@ -588,7 +588,7 @@ internal abstract class MangaReaderParser( } @MangaSourceParser("LEGACY_SCANS", "Legacy Scans", "fr") - class LegacyScansParser(context: MangaLoaderContext) : + class LegacyScansParser(context: MangaLoaderContext) : MangaReaderParser(context, MangaSource.LEGACY_SCANS, pageSize = 20, searchPageSize = 10) { override val configKeyDomain: ConfigKey.Domain get() = ConfigKey.Domain("legacy-scans.com") @@ -596,7 +596,7 @@ internal abstract class MangaReaderParser( override val listUrl: String get() = "/manga" override val tableMode: Boolean - get() = false + get() = false override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.FRENCH) @@ -611,8 +611,8 @@ internal abstract class MangaReaderParser( .orEmpty(), ) } - } - + } + @MangaSourceParser("KOMIKLOKAL", "KomikLokal", "id") class KomikLokalParser(context: MangaLoaderContext) : MangaReaderParser(context, MangaSource.KOMIKLOKAL, pageSize = 20, searchPageSize = 10) { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt index cb8a6a3d..60e5a26e 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt @@ -7,86 +7,86 @@ import org.koitharu.kotatsu.parsers.network.WebClient import org.koitharu.kotatsu.parsers.util.json.mapJSON class FaviconParser( - private val webClient: WebClient, - private val domain: String, + private val webClient: WebClient, + private val domain: String, ) { - suspend fun parseFavicons(): Favicons { - val url = "https://$domain" - val doc = webClient.httpGet(url).parseHtml() - val result = HashSet() - val manifestLink = doc.getElementsByAttributeValue("rel", "manifest").firstOrNull() - ?.attrAsAbsoluteUrlOrNull("href") - if (manifestLink != null) { - result += parseManifest(manifestLink) - } - val links = doc.getElementsByAttributeValueContaining("rel", "icon") - links.mapNotNullTo(result) { link -> - parseLink(link) - } - if (result.isEmpty()) { - result.add(createFallback()) - } - return Favicons(result, url) - } + suspend fun parseFavicons(): Favicons { + val url = "https://$domain" + val doc = webClient.httpGet(url).parseHtml() + val result = HashSet() + val manifestLink = doc.getElementsByAttributeValue("rel", "manifest").firstOrNull() + ?.attrAsAbsoluteUrlOrNull("href") + if (manifestLink != null) { + result += parseManifest(manifestLink) + } + val links = doc.getElementsByAttributeValueContaining("rel", "icon") + links.mapNotNullTo(result) { link -> + parseLink(link) + } + if (result.isEmpty()) { + result.add(createFallback()) + } + return Favicons(result, url) + } - private fun parseLink(link: Element): Favicon? { - val href = link.attrAsAbsoluteUrlOrNull("href") - if (href == null || href.endsWith('/')) { - return null - } - val sizes = link.attr("sizes") - return Favicon( - url = href, - size = parseSize(sizes), - rel = link.attrOrNull("rel"), - ) - } + private fun parseLink(link: Element): Favicon? { + val href = link.attrAsAbsoluteUrlOrNull("href") + if (href == null || href.endsWith('/')) { + return null + } + val sizes = link.attr("sizes") + return Favicon( + url = href, + size = parseSize(sizes), + rel = link.attrOrNull("rel"), + ) + } - private fun parseSize(sizes: String): Int { - if (sizes.isEmpty() || sizes == "any") { - return 0 - } - return sizes.substringBefore(' ') - .split('x', 'X', '*') - .firstNotNullOfOrNull { it.toIntOrNull() } - ?: 0 - } + private fun parseSize(sizes: String): Int { + if (sizes.isEmpty() || sizes == "any") { + return 0 + } + return sizes.substringBefore(' ') + .split('x', 'X', '*') + .firstNotNullOfOrNull { it.toIntOrNull() } + ?: 0 + } - private suspend fun parseManifest(url: String): List { - val json = webClient.httpGet(url).parseJson() - val icons = json.getJSONArray("icons") - return icons.mapJSON { jo -> - Favicon( - url = jo.getString("src").resolveLink(), - size = parseSize(jo.getString("sizes")), - rel = null, - ) - } - } + private suspend fun parseManifest(url: String): List { + val json = webClient.httpGet(url).parseJson() + val icons = json.getJSONArray("icons") + return icons.mapJSON { jo -> + Favicon( + url = jo.getString("src").resolveLink(), + size = parseSize(jo.getString("sizes")), + rel = null, + ) + } + } - private fun createFallback(): Favicon { - val href = "https://$domain/favicon.ico" - return Favicon( - url = href, - size = 0, - rel = null, - ) - } + private fun createFallback(): Favicon { + val href = "https://$domain/favicon.ico" + return Favicon( + url = href, + size = 0, + rel = null, + ) + } - private fun String.resolveLink(): String { - return when { - startsWith("http:") || startsWith("https:") -> { - this - } + private fun String.resolveLink(): String { + return when { + startsWith("http:") || startsWith("https:") -> { + this + } - startsWith('/') -> { - "https://$domain$this" - } + startsWith('/') -> { + "https://$domain$this" + } - else -> { - "https://$domain/$this" - } - } - } + else -> { + "https://$domain/$this" + } + } + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt index 1e20c9e0..181745d3 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt @@ -20,14 +20,14 @@ import org.koitharu.kotatsu.parsers.model.MangaTag */ @InternalParsersApi fun MangaParser.generateUid(url: String): Long { - var h = 1125899906842597L - source.name.forEach { c -> - h = 31 * h + c.code - } - url.forEach { c -> - h = 31 * h + c.code - } - return h + var h = 1125899906842597L + source.name.forEach { c -> + h = 31 * h + c.code + } + url.forEach { c -> + h = 31 * h + c.code + } + return h } /** @@ -39,40 +39,40 @@ fun MangaParser.generateUid(url: String): Long { */ @InternalParsersApi fun MangaParser.generateUid(id: Long): Long { - var h = 1125899906842597L - source.name.forEach { c -> - h = 31 * h + c.code - } - h = 31 * h + id - return h + var h = 1125899906842597L + source.name.forEach { c -> + h = 31 * h + c.code + } + h = 31 * h + id + return h } @InternalParsersApi fun Element.parseFailed(message: String? = null): Nothing { - throw ParseException(message, ownerDocument()?.location() ?: baseUri(), null) + throw ParseException(message, ownerDocument()?.location() ?: baseUri(), null) } @InternalParsersApi fun Set?.oneOrThrowIfMany(): MangaTag? { - return when { - isNullOrEmpty() -> null - size == 1 -> first() - else -> throw IllegalArgumentException("Multiple genres are not supported by this source") - } + return when { + isNullOrEmpty() -> null + size == 1 -> first() + else -> throw IllegalArgumentException("Multiple genres are not supported by this source") + } } val MangaParser.domain: String - get() { - return config[configKeyDomain] - } + get() { + return config[configKeyDomain] + } fun MangaParser.getDomain(subdomain: String): String { - val domain = domain - return subdomain + "." + domain.removePrefix("www.") + val domain = domain + return subdomain + "." + domain.removePrefix("www.") } fun MangaParser.urlBuilder(): HttpUrl.Builder { - return HttpUrl.Builder() - .scheme("https") - .host(domain) + return HttpUrl.Builder() + .scheme("https") + .host(domain) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Number.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Number.kt index 3c5abc9b..99a8b282 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Number.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Number.kt @@ -23,6 +23,7 @@ fun Number.format(decimals: Int = 0, decPoint: Char = '.', thousandsSep: Char? = is Float, is Double, -> formatter.format(this.toDouble()) + else -> formatter.format(this.toLong()) } } @@ -43,4 +44,4 @@ infix fun Int.upBy(step: Int): Int { } else { this - mod + step } -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt index df363e70..c4f37074 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt @@ -8,22 +8,22 @@ import okhttp3.Headers import okhttp3.Response suspend fun Call.await(): Response = suspendCancellableCoroutine { continuation -> - val callback = ContinuationCallCallback(this, continuation) - enqueue(callback) - continuation.invokeOnCancellation(callback) + val callback = ContinuationCallCallback(this, continuation) + enqueue(callback) + continuation.invokeOnCancellation(callback) } val Response.mimeType: String? - get() = body?.contentType()?.run { "$type/$subtype" } + get() = body?.contentType()?.run { "$type/$subtype" } val Response.contentDisposition: String? - get() = header("Content-Disposition") + get() = header("Content-Disposition") fun Headers.Builder.mergeWith(other: Headers, replaceExisting: Boolean): Headers.Builder { - for ((name, value) in other) { - if (replaceExisting || this[name] == null) { - this[name] = value - } - } - return this + for ((name, value) in other) { + if (replaceExisting || this[name] == null) { + this[name] = value + } + } + return this } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Paginator.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Paginator.kt index 5e41bd80..ab313c53 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Paginator.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Paginator.kt @@ -3,7 +3,7 @@ package org.koitharu.kotatsu.parsers.util import androidx.collection.SparseArrayCompat import androidx.collection.set -class Paginator constructor(private val initialPageSize: Int) { +class Paginator(private val initialPageSize: Int) { var firstPage = 1 private var pages = SparseArrayCompat() @@ -22,4 +22,4 @@ class Paginator constructor(private val initialPageSize: Int) { fun onListReceived(offset: Int, page: Int, count: Int) { pages[offset + count] = if (count > 0) page + 1 else page } -} \ No newline at end of file +}