From 69078ac42e0c3d19e4a43854ae4154b7c64135a6 Mon Sep 17 00:00:00 2001 From: tom5079 <7948651+tom5079@users.noreply.github.com> Date: Sat, 2 Mar 2024 17:51:18 -0800 Subject: [PATCH] Suggestion --- .../pupil/networking/HitomiHttpClient.kt | 135 ++++++++++++------ 1 file changed, 92 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt b/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt index 965cd8fc..bc3ad347 100644 --- a/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt +++ b/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt @@ -13,7 +13,9 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.withContext import xyz.quaver.pupil.hitomi.max_node_size import java.nio.ByteBuffer +import java.nio.ByteOrder import java.nio.IntBuffer +import java.nio.charset.Charset const val domain = "ltn.hitomi.la" const val galleryBlockExtension = ".html" @@ -28,6 +30,11 @@ const val galleriesIndexDir = "galleriesindex" const val languagesIndexDir = "languagesindex" const val nozomiURLIndexDir = "nozomiurlindex" +data class Suggestion( + val tag: SearchQuery.Tag, + val count: Int +) + fun IntBuffer.toSet(): Set { val result = mutableSetOf() @@ -78,7 +85,7 @@ class HitomiHttpClient { } return Node.decodeNode( - getURLAtRange(url, address until (address+max_node_size)) + getURLAtRange(url, address ..< address+max_node_size) ) } @@ -112,7 +119,38 @@ class HitomiHttpClient { return getURLAtRange(url, offset until (offset+length)).asIntBuffer() } - suspend fun getGalleryIDsFromNozomi( + private suspend fun getSuggestionsFromData(field: String, data: Node.Data): List { + val url = "https://$domain/$indexDir/$field.${getTagIndexVersion()}.data" + val (offset, length) = data + + check(data.length in 1..10000) { "Invalid length ${data.length}" } + + val buffer = getURLAtRange(url, offset.. getGalleryIDsFromNozomi("tag", query.toString(), language) "language" -> getGalleryIDsFromNozomi(null, "index", query.tag) null -> { @@ -146,62 +184,73 @@ class HitomiHttpClient { else -> getGalleryIDsFromNozomi(query.namespace, query.tag, language) } - suspend fun search(query: SearchQuery?): Set = when (query) { - is SearchQuery.Tag -> getGalleryIDsForQuery(query).toSet() - is SearchQuery.Not -> coroutineScope { - val allGalleries = async { - getGalleryIDsFromNozomi(null, "index", "all") - } + suspend fun getSuggestionsForQuery(query: SearchQuery.Tag): Result> = runCatching { + val field = query.namespace ?: "global" + val key = Node.Key(field) + val node = getNodeAtAddress(field, 0) + val data = bSearch(field, key, node) - val queriedGalleries = search(query.query) + data?.let { getSuggestionsFromData(field, data) } ?: emptyList() + } - val result = mutableSetOf() + suspend fun search(query: SearchQuery?): Result> = runCatching { + when (query) { + is SearchQuery.Tag -> getGalleryIDsForQuery(query).toSet() + is SearchQuery.Not -> coroutineScope { + val allGalleries = async { + getGalleryIDsFromNozomi(null, "index", "all") + } - with (allGalleries.await()) { - while (this.hasRemaining()) { - val gallery = this.get() + val queriedGalleries = search(query.query).getOrThrow() - if (gallery in queriedGalleries) { - result.add(gallery) + val result = mutableSetOf() + + with (allGalleries.await()) { + while (this.hasRemaining()) { + val gallery = this.get() + + if (gallery in queriedGalleries) { + result.add(gallery) + } } } - } - result - } - is SearchQuery.And -> coroutineScope { - val queries = query.queries.map { query -> - async { - search(query) + result + } + is SearchQuery.And -> coroutineScope { + val queries = query.queries.map { query -> + async { + search(query).getOrThrow() + } } - } - val result = queries.first().await().toMutableSet() + val result = queries.first().await().toMutableSet() - queries.drop(1).forEach { - val queryResult = it.await() + queries.drop(1).forEach { + val queryResult = it.await() - result.retainAll(queryResult) - } - - result - } - is SearchQuery.Or -> coroutineScope { - val queries = query.queries.map { query -> - async { - search(query) + result.retainAll(queryResult) } + + result } + is SearchQuery.Or -> coroutineScope { + val queries = query.queries.map { query -> + async { + search(query).getOrThrow() + } + } - val result = mutableSetOf() + val result = mutableSetOf() - queries.forEach { - val queryResult = it.await() - result.addAll(queryResult) + queries.forEach { + val queryResult = it.await() + result.addAll(queryResult) + } + + result } - - result + null -> getGalleryIDsFromNozomi(null, "index", "all").toSet() } - null -> getGalleryIDsFromNozomi(null, "index", "all").toSet() } } \ No newline at end of file