all/SimplyHentai: Fix http 404 (#1008)

* fix: Fix popular manga page

* fix: Fix latest manga page

* fix: Fix search manga page

* chore: Minor changes to prevent future issues

* refactor: Minor refactoration

* chore: Bump version

* chore: Follow suggestion - re-add cloudflareClient

* refactor: Commit suggestion - remove unnecessary chapter_number

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
This commit is contained in:
Claudemirovsky 2024-02-05 04:34:40 -03:00 committed by Draff
parent ac1575dd81
commit 00e4bed8ab
4 changed files with 48 additions and 74 deletions

View File

@ -1,7 +1,7 @@
ext {
extName = 'Simply Hentai'
extClass = '.SimplyHentaiFactory'
extVersionCode = 6
extVersionCode = 7
isNsfw = true
}

View File

@ -5,7 +5,6 @@ import android.net.Uri
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
@ -13,15 +12,20 @@ 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.HttpSource
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import okhttp3.Response
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.Locale
open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSource() {
open class SimplyHentai(
override val lang: String,
private val langName: String,
) : ConfigurableSource, HttpSource() {
override val name = "Simply Hentai"
override val baseUrl = "https://www.simply-hentai.com"
@ -34,47 +38,32 @@ open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSou
private val apiUrl = "https://api.simply-hentai.com/v3"
private val langName by lazy {
Locale.forLanguageTag(lang).displayName
}
private val json by lazy { Injekt.get<Json>() }
private val json: Json by injectLazy()
private val preferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)!!
}
override fun popularMangaRequest(page: Int) =
Uri.parse("$apiUrl/albums").buildUpon().run {
appendQueryParameter("si", "0")
appendQueryParameter("locale", lang)
appendQueryParameter("language", langName)
appendQueryParameter("sort", "spotlight")
Uri.parse("$apiUrl/tag/$langName").buildUpon().run {
appendQueryParameter("type", "language")
appendQueryParameter("page", page.toString())
GET(build().toString(), headers)
}
override fun popularMangaParse(response: Response) =
response.decode<SHList<SHObject>>().run {
response.decode<SHList<SHDataAlbum>>().run {
MangasPage(
data.map {
SManga.create().apply {
url = it.path
title = it.title
thumbnail_url = it.preview.sizes.thumb
}
},
data.albums.map(SHObject::toSManga),
pagination.next != null,
)
}
override fun latestUpdatesRequest(page: Int) =
Uri.parse("$apiUrl/albums").buildUpon().run {
appendQueryParameter("si", "0")
appendQueryParameter("locale", lang)
appendQueryParameter("language", langName)
appendQueryParameter("sort", "newest")
Uri.parse("$apiUrl/tag/$langName").buildUpon().run {
appendQueryParameter("type", "language")
appendQueryParameter("page", page.toString())
appendQueryParameter("sort", "newest")
GET(build().toString(), headers)
}
@ -83,18 +72,16 @@ open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSou
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
Uri.parse("$apiUrl/search/complex").buildUpon().run {
appendQueryParameter("si", "0")
appendQueryParameter("locale", lang)
appendQueryParameter("query", query)
appendQueryParameter("page", page.toString())
appendQueryParameter("blacklist", blacklist)
appendQueryParameter("filter[languages][0]", langName)
appendQueryParameter("filter[language][0]", langName.replaceFirstChar(Char::uppercase))
filters.forEach { filter ->
when (filter) {
is SortFilter -> {
appendQueryParameter("sort", filter.orders[filter.state])
}
is SeriesFilter -> filter.value?.let {
is SeriesFilter -> filter.value?.also {
appendQueryParameter("filter[series_title][0]", it)
}
is TagsFilter -> filter.value?.forEachIndexed { idx, tag ->
@ -116,25 +103,14 @@ open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSou
}
override fun searchMangaParse(response: Response) =
response.decode<SHList<SHWrapper>>().run {
response.decode<SHList<List<SHWrapper>>>().run {
MangasPage(
data.map {
SManga.create().apply {
url = it.`object`.path
title = it.`object`.title
thumbnail_url = it.`object`.preview.sizes.thumb
}
},
data.map { it.`object`.toSManga() },
pagination.next != null,
)
}
override fun mangaDetailsRequest(manga: SManga) =
GET(baseUrl + manga.url, headers)
override fun fetchMangaDetails(manga: SManga) =
client.newCall(chapterListRequest(manga))
.asObservableSuccess().map(::mangaDetailsParse)!!
override fun mangaDetailsRequest(manga: SManga) = chapterListRequest(manga)
override fun mangaDetailsParse(response: Response) =
SManga.create().apply {
@ -143,9 +119,9 @@ open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSou
title = album.title
description = buildString {
if (!album.description.isNullOrEmpty()) {
append("${album.description}\n\n")
append(album.description, "\n\n")
}
append("Series: ${album.series.title}\n")
append("Series: ", album.series.title, "\n")
album.characters.joinTo(this, prefix = "Characters: ") { it.title }
}
thumbnail_url = album.preview.sizes.thumb
@ -156,10 +132,8 @@ open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSou
}
override fun chapterListRequest(manga: SManga) =
Uri.parse("$apiUrl/album").buildUpon().run {
Uri.parse("$apiUrl/manga").buildUpon().run {
appendEncodedPath(manga.url.split('/')[2])
appendQueryParameter("si", "0")
appendQueryParameter("locale", lang)
GET(build().toString(), headers)
}
@ -167,18 +141,15 @@ open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSou
SChapter.create().apply {
val album = response.decode<SHAlbum>().data
name = "Chapter"
chapter_number = -1f
url = "${album.path}/all-pages"
scanlator = album.translators.joinToString { it.title }
date_upload = dateFormat.parse(album.created_at)?.time ?: 0L
}.let(::listOf)
override fun pageListRequest(chapter: SChapter) =
Uri.parse("$apiUrl/album").buildUpon().run {
Uri.parse("$apiUrl/manga").buildUpon().run {
appendEncodedPath(chapter.url.split('/')[2])
appendEncodedPath("/pages")
appendQueryParameter("si", "0")
appendQueryParameter("locale", lang)
appendEncodedPath("pages")
GET(build().toString(), headers)
}
@ -215,8 +186,8 @@ open class SimplyHentai(override val lang: String) : ConfigurableSource, HttpSou
private inline val blacklist: String
get() = preferences.getString("blacklist", "")!!
private inline fun <reified T> Response.decode() =
json.decodeFromString<T>(body.string())
private inline fun <reified T> Response.decode(): T =
json.decodeFromStream(body.byteStream())
override fun imageUrlParse(response: Response) =
throw UnsupportedOperationException()

View File

@ -1,9 +1,10 @@
package eu.kanade.tachiyomi.extension.all.simplyhentai
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.serialization.Serializable
@Serializable
data class SHList<T>(val pagination: SHPagination, val data: List<T>)
data class SHList<T>(val pagination: SHPagination, val data: T)
@Serializable
data class SHPagination(val next: Int?)
@ -11,6 +12,9 @@ data class SHPagination(val next: Int?)
@Serializable
data class SHWrapper(val `object`: SHObject)
@Serializable
data class SHDataAlbum(val albums: List<SHObject>)
@Serializable
data class SHObject(
val preview: SHImage,
@ -18,7 +22,11 @@ data class SHObject(
val slug: String,
val title: String,
) {
val path by lazy { "/${series.slug}/$slug" }
fun toSManga() = SManga.create().apply {
url = "/${series.slug}/$slug"
title = this@SHObject.title
thumbnail_url = preview.sizes.thumb
}
}
@Serializable

View File

@ -4,20 +4,15 @@ import eu.kanade.tachiyomi.source.SourceFactory
class SimplyHentaiFactory : SourceFactory {
override fun createSources() = listOf(
SimplyHentai("en"),
SimplyHentai("ja"),
SimplyHentai("zh"),
SimplyHentai("ko"),
SimplyHentai("es"),
SimplyHentai("ru"),
SimplyHentai("fr"),
SimplyHentai("de"),
object : SimplyHentai("pt-BR") {
// The site uses a Portugal flag for the language,
// but the contents are in Brazilian Portuguese.
override val id = 23032005200449651
},
SimplyHentai("it"),
SimplyHentai("pl"),
SimplyHentai("en", "english"),
SimplyHentai("ja", "japanese"),
SimplyHentai("zh", "chinese"),
SimplyHentai("ko", "korean"),
SimplyHentai("es", "spanish"),
SimplyHentai("ru", "russian"),
SimplyHentai("fr", "french"),
SimplyHentai("de", "german"),
SimplyHentai("it", "italian"),
SimplyHentai("pl", "polish"),
)
}