Add search query filtering for Honkaiimpact extension (#8781)

* Add search query filtering for Honkaiimpact extension

* removed interceptors, added searchMangaParse

* Use fetchSearchManga for search query filtering to avoid race conditions

* Update src/en/honkaiimpact/src/eu/kanade/tachiyomi/extension/en/honkaiimpact/Honkaiimpact.kt

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>

* Update src/en/honkaiimpact/src/eu/kanade/tachiyomi/extension/en/honkaiimpact/Honkaiimpact.kt

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>

* Update src/en/honkaiimpact/src/eu/kanade/tachiyomi/extension/en/honkaiimpact/Honkaiimpact.kt

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>

* Update src/en/honkaiimpact/src/eu/kanade/tachiyomi/extension/en/honkaiimpact/Honkaiimpact.kt

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>

* Update src/en/honkaiimpact/src/eu/kanade/tachiyomi/extension/en/honkaiimpact/Honkaiimpact.kt

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>

---------

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>
This commit is contained in:
Atasshe 2025-06-01 23:10:14 -03:00 committed by Draff
parent 9b9440e3e9
commit 86727e4cde
Signed by: Draff
GPG Key ID: E8A89F3211677653
2 changed files with 37 additions and 31 deletions

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'HonkaiImpact3' extName = 'HonkaiImpact3'
extClass = '.Honkaiimpact' extClass = '.Honkaiimpact'
extVersionCode = 2 extVersionCode = 3
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -1,11 +1,14 @@
package eu.kanade.tachiyomi.extension.en.honkaiimpact package eu.kanade.tachiyomi.extension.en.honkaiimpact
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList 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.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.float import kotlinx.serialization.json.float
@ -14,71 +17,80 @@ import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
// Info - Based of BH3
// This is the english version of the site
class Honkaiimpact : ParsedHttpSource() { class Honkaiimpact : ParsedHttpSource() {
override val name = "Honkai Impact 3rd" override val name = "Honkai Impact 3rd"
override val baseUrl = "https://manga.honkaiimpact3.com" override val baseUrl = "https://manga.honkaiimpact3.com"
override val lang = "en" override val lang = "en"
override val supportsLatest = false override val supportsLatest = false
private var searchQuery = ""
private val json: Json by injectLazy()
override val client: OkHttpClient = network.cloudflareClient.newBuilder() override val client: OkHttpClient = network.cloudflareClient.newBuilder()
// .addInterceptor(filteringInterceptor)
.connectTimeout(1, TimeUnit.MINUTES) .connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES) .readTimeout(1, TimeUnit.MINUTES)
.retryOnConnectionFailure(true) .retryOnConnectionFailure(true)
.followRedirects(true) .followRedirects(true)
.build() .build()
private val json: Json by injectLazy()
// Popular // Popular
override fun popularMangaSelector() = "a[href*=book]" override fun popularMangaSelector() = "a[href*=book]"
override fun popularMangaNextPageSelector(): String? = null override fun popularMangaNextPageSelector(): String? = null
override fun popularMangaRequest(page: Int) =
override fun popularMangaRequest(page: Int) = GET("$baseUrl/book", headers) GET("$baseUrl/book", headers) // .newBuilder().tag(String::class.java, searchQuery).build()
override fun popularMangaFromElement(element: Element) = mangaFromElement(element) override fun popularMangaFromElement(element: Element) = mangaFromElement(element)
// Latest // Latest
override fun latestUpdatesSelector() = throw UnsupportedOperationException() override fun latestUpdatesSelector() = throw UnsupportedOperationException()
override fun latestUpdatesNextPageSelector(): String? = null override fun latestUpdatesNextPageSelector(): String? = null
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element) = mangaFromElement(element)
// Search // Search
override fun searchMangaSelector() = throw UnsupportedOperationException() override fun searchMangaSelector() = "a[href*=book]"
override fun searchMangaNextPageSelector(): String? = null override fun searchMangaNextPageSelector(): String? = null
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw Exception("No search") return GET("$baseUrl/book", headers)
}
override fun searchMangaFromElement(element: Element) = mangaFromElement(element) override fun searchMangaFromElement(element: Element) = mangaFromElement(element)
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return client.newCall(searchMangaRequest(page, query, filters))
.asObservableSuccess()
.map { response ->
val document = response.asJsoup()
val mangas = document.select(searchMangaSelector()).map { element ->
searchMangaFromElement(element)
}.filter { manga ->
query.isEmpty() || manga.title.contains(query.trim(), ignoreCase = true)
}
val hasNextPage = searchMangaNextPageSelector()?.let { selector ->
document.selectFirst(selector)
} != null
MangasPage(mangas, hasNextPage)
}
}
private fun mangaFromElement(element: Element): SManga { private fun mangaFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.setUrlWithoutDomain(element.select("a").attr("abs:href")) manga.setUrlWithoutDomain(element.attr("abs:href"))
manga.title = element.select("div.container-title").text().trim() manga.title = element.select(".container-title").text()
manga.thumbnail_url = element.select("img").attr("abs:src") manga.thumbnail_url = element.select(".container-cover img").attr("abs:src")
return manga return manga
} }
// Manga Details
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.thumbnail_url = document.select("img.cover").attr("abs:src") manga.thumbnail_url = document.select("img.cover").attr("abs:src")
@ -87,13 +99,9 @@ class Honkaiimpact : ParsedHttpSource() {
return manga return manga
} }
// Chapters
override fun chapterListSelector() = throw UnsupportedOperationException() override fun chapterListSelector() = throw UnsupportedOperationException()
override fun chapterFromElement(element: Element) = throw UnsupportedOperationException() override fun chapterFromElement(element: Element) = throw UnsupportedOperationException()
override fun chapterListRequest(manga: SManga) = GET(baseUrl + manga.url + "/get_chapter", headers) override fun chapterListRequest(manga: SManga) = GET(baseUrl + manga.url + "/get_chapter", headers)
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val jsonResult = json.parseToJsonElement(response.body.string()).jsonArray val jsonResult = json.parseToJsonElement(response.body.string()).jsonArray
@ -111,8 +119,6 @@ class Honkaiimpact : ParsedHttpSource() {
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).parse(date)?.time ?: 0 return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).parse(date)?.time ?: 0
} }
// Manga Pages
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
return document.select("img.lazy.comic_img").mapIndexed { i, el -> return document.select("img.lazy.comic_img").mapIndexed { i, el ->
Page(i, "", el.attr("data-original")) Page(i, "", el.attr("data-original"))