mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
feat(Subtitles): SubSource subtitles provider (#1199)
This commit is contained in:
parent
694193fa3e
commit
a157115cfa
2 changed files with 161 additions and 1 deletions
|
@ -22,6 +22,7 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
|
||||||
val addic7ed = Addic7ed()
|
val addic7ed = Addic7ed()
|
||||||
val subDlApi = SubDlApi(0)
|
val subDlApi = SubDlApi(0)
|
||||||
val localListApi = LocalList()
|
val localListApi = LocalList()
|
||||||
|
val subSourceApi = SubSourceApi()
|
||||||
|
|
||||||
// used to login via app intent
|
// used to login via app intent
|
||||||
val OAuth2Apis
|
val OAuth2Apis
|
||||||
|
@ -51,7 +52,8 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
|
||||||
get() = listOf(
|
get() = listOf(
|
||||||
openSubtitlesApi,
|
openSubtitlesApi,
|
||||||
addic7ed,
|
addic7ed,
|
||||||
subDlApi
|
subDlApi,
|
||||||
|
subSourceApi
|
||||||
)
|
)
|
||||||
|
|
||||||
const val appString = "cloudstreamapp"
|
const val appString = "cloudstreamapp"
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
package com.lagradost.cloudstream3.syncproviders.providers
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.lagradost.cloudstream3.TvType
|
||||||
|
import com.lagradost.cloudstream3.app
|
||||||
|
import com.lagradost.cloudstream3.subtitles.AbstractSubProvider
|
||||||
|
import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities
|
||||||
|
import com.lagradost.cloudstream3.subtitles.SubtitleResource
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||||
|
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
||||||
|
|
||||||
|
class SubSourceApi : AbstractSubProvider {
|
||||||
|
override val idPrefix = "subsource"
|
||||||
|
val name = "SubSource"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val APIURL = "https://api.subsource.net/api"
|
||||||
|
const val DOWNLOADENDPOINT = "https://api.subsource.net/api/downloadSub"
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun search(query: AbstractSubtitleEntities.SubtitleSearch): List<AbstractSubtitleEntities.SubtitleEntity>? {
|
||||||
|
|
||||||
|
//Only supports Imdb Id search for now
|
||||||
|
if (query.imdbId == null) return null
|
||||||
|
val queryLang = SubtitleHelper.fromTwoLettersToLanguage(query.lang!!)
|
||||||
|
val type = if ((query.seasonNumber ?: 0) > 0) TvType.TvSeries else TvType.Movie
|
||||||
|
|
||||||
|
val searchRes = app.post(
|
||||||
|
url = "$APIURL/searchMovie",
|
||||||
|
data = mapOf(
|
||||||
|
"query" to query.imdbId!!
|
||||||
|
)
|
||||||
|
).parsedSafe<ApiSearch>() ?: return null
|
||||||
|
|
||||||
|
val postData = if (type == TvType.TvSeries) {
|
||||||
|
mapOf(
|
||||||
|
"langs" to "[]",
|
||||||
|
"movieName" to searchRes.found.first().linkName,
|
||||||
|
"season" to "season-${query.seasonNumber}"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
mapOf(
|
||||||
|
"langs" to "[]",
|
||||||
|
"movieName" to searchRes.found.first().linkName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val getMovieRes = app.post(
|
||||||
|
url = "$APIURL/getMovie",
|
||||||
|
data = postData
|
||||||
|
).parsedSafe<ApiResponse>().let {
|
||||||
|
// api doesn't has episode number or lang filtering
|
||||||
|
if (type == TvType.Movie) {
|
||||||
|
it?.subs?.filter { sub ->
|
||||||
|
sub.lang == queryLang
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
it?.subs?.filter { sub ->
|
||||||
|
sub.releaseName!!.contains(
|
||||||
|
String.format(
|
||||||
|
"E%02d",
|
||||||
|
query.epNumber
|
||||||
|
)
|
||||||
|
) && sub.lang == queryLang
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
|
return getMovieRes.map { subtitle ->
|
||||||
|
AbstractSubtitleEntities.SubtitleEntity(
|
||||||
|
idPrefix = this.idPrefix,
|
||||||
|
name = subtitle.releaseName!!,
|
||||||
|
lang = subtitle.lang!!,
|
||||||
|
data = SubData(
|
||||||
|
movie = subtitle.linkName!!,
|
||||||
|
lang = subtitle.lang,
|
||||||
|
id = subtitle.subId.toString(),
|
||||||
|
).toJson(),
|
||||||
|
type = type,
|
||||||
|
source = this.name,
|
||||||
|
epNumber = query.epNumber,
|
||||||
|
seasonNumber = query.seasonNumber,
|
||||||
|
isHearingImpaired = subtitle.hi == 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun SubtitleResource.getResources(data: AbstractSubtitleEntities.SubtitleEntity) {
|
||||||
|
|
||||||
|
val parsedSub = parseJson<SubData>(data.data)
|
||||||
|
|
||||||
|
val subRes = app.post(
|
||||||
|
url = "$APIURL/getSub",
|
||||||
|
data = mapOf(
|
||||||
|
"movie" to parsedSub.movie,
|
||||||
|
"lang" to data.lang,
|
||||||
|
"id" to parsedSub.id
|
||||||
|
)
|
||||||
|
).parsedSafe<SubTitleLink>() ?: return
|
||||||
|
|
||||||
|
this.addZipUrl(
|
||||||
|
"$DOWNLOADENDPOINT/${subRes.sub.downloadToken}"
|
||||||
|
) { name, _ ->
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ApiSearch(
|
||||||
|
@JsonProperty("success") val success: Boolean,
|
||||||
|
@JsonProperty("found") val found: List<Found>,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Found(
|
||||||
|
@JsonProperty("id") val id: Long,
|
||||||
|
@JsonProperty("title") val title: String,
|
||||||
|
@JsonProperty("seasons") val seasons: Long,
|
||||||
|
@JsonProperty("type") val type: String,
|
||||||
|
@JsonProperty("releaseYear") val releaseYear: Long,
|
||||||
|
@JsonProperty("linkName") val linkName: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ApiResponse(
|
||||||
|
@JsonProperty("success") val success: Boolean,
|
||||||
|
@JsonProperty("movie") val movie: Movie,
|
||||||
|
@JsonProperty("subs") val subs: List<Sub>,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Movie(
|
||||||
|
@JsonProperty("id") val id: Long? = null,
|
||||||
|
@JsonProperty("type") val type: String? = null,
|
||||||
|
@JsonProperty("year") val year: Long? = null,
|
||||||
|
@JsonProperty("fullName") val fullName: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Sub(
|
||||||
|
@JsonProperty("hi") val hi: Int? = null,
|
||||||
|
@JsonProperty("fullLink") val fullLink: String? = null,
|
||||||
|
@JsonProperty("linkName") val linkName: String? = null,
|
||||||
|
@JsonProperty("lang") val lang: String? = null,
|
||||||
|
@JsonProperty("releaseName") val releaseName: String? = null,
|
||||||
|
@JsonProperty("subId") val subId: Long? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SubData(
|
||||||
|
@JsonProperty("movie") val movie: String,
|
||||||
|
@JsonProperty("lang") val lang: String,
|
||||||
|
@JsonProperty("id") val id: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SubTitleLink(
|
||||||
|
@JsonProperty("sub") val sub: SubToken,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SubToken(
|
||||||
|
@JsonProperty("downloadToken") val downloadToken: String,
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in a new issue