Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Update extension [Pornhub] (#20)
Browse files Browse the repository at this point in the history
* add PH CDN extractor

* update extractor

* update code

* update gradle version

* update version

* fix preference screen

* fix version
  • Loading branch information
immortal-forest authored Aug 2, 2023
1 parent aa00bfb commit 1555f1b
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 46 deletions.
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Mon Jul 31 23:55:52 NPT 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2 changes: 1 addition & 1 deletion src/all/pornhub/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ext {
extName = 'Pornhub'
pkgNameSuffix = 'all.pornhub'
extClass = '.Pornhub'
extVersionCode = 5
extVersionCode = 6
libVersion = '13'
containsNsfw = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.text.SpannableString
import android.text.Spanned
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.all.pornhub.extractors.PhCdnExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
Expand Down Expand Up @@ -92,21 +93,7 @@ class Pornhub : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@OptIn(ExperimentalSerializationApi::class)
override fun videoListParse(response: Response): List<Video> {
val url = response.request.url.toString()
val videoList = mutableListOf<Video>()
// credits to: https://github.com/Joel2B
val document = client.newCall(GET("https://appsdev.cyou/xv-ph-rt/api/?data=$url")).execute().asJsoup().body().text()
val jsonResponse = json.decodeFromString<PornApiResponse>(document)

return listOf(
Video(jsonResponse.hls!!.all!!, "HLS: ALL", jsonResponse.hls!!.all),
Video(jsonResponse.hls!!.low!!, "HLS: LOW", jsonResponse.hls!!.low),
Video(jsonResponse.hls!!.hd!!, "HLS: HD", jsonResponse.hls!!.hd),
Video(jsonResponse.hls!!.fhd!!, "HLS: FHD", jsonResponse.hls!!.fhd),
Video(jsonResponse.mp4!!.low!!, "MP4: LOW", jsonResponse.mp4!!.low),
Video(jsonResponse.mp4!!.sd!!, "MP4: SD", jsonResponse.mp4!!.sd),
Video(jsonResponse.mp4!!.hd!!, "MP4: HD", jsonResponse.mp4!!.hd),
Video(jsonResponse.mp4!!.fhd!!, "MP4: FHD", jsonResponse.mp4!!.fhd)
).filter { it.url.isNotBlank() }
return PhCdnExtractor(client).videoFromUrl(url)
}

override fun videoListSelector() = throw Exception("not used")
Expand All @@ -116,7 +103,7 @@ class Pornhub : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")

override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "720p")
val quality = preferences.getString("preferred_quality", "480p")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
Expand Down Expand Up @@ -176,7 +163,7 @@ class Pornhub : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
title = "Preferred quality"
entries = arrayOf("1080p", "720p", "480p", "240p")
entryValues = arrayOf("1080p", "720p", "480p", "240p")
setDefaultValue("1080p")
setDefaultValue("480p")
summary = "%s"

setOnPreferenceChangeListener { _, newValue ->
Expand All @@ -189,33 +176,6 @@ class Pornhub : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
screen.addPreference(videoQualityPref)
}

@Serializable
data class PornApiResponse(
var hls: Hls? = Hls(),
var mp4: Mp4? = Mp4(),
var thumb: String? = null,
var thumbnails: String? = null

)

@Serializable
data class Hls(
var all: String? = "",
@SerialName("1080p") var fhd: String? = "",
@SerialName("720p") var hd: String? = "",
@SerialName("480p") var sd: String? = "",
@SerialName("240p") var low: String? = ""

)

@Serializable
data class Mp4(
@SerialName("1080p") var fhd: String? = "",
@SerialName("720p") var hd: String? = "",
@SerialName("480p") var sd: String? = "",
@SerialName("240p") var low: String? = ""
)

@Serializable
data class VideoDetail(
@SerialName("@context") var context: String? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package eu.kanade.tachiyomi.animeextension.all.pornhub.extractors

import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient

class PhCdnExtractor(private val client: OkHttpClient) {
fun videoFromUrl(videoUrl: String): MutableList<Video> {
val pattern = Regex("(?<=viewkey=)[^&]+")
val key = pattern.find(videoUrl)?.value
val document = client.newCall(GET("https://www.pornhub.com/embed/$key")).execute().asJsoup()
val scriptPart = document.select("body > script:nth-child(7)").html()
// contains the stream url broken into multiple random variables and comments
var vars = scriptPart.subSequence(
scriptPart.indexOf("var ra"),
scriptPart.indexOf(";flashvars.mediaDefinitions.hls") + 1
).toString().split(";").toMutableList()
vars = vars.map {
it.replace("var ", "")
}.toMutableList()

var hls = String()
var quality = String()
// create a map of variable to value
val data = mutableMapOf<String, String>()
for (v in vars) {
if (v.isEmpty()) {
continue
}
val index = v.indexOf("=")
if (v.startsWith("hls")) {
val tmp = removeComment(v)
quality = tmp.replace("hls", "").split("=")[0]
hls = tmp.subSequence(index + 1, tmp.length).toString()
} else {
val x = v.subSequence(0, index).toString()
val y = v.subSequence(index + 1, v.length).toString().replace("\"", "").replace(" + ", "")
data.put(x, y)
}
}
// replace the variables in hls from the map created above
var finalHls = String()
for (part in hls.split(" + ")) {
finalHls += data.get(part)
}
val streamFile = client.newCall(GET(finalHls)).execute().body!!.string().split("\n").filter {
it.contains("index")
}[0]
val streamUrl = finalHls.subSequence(0, finalHls.indexOf("master")).toString() + streamFile
val videoList = mutableListOf<Video>()
videoList.add(Video(streamUrl, quality + 'p', streamUrl))
return videoList
}

private fun removeComment(v: String): String {
return v.replace(Regex("""(\/\/[^\n]*|\/\*(.|[\r\n])*?\*\/)"""), "")
}
}

0 comments on commit 1555f1b

Please sign in to comment.