forked from recloudstream/cloudstream
		
	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 | # Globals | ||||||
| URL_REGEX = compile( | 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\{") | NAME_REGEX = compile("class (.+?) ?: \w+\(\)\s\{") | ||||||
| START_MARKER = "<!--SITE LIST START-->" | START_MARKER = "<!--SITE LIST START-->" | ||||||
| END_MARKER = "<!--SITE LIST END-->" | END_MARKER = "<!--SITE LIST END-->" | ||||||
| GLOB = "app/src/main/java/com/lagradost/cloudstream3/*providers/*Provider.kt" | GLOB = "app/src/main/java/com/lagradost/cloudstream3/*providers/*Provider.kt" | ||||||
| MAIN_API = "app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt" | MAIN_API = "app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt" | ||||||
| API_REGEX = compile( | 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] = {} | sites: Dict[str, str] = {} | ||||||
| enabled_sites: List[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)  | - [9anime.center](https://9anime.center)  | ||||||
| - [animeworld.tv](https://www.animeworld.tv)  | - [animeworld.tv](https://www.animeworld.tv)  | ||||||
| - [asiaflix.app](https://asiaflix.app)  | - [asiaflix.app](https://asiaflix.app)  | ||||||
|  | - [kawaiifu.com](https://kawaiifu.com)  | ||||||
|  | - [hdm.to](https://hdm.to)  | ||||||
| <!--SITE LIST END--> | <!--SITE LIST END--> | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ import android.net.Uri | ||||||
| import android.util.Base64.encodeToString | import android.util.Base64.encodeToString | ||||||
| import androidx.annotation.WorkerThread | import androidx.annotation.WorkerThread | ||||||
| import androidx.preference.PreferenceManager | import androidx.preference.PreferenceManager | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.fasterxml.jackson.databind.DeserializationFeature | import com.fasterxml.jackson.databind.DeserializationFeature | ||||||
| import com.fasterxml.jackson.databind.json.JsonMapper | import com.fasterxml.jackson.databind.json.JsonMapper | ||||||
| import com.fasterxml.jackson.module.kotlin.KotlinModule | import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||||
|  | @ -31,21 +32,13 @@ object APIHolder { | ||||||
| 
 | 
 | ||||||
|     private const val defProvider = 0 |     private const val defProvider = 0 | ||||||
| 
 | 
 | ||||||
|     val apis = arrayListOf( |     val allProviders by lazy { | ||||||
|  |         arrayListOf( | ||||||
|  |             // Movie providers | ||||||
|             PelisplusProvider(), |             PelisplusProvider(), | ||||||
|             PelisplusHDProvider(), |             PelisplusHDProvider(), | ||||||
|             PeliSmartProvider(), |             PeliSmartProvider(), | ||||||
|         GogoanimeProvider(), |             MeloMovieProvider(), // Captcha for links | ||||||
|         AllAnimeProvider(), |  | ||||||
|         AnimekisaProvider(), |  | ||||||
|         //ShiroProvider(), // v2 fucked me |  | ||||||
|         AnimeFlickProvider(), |  | ||||||
|         AnimeflvnetProvider(), |  | ||||||
| 
 |  | ||||||
|         TenshiProvider(), |  | ||||||
|         WcoProvider(), |  | ||||||
|         // MeloMovieProvider(), // Captcha for links |  | ||||||
|         DubbedAnimeProvider(), |  | ||||||
|             DoramasYTProvider(), |             DoramasYTProvider(), | ||||||
|             CinecalidadProvider(), |             CinecalidadProvider(), | ||||||
|             CuevanaProvider(), |             CuevanaProvider(), | ||||||
|  | @ -53,34 +46,22 @@ object APIHolder { | ||||||
|             PelisflixProvider(), |             PelisflixProvider(), | ||||||
|             SeriesflixProvider(), |             SeriesflixProvider(), | ||||||
|             IHaveNoTvProvider(), // Documentaries provider |             IHaveNoTvProvider(), // Documentaries provider | ||||||
|         //LookMovieProvider(), // RECAPTCHA (Please allow up to 5 seconds...) |             LookMovieProvider(), // RECAPTCHA (Please allow up to 5 seconds...) | ||||||
|             VMoveeProvider(), |             VMoveeProvider(), | ||||||
|         WatchCartoonOnlineProvider(), |  | ||||||
|             AllMoviesForYouProvider(), |             AllMoviesForYouProvider(), | ||||||
|         ApiMDBProvider(), |  | ||||||
| 
 |  | ||||||
|         MonoschinosProvider(), |  | ||||||
| 
 |  | ||||||
|             VidEmbedProvider(), |             VidEmbedProvider(), | ||||||
|             VfFilmProvider(), |             VfFilmProvider(), | ||||||
|             VfSerieProvider(), |             VfSerieProvider(), | ||||||
|             FrenchStreamProvider(), |             FrenchStreamProvider(), | ||||||
| 
 |  | ||||||
|             AsianLoadProvider(), |             AsianLoadProvider(), | ||||||
| 
 |             AsiaFlixProvider(), // restricted | ||||||
|         BflixProvider("https://bflix.ru","Bflix"), |             BflixProvider(), | ||||||
|         BflixProvider("https://fmovies.to","Fmovies.to"), |             FmoviesToProvider(), | ||||||
|         BflixProvider("https://sflix.pro","Sflix.pro"), |             SflixProProvider(), | ||||||
| 
 |  | ||||||
|         SflixProvider("https://sflix.to", "Sflix.to"), |  | ||||||
|         SflixProvider("https://dopebox.to", "Dopebox"), |  | ||||||
|         SflixProvider("https://solarmovie.pe", "Solarmovie"), |  | ||||||
| 
 |  | ||||||
|         //TmdbProvider(), |  | ||||||
| 
 |  | ||||||
|             FilmanProvider(), |             FilmanProvider(), | ||||||
| 
 |             SflixProvider(), | ||||||
|         ZoroProvider(), |             DopeboxProvider(), | ||||||
|  |             SolarmovieProvider(), | ||||||
|             PinoyMoviePediaProvider(), |             PinoyMoviePediaProvider(), | ||||||
|             PinoyHDXyzProvider(), |             PinoyHDXyzProvider(), | ||||||
|             PinoyMoviesEsProvider(), |             PinoyMoviesEsProvider(), | ||||||
|  | @ -92,25 +73,35 @@ object APIHolder { | ||||||
|             AkwamProvider(), |             AkwamProvider(), | ||||||
|             MyCimaProvider(), |             MyCimaProvider(), | ||||||
|             EgyBestProvider(), |             EgyBestProvider(), | ||||||
|  |             SoaptwoDayProvider(), | ||||||
|  |             HDMProvider(),// disabled due to cloudflare | ||||||
|  | 
 | ||||||
|  |             // Metadata providers | ||||||
|  |             //TmdbProvider(), | ||||||
|  |             CrossTmdbProvider(), | ||||||
|  |             ApiMDBProvider(), | ||||||
|  | 
 | ||||||
|  |             // Anime providers | ||||||
|  |             WatchCartoonOnlineProvider(), | ||||||
|  |             GogoanimeProvider(), | ||||||
|  |             AllAnimeProvider(), | ||||||
|  |             AnimekisaProvider(), | ||||||
|  |             //ShiroProvider(), // v2 fucked me | ||||||
|  |             AnimeFlickProvider(), | ||||||
|  |             AnimeflvnetProvider(), | ||||||
|  |             TenshiProvider(), | ||||||
|  |             WcoProvider(), | ||||||
|             AnimePaheProvider(), |             AnimePaheProvider(), | ||||||
|             NineAnimeProvider(), |             NineAnimeProvider(), | ||||||
|             AnimeWorldProvider(), |             AnimeWorldProvider(), | ||||||
|         SoaptwoDayProvider(), |             ZoroProvider(), | ||||||
| 
 |             DubbedAnimeProvider(), | ||||||
|         CrossTmdbProvider(), |             MonoschinosProvider(), | ||||||
|  |             KawaiifuProvider(), // disabled due to cloudflare | ||||||
|         ) |         ) | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     val restrictedApis = arrayListOf( |     var apis : List<MainAPI> = 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 |  | ||||||
|     ) |  | ||||||
| 
 | 
 | ||||||
|     fun getApiFromName(apiName: String?): MainAPI { |     fun getApiFromName(apiName: String?): MainAPI { | ||||||
|         return getApiFromNameNull(apiName) ?: apis[defProvider] |         return getApiFromNameNull(apiName) ?: apis[defProvider] | ||||||
|  | @ -118,15 +109,7 @@ object APIHolder { | ||||||
| 
 | 
 | ||||||
|     fun getApiFromNameNull(apiName: String?): MainAPI? { |     fun getApiFromNameNull(apiName: String?): MainAPI? { | ||||||
|         if (apiName == null) return null |         if (apiName == null) return null | ||||||
|         for (api in apis) { |         for (api in allProviders) { | ||||||
|             if (apiName == api.name) |  | ||||||
|                 return api |  | ||||||
|         } |  | ||||||
|         for (api in restrictedApis) { |  | ||||||
|             if (apiName == api.name) |  | ||||||
|                 return api |  | ||||||
|         } |  | ||||||
|         for (api in backwardsCompatibleProviders) { |  | ||||||
|             if (apiName == api.name) |             if (apiName == api.name) | ||||||
|                 return api |                 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*/ | /**Every provider will **not** have try catch built in, so handle exceptions when calling these functions*/ | ||||||
| abstract class MainAPI { | abstract class MainAPI { | ||||||
|     open val name = "NONE" |     companion object { | ||||||
|     open val mainUrl = "NONE" |         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 |     //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 |     open val providerType = ProviderType.DirectProvider | ||||||
| 
 | 
 | ||||||
|     @WorkerThread |     @WorkerThread | ||||||
|     suspend open fun getMainPage(): HomePageResponse? { |     open suspend fun getMainPage(): HomePageResponse? { | ||||||
|         throw NotImplementedError() |         throw NotImplementedError() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @WorkerThread |     @WorkerThread | ||||||
|     suspend open fun search(query: String): List<SearchResponse>? { |     open suspend fun search(query: String): List<SearchResponse>? { | ||||||
|         throw NotImplementedError() |         throw NotImplementedError() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @WorkerThread |     @WorkerThread | ||||||
|     suspend open fun quickSearch(query: String): List<SearchResponse>? { |     open suspend fun quickSearch(query: String): List<SearchResponse>? { | ||||||
|         throw NotImplementedError() |         throw NotImplementedError() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -336,7 +354,7 @@ abstract class MainAPI { | ||||||
|      * Based on data from search() or getMainPage() it generates a LoadResponse, |      * Based on data from search() or getMainPage() it generates a LoadResponse, | ||||||
|      * basically opening the info page from a link. |      * basically opening the info page from a link. | ||||||
|      * */ |      * */ | ||||||
|     suspend open fun load(url: String): LoadResponse? { |     open suspend fun load(url: String): LoadResponse? { | ||||||
|         throw NotImplementedError() |         throw NotImplementedError() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -350,13 +368,13 @@ abstract class MainAPI { | ||||||
|      * if the need arises. |      * if the need arises. | ||||||
|      * */ |      * */ | ||||||
|     @WorkerThread |     @WorkerThread | ||||||
|     suspend open fun extractorVerifierJob(extractorData: String?) { |     open suspend fun extractorVerifierJob(extractorData: String?) { | ||||||
|         throw NotImplementedError() |         throw NotImplementedError() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /**Callback is fired once a link is found, will return true if method is executed successfully*/ |     /**Callback is fired once a link is found, will return true if method is executed successfully*/ | ||||||
|     @WorkerThread |     @WorkerThread | ||||||
|     suspend open fun loadLinks( |     open suspend fun loadLinks( | ||||||
|         data: String, |         data: String, | ||||||
|         isCasting: Boolean, |         isCasting: Boolean, | ||||||
|         subtitleCallback: (SubtitleFile) -> Unit, |         subtitleCallback: (SubtitleFile) -> Unit, | ||||||
|  |  | ||||||
|  | @ -23,9 +23,9 @@ import androidx.preference.PreferenceManager | ||||||
| import com.google.android.gms.cast.framework.* | import com.google.android.gms.cast.framework.* | ||||||
| import com.google.android.material.navigationrail.NavigationRailView | import com.google.android.material.navigationrail.NavigationRailView | ||||||
| import com.jaredrummler.android.colorpicker.ColorPickerDialogListener | import com.jaredrummler.android.colorpicker.ColorPickerDialogListener | ||||||
|  | import com.lagradost.cloudstream3.APIHolder.allProviders | ||||||
| import com.lagradost.cloudstream3.APIHolder.apis | import com.lagradost.cloudstream3.APIHolder.apis | ||||||
| import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings | import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings | ||||||
| import com.lagradost.cloudstream3.APIHolder.restrictedApis |  | ||||||
| import com.lagradost.cloudstream3.CommonActivity.backEvent | import com.lagradost.cloudstream3.CommonActivity.backEvent | ||||||
| import com.lagradost.cloudstream3.CommonActivity.loadThemes | import com.lagradost.cloudstream3.CommonActivity.loadThemes | ||||||
| import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent | 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.isCastApiAvailable | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.loadCache | import com.lagradost.cloudstream3.utils.AppUtils.loadCache | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.loadResult | 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.BackupUtils.setUpBackup | ||||||
|  | import com.lagradost.cloudstream3.utils.Coroutines.main | ||||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||||
| import com.lagradost.cloudstream3.utils.DataStore.removeKey | 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.DataStoreHelper.setViewPos | ||||||
| import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate | import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState | 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 com.lagradost.cloudstream3.utils.UIHelper.requestRW | ||||||
| import kotlinx.android.synthetic.main.activity_main.* | import kotlinx.android.synthetic.main.activity_main.* | ||||||
| import kotlinx.android.synthetic.main.fragment_result_swipe.* | 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 java.io.File | ||||||
| import kotlin.concurrent.thread | import kotlin.concurrent.thread | ||||||
| 
 | 
 | ||||||
|  | @ -308,6 +314,88 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|         for (api in OAuth2accountApis) { |         for (api in OAuth2accountApis) { | ||||||
|             api.init() |             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) |         loadThemes(this) | ||||||
|         updateLocale() |         updateLocale() | ||||||
|         app.initClient(this) |         app.initClient(this) | ||||||
|  | @ -458,10 +546,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|             createISO() |             createISO() | ||||||
|         }*/ |         }*/ | ||||||
| 
 | 
 | ||||||
|         var providersString = "Current providers are:\n" |  | ||||||
|         var providersAndroidManifestString = "Current androidmanifest should be:\n" |         var providersAndroidManifestString = "Current androidmanifest should be:\n" | ||||||
|         for (api in apis) { |         for (api in allProviders) { | ||||||
|             providersString += "+ ${api.mainUrl}\n" |  | ||||||
|             providersAndroidManifestString += "<data android:scheme=\"https\" android:host=\"${ |             providersAndroidManifestString += "<data android:scheme=\"https\" android:host=\"${ | ||||||
|                 api.mainUrl.removePrefix( |                 api.mainUrl.removePrefix( | ||||||
|                     "https://" |                     "https://" | ||||||
|  | @ -469,17 +555,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|             }\" android:pathPrefix=\"/\"/>\n" |             }\" 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) |         println(providersAndroidManifestString) | ||||||
| 
 | 
 | ||||||
|         handleAppIntent(intent) |         handleAppIntent(intent) | ||||||
|  | @ -488,15 +563,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|             runAutoUpdate() |             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() |         APIRepository.dubStatusActive = getApiDubstatusSettings() | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|  | @ -507,7 +573,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|         } catch (e: Exception) { |         } catch (e: Exception) { | ||||||
|             logError(e) |             logError(e) | ||||||
|         } |         } | ||||||
| 
 |         println("Loaded everything") | ||||||
| /* | /* | ||||||
|         val relativePath = (Environment.DIRECTORY_DOWNLOADS) + File.separatorChar |         val relativePath = (Environment.DIRECTORY_DOWNLOADS) + File.separatorChar | ||||||
|         val displayName = "output.dex" //""output.dex" |         val displayName = "output.dex" //""output.dex" | ||||||
|  |  | ||||||
|  | @ -17,8 +17,8 @@ import java.util.* | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AllAnimeProvider : MainAPI() { | class AllAnimeProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://allanime.site" |     override var mainUrl = "https://allanime.site" | ||||||
|     override val name = "AllAnime" |     override var name = "AllAnime" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = false |     override val hasMainPage = false | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,8 +16,8 @@ class AnimeFlickProvider : MainAPI() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://animeflick.net" |     override var mainUrl = "https://animeflick.net" | ||||||
|     override val name = "AnimeFlick" |     override var name = "AnimeFlick" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = 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}.*${'$'})""") |             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 var mainUrl = MAIN_URL | ||||||
|     override val name = "AnimePahe" |     override var name = "AnimePahe" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.Qualities | import com.lagradost.cloudstream3.utils.Qualities | ||||||
| 
 | 
 | ||||||
| class AnimeWorldProvider : MainAPI() { | class AnimeWorldProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://www.animeworld.tv" |     override var mainUrl = "https://www.animeworld.tv" | ||||||
|     override val name = "AnimeWorld" |     override var name = "AnimeWorld" | ||||||
|     override val lang = "it" |     override val lang = "it" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,8 +14,8 @@ class AnimeflvnetProvider:MainAPI() { | ||||||
|             else TvType.Anime |             else TvType.Anime | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     override val mainUrl = "https://www3.animeflv.net" |     override var mainUrl = "https://www3.animeflv.net" | ||||||
|     override val name = "Animeflv.net" |     override var name = "Animeflv.net" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -12,8 +12,8 @@ import kotlin.collections.ArrayList | ||||||
| 
 | 
 | ||||||
| class AnimekisaProvider : MainAPI() { | class AnimekisaProvider : MainAPI() { | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://animekisa.in" |     override var mainUrl = "https://animekisa.in" | ||||||
|     override val name = "Animekisa" |     override var name = "Animekisa" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|     override val hasDownloadSupport = true |     override val hasDownloadSupport = true | ||||||
|  |  | ||||||
|  | @ -11,8 +11,8 @@ import org.jsoup.Jsoup | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class DubbedAnimeProvider : MainAPI() { | class DubbedAnimeProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://bestdubbedanime.com" |     override var mainUrl = "https://bestdubbedanime.com" | ||||||
|     override val name = "DubbedAnime" |     override var name = "DubbedAnime" | ||||||
|     override val hasQuickSearch = true |     override val hasQuickSearch = true | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -155,8 +155,8 @@ class GogoanimeProvider : MainAPI() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://gogoanime.film" |     override var mainUrl = "https://gogoanime.film" | ||||||
|     override val name = "GogoAnime" |     override var name = "GogoAnime" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import org.jsoup.Jsoup | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class KawaiifuProvider : MainAPI() { | class KawaiifuProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://kawaiifu.com" |     override var mainUrl = "https://kawaiifu.com" | ||||||
|     override val name = "Kawaiifu" |     override var name = "Kawaiifu" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,8 +17,8 @@ class MonoschinosProvider : MainAPI() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://monoschinos2.com" |     override var mainUrl = "https://monoschinos2.com" | ||||||
|     override val name = "Monoschinos" |     override var name = "Monoschinos" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -10,8 +10,8 @@ import org.jsoup.Jsoup | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class NineAnimeProvider : MainAPI() { | class NineAnimeProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://9anime.center" |     override var mainUrl = "https://9anime.center" | ||||||
|     override val name = "9Anime" |     override var name = "9Anime" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|     override val hasDownloadSupport = true |     override val hasDownloadSupport = true | ||||||
|  |  | ||||||
|  | @ -25,8 +25,8 @@ class TenshiProvider : MainAPI() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://tenshi.moe" |     override var mainUrl = "https://tenshi.moe" | ||||||
|     override val name = "Tenshi.moe" |     override var name = "Tenshi.moe" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie, TvType.OVA) |     override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie, TvType.OVA) | ||||||
|  |  | ||||||
|  | @ -12,8 +12,8 @@ import java.util.* | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class WatchCartoonOnlineProvider : MainAPI() { | class WatchCartoonOnlineProvider : MainAPI() { | ||||||
|     override val name = "WatchCartoonOnline" |     override var name = "WatchCartoonOnline" | ||||||
|     override val mainUrl = "https://www.wcostream.com" |     override var mainUrl = "https://www.wcostream.com" | ||||||
| 
 | 
 | ||||||
|     override val supportedTypes = setOf( |     override val supportedTypes = setOf( | ||||||
|         TvType.Cartoon, |         TvType.Cartoon, | ||||||
|  |  | ||||||
|  | @ -19,8 +19,8 @@ class WcoProvider : MainAPI() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://wcostream.cc" |     override var mainUrl = "https://wcostream.cc" | ||||||
|     override val name = "WCO Stream" |     override var name = "WCO Stream" | ||||||
|     override val hasQuickSearch = true |     override val hasQuickSearch = true | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,8 +18,8 @@ import java.net.URI | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class ZoroProvider : MainAPI() { | class ZoroProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://zoro.to" |     override var mainUrl = "https://zoro.to" | ||||||
|     override val name = "Zoro" |     override var name = "Zoro" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -5,8 +5,8 @@ import com.lagradost.cloudstream3.utils.* | ||||||
| import java.net.URI | import java.net.URI | ||||||
| 
 | 
 | ||||||
| class AsianLoad : ExtractorApi() { | class AsianLoad : ExtractorApi() { | ||||||
|     override val name = "AsianLoad" |     override var name = "AsianLoad" | ||||||
|     override val mainUrl = "https://asianembed.io" |     override var mainUrl = "https://asianembed.io" | ||||||
|     override val requiresReferer = true |     override val requiresReferer = true | ||||||
| 
 | 
 | ||||||
|     private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*?["'](.*?)["']""") |     private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*?["'](.*?)["']""") | ||||||
|  |  | ||||||
|  | @ -7,21 +7,21 @@ import com.lagradost.cloudstream3.utils.Qualities | ||||||
| import kotlinx.coroutines.delay | import kotlinx.coroutines.delay | ||||||
| 
 | 
 | ||||||
| class DoodToExtractor : DoodLaExtractor() { | class DoodToExtractor : DoodLaExtractor() { | ||||||
|     override val mainUrl = "https://dood.to" |     override var mainUrl = "https://dood.to" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class DoodSoExtractor : DoodLaExtractor() { | class DoodSoExtractor : DoodLaExtractor() { | ||||||
|     override val mainUrl = "https://dood.so" |     override var mainUrl = "https://dood.so" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class DoodWsExtractor : DoodLaExtractor() { | class DoodWsExtractor : DoodLaExtractor() { | ||||||
|     override val mainUrl = "https://dood.ws" |     override var mainUrl = "https://dood.ws" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| open class DoodLaExtractor : ExtractorApi() { | open class DoodLaExtractor : ExtractorApi() { | ||||||
|     override val name = "DoodStream" |     override var name = "DoodStream" | ||||||
|     override val mainUrl = "https://dood.la" |     override var mainUrl = "https://dood.la" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override fun getExtractorUrl(id: String): String { |     override fun getExtractorUrl(id: String): String { | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ import com.lagradost.cloudstream3.utils.* | ||||||
| import com.lagradost.cloudstream3.app | import com.lagradost.cloudstream3.app | ||||||
| 
 | 
 | ||||||
| class Evoload1 : Evoload() { | class Evoload1 : Evoload() { | ||||||
|     override val mainUrl = "https://evoload.io" |     override var mainUrl = "https://evoload.io" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| open class Evoload : ExtractorApi() { | open class Evoload : ExtractorApi() { | ||||||
|  |  | ||||||
|  | @ -12,8 +12,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| open class GenericM3U8 : ExtractorApi() { | open class GenericM3U8 : ExtractorApi() { | ||||||
|     override val name = "Upstream" |     override var name = "Upstream" | ||||||
|     override val mainUrl = "https://upstream.to" |     override var mainUrl = "https://upstream.to" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import com.lagradost.cloudstream3.app | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| open class Jawcloud : ExtractorApi() { | open class Jawcloud : ExtractorApi() { | ||||||
|     override val name = "Jawcloud" |     override var name = "Jawcloud" | ||||||
|     override val mainUrl = "https://jawcloud.co" |     override var mainUrl = "https://jawcloud.co" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     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 | import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
| 
 | 
 | ||||||
| open class Mcloud : ExtractorApi() { | open class Mcloud : ExtractorApi() { | ||||||
|     override val name = "Mcloud" |     override var name = "Mcloud" | ||||||
|     override val mainUrl = "https://mcloud.to" |     override var mainUrl = "https://mcloud.to" | ||||||
|     override val requiresReferer = true |     override val requiresReferer = true | ||||||
|     val headers = mapOf( |     val headers = mapOf( | ||||||
|         "Host" to "mcloud.to", |         "Host" to "mcloud.to", | ||||||
|  |  | ||||||
|  | @ -4,8 +4,8 @@ import com.lagradost.cloudstream3.app | ||||||
| import com.lagradost.cloudstream3.utils.* | import com.lagradost.cloudstream3.utils.* | ||||||
| 
 | 
 | ||||||
| class MixDrop : ExtractorApi() { | class MixDrop : ExtractorApi() { | ||||||
|     override val name = "MixDrop" |     override var name = "MixDrop" | ||||||
|     override val mainUrl = "https://mixdrop.co" |     override var mainUrl = "https://mixdrop.co" | ||||||
|     private val srcRegex = Regex("""wurl.*?=.*?"(.*?)";""") |     private val srcRegex = Regex("""wurl.*?=.*?"(.*?)";""") | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.Qualities | ||||||
| import com.lagradost.cloudstream3.utils.getAndUnpack | import com.lagradost.cloudstream3.utils.getAndUnpack | ||||||
| 
 | 
 | ||||||
| class Mp4Upload : ExtractorApi() { | class Mp4Upload : ExtractorApi() { | ||||||
|     override val name = "Mp4Upload" |     override var name = "Mp4Upload" | ||||||
|     override val mainUrl = "https://www.mp4upload.com" |     override var mainUrl = "https://www.mp4upload.com" | ||||||
|     private val srcRegex = Regex("""player\.src\("(.*?)"""") |     private val srcRegex = Regex("""player\.src\("(.*?)"""") | ||||||
|     override val requiresReferer = true |     override val requiresReferer = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
| import java.net.URI | import java.net.URI | ||||||
| 
 | 
 | ||||||
| class MultiQuality : ExtractorApi() { | class MultiQuality : ExtractorApi() { | ||||||
|     override val name = "MultiQuality" |     override var name = "MultiQuality" | ||||||
|     override val mainUrl = "https://gogo-play.net" |     override var mainUrl = "https://gogo-play.net" | ||||||
|     private val sourceRegex = Regex("""file:\s*['"](.*?)['"],label:\s*['"](.*?)['"]""") |     private val sourceRegex = Regex("""file:\s*['"](.*?)['"],label:\s*['"](.*?)['"]""") | ||||||
|     private val m3u8Regex = Regex(""".*?(\d*).m3u8""") |     private val m3u8Regex = Regex(""".*?(\d*).m3u8""") | ||||||
|     private val urlRegex = Regex("""(.*?)([^/]+$)""") |     private val urlRegex = Regex("""(.*?)([^/]+$)""") | ||||||
|  |  | ||||||
|  | @ -1,35 +1,63 @@ | ||||||
| package com.lagradost.cloudstream3.extractors | package com.lagradost.cloudstream3.extractors | ||||||
| 
 | 
 | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.lagradost.cloudstream3.utils.* | import com.lagradost.cloudstream3.utils.* | ||||||
| import com.lagradost.cloudstream3.app | 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() { | open class OkRu : ExtractorApi() { | ||||||
|     override val name = "Okru" |     override var name = "Okru" | ||||||
|     override val mainUrl = "http://ok.ru" |     override var mainUrl = "http://ok.ru" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|         val doc = app.get(url).document |         val doc = app.get(url).document | ||||||
|         val urlString = doc.select("div[data-options]").attr("data-options") |         val sources = ArrayList<ExtractorLink>() | ||||||
|             .substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"") |         val datajson = doc.select("div[data-options]").attr("data-options") | ||||||
|             .substringBefore("]") |         if (datajson.isNotBlank()) { | ||||||
|         urlString.split("{\\\"name\\\":\\\"").reversed().forEach { |             val main = parseJson<DataOptionsJson>(datajson) | ||||||
|             val extractedUrl = it.substringAfter("url\\\":\\\"") |             val metadatajson = parseJson<MetadataOkru>(main.flashvars?.metadata!!) | ||||||
|                 .substringBefore("\\\"") |             val servers = metadatajson.videos | ||||||
|                 .replace("\\\\u0026", "&") |             servers.forEach { | ||||||
|             val Quality = it.uppercase().substringBefore("\\\"") |                 val quality = it.name.uppercase() | ||||||
| 
 |                     .replace("MOBILE","144p") | ||||||
|             if (extractedUrl.isNotBlank())  return listOf( |                     .replace("LOWEST","240p") | ||||||
|                 ExtractorLink( |                     .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, | ||||||
|                     "$name ${Quality}", |                     "$name $quality", | ||||||
|                     extractedUrl, |                     extractedurl, | ||||||
|                     url, |                     url, | ||||||
|                     Qualities.Unknown.value, |                     getQualityFromName(quality), | ||||||
|                     isM3u8 = false |                     isM3u8 = false | ||||||
|                 ) |                 )) | ||||||
|             ) |             } | ||||||
|         } |         } | ||||||
|         return null |         return sources | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -6,8 +6,8 @@ import com.lagradost.cloudstream3.app | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| open class PlayerVoxzer : ExtractorApi() { | open class PlayerVoxzer : ExtractorApi() { | ||||||
|     override val name = "Voxzer" |     override var name = "Voxzer" | ||||||
|     override val mainUrl = "https://player.voxzer.org" |     override var mainUrl = "https://player.voxzer.org" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|  |  | ||||||
|  | @ -10,16 +10,16 @@ import com.lagradost.cloudstream3.utils.getPostForm | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| //class SBPlay1 : SBPlay() { | //class SBPlay1 : SBPlay() { | ||||||
| //    override val mainUrl = "https://sbplay1.com" | //    override var mainUrl = "https://sbplay1.com" | ||||||
| //} | //} | ||||||
| 
 | 
 | ||||||
| //class SBPlay2 : SBPlay() { | //class SBPlay2 : SBPlay() { | ||||||
| //    override val mainUrl = "https://sbplay2.com" | //    override var mainUrl = "https://sbplay2.com" | ||||||
| //} | //} | ||||||
| 
 | 
 | ||||||
| open class SBPlay : ExtractorApi() { | open class SBPlay : ExtractorApi() { | ||||||
|     override val mainUrl = "https://sbplay.one" |     override var mainUrl = "https://sbplay.one" | ||||||
|     override val name = "SBPlay" |     override var name = "SBPlay" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||||
|  |  | ||||||
|  | @ -9,46 +9,50 @@ import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class StreamSB1 : StreamSB() { | class StreamSB1 : StreamSB() { | ||||||
|     override val mainUrl = "https://sbplay1.com" |     override var mainUrl = "https://sbplay1.com" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB2 : StreamSB() { | class StreamSB2 : StreamSB() { | ||||||
|     override val mainUrl = "https://sbplay2.com" |     override var mainUrl = "https://sbplay2.com" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB3 : StreamSB() { | class StreamSB3 : StreamSB() { | ||||||
|     override val mainUrl = "https://sbplay3.com" |     override var mainUrl = "https://sbplay3.com" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB4 : StreamSB() { | class StreamSB4 : StreamSB() { | ||||||
|     override val mainUrl = "https://cloudemb.com" |     override var mainUrl = "https://cloudemb.com" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB5 : StreamSB() { | class StreamSB5 : StreamSB() { | ||||||
|     override val mainUrl = "https://sbplay.org" |     override var mainUrl = "https://sbplay.org" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB6 : StreamSB() { | class StreamSB6 : StreamSB() { | ||||||
|     override val mainUrl = "https://embedsb.com" |     override var mainUrl = "https://embedsb.com" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB7 : StreamSB() { | class StreamSB7 : StreamSB() { | ||||||
|     override val mainUrl = "https://pelistop.co" |     override var mainUrl = "https://pelistop.co" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB8 : StreamSB() { | class StreamSB8 : StreamSB() { | ||||||
|     override val mainUrl = "https://streamsb.net" |     override var mainUrl = "https://streamsb.net" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class StreamSB9 : StreamSB() { | 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 | // 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 | // The following code is under the Apache License 2.0 https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE | ||||||
| open class StreamSB : ExtractorApi() { | open class StreamSB : ExtractorApi() { | ||||||
|     override val name = "StreamSB" |     override var name = "StreamSB" | ||||||
|     override val mainUrl = "https://watchsb.com" |     override var mainUrl = "https://watchsb.com" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     private val hexArray = "0123456789ABCDEF".toCharArray() |     private val hexArray = "0123456789ABCDEF".toCharArray() | ||||||
|  | @ -88,53 +92,30 @@ open class StreamSB : ExtractorApi() { | ||||||
|         }.first() |         }.first() | ||||||
|         val bytes = id.toByteArray() |         val bytes = id.toByteArray() | ||||||
|         val bytesToHex = bytesToHex(bytes) |         val bytesToHex = bytesToHex(bytes) | ||||||
|         val master = "$mainUrl/sources41/566d337678566f743674494a7c7c${bytesToHex}7c7c346b6767586d6934774855537c7c73747265616d7362/6565417268755339773461447c7c346133383438333436313335376136323337373433383634376337633465366534393338373136643732373736343735373237613763376334363733353737303533366236333463353333363534366137633763373337343732363536313664373336327c7c6b586c3163614468645a47617c7c73747265616d7362" |         val master = "$mainUrl/sources41/6d6144797752744a454267617c7c${bytesToHex.lowercase()}7c7c4e61755a56456f34385243727c7c73747265616d7362/6b4a33767968506e4e71374f7c7c343837323439333133333462353935333633373836643638376337633462333634663539343137373761333635313533333835333763376333393636363133393635366136323733343435323332376137633763373337343732363536313664373336327c7c504d754478413835306633797c7c73747265616d7362" | ||||||
|         val headers = mapOf( |         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", |             "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, |         val urltext = app.get(master, | ||||||
|             headers = headers, |             headers = headers, | ||||||
|             allowRedirects = false |             allowRedirects = false | ||||||
|         ).text |         ).text | ||||||
|         val mapped = urltext.let { parseJson<Main>(it) } |         val mapped = urltext.let { parseJson<Main>(it) } | ||||||
|         val testurl = app.get(mapped.streamData.file, headers = headers).text |         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( |         if (urltext.contains("m3u8") && testurl.contains("EXTM3U")) return  M3u8Helper().m3u8Generation( | ||||||
|             M3u8Helper.M3u8Stream( |             M3u8Helper.M3u8Stream( | ||||||
|                 mapped.streamData.file, |                 mapped.streamData.file, | ||||||
|                 headers = mapOf( |                 headers = headers | ||||||
|                     "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",), |  | ||||||
|             ), true |             ), true | ||||||
|         ) |         ) | ||||||
|             .map { stream -> |             .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" |                 val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" | ||||||
|                 ExtractorLink( |                 ExtractorLink( | ||||||
|                     name, |                     name, | ||||||
|                     "$name $qualityString", |                     "$name $qualityString", | ||||||
|                     cleanstreamurl, |                     stream.streamUrl, | ||||||
|                     url, |                     url, | ||||||
|                     getQualityFromName(stream.quality.toString()), |                     getQualityFromName(stream.quality.toString()), | ||||||
|                     true |                     true | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.Qualities | import com.lagradost.cloudstream3.utils.Qualities | ||||||
| 
 | 
 | ||||||
| class StreamTape : ExtractorApi() { | class StreamTape : ExtractorApi() { | ||||||
|     override val name = "StreamTape" |     override var name = "StreamTape" | ||||||
|     override val mainUrl = "https://streamtape.com" |     override var mainUrl = "https://streamtape.com" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     private val linkRegex = |     private val linkRegex = | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.Qualities | ||||||
| import java.net.URI | import java.net.URI | ||||||
| 
 | 
 | ||||||
| class Streamhub : ExtractorApi() { | class Streamhub : ExtractorApi() { | ||||||
|     override val mainUrl = "https://streamhub.to" |     override var mainUrl = "https://streamhub.to" | ||||||
|     override val name = "Streamhub" |     override var name = "Streamhub" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override fun getExtractorUrl(id: String): String { |     override fun getExtractorUrl(id: String): String { | ||||||
|  |  | ||||||
|  | @ -1,19 +1,21 @@ | ||||||
| package com.lagradost.cloudstream3.extractors | package com.lagradost.cloudstream3.extractors | ||||||
| 
 | 
 | ||||||
| import com.lagradost.cloudstream3.utils.* |  | ||||||
| import com.lagradost.cloudstream3.app |  | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
|  | import com.lagradost.cloudstream3.app | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.parseJson | 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() { | class Cinestart: Tomatomatela() { | ||||||
|     override val name: String = "Cinestart" |     override var name = "Cinestart" | ||||||
|     override val mainUrl: String = "https://cinestart.net" |     override var mainUrl = "https://cinestart.net" | ||||||
|     override val details = "vr.php?v=" |     override val details = "vr.php?v=" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| open class Tomatomatela : ExtractorApi() { | open class Tomatomatela : ExtractorApi() { | ||||||
|     override val name = "Tomatomatela" |     override var name = "Tomatomatela" | ||||||
|     override val mainUrl = "https://tomatomatela.com" |     override var mainUrl = "https://tomatomatela.com" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
|     private data class Tomato ( |     private data class Tomato ( | ||||||
|         @JsonProperty("status") val status: Int, |         @JsonProperty("status") val status: Int, | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ import com.lagradost.cloudstream3.utils.* | ||||||
| import com.lagradost.cloudstream3.app | import com.lagradost.cloudstream3.app | ||||||
| 
 | 
 | ||||||
| class Uqload1 : Uqload() { | class Uqload1 : Uqload() { | ||||||
|     override val mainUrl = "https://uqload.com" |     override var mainUrl = "https://uqload.com" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| open class Uqload : ExtractorApi() { | open class Uqload : ExtractorApi() { | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.M3u8Helper | ||||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
| 
 | 
 | ||||||
| open class WatchSB : ExtractorApi() { | open class WatchSB : ExtractorApi() { | ||||||
|     override val name = "WatchSB" |     override var name = "WatchSB" | ||||||
|     override val mainUrl = "https://watchsb.com" |     override var mainUrl = "https://watchsb.com" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||||
|  |  | ||||||
|  | @ -8,19 +8,19 @@ import com.lagradost.cloudstream3.mapper | ||||||
| import com.lagradost.cloudstream3.utils.* | import com.lagradost.cloudstream3.utils.* | ||||||
| 
 | 
 | ||||||
| class Vidstreamz : WcoStream() { | class Vidstreamz : WcoStream() { | ||||||
|     override val mainUrl: String = "https://vidstreamz.online" |     override var mainUrl = "https://vidstreamz.online" | ||||||
| } | } | ||||||
| class Vizcloud : WcoStream() { | class Vizcloud : WcoStream() { | ||||||
|     override val mainUrl: String = "https://vizcloud2.ru" |     override var mainUrl = "https://vizcloud2.ru" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class Vizcloud2 : WcoStream() { | class Vizcloud2 : WcoStream() { | ||||||
|     override val mainUrl: String = "https://vizcloud2.online" |     override var mainUrl = "https://vizcloud2.online" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| open class WcoStream : ExtractorApi() { | open class WcoStream : ExtractorApi() { | ||||||
|     override val name = "VidStream" //Cause works for animekisa and wco |     override var name = "VidStream" //Cause works for animekisa and wco | ||||||
|     override val mainUrl = "https://vidstream.pro" |     override var mainUrl = "https://vidstream.pro" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
|     private val hlsHelper = M3u8Helper() |     private val hlsHelper = M3u8Helper() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,23 +5,23 @@ import com.lagradost.cloudstream3.app | ||||||
| import com.lagradost.cloudstream3.utils.* | import com.lagradost.cloudstream3.utils.* | ||||||
| 
 | 
 | ||||||
| class Zplayer: ZplayerV2() { | class Zplayer: ZplayerV2() { | ||||||
|     override val name: String = "Zplayer" |     override var name: String = "Zplayer" | ||||||
|     override val mainUrl: String = "https://zplayer.live" |     override var mainUrl: String = "https://zplayer.live" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class Upstream: ZplayerV2() { | class Upstream: ZplayerV2() { | ||||||
|     override val name: String = "Upstream" //Here 'cause works |     override var name: String = "Upstream" //Here 'cause works | ||||||
|     override val mainUrl: String = "https://upstream.to" |     override var mainUrl: String = "https://upstream.to" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class Streamhub2: ZplayerV2() { | class Streamhub2: ZplayerV2() { | ||||||
|     override val name: String = "Streamhub" //Here 'cause works |     override var name = "Streamhub" //Here 'cause works | ||||||
|     override val mainUrl: String = "https://streamhub.to" |     override var mainUrl = "https://streamhub.to" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| open class ZplayerV2 : ExtractorApi() { | open class ZplayerV2 : ExtractorApi() { | ||||||
|     override val name = "Zplayer V2" |     override var name = "Zplayer V2" | ||||||
|     override val mainUrl = "https://v2.zplayer.live" |     override var mainUrl = "https://v2.zplayer.live" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { |     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 | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| 
 | 
 | ||||||
| class CrossTmdbProvider : TmdbProvider() { | class CrossTmdbProvider : TmdbProvider() { | ||||||
|     override val name = "MultiMovie" |     override var name = "MultiMovie" | ||||||
|     override val apiName = "MultiMovie" |     override val apiName = "MultiMovie" | ||||||
|     override val lang = "en" |     override val lang = "en" | ||||||
|     override val useMetaLoadResponse = true |     override val useMetaLoadResponse = true | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ import org.jsoup.nodes.Element | ||||||
| 
 | 
 | ||||||
| class AkwamProvider : MainAPI() { | class AkwamProvider : MainAPI() { | ||||||
|     override val lang = "ar" |     override val lang = "ar" | ||||||
|     override val mainUrl = "https://akwam.to" |     override var mainUrl = "https://akwam.to" | ||||||
|     override val name = "Akwam" |     override var name = "Akwam" | ||||||
|     override val usesWebView = false |     override val usesWebView = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie, TvType.Anime, TvType.Cartoon) |     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. |     // Fetching movies will not work if this link is outdated. | ||||||
|     override val mainUrl = "https://allmoviesforyou.net" |     override var mainUrl = "https://allmoviesforyou.net" | ||||||
|     override val name = "AllMoviesForYou" |     override var name = "AllMoviesForYou" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val supportedTypes = setOf( |     override val supportedTypes = setOf( | ||||||
|         TvType.Movie, |         TvType.Movie, | ||||||
|  | @ -149,7 +149,7 @@ class AllMoviesForYouProvider : MainAPI() { | ||||||
|                                 name, |                                 name, | ||||||
|                                 season.first, |                                 season.first, | ||||||
|                                 epNum, |                                 epNum, | ||||||
|                                 href, |                                 fixUrl(href), | ||||||
|                                 fixUrlNull(poster), |                                 fixUrlNull(poster), | ||||||
|                                 date |                                 date | ||||||
|                             ) |                             ) | ||||||
|  | @ -175,7 +175,7 @@ class AllMoviesForYouProvider : MainAPI() { | ||||||
|                 title, |                 title, | ||||||
|                 url, |                 url, | ||||||
|                 type, |                 type, | ||||||
|                 url |                 fixUrl(url) | ||||||
|             ) { |             ) { | ||||||
|                 posterUrl = backgroundPoster |                 posterUrl = backgroundPoster | ||||||
|                 this.year = year?.toIntOrNull() |                 this.year = year?.toIntOrNull() | ||||||
|  | @ -193,12 +193,12 @@ class AllMoviesForYouProvider : MainAPI() { | ||||||
|         callback: (ExtractorLink) -> Unit |         callback: (ExtractorLink) -> Unit | ||||||
|     ): Boolean { |     ): Boolean { | ||||||
|         val doc = app.get(data).document |         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 -> |         iframe.apmap { id -> | ||||||
|             if (id.contains("trembed")) { |             if (id.contains("trembed")) { | ||||||
|                 val soup = app.get(id).document |                 val soup = app.get(id).document | ||||||
|                 soup.select("body iframe").map { |                 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) |                     loadExtractor(link, data, callback) | ||||||
|                 } |                 } | ||||||
|             } else loadExtractor(id, data, callback) |             } else loadExtractor(id, data, callback) | ||||||
|  |  | ||||||
|  | @ -10,8 +10,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class ApiMDBProvider : TmdbProvider() { | class ApiMDBProvider : TmdbProvider() { | ||||||
|     override val apiName = "ApiMDB" |     override val apiName = "ApiMDB" | ||||||
|     override val name = "ApiMDB" |     override var name = "ApiMDB" | ||||||
|     override val mainUrl = "https://v2.apimdb.net" |     override var mainUrl = "https://v2.apimdb.net" | ||||||
|     override val useMetaLoadResponse = true |     override val useMetaLoadResponse = true | ||||||
|     override val instantLinkLoading = false |     override val instantLinkLoading = false | ||||||
|     override val supportedTypes = setOf( |     override val supportedTypes = setOf( | ||||||
|  |  | ||||||
|  | @ -11,8 +11,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
| import java.net.URI | import java.net.URI | ||||||
| 
 | 
 | ||||||
| class AsiaFlixProvider : MainAPI() { | class AsiaFlixProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://asiaflix.app" |     override var mainUrl = "https://asiaflix.app" | ||||||
|     override val name = "AsiaFlix" |     override var name = "AsiaFlix" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = false |     override val hasChromecastSupport = false | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import com.lagradost.cloudstream3.TvType | ||||||
|  * make the app know what functions to call |  * make the app know what functions to call | ||||||
|  */ |  */ | ||||||
| class AsianLoadProvider : VidstreamProviderTemplate() { | class AsianLoadProvider : VidstreamProviderTemplate() { | ||||||
|     override val name = "AsianLoad" |     override var name = "AsianLoad" | ||||||
|     override val mainUrl = "https://asianembed.io" |     override var mainUrl = "https://asianembed.io" | ||||||
|     override val homePageUrlList = listOf( |     override val homePageUrlList = listOf( | ||||||
|         mainUrl, |         mainUrl, | ||||||
|         "$mainUrl/recently-added-raw", |         "$mainUrl/recently-added-raw", | ||||||
|  |  | ||||||
|  | @ -7,9 +7,18 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.loadExtractor | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| class BflixProvider(providerUrl: String, providerName: String) : MainAPI() { | class FmoviesToProvider : BflixProvider() { | ||||||
|     override val mainUrl = providerUrl |     override var mainUrl = "https://fmovies.to" | ||||||
|     override val name = providerName |     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 hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|     override val hasDownloadSupport = true |     override val hasDownloadSupport = true | ||||||
|  |  | ||||||
|  | @ -1,17 +1,14 @@ | ||||||
| package com.lagradost.cloudstream3.movieproviders | package com.lagradost.cloudstream3.movieproviders | ||||||
| 
 | 
 | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty |  | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.extractors.Cinestart | import com.lagradost.cloudstream3.extractors.Cinestart | ||||||
| import com.lagradost.cloudstream3.mvvm.logError | import com.lagradost.cloudstream3.mvvm.logError | ||||||
| import com.lagradost.cloudstream3.utils.* | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import java.util.* | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class CinecalidadProvider:MainAPI() { | class CinecalidadProvider:MainAPI() { | ||||||
|     override val mainUrl: String |     override var mainUrl = "https://cinecalidad.lol" | ||||||
|         get() = "https://cinecalidad.lol" |     override var name = "Cinecalidad" | ||||||
|     override val name: String |  | ||||||
|         get() = "Cinecalidad" |  | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class CuevanaProvider:MainAPI() { | class CuevanaProvider:MainAPI() { | ||||||
|     override val mainUrl = "https://cuevana3.io" |     override var mainUrl = "https://cuevana3.me" | ||||||
|     override val name = "Cuevana" |     override var name = "Cuevana" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  | @ -191,19 +191,19 @@ class CuevanaProvider:MainAPI() { | ||||||
|     ): Boolean { |     ): Boolean { | ||||||
|         app.get(data).document.select("div.TPlayer.embed_div iframe").apmap { |         app.get(data).document.select("div.TPlayer.embed_div iframe").apmap { | ||||||
|             val iframe = fixUrl(it.attr("data-src")) |             val iframe = fixUrl(it.attr("data-src")) | ||||||
|             if (iframe.contains("api.cuevana3.io/fembed/")) { |             if (iframe.contains("api.cuevana3.me/fembed/")) { | ||||||
|                 val femregex = Regex("(https.\\/\\/api\\.cuevana3\\.io\\/fembed\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)") |                 val femregex = Regex("(https.\\/\\/api\\.cuevana3\\.me\\/fembed\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)") | ||||||
|                 femregex.findAll(iframe).map { femreg -> |                 femregex.findAll(iframe).map { femreg -> | ||||||
|                     femreg.value |                     femreg.value | ||||||
|                 }.toList().apmap { fem -> |                 }.toList().apmap { fem -> | ||||||
|                     val key = fem.replace("https://api.cuevana3.io/fembed/?h=","") |                     val key = fem.replace("https://api.cuevana3.me/fembed/?h=","") | ||||||
|                     val url = app.post("https://api.cuevana3.io/fembed/api.php", allowRedirects = false, headers = mapOf("Host" to "api.cuevana3.io", |                     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, |                         "User-Agent" to USER_AGENT, | ||||||
|                         "Accept" to "application/json, text/javascript, */*; q=0.01", |                         "Accept" to "application/json, text/javascript, */*; q=0.01", | ||||||
|                         "Accept-Language" to "en-US,en;q=0.5", |                         "Accept-Language" to "en-US,en;q=0.5", | ||||||
|                         "Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8", |                         "Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8", | ||||||
|                         "X-Requested-With" to "XMLHttpRequest", |                         "X-Requested-With" to "XMLHttpRequest", | ||||||
|                         "Origin" to "https://api.cuevana3.io", |                         "Origin" to "https://api.cuevana3.me", | ||||||
|                         "DNT" to "1", |                         "DNT" to "1", | ||||||
|                         "Connection" to "keep-alive", |                         "Connection" to "keep-alive", | ||||||
|                         "Sec-Fetch-Dest" to "empty", |                         "Sec-Fetch-Dest" to "empty", | ||||||
|  | @ -239,12 +239,12 @@ class CuevanaProvider:MainAPI() { | ||||||
|                         data = mapOf(Pair("url",tomkey)) |                         data = mapOf(Pair("url",tomkey)) | ||||||
|                     ).response.headers.values("location").apmap { loc -> |                     ).response.headers.values("location").apmap { loc -> | ||||||
|                         if (loc.contains("goto_ddh.php")) { |                         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 -> |                             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 -> |                             }.toList().apmap { gotolink -> | ||||||
|                                 app.post("https://api.cuevana3.io/ir/redirect_ddh.php", allowRedirects = false, |                                 app.post("https://api.cuevana3.me/ir/redirect_ddh.php", allowRedirects = false, | ||||||
|                                     headers = mapOf("Host" to "api.cuevana3.io", |                                     headers = mapOf("Host" to "api.cuevana3.me", | ||||||
|                                         "User-Agent" to USER_AGENT, |                                         "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" 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", |                                         "Accept-Language" to "en-US,en;q=0.5", | ||||||
|  | @ -263,12 +263,12 @@ class CuevanaProvider:MainAPI() { | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         if (loc.contains("index.php?h=")) { |                         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 -> |                             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 -> |                             }.toList().apmap { inlink -> | ||||||
|                                 app.post("https://api.cuevana3.io/sc/r.php", allowRedirects = false, |                                 app.post("https://api.cuevana3.me/sc/r.php", allowRedirects = false, | ||||||
|                                     headers = mapOf("Host" to "api.cuevana3.io", |                                     headers = mapOf("Host" to "api.cuevana3.me", | ||||||
|                                         "User-Agent" to USER_AGENT, |                                         "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" 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", |                                         "Accept-Language" to "en-US,en;q=0.5", | ||||||
|  |  | ||||||
|  | @ -16,8 +16,8 @@ class DoramasYTProvider : MainAPI() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://doramasyt.com" |     override var mainUrl = "https://doramasyt.com" | ||||||
|     override val name = "DoramasYT" |     override var name = "DoramasYT" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -10,8 +10,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.loadExtractor | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class DramaSeeProvider : MainAPI() { | class DramaSeeProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://dramasee.net" |     override var mainUrl = "https://dramasee.net" | ||||||
|     override val name = "DramaSee" |     override var name = "DramaSee" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = false |     override val hasChromecastSupport = false | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import org.jsoup.nodes.Element | ||||||
| 
 | 
 | ||||||
| class EgyBestProvider : MainAPI() { | class EgyBestProvider : MainAPI() { | ||||||
|     override val lang = "ar" |     override val lang = "ar" | ||||||
|     override val mainUrl = "https://egy.best" |     override var mainUrl = "https://egy.best" | ||||||
|     override val name = "EgyBest" |     override var name = "EgyBest" | ||||||
|     override val usesWebView = false |     override val usesWebView = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) |     override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.* | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class EntrepeliculasyseriesProvider:MainAPI() { | class EntrepeliculasyseriesProvider:MainAPI() { | ||||||
|     override val mainUrl = "https://entrepeliculasyseries.nu" |     override var mainUrl = "https://entrepeliculasyseries.nu" | ||||||
|     override val name = "EntrePeliculasySeries" |     override var name = "EntrePeliculasySeries" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ import org.jsoup.Jsoup | ||||||
| import org.jsoup.select.Elements | import org.jsoup.select.Elements | ||||||
| 
 | 
 | ||||||
| class FilmanProvider : MainAPI() { | class FilmanProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://filman.cc" |     override var mainUrl = "https://filman.cc" | ||||||
|     override val name = "filman.cc" |     override var name = "filman.cc" | ||||||
|     override val lang = "pl" |     override val lang = "pl" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val supportedTypes = setOf( |     override val supportedTypes = setOf( | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.Qualities | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| class HDMProvider : MainAPI() { | class HDMProvider : MainAPI() { | ||||||
|     override val name = "HD Movies" |     override var name = "HD Movies" | ||||||
|     override val mainUrl = "https://hdm.to" |     override var mainUrl = "https://hdm.to" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|     override val supportedTypes = setOf( |     override val supportedTypes = setOf( | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import org.jsoup.Jsoup | ||||||
| import java.net.URLEncoder | import java.net.URLEncoder | ||||||
| 
 | 
 | ||||||
| class IHaveNoTvProvider : MainAPI() { | class IHaveNoTvProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://ihavenotv.com" |     override var mainUrl = "https://ihavenotv.com" | ||||||
|     override val name = "I Have No TV" |     override var name = "I Have No TV" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,8 +14,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| class KdramaHoodProvider : MainAPI() { | class KdramaHoodProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://kdramahood.com" |     override var mainUrl = "https://kdramahood.com" | ||||||
|     override val name = "KDramaHood" |     override var name = "KDramaHood" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = false |     override val hasChromecastSupport = false | ||||||
|  |  | ||||||
|  | @ -13,8 +13,8 @@ import org.jsoup.Jsoup | ||||||
| //BE AWARE THAT weboas.is is a clone of lookmovie | //BE AWARE THAT weboas.is is a clone of lookmovie | ||||||
| class LookMovieProvider : MainAPI() { | class LookMovieProvider : MainAPI() { | ||||||
|     override val hasQuickSearch = true |     override val hasQuickSearch = true | ||||||
|     override val name = "LookMovie" |     override var name = "LookMovie" | ||||||
|     override val mainUrl = "https://lookmovie.io" |     override var mainUrl = "https://lookmovie.io" | ||||||
| 
 | 
 | ||||||
|     override val supportedTypes = setOf( |     override val supportedTypes = setOf( | ||||||
|         TvType.Movie, |         TvType.Movie, | ||||||
|  |  | ||||||
|  | @ -11,8 +11,8 @@ import org.jsoup.Jsoup | ||||||
| import org.jsoup.nodes.Element | import org.jsoup.nodes.Element | ||||||
| 
 | 
 | ||||||
| class MeloMovieProvider : MainAPI() { | class MeloMovieProvider : MainAPI() { | ||||||
|     override val name = "MeloMovie" |     override var name = "MeloMovie" | ||||||
|     override val mainUrl = "https://melomovie.com" |     override var mainUrl = "https://melomovie.com" | ||||||
|     override val instantLinkLoading = true |     override val instantLinkLoading = true | ||||||
|     override val hasQuickSearch = true |     override val hasQuickSearch = true | ||||||
|     override val hasChromecastSupport = false // MKV FILES CANT BE PLAYED ON A CHROMECAST |     override val hasChromecastSupport = false // MKV FILES CANT BE PLAYED ON A CHROMECAST | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ import org.jsoup.nodes.Element | ||||||
| 
 | 
 | ||||||
| class MyCimaProvider : MainAPI() { | class MyCimaProvider : MainAPI() { | ||||||
|     override val lang = "ar" |     override val lang = "ar" | ||||||
|     override val mainUrl = "https://mycima.tv" |     override var mainUrl = "https://mycima.tv" | ||||||
|     override val name = "MyCima" |     override var name = "MyCima" | ||||||
|     override val usesWebView = false |     override val usesWebView = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) |     override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| import kotlin.collections.ArrayList | import kotlin.collections.ArrayList | ||||||
| 
 | 
 | ||||||
| class PeliSmartProvider: MainAPI() { | class PeliSmartProvider: MainAPI() { | ||||||
|     override val mainUrl = "https://pelismart.com" |     override var mainUrl = "https://pelismart.com" | ||||||
|     override val name = "PeliSmart" |     override var name = "PeliSmart" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.loadExtractor | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class PelisflixProvider : MainAPI() { | class PelisflixProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://pelisflix.li" |     override var mainUrl = "https://pelisflix.li" | ||||||
|     override val name = "Pelisflix" |     override var name = "Pelisflix" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import org.jsoup.nodes.Element | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class PelisplusHDProvider:MainAPI() { | class PelisplusHDProvider:MainAPI() { | ||||||
|     override val mainUrl = "https://pelisplushd.net" |     override var mainUrl = "https://pelisplushd.net" | ||||||
|     override val name = "PelisplusHD" |     override var name = "PelisplusHD" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -7,10 +7,10 @@ import com.lagradost.cloudstream3.TvType | ||||||
|  */  |  */  | ||||||
| class PelisplusProvider : PelisplusProviderTemplate() { | class PelisplusProvider : PelisplusProviderTemplate() { | ||||||
|     // mainUrl is good to have as a holder for the url to make future changes easier. |     // 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. |     // 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( |     override val homePageUrlList = listOf( | ||||||
|         mainUrl, |         mainUrl, | ||||||
|  |  | ||||||
|  | @ -1,11 +1,8 @@ | ||||||
| package com.lagradost.cloudstream3.movieproviders | package com.lagradost.cloudstream3.movieproviders | ||||||
| 
 | 
 | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.extractors.Pelisplus | import com.lagradost.cloudstream3.utils.* | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink |  | ||||||
| import com.lagradost.cloudstream3.utils.getQualityFromName |  | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| import java.net.URI |  | ||||||
| 
 | 
 | ||||||
| /** Needs to inherit from MainAPI() to | /** Needs to inherit from MainAPI() to | ||||||
|  * make the app know what functions to call |  * make the app know what functions to call | ||||||
|  | @ -14,7 +11,6 @@ import java.net.URI | ||||||
| open class PelisplusProviderTemplate : MainAPI() { | open class PelisplusProviderTemplate : MainAPI() { | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     open val homePageUrlList = listOf<String>() |     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. | //    // mainUrl is good to have as a holder for the url to make future changes easier. | ||||||
| //    override val mainUrl: String | //    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 |     // 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. |     // 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> { |     override suspend fun search(query: String): ArrayList<SearchResponse> { | ||||||
|         // Simply looking at devtools network is enough to spot a request like: |         // 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. |         // 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")) |             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 |             // .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. |             // 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() |             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 html = app.get(url).text | ||||||
|         val soup = Jsoup.parse(html) |         val soup = Jsoup.parse(html) | ||||||
| 
 | 
 | ||||||
|         var title = soup.selectFirst("h1,h2,h3").text() |         val title = cleanName(soup.selectFirst("h1,h2,h3").text()) | ||||||
|         title = if (!title.contains("Episode")) title else title.split("Episode")[0].trim() |  | ||||||
| 
 |  | ||||||
|         val description = soup.selectFirst(".post-entry")?.text()?.trim() |         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 episodes = soup.select(".listing.items.lists > .video-block").map { li -> | ||||||
|             val epTitle = if (li.selectFirst(".name") != null) |             val href = fixUrl(li.selectFirst("a").attr("href")) | ||||||
|                 if (li.selectFirst(".name").text().contains("Episode")) |             val regexseason = Regex("(-[Tt]emporada-(\\d+)-[Cc]apitulo-(\\d+))") | ||||||
|                     "Episode " + li.selectFirst(".name").text().split("Episode")[1].trim() |             val aaa = regexseason.find(href)?.destructured?.component1()?.replace(Regex("(-[Tt]emporada-|[Cc]apitulo-)"),"") | ||||||
|                 else |             val seasonid = aaa.let { str -> | ||||||
|                     li.selectFirst(".name").text() |                 str?.split("-")?.mapNotNull { subStr -> subStr.toIntOrNull() } | ||||||
|             else "" |             } | ||||||
|  |             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 epThumb = fixUrl(li.selectFirst("img").attr("src")) | ||||||
|             val epDate = li.selectFirst(".meta > .date").text() |             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( |             TvSeriesEpisode( | ||||||
|                 epTitle, |  | ||||||
|                 null, |                 null, | ||||||
|                 epNum, |                 season, | ||||||
|  |                 episode, | ||||||
|                 fixUrl(li.selectFirst("a").attr("href")), |                 fixUrl(li.selectFirst("a").attr("href")), | ||||||
|                 epThumb, |                 epThumb, | ||||||
|                 epDate |                 epDate | ||||||
|  | @ -119,10 +112,10 @@ open class PelisplusProviderTemplate : MainAPI() { | ||||||
|                     this.name, |                     this.name, | ||||||
|                     tvType, |                     tvType, | ||||||
|                     episodes, |                     episodes, | ||||||
|                     poster, |                     fixUrl(poster), | ||||||
|                     year, |                     year, | ||||||
|                     description, |                     description, | ||||||
|                     ShowStatus.Ongoing, |                     null, | ||||||
|                     null, |                     null, | ||||||
|                     null |                     null | ||||||
|                 ) |                 ) | ||||||
|  | @ -134,7 +127,7 @@ open class PelisplusProviderTemplate : MainAPI() { | ||||||
|                     this.name, |                     this.name, | ||||||
|                     tvType, |                     tvType, | ||||||
|                     episodes[0].data, |                     episodes[0].data, | ||||||
|                     poster, |                     fixUrl(poster), | ||||||
|                     year, |                     year, | ||||||
|                     description, |                     description, | ||||||
|                     null, |                     null, | ||||||
|  | @ -156,12 +149,12 @@ open class PelisplusProviderTemplate : MainAPI() { | ||||||
|             val document = Jsoup.parse(response) |             val document = Jsoup.parse(response) | ||||||
|             document.select("div.main-inner")?.forEach { inner -> |             document.select("div.main-inner")?.forEach { inner -> | ||||||
|                 // Always trim your text unless you want the risk of spaces at the start or end. |                 // 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 elements = inner.select(".video-block").map { | ||||||
|                     val link = fixUrl(it.select("a").attr("href")) |                     val link = fixUrl(it.select("a").attr("href")) | ||||||
|                     val image = it.select(".picture > img").attr("src").replace("//img", "https://img") |                     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 name = cleanName(it.select("div.name").text()) | ||||||
|                     val isSeries = (name.contains("Season") || name.contains("Episode")) |                     val isSeries = (name.contains("Temporada") || name.contains("Capítulo")) | ||||||
| 
 | 
 | ||||||
|                     if (isSeries) { |                     if (isSeries) { | ||||||
|                         TvSeriesSearchResponse( |                         TvSeriesSearchResponse( | ||||||
|  | @ -198,6 +191,38 @@ open class PelisplusProviderTemplate : MainAPI() { | ||||||
|         return HomePageResponse(homePageList) |         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() |     // loadLinks gets the raw .mp4 or .m3u8 urls from the data parameter in the episodes class generated in load() | ||||||
|     // See TvSeriesEpisode(...) in this provider. |     // See TvSeriesEpisode(...) in this provider. | ||||||
|     // The data are usually links, but can be any other string to help aid loading the links. |     // 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, |         subtitleCallback: (SubtitleFile) -> Unit, | ||||||
|         callback: (ExtractorLink) -> Unit |         callback: (ExtractorLink) -> Unit | ||||||
|     ): Boolean { |     ): Boolean { | ||||||
|         // "?: return" is a very useful statement which returns if the iframe link isn't found. |         val doc = app.get(data).document | ||||||
|         val iframeLink = Jsoup.parse(app.get(data).text).selectFirst(".tab-video")?.attr("data-video") ?: return false |         val info = doc.select("div.tabs-video li").text() | ||||||
| 
 |         if (info.contains("Latino")) { | ||||||
|         // In this case the video player is a vidstream clone and can be handled by the vidstream extractor. |             doc.select(".server-item-1 li").apmap { | ||||||
|         // This case is a both unorthodox and you normally do not call extractors as they detect the url returned and does the rest. |                 val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play") | ||||||
|         val vidstreamObject = Pelisplus(pelisplusExtractorUrl ?: mainUrl) |                 loadExtractor(serverid, data, callback) | ||||||
|         // https://vidembed.cc/streaming.php?id=MzUwNTY2&... -> MzUwNTY2 |                 if (serverid.contains("pelisplus.icu")) { | ||||||
|         val id = Regex("""id=([^?]*)""").find(iframeLink)?.groupValues?.get(1) |                     getPelisStream(serverid, callback) | ||||||
| 
 |  | ||||||
|         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] |  | ||||||
|                         ) |  | ||||||
|                     ) |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         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 |         return true | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.loadExtractor | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class PinoyHDXyzProvider : MainAPI() { | class PinoyHDXyzProvider : MainAPI() { | ||||||
|     override val name = "Pinoy-HD" |     override var name = "Pinoy-HD" | ||||||
|     override val mainUrl = "https://www.pinoy-hd.xyz" |     override var mainUrl = "https://www.pinoy-hd.xyz" | ||||||
|     override val lang = "tl" |     override val lang = "tl" | ||||||
|     override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) |     override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) | ||||||
|     override val hasDownloadSupport = true |     override val hasDownloadSupport = true | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| import java.lang.Exception | import java.lang.Exception | ||||||
| 
 | 
 | ||||||
| class PinoyMoviePediaProvider : MainAPI() { | class PinoyMoviePediaProvider : MainAPI() { | ||||||
|     override val name = "Pinoy Moviepedia" |     override var name = "Pinoy Moviepedia" | ||||||
|     override val mainUrl = "https://pinoymoviepedia.ru" |     override var mainUrl = "https://pinoymoviepedia.ru" | ||||||
|     override val lang = "tl" |     override val lang = "tl" | ||||||
|     override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) |     override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) | ||||||
|     override val hasDownloadSupport = true |     override val hasDownloadSupport = true | ||||||
|  |  | ||||||
|  | @ -13,8 +13,8 @@ import org.jsoup.select.Elements | ||||||
| import java.lang.Exception | import java.lang.Exception | ||||||
| 
 | 
 | ||||||
| class PinoyMoviesEsProvider : MainAPI() { | class PinoyMoviesEsProvider : MainAPI() { | ||||||
|     override val name = "Pinoy Movies" |     override var name = "Pinoy Movies" | ||||||
|     override val mainUrl = "https://pinoymovies.es" |     override var mainUrl = "https://pinoymovies.es" | ||||||
|     override val lang = "tl" |     override val lang = "tl" | ||||||
|     override val supportedTypes = setOf(TvType.Movie) |     override val supportedTypes = setOf(TvType.Movie) | ||||||
|     override val hasDownloadSupport = false |     override val hasDownloadSupport = false | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.loadExtractor | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class SeriesflixProvider : MainAPI() { | class SeriesflixProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://seriesflix.video" |     override var mainUrl = "https://seriesflix.video" | ||||||
|     override val name = "Seriesflix" |     override var name = "Seriesflix" | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|  |  | ||||||
|  | @ -21,9 +21,18 @@ import org.jsoup.nodes.Element | ||||||
| import java.net.URI | import java.net.URI | ||||||
| import kotlin.system.measureTimeMillis | import kotlin.system.measureTimeMillis | ||||||
| 
 | 
 | ||||||
| class SflixProvider(providerUrl: String, providerName: String) : MainAPI() { | class DopeboxProvider : SflixProvider() { | ||||||
|     override val mainUrl = providerUrl |     override var mainUrl = "https://dopebox.to" | ||||||
|     override val name = providerName |     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 hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class SoaptwoDayProvider:MainAPI() { | class SoaptwoDayProvider:MainAPI() { | ||||||
|     override val mainUrl = "https://secretlink.xyz" //Probably a rip off, but it has no captcha |     override var mainUrl = "https://secretlink.xyz" //Probably a rip off, but it has no captcha | ||||||
|     override val name = "Soap2Day" |     override var name = "Soap2Day" | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = true |     override val hasChromecastSupport = true | ||||||
|     override val hasDownloadSupport = true |     override val hasDownloadSupport = true | ||||||
|  |  | ||||||
|  | @ -12,8 +12,8 @@ import com.lagradost.cloudstream3.utils.SubtitleHelper | ||||||
| class TrailersTwoProvider : TmdbProvider() { | class TrailersTwoProvider : TmdbProvider() { | ||||||
|     val user = "cloudstream" |     val user = "cloudstream" | ||||||
|     override val apiName = "Trailers.to" |     override val apiName = "Trailers.to" | ||||||
|     override val name = "Trailers.to" |     override var name = "Trailers.to" | ||||||
|     override val mainUrl = "https://trailers.to" |     override var mainUrl = "https://trailers.to" | ||||||
|     override val useMetaLoadResponse = true |     override val useMetaLoadResponse = true | ||||||
|     override val instantLinkLoading = true |     override val instantLinkLoading = true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,8 +12,8 @@ import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class TwoEmbedProvider : TmdbProvider() { | class TwoEmbedProvider : TmdbProvider() { | ||||||
|     override val apiName = "2Embed" |     override val apiName = "2Embed" | ||||||
|     override val name = "2Embed" |     override var name = "2Embed" | ||||||
|     override val mainUrl = "https://www.2embed.ru" |     override var mainUrl = "https://www.2embed.ru" | ||||||
|     override val useMetaLoadResponse = true |     override val useMetaLoadResponse = true | ||||||
|     override val instantLinkLoading = false |     override val instantLinkLoading = false | ||||||
|     override val supportedTypes = setOf( |     override val supportedTypes = setOf( | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| class VMoveeProvider : MainAPI() { | class VMoveeProvider : MainAPI() { | ||||||
|     override val name = "VMovee" |     override var name = "VMovee" | ||||||
|     override val mainUrl = "https://www.vmovee.watch" |     override var mainUrl = "https://www.vmovee.watch" | ||||||
| 
 | 
 | ||||||
|     override val supportedTypes = setOf(TvType.Movie) |     override val supportedTypes = setOf(TvType.Movie) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| // referer = https://vf-film.org, USERAGENT ALSO REQUIRED | // referer = https://vf-film.org, USERAGENT ALSO REQUIRED | ||||||
| class VfFilmProvider : MainAPI() { | class VfFilmProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://vf-film.me" |     override var mainUrl = "https://vf-film.me" | ||||||
|     override val name = "vf-film.me" |     override var name = "vf-film.me" | ||||||
|     override val lang = "fr" |     override val lang = "fr" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = false |     override val hasMainPage = false | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| // referer = https://vf-serie.org, USERAGENT ALSO REQUIRED | // referer = https://vf-serie.org, USERAGENT ALSO REQUIRED | ||||||
| class VfSerieProvider : MainAPI() { | class VfSerieProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://vf-serie.org" |     override var mainUrl = "https://vf-serie.org" | ||||||
|     override val name = "vf-serie.org" |     override var name = "vf-serie.org" | ||||||
|     override val lang = "fr" |     override val lang = "fr" | ||||||
| 
 | 
 | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|  |  | ||||||
|  | @ -7,10 +7,10 @@ import com.lagradost.cloudstream3.TvType | ||||||
|  */ |  */ | ||||||
| class VidEmbedProvider : VidstreamProviderTemplate() { | class VidEmbedProvider : VidstreamProviderTemplate() { | ||||||
|     // mainUrl is good to have as a holder for the url to make future changes easier. |     // 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. |     // 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( |     override val homePageUrlList: List<String> = listOf( | ||||||
|         mainUrl, |         mainUrl, | ||||||
|  |  | ||||||
|  | @ -10,8 +10,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.loadExtractor | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 
 | 
 | ||||||
| class WatchAsianProvider : MainAPI() { | class WatchAsianProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://watchasian.sh" |     override var mainUrl = "https://watchasian.sh" | ||||||
|     override val name = "WatchAsian" |     override var name = "WatchAsian" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val hasChromecastSupport = false |     override val hasChromecastSupport = false | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import com.lagradost.cloudstream3.utils.extractorApis | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class FrenchStreamProvider : MainAPI() { | class FrenchStreamProvider : MainAPI() { | ||||||
|     override val mainUrl = "https://french-stream.re" |     override var mainUrl = "https://french-stream.re" | ||||||
|     override val name = "French Stream" |     override var name = "French Stream" | ||||||
|     override val hasQuickSearch = false |     override val hasQuickSearch = false | ||||||
|     override val hasMainPage = true |     override val hasMainPage = true | ||||||
|     override val lang = "fr" |     override val lang = "fr" | ||||||
|  |  | ||||||
|  | @ -26,11 +26,11 @@ import java.net.URL | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class AniListApi(index: Int) : AccountManager(index), SyncAPI { | class AniListApi(index: Int) : AccountManager(index), SyncAPI { | ||||||
|     override val name = "AniList" |     override var name = "AniList" | ||||||
|     override val key = "6871" |     override val key = "6871" | ||||||
|     override val redirectUrl = "anilistlogin" |     override val redirectUrl = "anilistlogin" | ||||||
|     override val idPrefix = "anilist" |     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 val icon = R.drawable.ic_anilist_icon | ||||||
| 
 | 
 | ||||||
|     override fun loginInfo(): OAuth2API.LoginInfo? { |     override fun loginInfo(): OAuth2API.LoginInfo? { | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ import com.lagradost.cloudstream3.syncproviders.OAuth2API | ||||||
| //TODO dropbox sync | //TODO dropbox sync | ||||||
| class Dropbox : OAuth2API { | class Dropbox : OAuth2API { | ||||||
|     override val idPrefix = "dropbox" |     override val idPrefix = "dropbox" | ||||||
|     override val name = "Dropbox" |     override var name = "Dropbox" | ||||||
|     override val key = "zlqsamadlwydvb2" |     override val key = "zlqsamadlwydvb2" | ||||||
|     override val redirectUrl = "dropboxlogin" |     override val redirectUrl = "dropboxlogin" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -31,11 +31,11 @@ import java.util.* | ||||||
| const val MAL_MAX_SEARCH_LIMIT = 25 | const val MAL_MAX_SEARCH_LIMIT = 25 | ||||||
| 
 | 
 | ||||||
| class MALApi(index: Int) : AccountManager(index), SyncAPI { | class MALApi(index: Int) : AccountManager(index), SyncAPI { | ||||||
|     override val name = "MAL" |     override var name = "MAL" | ||||||
|     override val key = "1714d6f2f4f7cc19644384f8c4629910" |     override val key = "1714d6f2f4f7cc19644384f8c4629910" | ||||||
|     override val redirectUrl = "mallogin" |     override val redirectUrl = "mallogin" | ||||||
|     override val idPrefix = "mal" |     override val idPrefix = "mal" | ||||||
|     override val mainUrl = "https://myanimelist.net" |     override var mainUrl = "https://myanimelist.net" | ||||||
|     override val icon = R.drawable.mal_logo |     override val icon = R.drawable.mal_logo | ||||||
| 
 | 
 | ||||||
|     override fun logOut() { |     override fun logOut() { | ||||||
|  |  | ||||||
|  | @ -6,10 +6,10 @@ import com.lagradost.cloudstream3.utils.Qualities | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| class NyaaProvider : MainAPI() { | class NyaaProvider : MainAPI() { | ||||||
|     override val name = "Nyaa" |     override var name = "Nyaa" | ||||||
|     override val hasChromecastSupport = false |     override val hasChromecastSupport = false | ||||||
| 
 | 
 | ||||||
|     override val mainUrl = "https://nyaa.si" |     override var mainUrl = "https://nyaa.si" | ||||||
|     override val supportedTypes = setOf(TvType.Torrent) |     override val supportedTypes = setOf(TvType.Torrent) | ||||||
|     override val vpnStatus = VPNStatus.Torrent |     override val vpnStatus = VPNStatus.Torrent | ||||||
|     override val instantLinkLoading = true |     override val instantLinkLoading = true | ||||||
|  |  | ||||||
|  | @ -11,11 +11,11 @@ class APIRepository(val api: MainAPI) { | ||||||
|         var dubStatusActive = HashSet<DubStatus>() |         var dubStatusActive = HashSet<DubStatus>() | ||||||
| 
 | 
 | ||||||
|         val noneApi = object : MainAPI() { |         val noneApi = object : MainAPI() { | ||||||
|             override val name = "None" |             override var name = "None" | ||||||
|             override val supportedTypes = emptySet<TvType>() |             override val supportedTypes = emptySet<TvType>() | ||||||
|         } |         } | ||||||
|         val randomApi = object : MainAPI() { |         val randomApi = object : MainAPI() { | ||||||
|             override val name = "Random" |             override var name = "Random" | ||||||
|             override val supportedTypes = emptySet<TvType>() |             override val supportedTypes = emptySet<TvType>() | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -339,14 +339,21 @@ abstract class AbstractPlayerFragment( | ||||||
|             SubtitlesFragment.applyStyleEvent += ::onSubStyleChanged |             SubtitlesFragment.applyStyleEvent += ::onSubStyleChanged | ||||||
| 
 | 
 | ||||||
|             try { |             try { | ||||||
|                 context?.let { |                 context?.let { ctx -> | ||||||
|                     val settingsManager = PreferenceManager.getDefaultSharedPreferences( |                     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) { |             } catch (e: Exception) { | ||||||
|                 logError(e) |                 logError(e) | ||||||
|  |  | ||||||
|  | @ -39,8 +39,9 @@ const val TAG = "CS3ExoPlayer" | ||||||
| class CS3IPlayer : IPlayer { | class CS3IPlayer : IPlayer { | ||||||
|     private var isPlaying = false |     private var isPlaying = false | ||||||
|     private var exoPlayer: ExoPlayer? = null |     private var exoPlayer: ExoPlayer? = null | ||||||
|     var cacheSize = 300L * 1024L * 1024L // 300 mb |     var cacheSize = 0L | ||||||
|     private val simpleCacheSize : Long get() = cacheSize / 2 // idk chosen at random kinda |     var simpleCacheSize = 0L | ||||||
|  |     var videoBufferMs = 0L | ||||||
| 
 | 
 | ||||||
|     private val seekActionTime = 30000L |     private val seekActionTime = 30000L | ||||||
| 
 | 
 | ||||||
|  | @ -423,6 +424,7 @@ class CS3IPlayer : IPlayer { | ||||||
|             playBackSpeed: Float, |             playBackSpeed: Float, | ||||||
|             subtitleOffset: Long, |             subtitleOffset: Long, | ||||||
|             cacheSize: Long, |             cacheSize: Long, | ||||||
|  |             videoBufferMs: Long, | ||||||
|             playWhenReady: Boolean = true, |             playWhenReady: Boolean = true, | ||||||
|             cacheFactory: CacheDataSource.Factory? = null, |             cacheFactory: CacheDataSource.Factory? = null, | ||||||
|             trackSelector: TrackSelector? = null, |             trackSelector: TrackSelector? = null, | ||||||
|  | @ -460,10 +462,11 @@ class CS3IPlayer : IPlayer { | ||||||
|                             ) |                             ) | ||||||
|                             .setBufferDurationsMs( |                             .setBufferDurationsMs( | ||||||
|                                 DefaultLoadControl.DEFAULT_MIN_BUFFER_MS, |                                 DefaultLoadControl.DEFAULT_MIN_BUFFER_MS, | ||||||
|                                 maxOf( |                                 if(videoBufferMs <= 0) { | ||||||
|                                     DefaultLoadControl.DEFAULT_MAX_BUFFER_MS, |                                     DefaultLoadControl.DEFAULT_MAX_BUFFER_MS | ||||||
|                                     ((cacheSize * 75L) / 32768L).toInt() |                                 } else { | ||||||
|                                 ), // 500mb = 20min |                                     videoBufferMs.toInt() | ||||||
|  |                                 }, | ||||||
|                                 DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS, |                                 DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS, | ||||||
|                                 DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS |                                 DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS | ||||||
|                             ).build() |                             ).build() | ||||||
|  | @ -574,6 +577,7 @@ class CS3IPlayer : IPlayer { | ||||||
|                 playbackPosition, |                 playbackPosition, | ||||||
|                 playBackSpeed, |                 playBackSpeed, | ||||||
|                 cacheSize = cacheSize, |                 cacheSize = cacheSize, | ||||||
|  |                 videoBufferMs = videoBufferMs, | ||||||
|                 playWhenReady = isPlaying, // this keep the current state of the player |                 playWhenReady = isPlaying, // this keep the current state of the player | ||||||
|                 cacheFactory = cacheFactory, |                 cacheFactory = cacheFactory, | ||||||
|                 subtitleOffset = currentSubtitleOffset |                 subtitleOffset = currentSubtitleOffset | ||||||
|  |  | ||||||
|  | @ -22,7 +22,6 @@ import com.hippo.unifile.UniFile | ||||||
| import com.lagradost.cloudstream3.APIHolder.apis | import com.lagradost.cloudstream3.APIHolder.apis | ||||||
| import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings | import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings | ||||||
| import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings | import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings | ||||||
| import com.lagradost.cloudstream3.APIHolder.restrictedApis |  | ||||||
| import com.lagradost.cloudstream3.AcraApplication | import com.lagradost.cloudstream3.AcraApplication | ||||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey | import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey | ||||||
| import com.lagradost.cloudstream3.CommonActivity.setLocale | import com.lagradost.cloudstream3.CommonActivity.setLocale | ||||||
|  | @ -205,26 +204,105 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     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?) { |     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { | ||||||
|         hideKeyboard() |         hideKeyboard() | ||||||
|         setPreferencesFromResource(R.xml.settings, rootKey) |         setPreferencesFromResource(R.xml.settings, rootKey) | ||||||
|         val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()) |         val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()) | ||||||
| 
 | 
 | ||||||
|         getPref(R.string.video_cache_key)?.setOnPreferenceClickListener { |         getPref(R.string.video_buffer_length_key)?.setOnPreferenceClickListener { | ||||||
|             val prefNames = resources.getStringArray(R.array.video_cache_size_names) |             val prefNames = resources.getStringArray(R.array.video_buffer_length_names) | ||||||
|             val prefValues = resources.getIntArray(R.array.video_cache_size_values) |             val prefValues = resources.getIntArray(R.array.video_buffer_length_values) | ||||||
| 
 | 
 | ||||||
|             val currentPrefSize = |             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(), |                 prefNames.toList(), | ||||||
|                 prefValues.indexOf(currentPrefSize), |                 prefValues.indexOf(currentPrefSize), | ||||||
|                 getString(R.string.video_cache_settings), |                 getString(R.string.video_buffer_length_settings), | ||||||
|                 true, |                 true, | ||||||
|                 {}) { |                 {}) { | ||||||
|                 settingsManager.edit() |                 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() |                     .apply() | ||||||
|             } |             } | ||||||
|             return@setOnPreferenceClickListener true |             return@setOnPreferenceClickListener true | ||||||
|  | @ -301,9 +379,6 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|                 for (api in apis) { |                 for (api in apis) { | ||||||
|                     allLangs.add(api.lang) |                     allLangs.add(api.lang) | ||||||
|                 } |                 } | ||||||
|                 for (api in restrictedApis) { |  | ||||||
|                     allLangs.add(api.lang) |  | ||||||
|                 } |  | ||||||
| 
 | 
 | ||||||
|                 val currentList = ArrayList<Int>() |                 val currentList = ArrayList<Int>() | ||||||
|                 for (i in current) { |                 for (i in current) { | ||||||
|  |  | ||||||
|  | @ -323,18 +323,25 @@ class SubtitlesFragment : Fragment() { | ||||||
|             val fontSizes = listOf( |             val fontSizes = listOf( | ||||||
|                 Pair(null, textView.context.getString(R.string.normal)), |                 Pair(null, textView.context.getString(R.string.normal)), | ||||||
|                 Pair(6f, "6$suffix"), |                 Pair(6f, "6$suffix"), | ||||||
|  |                 Pair(7f, "7$suffix"), | ||||||
|                 Pair(8f, "8$suffix"), |                 Pair(8f, "8$suffix"), | ||||||
|                 Pair(9f, "9$suffix"), |                 Pair(9f, "9$suffix"), | ||||||
|                 Pair(10f, "10$suffix"), |                 Pair(10f, "10$suffix"), | ||||||
|                 Pair(11f, "11$suffix"), |                 Pair(11f, "11$suffix"), | ||||||
|                 Pair(12f, "12$suffix"), |                 Pair(12f, "12$suffix"), | ||||||
|  |                 Pair(13f, "13$suffix"), | ||||||
|                 Pair(14f, "14$suffix"), |                 Pair(14f, "14$suffix"), | ||||||
|  |                 Pair(15f, "15$suffix"), | ||||||
|                 Pair(16f, "16$suffix"), |                 Pair(16f, "16$suffix"), | ||||||
|  |                 Pair(17f, "17$suffix"), | ||||||
|                 Pair(18f, "18$suffix"), |                 Pair(18f, "18$suffix"), | ||||||
|                 Pair(19f, "19$suffix"), |                 Pair(19f, "19$suffix"), | ||||||
|  |                 Pair(20f, "20$suffix"), | ||||||
|                 Pair(21f, "21$suffix"), |                 Pair(21f, "21$suffix"), | ||||||
|  |                 Pair(22f, "22$suffix"), | ||||||
|                 Pair(23f, "23$suffix"), |                 Pair(23f, "23$suffix"), | ||||||
|                 Pair(24f, "24$suffix"), |                 Pair(24f, "24$suffix"), | ||||||
|  |                 Pair(25f, "25$suffix"), | ||||||
|                 Pair(26f, "26$suffix"), |                 Pair(26f, "26$suffix"), | ||||||
|                 Pair(28f, "28$suffix"), |                 Pair(28f, "28$suffix"), | ||||||
|                 Pair(30f, "30$suffix"), |                 Pair(30f, "30$suffix"), | ||||||
|  |  | ||||||
|  | @ -112,6 +112,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
|     StreamSB7(), |     StreamSB7(), | ||||||
|     StreamSB8(), |     StreamSB8(), | ||||||
|     StreamSB9(), |     StreamSB9(), | ||||||
|  |     StreamSB10(), | ||||||
|    // Streamhub(), cause Streamhub2() works |    // Streamhub(), cause Streamhub2() works | ||||||
|     Streamhub2(), |     Streamhub2(), | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -232,7 +232,7 @@ | ||||||
|     <string name="dont_show_again">لا تظهر مرة أخرى</string> |     <string name="dont_show_again">لا تظهر مرة أخرى</string> | ||||||
|     <string name="update">تحديث</string> |     <string name="update">تحديث</string> | ||||||
|     <string name="watch_quality_pref">جودة المشاهدة المفضلة</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">DNS فوق HTTPS</string> | ||||||
|     <string name="dns_pref_summary">مفيد لتجاوز كتل مزود خدمة الإنترنت</string> |     <string name="dns_pref_summary">مفيد لتجاوز كتل مزود خدمة الإنترنت</string> | ||||||
| 	 | 	 | ||||||
|  |  | ||||||
|  | @ -186,7 +186,7 @@ | ||||||
| \n%s -> %s</string> | \n%s -> %s</string> | ||||||
|     <string name="filler" formatted="true">Épisode spécial</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="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="resize_fill">Étendre</string> | ||||||
|     <string name="legal_notice">Non-responsabilité</string> |     <string name="legal_notice">Non-responsabilité</string> | ||||||
|     <string name="primary_color_settings">Couleur principale</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="dont_show_again">Non mostrare di nuovo</string> | ||||||
|     <string name="update">Aggiorna</string> |     <string name="update">Aggiorna</string> | ||||||
|     <string name="watch_quality_pref">Risoluzione preferita</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">DNS over HTTPS</string> | ||||||
|     <string name="dns_pref_summary">Utile per bypassare i blocchi ISP</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="dont_show_again">Không hiển thị lại</string> | ||||||
|     <string name="update">Cập nhật</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="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="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> |     <string name="download_path_pref">Đường dẫn tải xuống</string> | ||||||
|  |  | ||||||
|  | @ -56,20 +56,88 @@ | ||||||
|         <item>1</item> |         <item>1</item> | ||||||
|         <item>2</item> |         <item>2</item> | ||||||
|     </array> |     </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>100MB</item> | ||||||
|  |         <item>150MB</item> | ||||||
|         <item>200MB</item> |         <item>200MB</item> | ||||||
|  |         <item>250MB</item> | ||||||
|         <item>300MB</item> |         <item>300MB</item> | ||||||
|  |         <item>350MB</item> | ||||||
|         <item>400MB</item> |         <item>400MB</item> | ||||||
|  |         <item>450MB</item> | ||||||
|         <item>500MB</item> |         <item>500MB</item> | ||||||
|     </array> |     </array> | ||||||
|     <array name="video_cache_size_values"> | 
 | ||||||
|  |     <array name="video_buffer_size_values"> | ||||||
|         <item>0</item> |         <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>100</item> | ||||||
|  |         <item>150</item> | ||||||
|         <item>200</item> |         <item>200</item> | ||||||
|  |         <item>250</item> | ||||||
|         <item>300</item> |         <item>300</item> | ||||||
|  |         <item>350</item> | ||||||
|         <item>400</item> |         <item>400</item> | ||||||
|  |         <item>450</item> | ||||||
|         <item>500</item> |         <item>500</item> | ||||||
|     </array> |     </array> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,10 @@ | ||||||
|     <string name="subtitle_settings_key" translatable="false">subtitle_settings_key</string> |     <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="subtitle_settings_chromecast_key" translatable="false">subtitle_settings_chromecast_key</string> | ||||||
|     <string name="quality_pref_key" translatable="false">quality_pref_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="prerelease_commit_hash" translatable="false">unknown_prerelease</string> | ||||||
|     <string name="use_system_brightness_key" translatable="false">use_system_brightness_key</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> |     <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="app_layout_key" translatable="false">app_layout_key</string> | ||||||
|     <string name="primary_color_key" translatable="false">primary_color_key</string> |     <string name="primary_color_key" translatable="false">primary_color_key</string> | ||||||
|     <string name="restore_key" translatable="false">restore_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="backup_key" translatable="false">backup_key</string> | ||||||
|     <string name="prefer_media_type_key" translatable="false">prefer_media_type_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> |     <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="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="storage_size_format" translatable="false" formatted="true">%s • %sGB</string> | ||||||
|     <string name="download_size_format" translatable="false" formatted="true">%sMB / %sMB</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="episode_name_format" translatable="false" formatted="true">%s %s</string> | ||||||
|     <string name="ffw_text_format" translatable="false" formatted="true">+%d</string> |     <string name="ffw_text_format" translatable="false" formatted="true">+%d</string> | ||||||
|     <string name="rew_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> | ||||||
| 
 | 
 | ||||||
|     <string name="restore_settings">Restore data from backup</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="backup_settings">Backup data</string> | ||||||
|     <string name="restore_success">Loaded backup file</string> |     <string name="restore_success">Loaded backup file</string> | ||||||
|     <string name="restore_failed_format" formatted="true">Failed to restore data from file %s</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="dont_show_again">Don\'t show again</string> | ||||||
|     <string name="update">Update</string> |     <string name="update">Update</string> | ||||||
|     <string name="watch_quality_pref">Preferred watch quality</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">DNS over HTTPS</string> | ||||||
|     <string name="dns_pref_summary">Useful for bypassing ISP blocks</string> |     <string name="dns_pref_summary">Useful for bypassing ISP blocks</string> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -20,10 +20,7 @@ | ||||||
|                 android:key="@string/quality_pref_key" |                 android:key="@string/quality_pref_key" | ||||||
|                 android:title="@string/watch_quality_pref" |                 android:title="@string/watch_quality_pref" | ||||||
|                 android:icon="@drawable/ic_baseline_hd_24" /> |                 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 |         <SwitchPreference | ||||||
|                 android:icon="@drawable/ic_baseline_picture_in_picture_alt_24" |                 android:icon="@drawable/ic_baseline_picture_in_picture_alt_24" | ||||||
|                 app:key="@string/pip_enabled_key" |                 app:key="@string/pip_enabled_key" | ||||||
|  | @ -66,6 +63,28 @@ | ||||||
|                 android:title="@string/double_tap_to_pause_settings" |                 android:title="@string/double_tap_to_pause_settings" | ||||||
|                 android:summary="@string/double_tap_to_pause_settings_des" |                 android:summary="@string/double_tap_to_pause_settings_des" | ||||||
|                 app:defaultValue="false" /> |                 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 |         <SwitchPreference | ||||||
|                 android:icon="@drawable/ic_baseline_brightness_7_24" |                 android:icon="@drawable/ic_baseline_brightness_7_24" | ||||||
|  | @ -179,6 +198,13 @@ | ||||||
|                 android:key="@string/restore_key" |                 android:key="@string/restore_key" | ||||||
|                 android:title="@string/restore_settings" /> |                 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 |         <Preference | ||||||
|                 android:key="@string/mal_key" |                 android:key="@string/mal_key" | ||||||
|                 android:icon="@drawable/mal_logo" /> |                 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue