diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/BatoToParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/BatoToParser.kt index dcb0b387..6d422c83 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/BatoToParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/BatoToParser.kt @@ -215,18 +215,21 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser( throw ParseException("Cannot find gernes list", scripts[0].baseUri()) } - override suspend fun getAvailableLocales(): Set { - val jsRaw = webClient.httpGet("https://$domain/amsta/build/jss-btoto_v22.js").parseRaw() - val langRaw = jsRaw.substringAfter("items: {").substringBefore(",\"_t\"").split("code\":\"").drop(1) - return langRaw.mapNotNullToSet { - val lang = it.substringBefore("\",\"") - if (lang.contains("-")) { - return@mapNotNullToSet null - } else { - Locale(lang) - } - } - } + override suspend fun getAvailableLocales(): Set = setOf( + Locale.CHINESE, Locale.ENGLISH, Locale.US, Locale.FRENCH, Locale.GERMAN, Locale.ITALIAN, Locale.JAPANESE, + Locale("af"), Locale("ar"), Locale("az"), Locale("eu"), Locale("be"), + Locale("bn"), Locale("bs"), Locale("bg"), Locale("my"), Locale("km"), + Locale("ceb"), Locale("zh_hk"), Locale("zh_tw"), Locale("hr"), Locale("cs"), + Locale("da"), Locale("nl"), Locale("eo"), Locale("et"), Locale("fil"), + Locale("fi"), Locale("ka"), Locale("el"), Locale("ht"), Locale("he"), + Locale("hi"), Locale("hu"), Locale("id"), Locale("kk"), Locale("ko"), + Locale("lv"), Locale("ms"), Locale("ml"), Locale("mo"), Locale("mn"), + Locale("ne"), Locale("no"), Locale("fa"), Locale("pl"), Locale("pt"), + Locale("pt_br"), Locale("pt_pt"), Locale("ro"), Locale("ru"), Locale("sr"), + Locale("si"), Locale("sk"), Locale("es"), Locale("es_419"), Locale("ta"), + Locale("te"), Locale("th"), Locale("ti"), Locale("tr"), Locale("uk"), + Locale("vi"), Locale("zu"), + ) private suspend fun search(page: Int, query: String): List { val url = buildString { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ComickFunParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ComickFunParser.kt index 30a4778d..7155c62a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ComickFunParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ComickFunParser.kt @@ -23,7 +23,7 @@ private const val CHAPTERS_LIMIT = 99999 @MangaSourceParser("COMICK_FUN", "ComicK") internal class ComickFunParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.COMICK_FUN, 20) { - override val configKeyDomain = ConfigKey.Domain("comick.app") + override val configKeyDomain = ConfigKey.Domain("comick.cc") override val availableSortOrders: Set = EnumSet.of( SortOrder.POPULARITY, diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt index 22993dfa..5b540760 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt @@ -1,7 +1,10 @@ package org.koitharu.kotatsu.parsers.site.all +import androidx.collection.ArrayMap import androidx.collection.SparseArrayCompat import androidx.collection.set +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext @@ -40,7 +43,7 @@ internal class ExHentaiParser( private val authCookies = arrayOf("ipb_member_id", "ipb_pass_hash") private var updateDm = false private val nextPages = SparseArrayCompat() - private val suspiciousContentKey = ConfigKey.ShowSuspiciousContent(true) + private val suspiciousContentKey = ConfigKey.ShowSuspiciousContent(false) override val isAuthorized: Boolean get() { @@ -89,17 +92,31 @@ internal class ExHentaiParser( } is MangaListFilter.Advanced -> { + + append("&f_search=") + + var fCats = 0 if (filter.tags.isNotEmpty()) { - var fCats = 0 - for (tag in filter.tags) { - tag.key.toIntOrNull()?.let { fCats = fCats or it } ?: run { - search += tag.key + " " + filter.tags.forEach { + if (it.title.startsWith("- ")) { + it.key.toIntOrNull()?.let { fCats = fCats or it } ?: run { + search += it.key + " " + } + } else { + append(" tag:".urlEncoded()) + append(it.key) } } - if (fCats != 0) { - append("&f_cats=") - append(1023 - fCats) - } + } + + if (filter.locale != null) { + append(" language:".urlEncoded()) + append(filter.locale.toLanguagePath()) + } + + if (fCats != 0) { + append("&f_cats=") + append(1023 - fCats) } } @@ -163,8 +180,18 @@ internal class ExHentaiParser( val root = doc.body().selectFirstOrThrow("div.gm") val cover = root.getElementById("gd1")?.children()?.first() val title = root.getElementById("gd2") - val taglist = root.getElementById("taglist") + val tagList = root.getElementById("taglist") val tabs = doc.body().selectFirst("table.ptt")?.selectFirst("tr") + val lang = + root.getElementById("gd3")?.selectFirst("tr:contains(Language)")?.selectFirst(".gdt2")?.text() ?: "Unknown" + + val tagMap = getOrCreateTagMap() + val tagF = + tagList?.selectFirst("tr:contains(female:)")?.select("a")?.mapNotNullToSet { tagMap[it.text()] }.orEmpty() + val tagM = + tagList?.selectFirst("tr:contains(male:)")?.select("a")?.mapNotNullToSet { tagMap[it.text()] }.orEmpty() + val tags = tagF + tagM + return manga.copy( title = title?.getElementById("gn")?.text()?.cleanupTitle() ?: manga.title, altTitle = title?.getElementById("gj")?.text()?.cleanupTitle() ?: manga.altTitle, @@ -174,10 +201,11 @@ internal class ExHentaiParser( ?.toFloatOrNull() ?.div(5f) ?: manga.rating, largeCoverUrl = cover?.styleValueOrNull("background")?.cssUrl(), - description = taglist?.select("tr")?.joinToString("
") { tr -> + tags = tags, + description = tagList?.select("tr")?.joinToString("
") { tr -> val (tc, td) = tr.children() - val subtags = td.select("a").joinToString { it.html() } - "${tc.html()} $subtags" + val subTags = td.select("a").joinToString { it.html() } + "${tc.html()} $subTags" }, chapters = tabs?.select("a")?.findLast { a -> a.text().toIntOrNull() != null @@ -194,7 +222,7 @@ internal class ExHentaiParser( uploadDate = 0L, source = source, scanlator = null, - branch = null, + branch = lang, ) } chapters.toList() @@ -221,18 +249,78 @@ internal class ExHentaiParser( return doc.body().requireElementById("img").attrAsAbsoluteUrl("src") } + private val tags = + "ahegao,anal,angel,apron,bandages,bbw,bdsm,beauty mark,big areolae,big ass,big breasts,big clit,big lips," + + "big nipples,bikini,blackmail,bloomers,blowjob,bodysuit,bondage,breast expansion,bukkake,bunny girl,business suit," + + "catgirl,centaur,cheating,chinese dress,christmas,collar,corset,cosplaying,cowgirl,crossdressing,cunnilingus," + + "dark skin,daughter,deepthroat,defloration,demon girl,double penetration,dougi,dragon,drunk,elf,exhibitionism,farting," + + "females only,femdom,filming,fingering,fishnets,footjob,fox girl,furry,futanari,garter belt,ghost,giantess," + + "glasses,gloves,goblin,gothic lolita,growth,guro,gyaru,hair buns,hairy,hairy armpits,handjob,harem,hidden sex," + + "horns,huge breasts,humiliation,impregnation,incest,inverted nipples,kemonomimi,kimono,kissing,lactation," + + "latex,leg lock,leotard,lingerie,lizard girl,maid,masked face,masturbation,midget,miko,milf,mind break," + + "mind control,monster girl,mother,muscle,nakadashi,netorare,nose hook,nun,nurse,oil,paizuri,panda girl," + + "pantyhose,piercing,pixie cut,policewoman,ponytail,pregnant,rape,rimjob,robot,scat,lolicon,schoolgirl uniform," + + "sex toys,shemale,sister,small breasts,smell,sole dickgirl,sole female,squirting,stockings,sundress,sweating," + + "swimsuit,swinging,tail,tall girl,teacher,tentacles,thigh high boots,tomboy,transformation,twins,twintails," + + "unusual pupils,urination,vore,vtuber,widow,wings,witch,wolf girl,x-ray,yuri,zombie,sole male,males only,yaoi," + + "tomgirl,tall man,oni,shotacon,prostate massage,policeman,males only,huge penis,fox boy,feminization,dog boy,dickgirl on male,big penis" + + private var tagCache: ArrayMap? = null + private val mutex = Mutex() + override suspend fun getAvailableTags(): Set { + return getOrCreateTagMap().values.toSet() + } + + protected suspend fun getOrCreateTagMap(): Map = mutex.withLock { + tagCache?.let { return@withLock it } + val tagMap = ArrayMap() + val tagElements = tags.split(",") + for (el in tagElements) { + if (el.isEmpty()) continue + tagMap[el] = MangaTag( + title = el, + key = el, + source = source, + ) + } + val doc = webClient.httpGet("https://${domain}").parseHtml() val root = doc.body().requireElementById("searchbox").selectFirstOrThrow("table") - return root.select("div.cs").mapNotNullToSet { div -> - val id = div.id().substringAfterLast('_').toIntOrNull() - ?: return@mapNotNullToSet null - MangaTag( - title = div.text().toTitleCase(), + root.select("div.cs").mapNotNullToSet { div -> + val id = div.id().substringAfterLast('_').toIntOrNull() ?: return@mapNotNullToSet null + val name = "- " + div.text().toTitleCase() + tagMap[name] = MangaTag( + title = name, key = id.toString(), source = source, ) } + + tagCache = tagMap + return@withLock tagMap + } + + override suspend fun getAvailableLocales(): Set = setOf( + Locale.JAPANESE, + Locale.ENGLISH, + Locale.CHINESE, + Locale("nl"), + Locale.FRENCH, + Locale.GERMAN, + Locale("hu"), + Locale.ITALIAN, + Locale("kr"), + Locale("pl"), + Locale("pt"), + Locale("ru"), + Locale("es"), + Locale("th"), + Locale("vi"), + ) + + private fun Locale.toLanguagePath() = when (language) { + else -> getDisplayLanguage(Locale.ENGLISH).lowercase() } override suspend fun getUsername(): String { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ImHentai.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ImHentai.kt index 3c9e0e39..effb15df 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ImHentai.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ImHentai.kt @@ -22,49 +22,42 @@ internal class ImHentai(context: MangaLoaderContext) : override val configKeyDomain = ConfigKey.Domain("imhentai.xxx") - override val isMultipleTagsSupported = false - override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) + append("/search/?page=") + append(page.toString()) when (filter) { is MangaListFilter.Search -> { - append("/search/?key=") + append("&key=") append(filter.query.urlEncoded()) - append("&page=") - append(page) } is MangaListFilter.Advanced -> { - val tag = filter.tags.oneOrThrowIfMany() if (filter.tags.isNotEmpty()) { - append("/tag/") - append(tag?.key.orEmpty()) - append("/") - when (filter.sortOrder) { - SortOrder.UPDATED -> append("") - SortOrder.POPULARITY -> append("popular/") - else -> append("") - } - append("?page=") - append(page) - } else { - append("/search/?page=") - append(page) - when (filter.sortOrder) { - SortOrder.UPDATED -> append("<=1&pp=0") - SortOrder.POPULARITY -> append("<=0&pp=1") - SortOrder.RATING -> append("<=0&pp=0") - else -> append("<=1&pp=0") - } + append("&key=") + append(filter.tags.joinToString(separator = ",") { it.key }) + } + + var lang = "&en=1&jp=1&es=1&fr=1&kr=1&de=1&ru=1" + filter.locale?.let { + lang = "&en=0&jp=0&es=0&fr=0&kr=0&de=0&ru=0" + lang = lang.replace("${it.language}=0", "${it.language}=1") + } + append(lang) + + when (filter.sortOrder) { + SortOrder.UPDATED -> append("<=1&pp=0") + SortOrder.POPULARITY -> append("<=0&pp=1") + SortOrder.RATING -> append("<=0&pp=0") + else -> append("<=1&pp=0") } } null -> { - append("/search/?lt=1&pp=0&page=") - append(page) + append("<=1&pp=0") } } @@ -115,6 +108,10 @@ internal class ImHentai(context: MangaLoaderContext) : ) } + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, Locale.JAPANESE, Locale("es"), Locale.FRENCH, Locale("kr"), Locale.GERMAN, Locale("ru"), + ) + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { val fullUrl = manga.url.toAbsoluteUrl(domain) val doc = webClient.httpGet(fullUrl).parseHtml() diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/MangaGeko.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/MangaGeko.kt index c1cf6a1e..3f333a3a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/MangaGeko.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/MangaGeko.kt @@ -17,7 +17,7 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context override val availableSortOrders: Set = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST) - override val configKeyDomain = ConfigKey.Domain("www.mangageko.com") + override val configKeyDomain = ConfigKey.Domain("www.mgeko.com", "www.mangageko.com") override val isMultipleTagsSupported = false diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt index d3f86602..ecd00892 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt @@ -127,10 +127,10 @@ internal abstract class HeanCmsAlt( } } - private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long { + protected open fun parseChapterDate(dateFormat: DateFormat, date: String?): Long { val d = date?.lowercase() ?: return 0 return when { - d.startsWith("hace ") -> parseRelativeDate(date) + d.startsWith("hace ") || d.endsWith(" antes") -> parseRelativeDate(date) else -> dateFormat.tryParse(date) } } @@ -153,7 +153,7 @@ internal abstract class HeanCmsAlt( ) }.timeInMillis - WordSet("mes").anyWordIn(date) -> cal.apply { add(Calendar.MONTH, -number) }.timeInMillis + WordSet("mes", "meses").anyWordIn(date) -> cal.apply { add(Calendar.MONTH, -number) }.timeInMillis WordSet("año").anyWordIn(date) -> cal.apply { add(Calendar.YEAR, -number) }.timeInMillis else -> 0 } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/es/Brakeout.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/es/Brakeout.kt new file mode 100644 index 00000000..6cd5ef63 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/es/Brakeout.kt @@ -0,0 +1,59 @@ +package org.koitharu.kotatsu.parsers.site.heancmsalt.es + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +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.site.heancmsalt.HeanCmsAlt +import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrl +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.parseHtml +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow +import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl +import java.text.SimpleDateFormat + +@MangaSourceParser("BRAKEOUT", "Brakeout", "es") +internal class Brakeout(context: MangaLoaderContext) : + HeanCmsAlt(context, MangaSource.BRAKEOUT, "brakeout.xyz", 10) { + override val selectManga = "div.grid.grid-cols-2 figure" + override val selectMangaTitle = "figcaption" + + override val selectDesc = "#section-sinopsis p" + override val selectChapter = ".grid-capitulos div.contenedor-capitulo-miniatura" + override val selectChapterTitle = "#name" + override val selectChapterDate = "time" + override val datePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'" + override suspend fun getDetails(manga: Manga): Manga { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val dateFormat = SimpleDateFormat(datePattern, sourceLocale) + return manga.copy( + altTitle = doc.selectFirst(selectAlt)?.text().orEmpty(), + description = doc.selectFirstOrThrow(selectDesc).html(), + chapters = doc.select(selectChapter) + .mapChapters(reversed = true) { i, div -> + val a = div.selectFirstOrThrow("a") + val dateText = div.selectFirstOrThrow(selectChapterDate).text() + val url = a.attrAsRelativeUrl("href").toAbsoluteUrl(domain) + MangaChapter( + id = generateUid(url), + name = div.selectFirstOrThrow(selectChapterTitle).text(), + number = i + 1, + url = url, + scanlator = null, + uploadDate = parseChapterDate( + dateFormat, + dateText, + ), + branch = null, + source = source, + ) + }, + ) + } + + override val selectPage = "section img.readImg" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ResetScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ResetScans.kt index c48ef64e..c603e122 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ResetScans.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ResetScans.kt @@ -7,6 +7,6 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser @MangaSourceParser("RESETSCANS", "ResetScans", "en") internal class ResetScans(context: MangaLoaderContext) : - MadaraParser(context, MangaSource.RESETSCANS, "reset-scans.com", 18) { + MadaraParser(context, MangaSource.RESETSCANS, "reset-scans.us", 18) { override val datePattern = "MMM dd" } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/Hentaizone.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/Hentaizone.kt index 05cad189..615855b7 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/Hentaizone.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/Hentaizone.kt @@ -4,6 +4,7 @@ import org.jsoup.nodes.Document 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.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser @@ -18,40 +19,42 @@ internal class Hentaizone(context: MangaLoaderContext) : override val datePattern = "MMM d, yyyy" override val sourceLocale: Locale = Locale.FRENCH - override suspend fun loadChapters(mangaUrl: String, document: Document): List { - val url = mangaUrl.toAbsoluteUrl(domain).removeSuffix('/') + "/ajax/chapters/" - val dateFormat = SimpleDateFormat(datePattern, sourceLocale) - val doc = webClient.httpPost(url, emptyMap()).parseHtml() - - return doc.select("li.wp-manga-chapter").mapChapters(reversed = true) { i, li -> - val a = li.selectFirstOrThrow("a") - val href = a.attrAsRelativeUrl("href") + "?style=list" - // correct parse date missing a "." - val dateOrg = li.selectFirst("span.chapter-release-date i")?.text() ?: "janv 1, 2000" - val dateCorrectParse = dateOrg - .replace("Jan", "janv.") - .replace("Fév", "févr.") - .replace("Mar", "mars") - .replace("avr", "avr.") - .replace("juil", "juil.") - .replace("Sep", "sept.") - .replace("nov", "nov.") - .replace("oct", "oct.") - .replace("déc", "déc.") + override suspend fun getChapters(manga: Manga, doc: Document): List { + val dateFormat = SimpleDateFormat(datePattern, sourceLocale) + return doc.body().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 dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text() + val dateCorrectParse = dateReplace(dateText ?: "janv 1, 1970") + val name = a.selectFirst("p")?.text() ?: a.ownText() MangaChapter( id = generateUid(href), - url = href, - name = a.text(), + name = name, number = i + 1, - branch = null, + url = link, uploadDate = parseChapterDate( dateFormat, dateCorrectParse, ), - scanlator = null, source = source, + scanlator = null, + branch = null, ) } } + + private fun dateReplace(date: String): String { + return date.lowercase() + .replace("jan", "janv.") + .replace("fév", "févr.") + .replace("mar", "mars") + .replace("avr", "avr.") + .replace("juil", "juil.") + .replace("sep", "sept.") + .replace("nov", "nov.") + .replace("oct", "oct.") + .replace("déc", "déc.") + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/ToonFr.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/ToonFr.kt index 5a953878..20aec5d7 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/ToonFr.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/fr/ToonFr.kt @@ -26,16 +26,8 @@ internal class ToonFr(context: MangaLoaderContext) : val a = li.selectFirstOrThrow("a") val href = a.attrAsRelativeUrl("href") + "?style=list" // correct parse date missing a "." - val dateOrg = li.selectFirst("span.chapter-release-date i")?.text() ?: "janv 1, 2000" - val dateCorrectParse = dateOrg - .replace("Jan", "janv.") - .replace("Févr", "févr.") - .replace("Avr", "avr.") - .replace("Juil", "juil.") - .replace("Sept", "sept.") - .replace("Nov", "nov.") - .replace("Oct", "oct.") - .replace("Déc", "déc.") + val dateText = li.selectFirst("span.chapter-release-date i")?.text() + val dateCorrectParse = dateReplace(dateText ?: "janv 1, 1970") MangaChapter( id = generateUid(href), url = href, @@ -51,5 +43,18 @@ internal class ToonFr(context: MangaLoaderContext) : ) } } + + private fun dateReplace(date: String): String { + return date.lowercase() + .replace("jan", "janv.") + .replace("fév", "févr.") + .replace("mar", "mars") + .replace("avr", "avr.") + .replace("juil", "juil.") + .replace("sep", "sept.") + .replace("nov", "nov.") + .replace("oct", "oct.") + .replace("déc", "déc.") + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madtheme/all/ManhuaScan.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madtheme/en/ManhuaScan.kt similarity index 96% rename from src/main/kotlin/org/koitharu/kotatsu/parsers/site/madtheme/all/ManhuaScan.kt rename to src/main/kotlin/org/koitharu/kotatsu/parsers/site/madtheme/en/ManhuaScan.kt index 341b086b..da959f84 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madtheme/all/ManhuaScan.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madtheme/en/ManhuaScan.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.parsers.site.madtheme.all +package org.koitharu.kotatsu.parsers.site.madtheme.en import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser @@ -7,7 +7,7 @@ import org.koitharu.kotatsu.parsers.site.madtheme.MadthemeParser import org.koitharu.kotatsu.parsers.util.* import java.util.Locale -@MangaSourceParser("MANHUASCAN", "ManhuaScan.io", "") +@MangaSourceParser("MANHUASCAN", "ManhuaScan.io", "en") internal class ManhuaScan(context: MangaLoaderContext) : MadthemeParser(context, MangaSource.MANHUASCAN, "manhuascan.io") { override val sourceLocale: Locale = Locale.ENGLISH diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuminousScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuminousScans.kt index 8d4ca8ad..2c3e1aab 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuminousScans.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuminousScans.kt @@ -7,6 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser @MangaSourceParser("LUMINOUSSCANS", "LuminousScans", "en") internal class LuminousScans(context: MangaLoaderContext) : - MangaReaderParser(context, MangaSource.LUMINOUSSCANS, "luminousscans.com", pageSize = 20, searchPageSize = 10) { + MangaReaderParser(context, MangaSource.LUMINOUSSCANS, "luminousscans.net", pageSize = 20, searchPageSize = 10) { override val listUrl = "/series" }