Chapter date parse optimization
This commit is contained in:
@@ -6,15 +6,15 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion '30.0.3'
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'org.koitharu.kotatsu'
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 369
|
||||
versionName '2.0-b1'
|
||||
targetSdkVersion 31
|
||||
versionCode 370
|
||||
versionName '2.0-b2'
|
||||
generatedDensities = []
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
@@ -82,7 +82,7 @@ dependencies {
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
implementation 'androidx.work:work-runtime-ktx:2.6.0'
|
||||
implementation 'androidx.work:work-runtime-ktx:2.7.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
//noinspection LifecycleAnnotationProcessorWithJava8
|
||||
kapt 'androidx.lifecycle:lifecycle-compiler:2.3.1'
|
||||
@@ -93,13 +93,13 @@ dependencies {
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
|
||||
implementation 'com.squareup.okio:okio:2.10.0'
|
||||
implementation 'org.jsoup:jsoup:1.14.2'
|
||||
implementation 'org.jsoup:jsoup:1.14.3'
|
||||
|
||||
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.0'
|
||||
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.0'
|
||||
|
||||
implementation 'io.insert-koin:koin-android:3.1.2'
|
||||
implementation 'io.coil-kt:coil-base:1.3.2'
|
||||
implementation 'io.coil-kt:coil-base:1.4.0'
|
||||
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
|
||||
implementation 'com.github.solkin:disk-lru-cache:1.3'
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
|
||||
val doc = loaderContext.httpGet(manga.url.withDomain()).parseHtml()
|
||||
val root =
|
||||
doc.body().getElementById("dle-content") ?: throw ParseException("Cannot find root")
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
return manga.copy(
|
||||
description = root.getElementById("description")?.html()?.substringBeforeLast("<div"),
|
||||
largeCoverUrl = root.getElementById("cover")?.absUrl("src"),
|
||||
@@ -87,7 +88,7 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
|
||||
name = tr.selectFirst("a")?.text().orEmpty(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(tr.selectFirst("div.date")?.text().orEmpty()),
|
||||
uploadDate = dateFormat.tryParse(tr.selectFirst("div.date")?.text()),
|
||||
source = source
|
||||
)
|
||||
}
|
||||
@@ -155,8 +156,4 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
|
||||
else -> "favdesc"
|
||||
}
|
||||
|
||||
private fun parseChapterDate(string: String): Long {
|
||||
return SimpleDateFormat("yyyy-MM-dd", Locale.US).tryParse(string)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -109,6 +109,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
||||
val doc = loaderContext.httpGet(manga.url.withDomain(), HEADER).parseHtml()
|
||||
val root = doc.body().getElementById("mangaBox")?.selectFirst("div.leftContent")
|
||||
?: throw ParseException("Cannot find root")
|
||||
val dateFormat = SimpleDateFormat("dd.MM.yy", Locale.US)
|
||||
return manga.copy(
|
||||
description = root.selectFirst("div.manga-description")?.html(),
|
||||
largeCoverUrl = root.selectFirst("div.subject-cower")?.selectFirst("img")?.attr(
|
||||
@@ -139,7 +140,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
||||
name = tr.selectFirst("a")?.text().orEmpty().removePrefix(manga.title).trim(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(tr.select("td.d-none").text()),
|
||||
uploadDate = dateFormat.tryParse(tr.selectFirst("td.d-none")?.text()),
|
||||
scanlator = translators,
|
||||
source = source
|
||||
)
|
||||
@@ -234,10 +235,6 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
||||
return loaderContext.httpPost(url, payload)
|
||||
}
|
||||
|
||||
private fun parseChapterDate(string: String): Long {
|
||||
return SimpleDateFormat("dd.MM.yy", Locale.US).tryParse(string)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
private const val PAGE_SIZE = 70
|
||||
|
||||
@@ -80,6 +80,7 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||
val info = root.selectFirst("div.media-content")
|
||||
val chaptersDoc = loaderContext.httpGet("$fullUrl?section=chapters").parseHtml()
|
||||
val scripts = chaptersDoc.select("script")
|
||||
val dateFormat = SimpleDateFormat("yyy-MM-dd", Locale.US)
|
||||
var chapters: ArrayList<MangaChapter>? = null
|
||||
scripts@ for (script in scripts) {
|
||||
val raw = script.html().lines()
|
||||
@@ -113,7 +114,9 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||
url = url,
|
||||
source = source,
|
||||
number = total - i,
|
||||
uploadDate = parseChapterDate(item.getString("chapter_created_at").substringBefore(" ")),
|
||||
uploadDate = dateFormat.tryParse(
|
||||
item.getString("chapter_created_at").substringBefore(" ")
|
||||
),
|
||||
scanlator = scanlator,
|
||||
name = if (nameChapter.isNullOrBlank()) fullNameChapter else "$fullNameChapter - $nameChapter"
|
||||
)
|
||||
@@ -241,9 +244,4 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseChapterDate(string: String): Long {
|
||||
return SimpleDateFormat("yyy-MM-dd", Locale.US).tryParse(string)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -74,6 +74,7 @@ class MangaOwlRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
|
||||
val doc = loaderContext.httpGet(manga.publicUrl).parseHtml()
|
||||
val info = doc.body().selectFirst("div.single_detail") ?: parseFailed("An error occurred while parsing")
|
||||
val table = doc.body().selectFirst("div.single-grid-right") ?: parseFailed("An error occurred while parsing")
|
||||
val dateFormat = SimpleDateFormat("MM/dd/yyyy", Locale.US)
|
||||
return manga.copy(
|
||||
description = info.selectFirst(".description")?.html(),
|
||||
largeCoverUrl = info.select("img").first()?.let { img ->
|
||||
@@ -100,7 +101,7 @@ class MangaOwlRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
|
||||
name = a.select("label").text(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(li.select("small:last-of-type").text()),
|
||||
uploadDate = dateFormat.tryParse(li.selectFirst("small:last-of-type")?.text()),
|
||||
source = MangaSource.MANGAOWL
|
||||
)
|
||||
}
|
||||
@@ -157,9 +158,4 @@ class MangaOwlRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
|
||||
SortOrder.UPDATED -> "3"
|
||||
else -> "3"
|
||||
}
|
||||
|
||||
private fun parseChapterDate(string: String): Long {
|
||||
return SimpleDateFormat("MM/dd/yyyy", Locale.US).tryParse(string)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -97,6 +98,7 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
|
||||
val info = root.selectFirst("div.detail_info")?.selectFirst("ul")
|
||||
val chaptersList = root.selectFirst("div.chapter_content")
|
||||
?.selectFirst("ul.chapter_list")?.select("li")?.asReversed()
|
||||
val dateFormat = SimpleDateFormat("MMM dd,yyyy", Locale.US)
|
||||
return manga.copy(
|
||||
tags = manga.tags + info?.select("li")?.find { x ->
|
||||
x.selectFirst("b")?.ownText() == "Genre(s):"
|
||||
@@ -118,7 +120,10 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
|
||||
url = href,
|
||||
source = MangaSource.MANGATOWN,
|
||||
number = i + 1,
|
||||
uploadDate = parseChapterDate(li.selectFirst("span.time")?.text().orEmpty()),
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
li.selectFirst("span.time")?.text()
|
||||
),
|
||||
name = name.ifEmpty { "${manga.title} - ${i + 1}" }
|
||||
)
|
||||
}
|
||||
@@ -169,11 +174,12 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseChapterDate(date: String): Long {
|
||||
private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
|
||||
return when {
|
||||
date.isNullOrEmpty() -> 0L
|
||||
date.contains("Today") -> Calendar.getInstance().timeInMillis
|
||||
date.contains("Yesterday") -> Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -1) }.timeInMillis
|
||||
else -> SimpleDateFormat("MMM dd,yyyy", Locale.US).tryParse(date)
|
||||
else -> dateFormat.tryParse(date)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
||||
import org.koitharu.kotatsu.utils.WordSet
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -116,6 +117,7 @@ class MangareadRepository(
|
||||
"manga" to mangaId.toString()
|
||||
)
|
||||
).parseHtml()
|
||||
val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
|
||||
return manga.copy(
|
||||
tags = root.selectFirst("div.genres-content")?.select("a")
|
||||
?.mapNotNullToSet { a ->
|
||||
@@ -140,7 +142,10 @@ class MangareadRepository(
|
||||
name = a!!.ownText(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(doc2.selectFirst("span.chapter-release-date i")?.text()),
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
doc2.selectFirst("span.chapter-release-date i")?.text()
|
||||
),
|
||||
source = MangaSource.MANGAREAD
|
||||
)
|
||||
}
|
||||
@@ -165,7 +170,8 @@ class MangareadRepository(
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseChapterDate(date: String?): Long {
|
||||
private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
|
||||
|
||||
date ?: return 0
|
||||
return when {
|
||||
date.endsWith(" ago", ignoreCase = true) -> {
|
||||
@@ -240,9 +246,5 @@ class MangareadRepository(
|
||||
val pos = it.indexOf('=')
|
||||
it.substring(0, pos) to it.substring(pos + 1)
|
||||
}.toMutableMap()
|
||||
|
||||
private val dateFormat by lazy {
|
||||
SimpleDateFormat("MMMM dd, yyyy", Locale.US)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ abstract class NineMangaRepository(
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun parseChapterDateByLang(date: String): Long {
|
||||
private fun parseChapterDateByLang(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
|
||||
@@ -94,6 +94,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
val chapters = loaderContext.httpGet(
|
||||
url = "https://api.$domain/api/titles/chapters/?branch_id=$branchId"
|
||||
).parseJson().getJSONArray("content")
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US)
|
||||
return manga.copy(
|
||||
description = content.getString("description"),
|
||||
state = when (content.optJSONObject("status")?.getInt("id")) {
|
||||
@@ -110,7 +111,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
},
|
||||
chapters = chapters.mapIndexed { i, jo ->
|
||||
val id = jo.getLong("id")
|
||||
val name = jo.getString("name").capitalize(Locale.ROOT)
|
||||
val name = jo.getString("name").toTitleCase(Locale.ROOT)
|
||||
val publishers = jo.getJSONArray("publishers")
|
||||
MangaChapter(
|
||||
id = generateUid(id),
|
||||
@@ -127,7 +128,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
append(name)
|
||||
}
|
||||
},
|
||||
uploadDate = parseChapterDate(jo.getString("upload_date")),
|
||||
uploadDate = dateFormat.tryParse(jo.getString("upload_date")),
|
||||
scanlator = publishers.optJSONObject(0)?.getStringOrNull("name"),
|
||||
source = MangaSource.REMANGA
|
||||
)
|
||||
@@ -178,10 +179,6 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
source = source
|
||||
)
|
||||
|
||||
private fun parseChapterDate(string: String): Long {
|
||||
return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US).tryParse(string)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
const val PAGE_SIZE = 30
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.nodes.Node
|
||||
import org.jsoup.select.Elements
|
||||
import java.text.SimpleDateFormat
|
||||
import java.text.DateFormat
|
||||
|
||||
fun Response.parseHtml(): Document {
|
||||
try {
|
||||
@@ -100,6 +100,10 @@ fun Element.css(property: String): String? {
|
||||
return css.substringAfter(':').removeSuffix(';').trim()
|
||||
}
|
||||
|
||||
fun SimpleDateFormat.tryParse(str: String): Long = runCatching {
|
||||
parse(str)?.time ?: 0L
|
||||
}.getOrDefault(0L)
|
||||
fun DateFormat.tryParse(str: String?): Long = if (str.isNullOrEmpty()) {
|
||||
0L
|
||||
} else {
|
||||
runCatching {
|
||||
parse(str)?.time ?: 0L
|
||||
}.getOrDefault(0L)
|
||||
}
|
||||
@@ -52,6 +52,10 @@ fun String.toTitleCase(): String {
|
||||
return replaceFirstChar { x -> x.uppercase() }
|
||||
}
|
||||
|
||||
fun String.toTitleCase(locale: Locale): String {
|
||||
return replaceFirstChar { x -> x.uppercase(locale) }
|
||||
}
|
||||
|
||||
fun String.transliterate(skipMissing: Boolean): String {
|
||||
val cyr = charArrayOf(
|
||||
'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п',
|
||||
|
||||
Reference in New Issue
Block a user