fix(it/streamingcommunity): Fix empty videolist and change base domain (#3103)
Co-authored-by: Secozzi <49240133+Secozzi@users.noreply.github.com>
This commit is contained in:
parent
59bfabf170
commit
c2096dd1be
@ -1,7 +1,7 @@
|
|||||||
ext {
|
ext {
|
||||||
extName = 'StreamingCommunity'
|
extName = 'StreamingCommunity'
|
||||||
extClass = '.StreamingCommunity'
|
extClass = '.StreamingCommunity'
|
||||||
extVersionCode = 3
|
extVersionCode = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.network.GET
|
|||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
@ -29,14 +30,14 @@ class StreamingCommunity : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
|
|
||||||
override val name = "StreamingCommunity"
|
override val name = "StreamingCommunity"
|
||||||
|
|
||||||
// TODO: Check frequency of url changes to potentially
|
override val baseUrl = "https://streamingcommunity.forum"
|
||||||
// add back overridable baseurl preference
|
|
||||||
override val baseUrl = "https://streamingcommunity.report"
|
|
||||||
|
|
||||||
override val lang = "it"
|
override val lang = "it"
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
|
override val client: OkHttpClient = network.client
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
private val preferences: SharedPreferences by lazy {
|
||||||
@ -240,7 +241,7 @@ class StreamingCommunity : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
SEpisode.create().apply {
|
SEpisode.create().apply {
|
||||||
name = "Stagione ${season.number} episodio ${episode.number} - ${episode.name}"
|
name = "Stagione ${season.number} episodio ${episode.number} - ${episode.name}"
|
||||||
episode_number = episode.number.toFloat()
|
episode_number = episode.number.toFloat()
|
||||||
url = "${data.title.id}?e=${episode.id}"
|
url = "${data.title.id}?episode_id=${episode.id}&next_episode=1"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -252,60 +253,67 @@ class StreamingCommunity : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
|
|
||||||
// ============================ Video Links =============================
|
// ============================ Video Links =============================
|
||||||
|
|
||||||
override fun videoListRequest(episode: SEpisode): Request = GET("$baseUrl/watch/${episode.url}", headers)
|
override suspend fun getVideoList(episode: SEpisode): List<Video> {
|
||||||
|
|
||||||
override fun videoListParse(response: Response): List<Video> {
|
|
||||||
val data = json.decodeFromString<VideoResponse>(response.asJsoup().getData())
|
|
||||||
val videoList = mutableListOf<Video>()
|
val videoList = mutableListOf<Video>()
|
||||||
|
val doc =
|
||||||
|
client
|
||||||
|
.newCall(
|
||||||
|
GET("$baseUrl/iframe/${episode.url}", headers),
|
||||||
|
).execute()
|
||||||
|
.asJsoup()
|
||||||
|
val iframeUrl =
|
||||||
|
doc.selectFirst("iframe[src]")?.attr("abs:src")
|
||||||
|
?: error("Failed to extract iframe")
|
||||||
|
val iframeHeaders =
|
||||||
|
headers
|
||||||
|
.newBuilder()
|
||||||
|
.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
|
||||||
|
.add("Host", iframeUrl.toHttpUrl().host)
|
||||||
|
.add("Referer", "$baseUrl/")
|
||||||
|
.build()
|
||||||
|
|
||||||
val embedUrl = data.props.embedUrl
|
val iframe =
|
||||||
val embedHeaders = headers.newBuilder()
|
client
|
||||||
.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
|
.newCall(
|
||||||
.add("Host", baseUrl.toHttpUrl().host)
|
GET(iframeUrl, headers = iframeHeaders),
|
||||||
.add("Referer", response.request.url.toString())
|
).execute()
|
||||||
.build()
|
.asJsoup()
|
||||||
|
val script = iframe.selectFirst("script:containsData(masterPlaylist)")!!.data().replace("\n", "\t")
|
||||||
|
var playlistUrl = PLAYLIST_URL_REGEX.find(script)!!.groupValues[1]
|
||||||
|
val filename = playlistUrl.substringAfterLast("/")
|
||||||
|
if (!filename.endsWith(".m3u8")) {
|
||||||
|
playlistUrl = playlistUrl.replace(filename, filename + ".m3u8")
|
||||||
|
}
|
||||||
|
|
||||||
val embedded = client.newCall(
|
val expires = EXPIRES_REGEX.find(script)!!.groupValues[1]
|
||||||
GET(embedUrl, headers = embedHeaders),
|
val token = TOKEN_REGEX.find(script)!!.groupValues[1]
|
||||||
).execute().asJsoup()
|
|
||||||
|
|
||||||
val iframeUrl = embedded.selectFirst("iframe[src]")?.attr("abs:src") ?: error("Failed to load iframe")
|
|
||||||
val iframeHeaders = headers.newBuilder()
|
|
||||||
.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
|
|
||||||
.add("Host", iframeUrl.toHttpUrl().host)
|
|
||||||
.add("Referer", "$baseUrl/")
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val iframe = client.newCall(
|
|
||||||
GET(iframeUrl, headers = iframeHeaders),
|
|
||||||
).execute().asJsoup()
|
|
||||||
val script = iframe.selectFirst("script:containsData(masterPlaylistParams)")!!.data()
|
|
||||||
|
|
||||||
val playlistUrl = Regex("""masterPlaylistUrl.*?'(.*?)'""").find(script)!!.groupValues[1]
|
|
||||||
val expires = Regex("""'expires': ?'(\d+)'""").find(script)!!.groupValues[1]
|
|
||||||
val canCast = Regex("""'canCast': ?'(\d*)'""").find(script)!!.groupValues[1]
|
|
||||||
val token = Regex("""'token': ?'([\w-]+)'""").find(script)!!.groupValues[1]
|
|
||||||
|
|
||||||
// Get subtitles
|
// Get subtitles
|
||||||
val masterPlUrl = "$playlistUrl?token=$token&expires=$expires&canCast=$canCast&n=1"
|
val masterPlUrl = "$playlistUrl?token=$token&expires=$expires&n=1"
|
||||||
val masterPl = client.newCall(GET(masterPlUrl)).execute().body.string()
|
val masterPl =
|
||||||
val subList = Regex("""#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"""").findAll(masterPl).map {
|
client
|
||||||
Track(it.groupValues[2], it.groupValues[1])
|
.newCall(GET(masterPlUrl))
|
||||||
}.toList()
|
.execute()
|
||||||
|
.body
|
||||||
Regex("""'token(\d+p?)': ?'([\w-]+)'""").findAll(script).forEach { match ->
|
.string()
|
||||||
|
val subList =
|
||||||
|
SUBTITLES_REGEX.findAll(masterPl)
|
||||||
|
.map {
|
||||||
|
Track(it.groupValues[2], it.groupValues[1])
|
||||||
|
}.toList()
|
||||||
|
TOKEN_QUALITY_REGEX.findAll(script).forEach { match ->
|
||||||
val quality = match.groupValues[1]
|
val quality = match.groupValues[1]
|
||||||
|
|
||||||
val videoUrl = buildString {
|
val videoUrl =
|
||||||
append(playlistUrl)
|
buildString {
|
||||||
append("?type=video&rendition=")
|
append(playlistUrl)
|
||||||
append(quality)
|
append("?type=video&rendition=")
|
||||||
append("&token=")
|
append(quality)
|
||||||
append(match.groupValues[2])
|
append("&token=")
|
||||||
append("&expires=$expires")
|
append(match.groupValues[2])
|
||||||
append("&canCast=$canCast")
|
append("&expires=$expires")
|
||||||
append("&n=1")
|
append("&n=1")
|
||||||
}
|
}
|
||||||
videoList.add(Video(videoUrl, quality, videoUrl, subtitleTracks = subList))
|
videoList.add(Video(videoUrl, quality, videoUrl, subtitleTracks = subList))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +322,10 @@ class StreamingCommunity : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
return videoList.sort()
|
return videoList.sort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun videoListRequest(episode: SEpisode): Request = throw Exception("Not used")
|
||||||
|
|
||||||
|
override fun videoListParse(response: Response): List<Video> = throw Exception("Not used")
|
||||||
|
|
||||||
// ============================= Utilities ==============================
|
// ============================= Utilities ==============================
|
||||||
|
|
||||||
private fun Document.getData(): String {
|
private fun Document.getData(): String {
|
||||||
@ -344,6 +356,11 @@ class StreamingCommunity : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val PLAYLIST_URL_REGEX = Regex("""url: ?'(.*?)'""")
|
||||||
|
private val EXPIRES_REGEX = Regex("""'expires': ?'(\d+)'""")
|
||||||
|
private val TOKEN_REGEX = Regex("""'token': ?'([\w-]+)'""")
|
||||||
|
private val TOKEN_QUALITY_REGEX = Regex("""'token(\d+p?)': ?'([\w-]+)'""")
|
||||||
|
private val SUBTITLES_REGEX = Regex("""#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"""")
|
||||||
private const val PREF_QUALITY_KEY = "preferred_quality"
|
private const val PREF_QUALITY_KEY = "preferred_quality"
|
||||||
private const val PREF_QUALITY_DEFAULT = "720"
|
private const val PREF_QUALITY_DEFAULT = "720"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user