diff --git a/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerApi.kt b/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerApi.kt index 5d63e47..136d263 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerApi.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerApi.kt @@ -59,9 +59,6 @@ class DeezerApi { private val pass: String get() = DeezerCredentials.pass - private val proxy: Boolean - get() = DeezerUtils.proxy - private val client: OkHttpClient = OkHttpClient.Builder().apply { addInterceptor { chain -> val originalResponse = chain.proceed(chain.request()) @@ -73,9 +70,7 @@ class DeezerApi { originalResponse } } - if(proxy) { - proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved("uk.proxy.murglar.app", 3128))) - } + proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved("uk.proxy.murglar.app", 3128))) }.build() private val json = Json { diff --git a/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerBase.kt b/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerBase.kt index 75e93bf..1f3330b 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerBase.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerBase.kt @@ -12,5 +12,4 @@ object DeezerCredentials { object DeezerUtils { var arl_expired: Boolean = false - var proxy: Boolean = false } diff --git a/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerExtension.kt b/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerExtension.kt index b804abd..690a52d 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerExtension.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerExtension.kt @@ -60,12 +60,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie "Use 128kbps(overrides FLAC option)", false ), - SettingSwitch( - "Use Proxy", - "proxy", - "Use Proxy against geo-blocking", - false - ) ) private lateinit var settings: Settings @@ -79,9 +73,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie private val use128 get() = settings.getBoolean("128") ?: false - private val proxy - get() = settings.getBoolean("proxy") ?: false - private val arl: String get() = DeezerCredentials.arl @@ -94,7 +85,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun getHomeTabs(): List { if (arl == "" || arlExpired) return emptyList() - DeezerUtils.proxy = proxy val jObject = DeezerApi().homePage() val resultObject = jObject["results"]!!.jsonObject val sections = resultObject["sections"]!!.jsonArray @@ -110,7 +100,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override fun getHomeFeed(tab: Tab?): PagedData = PagedData.Single { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy val dataList = mutableListOf() val jsonData = json.decodeFromString(tab?.extras!!["sections"].toString()) jsonData.map { section -> @@ -137,7 +126,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun getLibraryTabs(): List { if (arl == "" || arlExpired) return emptyList() - DeezerUtils.proxy = proxy val tabs = listOf(Tab("playlists", "Playlists"), Tab("albums", "Albums"), Tab("tracks", "Tracks"), Tab("artists", "Artists")) allTabs = "all" to tabs.mapNotNull { tab -> @@ -182,7 +170,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override fun getLibraryFeed(tab: Tab?) = PagedData.Single { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy val tabId = tab?.id ?: "all" var list = listOf() when (tabId) { @@ -245,13 +232,11 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun addTracksToPlaylist(playlist: Playlist, tracks: List, index: Int, new: List) { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy DeezerApi().addToPlaylist(playlist, new) } override suspend fun createPlaylist(title: String, description: String?): Playlist { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy val jsonObject = DeezerApi().createPlaylist(title, description) val id = jsonObject["results"]?.jsonPrimitive?.content ?: "" val playlist = Playlist( @@ -265,19 +250,16 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun deletePlaylist(playlist: Playlist) { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy DeezerApi().deletePlaylist(playlist.id) } override suspend fun editPlaylistMetadata(playlist: Playlist, title: String, description: String?) { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy DeezerApi().updatePlaylist(playlist.id, title, description) } override suspend fun likeTrack(track: Track, liked: Boolean): Boolean { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy if(liked) { DeezerApi().addFavoriteTrack(track.id) return true @@ -289,7 +271,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun listEditablePlaylists(): List { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy val playlistList = mutableListOf() val jsonObject = DeezerApi().getPlaylists() val resultObject = jsonObject["results"]!!.jsonObject @@ -308,7 +289,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun moveTrackInPlaylist(playlist: Playlist, tracks: List, fromIndex: Int, toIndex: Int) { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy val idArray = tracks.map { it.id }.toTypedArray() val newIdArray = moveElement(idArray, fromIndex, toIndex) DeezerApi().updatePlaylistOrder(playlist.id, newIdArray) @@ -316,14 +296,12 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun removeTracksFromPlaylist(playlist: Playlist, tracks: List, indexes: List) { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy DeezerApi().removeFromPlaylist(playlist, tracks, indexes) } //<============= Search =============> override suspend fun quickSearch(query: String?) = query?.run { - DeezerUtils.proxy = proxy try { val jsonObject = DeezerApi().searchSuggestions(query) val resultObject = jsonObject["results"]!!.jsonObject @@ -342,7 +320,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie private var oldSearch: Pair>? = null override fun searchFeed(query: String?, tab: Tab?) = PagedData.Single { if(arl == "" || arlExpired) throw loginRequiredException - DeezerUtils.proxy = proxy query ?: return@Single emptyList() val old = oldSearch?.takeIf { it.first == query && (tab == null || tab.id == "All") @@ -366,7 +343,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun searchTabs(query: String?): List { if (arl == "" || arlExpired) return emptyList() - DeezerUtils.proxy = proxy query ?: return emptyList() val jsonObject = DeezerApi().search(query) val resultObject = jsonObject["results"]!!.jsonObject @@ -402,7 +378,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override suspend fun getStreamableVideo(streamable: Streamable) = throw Exception("not Used") override suspend fun loadTrack(track: Track) = coroutineScope { - DeezerUtils.proxy = false val api = DeezerApi() val jsonObject = if (track.extras["FILESIZE_MP3_MISC"] != "0" && track.extras["FILESIZE_MP3_MISC"] != null) { api.getMP3MediaUrl(track) @@ -477,14 +452,12 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override fun getMediaItems(album: Album) = getMediaItems(album.artists.first()) override suspend fun loadAlbum(album: Album): Album { - DeezerUtils.proxy = proxy val jsonObject = DeezerApi().album(album) val resultsObject = jsonObject["results"]!!.jsonObject return resultsObject.toAlbum() } override fun loadTracks(album: Album): PagedData = PagedData.Single { - DeezerUtils.proxy = proxy val jsonObject = DeezerApi().album(album) val resultsObject = jsonObject["results"]!!.jsonObject val songsObject = resultsObject["SONGS"]!!.jsonObject @@ -498,7 +471,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie //<============= Playlist =============> override fun getMediaItems(playlist: Playlist) = PagedData.Single { - DeezerUtils.proxy = proxy val jsonObject = DeezerApi().playlist(playlist) val resultsObject = jsonObject["results"]!!.jsonObject val songsObject = resultsObject["SONGS"]!!.jsonObject @@ -510,14 +482,12 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie } override suspend fun loadPlaylist(playlist: Playlist): Playlist { - DeezerUtils.proxy = proxy val jsonObject = DeezerApi().playlist(playlist) val resultsObject = jsonObject["results"]!!.jsonObject return resultsObject.toPlaylist() } override fun loadTracks(playlist: Playlist): PagedData = PagedData.Single { - DeezerUtils.proxy = proxy val jsonObject = DeezerApi().playlist(playlist) val resultsObject = jsonObject["results"]!!.jsonObject val songsObject = resultsObject["SONGS"]!!.jsonObject @@ -531,7 +501,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie //<============= Artist =============> override fun getMediaItems(artist: Artist) = PagedData.Single { - DeezerUtils.proxy = proxy val dataList = mutableListOf() val jsonObject = DeezerApi().artist(artist) @@ -580,7 +549,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie } override suspend fun loadArtist(artist: Artist): Artist { - DeezerUtils.proxy = proxy val jsonObject = DeezerApi().artist(artist) val resultsObject = jsonObject["results"]!!.jsonObject["DATA"]!!.jsonObject return resultsObject.toArtist() @@ -596,7 +564,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie override val loginWebViewStopUrlRegex = "https://www\\.deezer\\.com/account/.*".toRegex() override suspend fun onLoginWebviewStop(url: String, data: String): List { - DeezerUtils.proxy = proxy if (data.contains("arl=")) { DeezerCredentials.arl = data.substringAfter("arl=").substringBefore(";") DeezerCredentials.sid = data.substringAfter("sid=").substringBefore(";") @@ -619,7 +586,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie ) override suspend fun onLogin(data: Map): List { - DeezerUtils.proxy = proxy DeezerCredentials.arl = data["arl"] ?: "" DeezerApi().getSid() val userList = DeezerApi().makeUser() @@ -627,7 +593,6 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie } override suspend fun onLogin(username: String, password: String): List { - DeezerUtils.proxy = proxy // Set shared credentials DeezerCredentials.email = username DeezerCredentials.pass = password diff --git a/app/src/main/java/dev/brahmkshatriya/echo/extension/Utils.kt b/app/src/main/java/dev/brahmkshatriya/echo/extension/Utils.kt index 4dd5ffe..c34d40d 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/extension/Utils.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/extension/Utils.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.withContext import okhttp3.OkHttpClient import okhttp3.Request import java.io.ByteArrayOutputStream +import java.io.IOException import java.math.BigInteger import java.security.MessageDigest import java.util.Arrays @@ -81,45 +82,49 @@ fun getByteStreamAudio(streamable: Streamable, client: OkHttpClient): Streamable withContext(Dispatchers.IO) { val response = client.newCall(request).execute() val byteStream = response.body?.byteStream() - - // Read the entire byte stream into memory - val completeStream = ByteArrayOutputStream() - val buffer = ByteArray(2 * 1024 * 1024) // Increased buffer size - var bytesRead: Int - while (byteStream?.read(buffer).also { bytesRead = it ?: -1 } != -1) { - completeStream.write(buffer, 0, bytesRead) - } - - // Ensure complete stream is read - val completeStreamBytes = completeStream.toByteArray() - println("Total bytes read: ${completeStreamBytes.size}") - - // Determine chunk size based on decryption block size - val chunkSize = 2048 * 3072 - val numChunks = (completeStreamBytes.size + chunkSize - 1) / chunkSize - println("Number of chunks: $numChunks") - - // Measure decryption time - val startTime = System.nanoTime() - - // Decrypt the chunks concurrently - val deferredChunks = (0 until numChunks).map { i -> - val start = i * chunkSize - val end = minOf((i + 1) * chunkSize, completeStreamBytes.size) - println("Chunk $i: start $start, end $end") - async(Dispatchers.Default) { decryptStreamChunk(completeStreamBytes.copyOfRange(start, end), key) } - } - - // Wait for all decryption tasks to complete and concatenate the results - deferredChunks.forEach { deferred -> - decChunk += deferred.await() + ?: throw IOException("Failed to get byte stream from response") + + try { + // Read the entire byte stream into memory + val completeStream = ByteArrayOutputStream() + val buffer = ByteArray(2 * 1024 * 1024) // Increased buffer size + var bytesRead: Int + while (byteStream.read(buffer).also { bytesRead = it } != -1) { + completeStream.write(buffer, 0, bytesRead) + } + + // Ensure complete stream is read + val completeStreamBytes = completeStream.toByteArray() + println("Total bytes read: ${completeStreamBytes.size}") + + // Determine chunk size based on decryption block size + val chunkSize = 2048 * 3072 + val numChunks = (completeStreamBytes.size + chunkSize - 1) / chunkSize + println("Number of chunks: $numChunks") + + // Measure decryption time + val startTime = System.nanoTime() + + // Decrypt the chunks concurrently + val deferredChunks = (0 until numChunks).map { i -> + val start = i * chunkSize + val end = minOf((i + 1) * chunkSize, completeStreamBytes.size) + println("Chunk $i: start $start, end $end") + async(Dispatchers.Default) { decryptStreamChunk(completeStreamBytes.copyOfRange(start, end), key) } + } + + // Wait for all decryption tasks to complete and concatenate the results + deferredChunks.forEach { deferred -> + decChunk += deferred.await() + } + + val endTime = System.nanoTime() + val duration = endTime - startTime + println("Decryption took ${duration / 1_000_000} milliseconds") + } finally { + response.close() + byteStream.close() } - - val endTime = System.nanoTime() - val duration = endTime - startTime - println("Decryption took ${duration / 1_000_000} milliseconds") - - response.close() } }