Fix warnings (refactor)
This commit is contained in:
@@ -230,7 +230,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
url = jo.getString("hid"),
|
||||
scanlator = jo.optJSONArray("group_name")?.asTypedList<String>()?.joinToString()
|
||||
?.takeUnless { it.isBlank() },
|
||||
uploadDate = dateFormat.tryParse(jo.getString("created_at").substringBefore('T')),
|
||||
uploadDate = dateFormat.parseSafe(jo.getString("created_at").substringBefore('T')),
|
||||
branch = branch,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -202,7 +202,7 @@ internal class ExHentaiParser(
|
||||
val uploadDate = gd3
|
||||
?.selectFirst("tr:contains(Posted)")
|
||||
?.selectFirst(".gdt2")?.ownTextOrNull()
|
||||
.let { SimpleDateFormat("yyyy-MM-dd HH:mm", sourceLocale).tryParse(it) }
|
||||
.let { SimpleDateFormat("yyyy-MM-dd HH:mm", sourceLocale).parseSafe(it) }
|
||||
val uploader = gd3
|
||||
?.getElementsByAttributeValueContaining("href", "/uploader/")
|
||||
?.firstOrNull()
|
||||
|
||||
@@ -590,7 +590,7 @@ internal class HitomiLaParser(context: MangaLoaderContext) : AbstractMangaParser
|
||||
volume = 0,
|
||||
branch = json.getString("language_localname"),
|
||||
source = source,
|
||||
uploadDate = dateFormat.tryParse(json.getString("date").substringBeforeLast("-")),
|
||||
uploadDate = dateFormat.parseSafe(json.getString("date").substringBeforeLast("-")),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -5,11 +5,10 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.core.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.model.search.*
|
||||
import org.koitharu.kotatsu.parsers.util.generateUid
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import org.koitharu.kotatsu.parsers.util.tryParse
|
||||
import org.koitharu.kotatsu.parsers.util.parseSafe
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
@@ -99,7 +98,7 @@ internal class HoloEarthParser(context: MangaLoaderContext) :
|
||||
val url = li.selectFirstOrThrow(".manga-detail__list-link").attr("href")
|
||||
val title = li.selectFirstOrThrow(".manga-detail__list-title").text()
|
||||
val dateStr = li.selectFirstOrThrow(".manga-detail__list-date").text()
|
||||
val uploadDate = dateFormat.tryParse(dateStr) ?: 0L
|
||||
val uploadDate = dateFormat.parseSafe(dateStr) ?: 0L
|
||||
val scanlator = root.selectFirst(".manga-detail__person")?.text()
|
||||
|
||||
MangaChapter(
|
||||
|
||||
@@ -489,7 +489,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : FlexibleMangaParser
|
||||
volume = volume,
|
||||
url = id,
|
||||
scanlator = team,
|
||||
uploadDate = dateFormat.tryParse(attrs.getString("publishAt")),
|
||||
uploadDate = dateFormat.parseSafe(attrs.getString("publishAt")),
|
||||
branch = branch,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -295,7 +295,7 @@ internal abstract class MangaFireParser(
|
||||
},
|
||||
url = "${branch.type}/${it.attr("data-id")}",
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(it.attr("upload-date")),
|
||||
uploadDate = dateFormat.parseSafe(it.attr("upload-date")),
|
||||
branch = "${branch.langTitle} ${branch.type.toTitleCase()}",
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -252,7 +252,7 @@ internal class MangaPark(context: MangaLoaderContext) :
|
||||
}.timeInMillis
|
||||
}
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ internal abstract class NineMangaParser(
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
if (dateWords[1].contains(",")) {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).tryParse(date)
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parseSafe(date)
|
||||
} else {
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
return Calendar.getInstance().apply {
|
||||
|
||||
@@ -128,7 +128,7 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = href,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
|
||||
@@ -202,7 +202,7 @@ internal class FlixScans(context: MangaLoaderContext) :
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
branch = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -200,7 +200,7 @@ internal class TeamXNovel(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(li.selectFirstOrThrow(".epl-date").text()),
|
||||
uploadDate = dateFormat.parseSafe(li.selectFirstOrThrow(".epl-date").text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -185,7 +185,7 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = SimpleDateFormat("MMMM d yyyy", Locale.US)
|
||||
.tryParse(cleanDate),
|
||||
.parseSafe(cleanDate),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.koitharu.kotatsu.parsers.site.en
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.parsers.Broken
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
@@ -130,7 +129,7 @@ internal class BatCave(context: MangaLoaderContext) :
|
||||
url = "/reader/$newsId/$chapterId",
|
||||
number = chapter.getFloatOrDefault("posi", 0f),
|
||||
title = chapter.getStringOrNull("title"),
|
||||
uploadDate = dateFormat.tryParse(chapter.getStringOrNull("date")),
|
||||
uploadDate = dateFormat.parseSafe(chapter.getStringOrNull("date")),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
|
||||
@@ -125,7 +125,7 @@ internal class BeeToon(context: MangaLoaderContext) :
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.ENGLISH)
|
||||
.tryParse(a.selectFirst(".chapter-date")?.attr("title") ?: "0"),
|
||||
.parseSafe(a.selectFirst(".chapter-date")?.attr("title") ?: "0"),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -173,7 +173,7 @@ internal class DemonicScans(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
branch = null,
|
||||
source = source
|
||||
)
|
||||
|
||||
@@ -183,7 +183,7 @@ internal class DynastyScans(context: MangaLoaderContext) :
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = href,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
|
||||
@@ -186,7 +186,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) :
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
branch = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -233,7 +233,7 @@ internal class Hentalk(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
|
||||
val parseTime = dateFormat.tryParse(createdAt)
|
||||
val parseTime = dateFormat.parseSafe(createdAt)
|
||||
val chapter = MangaChapter(
|
||||
id = generateUid("/g/$mangaId/read/1"),
|
||||
url = "/g/$mangaId/read/1/__data.json?x-sveltekit-invalidated=011",
|
||||
|
||||
@@ -149,7 +149,7 @@ internal class MangaGeko(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -249,7 +249,7 @@ internal class MangaTownParser(context: MangaLoaderContext) :
|
||||
date.isNullOrEmpty() -> 0L
|
||||
date.contains("Today") -> Calendar.getInstance().timeInMillis
|
||||
date.contains("Yesterday") -> Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -1) }.timeInMillis
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ internal class Mangaowl(context: MangaLoaderContext) :
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = url,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
|
||||
@@ -149,7 +149,7 @@ internal class ManhwasMen(context: MangaLoaderContext) :
|
||||
val d = date?.lowercase() ?: return 0
|
||||
return when {
|
||||
d.endsWith(" ago") -> parseRelativeDate(date)
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ internal class Po2Scans(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(div.select(".detail span").last()?.text()),
|
||||
uploadDate = dateFormat.parseSafe(div.select(".detail span").last()?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.koitharu.kotatsu.parsers.util.generateUid
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import org.koitharu.kotatsu.parsers.util.urlEncoded
|
||||
import org.koitharu.kotatsu.parsers.util.tryParse
|
||||
import org.koitharu.kotatsu.parsers.util.parseSafe
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
@@ -199,7 +199,7 @@ internal class VioletScans(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
val dateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH)
|
||||
val date = dateFormat.tryParse(dateString) ?: 0L
|
||||
val date = dateFormat.parseSafe(dateString) ?: 0L
|
||||
|
||||
val chaptersList = root.selectFirstOrThrow("#chapterlist ul")
|
||||
val chapters = chaptersList.select("li")
|
||||
|
||||
@@ -172,7 +172,7 @@ internal class VyManga(context: MangaLoaderContext) :
|
||||
val d = date?.lowercase() ?: return 0
|
||||
return when {
|
||||
d.endsWith(" ago") -> parseRelativeDate(date)
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ internal class WeebCentral(context: MangaLoaderContext) : AbstractMangaParser(co
|
||||
"#d8b4fe" -> "Official"
|
||||
else -> null
|
||||
},
|
||||
uploadDate = dateFormat.tryParse(
|
||||
uploadDate = dateFormat.parseSafe(
|
||||
element.selectFirst("time[datetime]")?.attr("datetime"),
|
||||
),
|
||||
branch = null,
|
||||
|
||||
@@ -104,7 +104,7 @@ internal class TempleScanEsp(context: MangaLoaderContext) :
|
||||
parseRelativeDate(d)
|
||||
}
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
url = href,
|
||||
scanlator = element.select("div.col-md-6.text-truncate").text(),
|
||||
branch = null,
|
||||
uploadDate = chapterDateFormat.tryParse(element.select("span.badge.badge-primary.p-2").first()?.text()),
|
||||
uploadDate = chapterDateFormat.parseSafe(element.select("span.badge.badge-primary.p-2").first()?.text()),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -233,7 +233,7 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
url = href,
|
||||
scanlator = element.select("div.col-md-6.text-truncate").text(),
|
||||
branch = null,
|
||||
uploadDate = chapterDateFormat.tryParse(element.select("span.badge.badge-primary.p-2").first()?.text()),
|
||||
uploadDate = chapterDateFormat.parseSafe(element.select("span.badge.badge-primary.p-2").first()?.text()),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -272,9 +272,9 @@ internal abstract class FmreaderParser(
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.let { dateFormat.tryParse(it.joinToString(" ")) }
|
||||
}.let { dateFormat.parseSafe(it.joinToString(" ")) }
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ internal abstract class FoolSlideParser(
|
||||
volume = 0,
|
||||
url = href,
|
||||
uploadDate = if (div.selectFirst(selectDate)?.text()?.contains(", ") == true) {
|
||||
dateFormat.tryParse(dateText)
|
||||
dateFormat.parseSafe(dateText)
|
||||
} else {
|
||||
0
|
||||
},
|
||||
|
||||
@@ -148,7 +148,7 @@ internal class FuryoSociety(context: MangaLoaderContext) :
|
||||
parseRelativeDate(d)
|
||||
}
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -121,7 +121,7 @@ internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -184,7 +184,7 @@ internal class LugnicaScans(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -298,7 +298,7 @@ internal class MangaMana(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -221,9 +221,9 @@ internal class PhenixscansParser(context: MangaLoaderContext) :
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.let { dateFormat.tryParse(it.joinToString(" ")) }
|
||||
}.let { dateFormat.parseSafe(it.joinToString(" ")) }
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ internal class ScantradUnion(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -297,7 +297,7 @@ internal abstract class FuzzyDoodleParser(
|
||||
parseRelativeDate(d)
|
||||
}
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ internal abstract class GalleryParser(
|
||||
volume = 0,
|
||||
url = relUrl,
|
||||
scanlator = null,
|
||||
uploadDate = df.tryParse(time),
|
||||
uploadDate = df.parseSafe(time),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import org.koitharu.kotatsu.parsers.util.src
|
||||
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
|
||||
import org.koitharu.kotatsu.parsers.util.tryParse
|
||||
import org.koitharu.kotatsu.parsers.util.parseSafe
|
||||
import org.koitharu.kotatsu.parsers.util.urlDecode
|
||||
import org.koitharu.kotatsu.parsers.util.urlEncoded
|
||||
import java.text.SimpleDateFormat
|
||||
@@ -177,7 +177,7 @@ internal class HentaiNexus(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = manga.url,
|
||||
scanlator = doc.select(selectPublisher).text().replace(Regex(" \\([\\d,]+\\)")) { "" },
|
||||
uploadDate = format.tryParse(doc.select(selectPublishedDate).text()),
|
||||
uploadDate = format.parseSafe(doc.select(selectPublishedDate).text()),
|
||||
branch = "English",
|
||||
source = source,
|
||||
),
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.koitharu.kotatsu.parsers.util.parseJson
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import org.koitharu.kotatsu.parsers.util.src
|
||||
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
|
||||
import org.koitharu.kotatsu.parsers.util.tryParse
|
||||
import org.koitharu.kotatsu.parsers.util.parseSafe
|
||||
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
@@ -250,7 +250,7 @@ internal class HentaiRead(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = manga.url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(uploadDateString),
|
||||
uploadDate = dateFormat.parseSafe(uploadDateString),
|
||||
branch = "English",
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -164,7 +164,7 @@ internal abstract class HeanCms(
|
||||
volume = 0,
|
||||
url = chapterUrl,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(it.getString("created_at").substringBefore("T")),
|
||||
uploadDate = dateFormat.parseSafe(it.getString("created_at").substringBefore("T")),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -133,7 +133,7 @@ internal abstract class HeanCmsAlt(
|
||||
val d = date?.lowercase() ?: return 0
|
||||
return when {
|
||||
d.startsWith("hace ") || d.endsWith(" antes") -> parseRelativeDate(date)
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ internal abstract class HotComicsParser(
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(li.selectFirst("time")?.attr("datetime")),
|
||||
uploadDate = dateFormat.parseSafe(li.selectFirst("time")?.attr("datetime")),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ internal class DayComics(context: MangaLoaderContext) :
|
||||
val url = element.attr("onclick").substringAfter("popupLogin('").substringBefore("'")
|
||||
val name = element.selectFirst(".cell-num")?.text() ?: "Unknown"
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
val dateUpload = dateFormat.tryParse(element.selectFirst(".cell-time")?.text())
|
||||
val dateUpload = dateFormat.parseSafe(element.selectFirst(".cell-time")?.text())
|
||||
val chapterNum = element.selectFirst(".num")?.text()?.toFloat() ?: (i + 1f)
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
|
||||
@@ -20,7 +20,7 @@ internal class HotComics(context: MangaLoaderContext) :
|
||||
val url = element.attr("onclick").substringAfter("popupLogin('").substringBefore("'")
|
||||
val name = element.selectFirst(".cell-num")?.text() ?: "Unknown"
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
val dateUpload = dateFormat.tryParse(element.selectFirst(".cell-time")?.text())
|
||||
val dateUpload = dateFormat.parseSafe(element.selectFirst(".cell-time")?.text())
|
||||
val chapterNum = element.selectFirst(".num")?.text()?.toFloat() ?: (i + 1f)
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
@@ -40,4 +40,4 @@ internal class HotComics(context: MangaLoaderContext) :
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ internal class DoujinDesuParser(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = chapterDateFormat.tryParse(element.select(".epsleft > .date").text()),
|
||||
uploadDate = chapterDateFormat.parseSafe(element.select(".epsleft > .date").text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -151,7 +151,7 @@ internal class Kumapage(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = row.select("td:nth-child(4) a").attr("href"),
|
||||
scanlator = null,
|
||||
uploadDate = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").tryParse(row.select("td:nth-child(3)").text()),
|
||||
uploadDate = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parseSafe(row.select("td:nth-child(3)").text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.json.JSONObject
|
||||
import org.json.JSONArray
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||
import org.koitharu.kotatsu.parsers.core.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
@@ -156,7 +155,7 @@ internal abstract class IkenParser(
|
||||
volume = 0,
|
||||
url = chapterUrl,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(it.getString("createdAt").substringBefore("T")),
|
||||
uploadDate = dateFormat.parseSafe(it.getString("createdAt").substringBefore("T")),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -283,9 +283,9 @@ internal abstract class KeyoappParser(
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.let { dateFormat.tryParse(it.joinToString(" ")) }
|
||||
}.let { dateFormat.parseSafe(it.joinToString(" ")) }
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ internal abstract class LikeMangaParser(
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
}.timeInMillis
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,9 +805,9 @@ internal abstract class MadaraParser(
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.let { dateFormat.tryParse(it.joinToString(" ")) }
|
||||
}.let { dateFormat.parseSafe(it.joinToString(" ")) }
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -288,9 +288,9 @@ internal abstract class MadthemeParser(
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.let { dateFormat.tryParse(it.joinToString(" ")) }
|
||||
}.let { dateFormat.parseSafe(it.joinToString(" ")) }
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ internal abstract class Manga18Parser(
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = href,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
|
||||
@@ -322,9 +322,9 @@ internal abstract class MangaboxParser(
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.let { dateFormat.tryParse(it.joinToString(" ")) }
|
||||
}.let { dateFormat.parseSafe(it.joinToString(" ")) }
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ internal abstract class MangaReaderParser(
|
||||
number = index + 1f,
|
||||
volume = 0,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(element.selectFirst(".chapterdate")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(element.selectFirst(".chapterdate")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -86,7 +86,7 @@ internal class Normoyun(context: MangaLoaderContext) :
|
||||
number = index + 1f,
|
||||
volume = 0,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(element.selectFirst(".chapter-date")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(element.selectFirst(".chapter-date")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -55,7 +55,7 @@ internal class VexManga(context: MangaLoaderContext) :
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
}.timeInMillis
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ internal class HentaiReader(context: MangaLoaderContext) :
|
||||
number = index + 1f,
|
||||
volume = 0,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(docs.selectFirst("time")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(docs.selectFirst("time")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -85,7 +85,7 @@ internal class LectorHentai(context: MangaLoaderContext) :
|
||||
number = index + 1f,
|
||||
volume = 0,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(docs.selectFirst("time")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(docs.selectFirst("time")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -137,7 +137,7 @@ internal class TuManhwas(context: MangaLoaderContext) :
|
||||
return when {
|
||||
d.startsWith("hace") -> parseRelativeDate(date)
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ internal class RevolutionScantrad(context: MangaLoaderContext) :
|
||||
number = index + 1f,
|
||||
volume = 0,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(element.selectFirst(".chapterdate")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(element.selectFirst(".chapterdate")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -117,7 +117,7 @@ internal class XxxRevolutionScantrad(context: MangaLoaderContext) :
|
||||
number = index + 1f,
|
||||
volume = 0,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(element.selectFirst(".chapterdate")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(element.selectFirst(".chapterdate")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -197,7 +197,7 @@ internal class Komikcast(context: MangaLoaderContext) :
|
||||
parseRelativeDate(date)
|
||||
}
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ internal abstract class MangaWorldParser(
|
||||
url = "$url?style=list",
|
||||
scanlator = null,
|
||||
uploadDate =
|
||||
SimpleDateFormat("dd MMMM yyyy", Locale.ITALIAN).tryParse(
|
||||
SimpleDateFormat("dd MMMM yyyy", Locale.ITALIAN).parseSafe(
|
||||
a.selectFirst(".chap-date")?.text(),
|
||||
),
|
||||
branch = null,
|
||||
|
||||
@@ -228,7 +228,7 @@ internal abstract class MmrcmsParser(
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = href,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
|
||||
@@ -236,7 +236,7 @@ internal abstract class NepnepParser(
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -251,7 +251,7 @@ internal abstract class OtakuSanctuaryParser(
|
||||
parseRelativeDate(d)
|
||||
}
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ internal abstract class PizzaReaderParser(
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
uploadDate = dateFormat.parseSafe(date),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -144,7 +144,7 @@ internal class LerManga(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(div.selectFirstOrThrow("small small").text()),
|
||||
uploadDate = dateFormat.parseSafe(div.selectFirstOrThrow("small small").text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -124,7 +124,7 @@ internal class LerMangaOnline(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -106,7 +106,7 @@ internal class LuratoonScansParser(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(span.nextElementSibling()?.text()),
|
||||
uploadDate = dateFormat.parseSafe(span.nextElementSibling()?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -117,7 +117,7 @@ internal class MangaOnline(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
uploadDate = dateFormat.parseSafe(dateText),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -141,7 +141,7 @@ internal class YugenMangas(context: MangaLoaderContext) :
|
||||
val d = date?.lowercase() ?: return 0
|
||||
return when {
|
||||
d.endsWith(" atrás") -> parseRelativeDate(date)
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.koitharu.kotatsu.parsers.site.en
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.parsers.Broken
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
@@ -141,7 +140,7 @@ internal class ComXParser(context: MangaLoaderContext) :
|
||||
url = "/reader/$newsId/$chapterId",
|
||||
number = chapter.getFloatOrDefault("posi", 0f),
|
||||
title = decodeText(chapter.getStringOrNull("title")),
|
||||
uploadDate = dateFormat.tryParse(chapter.getStringOrNull("date")),
|
||||
uploadDate = dateFormat.parseSafe(chapter.getStringOrNull("date")),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
|
||||
@@ -214,7 +214,7 @@ internal class MangaWtfParser(
|
||||
volume = volume,
|
||||
url = jo.getString("id"),
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(jo.getString("createdAt")),
|
||||
uploadDate = dateFormat.parseSafe(jo.getString("createdAt")),
|
||||
branch = branches.getOrPut(branchId) { getBranchName(branchId) },
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -143,7 +143,7 @@ internal class NudeMoonParser(
|
||||
title = manga.title,
|
||||
scanlator = root.getElementsByAttributeValueContaining("href", "/perevod/").firstOrNull()
|
||||
?.textOrNull(),
|
||||
uploadDate = dateFormat.tryParse(
|
||||
uploadDate = dateFormat.parseSafe(
|
||||
root.getElementsByAttributeValueEnding("src", "ico/time.png").firstOrNull()
|
||||
?.nextElementSibling()?.text(),
|
||||
),
|
||||
|
||||
@@ -176,7 +176,7 @@ internal class RemangaParser(
|
||||
number = jo.getIntOrDefault("index", chapters.size - i).toFloat(),
|
||||
volume = 0,
|
||||
title = name.nullIfEmpty(),
|
||||
uploadDate = dateFormat.tryParse(jo.getString("upload_date")),
|
||||
uploadDate = dateFormat.parseSafe(jo.getString("upload_date")),
|
||||
scanlator = publishers?.optJSONObject(0)?.getStringOrNull("name"),
|
||||
source = MangaParserSource.REMANGA,
|
||||
branch = null,
|
||||
@@ -192,7 +192,7 @@ internal class RemangaParser(
|
||||
val pages = content.optJSONArray("pages")
|
||||
if (pages == null) {
|
||||
val pubDate = content.getStringOrNull("pub_date")?.let {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US).tryParse(it)
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US).parseSafe(it)
|
||||
}
|
||||
if (pubDate != null && pubDate > System.currentTimeMillis()) {
|
||||
val at = SimpleDateFormat.getDateInstance(DateFormat.LONG).format(Date(pubDate))
|
||||
|
||||
@@ -94,7 +94,7 @@ internal class WaMangaParser(
|
||||
volume = it.getIntOrDefault("volume", 0),
|
||||
title = it.getStringOrNull("full_title"),
|
||||
scanlator = it.getJSONArray("teams").getJSONObject(0)?.getStringOrNull("name"),
|
||||
uploadDate = dateFormat.tryParse(it.getStringOrNull("published_on")),
|
||||
uploadDate = dateFormat.parseSafe(it.getStringOrNull("published_on")),
|
||||
branch = null,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -179,7 +179,7 @@ internal abstract class GroupleParser(
|
||||
number = number,
|
||||
volume = volume,
|
||||
url = href.withQueryParam("d", userHash),
|
||||
uploadDate = dateFormat.tryParse(tr.selectFirst("td.date")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(tr.selectFirst("td.date")?.text()),
|
||||
scanlator = translators,
|
||||
source = newSource,
|
||||
branch = null,
|
||||
@@ -196,7 +196,7 @@ internal abstract class GroupleParser(
|
||||
number = number,
|
||||
volume = volume,
|
||||
url = link.withQueryParam("d", userHash),
|
||||
uploadDate = dateFormat.tryParse(jo.getStringOrNull("dateCreated")),
|
||||
uploadDate = dateFormat.parseSafe(jo.getStringOrNull("dateCreated")),
|
||||
scanlator = null,
|
||||
source = newSource,
|
||||
branch = translations[personId],
|
||||
|
||||
@@ -99,7 +99,7 @@ internal abstract class ChanParser(
|
||||
url = href,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
uploadDate = dateFormat.tryParse(tr.selectFirst("div.date")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(tr.selectFirst("div.date")?.text()),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -320,7 +320,7 @@ internal abstract class LibSocialParser(
|
||||
}
|
||||
},
|
||||
scanlator = team,
|
||||
uploadDate = dateFormat.tryParse(bjo.getStringOrNull("created_at")),
|
||||
uploadDate = dateFormat.parseSafe(bjo.getStringOrNull("created_at")),
|
||||
branch = if (useBranching) team else null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -97,7 +97,7 @@ internal abstract class ScanParser(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
|
||||
coverUrl = div.selectFirst("img")?.attr("data-src")?.replace("\t", "").orEmpty(),
|
||||
coverUrl = div.selectFirst("img")?.attr("data-src")?.replace("\t", ""),
|
||||
title = div.selectFirst(".link-series h3, .item-title")?.text().orEmpty(),
|
||||
altTitles = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
@@ -116,10 +116,10 @@ internal abstract class ScanParser(
|
||||
|
||||
protected suspend fun getOrCreateTagMap(): Map<String, MangaTag> = mutex.withLock {
|
||||
tagCache?.let { return@withLock it }
|
||||
val tagMap = ArrayMap<String, MangaTag>()
|
||||
val tagElements = webClient.httpGet("https://$domain$listUrl").parseHtml()
|
||||
.requireElementById("filter-wrapper")
|
||||
.select(".form-filters div.form-check, .form-filters div.custom-control")
|
||||
val tagMap = ArrayMap<String, MangaTag>(tagElements.size)
|
||||
for (el in tagElements) {
|
||||
val name = el.selectFirstOrThrow("label").text()
|
||||
if (name.isEmpty()) continue
|
||||
@@ -130,7 +130,7 @@ internal abstract class ScanParser(
|
||||
)
|
||||
}
|
||||
tagCache = tagMap
|
||||
return@withLock tagMap
|
||||
tagMap
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
@@ -162,7 +162,7 @@ internal abstract class ScanParser(
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(doc.selectFirst("h5 div")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(doc.selectFirst("h5 div")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ internal class MangaFr(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(doc.selectFirstOrThrow("h5 div").text()),
|
||||
uploadDate = dateFormat.parseSafe(doc.selectFirstOrThrow("h5 div").text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -50,7 +50,7 @@ internal class ScanIta(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(doc.selectFirstOrThrow("h5 div").text()),
|
||||
uploadDate = dateFormat.parseSafe(doc.selectFirstOrThrow("h5 div").text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -174,7 +174,7 @@ internal abstract class SinmhParser(
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
title = a.text(),
|
||||
title = a.textOrNull(),
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = href,
|
||||
|
||||
@@ -159,7 +159,7 @@ internal class ElderManga(context: MangaLoaderContext):
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = el.selectFirst("span")?.text()?.let { dateFormat.tryParse(it) } ?: 0L,
|
||||
uploadDate = el.selectFirst("span")?.text()?.let { dateFormat.parseSafe(it) } ?: 0L,
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -65,7 +65,7 @@ internal class EleceedTurkiye(context: MangaLoaderContext) :
|
||||
title = title,
|
||||
number = title?.let { Regex("\\d+").find(it)?.value?.toFloatOrNull() } ?: 0f,
|
||||
url = href,
|
||||
uploadDate = dateFormat.tryParse(div.selectFirst("span.chapterdate")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(div.selectFirst("span.chapterdate")?.text()),
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
source = source,
|
||||
|
||||
@@ -90,14 +90,14 @@ internal class MangaAy(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
url = href,
|
||||
publicUrl = a.attrAsAbsoluteUrl("href"),
|
||||
title = div.selectLast(".item-name")?.text().orEmpty(),
|
||||
coverUrl = div.selectFirst("img")?.src().orEmpty(),
|
||||
coverUrl = div.selectFirst("img")?.src(),
|
||||
altTitles = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
description = null,
|
||||
state = null,
|
||||
authors = emptySet(),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
contentRating = sourceContentRating,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -119,7 +119,7 @@ internal class MangaAy(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
description = null,
|
||||
state = null,
|
||||
authors = emptySet(),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
contentRating = sourceContentRating,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -152,7 +152,8 @@ internal class MangaAy(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
val tags = doc.select("P.card-text .bg-success").mapNotNullToSet { tagMap[it.text()] }
|
||||
return manga.copy(
|
||||
description = doc.selectFirst("p.card-text")?.html()?.substringAfterLast("<br>"),
|
||||
coverUrl = doc.selectFirst("div.align-items-center div.align-items-center img")?.src().orEmpty(),
|
||||
coverUrl = doc.selectFirst("div.align-items-center div.align-items-center img")?.src()
|
||||
?: manga.coverUrl,
|
||||
tags = tags,
|
||||
chapters = doc.requireElementById("sonyuklemeler").select("tbody tr")
|
||||
.mapChapters(reversed = true) { i, tr ->
|
||||
@@ -165,7 +166,7 @@ internal class MangaAy(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(tr.selectFirstOrThrow("time").attr("datetime")),
|
||||
uploadDate = dateFormat.parseSafe(tr.selectFirstOrThrow("time").attr("datetime")),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -80,12 +80,12 @@ internal class SadScans(context: MangaLoaderContext) :
|
||||
val url = "/" + a.attrAsRelativeUrl("href")
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
title = a.text(),
|
||||
title = a.textOrNull(),
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(div.select(".detail span").last()?.text()),
|
||||
uploadDate = dateFormat.parseSafe(div.select(".detail span").last()?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -7,198 +7,199 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.core.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("TENSHIMANGA", "Tenshi Manga", "tr")
|
||||
internal class TenshiManga(context: MangaLoaderContext):
|
||||
PagedMangaParser(context, MangaParserSource.TENSHIMANGA, 25) {
|
||||
internal class TenshiManga(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaParserSource.TENSHIMANGA, 25) {
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("tenshimanga.com")
|
||||
private val cdnSuffix = "cdn1.$domain"
|
||||
override val configKeyDomain = ConfigKey.Domain("tenshimanga.com")
|
||||
private val cdnSuffix = "cdn1.$domain"
|
||||
|
||||
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
|
||||
super.onCreateConfig(keys)
|
||||
keys.add(userAgentKey)
|
||||
}
|
||||
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
|
||||
super.onCreateConfig(keys)
|
||||
keys.add(userAgentKey)
|
||||
}
|
||||
|
||||
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
|
||||
SortOrder.ALPHABETICAL,
|
||||
SortOrder.ALPHABETICAL_DESC,
|
||||
SortOrder.NEWEST,
|
||||
SortOrder.POPULARITY,
|
||||
SortOrder.UPDATED,
|
||||
)
|
||||
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
|
||||
SortOrder.ALPHABETICAL,
|
||||
SortOrder.ALPHABETICAL_DESC,
|
||||
SortOrder.NEWEST,
|
||||
SortOrder.POPULARITY,
|
||||
SortOrder.UPDATED,
|
||||
)
|
||||
|
||||
override val filterCapabilities: MangaListFilterCapabilities
|
||||
get() = MangaListFilterCapabilities(
|
||||
isSearchSupported = true,
|
||||
isMultipleTagsSupported = true,
|
||||
isSearchWithFiltersSupported = true,
|
||||
)
|
||||
override val filterCapabilities: MangaListFilterCapabilities
|
||||
get() = MangaListFilterCapabilities(
|
||||
isSearchSupported = true,
|
||||
isMultipleTagsSupported = true,
|
||||
isSearchWithFiltersSupported = true,
|
||||
)
|
||||
|
||||
override suspend fun getFilterOptions() = MangaListFilterOptions(
|
||||
availableTags = fetchTags(),
|
||||
availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED, MangaState.PAUSED),
|
||||
availableContentTypes = EnumSet.of(
|
||||
ContentType.MANGA,
|
||||
ContentType.MANHWA,
|
||||
ContentType.MANHUA,
|
||||
ContentType.COMICS,
|
||||
),
|
||||
)
|
||||
override suspend fun getFilterOptions() = MangaListFilterOptions(
|
||||
availableTags = fetchTags(),
|
||||
availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED, MangaState.PAUSED),
|
||||
availableContentTypes = EnumSet.of(
|
||||
ContentType.MANGA,
|
||||
ContentType.MANHWA,
|
||||
ContentType.MANHUA,
|
||||
ContentType.COMICS,
|
||||
),
|
||||
)
|
||||
|
||||
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/search")
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/search")
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
|
||||
if (!filter.query.isNullOrEmpty()) {
|
||||
append("&search=")
|
||||
append(filter.query.urlEncoded())
|
||||
}
|
||||
if (!filter.query.isNullOrEmpty()) {
|
||||
append("&search=")
|
||||
append(filter.query.urlEncoded())
|
||||
}
|
||||
|
||||
if (filter.tags.isNotEmpty()) {
|
||||
append("&categories=")
|
||||
filter.tags.joinTo(this, ",") { it.key }
|
||||
}
|
||||
if (filter.tags.isNotEmpty()) {
|
||||
append("&categories=")
|
||||
filter.tags.joinTo(this, ",") { it.key }
|
||||
}
|
||||
|
||||
if (filter.states.isNotEmpty()) {
|
||||
append("&publicStatus=")
|
||||
filter.states.oneOrThrowIfMany()?.let {
|
||||
append(
|
||||
when (it) {
|
||||
MangaState.ONGOING -> "1"
|
||||
MangaState.FINISHED -> "2"
|
||||
MangaState.ABANDONED -> "3"
|
||||
MangaState.PAUSED -> "4"
|
||||
else -> ""
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
if (filter.states.isNotEmpty()) {
|
||||
append("&publicStatus=")
|
||||
filter.states.oneOrThrowIfMany()?.let {
|
||||
append(
|
||||
when (it) {
|
||||
MangaState.ONGOING -> "1"
|
||||
MangaState.FINISHED -> "2"
|
||||
MangaState.ABANDONED -> "3"
|
||||
MangaState.PAUSED -> "4"
|
||||
else -> ""
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.types.isNotEmpty()) {
|
||||
append("&country=")
|
||||
filter.types.oneOrThrowIfMany()?.let {
|
||||
append(
|
||||
when (it) {
|
||||
ContentType.MANHUA -> "1"
|
||||
ContentType.MANHWA -> "2"
|
||||
ContentType.MANGA -> "3"
|
||||
ContentType.COMICS -> "4"
|
||||
else -> ""
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
if (filter.types.isNotEmpty()) {
|
||||
append("&country=")
|
||||
filter.types.oneOrThrowIfMany()?.let {
|
||||
append(
|
||||
when (it) {
|
||||
ContentType.MANHUA -> "1"
|
||||
ContentType.MANHWA -> "2"
|
||||
ContentType.MANGA -> "3"
|
||||
ContentType.COMICS -> "4"
|
||||
else -> ""
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
append("&order=")
|
||||
append(
|
||||
when (order) {
|
||||
SortOrder.ALPHABETICAL -> "1"
|
||||
SortOrder.ALPHABETICAL_DESC -> "2"
|
||||
SortOrder.NEWEST -> "3"
|
||||
SortOrder.POPULARITY -> "4"
|
||||
SortOrder.UPDATED, -> "5"
|
||||
else -> "1"
|
||||
}
|
||||
)
|
||||
}
|
||||
append("&order=")
|
||||
append(
|
||||
when (order) {
|
||||
SortOrder.ALPHABETICAL -> "1"
|
||||
SortOrder.ALPHABETICAL_DESC -> "2"
|
||||
SortOrder.NEWEST -> "3"
|
||||
SortOrder.POPULARITY -> "4"
|
||||
SortOrder.UPDATED -> "5"
|
||||
else -> "1"
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("section[aria-label='series area'] .card").map { card ->
|
||||
val href = card.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = card.selectFirst("h2")?.text().orEmpty(),
|
||||
altTitles = emptySet(),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
contentRating = null,
|
||||
coverUrl = card.selectFirst("img")?.attrAsAbsoluteUrlOrNull("src"),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("section[aria-label='series area'] .card").map { card ->
|
||||
val href = card.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = card.selectFirst("h2")?.text().orEmpty(),
|
||||
altTitles = emptySet(),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
contentRating = null,
|
||||
coverUrl = card.selectFirst("img")?.attrAsAbsoluteUrlOrNull("src"),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val statusText = doc.selectFirst("span:contains(Durum) + span")?.text().orEmpty()
|
||||
return manga.copy(
|
||||
tags = doc.select("a[href^='search?categories']").mapToSet {
|
||||
val key = it.attr("href").substringAfter("?categories=")
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
description = doc.selectFirst("div.grid h2 + p")?.text(),
|
||||
state = when (statusText) {
|
||||
"Devam Ediyor" -> MangaState.ONGOING
|
||||
"Birakildi" -> MangaState.ONGOING
|
||||
"Tamamlandi" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
chapters = doc.select("div.list-episode a").mapChapters(reversed = true) { i, el ->
|
||||
val href = el.attrAsRelativeUrl("href")
|
||||
val dateFormat = SimpleDateFormat("MMM d ,yyyy", Locale("tr"))
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
title = el.selectFirstOrThrow("h3").text(),
|
||||
number = (i + 1).toFloat(),
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = el.selectFirst("span")?.text()?.let { dateFormat.tryParse(it) } ?: 0L,
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val statusText = doc.selectFirst("span:contains(Durum) + span")?.text().orEmpty()
|
||||
return manga.copy(
|
||||
tags = doc.select("a[href^='search?categories']").mapToSet {
|
||||
val key = it.attr("href").substringAfter("?categories=")
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
description = doc.selectFirst("div.grid h2 + p")?.text(),
|
||||
state = when (statusText) {
|
||||
"Devam Ediyor" -> MangaState.ONGOING
|
||||
"Birakildi" -> MangaState.ONGOING
|
||||
"Tamamlandi" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
chapters = doc.select("div.list-episode a").mapChapters(reversed = true) { i, el ->
|
||||
val href = el.attrAsRelativeUrl("href")
|
||||
val dateFormat = SimpleDateFormat("MMM d ,yyyy", Locale("tr"))
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
title = el.selectFirst("h3")?.textOrNull(),
|
||||
number = (i + 1).toFloat(),
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.parseSafe(el.selectFirst("span")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val pageRegex = Regex("\\\\\"path\\\\\":\\\\\"([^\"]+)\\\\\"")
|
||||
val script = doc.select("script").find { it.html().contains(pageRegex) }?.html() ?: return emptyList()
|
||||
return pageRegex.findAll(script).mapNotNull { result ->
|
||||
result.groups[1]?.value?.let { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = "https://$cdnSuffix/upload/series/$url",
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val pageRegex = Regex("\\\\\"path\\\\\":\\\\\"([^\"]+)\\\\\"")
|
||||
val script = doc.select("script").find { it.html().contains(pageRegex) }?.html() ?: return emptyList()
|
||||
return pageRegex.findAll(script).mapNotNull { result ->
|
||||
result.groups[1]?.value?.let { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = "https://$cdnSuffix/upload/series/$url",
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private suspend fun fetchTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/search").parseHtml()
|
||||
val script = doc.select("script").find { it.html().contains("self.__next_f.push([1,\"10:[\\\"\\$,\\\"section") }?.html()
|
||||
?: return emptySet()
|
||||
|
||||
val jsonStr = script.substringAfter("\"category\":[")
|
||||
.substringBefore("],\"searchParams\":{}")
|
||||
.replace("\\", "")
|
||||
|
||||
val jsonArray = JSONArray("[$jsonStr]")
|
||||
return jsonArray.mapJSONToSet { jo ->
|
||||
MangaTag(
|
||||
key = jo.getString("id"),
|
||||
title = jo.getString("name"),
|
||||
source = source
|
||||
)
|
||||
}
|
||||
}
|
||||
private suspend fun fetchTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/search").parseHtml()
|
||||
val script =
|
||||
doc.select("script").find { it.html().contains("self.__next_f.push([1,\"10:[\\\"\\$,\\\"section") }?.html()
|
||||
?: return emptySet()
|
||||
|
||||
val jsonStr = script.substringAfter("\"category\":[")
|
||||
.substringBefore("],\"searchParams\":{}")
|
||||
.replace("\\", "")
|
||||
|
||||
val jsonArray = JSONArray("[$jsonStr]")
|
||||
return jsonArray.mapJSONToSet { jo ->
|
||||
MangaTag(
|
||||
key = jo.getString("id"),
|
||||
title = jo.getString("name"),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ internal class TrWebtoon(context: MangaLoaderContext) :
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
coverUrl = li.selectFirst("img")?.src().orEmpty(),
|
||||
coverUrl = li.selectFirst("img")?.src(),
|
||||
title = li.selectFirst(".table-responsive a")?.text().orEmpty(),
|
||||
altTitles = emptySet(),
|
||||
rating = li.selectFirst(".row .col-xl-4 .mt-2 .my-1 .text-muted")?.text()?.substringBefore("/")
|
||||
@@ -117,7 +117,7 @@ internal class TrWebtoon(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
contentRating = sourceContentRating,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ internal class TrWebtoon(context: MangaLoaderContext) :
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
coverUrl = li.selectFirst(".figure img")?.src().orEmpty(),
|
||||
coverUrl = li.selectFirst(".figure img")?.src(),
|
||||
title = li.selectFirst(".title")?.text().orEmpty(),
|
||||
altTitles = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
@@ -207,7 +207,7 @@ internal class TrWebtoon(context: MangaLoaderContext) :
|
||||
|
||||
d.endsWith(" önce") -> parseRelativeDate(date)
|
||||
|
||||
else -> dateFormat.tryParse(date)
|
||||
else -> dateFormat.parseSafe(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,83 +7,83 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.core.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("UZAYMANGA", "Uzay Manga", "tr")
|
||||
internal class UzayManga(context: MangaLoaderContext):
|
||||
PagedMangaParser(context, MangaParserSource.UZAYMANGA, 25) {
|
||||
internal class UzayManga(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaParserSource.UZAYMANGA, 25) {
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("uzaymanga.com")
|
||||
private val cdnSuffix = "cdn1.$domain"
|
||||
override val configKeyDomain = ConfigKey.Domain("uzaymanga.com")
|
||||
private val cdnSuffix = "cdn1.$domain"
|
||||
|
||||
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
|
||||
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
|
||||
super.onCreateConfig(keys)
|
||||
keys.add(userAgentKey)
|
||||
}
|
||||
|
||||
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
|
||||
SortOrder.ALPHABETICAL,
|
||||
SortOrder.ALPHABETICAL_DESC,
|
||||
SortOrder.NEWEST,
|
||||
SortOrder.POPULARITY,
|
||||
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
|
||||
SortOrder.ALPHABETICAL,
|
||||
SortOrder.ALPHABETICAL_DESC,
|
||||
SortOrder.NEWEST,
|
||||
SortOrder.POPULARITY,
|
||||
SortOrder.UPDATED,
|
||||
)
|
||||
)
|
||||
|
||||
override val filterCapabilities: MangaListFilterCapabilities
|
||||
get() = MangaListFilterCapabilities(
|
||||
isSearchSupported = true,
|
||||
isMultipleTagsSupported = true,
|
||||
isSearchWithFiltersSupported = true,
|
||||
)
|
||||
override val filterCapabilities: MangaListFilterCapabilities
|
||||
get() = MangaListFilterCapabilities(
|
||||
isSearchSupported = true,
|
||||
isMultipleTagsSupported = true,
|
||||
isSearchWithFiltersSupported = true,
|
||||
)
|
||||
|
||||
override suspend fun getFilterOptions() = MangaListFilterOptions(
|
||||
availableTags = fetchTags(),
|
||||
availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED, MangaState.PAUSED),
|
||||
availableContentTypes = EnumSet.of(
|
||||
ContentType.MANGA,
|
||||
ContentType.MANHWA,
|
||||
ContentType.MANHUA,
|
||||
ContentType.COMICS,
|
||||
),
|
||||
)
|
||||
override suspend fun getFilterOptions() = MangaListFilterOptions(
|
||||
availableTags = fetchTags(),
|
||||
availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED, MangaState.PAUSED),
|
||||
availableContentTypes = EnumSet.of(
|
||||
ContentType.MANGA,
|
||||
ContentType.MANHWA,
|
||||
ContentType.MANHUA,
|
||||
ContentType.COMICS,
|
||||
),
|
||||
)
|
||||
|
||||
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/search")
|
||||
append("?page=")
|
||||
append("/search")
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
|
||||
if (!filter.query.isNullOrEmpty()) {
|
||||
append("&search=")
|
||||
append(filter.query.urlEncoded())
|
||||
}
|
||||
if (!filter.query.isNullOrEmpty()) {
|
||||
append("&search=")
|
||||
append(filter.query.urlEncoded())
|
||||
}
|
||||
|
||||
if (filter.tags.isNotEmpty()) {
|
||||
append("&categories=")
|
||||
if (filter.tags.isNotEmpty()) {
|
||||
append("&categories=")
|
||||
filter.tags.joinTo(this, ",") { it.key }
|
||||
}
|
||||
|
||||
if (filter.states.isNotEmpty()) {
|
||||
append("&publicStatus=")
|
||||
if (filter.states.isNotEmpty()) {
|
||||
append("&publicStatus=")
|
||||
filter.states.oneOrThrowIfMany()?.let {
|
||||
append(
|
||||
when (it) {
|
||||
MangaState.ONGOING -> "1"
|
||||
MangaState.FINISHED -> "2"
|
||||
MangaState.ABANDONED -> "3"
|
||||
MangaState.PAUSED -> "4"
|
||||
MangaState.ABANDONED -> "3"
|
||||
MangaState.PAUSED -> "4"
|
||||
else -> ""
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.types.isNotEmpty()) {
|
||||
append("&country=")
|
||||
if (filter.types.isNotEmpty()) {
|
||||
append("&country=")
|
||||
filter.types.oneOrThrowIfMany()?.let {
|
||||
append(
|
||||
when (it) {
|
||||
@@ -97,108 +97,109 @@ internal class UzayManga(context: MangaLoaderContext):
|
||||
}
|
||||
}
|
||||
|
||||
append("&order=")
|
||||
append(
|
||||
when (order) {
|
||||
SortOrder.ALPHABETICAL -> "1"
|
||||
SortOrder.ALPHABETICAL_DESC -> "2"
|
||||
SortOrder.NEWEST -> "3"
|
||||
SortOrder.POPULARITY -> "4"
|
||||
append("&order=")
|
||||
append(
|
||||
when (order) {
|
||||
SortOrder.ALPHABETICAL -> "1"
|
||||
SortOrder.ALPHABETICAL_DESC -> "2"
|
||||
SortOrder.NEWEST -> "3"
|
||||
SortOrder.POPULARITY -> "4"
|
||||
SortOrder.UPDATED -> "5"
|
||||
else -> "1"
|
||||
}
|
||||
)
|
||||
}
|
||||
else -> "1"
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("section[aria-label='series area'] .card").map { card ->
|
||||
val href = card.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = card.selectFirst("h2")?.text().orEmpty(),
|
||||
altTitles = emptySet(),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
contentRating = null,
|
||||
coverUrl = card.selectFirst("img")?.attrAsAbsoluteUrlOrNull("src"),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("section[aria-label='series area'] .card").map { card ->
|
||||
val href = card.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = card.selectFirst("h2")?.text().orEmpty(),
|
||||
altTitles = emptySet(),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
contentRating = null,
|
||||
coverUrl = card.selectFirst("img")?.attrAsAbsoluteUrlOrNull("src"),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val statusText = doc.selectFirst("span:contains(Durum) + span")?.text().orEmpty()
|
||||
return manga.copy(
|
||||
tags = doc.select("a[href^='search?categories']").mapToSet {
|
||||
val key = it.attr("href").substringAfter("?categories=")
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
description = doc.selectFirst("div.grid h2 + p")?.text(),
|
||||
state = when (statusText) {
|
||||
"Devam Ediyor" -> MangaState.ONGOING
|
||||
"Birakildi" -> MangaState.ONGOING
|
||||
"Tamamlandi" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
chapters = doc.select("div.list-episode a").mapChapters(reversed = true) { i, el ->
|
||||
val href = el.attrAsRelativeUrl("href")
|
||||
val dateFormat = SimpleDateFormat("MMM d ,yyyy", Locale("tr"))
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
title = el.selectFirstOrThrow("h3").text(),
|
||||
number = (i + 1).toFloat(),
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = el.selectFirst("span")?.text()?.let { dateFormat.tryParse(it) } ?: 0L,
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val statusText = doc.selectFirst("span:contains(Durum) + span")?.text().orEmpty()
|
||||
return manga.copy(
|
||||
tags = doc.select("a[href^='search?categories']").mapToSet {
|
||||
val key = it.attr("href").substringAfter("?categories=")
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
description = doc.selectFirst("div.grid h2 + p")?.text(),
|
||||
state = when (statusText) {
|
||||
"Devam Ediyor" -> MangaState.ONGOING
|
||||
"Birakildi" -> MangaState.ONGOING
|
||||
"Tamamlandi" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
chapters = doc.select("div.list-episode a").mapChapters(reversed = true) { i, el ->
|
||||
val href = el.attrAsRelativeUrl("href")
|
||||
val dateFormat = SimpleDateFormat("MMM d ,yyyy", Locale("tr"))
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
title = el.selectFirst("h3")?.textOrNull(),
|
||||
number = (i + 1).toFloat(),
|
||||
volume = 0,
|
||||
url = href,
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.parseSafe(el.selectFirst("span")?.text()),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val pageRegex = Regex("\\\\\"path\\\\\":\\\\\"([^\"]+)\\\\\"")
|
||||
val script = doc.select("script").find { it.html().contains(pageRegex) }?.html() ?: return emptyList()
|
||||
return pageRegex.findAll(script).mapNotNull { result ->
|
||||
result.groups[1]?.value?.let { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = "https://$cdnSuffix/upload/series/$url",
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val pageRegex = Regex("\\\\\"path\\\\\":\\\\\"([^\"]+)\\\\\"")
|
||||
val script = doc.select("script").find { it.html().contains(pageRegex) }?.html() ?: return emptyList()
|
||||
return pageRegex.findAll(script).mapNotNull { result ->
|
||||
result.groups[1]?.value?.let { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = "https://$cdnSuffix/upload/series/$url",
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private suspend fun fetchTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/search").parseHtml()
|
||||
val script = doc.select("script").find { it.html().contains("self.__next_f.push([1,\"10:[\\\"\\$,\\\"section") }?.html()
|
||||
?: return emptySet()
|
||||
|
||||
val jsonStr = script.substringAfter("\"category\":[")
|
||||
.substringBefore("],\"searchParams\":{}")
|
||||
.replace("\\", "")
|
||||
|
||||
val jsonArray = JSONArray("[$jsonStr]")
|
||||
return jsonArray.mapJSONToSet { jo ->
|
||||
MangaTag(
|
||||
key = jo.getString("id"),
|
||||
title = jo.getString("name"),
|
||||
source = source
|
||||
)
|
||||
}
|
||||
}
|
||||
private suspend fun fetchTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/search").parseHtml()
|
||||
val script =
|
||||
doc.select("script").find { it.html().contains("self.__next_f.push([1,\"10:[\\\"\\$,\\\"section") }?.html()
|
||||
?: return emptySet()
|
||||
|
||||
val jsonStr = script.substringAfter("\"category\":[")
|
||||
.substringBefore("],\"searchParams\":{}")
|
||||
.replace("\\", "")
|
||||
|
||||
val jsonArray = JSONArray("[$jsonStr]")
|
||||
return jsonArray.mapJSONToSet { jo ->
|
||||
MangaTag(
|
||||
key = jo.getString("id"),
|
||||
title = jo.getString("name"),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ internal class HentaiUkrParser(context: MangaLoaderContext) : AbstractMangaParse
|
||||
volume = 0,
|
||||
url = manga.url,
|
||||
scanlator = null,
|
||||
uploadDate = date.tryParse(jsonDeferred.await().getString("add_date")),
|
||||
uploadDate = date.parseSafe(jsonDeferred.await().getString("add_date")),
|
||||
branch = null,
|
||||
source = source,
|
||||
),
|
||||
|
||||
@@ -80,7 +80,7 @@ internal class HoneyMangaParser(context: MangaLoaderContext) :
|
||||
volume = volume,
|
||||
url = jo.optString("chapterResourcesId"),
|
||||
scanlator = null,
|
||||
uploadDate = dateFormat.tryParse(jo.getString("lastUpdated")),
|
||||
uploadDate = dateFormat.parseSafe(jo.getString("lastUpdated")),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -145,7 +145,7 @@ internal class MangaInUaParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
} else {
|
||||
DEF_BRANCH_NAME
|
||||
},
|
||||
uploadDate = dateFormat.tryParse(item.selectFirst("div.ltcright")?.text()),
|
||||
uploadDate = dateFormat.parseSafe(item.selectFirst("div.ltcright")?.text()),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -150,7 +150,7 @@ internal class BlogTruyenParser(context: MangaLoaderContext) :
|
||||
val name = titleElement.text()
|
||||
val relativeUrl = titleElement.attrAsRelativeUrl("href")
|
||||
val id = relativeUrl.substringAfter('/').substringBefore('/')
|
||||
val uploadDate = dateFormat.tryParse(element.select("span.publishedDate").text())
|
||||
val uploadDate = dateFormat.parseSafe(element.select("span.publishedDate").text())
|
||||
MangaChapter(
|
||||
id = generateUid(id),
|
||||
title = name,
|
||||
|
||||
@@ -202,7 +202,7 @@ internal class BlogTruyenVN(context: MangaLoaderContext) :
|
||||
val name = titleElement.text()
|
||||
val relativeUrl = titleElement.attrAsRelativeUrl("href")
|
||||
val id = relativeUrl.substringAfter('/').substringBefore('/')
|
||||
val uploadDate = dateFormat.tryParse(element.select("span.publishedDate").text())
|
||||
val uploadDate = dateFormat.parseSafe(element.select("span.publishedDate").text())
|
||||
MangaChapter(
|
||||
id = generateUid(id),
|
||||
title = name,
|
||||
|
||||
@@ -94,7 +94,7 @@ internal class CMangaParser(context: MangaLoaderContext) :
|
||||
number = chapterNumber,
|
||||
volume = 0,
|
||||
url = "/album/$slug/chapter-$mangaId-$chapterId",
|
||||
uploadDate = df.tryParse(info.getString("last_update")),
|
||||
uploadDate = df.parseSafe(info.getString("last_update")),
|
||||
branch = null,
|
||||
scanlator = null,
|
||||
source = source,
|
||||
|
||||
@@ -197,7 +197,7 @@ internal class CuuTruyenParser(context: MangaLoaderContext) :
|
||||
volume = 0,
|
||||
url = "/api/v2/chapters/$chapterId",
|
||||
scanlator = team,
|
||||
uploadDate = chapterDateFormat.tryParse(jo.getStringOrNull("created_at")),
|
||||
uploadDate = chapterDateFormat.parseSafe(jo.getStringOrNull("created_at")),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user