mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Play with CloudStream, fixed #1335
This commit is contained in:
parent
738d56916f
commit
bec9a87eed
6 changed files with 284 additions and 210 deletions
|
@ -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" />
|
||||||
|
|
||||||
|
|
|
@ -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)))
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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="))
|
|
||||||
}
|
}
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue