Nekopost extension: Search fix (HTTP error 520) (#18931)

* format the code and change the throw exception

* fix nekopost search

* switch to HttpSource
use request/parse instead of fetch

* Remove commented code.
This commit is contained in:
Taihenc 2023-11-15 23:27:39 +07:00 committed by GitHub
parent d044170507
commit 11a8fc6e5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 160 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'Nekopost'
pkgNameSuffix = 'th.nekopost'
extClass = '.Nekopost'
extVersionCode = 9
extVersionCode = 10
isNsfw = true
}

View File

@ -2,38 +2,35 @@ package eu.kanade.tachiyomi.extension.th.nekopost
import eu.kanade.tachiyomi.extension.th.nekopost.model.RawChapterInfo
import eu.kanade.tachiyomi.extension.th.nekopost.model.RawProjectInfo
import eu.kanade.tachiyomi.extension.th.nekopost.model.RawProjectNameListItem
import eu.kanade.tachiyomi.extension.th.nekopost.model.RawProjectSearchSummary
import eu.kanade.tachiyomi.extension.th.nekopost.model.RawProjectSummaryList
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.Locale
class Nekopost : ParsedHttpSource() {
class Nekopost : HttpSource() {
private val json: Json by injectLazy()
override val baseUrl: String = "https://www.nekopost.net/manga/"
private val latestMangaEndpoint: String =
"https://api.osemocphoto.com/frontAPI/getLatestChapter/m"
private val projectDataEndpoint: String =
"https://api.osemocphoto.com/frontAPI/getProjectInfo"
private val latestMangaEndpoint: String = "https://api.osemocphoto.com/frontAPI/getLatestChapter/m"
private val projectDataEndpoint: String = "https://api.osemocphoto.com/frontAPI/getProjectInfo"
private val fileHost: String = "https://www.osemocphoto.com"
private val nekopostUrl = "https://www.nekopost.net"
override val client: OkHttpClient = network.cloudflareClient
@ -57,35 +54,22 @@ class Nekopost : ParsedHttpSource() {
else -> SManga.UNKNOWN
}
override fun latestUpdatesRequest(page: Int): Request = throw NotImplementedError("Unused")
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException("Not used.")
override fun latestUpdatesParse(response: Response): MangasPage =
throw NotImplementedError("Unused")
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used.")
override fun chapterListSelector(): String = throw NotImplementedError("Unused")
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used.")
override fun chapterFromElement(element: Element): SChapter =
throw NotImplementedError("Unused")
override fun imageUrlRequest(page: Page): Request = throw UnsupportedOperationException("Not used.")
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl)
override fun mangaDetailsRequest(manga: SManga): Request {
return GET("$projectDataEndpoint/${manga.url}", headers)
}
override fun imageUrlParse(document: Document): String = throw NotImplementedError("Unused")
override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("Unused")
override fun latestUpdatesNextPageSelector(): String = throw Exception("Unused")
override fun latestUpdatesSelector(): String = throw Exception("Unused")
override fun mangaDetailsParse(document: Document): SManga = throw NotImplementedError("Unused")
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return client.newCall(GET("$projectDataEndpoint/${manga.url}", headers))
.asObservableSuccess()
.map { response ->
override fun mangaDetailsParse(response: Response): SManga {
val responseBody = response.body
val projectInfo: RawProjectInfo = json.decodeFromString(responseBody.string())
val manga = SManga.create()
manga.apply {
projectInfo.projectInfo.let {
url = it.projectId
@ -94,8 +78,7 @@ class Nekopost : ParsedHttpSource() {
author = it.authorName
description = it.info
status = getStatus(it.status)
thumbnail_url =
"$fileHost/collectManga/${it.projectId}/${it.projectId}_cover.jpg"
thumbnail_url = "$fileHost/collectManga/${it.projectId}/${it.projectId}_cover.jpg"
initialized = true
}
@ -105,51 +88,47 @@ class Nekopost : ParsedHttpSource() {
""
}
}
}
return manga
}
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
return if (manga.status != SManga.LICENSED) {
client.newCall(GET("$projectDataEndpoint/${manga.url}", headers))
.asObservableSuccess()
.map { response ->
val responseBody = response.body
val projectInfo: RawProjectInfo = json.decodeFromString(responseBody.string())
override fun chapterListRequest(manga: SManga): Request {
val headers = Headers.headersOf("accept", "*/*", "content-type", "text/plain;charset=UTF-8", "origin", nekopostUrl)
return GET("$projectDataEndpoint/${manga.url}", headers)
}
override fun chapterListParse(response: Response): List<SChapter> {
val responseBody = response.body.string()
val projectInfo: RawProjectInfo = json.decodeFromString(responseBody)
val manga = SManga.create()
manga.status = getStatus(projectInfo.projectInfo.status)
if (manga.status == SManga.LICENSED) {
throw Exception("Licensed - No chapter to show")
}
projectInfo.projectChapterList!!.map { chapter ->
return projectInfo.projectChapterList!!.map { chapter ->
SChapter.create().apply {
url =
"${manga.url}/${chapter.chapterId}/${manga.url}_${chapter.chapterId}.json"
url = "${projectInfo.projectInfo.projectId.toInt()}/${chapter.chapterId}/${projectInfo.projectInfo.projectId.toInt()}_${chapter.chapterId}.json"
name = chapter.chapterName
date_upload = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss",
Locale("th"),
).parse(chapter.createDate)?.time
?: 0L
).parse(chapter.createDate)?.time ?: 0L
chapter_number = chapter.chapterNo.toFloat()
scanlator = chapter.providerName
}
}
}
} else {
Observable.error(Exception("Licensed - No chapter to show"))
}
override fun pageListRequest(chapter: SChapter): Request {
return GET("$fileHost/collectManga/${chapter.url}", headers)
}
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
return client.newCall(GET("$fileHost/collectManga/${chapter.url}", headers))
.asObservableSuccess()
.map { response ->
override fun pageListParse(response: Response): List<Page> {
val responseBody = response.body
val chapterInfo: RawChapterInfo = json.decodeFromString(responseBody.string())
chapterInfo.pageItem.map { page ->
return chapterInfo.pageItem.map { page ->
val imgUrl: String = if (page.pageName != null) {
"$fileHost/collectManga/${chapterInfo.projectId}/${chapterInfo.chapterId}/${page.pageName}"
} else {
@ -161,14 +140,10 @@ class Nekopost : ParsedHttpSource() {
)
}
}
}
override fun pageListParse(document: Document): List<Page> = throw NotImplementedError("Unused")
override fun popularMangaRequest(page: Int): Request {
if (page <= 1) existingProject.clear()
// API has a bug that sometime it returns null on first page
return GET("$latestMangaEndpoint/${if (firstPageNulled) page else page - 1 }", headers)
return GET("$latestMangaEndpoint/${if (firstPageNulled) page else page - 1}", headers)
}
override fun popularMangaParse(response: Response): MangasPage {
@ -176,14 +151,11 @@ class Nekopost : ParsedHttpSource() {
val projectList: RawProjectSummaryList = json.decodeFromString(responseBody.string())
val mangaList: List<SManga> = if (projectList.listChapter != null) {
projectList.listChapter
.filter { !existingProject.contains(it.projectId) }
.map {
projectList.listChapter.filter { !existingProject.contains(it.projectId) }.map {
SManga.create().apply {
url = it.projectId
title = it.projectName
thumbnail_url =
"$fileHost/collectManga/${it.projectId}/${it.projectId}_cover.jpg"
thumbnail_url = "$fileHost/collectManga/${it.projectId}/${it.projectId}_cover.jpg"
initialized = false
status = 0
}
@ -198,51 +170,27 @@ class Nekopost : ParsedHttpSource() {
return MangasPage(mangaList, hasNextPage = true)
}
override fun popularMangaFromElement(element: Element): SManga =
throw NotImplementedError("Unused")
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val headers = Headers.headersOf("accept", "*/*", "content-type", "text/plain;charset=UTF-8", "origin", nekopostUrl)
val requestBody = "{\"keyword\":\"$query\"}".toRequestBody()
return POST("$nekopostUrl/api/explore/search", headers, requestBody)
}
override fun popularMangaNextPageSelector(): String = throw Exception("Unused")
override fun popularMangaSelector(): String = throw Exception("Unused")
override fun searchMangaFromElement(element: Element): SManga = throw Exception("Unused")
override fun searchMangaNextPageSelector(): String = throw Exception("Unused")
override fun fetchSearchManga(
page: Int,
query: String,
filters: FilterList,
): Observable<MangasPage> {
return client.newCall(GET("$fileHost/dataJson/dataProjectName.json"))
.asObservableSuccess()
.map { response ->
val responseBody = response.body
val projectList: List<RawProjectNameListItem> =
json.decodeFromString(responseBody.string())
override fun searchMangaParse(response: Response): MangasPage {
val responseBody = response.body.string()
val projectList: List<RawProjectSearchSummary> = json.decodeFromString(responseBody)
val mangaList: List<SManga> = projectList.filter { project ->
Regex(
query,
setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE),
).find(project.npName) != null
project.projectType == "m"
}.map { project ->
SManga.create().apply {
url = project.npProjectId
title = project.npName
status = getStatus(project.npStatus)
url = project.projectId.toString()
title = project.projectName
status = project.status
initialized = false
}
}
MangasPage(mangaList, false)
return MangasPage(mangaList, false)
}
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request =
throw Exception("Unused")
override fun searchMangaParse(response: Response): MangasPage = throw Exception("Unused")
override fun searchMangaSelector(): String = throw Exception("Unused")
}

View File

@ -0,0 +1,19 @@
package eu.kanade.tachiyomi.extension.th.nekopost.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class RawProjectSearchSummary(
val projectId: Int,
val projectName: String,
val projectType: String,
@SerialName("STATUS")
val status: Int,
val noChapter: Int,
val coverVersion: Int,
val info: String,
val views: Int,
@SerialName("lastUpdate")
val lastUpdateDate: String,
)