Skip to content

Commit

Permalink
Add proxy option in settings & Fix some fallback songs
Browse files Browse the repository at this point in the history
  • Loading branch information
LuftVerbot committed May 31, 2024
1 parent 2d79e09 commit c3d105d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.brahmkshatriya.echo.extension

import android.annotation.TargetApi
import android.os.Build
import dev.brahmkshatriya.echo.common.models.Album
import dev.brahmkshatriya.echo.common.models.Artist
import dev.brahmkshatriya.echo.common.models.EchoMediaItem
Expand All @@ -15,6 +17,8 @@ import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import java.time.Instant
import java.util.Date


fun JsonElement.toMediaItemsContainer(
Expand Down Expand Up @@ -72,6 +76,7 @@ fun JsonElement.toAlbum(): Album {
id = data["ALB_ID"]?.jsonPrimitive?.content ?: "",
title = data["ALB_TITLE"]?.jsonPrimitive?.content ?: "",
cover = getCover(md5, "cover"),
tracks = jsonObject["SONGS"]?.jsonObject?.get("total")?.jsonPrimitive?.int,
artists = listOf(
Artist(
id = artistObject?.get("ART_ID")?.jsonPrimitive?.content ?: "",
Expand All @@ -96,6 +101,7 @@ fun JsonElement.toArtist(): Artist {
)
}

@TargetApi(Build.VERSION_CODES.O)
fun JsonElement.toTrack(): Track {
val data = jsonObject["data"]?.jsonObject ?: jsonObject
val md5 = data["ALB_PICTURE"]?.jsonPrimitive?.content ?: ""
Expand All @@ -105,6 +111,8 @@ fun JsonElement.toTrack(): Track {
id = data["SNG_ID"]!!.jsonPrimitive.content,
title = data["SNG_TITLE"]!!.jsonPrimitive.content,
cover = getCover(md5, "cover"),
duration = data["DURATION"]?.jsonPrimitive?.content?.toLong()?.times(1000),
releaseDate = Date.from(Instant.ofEpochSecond(data["DATE_ADD"]?.jsonPrimitive?.content?.toLong() ?: 0)).toString(),
artists = listOf(
Artist(
id = artistObject?.get("ART_ID")?.jsonPrimitive?.content ?: "",
Expand Down
14 changes: 10 additions & 4 deletions app/src/main/java/dev/brahmkshatriya/echo/extension/DeezerApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ class DeezerApi {
private val pass: String
get() = DeezerCredentials.pass

private val client: OkHttpClient = OkHttpClient.Builder()
.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved("uk.proxy.murglar.app", 3128)))
.addInterceptor { chain ->
private val proxy: Boolean
get() = DeezerUtils.proxy

private val client: OkHttpClient = OkHttpClient.Builder().apply {
addInterceptor { chain ->
val originalResponse = chain.proceed(chain.request())
if (originalResponse.header("Content-Encoding") == "gzip") {
val gzipSource = GZIPInputStream(originalResponse.body?.byteStream())
Expand All @@ -70,7 +72,11 @@ class DeezerApi {
} else {
originalResponse
}
}.build()
}
if(proxy) {
proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved("uk.proxy.murglar.app", 3128)))
}
}.build()

private val json = Json {
isLenient = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ object DeezerCredentials {

object DeezerUtils {
var arl_expired: Boolean = false
var proxy: Boolean = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie
"128",
"Use 128kbps(overrides FLAC option)",
false
),
SettingSwitch(
"Use Proxy",
"proxy",
"Use Proxy against geo-blocking",
false
)
)

Expand All @@ -73,6 +79,9 @@ 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

Expand All @@ -85,6 +94,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie

override suspend fun getHomeTabs(): List<Tab> {
if (arl == "" || arlExpired) return emptyList()
DeezerUtils.proxy = proxy
val jObject = DeezerApi().homePage()
val resultObject = jObject["results"]!!.jsonObject
val sections = resultObject["sections"]!!.jsonArray
Expand All @@ -100,6 +110,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie

override fun getHomeFeed(tab: Tab?): PagedData<MediaItemsContainer> = PagedData.Single {
if(arl == "" || arlExpired) throw loginRequiredException
DeezerUtils.proxy = proxy
val dataList = mutableListOf<MediaItemsContainer>()
val jsonData = json.decodeFromString<JsonArray>(tab?.extras!!["sections"].toString())
jsonData.map { section ->
Expand All @@ -126,6 +137,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie

override suspend fun getLibraryTabs(): List<Tab> {
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 ->
Expand Down Expand Up @@ -170,6 +182,7 @@ 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<MediaItemsContainer>()
when (tabId) {
Expand Down Expand Up @@ -232,11 +245,13 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie

override suspend fun addTracksToPlaylist(playlist: Playlist, tracks: List<Track>, index: Int, new: List<Track>) {
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(
Expand All @@ -250,16 +265,19 @@ 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
Expand All @@ -271,6 +289,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie

override suspend fun listEditablePlaylists(): List<Playlist> {
if(arl == "" || arlExpired) throw loginRequiredException
DeezerUtils.proxy = proxy
val playlistList = mutableListOf<Playlist>()
val jsonObject = DeezerApi().getPlaylists()
val resultObject = jsonObject["results"]!!.jsonObject
Expand All @@ -289,19 +308,22 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie

override suspend fun moveTrackInPlaylist(playlist: Playlist, tracks: List<Track>, 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)
}

override suspend fun removeTracksFromPlaylist(playlist: Playlist, tracks: List<Track>, indexes: List<Int>) {
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
Expand All @@ -320,6 +342,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie
private var oldSearch: Pair<String, List<MediaItemsContainer>>? = 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")
Expand All @@ -343,6 +366,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie

override suspend fun searchTabs(query: String?): List<Tab> {
if (arl == "" || arlExpired) return emptyList()
DeezerUtils.proxy = proxy
query ?: return emptyList()
val jsonObject = DeezerApi().search(query)
val resultObject = jsonObject["results"]!!.jsonObject
Expand Down Expand Up @@ -378,6 +402,7 @@ 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)
Expand All @@ -398,10 +423,9 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie
val code = client.newCall(request).execute().code
if (code == 403) {
val fallbackObject = fetchTrackData(track)["FALLBACK"]!!.jsonObject
val backId = fallbackObject["SNG_ID"]?.jsonPrimitive?.content ?: ""
val backMd5Origin = fallbackObject["MD5_ORIGIN"]?.jsonPrimitive?.content ?: ""
val backMediaVersion = fallbackObject["MEDIA_VERSION"]?.jsonPrimitive?.content ?: ""
url = generateTrackUrl(backId, backMd5Origin, backMediaVersion, 1)
url = generateTrackUrl(trackId, backMd5Origin, backMediaVersion, 1)
}
return url
}
Expand All @@ -421,7 +445,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie
val newDataObject = fetchTrackData(newTrack)
val md5Origin = newDataObject["MD5_ORIGIN"]?.jsonPrimitive?.content ?: ""
val mediaVersion = newDataObject["MEDIA_VERSION"]?.jsonPrimitive?.content ?: ""
generateUrl(newTrack.id, md5Origin, mediaVersion)
generateUrl(track.id, md5Origin, mediaVersion)
}
else -> {
val dataObject = jsonObject["data"]!!.jsonArray.first().jsonObject
Expand Down Expand Up @@ -453,12 +477,14 @@ 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<Track> = PagedData.Single {
DeezerUtils.proxy = proxy
val jsonObject = DeezerApi().album(album)
val resultsObject = jsonObject["results"]!!.jsonObject
val songsObject = resultsObject["SONGS"]!!.jsonObject
Expand All @@ -472,6 +498,7 @@ 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
Expand All @@ -483,12 +510,14 @@ 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<Track> = PagedData.Single {
DeezerUtils.proxy = proxy
val jsonObject = DeezerApi().playlist(playlist)
val resultsObject = jsonObject["results"]!!.jsonObject
val songsObject = resultsObject["SONGS"]!!.jsonObject
Expand All @@ -502,6 +531,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie
//<============= Artist =============>

override fun getMediaItems(artist: Artist) = PagedData.Single {
DeezerUtils.proxy = proxy
val dataList = mutableListOf<MediaItemsContainer>()
val jsonObject = DeezerApi().artist(artist)

Expand Down Expand Up @@ -550,6 +580,7 @@ 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()
Expand All @@ -565,6 +596,7 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie
override val loginWebViewStopUrlRegex = "https://www\\.deezer\\.com/account/.*".toRegex()

override suspend fun onLoginWebviewStop(url: String, data: String): List<User> {
DeezerUtils.proxy = proxy
if (data.contains("arl=")) {
DeezerCredentials.arl = data.substringAfter("arl=").substringBefore(";")
DeezerCredentials.sid = data.substringAfter("sid=").substringBefore(";")
Expand All @@ -587,13 +619,15 @@ class DeezerExtension : ExtensionClient, HomeFeedClient, TrackClient, SearchClie
)

override suspend fun onLogin(data: Map<String, String?>): List<User> {
DeezerUtils.proxy = proxy
DeezerCredentials.arl = data["arl"] ?: ""
DeezerApi().getSid()
val userList = DeezerApi().makeUser()
return userList
}

override suspend fun onLogin(username: String, password: String): List<User> {
DeezerUtils.proxy = proxy
// Set shared credentials
DeezerCredentials.email = username
DeezerCredentials.pass = password
Expand Down

0 comments on commit c3d105d

Please sign in to comment.