copy paste extractors from shiro

This commit is contained in:
LagradOst 2021-05-19 20:44:02 +02:00
parent d0fbf5a782
commit 68605fb563
11 changed files with 641 additions and 5 deletions

124
.idea/uiDesigner.xml Normal file
View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

View file

@ -73,11 +73,6 @@ data class Link(
val referer: String?,
)
interface LinkExtractor {
val linkStart: String // THIS IS USED TO AUTO-EXTRACT LINKS FROM URL
fun extract(link: String, referer: String): ArrayList<Link>
}
enum class ShowStatus {
Completed,
Ongoing,

View file

@ -0,0 +1,58 @@
package com.lagradost.cloudstream3.utils
import com.lagradost.cloudstream3.utils.extractors.MixDrop
import com.lagradost.cloudstream3.utils.extractors.Mp4Upload
import com.lagradost.cloudstream3.utils.extractors.Shiro
import com.lagradost.cloudstream3.cloudstream3.extractors.StreamTape
import com.lagradost.cloudstream3.utils.extractors.XStreamCdn
data class ExtractorLink(
val name: String,
val url: String,
val referer: String,
val quality: Int,
val isM3u8: Boolean = false,
)
enum class Qualities(var value: Int) {
Unknown(0),
SD(-1), // 360p - 480p
HD(1), // 720p
FullHd(2), // 1080p
UHD(3) // 4k
}
private val packedRegex = Regex("""eval\(function\(p,a,c,k,e,.*\)\)""")
fun getPacked(string: String): String? {
return packedRegex.find(string)?.value
}
fun getAndUnpack(string: String): String? {
val packedText = getPacked(string)
return JsUnpacker(packedText).unpack()
}
val APIS: Array<ExtractorApi> = arrayOf(
//AllProvider(),
Shiro(),
Mp4Upload(),
StreamTape(),
MixDrop(),
XStreamCdn()
)
fun httpsify(url: String): String {
return if (url.startsWith("//")) "https:$url" else url
}
abstract class ExtractorApi {
abstract val name: String
abstract val mainUrl: String
abstract val requiresReferer: Boolean
abstract fun getUrl(url: String, referer: String? = null): List<ExtractorLink>?
open fun getExtractorUrl(id: String): String{
return id
}
}

View file

@ -0,0 +1,125 @@
package com.lagradost.cloudstream3.utils
import java.lang.Exception
import java.lang.StringBuilder
import java.util.HashMap
import java.util.regex.Pattern
import kotlin.math.pow
// https://github.com/cylonu87/JsUnpacker
class JsUnpacker(packedJS: String?) {
private var packedJS: String? = null
/**
* Detects whether the javascript is P.A.C.K.E.R. coded.
*
* @return true if it's P.A.C.K.E.R. coded.
*/
fun detect(): Boolean {
val js = packedJS!!.replace(" ", "")
val p = Pattern.compile("eval\\(function\\(p,a,c,k,e,[rd]")
val m = p.matcher(js)
return m.find()
}
/**
* Unpack the javascript
*
* @return the javascript unpacked or null.
*/
fun unpack(): String? {
val js = packedJS
try {
var p =
Pattern.compile("""\}\s*\('(.*)',\s*(.*?),\s*(\d+),\s*'(.*?)'\.split\('\|'\)""", Pattern.DOTALL)
var m = p.matcher(js)
if (m.find() && m.groupCount() == 4) {
val payload = m.group(1).replace("\\'", "'")
val radixStr = m.group(2)
val countStr = m.group(3)
val symtab = m.group(4).split("\\|".toRegex()).toTypedArray()
var radix = 36
var count = 0
try {
radix = radixStr.toInt()
} catch (e: Exception) {
}
try {
count = countStr.toInt()
} catch (e: Exception) {
}
if (symtab.size != count) {
throw Exception("Unknown p.a.c.k.e.r. encoding")
}
val unbase = Unbase(radix)
p = Pattern.compile("\\b\\w+\\b")
m = p.matcher(payload)
val decoded = StringBuilder(payload)
var replaceOffset = 0
while (m.find()) {
val word = m.group(0)
val x = unbase.unbase(word)
var value: String? = null
if (x < symtab.size) {
value = symtab[x]
}
if (value != null && value.isNotEmpty()) {
decoded.replace(m.start() + replaceOffset, m.end() + replaceOffset, value)
replaceOffset += value.length - word.length
}
}
return decoded.toString()
}
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
private inner class Unbase(private val radix: Int) {
private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
private val ALPHABET_95 =
" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
private var alphabet: String? = null
private var dictionary: HashMap<String, Int>? = null
fun unbase(str: String): Int {
var ret = 0
if (alphabet == null) {
ret = str.toInt(radix)
} else {
val tmp = StringBuilder(str).reverse().toString()
for (i in tmp.indices) {
ret += (radix.toDouble().pow(i.toDouble()) * dictionary!![tmp.substring(i, i + 1)]!!).toInt()
}
}
return ret
}
init {
if (radix > 36) {
when {
radix < 62 -> {
alphabet = ALPHABET_62.substring(0, radix)
}
radix in 63..94 -> {
alphabet = ALPHABET_95.substring(0, radix)
}
radix == 62 -> {
alphabet = ALPHABET_62
}
radix == 95 -> {
alphabet = ALPHABET_95
}
}
dictionary = HashMap(95)
for (i in 0 until alphabet!!.length) {
dictionary!![alphabet!!.substring(i, i + 1)] = i
}
}
}
}
/**
* @param packedJS javascript P.A.C.K.E.R. coded.
*/
init {
this.packedJS = packedJS
}
}

View file

@ -0,0 +1,36 @@
package com.lagradost.cloudstream3.utils.extractors
import com.lagradost.cloudstream3.utils.*
class MixDrop : ExtractorApi() {
override val name: String = "MixDrop"
override val mainUrl: String = "https://mixdrop.co"
private val srcRegex = Regex("""wurl.*?=.*?"(.*?)";""")
override val requiresReferer = true
override fun getExtractorUrl(id: String): String {
return "$mainUrl/e/$id"
}
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
try {
with(khttp.get(url)) {
getAndUnpack(this.text)?.let { unpackedText ->
srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link ->
return listOf(
ExtractorLink(
name,
httpsify(link),
url,
Qualities.Unknown.value,
)
)
}
}
}
return null
} catch (e: Exception) {
return null
}
}
}

View file

@ -0,0 +1,32 @@
package com.lagradost.cloudstream3.utils.extractors
import com.lagradost.cloudstream3.utils.*
class Mp4Upload : ExtractorApi() {
override val name: String = "Mp4Upload"
override val mainUrl: String = "https://www.mp4upload.com"
private val srcRegex = Regex("""player\.src\("(.*?)"""")
override val requiresReferer = true
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
try {
with(khttp.get(url)) {
getAndUnpack(this.text)?.let { unpackedText ->
srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link ->
return listOf(
ExtractorLink(
name,
link,
url,
Qualities.Unknown.value,
)
)
}
}
}
return null
} catch (e: Exception) {
return null
}
}
}

View file

@ -0,0 +1,69 @@
package com.lagradost.cloudstream3.utils.extractors
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
class MultiQuality : ExtractorApi() {
override val name: String = "MultiQuality"
override val mainUrl: String = "https://gogo-play.net"
private val sourceRegex = Regex("""file:\s*'(.*?)',label:\s*'(.*?)'""")
private val m3u8Regex = Regex(""".*?(\d*).m3u8""")
private val urlRegex = Regex("""(.*?)([^/]+$)""")
override val requiresReferer = false
override fun getExtractorUrl(id: String): String {
return "$mainUrl/loadserver.php?id=$id"
}
private fun getQuality(string: String): Int {
return when (string) {
"360" -> Qualities.SD.value
"480" -> Qualities.SD.value
"720" -> Qualities.HD.value
"1080" -> Qualities.FullHd.value
else -> Qualities.Unknown.value
}
}
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
try {
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
with(khttp.get(url)) {
sourceRegex.findAll(this.text).forEach { sourceMatch ->
val extractedUrl = sourceMatch.groupValues[1]
// Trusting this isn't mp4, may fuck up stuff
if (extractedUrl.endsWith(".m3u8")) {
with(khttp.get(extractedUrl)) {
m3u8Regex.findAll(this.text).forEach { match ->
extractedLinksList.add(
ExtractorLink(
"$name ${match.groupValues[1]}p",
urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[0],
url,
getQuality(match.groupValues[1]),
isM3u8 = true
)
)
}
}
} else if (extractedUrl.endsWith(".mp4")) {
extractedLinksList.add(
ExtractorLink(
"$name ${sourceMatch.groupValues[2]}",
extractedUrl,
url.replace(" ", "%20"),
Qualities.Unknown.value,
)
)
}
}
return extractedLinksList
}
} catch (e: Exception) {
}
return null
}
}

View file

@ -0,0 +1,33 @@
package com.lagradost.cloudstream3.utils.extractors
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import org.jsoup.Jsoup
class Shiro : ExtractorApi() {
override val name: String = "Shiro"
override val mainUrl: String = "https://cherry.subsplea.se"
override val requiresReferer = false
override fun getExtractorUrl(id: String): String {
return "$mainUrl/$id"
}
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
val headers = mapOf("Referer" to "https://shiro.is/")
val res = khttp.get(url, headers = headers).text
Jsoup.parse(res).select("source").firstOrNull()?.attr("src")?.replace("&amp;", "?")?.let {
return listOf(
ExtractorLink(
name,
it.replace(" ", "%20"),
"https://cherry.subsplea.se/",
// UHD to give top priority
Qualities.UHD.value
)
)
}
return null
}
}

View file

@ -0,0 +1,35 @@
package com.lagradost.cloudstream3.cloudstream3.extractors
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
class StreamTape : ExtractorApi() {
override val name: String = "StreamTape"
override val mainUrl: String = "https://streamtape.com"
override val requiresReferer = true
// Because they add concatenation to fuck up scrapers
private val linkRegex =
Regex("""(i(|" \+ ')d(|" \+ ')=.*?&(|" \+ ')e(|" \+ ')x(|" \+ ')p(|" \+ ')i(|" \+ ')r(|" \+ ')e(|" \+ ')s(|" \+ ')=.*?&(|" \+ ')i(|" \+ ')p(|" \+ ')=.*?&(|" \+ ')t(|" \+ ')o(|" \+ ')k(|" \+ ')e(|" \+ ')n(|" \+ ')=.*)'""")
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
try {
with(khttp.get(url)) {
linkRegex.find(this.text)?.let {
val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "")
return listOf(
ExtractorLink(
name,
extractedUrl,
url,
Qualities.Unknown.value,
)
)
}
}
} catch (e: Exception) {
}
return null
}
}

View file

@ -0,0 +1,59 @@
package com.lagradost.cloudstream3.utils.extractors
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.APIS
import com.lagradost.cloudstream3.utils.extractors.MultiQuality
import com.lagradost.cloudstream3.utils.extractors.Shiro
import org.jsoup.Jsoup
class Vidstream {
val name: String = "Vidstream"
private val mainUrl: String = "https://gogo-stream.com"
private fun getExtractorUrl(id: String): String {
return "$mainUrl/streaming.php?id=$id"
}
// https://gogo-stream.com/streaming.php?id=MTE3NDg5
fun getUrl(id: String, isCasting: Boolean = false): List<ExtractorLink> {
try {
val url = getExtractorUrl(id)
with(khttp.get(url)) {
val document = Jsoup.parse(this.text)
val primaryLinks = document.select("ul.list-server-items > li.linkserver")
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
// --- Shiro ---
val shiroUrl = Shiro().getExtractorUrl(id)
val shiroSource = Shiro().getUrl(shiroUrl)
shiroSource?.forEach { extractedLinksList.add(it) }
// --- MultiQuality ---
val multiQualityUrl = MultiQuality().getExtractorUrl(id)
val multiQualitySource = MultiQuality().getUrl(multiQualityUrl)
multiQualitySource?.forEach { extractedLinksList.add(it) }
// --------------------
// All vidstream links passed to extractors
primaryLinks.forEach { element ->
val link = element.attr("data-video")
//val name = element.text()
// Matches vidstream links with extractors
APIS.filter { !it.requiresReferer || !isCasting}.forEach { api ->
if (link.startsWith(api.mainUrl)) {
val extractedLinks = api.getUrl(link, url)
if (extractedLinks?.isNotEmpty() == true) {
extractedLinks.forEach {
extractedLinksList.add(it)
}
}
}
}
}
return extractedLinksList
}
} catch (e: Exception) {
return listOf()
}
}
}

View file

@ -0,0 +1,70 @@
package com.lagradost.cloudstream3.utils.extractors
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.mapper
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
class XStreamCdn : ExtractorApi() {
override val name: String = "XStreamCdn"
override val mainUrl: String = "https://fcdn.stream"
override val requiresReferer = true
private data class ResponseData(
@JsonProperty("file") val file: String,
@JsonProperty("label") val label: String,
//val type: String // Mp4
)
private data class ResponseJson(
@JsonProperty("success") val success: Boolean,
@JsonProperty("data") val data: List<ResponseData>?
)
override fun getExtractorUrl(id: String): String {
return "$mainUrl/api/source/$id"
}
private fun getQuality(string: String): Int {
return when (string) {
"360p" -> Qualities.SD.value
"480p" -> Qualities.SD.value
"720p" -> Qualities.HD.value
"1080p" -> Qualities.FullHd.value
else -> Qualities.Unknown.value
}
}
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
try {
val headers = mapOf(
"Referer" to url,
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0",
)
val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/")
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
with(khttp.post(newUrl, headers = headers)) {
mapper.readValue<ResponseJson?>(this.text)?.let {
if (it.success && it.data != null) {
it.data.forEach { data ->
extractedLinksList.add(
ExtractorLink(
"$name ${data.label}",
data.file,
url,
getQuality(data.label),
)
)
}
}
}
}
return extractedLinksList
} catch (e: Exception) {
}
return null
}
}