diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9f15360..9a5d7cf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -125,7 +125,6 @@ dependencies { implementation(libs.androidx.media3.exoplayer.dash) implementation(libs.androidx.media3.ui) implementation(libs.androidx.media3.exoplayer.hls) - implementation(libs.androidx.media3.datasource.okhttp) // Firebase implementation(platform(libs.com.google.firebase.bom)) @@ -140,7 +139,6 @@ dependencies { // Network implementation(libs.com.github.kittinunf.fuel) - implementation(files("../libs/re-bridge-1.0-SNAPSHOT.jar")) // Datastore implementation(libs.androidx.datastore.preferences) diff --git a/app/src/main/java/org/shirabox/app/service/media/DownloadsServiceHelper.kt b/app/src/main/java/org/shirabox/app/service/media/DownloadsServiceHelper.kt index 8703144..cc71ab5 100755 --- a/app/src/main/java/org/shirabox/app/service/media/DownloadsServiceHelper.kt +++ b/app/src/main/java/org/shirabox/app/service/media/DownloadsServiceHelper.kt @@ -1,6 +1,6 @@ package org.shirabox.app.service.media -import ddosGuardBridge +import com.google.common.net.InternetDomainName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -27,6 +27,7 @@ import org.shirabox.core.util.Util import java.io.BufferedInputStream import java.io.File import java.io.FileOutputStream +import java.net.URI object DownloadsServiceHelper { @@ -154,10 +155,15 @@ object DownloadsServiceHelper { if (file.exists() && mediaDownloadTask.pauseData == null) file.delete() if (!file.exists()) file.createNewFile() + val host = URI(mediaDownloadTask.url).host + val topDomain = InternetDomainName.from(host).topPrivateDomain() + val request = Request.Builder() .url(mediaDownloadTask.url) .addHeader("Range", "bytes=$pausedBytes-") - .ddosGuardBridge(mediaDownloadTask.url) // DDoS-Guard.net bypass + .apply { + mpegHeaders("https://$topDomain/").forEach { addHeader(it.key, it.value) } + } .build() val responseBody = okHttpClient.newCall(request).execute().body @@ -408,6 +414,21 @@ object DownloadsServiceHelper { .forEach { it.state.value = TaskState.STOPPED } } + fun mpegHeaders(rootHost: String): Map = mapOf( + "Accept" to "*/*", + "Accept-Encoding" to "identity;q=1, *;q=0", + "Origin" to rootHost, + "Priority" to "i", + "Referer" to rootHost, + "Sec-Ch-Ua" to "\"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"", + "Sec-Ch-Ua-Mobile" to "?0", + "Sec-Ch-Ua-Platform" to "\"Windows\"", + "Sec-Fetch-Dest" to "video", + "Sec-Fetch-Mode" to "cors", + "Sec-Fetch-Site" to "same-site", + "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" + ) + class ForcedInterruptionException : Exception() class MpegRepairmentFailureException : Exception() diff --git a/app/src/main/java/org/shirabox/app/ui/activity/player/ShiraPlayer.kt b/app/src/main/java/org/shirabox/app/ui/activity/player/ShiraPlayer.kt index 7a97b9b..0b3f238 100644 --- a/app/src/main/java/org/shirabox/app/ui/activity/player/ShiraPlayer.kt +++ b/app/src/main/java/org/shirabox/app/ui/activity/player/ShiraPlayer.kt @@ -28,15 +28,12 @@ import androidx.media3.common.MediaItem import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.DefaultHttpDataSource import androidx.media3.datasource.FileDataSource -import androidx.media3.datasource.okhttp.OkHttpDataSource import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.hls.HlsMediaSource import androidx.media3.exoplayer.source.ProgressiveMediaSource import androidx.media3.ui.PlayerView -import ddosGuardBridge import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.launch -import okhttp3.OkHttpClient import org.shirabox.app.ui.activity.player.presentation.PlayerScaffold import org.shirabox.app.ui.activity.player.presentation.SettingsBottomSheet import org.shirabox.app.ui.activity.player.presentation.hideControls @@ -44,6 +41,7 @@ import org.shirabox.core.datastore.DataStoreScheme import org.shirabox.core.entity.EpisodeEntity import org.shirabox.core.model.Quality import org.shirabox.core.model.StreamProtocol +import org.shirabox.data.content.AbstractContentRepository @OptIn(UnstableApi::class) @@ -131,22 +129,13 @@ private fun PlayerSurface(exoPlayer: ExoPlayer, model: PlayerViewModel, playlist .createMediaSource(MediaItem.fromUri(uri)) } - // DDos-Guard.net bypass - val client = OkHttpClient.Builder().addInterceptor { chain -> - val request = chain.request().newBuilder() - .ddosGuardBridge(chain.request().url.toString()).build() - chain.proceed(request) - }.build() - val okHttpDataSourceFactory = OkHttpDataSource.Factory(client) - val streamMediaSource = when (repository.streamingType) { StreamProtocol.MPEG -> ProgressiveMediaSource - .Factory(okHttpDataSourceFactory) + .Factory(DefaultHttpDataSource.Factory().setDefaultRequestProperties(repository.hostHeaders())) StreamProtocol.HLS -> HlsMediaSource - .Factory(DefaultHttpDataSource.Factory()) + .Factory(DefaultHttpDataSource.Factory().setDefaultRequestProperties(repository.hostHeaders())) }.createMediaSource(MediaItem.fromUri(stream.value)) - return@map offlineMediaSource ?: streamMediaSource }) @@ -173,6 +162,7 @@ private fun PlayerSurface(exoPlayer: ExoPlayer, model: PlayerViewModel, playlist rebuildExoPlaylist( exoPlayer, playlist, + model.currentRepository!!, model.currentQuality ) } @@ -212,20 +202,29 @@ private fun PlayerSurface(exoPlayer: ExoPlayer, model: PlayerViewModel, playlist SettingsBottomSheet(exoPlayer = exoPlayer, playlist = playlist, model = model) } +@OptIn(UnstableApi::class) private fun rebuildExoPlaylist( exoPlayer: ExoPlayer, playlist: List, + repository: AbstractContentRepository, currentQuality: Quality ) { val currentPosition = exoPlayer.currentPosition val currentItemIndex = exoPlayer.currentMediaItemIndex exoPlayer.apply { - setMediaItems( - playlist.map { MediaItem.fromUri(it.videos[currentQuality] ?: "") }, - currentItemIndex, - currentPosition + setMediaSources( + playlist.map { + val streamMediaSource = when (repository.streamingType) { + StreamProtocol.MPEG -> ProgressiveMediaSource + .Factory(DefaultHttpDataSource.Factory().setDefaultRequestProperties(repository.hostHeaders())) + StreamProtocol.HLS -> HlsMediaSource + .Factory(DefaultHttpDataSource.Factory().setDefaultRequestProperties(repository.hostHeaders())) + }.createMediaSource(MediaItem.fromUri(it.videos[currentQuality] ?: "")) + streamMediaSource + } ) + seekTo(currentItemIndex, currentPosition) } } diff --git a/app/src/main/java/org/shirabox/app/ui/activity/resource/ResourceActivity.kt b/app/src/main/java/org/shirabox/app/ui/activity/resource/ResourceActivity.kt index a39cb93..1d79409 100644 --- a/app/src/main/java/org/shirabox/app/ui/activity/resource/ResourceActivity.kt +++ b/app/src/main/java/org/shirabox/app/ui/activity/resource/ResourceActivity.kt @@ -6,6 +6,7 @@ import android.content.Intent import android.os.Bundle import android.widget.Toast import androidx.activity.ComponentActivity +import androidx.activity.compose.LocalActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.animation.AnimatedVisibility @@ -32,10 +33,6 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.NotificationAdd -import androidx.compose.material.icons.outlined.NotificationsOff -import androidx.compose.material.icons.rounded.Share import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.pullRefresh import androidx.compose.material.pullrefresh.rememberPullRefreshState @@ -76,7 +73,6 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource @@ -157,7 +153,7 @@ fun Resource( model: ResourceViewModel = hiltViewModel(), colorScheme: ColorScheme = MaterialTheme.colorScheme ) { - val activity = LocalContext.current as Activity? + val activity = LocalActivity.current val content = model.content.value val isFavourite = model.isFavourite.value val isRefreshing = model.isRefreshing.value diff --git a/data/src/main/java/org/shirabox/data/content/AbstractContentRepository.kt b/data/src/main/java/org/shirabox/data/content/AbstractContentRepository.kt index cd0c9ec..557fd1b 100644 --- a/data/src/main/java/org/shirabox/data/content/AbstractContentRepository.kt +++ b/data/src/main/java/org/shirabox/data/content/AbstractContentRepository.kt @@ -17,4 +17,5 @@ abstract class AbstractContentRepository ( abstract suspend fun searchEpisodes(content: Content): Flow> abstract suspend fun searchEpisodesInRange(content: Content, range: IntRange): Flow> + abstract fun hostHeaders(): Map } \ No newline at end of file diff --git a/data/src/main/java/org/shirabox/data/content/anime/animelib/AniLibRepository.kt b/data/src/main/java/org/shirabox/data/content/anime/animelib/AniLibRepository.kt index 2df520a..3e82f28 100644 --- a/data/src/main/java/org/shirabox/data/content/anime/animelib/AniLibRepository.kt +++ b/data/src/main/java/org/shirabox/data/content/anime/animelib/AniLibRepository.kt @@ -117,6 +117,21 @@ class AniLibRepository : AbstractContentRepository( } catch (ex: Exception) { throw ex } } + override fun hostHeaders(): Map = mapOf( + "Accept" to "*/*", + "Accept-Encoding" to "identity;q=1, *;q=0", + "Origin" to "https://anilib.me", + "Priority" to "i", + "Referer" to "https://anilib.me/", + "Sec-Ch-Ua" to "\"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"", + "Sec-Ch-Ua-Mobile" to "?0", + "Sec-Ch-Ua-Platform" to "\"Windows\"", + "Sec-Fetch-Dest" to "video", + "Sec-Fetch-Mode" to "cors", + "Sec-Fetch-Site" to "same-site", + "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" + ) + private fun fetchEpisode(id: Int): Flow = flow { try { diff --git a/data/src/main/java/org/shirabox/data/content/anime/libria/LibriaRepository.kt b/data/src/main/java/org/shirabox/data/content/anime/libria/LibriaRepository.kt index 6645b9d..d29d52b 100644 --- a/data/src/main/java/org/shirabox/data/content/anime/libria/LibriaRepository.kt +++ b/data/src/main/java/org/shirabox/data/content/anime/libria/LibriaRepository.kt @@ -44,6 +44,8 @@ class LibriaRepository : AbstractContentRepository( ) } + override fun hostHeaders(): Map = emptyMap() + private suspend fun lookupEpisodes(content: Content): List { try { val id = search(content)?.id diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1114151..234a9c8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -79,7 +79,6 @@ androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", versi androidx-media3-exoplayer-dash = { module = "androidx.media3:media3-exoplayer-dash", version.ref = "androidxMedia3" } androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "androidxMedia3" } androidx-media3-exoplayer-hls = { module = "androidx.media3:media3-exoplayer-hls", version.ref = "androidxMedia3" } -androidx-media3-datasource-okhttp = { module = "androidx.media3:media3-datasource-okhttp", version.ref = "androidxMedia3"} com-google-firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "comGoogleFirebase" } io-coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "ioCoilKt" } io-coil-kt-svg = { module = "io.coil-kt:coil-svg", version.ref = "ioCoilKt" } diff --git a/libs/re-bridge-1.0-SNAPSHOT.jar b/libs/re-bridge-1.0-SNAPSHOT.jar deleted file mode 100644 index f8b8253..0000000 Binary files a/libs/re-bridge-1.0-SNAPSHOT.jar and /dev/null differ