Created
October 26, 2025 14:44
-
-
Save ShivamKumarJha/02dfbef4a119268b460d58322cf16f80 to your computer and use it in GitHub Desktop.
StreamTape
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.shivamkumarjha.network_common | |
| import kotlinx.serialization.Serializable | |
| @Serializable | |
| data class HttpRequestData( | |
| val url: String, | |
| val headers: Map<String, String> = emptyMap(), | |
| val queries: Map<String, String> = emptyMap(), | |
| val body: String? = null, | |
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.shivamkumarjha.media_extractor.extractors | |
| import com.fleeksoft.ksoup.Ksoup | |
| import com.shivamkumarjha.media_common.model.Media | |
| import com.shivamkumarjha.media_common.model.MediaPlayerItem | |
| import com.shivamkumarjha.media_extractor.BaseMediaExtractor | |
| import com.shivamkumarjha.network_client.getEmbedHeaders | |
| import com.shivamkumarjha.network_client.getHost | |
| import com.shivamkumarjha.network_client.getHttpRequestData | |
| import com.shivamkumarjha.network_common.HttpRequestData | |
| import com.shivamkumarjha.network_common.Resource | |
| import com.shivamkumarjha.utility_logging.logger | |
| import io.ktor.client.HttpClient | |
| import io.ktor.client.statement.bodyAsText | |
| import io.ktor.http.isSuccess | |
| internal class StreamTapeExtractor( | |
| private val httpClient: HttpClient, | |
| ) : BaseMediaExtractor() { | |
| override val tag: String | |
| get() = "StreamTape" | |
| override suspend fun isSupported(httpRequestData: HttpRequestData): Boolean { | |
| return httpRequestData.url.getHost().contains("streamtape") || | |
| httpRequestData.url.getHost().contains("tapepops") | |
| } | |
| override suspend fun mediaPlayerItem( | |
| httpRequestData: HttpRequestData, | |
| callback: suspend (MediaPlayerItem) -> Unit | |
| ): Resource<MediaPlayerItem> { | |
| val newUrl = if (httpRequestData.url.contains("/v/")) | |
| httpRequestData.url | |
| .replace("/v/", "/e/") | |
| .replace(".com", ".xyz") | |
| .substringBeforeLast("/") | |
| else | |
| httpRequestData.url.replace(".com", ".xyz") | |
| val response = httpClient.getHttpRequestData(httpRequestData.copy(url = newUrl)) | |
| if (!response.status.isSuccess()) { | |
| val throwable = Throwable(response.status.toString()) | |
| logger.error("Failed mediaPlayerItem $httpRequestData", throwable, tag = tag) | |
| return Resource.Error(null, throwable) | |
| } | |
| val body = response.bodyAsText() | |
| val document = Ksoup.parse(body) | |
| val targetLine = "document.getElementById('robotlink')" | |
| val script = document.selectFirst("script:containsData($targetLine)") | |
| ?.data() | |
| ?.substringAfter("$targetLine.innerHTML = '") | |
| if (script.isNullOrEmpty()) { | |
| val throwable = Throwable("Not found") | |
| logger.error("BAD unpacked", throwable, tag = tag) | |
| return Resource.Error(null, throwable) | |
| } | |
| val mediaUrl = "https:" + script.substringBefore("'") + | |
| script.substringAfter("+ ('xcd").substringBefore("'") | |
| val mediaItems = listOf( | |
| Media( | |
| httpRequestData = HttpRequestData( | |
| url = mediaUrl, | |
| headers = httpRequestData.url.getEmbedHeaders(), | |
| ), | |
| label = httpRequestData.url.getHost(), | |
| description = mediaUrl.getHost(), | |
| ) | |
| ) | |
| return Resource.Success(MediaPlayerItem(mediaItems)) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment