Chapter date parse optimization

This commit is contained in:
Koitharu
2021-10-20 08:10:54 +03:00
parent 7ded7fd12a
commit 78f2a13761
11 changed files with 50 additions and 49 deletions

View File

@@ -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'

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}
}

View File

@@ -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) {

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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(
'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п',