Small fixes
This commit is contained in:
@@ -40,7 +40,7 @@ This library provides manga sources.
|
|||||||
3. Usage in code
|
3. Usage in code
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val parser = MangaSource.MANGADEX.newParser(mangaLoaderContext)
|
val parser = mangaLoaderContext.newParserInstance(MangaSource.MANGADEX)
|
||||||
```
|
```
|
||||||
|
|
||||||
`mangaLoaderContext` is an implementation of the `MangaLoaderContext` class.
|
`mangaLoaderContext` is an implementation of the `MangaLoaderContext` class.
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ class ParserProcessor(
|
|||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
|
@Deprecated("", replaceWith = ReplaceWith("context.newParserInstance(this)"))
|
||||||
fun MangaSource.newParser(context: MangaLoaderContext): MangaParser = when (this) {
|
fun MangaSource.newParser(context: MangaLoaderContext): MangaParser = when (this) {
|
||||||
|
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
@@ -155,4 +156,4 @@ class ParserProcessor(
|
|||||||
sourcesWriter?.write("\t$deprecationString$name(\"$title\", $localeString$localeComment),\n")
|
sourcesWriter?.write("\t$deprecationString$name(\"$title\", $localeString$localeComment),\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,22 +8,24 @@ import java.util.*
|
|||||||
|
|
||||||
abstract class MangaLoaderContext {
|
abstract class MangaLoaderContext {
|
||||||
|
|
||||||
abstract val httpClient: OkHttpClient
|
abstract val httpClient: OkHttpClient
|
||||||
|
|
||||||
abstract val cookieJar: CookieJar
|
abstract val cookieJar: CookieJar
|
||||||
|
|
||||||
open fun encodeBase64(data: ByteArray): String = Base64.getEncoder().encodeToString(data)
|
fun newParserInstance(source: MangaSource): MangaParser = source.newParser(this)
|
||||||
|
|
||||||
open fun decodeBase64(data: String): ByteArray = Base64.getDecoder().decode(data)
|
open fun encodeBase64(data: ByteArray): String = Base64.getEncoder().encodeToString(data)
|
||||||
|
|
||||||
open fun getPreferredLocales(): List<Locale> = listOf(Locale.getDefault())
|
open fun decodeBase64(data: String): ByteArray = Base64.getDecoder().decode(data)
|
||||||
|
|
||||||
/**
|
open fun getPreferredLocales(): List<Locale> = listOf(Locale.getDefault())
|
||||||
* Execute JavaScript code and return result
|
|
||||||
* @param script JavaScript source code
|
|
||||||
* @return execution result as string, may be null
|
|
||||||
*/
|
|
||||||
abstract suspend fun evaluateJs(script: String): String?
|
|
||||||
|
|
||||||
abstract fun getConfig(source: MangaSource): MangaSourceConfig
|
/**
|
||||||
|
* Execute JavaScript code and return result
|
||||||
|
* @param script JavaScript source code
|
||||||
|
* @return execution result as string, may be null
|
||||||
|
*/
|
||||||
|
abstract suspend fun evaluateJs(script: String): String?
|
||||||
|
|
||||||
|
abstract fun getConfig(source: MangaSource): MangaSourceConfig
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
|
|||||||
/**
|
/**
|
||||||
* Authorization is required for access to the requested content
|
* Authorization is required for access to the requested content
|
||||||
*/
|
*/
|
||||||
class AuthRequiredException @InternalParsersApi constructor(
|
class AuthRequiredException @InternalParsersApi @JvmOverloads constructor(
|
||||||
val source: MangaSource,
|
val source: MangaSource,
|
||||||
) : RuntimeException("Authorization required")
|
cause: Throwable? = null,
|
||||||
|
) : RuntimeException("Authorization required", cause)
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ import org.koitharu.kotatsu.parsers.exception.ParseException
|
|||||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
import org.koitharu.kotatsu.parsers.util.*
|
import org.koitharu.kotatsu.parsers.util.domain
|
||||||
|
import org.koitharu.kotatsu.parsers.util.parseFailed
|
||||||
|
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||||
|
import org.koitharu.kotatsu.parsers.util.urlEncoded
|
||||||
|
|
||||||
@MangaSourceParser("ALLHENTAI", "ALlHentai", "ru")
|
@MangaSourceParser("ALLHENTAI", "ALlHentai", "ru")
|
||||||
internal class AllHentaiParser(
|
internal class AllHentaiParser(
|
||||||
@@ -24,9 +27,6 @@ internal class AllHentaiParser(
|
|||||||
return "https://qawa.org/internal/auth/login?targetUri=$targetUri&siteId=1"
|
return "https://qawa.org/internal/auth/login?targetUri=$targetUri&siteId=1"
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isAuthorized: Boolean
|
|
||||||
get() = context.cookieJar.getCookies(domain).any { it.name == "trSessionId" }
|
|
||||||
|
|
||||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||||
try {
|
try {
|
||||||
return super.getPages(chapter)
|
return super.getPages(chapter)
|
||||||
@@ -34,7 +34,7 @@ internal class AllHentaiParser(
|
|||||||
if (isAuthorized) {
|
if (isAuthorized) {
|
||||||
throw e
|
throw e
|
||||||
} else {
|
} else {
|
||||||
throw AuthRequiredException(source)
|
throw AuthRequiredException(source, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|list|{0}")
|
@ParameterizedTest(name = "{index}|list|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun list(source: MangaSource) = runTest {
|
fun list(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val list = parser.getList(0, sortOrder = SortOrder.POPULARITY, tags = null)
|
val list = parser.getList(0, sortOrder = SortOrder.POPULARITY, tags = null)
|
||||||
checkMangaList(list, "list")
|
checkMangaList(list, "list")
|
||||||
assert(list.all { it.source == source })
|
assert(list.all { it.source == source })
|
||||||
@@ -34,7 +34,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|pagination|{0}")
|
@ParameterizedTest(name = "{index}|pagination|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun pagination(source: MangaSource) = runTest {
|
fun pagination(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val page1 = parser.getList(0, sortOrder = null, tags = null)
|
val page1 = parser.getList(0, sortOrder = null, tags = null)
|
||||||
val page2 = parser.getList(page1.size, sortOrder = null, tags = null)
|
val page2 = parser.getList(page1.size, sortOrder = null, tags = null)
|
||||||
if (parser is PagedMangaParser) {
|
if (parser is PagedMangaParser) {
|
||||||
@@ -54,7 +54,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|search|{0}")
|
@ParameterizedTest(name = "{index}|search|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun search(source: MangaSource) = runTest {
|
fun search(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val subject = parser.getList(0, sortOrder = SortOrder.POPULARITY, tags = null).minByOrNull {
|
val subject = parser.getList(0, sortOrder = SortOrder.POPULARITY, tags = null).minByOrNull {
|
||||||
it.title.length
|
it.title.length
|
||||||
} ?: error("No manga found")
|
} ?: error("No manga found")
|
||||||
@@ -72,7 +72,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|tags|{0}")
|
@ParameterizedTest(name = "{index}|tags|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun tags(source: MangaSource) = runTest {
|
fun tags(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val tags = parser.getTags()
|
val tags = parser.getTags()
|
||||||
assert(tags.isNotEmpty()) { "No tags found" }
|
assert(tags.isNotEmpty()) { "No tags found" }
|
||||||
val keys = tags.map { it.key }
|
val keys = tags.map { it.key }
|
||||||
@@ -92,7 +92,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|tags_multiple|{0}")
|
@ParameterizedTest(name = "{index}|tags_multiple|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun tagsMultiple(source: MangaSource) = runTest {
|
fun tagsMultiple(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val tags = parser.getTags().shuffled().take(2).toSet()
|
val tags = parser.getTags().shuffled().take(2).toSet()
|
||||||
|
|
||||||
val list = try {
|
val list = try {
|
||||||
@@ -111,7 +111,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|details|{0}")
|
@ParameterizedTest(name = "{index}|details|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun details(source: MangaSource) = runTest {
|
fun details(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val list = parser.getList(0, sortOrder = SortOrder.POPULARITY, tags = null)
|
val list = parser.getList(0, sortOrder = SortOrder.POPULARITY, tags = null)
|
||||||
val manga = list[3]
|
val manga = list[3]
|
||||||
parser.getDetails(manga).apply {
|
parser.getDetails(manga).apply {
|
||||||
@@ -140,7 +140,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|pages|{0}")
|
@ParameterizedTest(name = "{index}|pages|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun pages(source: MangaSource) = runTest {
|
fun pages(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val list = parser.getList(0, sortOrder = SortOrder.UPDATED, tags = null)
|
val list = parser.getList(0, sortOrder = SortOrder.UPDATED, tags = null)
|
||||||
val manga = list.first()
|
val manga = list.first()
|
||||||
val chapter = parser.getDetails(manga).chapters?.firstOrNull() ?: error("Chapter is null at ${manga.publicUrl}")
|
val chapter = parser.getDetails(manga).chapters?.firstOrNull() ?: error("Chapter is null at ${manga.publicUrl}")
|
||||||
@@ -164,7 +164,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|favicon|{0}")
|
@ParameterizedTest(name = "{index}|favicon|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun favicon(source: MangaSource) = runTest {
|
fun favicon(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val favicons = parser.getFavicons()
|
val favicons = parser.getFavicons()
|
||||||
val types = setOf("png", "svg", "ico", "gif", "jpg", "jpeg")
|
val types = setOf("png", "svg", "ico", "gif", "jpg", "jpeg")
|
||||||
assert(favicons.isNotEmpty())
|
assert(favicons.isNotEmpty())
|
||||||
@@ -180,7 +180,7 @@ internal class MangaParserTest {
|
|||||||
@ParameterizedTest(name = "{index}|domain|{0}")
|
@ParameterizedTest(name = "{index}|domain|{0}")
|
||||||
@MangaSources
|
@MangaSources
|
||||||
fun domain(source: MangaSource) = runTest {
|
fun domain(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
val defaultDomain = parser.domain
|
val defaultDomain = parser.domain
|
||||||
val url = HttpUrl.Builder().host(defaultDomain).scheme("https").toString()
|
val url = HttpUrl.Builder().host(defaultDomain).scheme("https").toString()
|
||||||
val response = context.doRequest(url, source)
|
val response = context.doRequest(url, source)
|
||||||
@@ -196,7 +196,7 @@ internal class MangaParserTest {
|
|||||||
@MangaSources
|
@MangaSources
|
||||||
@Disabled
|
@Disabled
|
||||||
fun authorization(source: MangaSource) = runTest {
|
fun authorization(source: MangaSource) = runTest {
|
||||||
val parser = source.newParser(context)
|
val parser = context.newParserInstance(source)
|
||||||
if (parser is MangaParserAuthProvider) {
|
if (parser is MangaParserAuthProvider) {
|
||||||
val username = parser.getUsername()
|
val username = parser.getUsername()
|
||||||
assert(username.isNotBlank()) { "Username is blank" }
|
assert(username.isNotBlank()) { "Username is blank" }
|
||||||
|
|||||||
Reference in New Issue
Block a user