Play with CloudStream, fixed #1335

This commit is contained in:
LagradOst 2022-07-26 04:31:58 +02:00
parent 738d56916f
commit bec9a87eed
6 changed files with 284 additions and 210 deletions

View File

@ -4,7 +4,7 @@
package="com.lagradost.cloudstream3"> package="com.lagradost.cloudstream3">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- I dont remember, probs has to do with downloads --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- I dont remember, probs has to do with downloads -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- unless you only use cs3 as a player for downloaded stuff, you need this -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Downloads --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Downloads -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Downloads on low api devices--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Downloads on low api devices-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- some dependency needs this --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- some dependency needs this -->
@ -53,13 +53,19 @@
<data android:scheme="content" /> <data android:scheme="content" />
<data android:mimeType="video/*" /> <data android:mimeType="video/*" />
</intent-filter> </intent-filter>
<!-- I dont think this label can be translated, but idk -->
<intent-filter android:label="@string/play_with_app_name">
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="*/*"/>
</intent-filter>
</activity> </activity>
<activity <activity
android:exported="true" android:exported="true"
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation"
android:label="@string/app_name"
android:resizeableActivity="true" android:resizeableActivity="true"
android:supportsPictureInPicture="true"> android:supportsPictureInPicture="true">
<intent-filter android:exported="true"> <intent-filter android:exported="true">
@ -68,11 +74,15 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" /> <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter android:exported="true"> <intent-filter android:exported="true">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https" android:host="elifilms.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www23.estrenosdoramas.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="pelisplus.icu" android:pathPrefix="/"/> <data android:scheme="https" android:host="pelisplus.icu" android:pathPrefix="/"/>
<data android:scheme="https" android:host="pelisplushd.net" android:pathPrefix="/"/> <data android:scheme="https" android:host="pelisplushd.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="pelismart.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="pelismart.com" android:pathPrefix="/"/>
@ -84,15 +94,15 @@
<data android:scheme="https" android:host="pelisflix.li" android:pathPrefix="/"/> <data android:scheme="https" android:host="pelisflix.li" android:pathPrefix="/"/>
<data android:scheme="https" android:host="seriesflix.video" android:pathPrefix="/"/> <data android:scheme="https" android:host="seriesflix.video" android:pathPrefix="/"/>
<data android:scheme="https" android:host="ihavenotv.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="ihavenotv.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="lookmovie.io" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www.vmovee.watch" android:pathPrefix="/"/> <data android:scheme="https" android:host="www.vmovee.watch" android:pathPrefix="/"/>
<data android:scheme="https" android:host="allmoviesforyou.net" android:pathPrefix="/"/> <data android:scheme="https" android:host="allmoviesforyou.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="vidembed.cc" android:pathPrefix="/"/> <data android:scheme="https" android:host="membed.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="vf-film.me" android:pathPrefix="/"/> <data android:scheme="https" android:host="vf-film.me" android:pathPrefix="/"/>
<data android:scheme="https" android:host="vf-serie.org" android:pathPrefix="/"/> <data android:scheme="https" android:host="vf-serie.org" android:pathPrefix="/"/>
<data android:scheme="https" android:host="french-stream.re" android:pathPrefix="/"/> <data android:scheme="https" android:host="french-stream.re" android:pathPrefix="/"/>
<data android:scheme="https" android:host="asianembed.io" android:pathPrefix="/"/> <data android:scheme="https" android:host="asianembed.io" android:pathPrefix="/"/>
<data android:scheme="https" android:host="asiaflix.app" android:pathPrefix="/"/> <data android:scheme="https" android:host="asiaflix.app" android:pathPrefix="/"/>
<data android:scheme="https" android:host="eja.tv/" android:pathPrefix="/"/>
<data android:scheme="https" android:host="bflix.ru" android:pathPrefix="/"/> <data android:scheme="https" android:host="bflix.ru" android:pathPrefix="/"/>
<data android:scheme="https" android:host="fmovies.to" android:pathPrefix="/"/> <data android:scheme="https" android:host="fmovies.to" android:pathPrefix="/"/>
<data android:scheme="https" android:host="sflix.pro" android:pathPrefix="/"/> <data android:scheme="https" android:host="sflix.pro" android:pathPrefix="/"/>
@ -104,39 +114,71 @@
<data android:scheme="https" android:host="www.pinoy-hd.xyz" android:pathPrefix="/"/> <data android:scheme="https" android:host="www.pinoy-hd.xyz" android:pathPrefix="/"/>
<data android:scheme="https" android:host="pinoymovies.es" android:pathPrefix="/"/> <data android:scheme="https" android:host="pinoymovies.es" android:pathPrefix="/"/>
<data android:scheme="https" android:host="trailers.to" android:pathPrefix="/"/> <data android:scheme="https" android:host="trailers.to" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www.2embed.ru" android:pathPrefix="/"/> <data android:scheme="https" android:host="2embed.org" android:pathPrefix="/"/>
<data android:scheme="https" android:host="dramasee.net" android:pathPrefix="/"/> <data android:scheme="https" android:host="dramasee.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="watchasian.sh" android:pathPrefix="/"/> <data android:scheme="https" android:host="watchasian.cx" android:pathPrefix="/"/>
<data android:scheme="https" android:host="185.224.83.103" android:pathPrefix="/"/>
<data android:scheme="https" android:host="kdramahood.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="kdramahood.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="akwam.to" android:pathPrefix="/"/> <data android:scheme="https" android:host="akwam.to" android:pathPrefix="/"/>
<data android:scheme="https" android:host="mycima.tv" android:pathPrefix="/"/> <data android:scheme="https" android:host="mycima.tv" android:pathPrefix="/"/>
<data android:scheme="https" android:host="cimanow.cc" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www.egy.best" android:pathPrefix="/"/> <data android:scheme="https" android:host="www.egy.best" android:pathPrefix="/"/>
<data android:scheme="https" android:host="faselhd.io" android:pathPrefix="/"/>
<data android:scheme="https" android:host="secretlink.xyz" android:pathPrefix="/"/> <data android:scheme="https" android:host="secretlink.xyz" android:pathPrefix="/"/>
<data android:scheme="https" android:host="hdm.to" android:pathPrefix="/"/> <data android:scheme="https" android:host="hdm.to" android:pathPrefix="/"/>
<data android:scheme="https" android:host="theflix.to" android:pathPrefix="/"/> <data android:scheme="https" android:host="theflix.to" android:pathPrefix="/"/>
<data android:scheme="https" android:host="streamingcommunity.best" android:pathPrefix="/"/> <data android:scheme="https" android:host="streamingcommunity.best" android:pathPrefix="/"/>
<data android:scheme="https" android:host="altadefinizione.tienda" android:pathPrefix="/"/>
<data android:scheme="https" android:host="cb01.rip" android:pathPrefix="/"/>
<data android:scheme="https" android:host="filmpertutti.love" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www.tantifilm.nl" android:pathPrefix="/"/> <data android:scheme="https" android:host="www.tantifilm.nl" android:pathPrefix="/"/>
<data android:scheme="https" android:host="v2.apimdb.net" android:pathPrefix="/"/> <data android:scheme="https" android:host="cb01.rip" android:pathPrefix="/"/>
<data android:scheme="https" android:host="altadefinizione.tienda" android:pathPrefix="/"/>
<data android:scheme="https" android:host="filmpertutti.love" android:pathPrefix="/"/>
<data android:scheme="https" android:host="hdmovie2.art" android:pathPrefix="/"/>
<data android:scheme="https" android:host="http://167.88.14.149" android:pathPrefix="/"/>
<data android:scheme="https" android:host="149.56.24.226" android:pathPrefix="/"/>
<data android:scheme="https" android:host="hdtoday.cc" android:pathPrefix="/"/>
<data android:scheme="https" android:host="openvids.io" android:pathPrefix="/"/>
<data android:scheme="https" android:host="94.103.82.88" android:pathPrefix="/"/>
<data android:scheme="https" android:host="146.19.24.137" android:pathPrefix="/"/>
<data android:scheme="https" android:host="v2.vidsrc.me" android:pathPrefix="/"/>
<data android:scheme="https" android:host="uakino.club" android:pathPrefix="/"/>
<data android:scheme="https" android:host="phimmoichill.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="rezka.ag" android:pathPrefix="/"/>
<data android:scheme="https" android:host="yomovies.plus" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www.wcostream.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="www.wcostream.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="gogoanime.film" android:pathPrefix="/"/> <data android:scheme="https" android:host="gogoanime.sk" android:pathPrefix="/"/>
<data android:scheme="https" android:host="allanime.site" android:pathPrefix="/"/> <data android:scheme="https" android:host="allanime.site" android:pathPrefix="/"/>
<data android:scheme="https" android:host="animekisa.in" android:pathPrefix="/"/> <data android:scheme="https" android:host="animekisa.in" android:pathPrefix="/"/>
<data android:scheme="https" android:host="animeflick.net" android:pathPrefix="/"/> <data android:scheme="https" android:host="animeflick.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www3.animeflv.net" android:pathPrefix="/"/> <data android:scheme="https" android:host="www3.animeflv.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="animefenix.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="animeflv.io" android:pathPrefix="/"/>
<data android:scheme="https" android:host="jkanime.net" android:pathPrefix="/"/>
<data android:scheme="https" android:host="tenshi.moe" android:pathPrefix="/"/> <data android:scheme="https" android:host="tenshi.moe" android:pathPrefix="/"/>
<data android:scheme="https" android:host="wcostream.cc" android:pathPrefix="/"/> <data android:scheme="https" android:host="wcostream.cc" android:pathPrefix="/"/>
<data android:scheme="https" android:host="animepahe.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="animepahe.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="dreamsub.me" android:pathPrefix="/"/>
<data android:scheme="https" android:host="9anime.id" android:pathPrefix="/"/> <data android:scheme="https" android:host="9anime.id" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www.animeworld.tv" android:pathPrefix="/"/> <data android:scheme="https" android:host="www.animeworld.tv" android:pathPrefix="/"/>
<data android:scheme="https" android:host="zoro.to" android:pathPrefix="/"/> <data android:scheme="https" android:host="zoro.to" android:pathPrefix="/"/>
<data android:scheme="https" android:host="bestdubbedanime.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="bestdubbedanime.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="monoschinos2.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="monoschinos2.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="www.mundodonghua.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="kawaiifu.com" android:pathPrefix="/"/> <data android:scheme="https" android:host="kawaiifu.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="neonime.watch" android:pathPrefix="/"/>
<data android:scheme="https" android:host="kuramanime.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="65.108.132.145" android:pathPrefix="/"/>
<data android:scheme="https" android:host="185.231.223.76" android:pathPrefix="/"/>
<data android:scheme="https" android:host="75.119.159.228" android:pathPrefix="/"/>
<data android:scheme="https" android:host="45.12.2.2" android:pathPrefix="/"/>
<data android:scheme="https" android:host="otakudesu.watch" android:pathPrefix="/"/>
<data android:scheme="https" android:host="animeindo.sbs" android:pathPrefix="/"/>
<data android:scheme="https" android:host="111.90.143.42" android:pathPrefix="/"/>
<data android:scheme="https" android:host="tocanime.co" android:pathPrefix="/"/>
<data android:scheme="https" android:host="olgply.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="aniflix.pro" android:pathPrefix="/"/>
<data android:scheme="https" android:host="kimcartoon.li" android:pathPrefix="/"/>
<data android:scheme="https" android:host="xcine.me" android:pathPrefix="/"/>
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />

View File

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.ui.player package com.lagradost.cloudstream3.ui.player
import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.KeyEvent import android.view.KeyEvent
@ -35,6 +37,34 @@ class DownloadedPlayerActivity : AppCompatActivity() {
finish() 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?) { override fun onCreate(savedInstanceState: Bundle?) {
Log.i(DTAG, "onCreate") Log.i(DTAG, "onCreate")
@ -45,69 +75,35 @@ class DownloadedPlayerActivity : AppCompatActivity() {
setContentView(R.layout.empty_layout) setContentView(R.layout.empty_layout)
val data = intent.data 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() finish()
return 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)))
// )
// )
// }
} }
} }

View File

@ -1,10 +1,7 @@
package com.lagradost.cloudstream3.ui.player package com.lagradost.cloudstream3.ui.player
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.ExtractorUri
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.loadExtractor
class LinkGenerator( class LinkGenerator(
private val links: List<String>, private val links: List<String>,
@ -50,12 +47,13 @@ class LinkGenerator(
if (!extract || !loadExtractor(link, referer) { if (!extract || !loadExtractor(link, referer) {
callback(it to null) callback(it to null)
}) { }) {
// if don't extract or if no extractor found simply return the link // if don't extract or if no extractor found simply return the link
callback( callback(
ExtractorLink( ExtractorLink(
"", "",
link, link,
link, unshortenLinkSafe(link), // unshorten because it might be a raw link
referer ?: "", referer ?: "",
Qualities.Unknown.value, link.contains(".m3u") // TODO USE REAL PARSER Qualities.Unknown.value, link.contains(".m3u") // TODO USE REAL PARSER
) to null ) to null

View File

@ -5,6 +5,7 @@ import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.* import com.lagradost.cloudstream3.extractors.*
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -143,6 +144,17 @@ fun getAndUnpack(string: String): String {
return JsUnpacker(packedText).unpack() ?: 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. * 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, referer: String? = null,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val currentUrl = unshortenLinkSafe(url)
for (extractor in extractorApis) { for (extractor in extractorApis) {
if (url.replace(schemaStripRegex, "") if (currentUrl.replace(schemaStripRegex, "")
.startsWith(extractor.mainUrl.replace(schemaStripRegex, "")) .startsWith(extractor.mainUrl.replace(schemaStripRegex, ""))
) { ) {
extractor.getSafeUrl(url, referer)?.forEach(callback) extractor.getSafeUrl(currentUrl, referer)?.forEach(callback)
return true return true
} }
} }
return false return false
} }
@ -166,9 +181,11 @@ suspend fun loadExtractor(
url: String, url: String,
referer: String? = null, referer: String? = null,
): List<ExtractorLink> { ): List<ExtractorLink> {
val currentUrl = unshortenLinkSafe(url)
for (extractor in extractorApis) { for (extractor in extractorApis) {
if (url.startsWith(extractor.mainUrl)) { if (currentUrl.startsWith(extractor.mainUrl)) {
return extractor.getSafeUrl(url, referer) ?: emptyList() return extractor.getSafeUrl(currentUrl, referer) ?: emptyList()
} }
} }
return emptyList() return emptyList()

View File

@ -1,4 +1,5 @@
package com.lagradost.cloudstream3.utils package com.lagradost.cloudstream3.utils
import android.util.Base64 import android.util.Base64
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.base64Decode import com.lagradost.cloudstream3.base64Decode
@ -8,163 +9,182 @@ import java.net.URLDecoder
//Code heavily based on unshortenit.py form kodiondemand /addon //Code heavily based on unshortenit.py form kodiondemand /addon
private data class ShortUrl( object ShortLink {
val regex: Regex, data class ShortUrl(
val type: String, val regex: Regex,
val function: suspend (String) -> String, val type: String,
) { val function: suspend (String) -> String,
constructor(regex: String, type: String, function: suspend (String) -> String) : this( ) {
Regex(regex), constructor(regex: String, type: String, function: suspend (String) -> String) : this(
type, Regex(regex),
function 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),
) )
} }
}
class ShortLink{ private val adflyRegex =
fun isShortLink(url : String) : Boolean{ """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"""
return ShortUrl.shortList.firstOrNull { private val linkupRegex = """linkup\.pro|buckler.link"""
it.regex.find(url) != null}!=null 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 { suspend fun unshorten(uri: String, type: String? = null): String {
var currentUrl = uri var currentUrl = uri
while (true) { while (true) {
val oldurl = currentUrl val oldurl = currentUrl
val domain = URI(currentUrl).host ?: throw IllegalArgumentException("No domain found in URI!") val domain =
currentUrl = ShortUrl.shortList.firstOrNull { URI(currentUrl).host ?: throw IllegalArgumentException("No domain found in URI!")
currentUrl = shortList.firstOrNull {
it.regex.find(domain) != null || type == it.type it.regex.find(domain) != null || type == it.type
}?.function?.let { it(currentUrl) } ?: break }?.function?.let { it(currentUrl) } ?: break
if (oldurl == currentUrl){ if (oldurl == currentUrl) {
break break
} }
} }
return currentUrl 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()){ suspend fun unshortenAdfly(uri: String): String {
var left = "" val html = app.get(uri).text
var right = "" 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}) { for (c in ysmm.replace(Regex("""var ysmm = '|';"""), "").chunked(2)
left += c[0] .dropLastWhile { it.length == 1 }) {
right = c[1] + right 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}){ suspend fun unshortenLinkup(uri: String): String {
val xor = (el[0].second).code.xor(el[1].second.code) var r: NiceResponse? = null
if (xor < 10){ var uri = uri
encodedUri[el[0].first] = xor.digitToChar() 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("<iframe[^<>]*src=\\'([^'>]*)\\'[^<>]*>").find(r.text)?.value
?: Regex("""action="(?:[^/]+.*?/[^/]+/([a-zA-Z0-9_]+))">""").find(r.text)?.value
?: Regex("""href","((.|\\n)*?)"""").findAll(r.text)
.elementAtOrNull(1)?.groupValues?.get(1)
if (link != null) {
uri = link
}
} }
} }
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){ val short = Regex("""^https?://.*?(https?://.*)""").find(uri)?.value
decodedUri = Base64.decode(decodedUri.replace(Regex("""(.*?)u="""),""),Base64.DEFAULT).decodeToString() if (short != null) {
uri = short
}
if (r == null) {
r = app.get(
uri,
allowRedirects = false
)
if (r.headers["location"] != null) {
uri = r.headers["location"].toString()
}
}
if (uri.contains("snip.")) {
if (uri.contains("out_generator")) {
uri = Regex("url=(.*)\$").find(uri)!!.value
} else if (uri.contains("/decode/")) {
uri = app.get(uri, allowRedirects = true).url
}
} }
return decodedUri
}
else {
return uri return uri
} }
return uri
}
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("<iframe[^<>]*src=\\'([^'>]*)\\'[^<>]*>").find(r.text)?.value ?:
Regex("""action="(?:[^/]+.*?/[^/]+/([a-zA-Z0-9_]+))">""").find(r.text)?.value ?:
Regex("""href","((.|\\n)*?)"""").findAll(r.text).elementAtOrNull(1)?.groupValues?.get(1)
if (link!=null) { fun unshortenLinksafe(uri: String): String {
uri = link return base64Decode(uri.split("?url=").last())
}
suspend fun unshortenNuovoIndirizzo(uri: String): String {
val soup = app.get(uri, allowRedirects = true)
val header = soup.headers["refresh"]
val link: String = if (header != null) {
soup.headers["refresh"]!!.substringAfter("=")
} else {
"non trovato"
}
return link
}
suspend fun unshortenNuovoLink(uri: String): String {
return app.get(uri, allowRedirects = true).document.selectFirst("a")!!.attr("href")
}
suspend fun unshortenUprot(uri: String): String {
val page = app.get(uri).text
Regex("""<a[^>]+href="([^"]+)""").findAll(page)
.map { it.value.replace("""<a href="""", "") }
.toList().forEach { link ->
if (link.contains("https://maxstream.video") || link.contains("https://uprot.net") && link != uri) {
return link
}
} }
} return uri
} }
val short = Regex("""^https?://.*?(https?://.*)""").find(uri)?.value fun unshortenDavisonbarker(uri: String): String {
if (short!=null){ return URLDecoder.decode(uri.substringAfter("dest="))
uri = short
} }
if (r==null){
r = app.get(
uri,
allowRedirects = false)
if (r.headers["location"]!= null){
uri = r.headers["location"].toString()
}
}
if (uri.contains("snip.")) {
if (uri.contains("out_generator")) {
uri = Regex("url=(.*)\$").find(uri)!!.value
}
else if (uri.contains("/decode/")) {
uri = app.get(uri, allowRedirects = true).url
}
}
return uri
}
fun unshortenLinksafe(uri:String) : String {
return base64Decode(uri.split("?url=").last())
}
suspend fun unshortenNuovoIndirizzo(uri:String) : String {
val soup = app.get(uri, allowRedirects = true)
val header = soup.headers["refresh"]
val link : String= if (header != null) {
soup.headers["refresh"]!!.substringAfter("=") }
else{
"non trovato"
}
return link
}
suspend fun unshortenNuovoLink(uri:String) : String {
return app.get(uri, allowRedirects = true).document.selectFirst("a")!!.attr("href")
}
suspend fun unshortenUprot(uri: String): String {
val page = app.get(uri).text
Regex("""<a[^>]+href="([^"]+)""").findAll(page).map { it.value.replace("""<a href="""","") }.toList().forEach { link ->
if (link.contains("https://maxstream.video") || link.contains("https://uprot.net") && link != uri){
return link
}
}
return uri
}
fun unshortenDavisonbarker(uri: String): String {
return URLDecoder.decode(uri.substringAfter("dest="))
} }

View File

@ -92,6 +92,7 @@
<string name="duration_format" formatted="true">%d min</string> <string name="duration_format" formatted="true">%d min</string>
<string name="app_name">CloudStream</string> <string name="app_name">CloudStream</string>
<string name="play_with_app_name">Play with CloudStream</string>
<string name="title_home">Home</string> <string name="title_home">Home</string>
<string name="title_search">Search</string> <string name="title_search">Search</string>
<string name="title_downloads">Downloads</string> <string name="title_downloads">Downloads</string>