* fix(delegate): migrate NH to the v2 api * bump versionId * remove versionId requirement * gemini review suggestions * remove dead code * remove unused imports * linging * unneeded comment * fix(delegate): migrate NH to the v2 api (jobobby04/TachiyomiSY#1581) * fix(delegate): migrate NH to the v2 api * remove extra comment * remove redundant data * linting * Code cleanup --------- Co-authored-by: Jobobby04 <jobobby04@users.noreply.github.com> (cherry picked from commit eec1236b8b5904b46d79bb716e29f073c6fe9b34) * close `response` * Avoid empty server list --------- Co-authored-by: Jobobby04 <jobobby04@users.noreply.github.com> Co-authored-by: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>
131 lines
4.6 KiB
Kotlin
131 lines
4.6 KiB
Kotlin
package exh.metadata.metadata
|
|
|
|
import android.content.Context
|
|
import eu.kanade.tachiyomi.source.model.SManga
|
|
import eu.kanade.tachiyomi.source.model.copy
|
|
import exh.metadata.MetadataUtil
|
|
import kotlinx.serialization.Serializable
|
|
import tachiyomi.core.common.i18n.stringResource
|
|
import tachiyomi.i18n.MR
|
|
import tachiyomi.i18n.sy.SYMR
|
|
import java.time.Instant
|
|
import java.time.ZoneId
|
|
import java.time.ZonedDateTime
|
|
|
|
@Serializable
|
|
class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
|
var url get() = nhId?.let { BASE_URL + nhIdToPath(it) }
|
|
set(a) {
|
|
a?.let {
|
|
nhId = nhUrlToId(a)
|
|
}
|
|
}
|
|
|
|
var nhId: Long? = null
|
|
|
|
var uploadDate: Long? = null
|
|
|
|
var favoritesCount: Long? = null
|
|
|
|
var mediaId: String? = null
|
|
|
|
var japaneseTitle by titleDelegate(TITLE_TYPE_JAPANESE)
|
|
var englishTitle by titleDelegate(TITLE_TYPE_ENGLISH)
|
|
var shortTitle by titleDelegate(TITLE_TYPE_SHORT)
|
|
|
|
var coverImageUrl: String? = null
|
|
var pageImagePreviewUrls: List<String> = emptyList()
|
|
|
|
var scanlator: String? = null
|
|
|
|
var preferredTitle: Int? = null
|
|
|
|
override fun createMangaInfo(manga: SManga): SManga {
|
|
val key = nhId?.let { nhIdToPath(it) }
|
|
|
|
val title = when (preferredTitle) {
|
|
TITLE_TYPE_SHORT -> shortTitle ?: englishTitle ?: japaneseTitle ?: manga.title
|
|
0, TITLE_TYPE_ENGLISH -> englishTitle ?: japaneseTitle ?: shortTitle ?: manga.title
|
|
else -> englishTitle ?: japaneseTitle ?: shortTitle ?: manga.title
|
|
}
|
|
|
|
// Set artist (if we can find one)
|
|
val artist = tags.ofNamespace(NHENTAI_ARTIST_NAMESPACE).let { tags ->
|
|
if (tags.isNotEmpty()) tags.joinToString(transform = { it.name }) else null
|
|
}
|
|
|
|
// Set group (if we can find one)
|
|
val group = tags.ofNamespace(NHENTAI_GROUP_NAMESPACE).let { tags ->
|
|
if (tags.isNotEmpty()) tags.joinToString(transform = { it.name }) else null
|
|
}
|
|
|
|
// Copy tags -> genres
|
|
val genres = tagsToGenreString()
|
|
|
|
// Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes
|
|
// We default to completed
|
|
var status = SManga.COMPLETED
|
|
englishTitle?.let { t ->
|
|
MetadataUtil.ONGOING_SUFFIX.find {
|
|
t.endsWith(it, ignoreCase = true)
|
|
}?.let {
|
|
status = SManga.ONGOING
|
|
}
|
|
}
|
|
|
|
return manga.copy(
|
|
url = key ?: manga.url,
|
|
thumbnail_url = coverImageUrl ?: manga.thumbnail_url,
|
|
title = title,
|
|
artist = group ?: manga.artist,
|
|
author = artist ?: manga.artist,
|
|
genre = genres,
|
|
status = status,
|
|
description = null,
|
|
)
|
|
}
|
|
|
|
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
|
return with(context) {
|
|
listOfNotNull(
|
|
getItem(nhId) { stringResource(SYMR.strings.id) },
|
|
getItem(
|
|
uploadDate,
|
|
{
|
|
MetadataUtil.EX_DATE_FORMAT
|
|
.format(ZonedDateTime.ofInstant(Instant.ofEpochSecond(it), ZoneId.systemDefault()))
|
|
},
|
|
) {
|
|
stringResource(SYMR.strings.date_posted)
|
|
},
|
|
getItem(favoritesCount) { stringResource(SYMR.strings.total_favorites) },
|
|
getItem(mediaId) { stringResource(SYMR.strings.media_id) },
|
|
getItem(japaneseTitle) { stringResource(SYMR.strings.japanese_title) },
|
|
getItem(englishTitle) { stringResource(SYMR.strings.english_title) },
|
|
getItem(shortTitle) { stringResource(SYMR.strings.short_title) },
|
|
getItem(coverImageUrl) { stringResource(SYMR.strings.thumbnail_url) },
|
|
getItem(pageImagePreviewUrls.size) { stringResource(SYMR.strings.page_count) },
|
|
getItem(scanlator) { stringResource(MR.strings.scanlator) },
|
|
)
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
private const val TITLE_TYPE_JAPANESE = 0
|
|
const val TITLE_TYPE_ENGLISH = 1
|
|
const val TITLE_TYPE_SHORT = 2
|
|
|
|
const val TAG_TYPE_DEFAULT = 0
|
|
|
|
const val BASE_URL = "https://nhentai.net"
|
|
|
|
private const val NHENTAI_ARTIST_NAMESPACE = "artist"
|
|
private const val NHENTAI_GROUP_NAMESPACE = "group"
|
|
const val NHENTAI_CATEGORIES_NAMESPACE = "category"
|
|
|
|
fun nhUrlToId(url: String) =
|
|
url.split("/").last { it.isNotBlank() }.toLong()
|
|
|
|
fun nhIdToPath(id: Long) = "/g/$id/"
|
|
}
|
|
}
|