diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0379aae9..702406c7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,7 +4,7 @@
package="com.lagradost.cloudstream3">
-
+
@@ -53,13 +53,19 @@
+
+
+
+
+
+
+
@@ -68,11 +74,15 @@
+
+
+
+
@@ -84,15 +94,15 @@
-
-
+
+
@@ -104,39 +114,71 @@
-
+
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt
index 6c7318e1..dc1bbba3 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt
@@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.ui.player
+import android.content.Intent
+import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
@@ -35,6 +37,34 @@ class DownloadedPlayerActivity : AppCompatActivity() {
finish()
}
+ private fun playLink(url: String) {
+ this.navigate(
+ R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
+ LinkGenerator(
+ listOf(
+ url
+ )
+ )
+ )
+ )
+ }
+
+ private fun playUri(uri: Uri) {
+ val name = UniFile.fromUri(this, uri).name
+ this.navigate(
+ R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
+ DownloadFileGenerator(
+ listOf(
+ ExtractorUri(
+ uri = uri,
+ name = name ?: getString(R.string.downloaded_file)
+ )
+ )
+ )
+ )
+ )
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
Log.i(DTAG, "onCreate")
@@ -45,69 +75,35 @@ class DownloadedPlayerActivity : AppCompatActivity() {
setContentView(R.layout.empty_layout)
val data = intent.data
- if (data == null) {
+
+ if (intent?.action == Intent.ACTION_SEND) {
+ val extraText = try { // I dont trust android
+ intent.getStringExtra(Intent.EXTRA_TEXT)
+ } catch (e: Exception) {
+ null
+ }
+ val cd = intent.clipData
+ val item = if (cd != null && cd.itemCount > 0) cd.getItemAt(0) else null
+ val url = item?.text?.toString()
+
+ // idk what I am doing, just hope any of these work
+ if (item?.uri != null)
+ playUri(item.uri)
+ else if (url != null)
+ playLink(url)
+ else if (data != null)
+ playUri(data)
+ else if (extraText != null)
+ playLink(extraText)
+ else {
+ finish()
+ return
+ }
+ } else if (data?.scheme == "content") {
+ playUri(data)
+ } else {
finish()
return
}
-
- if (data.scheme == "content") {
- val name = UniFile.fromUri(this, data).name
- this.navigate(
- R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
- DownloadFileGenerator(
- listOf(
- ExtractorUri(
- uri = data,
- name = name ?: getString(R.string.downloaded_file)
- )
- )
- )
- )
- )
- }
-
- // Legacy code, seems to work perfectly fine without it
-
-// } else {
-// val uri = getUri(intent.data)
-// if (uri == null) {
-// finish()
-// return
-// }
-// val path = uri.path
-// // Because it doesn't get the path when it's downloaded, I have no idea
-// val realPath = if (File(
-// intent.data?.path?.removePrefix("/file") ?: "NONE"
-// ).exists()
-// ) intent.data?.path?.removePrefix("/file") else path
-//
-// if (realPath == null) {
-// finish()
-// return
-// }
-//
-// val name = try {
-// File(realPath).name
-// } catch (e: Exception) {
-// "NULL"
-// }
-//
-// val tryUri = try {
-// AppUtils.getVideoContentUri(this, realPath) ?: uri
-// } catch (e: Exception) {
-// logError(e)
-// uri
-// }
-//
-// setContentView(R.layout.empty_layout)
-// Log.i(DTAG, "navigating")
-//
-// //TODO add relative path for subs
-// this.navigate(
-// R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
-// DownloadFileGenerator(listOf(ExtractorUri(uri = tryUri, name = name)))
-// )
-// )
-// }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt
index 27bf1435..d604e2f8 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt
@@ -1,10 +1,7 @@
package com.lagradost.cloudstream3.ui.player
import com.lagradost.cloudstream3.apmap
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.ExtractorUri
-import com.lagradost.cloudstream3.utils.Qualities
-import com.lagradost.cloudstream3.utils.loadExtractor
+import com.lagradost.cloudstream3.utils.*
class LinkGenerator(
private val links: List,
@@ -50,12 +47,13 @@ class LinkGenerator(
if (!extract || !loadExtractor(link, referer) {
callback(it to null)
}) {
+
// if don't extract or if no extractor found simply return the link
callback(
ExtractorLink(
"",
link,
- link,
+ unshortenLinkSafe(link), // unshorten because it might be a raw link
referer ?: "",
Qualities.Unknown.value, link.contains(".m3u") // TODO USE REAL PARSER
) to null
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt
index 110c72e3..be0ca1ad 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt
@@ -5,6 +5,7 @@ import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.*
+import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import kotlinx.coroutines.delay
import org.jsoup.Jsoup
@@ -143,6 +144,17 @@ fun getAndUnpack(string: String): String {
return JsUnpacker(packedText).unpack() ?: string
}
+suspend fun unshortenLinkSafe(url : String) : String {
+ return try {
+ if (ShortLink.isShortLink(url))
+ ShortLink.unshorten(url)
+ else url
+ } catch (e: Exception) {
+ logError(e)
+ url
+ }
+}
+
/**
* Tries to load the appropriate extractor based on link, returns true if any extractor is loaded.
* */
@@ -151,14 +163,17 @@ suspend fun loadExtractor(
referer: String? = null,
callback: (ExtractorLink) -> Unit
): Boolean {
+ val currentUrl = unshortenLinkSafe(url)
+
for (extractor in extractorApis) {
- if (url.replace(schemaStripRegex, "")
+ if (currentUrl.replace(schemaStripRegex, "")
.startsWith(extractor.mainUrl.replace(schemaStripRegex, ""))
) {
- extractor.getSafeUrl(url, referer)?.forEach(callback)
+ extractor.getSafeUrl(currentUrl, referer)?.forEach(callback)
return true
}
}
+
return false
}
@@ -166,9 +181,11 @@ suspend fun loadExtractor(
url: String,
referer: String? = null,
): List {
+ val currentUrl = unshortenLinkSafe(url)
+
for (extractor in extractorApis) {
- if (url.startsWith(extractor.mainUrl)) {
- return extractor.getSafeUrl(url, referer) ?: emptyList()
+ if (currentUrl.startsWith(extractor.mainUrl)) {
+ return extractor.getSafeUrl(currentUrl, referer) ?: emptyList()
}
}
return emptyList()
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/UnshortenUrl.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/UnshortenUrl.kt
index 119e4a00..d0d3298d 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/UnshortenUrl.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/UnshortenUrl.kt
@@ -1,4 +1,5 @@
package com.lagradost.cloudstream3.utils
+
import android.util.Base64
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.base64Decode
@@ -8,163 +9,182 @@ import java.net.URLDecoder
//Code heavily based on unshortenit.py form kodiondemand /addon
-private data class ShortUrl(
- val regex: Regex,
- val type: String,
- val function: suspend (String) -> String,
-) {
- constructor(regex: String, type: String, function: suspend (String) -> String) : this(
- Regex(regex),
- type,
- function
- )
- companion object {
- val adflyRegex = """adf\.ly|j\.gs|q\.gs|u\.bb|ay\.gy|atominik\.com|tinyium\.com|microify\.com|threadsphere\.bid|clearload\.bid|activetect\.net|swiftviz\.net|briskgram\.net|activetect\.net|stoodsef\.com|baymaleti\.net|thouth\.net|uclaut\.net|gloyah\.net|larati\.net|scuseami\.net"""
- val linkupRegex = """linkup\.pro|buckler.link"""
- val linksafeRegex = """linksafe\.cc"""
- val nuovoIndirizzoRegex = """mixdrop\.nuovoindirizzo\.com"""
- val nuovoLinkRegex = """nuovolink\.com"""
- val uprotRegex = """uprot\.net"""
- val davisonbarkerRegex = """davisonbarker\.pro|lowrihouston\.pro"""
-
- val shortList = listOf(
- ShortUrl(adflyRegex,"adfly",::unshortenAdfly),
- ShortUrl(linkupRegex,"linkup",::unshortenLinkup),
- ShortUrl(linksafeRegex,"linksafe",::unshortenLinksafe),
- ShortUrl(nuovoIndirizzoRegex,"nuovoindirizzo",::unshortenNuovoIndirizzo),
- ShortUrl(nuovoLinkRegex,"nuovolink",::unshortenNuovoLink),
- ShortUrl(uprotRegex,"uprot",::unshortenUprot),
- ShortUrl(davisonbarkerRegex,"uprot",::unshortenDavisonbarker),
+object ShortLink {
+ data class ShortUrl(
+ val regex: Regex,
+ val type: String,
+ val function: suspend (String) -> String,
+ ) {
+ constructor(regex: String, type: String, function: suspend (String) -> String) : this(
+ Regex(regex),
+ type,
+ function
)
}
-}
-class ShortLink{
- fun isShortLink(url : String) : Boolean{
- return ShortUrl.shortList.firstOrNull {
- it.regex.find(url) != null}!=null
+ private val adflyRegex =
+ """adf\.ly|j\.gs|q\.gs|u\.bb|ay\.gy|atominik\.com|tinyium\.com|microify\.com|threadsphere\.bid|clearload\.bid|activetect\.net|swiftviz\.net|briskgram\.net|activetect\.net|stoodsef\.com|baymaleti\.net|thouth\.net|uclaut\.net|gloyah\.net|larati\.net|scuseami\.net"""
+ private val linkupRegex = """linkup\.pro|buckler.link"""
+ private val linksafeRegex = """linksafe\.cc"""
+ private val nuovoIndirizzoRegex = """mixdrop\.nuovoindirizzo\.com"""
+ private val nuovoLinkRegex = """nuovolink\.com"""
+ private val uprotRegex = """uprot\.net"""
+ private val davisonbarkerRegex = """davisonbarker\.pro|lowrihouston\.pro"""
+
+ private val shortList = listOf(
+ ShortUrl(adflyRegex, "adfly", ::unshortenAdfly),
+ ShortUrl(linkupRegex, "linkup", ::unshortenLinkup),
+ ShortUrl(linksafeRegex, "linksafe", ::unshortenLinksafe),
+ ShortUrl(nuovoIndirizzoRegex, "nuovoindirizzo", ::unshortenNuovoIndirizzo),
+ ShortUrl(nuovoLinkRegex, "nuovolink", ::unshortenNuovoLink),
+ ShortUrl(uprotRegex, "uprot", ::unshortenUprot),
+ ShortUrl(davisonbarkerRegex, "uprot", ::unshortenDavisonbarker),
+ )
+
+ fun isShortLink(url: String): Boolean {
+ return shortList.any {
+ it.regex.find(url) != null
+ }
}
+
suspend fun unshorten(uri: String, type: String? = null): String {
var currentUrl = uri
while (true) {
val oldurl = currentUrl
- val domain = URI(currentUrl).host ?: throw IllegalArgumentException("No domain found in URI!")
- currentUrl = ShortUrl.shortList.firstOrNull {
+ val domain =
+ URI(currentUrl).host ?: throw IllegalArgumentException("No domain found in URI!")
+ currentUrl = shortList.firstOrNull {
it.regex.find(domain) != null || type == it.type
}?.function?.let { it(currentUrl) } ?: break
- if (oldurl == currentUrl){
+ if (oldurl == currentUrl) {
break
}
}
return currentUrl
}
-}
-suspend fun unshortenAdfly(uri: String): String{
- val html = app.get(uri).text
- val ysmm = Regex("""var ysmm =.*\;?""").find(html)!!.value
- if (ysmm.isNotEmpty()){
- var left = ""
- var right = ""
+ suspend fun unshortenAdfly(uri: String): String {
+ val html = app.get(uri).text
+ val ysmm = Regex("""var ysmm =.*;?""").find(html)!!.value
+
+ if (ysmm.isNotEmpty()) {
+ var left = ""
+ var right = ""
- for (c in ysmm.replace(Regex("""var ysmm \= \'|\'\;"""),"").chunked(2).dropLastWhile {it.length==1}) {
- left += c[0]
- right = c[1] + right
+ for (c in ysmm.replace(Regex("""var ysmm = '|';"""), "").chunked(2)
+ .dropLastWhile { it.length == 1 }) {
+ left += c[0]
+ right = c[1] + right
+ }
+ val encodedUri = (left + right).toMutableList()
+ val numbers =
+ encodedUri.mapIndexed { i, n -> Pair(i, n) }.filter { it.second.isDigit() }
+ for (el in numbers.chunked(2).dropLastWhile { it.size == 1 }) {
+ val xor = (el[0].second).code.xor(el[1].second.code)
+ if (xor < 10) {
+ encodedUri[el[0].first] = xor.digitToChar()
+ }
+ }
+ val encodedbytearray = encodedUri.map { it.code.toByte() }.toByteArray()
+ var decodedUri =
+ Base64.decode(encodedbytearray, Base64.DEFAULT).decodeToString().dropLast(16)
+ .drop(16)
+
+ if (Regex("""go\.php\?u=""").find(decodedUri) != null) {
+ decodedUri =
+ Base64.decode(decodedUri.replace(Regex("""(.*?)u="""), ""), Base64.DEFAULT)
+ .decodeToString()
+ }
+
+ return decodedUri
+ } else {
+ return uri
}
- val encodedUri = (left + right).toMutableList()
- val numbers = encodedUri.mapIndexed{ i, n-> Pair(i,n)}.filter{it.second.isDigit()}
- for (el in numbers.chunked(2).dropLastWhile {it.size==1}){
- val xor = (el[0].second).code.xor(el[1].second.code)
- if (xor < 10){
- encodedUri[el[0].first] = xor.digitToChar()
+ }
+
+ suspend fun unshortenLinkup(uri: String): String {
+ var r: NiceResponse? = null
+ var uri = uri
+ when {
+ uri.contains("/tv/") -> uri = uri.replace("/tv/", "/tva/")
+ uri.contains("delta") -> uri = uri.replace("/delta/", "/adelta/")
+ (uri.contains("/ga/") || uri.contains("/ga2/")) -> uri =
+ base64Decode(uri.split('/').last()).trim()
+ uri.contains("/speedx/") -> uri =
+ uri.replace("http://linkup.pro/speedx", "http://speedvideo.net")
+ else -> {
+ r = app.get(uri, allowRedirects = true)
+ uri = r.url
+ val link =
+ Regex("