Add internal support for subtitle headers + season names

This commit is contained in:
Blatzar 2022-09-10 19:59:37 +02:00
parent c8cd6f921d
commit 53965b13fb
13 changed files with 71 additions and 30 deletions

View file

@ -13,7 +13,8 @@ class AbstractSubtitleEntities {
var epNumber: Int? = null,
var seasonNumber: Int? = null,
var year: Int? = null,
var isHearingImpaired: Boolean = false
var isHearingImpaired: Boolean = false,
var headers: Map<String, String> = emptyMap()
)
data class SubtitleSearch(

View file

@ -4,6 +4,7 @@ import android.util.Log
import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.imdbUrlToIdNullable
import com.lagradost.cloudstream3.network.CloudflareKiller
import com.lagradost.cloudstream3.subtitles.AbstractSubApi
import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities
import com.lagradost.cloudstream3.utils.SubtitleHelper
@ -19,6 +20,8 @@ class IndexSubtitleApi : AbstractSubApi {
override fun logOut() {}
private val interceptor = CloudflareKiller()
companion object {
const val host = "https://indexsubtitle.com"
const val TAG = "INDEXSUBS"
@ -122,12 +125,13 @@ class IndexSubtitleApi : AbstractSubApi {
type = if (seasonNum > 0) TvType.TvSeries else TvType.Movie,
epNumber = epNum,
seasonNumber = seasonNum,
year = yearNum
year = yearNum,
headers = interceptor.getCookieHeaders(link).toMap()
)
)
}
val document = app.get("$host/?search=$queryText").document
val document = app.get("$host/?search=$queryText", interceptor = interceptor).document
document.select("div.my-3.p-3 div.media").map { block ->
if (seasonNum > 0) {
@ -159,7 +163,7 @@ class IndexSubtitleApi : AbstractSubApi {
val urlItem = fixUrl(
it.selectFirst("a")!!.attr("href")
)
val itemDoc = app.get(urlItem).document
val itemDoc = app.get(urlItem, interceptor = interceptor).document
val id = imdbUrlToIdNullable(
itemDoc.selectFirst("div.d-flex span.badge.badge-primary")?.parent()
?.attr("href")
@ -198,7 +202,7 @@ class IndexSubtitleApi : AbstractSubApi {
val results = mutableListOf<AbstractSubtitleEntities.SubtitleEntity>()
urlItems.forEach { url ->
val request = app.get(url)
val request = app.get(url, interceptor = interceptor)
if (request.isSuccessful) {
request.document.select("div.my-3.p-3 div.media").map { block ->
if (block.select("span.d-block span[data-original-title=Language]").text()
@ -231,7 +235,7 @@ class IndexSubtitleApi : AbstractSubApi {
val seasonNum = data.seasonNumber
val epNum = data.epNumber
val req = app.get(data.data)
val req = app.get(data.data, interceptor = interceptor)
if (req.isSuccessful) {
val document = req.document

View file

@ -20,6 +20,7 @@ import com.google.android.exoplayer2.ui.SubtitleView
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.upstream.HttpDataSource
import com.google.android.exoplayer2.upstream.cache.CacheDataSource
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor
import com.google.android.exoplayer2.upstream.cache.SimpleCache
@ -442,7 +443,14 @@ class CS3IPlayer : IPlayer {
var requestSubtitleUpdate: (() -> Unit)? = null
private fun createOnlineSource(link: ExtractorLink): DataSource.Factory {
private fun createOnlineSource(headers: Map<String, String>): HttpDataSource.Factory {
val source = OkHttpDataSource.Factory(app.baseClient).setUserAgent(USER_AGENT)
return source.apply {
setDefaultRequestProperties(headers)
}
}
private fun createOnlineSource(link: ExtractorLink): HttpDataSource.Factory {
val provider = getApiFromNameNull(link.source)
val interceptor = provider?.getVideoInterceptor(link)
@ -813,7 +821,8 @@ class CS3IPlayer : IPlayer {
// See setPreferredTextLanguage
it.language!!,
SubtitleOrigin.EMBEDDED_IN_VIDEO,
it.sampleMimeType ?: MimeTypes.APPLICATION_SUBRIP
it.sampleMimeType ?: MimeTypes.APPLICATION_SUBRIP,
emptyMap()
)
}
@ -981,9 +990,10 @@ class CS3IPlayer : IPlayer {
val mediaItem = getMediaItem(MimeTypes.VIDEO_MP4, data.uri)
val offlineSourceFactory = context.createOfflineSource()
val onlineSourceFactory = createOnlineSource(emptyMap())
val (subSources, activeSubtitles) = getSubSources(
onlineSourceFactory = offlineSourceFactory,
onlineSourceFactory = onlineSourceFactory,
offlineSourceFactory = offlineSourceFactory,
subtitleHelper,
)
@ -997,7 +1007,7 @@ class CS3IPlayer : IPlayer {
}
private fun getSubSources(
onlineSourceFactory: DataSource.Factory?,
onlineSourceFactory: HttpDataSource.Factory?,
offlineSourceFactory: DataSource.Factory?,
subHelper: PlayerSubtitleHelper,
): Pair<List<SingleSampleMediaSource>, List<SubtitleData>> {
@ -1021,7 +1031,10 @@ class CS3IPlayer : IPlayer {
SubtitleOrigin.URL -> {
if (onlineSourceFactory != null) {
activeSubtitles.add(sub)
SingleSampleMediaSource.Factory(onlineSourceFactory)
SingleSampleMediaSource.Factory(onlineSourceFactory.apply {
if (sub.headers.isNotEmpty())
this.setDefaultRequestProperties(sub.headers)
})
.createMediaSource(subConfig, C.TIME_UNSET)
} else {
null

View file

@ -84,7 +84,8 @@ class DownloadFileGenerator(
realName.ifBlank { ctx.getString(R.string.default_subtitles) },
file.second.toString(),
SubtitleOrigin.DOWNLOADED_FILE,
name.toSubtitleMimeType()
name.toSubtitleMimeType(),
emptyMap()
)
)
}

View file

@ -399,7 +399,8 @@ class GeneratorPlayer : FullScreenPlayer() {
name = getName(currentSubtitle, true),
url = url,
origin = SubtitleOrigin.URL,
mimeType = url.toSubtitleMimeType()
mimeType = url.toSubtitleMimeType(),
headers = currentSubtitle.headers
)
runOnMainThread {
addAndSelectSubtitles(subtitle)
@ -483,7 +484,8 @@ class GeneratorPlayer : FullScreenPlayer() {
name,
uri.toString(),
SubtitleOrigin.DOWNLOADED_FILE,
name.toSubtitleMimeType()
name.toSubtitleMimeType(),
emptyMap()
)
addAndSelectSubtitles(subtitleData)

View file

@ -29,12 +29,14 @@ enum class SubtitleOrigin {
/**
* @param name To be displayed in the player
* @param url Url for the subtitle, when EMBEDDED_IN_VIDEO this variable is used as the real backend language
* @param headers if empty it will use the base onlineDataSource headers else only the specified headers
* */
data class SubtitleData(
val name: String,
val url: String,
val origin: SubtitleOrigin,
val mimeType: String,
val headers: Map<String, String>
)
class PlayerSubtitleHelper {
@ -71,7 +73,8 @@ class PlayerSubtitleHelper {
name = subtitleFile.lang,
url = subtitleFile.url,
origin = SubtitleOrigin.URL,
mimeType = subtitleFile.url.toSubtitleMimeType()
mimeType = subtitleFile.url.toSubtitleMimeType(),
headers = emptyMap()
)
}
}

View file

@ -409,6 +409,11 @@ class ResultViewModel2 : ViewModel() {
private const val EPISODE_RANGE_SIZE = 20
private const val EPISODE_RANGE_OVERLOAD = 30
private fun List<SeasonData>?.getSeason(season: Int?): SeasonData? {
if (season == null) return null
return this?.firstOrNull { it.season == season }
}
private fun filterName(name: String?): String? {
if (name == null) return null
Regex("[eE]pisode [0-9]*(.*)").find(name)?.groupValues?.get(1)?.let {
@ -1476,11 +1481,18 @@ class ResultViewModel2 : ViewModel() {
if (isMovie || currentSeasons.size <= 1) null else
when (indexer.season) {
0 -> txt(R.string.no_season)
else -> txt(
R.string.season_format,
txt(R.string.season),
indexer.season
) //TODO FIX DISPLAYNAME
else -> {
val seasonNames = (currentResponse as? EpisodeResponse)?.seasonNames
val seasonData =
seasonNames.getSeason(indexer.season)
val suffix = seasonData?.name?.let { " $it" } ?: ""
txt(
R.string.season_format,
txt(R.string.season),
seasonData?.displaySeason ?: indexer.season,
suffix
)
}
}
)
)
@ -1578,6 +1590,7 @@ class ResultViewModel2 : ViewModel() {
val id = mainId + episode + idIndex * 1000000
if (!existingEpisodes.contains(episode)) {
existingEpisodes.add(id)
val seasonData = loadResponse.seasonNames.getSeason(i.season)
val eps =
buildResultEpisode(
loadResponse.name,
@ -1585,7 +1598,7 @@ class ResultViewModel2 : ViewModel() {
i.posterUrl,
episode,
null,
i.season,
seasonData?.displaySeason ?: i.season,
i.data,
loadResponse.apiName,
id,
@ -1621,7 +1634,7 @@ class ResultViewModel2 : ViewModel() {
existingEpisodes.add(id)
val seasonIndex = episode.season?.minus(1)
val currentSeason =
loadResponse.seasonNames?.getOrNull(seasonIndex ?: -1)
loadResponse.seasonNames.getSeason(episode.season)
val ep =
buildResultEpisode(
@ -1630,7 +1643,7 @@ class ResultViewModel2 : ViewModel() {
episode.posterUrl,
episodeIndex,
seasonIndex,
currentSeason?.season ?: episode.season,
currentSeason?.displaySeason ?: episode.season,
episode.data,
loadResponse.apiName,
id,
@ -1731,10 +1744,19 @@ class ResultViewModel2 : ViewModel() {
_dubSubSelections.postValue(dubSelection.map { txt(it) to it })
if (loadResponse is EpisodeResponse) {
_seasonSelections.postValue(seasonsSelection.map { seasonNumber ->
val seasonData = loadResponse.seasonNames.getSeason(seasonNumber)
val fixedSeasonNumber = seasonData?.displaySeason ?: seasonNumber
val suffix = seasonData?.name?.let { " $it" } ?: ""
val name =
/*loadResponse.seasonNames?.firstOrNull { it.season == seasonNumber }?.name?.let { seasonData ->
txt(seasonData)
} ?:*/txt(R.string.season_format, txt(R.string.season), seasonNumber) //TODO FIX
} ?:*/txt(
R.string.season_format,
txt(R.string.season),
fixedSeasonNumber,
suffix
)
name to seasonNumber
})
}

View file

@ -210,7 +210,6 @@
</string>
<string name="season">Staffel</string>
<string name="season_format">%s %d</string>
<string name="no_season">Keine Staffel</string>
<string name="episode">Episode</string>
<string name="episodes">Episoden</string>

View file

@ -228,7 +228,6 @@
</string>
<string name="season">Sezona</string>
<string name="season_format">%s %d</string>
<string name="no_season">Nema sezone</string>
<string name="episode">Epizoda</string>
<string name="episodes">Epizode</string>

View file

@ -208,7 +208,6 @@
<string name="acra_report_toast">Sorry, de applicatie is gecrasht. Er wordt een anoniem bugrapport naar de ontwikkelaars gestuurd </string>
<string name="season">Seizoen</string>
<string name="season_format">%s %d</string>
<string name="no_season">Geen seizoen</string>
<string name="episode">Aflevering</string>
<string name="episodes">afleveringen</string>

View file

@ -221,7 +221,6 @@
<string name="season">Mùa</string>
<string name="season_format">%s %d</string>
<string name="no_season">Không có mùa nào</string>
<string name="episode">Tập</string>
<string name="episodes">Tập</string>

View file

@ -231,7 +231,6 @@
</string>
<string name="season"></string>
<string name="season_format">%s %d</string>
<string name="no_season">无季</string>
<string name="episode"></string>
<string name="episodes"></string>

View file

@ -290,7 +290,7 @@
</string>
<string name="season">Season</string>
<string name="season_format">%s %d</string>
<string name="season_format">%s %d%s</string>
<string name="no_season">No Season</string>
<string name="episode">Episode</string>
<string name="episodes">Episodes</string>