mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	fillers
This commit is contained in:
		
							parent
							
								
									bc1653e8c1
								
							
						
					
					
						commit
						989d7666be
					
				
					 8 changed files with 178 additions and 33 deletions
				
			
		|  | @ -351,6 +351,7 @@ data class AnimeEpisode( | ||||||
|     val date: String? = null, |     val date: String? = null, | ||||||
|     val rating: Int? = null, |     val rating: Int? = null, | ||||||
|     val descript: String? = null, |     val descript: String? = null, | ||||||
|  |     val episode : Int? = null, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class TorrentLoadResponse( | data class TorrentLoadResponse( | ||||||
|  |  | ||||||
|  | @ -141,7 +141,7 @@ class EpisodeAdapter( | ||||||
|             localCard = card |             localCard = card | ||||||
| 
 | 
 | ||||||
|             val name = if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}" |             val name = if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}" | ||||||
|             episodeText.text = name |             episodeText.text = if(card.isFiller == true) episodeText.context.getString(R.string.filler_format).format(name) else name | ||||||
|             episodeText.isSelected = true // is needed for text repeating |             episodeText.isSelected = true // is needed for text repeating | ||||||
| 
 | 
 | ||||||
|             val displayPos = card.getDisplayPosition() |             val displayPos = card.getDisplayPosition() | ||||||
|  |  | ||||||
|  | @ -22,9 +22,11 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout | ||||||
| import androidx.core.content.ContextCompat | import androidx.core.content.ContextCompat | ||||||
| import androidx.core.content.FileProvider | import androidx.core.content.FileProvider | ||||||
| import androidx.core.text.color | import androidx.core.text.color | ||||||
|  | import androidx.core.view.isVisible | ||||||
| import androidx.core.widget.NestedScrollView | import androidx.core.widget.NestedScrollView | ||||||
| import androidx.fragment.app.Fragment | import androidx.fragment.app.Fragment | ||||||
| import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||||
|  | import androidx.preference.PreferenceManager | ||||||
| import androidx.recyclerview.widget.GridLayoutManager | import androidx.recyclerview.widget.GridLayoutManager | ||||||
| import androidx.recyclerview.widget.RecyclerView | import androidx.recyclerview.widget.RecyclerView | ||||||
| import com.google.android.gms.cast.framework.CastButtonFactory | import com.google.android.gms.cast.framework.CastButtonFactory | ||||||
|  | @ -35,6 +37,7 @@ import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.APIHolder.getApiFromName | import com.lagradost.cloudstream3.APIHolder.getApiFromName | ||||||
| import com.lagradost.cloudstream3.APIHolder.getId | import com.lagradost.cloudstream3.APIHolder.getId | ||||||
| import com.lagradost.cloudstream3.MainActivity.Companion.showToast | import com.lagradost.cloudstream3.MainActivity.Companion.showToast | ||||||
|  | import com.lagradost.cloudstream3.MainActivity.Companion.updateLocale | ||||||
| import com.lagradost.cloudstream3.mvvm.Resource | import com.lagradost.cloudstream3.mvvm.Resource | ||||||
| import com.lagradost.cloudstream3.mvvm.observe | import com.lagradost.cloudstream3.mvvm.observe | ||||||
| import com.lagradost.cloudstream3.ui.WatchType | import com.lagradost.cloudstream3.ui.WatchType | ||||||
|  | @ -92,6 +95,7 @@ data class ResultEpisode( | ||||||
|     val duration: Long, // duration in MS |     val duration: Long, // duration in MS | ||||||
|     val rating: Int?, |     val rating: Int?, | ||||||
|     val descript: String?, |     val descript: String?, | ||||||
|  |     val isFiller: Boolean?, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| fun ResultEpisode.getRealPosition(): Long { | fun ResultEpisode.getRealPosition(): Long { | ||||||
|  | @ -121,6 +125,7 @@ fun Context.buildResultEpisode( | ||||||
|     index: Int, |     index: Int, | ||||||
|     rating: Int?, |     rating: Int?, | ||||||
|     descript: String?, |     descript: String?, | ||||||
|  |     isFiller: Boolean?, | ||||||
| ): ResultEpisode { | ): ResultEpisode { | ||||||
|     val posDur = getViewPos(id) |     val posDur = getViewPos(id) | ||||||
|     return ResultEpisode( |     return ResultEpisode( | ||||||
|  | @ -136,6 +141,7 @@ fun Context.buildResultEpisode( | ||||||
|         posDur?.duration ?: 0, |         posDur?.duration ?: 0, | ||||||
|         rating, |         rating, | ||||||
|         descript, |         descript, | ||||||
|  |         isFiller | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -442,9 +448,11 @@ class ResultFragment : Fragment() { | ||||||
|                     if (isMovie) null else episodeClick.data.episode |                     if (isMovie) null else episodeClick.data.episode | ||||||
|                 ) |                 ) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|                 val folder = when (currentType) { |                 val folder = when (currentType) { | ||||||
|                     TvType.Anime -> "Anime/$titleName" |                     TvType.Anime -> "Anime/$titleName" | ||||||
|                     TvType.Movie -> "Movies" |                     TvType.Movie -> "Movies" | ||||||
|  |                     TvType.AnimeMovie -> "Movies" | ||||||
|                     TvType.TvSeries -> "TVSeries/$titleName" |                     TvType.TvSeries -> "TVSeries/$titleName" | ||||||
|                     TvType.ONA -> "ONA" |                     TvType.ONA -> "ONA" | ||||||
|                     TvType.Cartoon -> "Cartoons/$titleName" |                     TvType.Cartoon -> "Cartoons/$titleName" | ||||||
|  | @ -817,11 +825,22 @@ class ResultFragment : Fragment() { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         observe(viewModel.publicEpisodes) { episodes -> |         observe(viewModel.publicEpisodes) { episodes -> | ||||||
|             if (result_episodes == null || result_episodes.adapter == null) return@observe |             when (episodes) { | ||||||
|             currentEpisodes = episodes |                 is Resource.Failure -> { | ||||||
|             (result_episodes?.adapter as EpisodeAdapter?)?.cardList = episodes |                     result_episode_loading.isVisible = false | ||||||
|             (result_episodes?.adapter as EpisodeAdapter?)?.updateLayout() |                 } | ||||||
|             (result_episodes?.adapter as EpisodeAdapter?)?.notifyDataSetChanged() |                 is Resource.Loading -> { | ||||||
|  |                     result_episode_loading.isVisible = true | ||||||
|  |                 } | ||||||
|  |                 is Resource.Success -> { | ||||||
|  |                     result_episode_loading.isVisible = false | ||||||
|  |                     if (result_episodes == null || result_episodes.adapter == null) return@observe | ||||||
|  |                     currentEpisodes = episodes.value | ||||||
|  |                     (result_episodes?.adapter as EpisodeAdapter?)?.cardList = episodes.value | ||||||
|  |                     (result_episodes?.adapter as EpisodeAdapter?)?.updateLayout() | ||||||
|  |                     (result_episodes?.adapter as EpisodeAdapter?)?.notifyDataSetChanged() | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         observe(viewModel.selectedRange) { range -> |         observe(viewModel.selectedRange) { range -> | ||||||
|  | @ -856,6 +875,10 @@ class ResultFragment : Fragment() { | ||||||
|                 is Resource.Success -> { |                 is Resource.Success -> { | ||||||
|                     val d = data.value |                     val d = data.value | ||||||
|                     if (d is LoadResponse) { |                     if (d is LoadResponse) { | ||||||
|  |                         if (d !is AnimeLoadResponse && result_episode_loading.isVisible) { // no episode loading when not anime | ||||||
|  |                             result_episode_loading.isVisible = false | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|                         updateVisStatus(2) |                         updateVisStatus(2) | ||||||
| 
 | 
 | ||||||
|                         result_vpn?.text = when (api.vpnStatus) { |                         result_vpn?.text = when (api.vpnStatus) { | ||||||
|  | @ -1034,7 +1057,8 @@ class ResultFragment : Fragment() { | ||||||
|                                                         0L, |                                                         0L, | ||||||
|                                                         0L, |                                                         0L, | ||||||
|                                                         null, |                                                         null, | ||||||
|                                                         null |                                                         null, | ||||||
|  |                                                         null, | ||||||
|                                                     ) |                                                     ) | ||||||
|                                                 ) |                                                 ) | ||||||
|                                             ) |                                             ) | ||||||
|  | @ -1073,25 +1097,28 @@ class ResultFragment : Fragment() { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         val tempUrl = url |         context?.let { ctx -> | ||||||
|         if (tempUrl != null) { |             val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx) | ||||||
|             result_reload_connectionerror.setOnClickListener { |             val showFillers = settingsManager.getBoolean(ctx.getString(R.string.show_fillers_key), true) | ||||||
|                 viewModel.load(it.context, tempUrl, apiName) |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             result_reload_connection_open_in_browser.setOnClickListener { |             val tempUrl = url | ||||||
|                 val i = Intent(ACTION_VIEW) |             if (tempUrl != null) { | ||||||
|                 i.data = Uri.parse(tempUrl) |                 result_reload_connectionerror.setOnClickListener { | ||||||
|                 try { |                     viewModel.load(it.context, tempUrl, apiName, showFillers) | ||||||
|                     startActivity(i) |  | ||||||
|                 } catch (e: Exception) { |  | ||||||
|                     e.printStackTrace() |  | ||||||
|                 } |                 } | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             if (viewModel.resultResponse.value == null) { |                 result_reload_connection_open_in_browser.setOnClickListener { | ||||||
|                 context?.let { ctx -> |                     val i = Intent(ACTION_VIEW) | ||||||
|                     viewModel.load(ctx, tempUrl, apiName) |                     i.data = Uri.parse(tempUrl) | ||||||
|  |                     try { | ||||||
|  |                         startActivity(i) | ||||||
|  |                     } catch (e: Exception) { | ||||||
|  |                         e.printStackTrace() | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (viewModel.resultResponse.value == null) { | ||||||
|  |                     viewModel.load(ctx, tempUrl, apiName, showFillers) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason | ||||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState | import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState | ||||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos | import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.FillerEpisodeCheck.getFillerEpisodes | ||||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| import kotlinx.coroutines.launch | import kotlinx.coroutines.launch | ||||||
|  | @ -39,7 +40,7 @@ class ResultViewModel : ViewModel() { | ||||||
|     private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData() |     private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData() | ||||||
|     private val episodeById: MutableLiveData<HashMap<Int, Int>> = MutableLiveData() // lookup by ID to get Index |     private val episodeById: MutableLiveData<HashMap<Int, Int>> = MutableLiveData() // lookup by ID to get Index | ||||||
| 
 | 
 | ||||||
|     private val _publicEpisodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData() |     private val _publicEpisodes: MutableLiveData<Resource<List<ResultEpisode>>> = MutableLiveData() | ||||||
|     private val _publicEpisodesCount: MutableLiveData<Int> = MutableLiveData() // before the sorting |     private val _publicEpisodesCount: MutableLiveData<Int> = MutableLiveData() // before the sorting | ||||||
|     private val _rangeOptions: MutableLiveData<List<String>> = MutableLiveData() |     private val _rangeOptions: MutableLiveData<List<String>> = MutableLiveData() | ||||||
|     val selectedRange: MutableLiveData<String> = MutableLiveData() |     val selectedRange: MutableLiveData<String> = MutableLiveData() | ||||||
|  | @ -48,7 +49,7 @@ class ResultViewModel : ViewModel() { | ||||||
| 
 | 
 | ||||||
|     val resultResponse: LiveData<Resource<Any?>> get() = _resultResponse |     val resultResponse: LiveData<Resource<Any?>> get() = _resultResponse | ||||||
|     val episodes: LiveData<List<ResultEpisode>> get() = _episodes |     val episodes: LiveData<List<ResultEpisode>> get() = _episodes | ||||||
|     val publicEpisodes: LiveData<List<ResultEpisode>> get() = _publicEpisodes |     val publicEpisodes: LiveData<Resource<List<ResultEpisode>>> get() = _publicEpisodes | ||||||
|     val publicEpisodesCount: LiveData<Int> get() = _publicEpisodesCount |     val publicEpisodesCount: LiveData<Int> get() = _publicEpisodesCount | ||||||
| 
 | 
 | ||||||
|     private val dubStatus: MutableLiveData<DubStatus> = MutableLiveData() |     private val dubStatus: MutableLiveData<DubStatus> = MutableLiveData() | ||||||
|  | @ -106,7 +107,7 @@ class ResultViewModel : ViewModel() { | ||||||
|         val seasons = seasonTypes.toList().map { it.first }.sortedBy { it } |         val seasons = seasonTypes.toList().map { it.first }.sortedBy { it } | ||||||
|         seasonSelections.postValue(seasons) |         seasonSelections.postValue(seasons) | ||||||
|         if (seasons.isEmpty()) { // WHAT THE FUCK DID YOU DO????? HOW DID YOU DO THIS |         if (seasons.isEmpty()) { // WHAT THE FUCK DID YOU DO????? HOW DID YOU DO THIS | ||||||
|             _publicEpisodes.postValue(ArrayList()) |             _publicEpisodes.postValue(Resource.Success( ArrayList())) | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -156,7 +157,7 @@ class ResultViewModel : ViewModel() { | ||||||
|             selectedRange.postValue(allRange) |             selectedRange.postValue(allRange) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         _publicEpisodes.postValue(currentList) |         _publicEpisodes.postValue(Resource.Success( currentList)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun changeSeason(context: Context, selection: Int?) { |     fun changeSeason(context: Context, selection: Int?) { | ||||||
|  | @ -224,17 +225,18 @@ class ResultViewModel : ViewModel() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun filterName(name : String?) : String? { |     private fun filterName(name: String?): String? { | ||||||
|         if(name == null) return null |         if (name == null) return null | ||||||
|         Regex("[eE]pisode [0-9]*(.*)").find(name)?.groupValues?.get(1)?.let { |         Regex("[eE]pisode [0-9]*(.*)").find(name)?.groupValues?.get(1)?.let { | ||||||
|             if(it.isEmpty()) |             if (it.isEmpty()) | ||||||
|                 return null |                 return null | ||||||
|         } |         } | ||||||
|         return name |         return name | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun load(context: Context, url: String, apiName: String) = viewModelScope.launch { |     fun load(context: Context, url: String, apiName: String, showFillers : Boolean) = viewModelScope.launch { | ||||||
|         _resultResponse.postValue(Resource.Loading(url)) |         _resultResponse.postValue(Resource.Loading(url)) | ||||||
|  |         _publicEpisodes.postValue(Resource.Loading()) | ||||||
| 
 | 
 | ||||||
|         _apiName.postValue(apiName) |         _apiName.postValue(apiName) | ||||||
|         val api = getApiFromName(apiName) |         val api = getApiFromName(apiName) | ||||||
|  | @ -273,14 +275,17 @@ class ResultViewModel : ViewModel() { | ||||||
| 
 | 
 | ||||||
|                         val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes) |                         val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes) | ||||||
| 
 | 
 | ||||||
|  |                         val fillerEpisodes = if(showFillers) safeApiCall { getFillerEpisodes(d.name) } else null | ||||||
|  | 
 | ||||||
|                         if (dataList != null) { // TODO dub and sub at the same time |                         if (dataList != null) { // TODO dub and sub at the same time | ||||||
|                             val episodes = ArrayList<ResultEpisode>() |                             val episodes = ArrayList<ResultEpisode>() | ||||||
|                             for ((index, i) in dataList.withIndex()) { |                             for ((index, i) in dataList.withIndex()) { | ||||||
|  |                                 val episode = i.episode ?: (index + 1); | ||||||
|                                 episodes.add( |                                 episodes.add( | ||||||
|                                     context.buildResultEpisode( |                                     context.buildResultEpisode( | ||||||
|                                         filterName(i.name), |                                         filterName(i.name), | ||||||
|                                         i.posterUrl, |                                         i.posterUrl, | ||||||
|                                         index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE |                                         episode, | ||||||
|                                         null, // TODO FIX SEASON |                                         null, // TODO FIX SEASON | ||||||
|                                         i.url, |                                         i.url, | ||||||
|                                         apiName, |                                         apiName, | ||||||
|  | @ -288,6 +293,10 @@ class ResultViewModel : ViewModel() { | ||||||
|                                         index, |                                         index, | ||||||
|                                         i.rating, |                                         i.rating, | ||||||
|                                         i.descript, |                                         i.descript, | ||||||
|  |                                         if (fillerEpisodes is Resource.Success) fillerEpisodes.value?.let { | ||||||
|  |                                             it.contains(episode) && it[episode] == true | ||||||
|  |                                         } | ||||||
|  |                                             ?: false else false, | ||||||
|                                     ) |                                     ) | ||||||
|                                 ) |                                 ) | ||||||
|                             } |                             } | ||||||
|  | @ -309,7 +318,8 @@ class ResultViewModel : ViewModel() { | ||||||
|                                     (mainId + index + 1).hashCode(), |                                     (mainId + index + 1).hashCode(), | ||||||
|                                     index, |                                     index, | ||||||
|                                     i.rating, |                                     i.rating, | ||||||
|                                     i.descript |                                     i.descript, | ||||||
|  |                                     null, | ||||||
|                                 ) |                                 ) | ||||||
|                             ) |                             ) | ||||||
|                         } |                         } | ||||||
|  | @ -329,6 +339,7 @@ class ResultViewModel : ViewModel() { | ||||||
|                                     0, |                                     0, | ||||||
|                                     null, |                                     null, | ||||||
|                                     null, |                                     null, | ||||||
|  |                                     null, | ||||||
|                                 ) |                                 ) | ||||||
|                             ), -1 |                             ), -1 | ||||||
|                         ) |                         ) | ||||||
|  | @ -347,6 +358,7 @@ class ResultViewModel : ViewModel() { | ||||||
|                                     0, |                                     0, | ||||||
|                                     null, |                                     null, | ||||||
|                                     null, |                                     null, | ||||||
|  |                                     null, | ||||||
|                                 ) |                                 ) | ||||||
|                             ), -1 |                             ), -1 | ||||||
|                         ) |                         ) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,90 @@ | ||||||
|  | package com.lagradost.cloudstream3.utils | ||||||
|  | 
 | ||||||
|  | import org.jsoup.Jsoup | ||||||
|  | import java.util.* | ||||||
|  | import kotlin.collections.HashMap | ||||||
|  | 
 | ||||||
|  | object FillerEpisodeCheck { | ||||||
|  |     private const val MAIN_URL = "https://www.animefillerlist.com" | ||||||
|  | 
 | ||||||
|  |     var list: HashMap<String, String>? = null | ||||||
|  | 
 | ||||||
|  |     private fun fixName(name: String): String { | ||||||
|  |         return name.toLowerCase(Locale.ROOT)/*.replace(" ", "")*/.replace("-", " ").replace("[^a-zA-Z0-9 ]".toRegex(), "") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun getFillerList(): Boolean { | ||||||
|  |         if (list != null) return true | ||||||
|  |         try { | ||||||
|  |             val result = khttp.get("$MAIN_URL/shows") | ||||||
|  |             val documented = Jsoup.parse(result.text) | ||||||
|  |             val localHTMLList = documented.select("div#ShowList > div.Group > ul > li > a") | ||||||
|  |             val localList = HashMap<String, String>() | ||||||
|  |             for (i in localHTMLList) { | ||||||
|  |                 val name = i.text() | ||||||
|  | 
 | ||||||
|  |                 if (name.toLowerCase(Locale.ROOT).contains("manga only")) continue | ||||||
|  | 
 | ||||||
|  |                 val href = i.attr("href") | ||||||
|  |                 if (name.isNullOrEmpty() || href.isNullOrEmpty()) { | ||||||
|  |                     continue | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 val values = "(.*) \\((.*)\\)".toRegex().matchEntire(name)?.groups | ||||||
|  |                 if (values != null) { | ||||||
|  |                     for (index in 1 until values.size) { | ||||||
|  |                         val localName = values[index]?.value ?: continue | ||||||
|  |                         localList[fixName(localName)] = href | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     localList[fixName(name)] = href | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if (localList.size > 0) { | ||||||
|  |                 list = localList | ||||||
|  |                 return true | ||||||
|  |             } | ||||||
|  |         } catch (e: Exception) { | ||||||
|  |             e.printStackTrace() | ||||||
|  |         } | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun getFillerEpisodes(query: String): HashMap<Int, Boolean>? { | ||||||
|  |         try { | ||||||
|  |             if (!getFillerList()) return null | ||||||
|  |             val localList = list ?: return null | ||||||
|  | 
 | ||||||
|  |             // Strips these from the name | ||||||
|  |             val blackList = listOf( | ||||||
|  |                 "TV Dubbed", | ||||||
|  |                 "(Dub)", | ||||||
|  |                 "Subbed", | ||||||
|  |                 "(TV)", | ||||||
|  |                 "(Uncensored)", | ||||||
|  |                 "(Censored)", | ||||||
|  |                 "(\\d+)" // year | ||||||
|  |             ) | ||||||
|  |             val blackListRegex = | ||||||
|  |                 Regex(""" (${blackList.joinToString(separator = "|").replace("(", "\\(").replace(")", "\\)")})""") | ||||||
|  | 
 | ||||||
|  |             val realQuery = fixName(query.replace(blackListRegex, "")).replace("shippuuden", "shippuden") | ||||||
|  |             if (!localList.containsKey(realQuery)) return null | ||||||
|  |             val href = localList[realQuery]?.replace(MAIN_URL, "") ?: return null // JUST IN CASE | ||||||
|  |             val result = khttp.get("$MAIN_URL$href") | ||||||
|  |             val documented = Jsoup.parse(result.text) ?: return null | ||||||
|  |             val hashMap = HashMap<Int, Boolean>() | ||||||
|  |             documented.select("table.EpisodeList > tbody > tr").forEach { | ||||||
|  |                 val type = it.selectFirst("td.Type > span").text() == "Filler" | ||||||
|  |                 val episodeNumber = it.selectFirst("td.Number").text().toIntOrNull() | ||||||
|  |                 if (episodeNumber != null) { | ||||||
|  |                     hashMap[episodeNumber] = type | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return hashMap | ||||||
|  |         } catch (e: Exception) { | ||||||
|  |             e.printStackTrace() | ||||||
|  |             return null | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -435,6 +435,13 @@ | ||||||
|                     /> |                     /> | ||||||
|                 </LinearLayout> |                 </LinearLayout> | ||||||
| 
 | 
 | ||||||
|  |                 <androidx.core.widget.ContentLoadingProgressBar | ||||||
|  |                         style="@style/Widget.AppCompat.ProgressBar" | ||||||
|  |                         android:id="@+id/result_episode_loading" | ||||||
|  |                         android:layout_gravity="center" | ||||||
|  |                         android:layout_width="50dp" | ||||||
|  |                         android:layout_height="50dp"> | ||||||
|  |                 </androidx.core.widget.ContentLoadingProgressBar> | ||||||
|                 <androidx.recyclerview.widget.RecyclerView |                 <androidx.recyclerview.widget.RecyclerView | ||||||
|                         android:layout_marginTop="0dp" |                         android:layout_marginTop="0dp" | ||||||
|                         android:paddingBottom="100dp" |                         android:paddingBottom="100dp" | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ | ||||||
|     <string name="double_tap_enabled_key" translatable="false">double_tap_enabled_key</string> |     <string name="double_tap_enabled_key" translatable="false">double_tap_enabled_key</string> | ||||||
|     <string name="swipe_vertical_enabled_key" translatable="false">swipe_vertical_enabled_key</string> |     <string name="swipe_vertical_enabled_key" translatable="false">swipe_vertical_enabled_key</string> | ||||||
|     <string name="display_sub_key" translatable="false">display_sub_key</string> |     <string name="display_sub_key" translatable="false">display_sub_key</string> | ||||||
|  |     <string name="show_fillers_key" translatable="false">show_fillers_key</string> | ||||||
| 
 | 
 | ||||||
|     <!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG --> |     <!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG --> | ||||||
|     <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> | ||||||
|  | @ -48,6 +49,7 @@ | ||||||
|     <string name="player_speed_text_format" formatted="true">Speed (%.2fx)</string> |     <string name="player_speed_text_format" formatted="true">Speed (%.2fx)</string> | ||||||
|     <string name="rated_format" formatted="true">Rated: %.1f</string> |     <string name="rated_format" formatted="true">Rated: %.1f</string> | ||||||
|     <string name="new_update_format" formatted="true">New update found!\n%s -> %s</string> |     <string name="new_update_format" formatted="true">New update found!\n%s -> %s</string> | ||||||
|  |     <string name="filler_format" formatted="true">(Filler) %s</string> | ||||||
| 
 | 
 | ||||||
|     <string name="app_name">CloudStream</string> |     <string name="app_name">CloudStream</string> | ||||||
|     <string name="title_home">Home</string> |     <string name="title_home">Home</string> | ||||||
|  | @ -169,6 +171,7 @@ | ||||||
|     <string name="advanced_search_des">Gives you the search results separated by provider</string> |     <string name="advanced_search_des">Gives you the search results separated by provider</string> | ||||||
|     <string name="bug_report_settings_off">Only sends data on crashes</string> |     <string name="bug_report_settings_off">Only sends data on crashes</string> | ||||||
|     <string name="bug_report_settings_on">Sends no data</string> |     <string name="bug_report_settings_on">Sends no data</string> | ||||||
|  |     <string name="show_fillers_settings">Show filler episode for anime</string> | ||||||
|     <string name="updates_settings">Show app updates</string> |     <string name="updates_settings">Show app updates</string> | ||||||
|     <string name="updates_settings_des">Automatically search for new updates on start</string> |     <string name="updates_settings_des">Automatically search for new updates on start</string> | ||||||
|     <string name="uprereleases_settings">Update to prereleases</string> |     <string name="uprereleases_settings">Update to prereleases</string> | ||||||
|  |  | ||||||
|  | @ -103,6 +103,11 @@ | ||||||
|                 android:title="@string/app_language" |                 android:title="@string/app_language" | ||||||
|                 android:icon="@drawable/ic_baseline_language_24"> |                 android:icon="@drawable/ic_baseline_language_24"> | ||||||
|         </Preference> |         </Preference> | ||||||
|  |         <SwitchPreference | ||||||
|  |                 android:key="@string/show_fillers_key" | ||||||
|  |                 android:icon="@drawable/ic_baseline_skip_next_24" | ||||||
|  |                 android:title="@string/show_fillers_settings" | ||||||
|  |                 android:defaultValue="true"/> | ||||||
|         <SwitchPreference |         <SwitchPreference | ||||||
|                 android:key="acra.disable" |                 android:key="acra.disable" | ||||||
|                 android:icon="@drawable/ic_baseline_bug_report_24" |                 android:icon="@drawable/ic_baseline_bug_report_24" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue