mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
f055b55e89
96 changed files with 1084 additions and 492 deletions
4
.github/site-list.py
vendored
4
.github/site-list.py
vendored
|
@ -6,14 +6,14 @@ from typing import List, Dict
|
|||
|
||||
# Globals
|
||||
URL_REGEX = compile(
|
||||
"override val mainUrl(?:\:\s?String)?[^\"']+[\"'](https?://[a-zA-Z0-9\.-]+)[\"']")
|
||||
"override\sva[lr]\smainUrl[^\"']+[\"'](https?://[a-zA-Z0-9\.-]+)[\"']")
|
||||
NAME_REGEX = compile("class (.+?) ?: \w+\(\)\s\{")
|
||||
START_MARKER = "<!--SITE LIST START-->"
|
||||
END_MARKER = "<!--SITE LIST END-->"
|
||||
GLOB = "app/src/main/java/com/lagradost/cloudstream3/*providers/*Provider.kt"
|
||||
MAIN_API = "app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt"
|
||||
API_REGEX = compile(
|
||||
"val (?:restrictedA|a)pis = arrayListOf\((.+?)\)(?=\n\n)", DOTALL)
|
||||
"val\s*allProviders.*?{\s.*?arrayListOf\(([\W\w]*?)\)\s*\n*\s*}", DOTALL)
|
||||
|
||||
sites: Dict[str, str] = {}
|
||||
enabled_sites: List[str] = []
|
||||
|
|
|
@ -98,4 +98,6 @@ It merely scrapes 3rd-party websites that are publicly accessable via any regula
|
|||
- [9anime.center](https://9anime.center)
|
||||
- [animeworld.tv](https://www.animeworld.tv)
|
||||
- [asiaflix.app](https://asiaflix.app)
|
||||
- [kawaiifu.com](https://kawaiifu.com)
|
||||
- [hdm.to](https://hdm.to)
|
||||
<!--SITE LIST END-->
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.net.Uri
|
|||
import android.util.Base64.encodeToString
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
|
@ -31,86 +32,76 @@ object APIHolder {
|
|||
|
||||
private const val defProvider = 0
|
||||
|
||||
val apis = arrayListOf(
|
||||
PelisplusProvider(),
|
||||
PelisplusHDProvider(),
|
||||
PeliSmartProvider(),
|
||||
GogoanimeProvider(),
|
||||
AllAnimeProvider(),
|
||||
AnimekisaProvider(),
|
||||
//ShiroProvider(), // v2 fucked me
|
||||
AnimeFlickProvider(),
|
||||
AnimeflvnetProvider(),
|
||||
val allProviders by lazy {
|
||||
arrayListOf(
|
||||
// Movie providers
|
||||
PelisplusProvider(),
|
||||
PelisplusHDProvider(),
|
||||
PeliSmartProvider(),
|
||||
MeloMovieProvider(), // Captcha for links
|
||||
DoramasYTProvider(),
|
||||
CinecalidadProvider(),
|
||||
CuevanaProvider(),
|
||||
EntrepeliculasyseriesProvider(),
|
||||
PelisflixProvider(),
|
||||
SeriesflixProvider(),
|
||||
IHaveNoTvProvider(), // Documentaries provider
|
||||
LookMovieProvider(), // RECAPTCHA (Please allow up to 5 seconds...)
|
||||
VMoveeProvider(),
|
||||
AllMoviesForYouProvider(),
|
||||
VidEmbedProvider(),
|
||||
VfFilmProvider(),
|
||||
VfSerieProvider(),
|
||||
FrenchStreamProvider(),
|
||||
AsianLoadProvider(),
|
||||
AsiaFlixProvider(), // restricted
|
||||
BflixProvider(),
|
||||
FmoviesToProvider(),
|
||||
SflixProProvider(),
|
||||
FilmanProvider(),
|
||||
SflixProvider(),
|
||||
DopeboxProvider(),
|
||||
SolarmovieProvider(),
|
||||
PinoyMoviePediaProvider(),
|
||||
PinoyHDXyzProvider(),
|
||||
PinoyMoviesEsProvider(),
|
||||
TrailersTwoProvider(),
|
||||
TwoEmbedProvider(),
|
||||
DramaSeeProvider(),
|
||||
WatchAsianProvider(),
|
||||
KdramaHoodProvider(),
|
||||
AkwamProvider(),
|
||||
MyCimaProvider(),
|
||||
EgyBestProvider(),
|
||||
SoaptwoDayProvider(),
|
||||
HDMProvider(),// disabled due to cloudflare
|
||||
|
||||
TenshiProvider(),
|
||||
WcoProvider(),
|
||||
// MeloMovieProvider(), // Captcha for links
|
||||
DubbedAnimeProvider(),
|
||||
DoramasYTProvider(),
|
||||
CinecalidadProvider(),
|
||||
CuevanaProvider(),
|
||||
EntrepeliculasyseriesProvider(),
|
||||
PelisflixProvider(),
|
||||
SeriesflixProvider(),
|
||||
IHaveNoTvProvider(), // Documentaries provider
|
||||
//LookMovieProvider(), // RECAPTCHA (Please allow up to 5 seconds...)
|
||||
VMoveeProvider(),
|
||||
WatchCartoonOnlineProvider(),
|
||||
AllMoviesForYouProvider(),
|
||||
ApiMDBProvider(),
|
||||
// Metadata providers
|
||||
//TmdbProvider(),
|
||||
CrossTmdbProvider(),
|
||||
ApiMDBProvider(),
|
||||
|
||||
MonoschinosProvider(),
|
||||
// Anime providers
|
||||
WatchCartoonOnlineProvider(),
|
||||
GogoanimeProvider(),
|
||||
AllAnimeProvider(),
|
||||
AnimekisaProvider(),
|
||||
//ShiroProvider(), // v2 fucked me
|
||||
AnimeFlickProvider(),
|
||||
AnimeflvnetProvider(),
|
||||
TenshiProvider(),
|
||||
WcoProvider(),
|
||||
AnimePaheProvider(),
|
||||
NineAnimeProvider(),
|
||||
AnimeWorldProvider(),
|
||||
ZoroProvider(),
|
||||
DubbedAnimeProvider(),
|
||||
MonoschinosProvider(),
|
||||
KawaiifuProvider(), // disabled due to cloudflare
|
||||
)
|
||||
}
|
||||
|
||||
VidEmbedProvider(),
|
||||
VfFilmProvider(),
|
||||
VfSerieProvider(),
|
||||
FrenchStreamProvider(),
|
||||
|
||||
AsianLoadProvider(),
|
||||
|
||||
BflixProvider("https://bflix.ru","Bflix"),
|
||||
BflixProvider("https://fmovies.to","Fmovies.to"),
|
||||
BflixProvider("https://sflix.pro","Sflix.pro"),
|
||||
|
||||
SflixProvider("https://sflix.to", "Sflix.to"),
|
||||
SflixProvider("https://dopebox.to", "Dopebox"),
|
||||
SflixProvider("https://solarmovie.pe", "Solarmovie"),
|
||||
|
||||
//TmdbProvider(),
|
||||
|
||||
FilmanProvider(),
|
||||
|
||||
ZoroProvider(),
|
||||
PinoyMoviePediaProvider(),
|
||||
PinoyHDXyzProvider(),
|
||||
PinoyMoviesEsProvider(),
|
||||
TrailersTwoProvider(),
|
||||
TwoEmbedProvider(),
|
||||
DramaSeeProvider(),
|
||||
WatchAsianProvider(),
|
||||
KdramaHoodProvider(),
|
||||
AkwamProvider(),
|
||||
MyCimaProvider(),
|
||||
EgyBestProvider(),
|
||||
AnimePaheProvider(),
|
||||
NineAnimeProvider(),
|
||||
AnimeWorldProvider(),
|
||||
SoaptwoDayProvider(),
|
||||
|
||||
CrossTmdbProvider(),
|
||||
)
|
||||
|
||||
val restrictedApis = arrayListOf(
|
||||
// TrailersToProvider(), // be aware that this is fuckery
|
||||
// NyaaProvider(), // torrents in cs3 is wack
|
||||
// ThenosProvider(), // ddos protection and wacked links
|
||||
AsiaFlixProvider(),
|
||||
)
|
||||
|
||||
private val backwardsCompatibleProviders = arrayListOf(
|
||||
KawaiifuProvider(), // removed due to cloudflare
|
||||
HDMProvider(),// removed due to cloudflare
|
||||
)
|
||||
var apis : List<MainAPI> = arrayListOf()
|
||||
|
||||
fun getApiFromName(apiName: String?): MainAPI {
|
||||
return getApiFromNameNull(apiName) ?: apis[defProvider]
|
||||
|
@ -118,15 +109,7 @@ object APIHolder {
|
|||
|
||||
fun getApiFromNameNull(apiName: String?): MainAPI? {
|
||||
if (apiName == null) return null
|
||||
for (api in apis) {
|
||||
if (apiName == api.name)
|
||||
return api
|
||||
}
|
||||
for (api in restrictedApis) {
|
||||
if (apiName == api.name)
|
||||
return api
|
||||
}
|
||||
for (api in backwardsCompatibleProviders) {
|
||||
for (api in allProviders) {
|
||||
if (apiName == api.name)
|
||||
return api
|
||||
}
|
||||
|
@ -281,10 +264,45 @@ object APIHolder {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
0 = Site not good
|
||||
1 = All good
|
||||
2 = Slow, heavy traffic
|
||||
3 = restricted, must donate 30 benenes to use
|
||||
*/
|
||||
const val PROVIDER_STATUS_KEY = "PROVIDER_STATUS_KEY"
|
||||
const val PROVIDER_STATUS_URL = "https://raw.githubusercontent.com/LagradOst/CloudStream-3/master/providers.json"
|
||||
const val PROVIDER_STATUS_BETA_ONLY = 3
|
||||
const val PROVIDER_STATUS_SLOW = 2
|
||||
const val PROVIDER_STATUS_OK = 1
|
||||
const val PROVIDER_STATUS_DOWN = 0
|
||||
|
||||
data class ProvidersInfoJson(
|
||||
@JsonProperty("name") var name: String,
|
||||
@JsonProperty("url") var url: String,
|
||||
@JsonProperty("status") var status: Int,
|
||||
)
|
||||
|
||||
/**Every provider will **not** have try catch built in, so handle exceptions when calling these functions*/
|
||||
abstract class MainAPI {
|
||||
open val name = "NONE"
|
||||
open val mainUrl = "NONE"
|
||||
companion object {
|
||||
var overrideData : HashMap<String, ProvidersInfoJson>? = null
|
||||
}
|
||||
|
||||
public fun overrideWithNewData(data : ProvidersInfoJson) {
|
||||
this.name = data.name
|
||||
this.mainUrl = data.url
|
||||
}
|
||||
|
||||
init {
|
||||
overrideData?.get(this.javaClass.simpleName)?.let { data ->
|
||||
overrideWithNewData(data)
|
||||
}
|
||||
}
|
||||
|
||||
open var name = "NONE"
|
||||
open var mainUrl = "NONE"
|
||||
|
||||
//open val uniqueId : Int by lazy { this.name.hashCode() } // in case of duplicate providers you can have a shared id
|
||||
|
||||
|
@ -317,17 +335,17 @@ abstract class MainAPI {
|
|||
open val providerType = ProviderType.DirectProvider
|
||||
|
||||
@WorkerThread
|
||||
suspend open fun getMainPage(): HomePageResponse? {
|
||||
open suspend fun getMainPage(): HomePageResponse? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
suspend open fun search(query: String): List<SearchResponse>? {
|
||||
open suspend fun search(query: String): List<SearchResponse>? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
suspend open fun quickSearch(query: String): List<SearchResponse>? {
|
||||
open suspend fun quickSearch(query: String): List<SearchResponse>? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
|
@ -336,7 +354,7 @@ abstract class MainAPI {
|
|||
* Based on data from search() or getMainPage() it generates a LoadResponse,
|
||||
* basically opening the info page from a link.
|
||||
* */
|
||||
suspend open fun load(url: String): LoadResponse? {
|
||||
open suspend fun load(url: String): LoadResponse? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
|
@ -350,13 +368,13 @@ abstract class MainAPI {
|
|||
* if the need arises.
|
||||
* */
|
||||
@WorkerThread
|
||||
suspend open fun extractorVerifierJob(extractorData: String?) {
|
||||
open suspend fun extractorVerifierJob(extractorData: String?) {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
/**Callback is fired once a link is found, will return true if method is executed successfully*/
|
||||
@WorkerThread
|
||||
suspend open fun loadLinks(
|
||||
open suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -23,9 +23,9 @@ import androidx.preference.PreferenceManager
|
|||
import com.google.android.gms.cast.framework.*
|
||||
import com.google.android.material.navigationrail.NavigationRailView
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
|
||||
import com.lagradost.cloudstream3.APIHolder.allProviders
|
||||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
|
||||
import com.lagradost.cloudstream3.APIHolder.restrictedApis
|
||||
import com.lagradost.cloudstream3.CommonActivity.backEvent
|
||||
import com.lagradost.cloudstream3.CommonActivity.loadThemes
|
||||
import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent
|
||||
|
@ -46,9 +46,12 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSet
|
|||
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.setUpBackup
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState
|
||||
|
@ -60,6 +63,9 @@ import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
|||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_result_swipe.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
|
@ -308,6 +314,88 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
for (api in OAuth2accountApis) {
|
||||
api.init()
|
||||
}
|
||||
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val downloadFromGithub = try {
|
||||
settingsManager.getBoolean(getString(R.string.killswitch_key), true)
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
false
|
||||
}
|
||||
|
||||
// must give benenes to get beta providers
|
||||
val hasBenene = try {
|
||||
val count = settingsManager.getInt(getString(R.string.benene_count), 0)
|
||||
count > 30
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
false
|
||||
}
|
||||
|
||||
// this pulls the latest data so ppl don't have to update to simply change provider url
|
||||
if(downloadFromGithub) {
|
||||
try {
|
||||
runBlocking {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val cacheStr: String? = getKey(PROVIDER_STATUS_KEY)
|
||||
val cache: HashMap<String, ProvidersInfoJson>? =
|
||||
cacheStr?.let { tryParseJson(cacheStr) }
|
||||
if (cache != null) {
|
||||
// if cache is found then spin up a new request, but dont wait
|
||||
main {
|
||||
try {
|
||||
val txt = app.get(PROVIDER_STATUS_URL).text
|
||||
val newCache =
|
||||
tryParseJson<HashMap<String, ProvidersInfoJson>>(txt)
|
||||
setKey(PROVIDER_STATUS_KEY, txt)
|
||||
MainAPI.overrideData = newCache // update all new providers
|
||||
for (api in apis) { // update current providers
|
||||
newCache?.get(api.javaClass.simpleName)?.let { data ->
|
||||
api.overrideWithNewData(data)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
cache
|
||||
} else {
|
||||
// if it is the first time the user has used the app then wait for a request to update all providers
|
||||
val txt = app.get(PROVIDER_STATUS_URL).text
|
||||
setKey(PROVIDER_STATUS_KEY, txt)
|
||||
val newCache = tryParseJson<HashMap<String, ProvidersInfoJson>>(txt)
|
||||
newCache
|
||||
}?.let { providersJsonMap ->
|
||||
MainAPI.overrideData = providersJsonMap
|
||||
val acceptableProviders =
|
||||
providersJsonMap.filter { it.value.status == PROVIDER_STATUS_OK || it.value.status == PROVIDER_STATUS_SLOW }
|
||||
.map { it.key }.toSet()
|
||||
|
||||
val restrictedApis =
|
||||
if (hasBenene) providersJsonMap.filter { it.value.status == PROVIDER_STATUS_BETA_ONLY }
|
||||
.map { it.key }.toSet() else emptySet()
|
||||
|
||||
apis = allProviders.filter { api ->
|
||||
val name = api.javaClass.simpleName
|
||||
// if the provider does not exist in the json file, then it is shown by default
|
||||
!providersJsonMap.containsKey(name) || acceptableProviders.contains(name) || restrictedApis.contains(name)
|
||||
}
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
apis = allProviders
|
||||
e.printStackTrace()
|
||||
logError(e)
|
||||
}
|
||||
} else {
|
||||
apis = allProviders
|
||||
}
|
||||
|
||||
loadThemes(this)
|
||||
updateLocale()
|
||||
app.initClient(this)
|
||||
|
@ -458,10 +546,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
createISO()
|
||||
}*/
|
||||
|
||||
var providersString = "Current providers are:\n"
|
||||
var providersAndroidManifestString = "Current androidmanifest should be:\n"
|
||||
for (api in apis) {
|
||||
providersString += "+ ${api.mainUrl}\n"
|
||||
for (api in allProviders) {
|
||||
providersAndroidManifestString += "<data android:scheme=\"https\" android:host=\"${
|
||||
api.mainUrl.removePrefix(
|
||||
"https://"
|
||||
|
@ -469,17 +555,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
}\" android:pathPrefix=\"/\"/>\n"
|
||||
}
|
||||
|
||||
for (api in restrictedApis) {
|
||||
providersString += "+ ${api.mainUrl}\n"
|
||||
providersAndroidManifestString += "<data android:scheme=\"https\" android:host=\"${
|
||||
api.mainUrl.removePrefix(
|
||||
"https://"
|
||||
)
|
||||
}\" android:pathPrefix=\"/\"/>\n"
|
||||
}
|
||||
println(providersString)
|
||||
|
||||
|
||||
println(providersAndroidManifestString)
|
||||
|
||||
handleAppIntent(intent)
|
||||
|
@ -488,15 +563,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
runAutoUpdate()
|
||||
}
|
||||
|
||||
// must give benenes to get beta providers
|
||||
try {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val count = settingsManager.getInt(getString(R.string.benene_count), 0)
|
||||
if (count > 30 && restrictedApis.size > 0 && !apis.contains(restrictedApis.first()))
|
||||
apis.addAll(restrictedApis)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
APIRepository.dubStatusActive = getApiDubstatusSettings()
|
||||
|
||||
try {
|
||||
|
@ -507,7 +573,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
|
||||
println("Loaded everything")
|
||||
/*
|
||||
val relativePath = (Environment.DIRECTORY_DOWNLOADS) + File.separatorChar
|
||||
val displayName = "output.dex" //""output.dex"
|
||||
|
|
|
@ -17,8 +17,8 @@ import java.util.*
|
|||
|
||||
|
||||
class AllAnimeProvider : MainAPI() {
|
||||
override val mainUrl = "https://allanime.site"
|
||||
override val name = "AllAnime"
|
||||
override var mainUrl = "https://allanime.site"
|
||||
override var name = "AllAnime"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = false
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ class AnimeFlickProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override val mainUrl = "https://animeflick.net"
|
||||
override val name = "AnimeFlick"
|
||||
override var mainUrl = "https://animeflick.net"
|
||||
override var name = "AnimeFlick"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = false
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ class AnimePaheProvider : MainAPI() {
|
|||
Regex("""(^(?:https?:)?(?://)?(?:www\.)?(?:youtu\.be/|youtube(?:-nocookie)?\.(?:[A-Za-z]{2,4}|[A-Za-z]{2,3}\.[A-Za-z]{2})/)(?:watch|embed/|vi?/)*(?:\?[\w=&]*vi?=)?[^#&?/]{11}.*${'$'})""")
|
||||
}
|
||||
|
||||
override val mainUrl = MAIN_URL
|
||||
override val name = "AnimePahe"
|
||||
override var mainUrl = MAIN_URL
|
||||
override var name = "AnimePahe"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
|
||||
class AnimeWorldProvider : MainAPI() {
|
||||
override val mainUrl = "https://www.animeworld.tv"
|
||||
override val name = "AnimeWorld"
|
||||
override var mainUrl = "https://www.animeworld.tv"
|
||||
override var name = "AnimeWorld"
|
||||
override val lang = "it"
|
||||
override val hasMainPage = true
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
else TvType.Anime
|
||||
}
|
||||
}
|
||||
override val mainUrl = "https://www3.animeflv.net"
|
||||
override val name = "Animeflv.net"
|
||||
override var mainUrl = "https://www3.animeflv.net"
|
||||
override var name = "Animeflv.net"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -12,8 +12,8 @@ import kotlin.collections.ArrayList
|
|||
|
||||
class AnimekisaProvider : MainAPI() {
|
||||
|
||||
override val mainUrl = "https://animekisa.in"
|
||||
override val name = "Animekisa"
|
||||
override var mainUrl = "https://animekisa.in"
|
||||
override var name = "Animekisa"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
override val hasDownloadSupport = true
|
||||
|
|
|
@ -11,8 +11,8 @@ import org.jsoup.Jsoup
|
|||
import java.util.*
|
||||
|
||||
class DubbedAnimeProvider : MainAPI() {
|
||||
override val mainUrl = "https://bestdubbedanime.com"
|
||||
override val name = "DubbedAnime"
|
||||
override var mainUrl = "https://bestdubbedanime.com"
|
||||
override var name = "DubbedAnime"
|
||||
override val hasQuickSearch = true
|
||||
override val hasMainPage = true
|
||||
|
||||
|
|
|
@ -155,8 +155,8 @@ class GogoanimeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override val mainUrl = "https://gogoanime.film"
|
||||
override val name = "GogoAnime"
|
||||
override var mainUrl = "https://gogoanime.film"
|
||||
override var name = "GogoAnime"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ import org.jsoup.Jsoup
|
|||
import java.util.*
|
||||
|
||||
class KawaiifuProvider : MainAPI() {
|
||||
override val mainUrl = "https://kawaiifu.com"
|
||||
override val name = "Kawaiifu"
|
||||
override var mainUrl = "https://kawaiifu.com"
|
||||
override var name = "Kawaiifu"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ class MonoschinosProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override val mainUrl = "https://monoschinos2.com"
|
||||
override val name = "Monoschinos"
|
||||
override var mainUrl = "https://monoschinos2.com"
|
||||
override var name = "Monoschinos"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -10,8 +10,8 @@ import org.jsoup.Jsoup
|
|||
import java.util.*
|
||||
|
||||
class NineAnimeProvider : MainAPI() {
|
||||
override val mainUrl = "https://9anime.center"
|
||||
override val name = "9Anime"
|
||||
override var mainUrl = "https://9anime.center"
|
||||
override var name = "9Anime"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
override val hasDownloadSupport = true
|
||||
|
|
|
@ -25,8 +25,8 @@ class TenshiProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override val mainUrl = "https://tenshi.moe"
|
||||
override val name = "Tenshi.moe"
|
||||
override var mainUrl = "https://tenshi.moe"
|
||||
override var name = "Tenshi.moe"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie, TvType.OVA)
|
||||
|
|
|
@ -12,8 +12,8 @@ import java.util.*
|
|||
|
||||
|
||||
class WatchCartoonOnlineProvider : MainAPI() {
|
||||
override val name = "WatchCartoonOnline"
|
||||
override val mainUrl = "https://www.wcostream.com"
|
||||
override var name = "WatchCartoonOnline"
|
||||
override var mainUrl = "https://www.wcostream.com"
|
||||
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Cartoon,
|
||||
|
|
|
@ -19,8 +19,8 @@ class WcoProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override val mainUrl = "https://wcostream.cc"
|
||||
override val name = "WCO Stream"
|
||||
override var mainUrl = "https://wcostream.cc"
|
||||
override var name = "WCO Stream"
|
||||
override val hasQuickSearch = true
|
||||
override val hasMainPage = true
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ import java.net.URI
|
|||
import java.util.*
|
||||
|
||||
class ZoroProvider : MainAPI() {
|
||||
override val mainUrl = "https://zoro.to"
|
||||
override val name = "Zoro"
|
||||
override var mainUrl = "https://zoro.to"
|
||||
override var name = "Zoro"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -5,8 +5,8 @@ import com.lagradost.cloudstream3.utils.*
|
|||
import java.net.URI
|
||||
|
||||
class AsianLoad : ExtractorApi() {
|
||||
override val name = "AsianLoad"
|
||||
override val mainUrl = "https://asianembed.io"
|
||||
override var name = "AsianLoad"
|
||||
override var mainUrl = "https://asianembed.io"
|
||||
override val requiresReferer = true
|
||||
|
||||
private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*?["'](.*?)["']""")
|
||||
|
|
|
@ -7,21 +7,21 @@ import com.lagradost.cloudstream3.utils.Qualities
|
|||
import kotlinx.coroutines.delay
|
||||
|
||||
class DoodToExtractor : DoodLaExtractor() {
|
||||
override val mainUrl = "https://dood.to"
|
||||
override var mainUrl = "https://dood.to"
|
||||
}
|
||||
|
||||
class DoodSoExtractor : DoodLaExtractor() {
|
||||
override val mainUrl = "https://dood.so"
|
||||
override var mainUrl = "https://dood.so"
|
||||
}
|
||||
|
||||
class DoodWsExtractor : DoodLaExtractor() {
|
||||
override val mainUrl = "https://dood.ws"
|
||||
override var mainUrl = "https://dood.ws"
|
||||
}
|
||||
|
||||
|
||||
open class DoodLaExtractor : ExtractorApi() {
|
||||
override val name = "DoodStream"
|
||||
override val mainUrl = "https://dood.la"
|
||||
override var name = "DoodStream"
|
||||
override var mainUrl = "https://dood.la"
|
||||
override val requiresReferer = false
|
||||
|
||||
override fun getExtractorUrl(id: String): String {
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.lagradost.cloudstream3.utils.*
|
|||
import com.lagradost.cloudstream3.app
|
||||
|
||||
class Evoload1 : Evoload() {
|
||||
override val mainUrl = "https://evoload.io"
|
||||
override var mainUrl = "https://evoload.io"
|
||||
}
|
||||
|
||||
open class Evoload : ExtractorApi() {
|
||||
|
|
|
@ -12,8 +12,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
|
|||
|
||||
|
||||
open class GenericM3U8 : ExtractorApi() {
|
||||
override val name = "Upstream"
|
||||
override val mainUrl = "https://upstream.to"
|
||||
override var name = "Upstream"
|
||||
override var mainUrl = "https://upstream.to"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.lagradost.cloudstream3.app
|
|||
|
||||
|
||||
open class Jawcloud : ExtractorApi() {
|
||||
override val name = "Jawcloud"
|
||||
override val mainUrl = "https://jawcloud.co"
|
||||
override var name = "Jawcloud"
|
||||
override var mainUrl = "https://jawcloud.co"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
|
||||
|
|
|
@ -11,8 +11,8 @@ import com.lagradost.cloudstream3.utils.M3u8Helper
|
|||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
|
||||
open class Mcloud : ExtractorApi() {
|
||||
override val name = "Mcloud"
|
||||
override val mainUrl = "https://mcloud.to"
|
||||
override var name = "Mcloud"
|
||||
override var mainUrl = "https://mcloud.to"
|
||||
override val requiresReferer = true
|
||||
val headers = mapOf(
|
||||
"Host" to "mcloud.to",
|
||||
|
|
|
@ -4,8 +4,8 @@ import com.lagradost.cloudstream3.app
|
|||
import com.lagradost.cloudstream3.utils.*
|
||||
|
||||
class MixDrop : ExtractorApi() {
|
||||
override val name = "MixDrop"
|
||||
override val mainUrl = "https://mixdrop.co"
|
||||
override var name = "MixDrop"
|
||||
override var mainUrl = "https://mixdrop.co"
|
||||
private val srcRegex = Regex("""wurl.*?=.*?"(.*?)";""")
|
||||
override val requiresReferer = false
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.Qualities
|
|||
import com.lagradost.cloudstream3.utils.getAndUnpack
|
||||
|
||||
class Mp4Upload : ExtractorApi() {
|
||||
override val name = "Mp4Upload"
|
||||
override val mainUrl = "https://www.mp4upload.com"
|
||||
override var name = "Mp4Upload"
|
||||
override var mainUrl = "https://www.mp4upload.com"
|
||||
private val srcRegex = Regex("""player\.src\("(.*?)"""")
|
||||
override val requiresReferer = true
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
|
|||
import java.net.URI
|
||||
|
||||
class MultiQuality : ExtractorApi() {
|
||||
override val name = "MultiQuality"
|
||||
override val mainUrl = "https://gogo-play.net"
|
||||
override var name = "MultiQuality"
|
||||
override var mainUrl = "https://gogo-play.net"
|
||||
private val sourceRegex = Regex("""file:\s*['"](.*?)['"],label:\s*['"](.*?)['"]""")
|
||||
private val m3u8Regex = Regex(""".*?(\d*).m3u8""")
|
||||
private val urlRegex = Regex("""(.*?)([^/]+$)""")
|
||||
|
|
|
@ -1,35 +1,63 @@
|
|||
package com.lagradost.cloudstream3.extractors
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
|
||||
data class DataOptionsJson (
|
||||
@JsonProperty("flashvars") var flashvars : Flashvars? = Flashvars(),
|
||||
)
|
||||
data class Flashvars (
|
||||
@JsonProperty("metadata") var metadata : String? = null,
|
||||
@JsonProperty("hlsManifestUrl") var hlsManifestUrl : String? = null, //m3u8
|
||||
)
|
||||
|
||||
data class MetadataOkru (
|
||||
@JsonProperty("videos") var videos: ArrayList<Videos> = arrayListOf(),
|
||||
)
|
||||
|
||||
data class Videos (
|
||||
@JsonProperty("name") var name : String,
|
||||
@JsonProperty("url") var url : String,
|
||||
@JsonProperty("seekSchema") var seekSchema : Int? = null,
|
||||
@JsonProperty("disallowed") var disallowed : Boolean? = null
|
||||
)
|
||||
|
||||
open class OkRu : ExtractorApi() {
|
||||
override val name = "Okru"
|
||||
override val mainUrl = "http://ok.ru"
|
||||
override var name = "Okru"
|
||||
override var mainUrl = "http://ok.ru"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
|
||||
val doc = app.get(url).document
|
||||
val urlString = doc.select("div[data-options]").attr("data-options")
|
||||
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
|
||||
.substringBefore("]")
|
||||
urlString.split("{\\\"name\\\":\\\"").reversed().forEach {
|
||||
val extractedUrl = it.substringAfter("url\\\":\\\"")
|
||||
.substringBefore("\\\"")
|
||||
.replace("\\\\u0026", "&")
|
||||
val Quality = it.uppercase().substringBefore("\\\"")
|
||||
|
||||
if (extractedUrl.isNotBlank()) return listOf(
|
||||
ExtractorLink(
|
||||
val sources = ArrayList<ExtractorLink>()
|
||||
val datajson = doc.select("div[data-options]").attr("data-options")
|
||||
if (datajson.isNotBlank()) {
|
||||
val main = parseJson<DataOptionsJson>(datajson)
|
||||
val metadatajson = parseJson<MetadataOkru>(main.flashvars?.metadata!!)
|
||||
val servers = metadatajson.videos
|
||||
servers.forEach {
|
||||
val quality = it.name.uppercase()
|
||||
.replace("MOBILE","144p")
|
||||
.replace("LOWEST","240p")
|
||||
.replace("LOW","360p")
|
||||
.replace("SD","480p")
|
||||
.replace("HD","720p")
|
||||
.replace("FULL","1080p")
|
||||
.replace("QUAD","1440p")
|
||||
.replace("ULTRA","4k")
|
||||
val extractedurl = it.url.replace("\\\\u0026", "&")
|
||||
sources.add(ExtractorLink(
|
||||
name,
|
||||
"$name ${Quality}",
|
||||
extractedUrl,
|
||||
"$name $quality",
|
||||
extractedurl,
|
||||
url,
|
||||
Qualities.Unknown.value,
|
||||
getQualityFromName(quality),
|
||||
isM3u8 = false
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
return null
|
||||
return sources
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@ import com.lagradost.cloudstream3.app
|
|||
|
||||
|
||||
open class PlayerVoxzer : ExtractorApi() {
|
||||
override val name = "Voxzer"
|
||||
override val mainUrl = "https://player.voxzer.org"
|
||||
override var name = "Voxzer"
|
||||
override var mainUrl = "https://player.voxzer.org"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
|
||||
|
|
|
@ -10,16 +10,16 @@ import com.lagradost.cloudstream3.utils.getPostForm
|
|||
import org.jsoup.Jsoup
|
||||
|
||||
//class SBPlay1 : SBPlay() {
|
||||
// override val mainUrl = "https://sbplay1.com"
|
||||
// override var mainUrl = "https://sbplay1.com"
|
||||
//}
|
||||
|
||||
//class SBPlay2 : SBPlay() {
|
||||
// override val mainUrl = "https://sbplay2.com"
|
||||
// override var mainUrl = "https://sbplay2.com"
|
||||
//}
|
||||
|
||||
open class SBPlay : ExtractorApi() {
|
||||
override val mainUrl = "https://sbplay.one"
|
||||
override val name = "SBPlay"
|
||||
override var mainUrl = "https://sbplay.one"
|
||||
override var name = "SBPlay"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
|
|
|
@ -9,46 +9,50 @@ import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|||
|
||||
|
||||
class StreamSB1 : StreamSB() {
|
||||
override val mainUrl = "https://sbplay1.com"
|
||||
override var mainUrl = "https://sbplay1.com"
|
||||
}
|
||||
|
||||
class StreamSB2 : StreamSB() {
|
||||
override val mainUrl = "https://sbplay2.com"
|
||||
override var mainUrl = "https://sbplay2.com"
|
||||
}
|
||||
|
||||
class StreamSB3 : StreamSB() {
|
||||
override val mainUrl = "https://sbplay3.com"
|
||||
override var mainUrl = "https://sbplay3.com"
|
||||
}
|
||||
|
||||
class StreamSB4 : StreamSB() {
|
||||
override val mainUrl = "https://cloudemb.com"
|
||||
override var mainUrl = "https://cloudemb.com"
|
||||
}
|
||||
|
||||
class StreamSB5 : StreamSB() {
|
||||
override val mainUrl = "https://sbplay.org"
|
||||
override var mainUrl = "https://sbplay.org"
|
||||
}
|
||||
|
||||
class StreamSB6 : StreamSB() {
|
||||
override val mainUrl = "https://embedsb.com"
|
||||
override var mainUrl = "https://embedsb.com"
|
||||
}
|
||||
|
||||
class StreamSB7 : StreamSB() {
|
||||
override val mainUrl = "https://pelistop.co"
|
||||
override var mainUrl = "https://pelistop.co"
|
||||
}
|
||||
|
||||
class StreamSB8 : StreamSB() {
|
||||
override val mainUrl = "https://streamsb.net"
|
||||
override var mainUrl = "https://streamsb.net"
|
||||
}
|
||||
|
||||
class StreamSB9 : StreamSB() {
|
||||
override val mainUrl = "https://sbplay.one"
|
||||
override var mainUrl = "https://sbplay.one"
|
||||
}
|
||||
|
||||
class StreamSB10 : StreamSB() {
|
||||
override var mainUrl = "https://sbplay2.xyz"
|
||||
}
|
||||
|
||||
// This is a modified version of https://github.com/jmir1/aniyomi-extensions/blob/master/src/en/genoanime/src/eu/kanade/tachiyomi/animeextension/en/genoanime/extractors/StreamSBExtractor.kt
|
||||
// The following code is under the Apache License 2.0 https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE
|
||||
open class StreamSB : ExtractorApi() {
|
||||
override val name = "StreamSB"
|
||||
override val mainUrl = "https://watchsb.com"
|
||||
override var name = "StreamSB"
|
||||
override var mainUrl = "https://watchsb.com"
|
||||
override val requiresReferer = false
|
||||
|
||||
private val hexArray = "0123456789ABCDEF".toCharArray()
|
||||
|
@ -88,53 +92,30 @@ open class StreamSB : ExtractorApi() {
|
|||
}.first()
|
||||
val bytes = id.toByteArray()
|
||||
val bytesToHex = bytesToHex(bytes)
|
||||
val master = "$mainUrl/sources41/566d337678566f743674494a7c7c${bytesToHex}7c7c346b6767586d6934774855537c7c73747265616d7362/6565417268755339773461447c7c346133383438333436313335376136323337373433383634376337633465366534393338373136643732373736343735373237613763376334363733353737303533366236333463353333363534366137633763373337343732363536313664373336327c7c6b586c3163614468645a47617c7c73747265616d7362"
|
||||
val master = "$mainUrl/sources41/6d6144797752744a454267617c7c${bytesToHex.lowercase()}7c7c4e61755a56456f34385243727c7c73747265616d7362/6b4a33767968506e4e71374f7c7c343837323439333133333462353935333633373836643638376337633462333634663539343137373761333635313533333835333763376333393636363133393635366136323733343435323332376137633763373337343732363536313664373336327c7c504d754478413835306633797c7c73747265616d7362"
|
||||
val headers = mapOf(
|
||||
"Host" to url.substringAfter("https://").substringBefore("/"),
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0",
|
||||
"Accept" to "application/json, text/plain, */*",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"Referer" to url,
|
||||
"watchsb" to "streamsb",
|
||||
"DNT" to "1",
|
||||
"Connection" to "keep-alive",
|
||||
"Sec-Fetch-Dest" to "empty",
|
||||
"Sec-Fetch-Mode" to "no-cors",
|
||||
"Sec-Fetch-Site" to "same-origin",
|
||||
"TE" to "trailers",
|
||||
"Pragma" to "no-cache",
|
||||
"Cache-Control" to "no-cache",)
|
||||
)
|
||||
val urltext = app.get(master,
|
||||
headers = headers,
|
||||
allowRedirects = false
|
||||
).text
|
||||
val mapped = urltext.let { parseJson<Main>(it) }
|
||||
val testurl = app.get(mapped.streamData.file, headers = headers).text
|
||||
val urlmain = mapped.streamData.file.substringBefore("/hls/")
|
||||
// val urlmain = mapped.streamData.file.substringBefore("/hls/")
|
||||
if (urltext.contains("m3u8") && testurl.contains("EXTM3U")) return M3u8Helper().m3u8Generation(
|
||||
M3u8Helper.M3u8Stream(
|
||||
mapped.streamData.file,
|
||||
headers = mapOf(
|
||||
"User-Agent" to USER_AGENT,
|
||||
"Accept" to "*/*",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"Accept-Encoding" to "gzip, deflate, br",
|
||||
"Origin" to mainUrl,
|
||||
"DNT" to "1",
|
||||
"Connection" to "keep-alive",
|
||||
"Referer" to "$mainUrl/",
|
||||
"Sec-Fetch-Dest" to "empty",
|
||||
"Sec-Fetch-Mode" to "cors",
|
||||
"Sec-Fetch-Site" to "cross-site",),
|
||||
headers = headers
|
||||
), true
|
||||
)
|
||||
.map { stream ->
|
||||
val cleanstreamurl = stream.streamUrl.replace(Regex("https://.*/hls/"), "$urlmain/hls/")
|
||||
// val cleanstreamurl = stream.streamUrl.replace(Regex("https://.*/hls/"), "$urlmain/hls/")
|
||||
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
|
||||
ExtractorLink(
|
||||
name,
|
||||
"$name $qualityString",
|
||||
cleanstreamurl,
|
||||
stream.streamUrl,
|
||||
url,
|
||||
getQualityFromName(stream.quality.toString()),
|
||||
true
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
|
||||
class StreamTape : ExtractorApi() {
|
||||
override val name = "StreamTape"
|
||||
override val mainUrl = "https://streamtape.com"
|
||||
override var name = "StreamTape"
|
||||
override var mainUrl = "https://streamtape.com"
|
||||
override val requiresReferer = false
|
||||
|
||||
private val linkRegex =
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.Qualities
|
|||
import java.net.URI
|
||||
|
||||
class Streamhub : ExtractorApi() {
|
||||
override val mainUrl = "https://streamhub.to"
|
||||
override val name = "Streamhub"
|
||||
override var mainUrl = "https://streamhub.to"
|
||||
override var name = "Streamhub"
|
||||
override val requiresReferer = false
|
||||
|
||||
override fun getExtractorUrl(id: String): String {
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
package com.lagradost.cloudstream3.extractors
|
||||
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
|
||||
class Cinestart: Tomatomatela() {
|
||||
override val name: String = "Cinestart"
|
||||
override val mainUrl: String = "https://cinestart.net"
|
||||
override var name = "Cinestart"
|
||||
override var mainUrl = "https://cinestart.net"
|
||||
override val details = "vr.php?v="
|
||||
}
|
||||
|
||||
open class Tomatomatela : ExtractorApi() {
|
||||
override val name = "Tomatomatela"
|
||||
override val mainUrl = "https://tomatomatela.com"
|
||||
override var name = "Tomatomatela"
|
||||
override var mainUrl = "https://tomatomatela.com"
|
||||
override val requiresReferer = false
|
||||
private data class Tomato (
|
||||
@JsonProperty("status") val status: Int,
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.lagradost.cloudstream3.utils.*
|
|||
import com.lagradost.cloudstream3.app
|
||||
|
||||
class Uqload1 : Uqload() {
|
||||
override val mainUrl = "https://uqload.com"
|
||||
override var mainUrl = "https://uqload.com"
|
||||
}
|
||||
|
||||
open class Uqload : ExtractorApi() {
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.M3u8Helper
|
|||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
|
||||
open class WatchSB : ExtractorApi() {
|
||||
override val name = "WatchSB"
|
||||
override val mainUrl = "https://watchsb.com"
|
||||
override var name = "WatchSB"
|
||||
override var mainUrl = "https://watchsb.com"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
|
|
|
@ -8,19 +8,19 @@ import com.lagradost.cloudstream3.mapper
|
|||
import com.lagradost.cloudstream3.utils.*
|
||||
|
||||
class Vidstreamz : WcoStream() {
|
||||
override val mainUrl: String = "https://vidstreamz.online"
|
||||
override var mainUrl = "https://vidstreamz.online"
|
||||
}
|
||||
class Vizcloud : WcoStream() {
|
||||
override val mainUrl: String = "https://vizcloud2.ru"
|
||||
override var mainUrl = "https://vizcloud2.ru"
|
||||
}
|
||||
|
||||
class Vizcloud2 : WcoStream() {
|
||||
override val mainUrl: String = "https://vizcloud2.online"
|
||||
override var mainUrl = "https://vizcloud2.online"
|
||||
}
|
||||
|
||||
open class WcoStream : ExtractorApi() {
|
||||
override val name = "VidStream" //Cause works for animekisa and wco
|
||||
override val mainUrl = "https://vidstream.pro"
|
||||
override var name = "VidStream" //Cause works for animekisa and wco
|
||||
override var mainUrl = "https://vidstream.pro"
|
||||
override val requiresReferer = false
|
||||
private val hlsHelper = M3u8Helper()
|
||||
|
||||
|
|
|
@ -5,23 +5,23 @@ import com.lagradost.cloudstream3.app
|
|||
import com.lagradost.cloudstream3.utils.*
|
||||
|
||||
class Zplayer: ZplayerV2() {
|
||||
override val name: String = "Zplayer"
|
||||
override val mainUrl: String = "https://zplayer.live"
|
||||
override var name: String = "Zplayer"
|
||||
override var mainUrl: String = "https://zplayer.live"
|
||||
}
|
||||
|
||||
class Upstream: ZplayerV2() {
|
||||
override val name: String = "Upstream" //Here 'cause works
|
||||
override val mainUrl: String = "https://upstream.to"
|
||||
override var name: String = "Upstream" //Here 'cause works
|
||||
override var mainUrl: String = "https://upstream.to"
|
||||
}
|
||||
|
||||
class Streamhub2: ZplayerV2() {
|
||||
override val name: String = "Streamhub" //Here 'cause works
|
||||
override val mainUrl: String = "https://streamhub.to"
|
||||
override var name = "Streamhub" //Here 'cause works
|
||||
override var mainUrl = "https://streamhub.to"
|
||||
}
|
||||
|
||||
open class ZplayerV2 : ExtractorApi() {
|
||||
override val name = "Zplayer V2"
|
||||
override val mainUrl = "https://v2.zplayer.live"
|
||||
override var name = "Zplayer V2"
|
||||
override var mainUrl = "https://v2.zplayer.live"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
|
|
|
@ -10,7 +10,7 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
|||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
||||
class CrossTmdbProvider : TmdbProvider() {
|
||||
override val name = "MultiMovie"
|
||||
override var name = "MultiMovie"
|
||||
override val apiName = "MultiMovie"
|
||||
override val lang = "en"
|
||||
override val useMetaLoadResponse = true
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.jsoup.nodes.Element
|
|||
|
||||
class AkwamProvider : MainAPI() {
|
||||
override val lang = "ar"
|
||||
override val mainUrl = "https://akwam.to"
|
||||
override val name = "Akwam"
|
||||
override var mainUrl = "https://akwam.to"
|
||||
override var name = "Akwam"
|
||||
override val usesWebView = false
|
||||
override val hasMainPage = true
|
||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie, TvType.Anime, TvType.Cartoon)
|
||||
|
|
|
@ -19,8 +19,8 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
}
|
||||
|
||||
// Fetching movies will not work if this link is outdated.
|
||||
override val mainUrl = "https://allmoviesforyou.net"
|
||||
override val name = "AllMoviesForYou"
|
||||
override var mainUrl = "https://allmoviesforyou.net"
|
||||
override var name = "AllMoviesForYou"
|
||||
override val hasMainPage = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
|
@ -149,7 +149,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
name,
|
||||
season.first,
|
||||
epNum,
|
||||
href,
|
||||
fixUrl(href),
|
||||
fixUrlNull(poster),
|
||||
date
|
||||
)
|
||||
|
@ -175,7 +175,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
title,
|
||||
url,
|
||||
type,
|
||||
url
|
||||
fixUrl(url)
|
||||
) {
|
||||
posterUrl = backgroundPoster
|
||||
this.year = year?.toIntOrNull()
|
||||
|
@ -193,12 +193,12 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val doc = app.get(data).document
|
||||
val iframe = doc.select("body iframe").map { it.attr("src") }
|
||||
val iframe = doc.select("body iframe").map { fixUrl(it.attr("src")) }
|
||||
iframe.apmap { id ->
|
||||
if (id.contains("trembed")) {
|
||||
val soup = app.get(id).document
|
||||
soup.select("body iframe").map {
|
||||
val link = it.attr("src").replace("streamhub.to/d/","streamhub.to/e/")
|
||||
val link = fixUrl(it.attr("src").replace("streamhub.to/d/","streamhub.to/e/"))
|
||||
loadExtractor(link, data, callback)
|
||||
}
|
||||
} else loadExtractor(id, data, callback)
|
||||
|
|
|
@ -10,8 +10,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
|||
|
||||
class ApiMDBProvider : TmdbProvider() {
|
||||
override val apiName = "ApiMDB"
|
||||
override val name = "ApiMDB"
|
||||
override val mainUrl = "https://v2.apimdb.net"
|
||||
override var name = "ApiMDB"
|
||||
override var mainUrl = "https://v2.apimdb.net"
|
||||
override val useMetaLoadResponse = true
|
||||
override val instantLinkLoading = false
|
||||
override val supportedTypes = setOf(
|
||||
|
|
|
@ -11,8 +11,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
|
|||
import java.net.URI
|
||||
|
||||
class AsiaFlixProvider : MainAPI() {
|
||||
override val mainUrl = "https://asiaflix.app"
|
||||
override val name = "AsiaFlix"
|
||||
override var mainUrl = "https://asiaflix.app"
|
||||
override var name = "AsiaFlix"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = false
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.lagradost.cloudstream3.TvType
|
|||
* make the app know what functions to call
|
||||
*/
|
||||
class AsianLoadProvider : VidstreamProviderTemplate() {
|
||||
override val name = "AsianLoad"
|
||||
override val mainUrl = "https://asianembed.io"
|
||||
override var name = "AsianLoad"
|
||||
override var mainUrl = "https://asianembed.io"
|
||||
override val homePageUrlList = listOf(
|
||||
mainUrl,
|
||||
"$mainUrl/recently-added-raw",
|
||||
|
|
|
@ -7,9 +7,18 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
class BflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
||||
override val mainUrl = providerUrl
|
||||
override val name = providerName
|
||||
class FmoviesToProvider : BflixProvider() {
|
||||
override var mainUrl = "https://fmovies.to"
|
||||
override var name = "Fmovies.to"
|
||||
}
|
||||
class SflixProProvider : BflixProvider() {
|
||||
override var mainUrl = "https://sflix.pro"
|
||||
override var name = "Sflix.pro"
|
||||
}
|
||||
|
||||
open class BflixProvider() : MainAPI() {
|
||||
override var mainUrl = "https://bflix.ru"
|
||||
override var name = "Bflix"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
override val hasDownloadSupport = true
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
package com.lagradost.cloudstream3.movieproviders
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.extractors.Cinestart
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import java.util.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
|
||||
class CinecalidadProvider:MainAPI() {
|
||||
override val mainUrl: String
|
||||
get() = "https://cinecalidad.lol"
|
||||
override val name: String
|
||||
get() = "Cinecalidad"
|
||||
override var mainUrl = "https://cinecalidad.lol"
|
||||
override var name = "Cinecalidad"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -9,8 +9,8 @@ import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|||
import java.util.*
|
||||
|
||||
class CuevanaProvider:MainAPI() {
|
||||
override val mainUrl = "https://cuevana3.io"
|
||||
override val name = "Cuevana"
|
||||
override var mainUrl = "https://cuevana3.me"
|
||||
override var name = "Cuevana"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
@ -191,19 +191,19 @@ class CuevanaProvider:MainAPI() {
|
|||
): Boolean {
|
||||
app.get(data).document.select("div.TPlayer.embed_div iframe").apmap {
|
||||
val iframe = fixUrl(it.attr("data-src"))
|
||||
if (iframe.contains("api.cuevana3.io/fembed/")) {
|
||||
val femregex = Regex("(https.\\/\\/api\\.cuevana3\\.io\\/fembed\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
if (iframe.contains("api.cuevana3.me/fembed/")) {
|
||||
val femregex = Regex("(https.\\/\\/api\\.cuevana3\\.me\\/fembed\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
femregex.findAll(iframe).map { femreg ->
|
||||
femreg.value
|
||||
}.toList().apmap { fem ->
|
||||
val key = fem.replace("https://api.cuevana3.io/fembed/?h=","")
|
||||
val url = app.post("https://api.cuevana3.io/fembed/api.php", allowRedirects = false, headers = mapOf("Host" to "api.cuevana3.io",
|
||||
val key = fem.replace("https://api.cuevana3.me/fembed/?h=","")
|
||||
val url = app.post("https://api.cuevana3.me/fembed/api.php", allowRedirects = false, headers = mapOf("Host" to "api.cuevana3.me",
|
||||
"User-Agent" to USER_AGENT,
|
||||
"Accept" to "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"X-Requested-With" to "XMLHttpRequest",
|
||||
"Origin" to "https://api.cuevana3.io",
|
||||
"Origin" to "https://api.cuevana3.me",
|
||||
"DNT" to "1",
|
||||
"Connection" to "keep-alive",
|
||||
"Sec-Fetch-Dest" to "empty",
|
||||
|
@ -239,12 +239,12 @@ class CuevanaProvider:MainAPI() {
|
|||
data = mapOf(Pair("url",tomkey))
|
||||
).response.headers.values("location").apmap { loc ->
|
||||
if (loc.contains("goto_ddh.php")) {
|
||||
val gotoregex = Regex("(\\/\\/api.cuevana3.io\\/ir\\/goto_ddh.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
val gotoregex = Regex("(\\/\\/api.cuevana3.me\\/ir\\/goto_ddh.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
gotoregex.findAll(loc).map { goreg ->
|
||||
goreg.value.replace("//api.cuevana3.io/ir/goto_ddh.php?h=","")
|
||||
goreg.value.replace("//api.cuevana3.me/ir/goto_ddh.php?h=","")
|
||||
}.toList().apmap { gotolink ->
|
||||
app.post("https://api.cuevana3.io/ir/redirect_ddh.php", allowRedirects = false,
|
||||
headers = mapOf("Host" to "api.cuevana3.io",
|
||||
app.post("https://api.cuevana3.me/ir/redirect_ddh.php", allowRedirects = false,
|
||||
headers = mapOf("Host" to "api.cuevana3.me",
|
||||
"User-Agent" to USER_AGENT,
|
||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
|
@ -263,12 +263,12 @@ class CuevanaProvider:MainAPI() {
|
|||
}
|
||||
}
|
||||
if (loc.contains("index.php?h=")) {
|
||||
val indexRegex = Regex("(\\/\\/api.cuevana3.io\\/sc\\/index.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
val indexRegex = Regex("(\\/\\/api.cuevana3.me\\/sc\\/index.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
indexRegex.findAll(loc).map { indreg ->
|
||||
indreg.value.replace("//api.cuevana3.io/sc/index.php?h=","")
|
||||
indreg.value.replace("//api.cuevana3.me/sc/index.php?h=","")
|
||||
}.toList().apmap { inlink ->
|
||||
app.post("https://api.cuevana3.io/sc/r.php", allowRedirects = false,
|
||||
headers = mapOf("Host" to "api.cuevana3.io",
|
||||
app.post("https://api.cuevana3.me/sc/r.php", allowRedirects = false,
|
||||
headers = mapOf("Host" to "api.cuevana3.me",
|
||||
"User-Agent" to USER_AGENT,
|
||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
|
|
|
@ -16,8 +16,8 @@ class DoramasYTProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override val mainUrl = "https://doramasyt.com"
|
||||
override val name = "DoramasYT"
|
||||
override var mainUrl = "https://doramasyt.com"
|
||||
override var name = "DoramasYT"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -10,8 +10,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
|
||||
class DramaSeeProvider : MainAPI() {
|
||||
override val mainUrl = "https://dramasee.net"
|
||||
override val name = "DramaSee"
|
||||
override var mainUrl = "https://dramasee.net"
|
||||
override var name = "DramaSee"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = false
|
||||
|
|
|
@ -8,8 +8,8 @@ import org.jsoup.nodes.Element
|
|||
|
||||
class EgyBestProvider : MainAPI() {
|
||||
override val lang = "ar"
|
||||
override val mainUrl = "https://egy.best"
|
||||
override val name = "EgyBest"
|
||||
override var mainUrl = "https://egy.best"
|
||||
override var name = "EgyBest"
|
||||
override val usesWebView = false
|
||||
override val hasMainPage = true
|
||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie)
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.*
|
|||
import java.util.*
|
||||
|
||||
class EntrepeliculasyseriesProvider:MainAPI() {
|
||||
override val mainUrl = "https://entrepeliculasyseries.nu"
|
||||
override val name = "EntrePeliculasySeries"
|
||||
override var mainUrl = "https://entrepeliculasyseries.nu"
|
||||
override var name = "EntrePeliculasySeries"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.jsoup.Jsoup
|
|||
import org.jsoup.select.Elements
|
||||
|
||||
class FilmanProvider : MainAPI() {
|
||||
override val mainUrl = "https://filman.cc"
|
||||
override val name = "filman.cc"
|
||||
override var mainUrl = "https://filman.cc"
|
||||
override var name = "filman.cc"
|
||||
override val lang = "pl"
|
||||
override val hasMainPage = true
|
||||
override val supportedTypes = setOf(
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.Qualities
|
|||
import org.jsoup.Jsoup
|
||||
|
||||
class HDMProvider : MainAPI() {
|
||||
override val name = "HD Movies"
|
||||
override val mainUrl = "https://hdm.to"
|
||||
override var name = "HD Movies"
|
||||
override var mainUrl = "https://hdm.to"
|
||||
override val hasMainPage = true
|
||||
|
||||
override val supportedTypes = setOf(
|
||||
|
|
|
@ -7,8 +7,8 @@ import org.jsoup.Jsoup
|
|||
import java.net.URLEncoder
|
||||
|
||||
class IHaveNoTvProvider : MainAPI() {
|
||||
override val mainUrl = "https://ihavenotv.com"
|
||||
override val name = "I Have No TV"
|
||||
override var mainUrl = "https://ihavenotv.com"
|
||||
override var name = "I Have No TV"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
|||
import org.jsoup.Jsoup
|
||||
|
||||
class KdramaHoodProvider : MainAPI() {
|
||||
override val mainUrl = "https://kdramahood.com"
|
||||
override val name = "KDramaHood"
|
||||
override var mainUrl = "https://kdramahood.com"
|
||||
override var name = "KDramaHood"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = false
|
||||
|
|
|
@ -13,8 +13,8 @@ import org.jsoup.Jsoup
|
|||
//BE AWARE THAT weboas.is is a clone of lookmovie
|
||||
class LookMovieProvider : MainAPI() {
|
||||
override val hasQuickSearch = true
|
||||
override val name = "LookMovie"
|
||||
override val mainUrl = "https://lookmovie.io"
|
||||
override var name = "LookMovie"
|
||||
override var mainUrl = "https://lookmovie.io"
|
||||
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
|
|
|
@ -11,8 +11,8 @@ import org.jsoup.Jsoup
|
|||
import org.jsoup.nodes.Element
|
||||
|
||||
class MeloMovieProvider : MainAPI() {
|
||||
override val name = "MeloMovie"
|
||||
override val mainUrl = "https://melomovie.com"
|
||||
override var name = "MeloMovie"
|
||||
override var mainUrl = "https://melomovie.com"
|
||||
override val instantLinkLoading = true
|
||||
override val hasQuickSearch = true
|
||||
override val hasChromecastSupport = false // MKV FILES CANT BE PLAYED ON A CHROMECAST
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.jsoup.nodes.Element
|
|||
|
||||
class MyCimaProvider : MainAPI() {
|
||||
override val lang = "ar"
|
||||
override val mainUrl = "https://mycima.tv"
|
||||
override val name = "MyCima"
|
||||
override var mainUrl = "https://mycima.tv"
|
||||
override var name = "MyCima"
|
||||
override val usesWebView = false
|
||||
override val hasMainPage = true
|
||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie)
|
||||
|
|
|
@ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
|||
import kotlin.collections.ArrayList
|
||||
|
||||
class PeliSmartProvider: MainAPI() {
|
||||
override val mainUrl = "https://pelismart.com"
|
||||
override val name = "PeliSmart"
|
||||
override var mainUrl = "https://pelismart.com"
|
||||
override var name = "PeliSmart"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
|
||||
class PelisflixProvider : MainAPI() {
|
||||
override val mainUrl = "https://pelisflix.li"
|
||||
override val name = "Pelisflix"
|
||||
override var mainUrl = "https://pelisflix.li"
|
||||
override var name = "Pelisflix"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -6,8 +6,8 @@ import org.jsoup.nodes.Element
|
|||
import java.util.*
|
||||
|
||||
class PelisplusHDProvider:MainAPI() {
|
||||
override val mainUrl = "https://pelisplushd.net"
|
||||
override val name = "PelisplusHD"
|
||||
override var mainUrl = "https://pelisplushd.net"
|
||||
override var name = "PelisplusHD"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -7,10 +7,10 @@ import com.lagradost.cloudstream3.TvType
|
|||
*/
|
||||
class PelisplusProvider : PelisplusProviderTemplate() {
|
||||
// mainUrl is good to have as a holder for the url to make future changes easier.
|
||||
override val mainUrl = "https://pelisplus.icu"
|
||||
override var mainUrl = "https://pelisplus.icu"
|
||||
|
||||
// name is for how the provider will be named which is visible in the UI, no real rules for this.
|
||||
override val name = "Pelisplus"
|
||||
override var name = "Pelisplus"
|
||||
|
||||
override val homePageUrlList = listOf(
|
||||
mainUrl,
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
package com.lagradost.cloudstream3.movieproviders
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.extractors.Pelisplus
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import org.jsoup.Jsoup
|
||||
import java.net.URI
|
||||
|
||||
/** Needs to inherit from MainAPI() to
|
||||
* make the app know what functions to call
|
||||
|
@ -14,7 +11,6 @@ import java.net.URI
|
|||
open class PelisplusProviderTemplate : MainAPI() {
|
||||
override val lang = "es"
|
||||
open val homePageUrlList = listOf<String>()
|
||||
open val pelisplusExtractorUrl: String? = null
|
||||
|
||||
// // mainUrl is good to have as a holder for the url to make future changes easier.
|
||||
// override val mainUrl: String
|
||||
|
@ -35,6 +31,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
|
||||
// Searching returns a SearchResponse, which can be one of the following: AnimeSearchResponse, MovieSearchResponse, TorrentSearchResponse, TvSeriesSearchResponse
|
||||
// Each of the classes requires some different data, but always has some critical things like name, poster and url.
|
||||
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
// Simply looking at devtools network is enough to spot a request like:
|
||||
// https://vidembed.cc/search.html?keyword=neverland where neverland is the query, can be written as below.
|
||||
|
@ -48,7 +45,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
val poster = fixUrl(li.selectFirst("img").attr("src"))
|
||||
|
||||
// .text() selects all the text in the element, be careful about doing this while too high up in the html hierarchy
|
||||
val title = li.selectFirst(".name").text()
|
||||
val title = cleanName(li.selectFirst(".name").text())
|
||||
// Use get(0) and toIntOrNull() to prevent any possible crashes, [0] or toInt() will error the search on unexpected values.
|
||||
val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull()
|
||||
|
||||
|
@ -73,33 +70,29 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
val html = app.get(url).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
||||
var title = soup.selectFirst("h1,h2,h3").text()
|
||||
title = if (!title.contains("Episode")) title else title.split("Episode")[0].trim()
|
||||
|
||||
val title = cleanName(soup.selectFirst("h1,h2,h3").text())
|
||||
val description = soup.selectFirst(".post-entry")?.text()?.trim()
|
||||
var poster: String? = null
|
||||
val poster = soup.selectFirst("head meta[property=og:image]").attr("content")
|
||||
|
||||
val episodes = soup.select(".listing.items.lists > .video-block").map { li ->
|
||||
val epTitle = if (li.selectFirst(".name") != null)
|
||||
if (li.selectFirst(".name").text().contains("Episode"))
|
||||
"Episode " + li.selectFirst(".name").text().split("Episode")[1].trim()
|
||||
else
|
||||
li.selectFirst(".name").text()
|
||||
else ""
|
||||
val href = fixUrl(li.selectFirst("a").attr("href"))
|
||||
val regexseason = Regex("(-[Tt]emporada-(\\d+)-[Cc]apitulo-(\\d+))")
|
||||
val aaa = regexseason.find(href)?.destructured?.component1()?.replace(Regex("(-[Tt]emporada-|[Cc]apitulo-)"),"")
|
||||
val seasonid = aaa.let { str ->
|
||||
str?.split("-")?.mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid?.size == 2
|
||||
val episode = if (isValid) seasonid?.getOrNull(1) else null
|
||||
val season = if (isValid) seasonid?.getOrNull(0) else null
|
||||
val epThumb = fixUrl(li.selectFirst("img").attr("src"))
|
||||
val epDate = li.selectFirst(".meta > .date").text()
|
||||
|
||||
if (poster == null) {
|
||||
poster = li.selectFirst("img")?.attr("onerror")?.replace("//img", "https://img")?.split("=")?.get(1)
|
||||
?.replace(Regex("[';]"), "")
|
||||
}
|
||||
|
||||
val epNum = Regex("""Episode (\d+)""").find(epTitle)?.destructured?.component1()?.toIntOrNull()
|
||||
|
||||
TvSeriesEpisode(
|
||||
epTitle,
|
||||
null,
|
||||
epNum,
|
||||
season,
|
||||
episode,
|
||||
fixUrl(li.selectFirst("a").attr("href")),
|
||||
epThumb,
|
||||
epDate
|
||||
|
@ -119,10 +112,10 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
this.name,
|
||||
tvType,
|
||||
episodes,
|
||||
poster,
|
||||
fixUrl(poster),
|
||||
year,
|
||||
description,
|
||||
ShowStatus.Ongoing,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
|
@ -134,7 +127,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
this.name,
|
||||
tvType,
|
||||
episodes[0].data,
|
||||
poster,
|
||||
fixUrl(poster),
|
||||
year,
|
||||
description,
|
||||
null,
|
||||
|
@ -156,12 +149,12 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
val document = Jsoup.parse(response)
|
||||
document.select("div.main-inner")?.forEach { inner ->
|
||||
// Always trim your text unless you want the risk of spaces at the start or end.
|
||||
val title = inner.select(".widget-title").text().trim()
|
||||
val title = cleanName(inner.select(".widget-title").text())
|
||||
val elements = inner.select(".video-block").map {
|
||||
val link = fixUrl(it.select("a").attr("href"))
|
||||
val image = it.select(".picture > img").attr("src").replace("//img", "https://img")
|
||||
val name = it.select("div.name").text().trim().replace(Regex("""[Ee]pisode \d+"""), "")
|
||||
val isSeries = (name.contains("Season") || name.contains("Episode"))
|
||||
val name = cleanName(it.select("div.name").text())
|
||||
val isSeries = (name.contains("Temporada") || name.contains("Capítulo"))
|
||||
|
||||
if (isSeries) {
|
||||
TvSeriesSearchResponse(
|
||||
|
@ -198,6 +191,38 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
return HomePageResponse(homePageList)
|
||||
}
|
||||
|
||||
|
||||
private fun cleanName(input: String): String = input.replace(Regex("([Tt]emporada (\\d+)|[Cc]apítulo (\\d+))|[Tt]emporada|[Cc]apítulo"),"").trim()
|
||||
|
||||
|
||||
private suspend fun getPelisStream(
|
||||
link: String,
|
||||
callback: (ExtractorLink) -> Unit) : Boolean {
|
||||
val soup = app.get(link).text
|
||||
val m3u8regex = Regex("((https:|http:)\\/\\/.*m3u8.*expiry=(\\d+))")
|
||||
val m3u8 = m3u8regex.find(soup)?.value ?: return false
|
||||
M3u8Helper().m3u8Generation(
|
||||
M3u8Helper.M3u8Stream(
|
||||
m3u8,
|
||||
headers = mapOf("Referer" to mainUrl)
|
||||
), true
|
||||
)
|
||||
.map { stream ->
|
||||
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
|
||||
callback(
|
||||
ExtractorLink(
|
||||
name,
|
||||
"$name $qualityString",
|
||||
stream.streamUrl,
|
||||
mainUrl,
|
||||
getQualityFromName(stream.quality.toString()),
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// loadLinks gets the raw .mp4 or .m3u8 urls from the data parameter in the episodes class generated in load()
|
||||
// See TvSeriesEpisode(...) in this provider.
|
||||
// The data are usually links, but can be any other string to help aid loading the links.
|
||||
|
@ -208,67 +233,37 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
// "?: return" is a very useful statement which returns if the iframe link isn't found.
|
||||
val iframeLink = Jsoup.parse(app.get(data).text).selectFirst(".tab-video")?.attr("data-video") ?: return false
|
||||
|
||||
// In this case the video player is a vidstream clone and can be handled by the vidstream extractor.
|
||||
// This case is a both unorthodox and you normally do not call extractors as they detect the url returned and does the rest.
|
||||
val vidstreamObject = Pelisplus(pelisplusExtractorUrl ?: mainUrl)
|
||||
// https://vidembed.cc/streaming.php?id=MzUwNTY2&... -> MzUwNTY2
|
||||
val id = Regex("""id=([^?]*)""").find(iframeLink)?.groupValues?.get(1)
|
||||
|
||||
if (id != null) {
|
||||
vidstreamObject.getUrl(id, isCasting, callback)
|
||||
}
|
||||
|
||||
val html = app.get(fixUrl(iframeLink)).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
||||
val servers = soup.select(".list-server-items > .linkserver").mapNotNull { li ->
|
||||
if (!li?.attr("data-video").isNullOrEmpty()) {
|
||||
Pair(li.text(), fixUrl(li.attr("data-video")))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
servers.apmap {
|
||||
// When checking strings make sure to make them lowercase and trimmed because edgecases like "beta server " wouldn't work otherwise.
|
||||
if (it.first.trim().equals("beta server", ignoreCase = true)) {
|
||||
// Group 1: link, Group 2: Label
|
||||
// Regex can be used to effectively parse small amounts of json without bothering with writing a json class.
|
||||
val sourceRegex = Regex("""sources:[\W\w]*?file:\s*["'](.*?)["'][\W\w]*?label:\s*["'](.*?)["']""")
|
||||
val trackRegex = Regex("""tracks:[\W\w]*?file:\s*["'](.*?)["'][\W\w]*?label:\s*["'](.*?)["']""")
|
||||
|
||||
// Having a referer is often required. It's a basic security check most providers have.
|
||||
// Try to replicate what your browser does.
|
||||
val serverHtml = app.get(it.second, headers = mapOf("referer" to iframeLink)).text
|
||||
sourceRegex.findAll(serverHtml).forEach { match ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
match.groupValues.getOrNull(2)?.let { "${this.name} $it" } ?: this.name,
|
||||
match.groupValues[1],
|
||||
it.second,
|
||||
// Useful function to turn something like "1080p" to an app quality.
|
||||
getQualityFromName(match.groupValues.getOrNull(2) ?: ""),
|
||||
// Kinda risky
|
||||
// isM3u8 makes the player pick the correct extractor for the source.
|
||||
// If isM3u8 is wrong the player will error on that source.
|
||||
URI(match.groupValues[1]).path.endsWith(".m3u8"),
|
||||
)
|
||||
)
|
||||
}
|
||||
trackRegex.findAll(serverHtml).forEach { match ->
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
match.groupValues.getOrNull(2) ?: "Unknown",
|
||||
match.groupValues[1]
|
||||
)
|
||||
)
|
||||
val doc = app.get(data).document
|
||||
val info = doc.select("div.tabs-video li").text()
|
||||
if (info.contains("Latino")) {
|
||||
doc.select(".server-item-1 li").apmap {
|
||||
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
||||
loadExtractor(serverid, data, callback)
|
||||
if (serverid.contains("pelisplus.icu")) {
|
||||
getPelisStream(serverid, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.contains("Subtitulado")) {
|
||||
doc.select(".server-item-0 li").apmap {
|
||||
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
||||
loadExtractor(serverid, data, callback)
|
||||
if (serverid.contains("pelisplus.icu")) {
|
||||
getPelisStream(serverid, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.contains("Castellano")) {
|
||||
doc.select(".server-item-2 li").apmap {
|
||||
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
||||
loadExtractor(serverid, data, callback)
|
||||
if (serverid.contains("pelisplus.icu")) {
|
||||
getPelisStream(serverid, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
|
||||
class PinoyHDXyzProvider : MainAPI() {
|
||||
override val name = "Pinoy-HD"
|
||||
override val mainUrl = "https://www.pinoy-hd.xyz"
|
||||
override var name = "Pinoy-HD"
|
||||
override var mainUrl = "https://www.pinoy-hd.xyz"
|
||||
override val lang = "tl"
|
||||
override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries)
|
||||
override val hasDownloadSupport = true
|
||||
|
|
|
@ -9,8 +9,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
|||
import java.lang.Exception
|
||||
|
||||
class PinoyMoviePediaProvider : MainAPI() {
|
||||
override val name = "Pinoy Moviepedia"
|
||||
override val mainUrl = "https://pinoymoviepedia.ru"
|
||||
override var name = "Pinoy Moviepedia"
|
||||
override var mainUrl = "https://pinoymoviepedia.ru"
|
||||
override val lang = "tl"
|
||||
override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries)
|
||||
override val hasDownloadSupport = true
|
||||
|
|
|
@ -13,8 +13,8 @@ import org.jsoup.select.Elements
|
|||
import java.lang.Exception
|
||||
|
||||
class PinoyMoviesEsProvider : MainAPI() {
|
||||
override val name = "Pinoy Movies"
|
||||
override val mainUrl = "https://pinoymovies.es"
|
||||
override var name = "Pinoy Movies"
|
||||
override var mainUrl = "https://pinoymovies.es"
|
||||
override val lang = "tl"
|
||||
override val supportedTypes = setOf(TvType.Movie)
|
||||
override val hasDownloadSupport = false
|
||||
|
|
|
@ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
|
||||
class SeriesflixProvider : MainAPI() {
|
||||
override val mainUrl = "https://seriesflix.video"
|
||||
override val name = "Seriesflix"
|
||||
override var mainUrl = "https://seriesflix.video"
|
||||
override var name = "Seriesflix"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
|
|
@ -21,9 +21,18 @@ import org.jsoup.nodes.Element
|
|||
import java.net.URI
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
||||
override val mainUrl = providerUrl
|
||||
override val name = providerName
|
||||
class DopeboxProvider : SflixProvider() {
|
||||
override var mainUrl = "https://dopebox.to"
|
||||
override var name = "Dopebox"
|
||||
}
|
||||
class SolarmovieProvider : SflixProvider() {
|
||||
override var mainUrl = "https://solarmovie.pe"
|
||||
override var name = "Solarmovie"
|
||||
}
|
||||
|
||||
open class SflixProvider() : MainAPI() {
|
||||
override var mainUrl = "https://sflix.to"
|
||||
override var name = "Sflix.to"
|
||||
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|||
import java.util.*
|
||||
|
||||
class SoaptwoDayProvider:MainAPI() {
|
||||
override val mainUrl = "https://secretlink.xyz" //Probably a rip off, but it has no captcha
|
||||
override val name = "Soap2Day"
|
||||
override var mainUrl = "https://secretlink.xyz" //Probably a rip off, but it has no captcha
|
||||
override var name = "Soap2Day"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
override val hasDownloadSupport = true
|
||||
|
|
|
@ -12,8 +12,8 @@ import com.lagradost.cloudstream3.utils.SubtitleHelper
|
|||
class TrailersTwoProvider : TmdbProvider() {
|
||||
val user = "cloudstream"
|
||||
override val apiName = "Trailers.to"
|
||||
override val name = "Trailers.to"
|
||||
override val mainUrl = "https://trailers.to"
|
||||
override var name = "Trailers.to"
|
||||
override var mainUrl = "https://trailers.to"
|
||||
override val useMetaLoadResponse = true
|
||||
override val instantLinkLoading = true
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
|||
|
||||
class TwoEmbedProvider : TmdbProvider() {
|
||||
override val apiName = "2Embed"
|
||||
override val name = "2Embed"
|
||||
override val mainUrl = "https://www.2embed.ru"
|
||||
override var name = "2Embed"
|
||||
override var mainUrl = "https://www.2embed.ru"
|
||||
override val useMetaLoadResponse = true
|
||||
override val instantLinkLoading = false
|
||||
override val supportedTypes = setOf(
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
|
|||
import org.jsoup.Jsoup
|
||||
|
||||
class VMoveeProvider : MainAPI() {
|
||||
override val name = "VMovee"
|
||||
override val mainUrl = "https://www.vmovee.watch"
|
||||
override var name = "VMovee"
|
||||
override var mainUrl = "https://www.vmovee.watch"
|
||||
|
||||
override val supportedTypes = setOf(TvType.Movie)
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ import org.jsoup.Jsoup
|
|||
|
||||
// referer = https://vf-film.org, USERAGENT ALSO REQUIRED
|
||||
class VfFilmProvider : MainAPI() {
|
||||
override val mainUrl = "https://vf-film.me"
|
||||
override val name = "vf-film.me"
|
||||
override var mainUrl = "https://vf-film.me"
|
||||
override var name = "vf-film.me"
|
||||
override val lang = "fr"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = false
|
||||
|
|
|
@ -7,8 +7,8 @@ import org.jsoup.Jsoup
|
|||
|
||||
// referer = https://vf-serie.org, USERAGENT ALSO REQUIRED
|
||||
class VfSerieProvider : MainAPI() {
|
||||
override val mainUrl = "https://vf-serie.org"
|
||||
override val name = "vf-serie.org"
|
||||
override var mainUrl = "https://vf-serie.org"
|
||||
override var name = "vf-serie.org"
|
||||
override val lang = "fr"
|
||||
|
||||
override val hasQuickSearch = false
|
||||
|
|
|
@ -7,10 +7,10 @@ import com.lagradost.cloudstream3.TvType
|
|||
*/
|
||||
class VidEmbedProvider : VidstreamProviderTemplate() {
|
||||
// mainUrl is good to have as a holder for the url to make future changes easier.
|
||||
override val mainUrl = "https://vidembed.cc"
|
||||
override var mainUrl = "https://vidembed.cc"
|
||||
|
||||
// name is for how the provider will be named which is visible in the UI, no real rules for this.
|
||||
override val name = "VidEmbed"
|
||||
override var name = "VidEmbed"
|
||||
|
||||
override val homePageUrlList: List<String> = listOf(
|
||||
mainUrl,
|
||||
|
|
|
@ -10,8 +10,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
|
||||
class WatchAsianProvider : MainAPI() {
|
||||
override val mainUrl = "https://watchasian.sh"
|
||||
override val name = "WatchAsian"
|
||||
override var mainUrl = "https://watchasian.sh"
|
||||
override var name = "WatchAsian"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = false
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.extractorApis
|
|||
|
||||
|
||||
class FrenchStreamProvider : MainAPI() {
|
||||
override val mainUrl = "https://french-stream.re"
|
||||
override val name = "French Stream"
|
||||
override var mainUrl = "https://french-stream.re"
|
||||
override var name = "French Stream"
|
||||
override val hasQuickSearch = false
|
||||
override val hasMainPage = true
|
||||
override val lang = "fr"
|
||||
|
|
|
@ -26,11 +26,11 @@ import java.net.URL
|
|||
import java.util.*
|
||||
|
||||
class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
||||
override val name = "AniList"
|
||||
override var name = "AniList"
|
||||
override val key = "6871"
|
||||
override val redirectUrl = "anilistlogin"
|
||||
override val idPrefix = "anilist"
|
||||
override val mainUrl = "https://anilist.co"
|
||||
override var mainUrl = "https://anilist.co"
|
||||
override val icon = R.drawable.ic_anilist_icon
|
||||
|
||||
override fun loginInfo(): OAuth2API.LoginInfo? {
|
||||
|
|
|
@ -5,7 +5,7 @@ import com.lagradost.cloudstream3.syncproviders.OAuth2API
|
|||
//TODO dropbox sync
|
||||
class Dropbox : OAuth2API {
|
||||
override val idPrefix = "dropbox"
|
||||
override val name = "Dropbox"
|
||||
override var name = "Dropbox"
|
||||
override val key = "zlqsamadlwydvb2"
|
||||
override val redirectUrl = "dropboxlogin"
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@ import java.util.*
|
|||
const val MAL_MAX_SEARCH_LIMIT = 25
|
||||
|
||||
class MALApi(index: Int) : AccountManager(index), SyncAPI {
|
||||
override val name = "MAL"
|
||||
override var name = "MAL"
|
||||
override val key = "1714d6f2f4f7cc19644384f8c4629910"
|
||||
override val redirectUrl = "mallogin"
|
||||
override val idPrefix = "mal"
|
||||
override val mainUrl = "https://myanimelist.net"
|
||||
override var mainUrl = "https://myanimelist.net"
|
||||
override val icon = R.drawable.mal_logo
|
||||
|
||||
override fun logOut() {
|
||||
|
|
|
@ -6,10 +6,10 @@ import com.lagradost.cloudstream3.utils.Qualities
|
|||
import org.jsoup.Jsoup
|
||||
|
||||
class NyaaProvider : MainAPI() {
|
||||
override val name = "Nyaa"
|
||||
override var name = "Nyaa"
|
||||
override val hasChromecastSupport = false
|
||||
|
||||
override val mainUrl = "https://nyaa.si"
|
||||
override var mainUrl = "https://nyaa.si"
|
||||
override val supportedTypes = setOf(TvType.Torrent)
|
||||
override val vpnStatus = VPNStatus.Torrent
|
||||
override val instantLinkLoading = true
|
||||
|
|
|
@ -11,11 +11,11 @@ class APIRepository(val api: MainAPI) {
|
|||
var dubStatusActive = HashSet<DubStatus>()
|
||||
|
||||
val noneApi = object : MainAPI() {
|
||||
override val name = "None"
|
||||
override var name = "None"
|
||||
override val supportedTypes = emptySet<TvType>()
|
||||
}
|
||||
val randomApi = object : MainAPI() {
|
||||
override val name = "Random"
|
||||
override var name = "Random"
|
||||
override val supportedTypes = emptySet<TvType>()
|
||||
}
|
||||
|
||||
|
|
|
@ -339,14 +339,21 @@ abstract class AbstractPlayerFragment(
|
|||
SubtitlesFragment.applyStyleEvent += ::onSubStyleChanged
|
||||
|
||||
try {
|
||||
context?.let {
|
||||
context?.let { ctx ->
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(
|
||||
it
|
||||
ctx
|
||||
)
|
||||
val currentPrefSize =
|
||||
settingsManager.getInt(getString(R.string.video_cache_key), 300)
|
||||
|
||||
player.cacheSize = currentPrefSize * 1024L * 1024L
|
||||
val currentPrefCacheSize =
|
||||
settingsManager.getInt(getString(R.string.video_buffer_size_key), 0)
|
||||
val currentPrefDiskSize =
|
||||
settingsManager.getInt(getString(R.string.video_buffer_disk_key), 0)
|
||||
val currentPrefBufferSec =
|
||||
settingsManager.getInt(getString(R.string.video_buffer_length_key), 0)
|
||||
|
||||
player.cacheSize = currentPrefCacheSize * 1024L * 1024L
|
||||
player.simpleCacheSize = currentPrefDiskSize * 1024L * 1024L
|
||||
player.videoBufferMs = currentPrefBufferSec * 1000L
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
|
|
|
@ -39,8 +39,9 @@ const val TAG = "CS3ExoPlayer"
|
|||
class CS3IPlayer : IPlayer {
|
||||
private var isPlaying = false
|
||||
private var exoPlayer: ExoPlayer? = null
|
||||
var cacheSize = 300L * 1024L * 1024L // 300 mb
|
||||
private val simpleCacheSize : Long get() = cacheSize / 2 // idk chosen at random kinda
|
||||
var cacheSize = 0L
|
||||
var simpleCacheSize = 0L
|
||||
var videoBufferMs = 0L
|
||||
|
||||
private val seekActionTime = 30000L
|
||||
|
||||
|
@ -423,6 +424,7 @@ class CS3IPlayer : IPlayer {
|
|||
playBackSpeed: Float,
|
||||
subtitleOffset: Long,
|
||||
cacheSize: Long,
|
||||
videoBufferMs: Long,
|
||||
playWhenReady: Boolean = true,
|
||||
cacheFactory: CacheDataSource.Factory? = null,
|
||||
trackSelector: TrackSelector? = null,
|
||||
|
@ -460,10 +462,11 @@ class CS3IPlayer : IPlayer {
|
|||
)
|
||||
.setBufferDurationsMs(
|
||||
DefaultLoadControl.DEFAULT_MIN_BUFFER_MS,
|
||||
maxOf(
|
||||
DefaultLoadControl.DEFAULT_MAX_BUFFER_MS,
|
||||
((cacheSize * 75L) / 32768L).toInt()
|
||||
), // 500mb = 20min
|
||||
if(videoBufferMs <= 0) {
|
||||
DefaultLoadControl.DEFAULT_MAX_BUFFER_MS
|
||||
} else {
|
||||
videoBufferMs.toInt()
|
||||
},
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS
|
||||
).build()
|
||||
|
@ -574,6 +577,7 @@ class CS3IPlayer : IPlayer {
|
|||
playbackPosition,
|
||||
playBackSpeed,
|
||||
cacheSize = cacheSize,
|
||||
videoBufferMs = videoBufferMs,
|
||||
playWhenReady = isPlaying, // this keep the current state of the player
|
||||
cacheFactory = cacheFactory,
|
||||
subtitleOffset = currentSubtitleOffset
|
||||
|
|
|
@ -22,7 +22,6 @@ import com.hippo.unifile.UniFile
|
|||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
||||
import com.lagradost.cloudstream3.APIHolder.restrictedApis
|
||||
import com.lagradost.cloudstream3.AcraApplication
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.setLocale
|
||||
|
@ -199,32 +198,111 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
private fun getPref(id: Int): Preference? {
|
||||
return try {
|
||||
findPreference(getString(id))
|
||||
} catch (e : Exception) {
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getFolderSize(dir: File): Long {
|
||||
var size: Long = 0
|
||||
dir.listFiles()?.let {
|
||||
for (file in it) {
|
||||
size += if (file.isFile) {
|
||||
// System.out.println(file.getName() + " " + file.length());
|
||||
file.length()
|
||||
} else getFolderSize(file)
|
||||
}
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
hideKeyboard()
|
||||
setPreferencesFromResource(R.xml.settings, rootKey)
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
|
||||
getPref(R.string.video_cache_key)?.setOnPreferenceClickListener {
|
||||
val prefNames = resources.getStringArray(R.array.video_cache_size_names)
|
||||
val prefValues = resources.getIntArray(R.array.video_cache_size_values)
|
||||
getPref(R.string.video_buffer_length_key)?.setOnPreferenceClickListener {
|
||||
val prefNames = resources.getStringArray(R.array.video_buffer_length_names)
|
||||
val prefValues = resources.getIntArray(R.array.video_buffer_length_values)
|
||||
|
||||
val currentPrefSize =
|
||||
settingsManager.getInt(getString(R.string.video_cache_key), 300)
|
||||
settingsManager.getInt(getString(R.string.video_buffer_length_key), 0)
|
||||
|
||||
activity?.showBottomDialog(
|
||||
activity?.showDialog(
|
||||
prefNames.toList(),
|
||||
prefValues.indexOf(currentPrefSize),
|
||||
getString(R.string.video_cache_settings),
|
||||
getString(R.string.video_buffer_length_settings),
|
||||
true,
|
||||
{}) {
|
||||
settingsManager.edit()
|
||||
.putInt(getString(R.string.video_cache_key), prefValues[it])
|
||||
.putInt(getString(R.string.video_buffer_length_key), prefValues[it])
|
||||
.apply()
|
||||
}
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
getPref(R.string.video_buffer_size_key)?.setOnPreferenceClickListener {
|
||||
val prefNames = resources.getStringArray(R.array.video_buffer_size_names)
|
||||
val prefValues = resources.getIntArray(R.array.video_buffer_size_values)
|
||||
|
||||
val currentPrefSize =
|
||||
settingsManager.getInt(getString(R.string.video_buffer_size_key), 0)
|
||||
|
||||
activity?.showDialog(
|
||||
prefNames.toList(),
|
||||
prefValues.indexOf(currentPrefSize),
|
||||
getString(R.string.video_buffer_size_settings),
|
||||
true,
|
||||
{}) {
|
||||
settingsManager.edit()
|
||||
.putInt(getString(R.string.video_buffer_size_key), prefValues[it])
|
||||
.apply()
|
||||
}
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
getPref(R.string.video_buffer_clear_key)?.let { pref ->
|
||||
val cacheDir = context?.cacheDir ?: return@let
|
||||
|
||||
fun updateSummery() {
|
||||
try {
|
||||
pref.summary =
|
||||
getString(R.string.mb_format).format(getFolderSize(cacheDir) / (1024L * 1024L))
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
|
||||
updateSummery()
|
||||
|
||||
pref.setOnPreferenceClickListener {
|
||||
try {
|
||||
cacheDir.deleteRecursively()
|
||||
updateSummery()
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
}
|
||||
|
||||
getPref(R.string.video_buffer_disk_key)?.setOnPreferenceClickListener {
|
||||
val prefNames = resources.getStringArray(R.array.video_buffer_size_names)
|
||||
val prefValues = resources.getIntArray(R.array.video_buffer_size_values)
|
||||
|
||||
val currentPrefSize =
|
||||
settingsManager.getInt(getString(R.string.video_buffer_disk_key), 0)
|
||||
|
||||
activity?.showDialog(
|
||||
prefNames.toList(),
|
||||
prefValues.indexOf(currentPrefSize),
|
||||
getString(R.string.video_buffer_disk_settings),
|
||||
true,
|
||||
{}) {
|
||||
settingsManager.edit()
|
||||
.putInt(getString(R.string.video_buffer_disk_key), prefValues[it])
|
||||
.apply()
|
||||
}
|
||||
return@setOnPreferenceClickListener true
|
||||
|
@ -301,9 +379,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
for (api in apis) {
|
||||
allLangs.add(api.lang)
|
||||
}
|
||||
for (api in restrictedApis) {
|
||||
allLangs.add(api.lang)
|
||||
}
|
||||
|
||||
val currentList = ArrayList<Int>()
|
||||
for (i in current) {
|
||||
|
|
|
@ -323,18 +323,25 @@ class SubtitlesFragment : Fragment() {
|
|||
val fontSizes = listOf(
|
||||
Pair(null, textView.context.getString(R.string.normal)),
|
||||
Pair(6f, "6$suffix"),
|
||||
Pair(7f, "7$suffix"),
|
||||
Pair(8f, "8$suffix"),
|
||||
Pair(9f, "9$suffix"),
|
||||
Pair(10f, "10$suffix"),
|
||||
Pair(11f, "11$suffix"),
|
||||
Pair(12f, "12$suffix"),
|
||||
Pair(13f, "13$suffix"),
|
||||
Pair(14f, "14$suffix"),
|
||||
Pair(15f, "15$suffix"),
|
||||
Pair(16f, "16$suffix"),
|
||||
Pair(17f, "17$suffix"),
|
||||
Pair(18f, "18$suffix"),
|
||||
Pair(19f, "19$suffix"),
|
||||
Pair(20f, "20$suffix"),
|
||||
Pair(21f, "21$suffix"),
|
||||
Pair(22f, "22$suffix"),
|
||||
Pair(23f, "23$suffix"),
|
||||
Pair(24f, "24$suffix"),
|
||||
Pair(25f, "25$suffix"),
|
||||
Pair(26f, "26$suffix"),
|
||||
Pair(28f, "28$suffix"),
|
||||
Pair(30f, "30$suffix"),
|
||||
|
|
|
@ -112,6 +112,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
|
|||
StreamSB7(),
|
||||
StreamSB8(),
|
||||
StreamSB9(),
|
||||
StreamSB10(),
|
||||
// Streamhub(), cause Streamhub2() works
|
||||
Streamhub2(),
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@
|
|||
<string name="dont_show_again">لا تظهر مرة أخرى</string>
|
||||
<string name="update">تحديث</string>
|
||||
<string name="watch_quality_pref">جودة المشاهدة المفضلة</string>
|
||||
<string name="video_cache_settings">حجم ذاكرة التخزين المؤقت للفيديو</string>
|
||||
<string name="video_buffer_size_settings">حجم ذاكرة التخزين المؤقت للفيديو</string>
|
||||
<string name="dns_pref">DNS فوق HTTPS</string>
|
||||
<string name="dns_pref_summary">مفيد لتجاوز كتل مزود خدمة الإنترنت</string>
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
\n%s -> %s</string>
|
||||
<string name="filler" formatted="true">Épisode spécial</string>
|
||||
<string name="watch_quality_pref">Qualité de visionnage préférée</string>
|
||||
<string name="video_cache_settings">Taille de la mémoire cache</string>
|
||||
<string name="video_buffer_size_settings">Taille de la mémoire cache</string>
|
||||
<string name="resize_fill">Étendre</string>
|
||||
<string name="legal_notice">Non-responsabilité</string>
|
||||
<string name="primary_color_settings">Couleur principale</string>
|
||||
|
|
|
@ -269,7 +269,7 @@
|
|||
<string name="dont_show_again">Non mostrare di nuovo</string>
|
||||
<string name="update">Aggiorna</string>
|
||||
<string name="watch_quality_pref">Risoluzione preferita</string>
|
||||
<string name="video_cache_settings">Dimensione cache video</string>
|
||||
<string name="video_buffer_size_settings">Dimensione cache video</string>
|
||||
<string name="dns_pref">DNS over HTTPS</string>
|
||||
<string name="dns_pref_summary">Utile per bypassare i blocchi ISP</string>
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@
|
|||
<string name="dont_show_again">Không hiển thị lại</string>
|
||||
<string name="update">Cập nhật</string>
|
||||
<string name="watch_quality_pref">Tự động chọn chất lượng phim</string>
|
||||
<string name="video_cache_settings">Kích thước video cache</string>
|
||||
<string name="video_buffer_size_settings">Kích thước video cache</string>
|
||||
<string name="dns_pref_summary">Rất hữu ích để bỏ chặn ISP</string>
|
||||
|
||||
<string name="download_path_pref">Đường dẫn tải xuống</string>
|
||||
|
|
|
@ -56,20 +56,88 @@
|
|||
<item>1</item>
|
||||
<item>2</item>
|
||||
</array>
|
||||
<array name="video_cache_size_names">
|
||||
<item>@string/none</item>
|
||||
|
||||
<array name="video_buffer_length_names">
|
||||
<item>@string/automatic</item>
|
||||
<item>1min</item>
|
||||
<item>1min 30s</item>
|
||||
<item>2min</item>
|
||||
<item>2min 30s</item>
|
||||
<item>3min</item>
|
||||
<item>3min 30s</item>
|
||||
<item>4min</item>
|
||||
<item>5min</item>
|
||||
<item>6min</item>
|
||||
<item>7min</item>
|
||||
<item>8min</item>
|
||||
<item>9min</item>
|
||||
<item>10min</item>
|
||||
<item>15min</item>
|
||||
<item>20min</item>
|
||||
<item>30min</item>
|
||||
</array>
|
||||
|
||||
<array name="video_buffer_length_values">
|
||||
<item>0</item>
|
||||
<item>60</item>
|
||||
<item>90</item>
|
||||
<item>120</item>
|
||||
<item>150</item>
|
||||
<item>180</item>
|
||||
<item>210</item>
|
||||
<item>240</item>
|
||||
<item>300</item>
|
||||
<item>360</item>
|
||||
<item>420</item>
|
||||
<item>480</item>
|
||||
<item>540</item>
|
||||
<item>600</item>
|
||||
<item>900</item>
|
||||
<item>1200</item>
|
||||
<item>1800</item>
|
||||
</array>
|
||||
|
||||
<array name="video_buffer_size_names">
|
||||
<item>@string/automatic</item>
|
||||
<item>10MB</item>
|
||||
<item>20MB</item>
|
||||
<item>30MB</item>
|
||||
<item>40MB</item>
|
||||
<item>50MB</item>
|
||||
<item>60MB</item>
|
||||
<item>70MB</item>
|
||||
<item>80MB</item>
|
||||
<item>90MB</item>
|
||||
<item>100MB</item>
|
||||
<item>150MB</item>
|
||||
<item>200MB</item>
|
||||
<item>250MB</item>
|
||||
<item>300MB</item>
|
||||
<item>350MB</item>
|
||||
<item>400MB</item>
|
||||
<item>450MB</item>
|
||||
<item>500MB</item>
|
||||
</array>
|
||||
<array name="video_cache_size_values">
|
||||
|
||||
<array name="video_buffer_size_values">
|
||||
<item>0</item>
|
||||
<item>10</item>
|
||||
<item>20</item>
|
||||
<item>30</item>
|
||||
<item>40</item>
|
||||
<item>50</item>
|
||||
<item>60</item>
|
||||
<item>70</item>
|
||||
<item>80</item>
|
||||
<item>90</item>
|
||||
<item>100</item>
|
||||
<item>150</item>
|
||||
<item>200</item>
|
||||
<item>250</item>
|
||||
<item>300</item>
|
||||
<item>350</item>
|
||||
<item>400</item>
|
||||
<item>450</item>
|
||||
<item>500</item>
|
||||
</array>
|
||||
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
<string name="subtitle_settings_key" translatable="false">subtitle_settings_key</string>
|
||||
<string name="subtitle_settings_chromecast_key" translatable="false">subtitle_settings_chromecast_key</string>
|
||||
<string name="quality_pref_key" translatable="false">quality_pref_key</string>
|
||||
<string name="video_cache_key" translatable="false">video_cache_key</string>
|
||||
<string name="video_buffer_size_key" translatable="false">video_buffer_size_key</string>
|
||||
<string name="video_buffer_length_key" translatable="false">video_buffer_length_key</string>
|
||||
<string name="video_buffer_clear_key" translatable="false">video_buffer_clear_key</string>
|
||||
<string name="video_buffer_disk_key" translatable="false">video_buffer_disk_key</string>
|
||||
<string name="prerelease_commit_hash" translatable="false">unknown_prerelease</string>
|
||||
<string name="use_system_brightness_key" translatable="false">use_system_brightness_key</string>
|
||||
<string name="swipe_enabled_key" translatable="false">swipe_enabled_key</string>
|
||||
|
@ -32,6 +35,7 @@
|
|||
<string name="app_layout_key" translatable="false">app_layout_key</string>
|
||||
<string name="primary_color_key" translatable="false">primary_color_key</string>
|
||||
<string name="restore_key" translatable="false">restore_key</string>
|
||||
<string name="killswitch_key" translatable="false">killswitch_key</string>
|
||||
<string name="backup_key" translatable="false">backup_key</string>
|
||||
<string name="prefer_media_type_key" translatable="false">prefer_media_type_key</string>
|
||||
<string name="app_theme_key" translatable="false">app_theme_key</string>
|
||||
|
@ -41,6 +45,7 @@
|
|||
<string name="extra_info_format" translatable="false" formatted="true">%d %s | %sMB</string>
|
||||
<string name="storage_size_format" translatable="false" formatted="true">%s • %sGB</string>
|
||||
<string name="download_size_format" translatable="false" formatted="true">%sMB / %sMB</string>
|
||||
<string name="mb_format" translatable="false" formatted="true">%dMB</string>
|
||||
<string name="episode_name_format" translatable="false" formatted="true">%s %s</string>
|
||||
<string name="ffw_text_format" translatable="false" formatted="true">+%d</string>
|
||||
<string name="rew_text_format" translatable="false" formatted="true">-%d</string>
|
||||
|
@ -198,6 +203,9 @@
|
|||
</string>
|
||||
|
||||
<string name="restore_settings">Restore data from backup</string>
|
||||
<string name="killswitch_settings">Download latest metadata from github</string>
|
||||
<string name="killswitch_settings_des">If you want access to all providers (even broken ones) turn this off</string>
|
||||
|
||||
<string name="backup_settings">Backup data</string>
|
||||
<string name="restore_success">Loaded backup file</string>
|
||||
<string name="restore_failed_format" formatted="true">Failed to restore data from file %s</string>
|
||||
|
@ -315,7 +323,14 @@
|
|||
<string name="dont_show_again">Don\'t show again</string>
|
||||
<string name="update">Update</string>
|
||||
<string name="watch_quality_pref">Preferred watch quality</string>
|
||||
<string name="video_cache_settings">Video cache size</string>
|
||||
<string name="video_buffer_size_settings">Video buffer size</string>
|
||||
<string name="video_buffer_length_settings">Video buffer length</string>
|
||||
<string name="video_buffer_disk_settings">Video cache on disk</string>
|
||||
<string name="video_buffer_clear_settings">Clear video and image cache</string>
|
||||
|
||||
<string name="video_ram_description">May cause problems on systems with low ram such as Android TV devices or old phones if you set it too high</string>
|
||||
<string name="video_disk_description">May cause problems on systems with low storage space such as Android TV devices if you set it too high</string>
|
||||
|
||||
<string name="dns_pref">DNS over HTTPS</string>
|
||||
<string name="dns_pref_summary">Useful for bypassing ISP blocks</string>
|
||||
|
||||
|
|
|
@ -20,10 +20,7 @@
|
|||
android:key="@string/quality_pref_key"
|
||||
android:title="@string/watch_quality_pref"
|
||||
android:icon="@drawable/ic_baseline_hd_24" />
|
||||
<Preference
|
||||
android:key="@string/video_cache_key"
|
||||
android:title="@string/video_cache_settings"
|
||||
android:icon="@drawable/ic_baseline_storage_24" />
|
||||
|
||||
<SwitchPreference
|
||||
android:icon="@drawable/ic_baseline_picture_in_picture_alt_24"
|
||||
app:key="@string/pip_enabled_key"
|
||||
|
@ -66,6 +63,28 @@
|
|||
android:title="@string/double_tap_to_pause_settings"
|
||||
android:summary="@string/double_tap_to_pause_settings_des"
|
||||
app:defaultValue="false" />
|
||||
<Preference
|
||||
android:key="@string/video_buffer_disk_key"
|
||||
android:title="@string/video_buffer_disk_settings"
|
||||
android:summary="@string/video_disk_description"
|
||||
android:icon="@drawable/ic_baseline_storage_24" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/video_buffer_size_key"
|
||||
android:title="@string/video_buffer_size_settings"
|
||||
android:summary="@string/video_ram_description"
|
||||
android:icon="@drawable/ic_baseline_storage_24" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/video_buffer_length_key"
|
||||
android:title="@string/video_buffer_length_settings"
|
||||
android:summary="@string/video_ram_description"
|
||||
android:icon="@drawable/ic_baseline_storage_24" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/video_buffer_clear_key"
|
||||
android:title="@string/video_buffer_clear_settings"
|
||||
android:icon="@drawable/ic_baseline_delete_outline_24" />
|
||||
<!--
|
||||
<SwitchPreference
|
||||
android:icon="@drawable/ic_baseline_brightness_7_24"
|
||||
|
@ -179,6 +198,13 @@
|
|||
android:key="@string/restore_key"
|
||||
android:title="@string/restore_settings" />
|
||||
|
||||
<SwitchPreference
|
||||
android:icon="@drawable/netflix_download"
|
||||
android:key="@string/killswitch_key"
|
||||
android:defaultValue="true"
|
||||
android:summary="@string/killswitch_settings_des"
|
||||
android:title="@string/killswitch_settings" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/mal_key"
|
||||
android:icon="@drawable/mal_logo" />
|
||||
|
|
282
providers.json
Normal file
282
providers.json
Normal file
|
@ -0,0 +1,282 @@
|
|||
{
|
||||
"AkwamProvider": {
|
||||
"name": "Akwam",
|
||||
"url": "https://akwam.to",
|
||||
"status": 1
|
||||
},
|
||||
"AllAnimeProvider": {
|
||||
"name": "AllAnime",
|
||||
"url": "https://allanime.site",
|
||||
"status": 1
|
||||
},
|
||||
"AllMoviesForYouProvider": {
|
||||
"name": "AllMoviesForYou",
|
||||
"url": "https://allmoviesforyou.net",
|
||||
"status": 1
|
||||
},
|
||||
"AnimeFlickProvider": {
|
||||
"name": "AnimeFlick",
|
||||
"url": "https://animeflick.net",
|
||||
"status": 1
|
||||
},
|
||||
"AnimePaheProvider": {
|
||||
"name": "AnimePahe",
|
||||
"url": "https://animepahe.com",
|
||||
"status": 1
|
||||
},
|
||||
"AnimeWorldProvider": {
|
||||
"name": "AnimeWorld",
|
||||
"url": "https://www.animeworld.tv",
|
||||
"status": 1
|
||||
},
|
||||
"AnimeflvnetProvider": {
|
||||
"name": "Animeflv.net",
|
||||
"url": "https://www3.animeflv.net",
|
||||
"status": 1
|
||||
},
|
||||
"AnimekisaProvider": {
|
||||
"name": "Animekisa",
|
||||
"url": "https://animekisa.in",
|
||||
"status": 1
|
||||
},
|
||||
"AsianLoadProvider": {
|
||||
"name": "AsianLoad",
|
||||
"url": "https://asianembed.io",
|
||||
"status": 1
|
||||
},
|
||||
"AsiaFlixProvider": {
|
||||
"name": "AsiaFlix",
|
||||
"url": "https://asiaflix.app",
|
||||
"status": 3
|
||||
},
|
||||
"BflixProvider": {
|
||||
"name": "Bflix",
|
||||
"url": "https://bflix.ru",
|
||||
"status": 1
|
||||
},
|
||||
"FmoviesToProvider": {
|
||||
"name": "Fmovies.to",
|
||||
"url": "https://fmovies.to",
|
||||
"status": 1
|
||||
},
|
||||
"SflixProProvider": {
|
||||
"name": "Sflix.pro",
|
||||
"url": "https://sflix.pro",
|
||||
"status": 1
|
||||
},
|
||||
"CinecalidadProvider": {
|
||||
"name": "Cinecalidad",
|
||||
"url": "https://cinecalidad.lol",
|
||||
"status": 1
|
||||
},
|
||||
"CrossTmdbProvider": {
|
||||
"name": "MultiMovie",
|
||||
"url": "NONE",
|
||||
"status": 1
|
||||
},
|
||||
"CuevanaProvider": {
|
||||
"name": "Cuevana",
|
||||
"url": "https://cuevana3.me",
|
||||
"status": 1
|
||||
},
|
||||
"DoramasYTProvider": {
|
||||
"name": "DoramasYT",
|
||||
"url": "https://doramasyt.com",
|
||||
"status": 1
|
||||
},
|
||||
"DramaSeeProvider": {
|
||||
"name": "DramaSee",
|
||||
"url": "https://dramasee.net",
|
||||
"status": 1
|
||||
},
|
||||
"DubbedAnimeProvider": {
|
||||
"name": "DubbedAnime",
|
||||
"url": "https://bestdubbedanime.com",
|
||||
"status": 1
|
||||
},
|
||||
"EgyBestProvider": {
|
||||
"name": "EgyBest",
|
||||
"url": "https://egy.best",
|
||||
"status": 1
|
||||
},
|
||||
"EntrepeliculasyseriesProvider": {
|
||||
"name": "EntrePeliculasySeries",
|
||||
"url": "https://entrepeliculasyseries.nu",
|
||||
"status": 1
|
||||
},
|
||||
"FilmanProvider": {
|
||||
"name": "filman.cc",
|
||||
"url": "https://filman.cc",
|
||||
"status": 1
|
||||
},
|
||||
"FrenchStreamProvider": {
|
||||
"name": "French Stream",
|
||||
"url": "https://french-stream.re",
|
||||
"status": 1
|
||||
},
|
||||
"GogoanimeProvider": {
|
||||
"name": "GogoAnime",
|
||||
"url": "https://gogoanime.film",
|
||||
"status": 1
|
||||
},
|
||||
"KawaiifuProvider": {
|
||||
"name": "Kawaiifu",
|
||||
"url": "https://kawaiifu.com",
|
||||
"status": 0
|
||||
},
|
||||
"HDMProvider": {
|
||||
"name": "HD Movies",
|
||||
"url": "https://hdm.to",
|
||||
"status": 0
|
||||
},
|
||||
"IHaveNoTvProvider": {
|
||||
"name": "I Have No TV",
|
||||
"url": "https://ihavenotv.com",
|
||||
"status": 1
|
||||
},
|
||||
"KdramaHoodProvider": {
|
||||
"name": "KDramaHood",
|
||||
"url": "https://kdramahood.com",
|
||||
"status": 1
|
||||
},
|
||||
"LookMovieProvider": {
|
||||
"name": "LookMovie",
|
||||
"url": "https://lookmovie.io",
|
||||
"status": 0
|
||||
},
|
||||
"MeloMovieProvider": {
|
||||
"name": "MeloMovie",
|
||||
"url": "https://melomovie.com",
|
||||
"status": 0
|
||||
},
|
||||
"MonoschinosProvider": {
|
||||
"name": "Monoschinos",
|
||||
"url": "https://monoschinos2.com",
|
||||
"status": 1
|
||||
},
|
||||
"MyCimaProvider": {
|
||||
"name": "MyCima",
|
||||
"url": "https://mycima.tv",
|
||||
"status": 1
|
||||
},
|
||||
"NineAnimeProvider": {
|
||||
"name": "9Anime",
|
||||
"url": "https://9anime.center",
|
||||
"status": 1
|
||||
},
|
||||
"PeliSmartProvider": {
|
||||
"name": "PeliSmart",
|
||||
"url": "https://pelismart.com",
|
||||
"status": 1
|
||||
},
|
||||
"PelisflixProvider": {
|
||||
"name": "Pelisflix",
|
||||
"url": "https://pelisflix.li",
|
||||
"status": 1
|
||||
},
|
||||
"PelisplusHDProvider": {
|
||||
"name": "PelisplusHD",
|
||||
"url": "https://pelisplushd.net",
|
||||
"status": 1
|
||||
},
|
||||
"PelisplusProvider": {
|
||||
"name": "Pelisplus",
|
||||
"url": "https://pelisplus.icu",
|
||||
"status": 1
|
||||
},
|
||||
"PinoyHDXyzProvider": {
|
||||
"name": "Pinoy-HD",
|
||||
"url": "https://www.pinoy-hd.xyz",
|
||||
"status": 1
|
||||
},
|
||||
"PinoyMoviePediaProvider": {
|
||||
"name": "Pinoy Moviepedia",
|
||||
"url": "https://pinoymoviepedia.ru",
|
||||
"status": 1
|
||||
},
|
||||
"PinoyMoviesEsProvider": {
|
||||
"name": "Pinoy Movies",
|
||||
"url": "https://pinoymovies.es",
|
||||
"status": 1
|
||||
},
|
||||
"SflixProvider": {
|
||||
"name": "Sflix.to",
|
||||
"url": "https://sflix.to",
|
||||
"status": 1
|
||||
},
|
||||
"DopeboxProvider": {
|
||||
"name": "Dopebox",
|
||||
"url": "https://dopebox.to",
|
||||
"status": 1
|
||||
},
|
||||
"SolarmovieProvider": {
|
||||
"name": "Solarmovie",
|
||||
"url": "https://solarmovie.pe",
|
||||
"status": 1
|
||||
},
|
||||
"SeriesflixProvider": {
|
||||
"name": "Seriesflix",
|
||||
"url": "https://seriesflix.video",
|
||||
"status": 1
|
||||
},
|
||||
"SoaptwoDayProvider": {
|
||||
"name": "Soap2Day",
|
||||
"url": "https://secretlink.xyz",
|
||||
"status": 1
|
||||
},
|
||||
"TenshiProvider": {
|
||||
"name": "Tenshi.moe",
|
||||
"url": "https://tenshi.moe",
|
||||
"status": 1
|
||||
},
|
||||
"TrailersTwoProvider": {
|
||||
"name": "Trailers.to",
|
||||
"url": "https://trailers.to",
|
||||
"status": 1
|
||||
},
|
||||
"TwoEmbedProvider": {
|
||||
"name": "2Embed",
|
||||
"url": "https://www.2embed.ru",
|
||||
"status": 1
|
||||
},
|
||||
"VMoveeProvider": {
|
||||
"name": "VMovee",
|
||||
"url": "https://www.vmovee.watch",
|
||||
"status": 1
|
||||
},
|
||||
"VfFilmProvider": {
|
||||
"name": "vf-film.me",
|
||||
"url": "https://vf-film.me",
|
||||
"status": 1
|
||||
},
|
||||
"VfSerieProvider": {
|
||||
"name": "vf-serie.org",
|
||||
"url": "https://vf-serie.org",
|
||||
"status": 1
|
||||
},
|
||||
"VidEmbedProvider": {
|
||||
"name": "VidEmbed",
|
||||
"url": "https://vidembed.cc",
|
||||
"status": 1
|
||||
},
|
||||
"WatchAsianProvider": {
|
||||
"name": "WatchAsian",
|
||||
"url": "https://watchasian.sh",
|
||||
"status": 1
|
||||
},
|
||||
"WatchCartoonOnlineProvider": {
|
||||
"name": "WatchCartoonOnline",
|
||||
"url": "https://www.wcostream.com",
|
||||
"status": 1
|
||||
},
|
||||
"WcoProvider": {
|
||||
"name": "WCO Stream",
|
||||
"url": "https://wcostream.cc",
|
||||
"status": 1
|
||||
},
|
||||
"ZoroProvider": {
|
||||
"name": "Zoro",
|
||||
"url": "https://zoro.to",
|
||||
"status": 1
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue