Update manga parsers

pull/83/head v2.1.1
Koitharu 4 years ago
parent 677f71dd84
commit e56c61d834
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -13,8 +13,8 @@ android {
applicationId 'org.koitharu.kotatsu' applicationId 'org.koitharu.kotatsu'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 31 targetSdkVersion 31
versionCode 376 versionCode 377
versionName '2.1' versionName '2.1.1'
generatedDensities = [] generatedDensities = []
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

@ -93,14 +93,14 @@ class DesuMeRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepositor
description = json.getString("description"), description = json.getString("description"),
chapters = chaptersList.mapIndexed { i, it -> chapters = chaptersList.mapIndexed { i, it ->
val chid = it.getLong("id") val chid = it.getLong("id")
val volChap = "Том " + it.getString("vol") + ". " + "Глава " + it.getString("ch") val volChap = "Том " + it.optString("vol", "0") + ". " + "Глава " + it.optString("ch", "0")
val title = if (it.getString("title") == "null") "" else it.getString("title") val title = it.optString("title", "null").takeUnless { it == "null" }
MangaChapter( MangaChapter(
id = generateUid(chid), id = generateUid(chid),
source = manga.source, source = manga.source,
url = "$baseChapterUrl$chid", url = "$baseChapterUrl$chid",
uploadDate = it.getLong("date") * 1000, uploadDate = it.getLong("date") * 1000,
name = if (title.isEmpty()) volChap else "$volChap: $title", name = if (title.isNullOrEmpty()) volChap else "$volChap: $title",
number = totalChapters - i, number = totalChapters - i,
scanlator = null, scanlator = null,
branch = null, branch = null,

@ -148,7 +148,7 @@ class MangaDexRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
chapters = feed.mapNotNull { jo -> chapters = feed.mapNotNull { jo ->
val id = jo.getString("id") val id = jo.getString("id")
val attrs = jo.getJSONObject("attributes") val attrs = jo.getJSONObject("attributes")
if (attrs.optJSONArray("data").isNullOrEmpty()) { if (!attrs.isNull("externalUrl")) {
return@mapNotNull null return@mapNotNull null
} }
val locale = Locale.forLanguageTag(attrs.getString("translatedLanguage")) val locale = Locale.forLanguageTag(attrs.getString("translatedLanguage"))
@ -175,11 +175,11 @@ class MangaDexRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
.parseJson() .parseJson()
.getJSONObject("data") .getJSONObject("data")
.getJSONObject("attributes") .getJSONObject("attributes")
val data = attrs.getJSONArray("data") val pages = attrs.getJSONArray("pages")
val prefix = "https://uploads.$domain/data/${attrs.getString("hash")}/" val prefix = "https://uploads.$domain/data/${attrs.getString("hash")}/"
val referer = "https://$domain/" val referer = "https://$domain/"
return List(data.length()) { i -> return List(pages.length()) { i ->
val url = prefix + data.getString(i) val url = prefix + pages.getString(i)
MangaPage( MangaPage(
id = generateUid(url), id = generateUid(url),
url = url, url = url,

@ -55,7 +55,7 @@ class MangareadRepository(
id = generateUid(href), id = generateUid(href),
url = href, url = href,
publicUrl = href.inContextOf(div), publicUrl = href.inContextOf(div),
coverUrl = div.selectFirst("img")?.absUrl("src").orEmpty(), coverUrl = div.selectFirst("img")?.absUrl("data-src").orEmpty(),
title = summary?.selectFirst("h3")?.text().orEmpty(), title = summary?.selectFirst("h3")?.text().orEmpty(),
rating = div.selectFirst("span.total_votes")?.ownText() rating = div.selectFirst("span.total_votes")?.ownText()
?.toFloatOrNull()?.div(5f) ?: -1f, ?.toFloatOrNull()?.div(5f) ?: -1f,
@ -107,16 +107,6 @@ class MangareadRepository(
val root2 = doc.body().selectFirst("div.content-area") val root2 = doc.body().selectFirst("div.content-area")
?.selectFirst("div.c-page") ?.selectFirst("div.c-page")
?: throw ParseException("Root2 not found") ?: throw ParseException("Root2 not found")
val mangaId = doc.getElementsByAttribute("data-post").firstOrNull()
?.attr("data-post")?.toLongOrNull()
?: throw ParseException("Cannot obtain manga id")
val doc2 = loaderContext.httpPost(
"https://${getDomain()}/wp-admin/admin-ajax.php",
mapOf(
"action" to "manga_get_chapters",
"manga" to mangaId.toString()
)
).parseHtml()
val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US) val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
return manga.copy( return manga.copy(
tags = root.selectFirst("div.genres-content")?.select("a") tags = root.selectFirst("div.genres-content")?.select("a")
@ -132,7 +122,7 @@ class MangareadRepository(
?.select("p") ?.select("p")
?.filterNot { it.ownText().startsWith("A brief description") } ?.filterNot { it.ownText().startsWith("A brief description") }
?.joinToString { it.html() }, ?.joinToString { it.html() },
chapters = doc2.select("li").asReversed().mapIndexed { i, li -> chapters = root2.select("li").asReversed().mapIndexed { i, li ->
val a = li.selectFirst("a") val a = li.selectFirst("a")
val href = a?.relUrl("href").orEmpty().ifEmpty { val href = a?.relUrl("href").orEmpty().ifEmpty {
parseFailed("Link is missing") parseFailed("Link is missing")
@ -144,7 +134,7 @@ class MangareadRepository(
url = href, url = href,
uploadDate = parseChapterDate( uploadDate = parseChapterDate(
dateFormat, dateFormat,
doc2.selectFirst("span.chapter-release-date i")?.text() li.selectFirst("span.chapter-release-date i")?.text()
), ),
source = MangaSource.MANGAREAD, source = MangaSource.MANGAREAD,
scanlator = null, scanlator = null,

@ -125,10 +125,10 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
number = chapters.length() - i, number = chapters.length() - i,
name = buildString { name = buildString {
append("Том ") append("Том ")
append(jo.getString("tome")) append(jo.optString("tome", "0"))
append(". ") append(". ")
append("Глава ") append("Глава ")
append(jo.getString("chapter")) append(jo.optString("chapter", "0"))
if (name.isNotEmpty()) { if (name.isNotEmpty()) {
append(" - ") append(" - ")
append(name) append(name)

@ -6,6 +6,7 @@ import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.junit.runners.Parameterized import org.junit.runners.Parameterized
import org.koin.core.component.inject import org.koin.core.component.inject
import org.koin.core.logger.Level
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
import org.koin.test.KoinTest import org.koin.test.KoinTest
import org.koin.test.KoinTestRule import org.koin.test.KoinTestRule
@ -18,7 +19,7 @@ import org.koitharu.kotatsu.utils.TestResponse
import org.koitharu.kotatsu.utils.ext.mapToSet import org.koitharu.kotatsu.utils.ext.mapToSet
import org.koitharu.kotatsu.utils.ext.medianOrNull import org.koitharu.kotatsu.utils.ext.medianOrNull
import org.koitharu.kotatsu.utils.isAbsoluteUrl import org.koitharu.kotatsu.utils.isAbsoluteUrl
import org.koitharu.kotatsu.utils.isRelativeUrl import org.koitharu.kotatsu.utils.isNotAbsoluteUrl
@RunWith(Parameterized::class) @RunWith(Parameterized::class)
class RemoteMangaRepositoryTest(private val source: MangaSource) : KoinTest { class RemoteMangaRepositoryTest(private val source: MangaSource) : KoinTest {
@ -29,7 +30,7 @@ class RemoteMangaRepositoryTest(private val source: MangaSource) : KoinTest {
@get:Rule @get:Rule
val koinTestRule = KoinTestRule.create { val koinTestRule = KoinTestRule.create {
printLogger() printLogger(Level.ERROR)
modules(repositoryTestModule) modules(repositoryTestModule)
} }
@ -112,7 +113,7 @@ class RemoteMangaRepositoryTest(private val source: MangaSource) : KoinTest {
Truth.assertThat(list.map { it.id }).containsNoDuplicates() Truth.assertThat(list.map { it.id }).containsNoDuplicates()
for (item in list) { for (item in list) {
Truth.assertThat(item.url).isNotEmpty() Truth.assertThat(item.url).isNotEmpty()
Truth.assertThat(item.url).isRelativeUrl() Truth.assertThat(item.url).isNotAbsoluteUrl()
Truth.assertThat(item.coverUrl).isAbsoluteUrl() Truth.assertThat(item.coverUrl).isAbsoluteUrl()
Truth.assertThat(item.title).isNotEmpty() Truth.assertThat(item.title).isNotEmpty()
Truth.assertThat(item.publicUrl).isAbsoluteUrl() Truth.assertThat(item.publicUrl).isAbsoluteUrl()

@ -3,25 +3,25 @@ package org.koitharu.kotatsu.utils
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestCoroutineDispatcher import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain import kotlinx.coroutines.test.setMain
import org.junit.rules.TestWatcher import org.junit.rules.TestWatcher
import org.junit.runner.Description import org.junit.runner.Description
class CoroutineTestRule( class CoroutineTestRule(
private val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher(), private val testDispatcher: TestDispatcher = StandardTestDispatcher(),
) : TestWatcher() { ) : TestWatcher() {
override fun starting(description: Description?) { override fun starting(description: Description) {
super.starting(description) super.starting(description)
Dispatchers.setMain(testDispatcher) Dispatchers.setMain(testDispatcher)
} }
override fun finished(description: Description?) { override fun finished(description: Description) {
super.finished(description) super.finished(description)
Dispatchers.resetMain() Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
} }
fun runBlockingTest(block: suspend CoroutineScope.() -> Unit) { fun runBlockingTest(block: suspend CoroutineScope.() -> Unit) {

@ -9,3 +9,5 @@ private val PATTERN_URL_RELATIVE = Pattern.compile("^/[^\\s]+", Pattern.CASE_INS
fun StringSubject.isRelativeUrl() = matches(PATTERN_URL_RELATIVE) fun StringSubject.isRelativeUrl() = matches(PATTERN_URL_RELATIVE)
fun StringSubject.isAbsoluteUrl() = matches(PATTERN_URL_ABSOLUTE) fun StringSubject.isAbsoluteUrl() = matches(PATTERN_URL_ABSOLUTE)
fun StringSubject.isNotAbsoluteUrl() = doesNotMatch(PATTERN_URL_ABSOLUTE)
Loading…
Cancel
Save