Add login support (#1340)

This commit is contained in:
Secozzi 2023-02-28 09:30:53 +01:00 committed by GitHub
parent 611c48d96f
commit f4e38d617a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 3 deletions

View File

@ -1,11 +1,12 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlinx-serialization'
ext { ext {
extName = 'hanime.tv' extName = 'hanime.tv'
pkgNameSuffix = 'en.hanime' pkgNameSuffix = 'en.hanime'
extClass = '.Hanime' extClass = '.Hanime'
extVersionCode = 15 extVersionCode = 16
libVersion = '13' libVersion = '13'
containsNsfw = true containsNsfw = true
} }

View File

@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
@ -25,11 +26,13 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long import kotlinx.serialization.json.long
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -45,6 +48,8 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
override val supportsLatest = true override val supportsLatest = true
private var authCookie: String? = null
private val json: Json by injectLazy() private val json: Json by injectLazy()
private val preferences: SharedPreferences by lazy { private val preferences: SharedPreferences by lazy {
@ -69,8 +74,9 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
private val popularRequestHeaders = private val popularRequestHeaders =
Headers.headersOf("authority", "search.htv-services.com", "accept", "application/json, text/plain, */*", "content-type", "application/json;charset=UTF-8") Headers.headersOf("authority", "search.htv-services.com", "accept", "application/json, text/plain, */*", "content-type", "application/json;charset=UTF-8")
override fun popularAnimeRequest(page: Int): Request = override fun popularAnimeRequest(page: Int): Request {
POST("https://search.htv-services.com/", popularRequestHeaders, searchRequestBody("", page, AnimeFilterList())) return POST("https://search.htv-services.com/", popularRequestHeaders, searchRequestBody("", page, AnimeFilterList()))
}
override fun popularAnimeParse(response: Response): AnimesPage { override fun popularAnimeParse(response: Response): AnimesPage {
val responseString = response.body!!.string() val responseString = response.body!!.string()
@ -127,6 +133,41 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
return GET(episode.url) return GET(episode.url)
} }
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
setAuthCookie()
if (authCookie != null) {
return fetchVideoListPremium(episode)
}
return super.fetchVideoList(episode)
}
private fun fetchVideoListPremium(episode: SEpisode): Observable<List<Video>> {
val videoList = mutableListOf<Video>()
val id = episode.url.substringAfter("?id=")
val headers = headers.newBuilder()
.add("cookie", authCookie!!)
val document = client.newCall(
GET("$baseUrl/videos/hentai/$id", headers = headers.build())
).execute().asJsoup()
val data = document.selectFirst("script:containsData(__NUXT__)").data()
.substringAfter("__NUXT__=").substringBeforeLast(";")
val parsed = json.decodeFromString<WindowNuxt>(data)
parsed.state.data.video.videos_manifest.servers.forEach { server ->
server.streams.forEach { stream ->
videoList.add(
Video(
stream.url,
stream.height + "p",
stream.url
)
)
}
}
return Observable.just(videoList)
}
override fun videoListParse(response: Response): List<Video> { override fun videoListParse(response: Response): List<Video> {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jObject = json.decodeFromString<JsonObject>(responseString) val jObject = json.decodeFromString<JsonObject>(responseString)
@ -182,6 +223,15 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
return listOf(episode) return listOf(episode)
} }
private fun setAuthCookie() {
if (authCookie == null) {
val cookieList = client.cookieJar.loadForRequest(baseUrl.toHttpUrl())
if (cookieList.isNotEmpty()) {
cookieList.firstOrNull { it.name == "htv3session" }?.let { authCookie = "${it.name}=${it.value}" }
}
}
}
private fun latestSearchRequestBody(page: Int): RequestBody { private fun latestSearchRequestBody(page: Int): RequestBody {
return """ return """
{"search_text": "", {"search_text": "",
@ -535,4 +585,40 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
} }
screen.addPreference(videoQualityPref) screen.addPreference(videoQualityPref)
} }
@Serializable
data class WindowNuxt(
val state: State
) {
@Serializable
data class State(
val data: Data
) {
@Serializable
data class Data(
val video: DataVideo
) {
@Serializable
data class DataVideo(
val videos_manifest: VideosManifest
) {
@Serializable
data class VideosManifest(
val servers: List<Server>
) {
@Serializable
data class Server(
val streams: List<Stream>
) {
@Serializable
data class Stream(
val height: String,
val url: String
)
}
}
}
}
}
}
} }