package com.github.felixgail.gplaymusic.api; import com.github.felixgail.gplaymusic.exceptions.NetworkException; import com.github.felixgail.gplaymusic.model.Album; import com.github.felixgail.gplaymusic.model.Artist; import com.github.felixgail.gplaymusic.model.Config; import com.github.felixgail.gplaymusic.model.DeviceInfo; import com.github.felixgail.gplaymusic.model.MutationResponse; import com.github.felixgail.gplaymusic.model.Playlist; import com.github.felixgail.gplaymusic.model.PlaylistEntry; import com.github.felixgail.gplaymusic.model.PodcastSeries; import com.github.felixgail.gplaymusic.model.Station; import com.github.felixgail.gplaymusic.model.Track; import com.github.felixgail.gplaymusic.model.enums.Provider; import com.github.felixgail.gplaymusic.model.enums.StreamQuality; import com.github.felixgail.gplaymusic.model.listennow.ListListenNowItemResponse; import com.github.felixgail.gplaymusic.model.listennow.ListenNowSituation; import com.github.felixgail.gplaymusic.model.requests.IncrementPlaycountRequest; import com.github.felixgail.gplaymusic.model.requests.ListStationTracksRequest; import com.github.felixgail.gplaymusic.model.requests.PagingRequest; import com.github.felixgail.gplaymusic.model.requests.SearchTypes; import com.github.felixgail.gplaymusic.model.requests.SharedPlaylistRequest; import com.github.felixgail.gplaymusic.model.requests.TimeZoneOffset; import com.github.felixgail.gplaymusic.model.requests.mutations.Mutator; import com.github.felixgail.gplaymusic.model.responses.GenreResponse; import com.github.felixgail.gplaymusic.model.responses.ListResult; import com.github.felixgail.gplaymusic.model.responses.SearchResponse; import com.github.felixgail.gplaymusic.model.responses.SharedPlaylistEntryListResult; import com.github.felixgail.gplaymusic.util.language.Language; import java.io.IOException; import java.util.Locale; import java.util.Map; import retrofit2.Call; import retrofit2.Response; import retrofit2.http.Body; import retrofit2.http.GET; import retrofit2.http.Header; import retrofit2.http.POST; import retrofit2.http.Path; import retrofit2.http.Query; import retrofit2.http.QueryMap; import retrofit2.http.Url; public interface GPlayService { @GET("sj/v2.5/query") Call<SearchResponse> search(@Query("q") String query, @Query("max-results") int maxResults, @Query("ct") SearchTypes searchTypes); @GET("sj/v2.5/config?dv=0&tier=ff") Call<Config> config(@Query("hl") Locale locale); @GET("music/{provider}?net=mob&pt=e") Call<Void> getTrackLocationMJCK(@Header("X-Device-ID") String androidID, @Path("provider") Provider provider, @Query("opt") StreamQuality quality, @Query("slt") String salt, @Query("sig") String signature, @Query("mjck") String trackID, @QueryMap Map<String, String> kwargs); @GET("music/{provider}?net=mob&pt=e") Call<Void> getTrackLocationSongId(@Header("X-Device-ID") String androidID, @Path("provider") Provider provider, @Query("opt") StreamQuality quality, @Query("slt") String salt, @Query("sig") String signature, @Query("songid") String trackID, @QueryMap Map<String, String> kwargs); @GET("sj/v2.5/devicemanagementinfo") Call<ListResult<DeviceInfo>> getDevices(); @POST("sj/v2.5/ephemeral/top") Call<ListResult<Track>> getPromotedTracks(); @POST("sj/v2.5/radio/station") Call<ListResult<Station>> listStations(); @POST("sj/v2.5/radio/station") Call<ListResult<Station>> listStations(@Body PagingRequest body); @POST("sj/v2.5/playlistfeed") Call<ListResult<Playlist>> listPlaylists(); @POST("sj/v2.5/playlistfeed") Call<ListResult<Playlist>> listPlaylists(@Body PagingRequest body); @POST("sj/v2.5/trackfeed") Call<ListResult<Track>> listTracks(); @POST("sj/v2.5/trackfeed") Call<ListResult<Track>> listTracks(@Body PagingRequest body); @GET("sj/v2.5/podcast/browse") Call<ListResult<PodcastSeries>> listBrowsePodcastSeries(@Query("id") String genre); @GET("sj/v2.5/listennow/getlistennowitems") Call<ListListenNowItemResponse> listListenNowItems(); @POST("sj/v2.5/listennow/situations") Call<ListenNowSituation> getListenNowSituation(@Body TimeZoneOffset offset); /** * As far as my understanding goes, this simply returns a list containing every {@link * PlaylistEntry} from every {@link Playlist} that is {@link Playlist.PlaylistType#USER_GENERATED}.<br> * <p> Entries from {@link Playlist.PlaylistType#SHARED} playlists that the user is subscribed to * are <b>not</b> included. To fetch contents from such a playlist use {@link * #listSharedPlaylistEntries(SharedPlaylistRequest)}. <p> The Server has no option to return the * contents of a single private Playlist. * * @return the {@link Call} to request a list of {@link PlaylistEntry} */ @POST("sj/v2.5/plentryfeed") Call<ListResult<PlaylistEntry>> listPrivatePlaylistEntries(); /** * As far as my understanding goes, this simply returns a list containing every {@link * PlaylistEntry} from every {@link Playlist} that is {@link Playlist.PlaylistType#USER_GENERATED}.<br> * <p> Entries from {@link Playlist.PlaylistType#SHARED} playlists that the user is subscribed to * are <b>not</b> included. To fetch contents from such a playlist use {@link * #listSharedPlaylistEntries(SharedPlaylistRequest)}. <p> The Server has no option to return the * contents of a single private Playlist. * * @return the {@link Call} to request a list of {@link PlaylistEntry} */ @POST("sj/v2.5/plentryfeed") Call<ListResult<PlaylistEntry>> listPrivatePlaylistEntries(@Body PagingRequest body); @POST("sj/v2.5/plentries/shared") Call<SharedPlaylistEntryListResult> listSharedPlaylistEntries( @Body SharedPlaylistRequest request); @POST Call<MutationResponse> batchCall(@Url String path, @Body Mutator mutator); @POST("sj/v2.5/radio/stationfeed?") Call<ListResult<Station>> getFilledStations(@Body ListStationTracksRequest request); @POST("sj/v2.5/trackstats") Call<MutationResponse> incremetPlaycount(@Body IncrementPlaycountRequest request); @GET("sj/v2.5/explore/genres") Call<GenreResponse> getGenres(@Query("parent-genre") String parentGenre); @GET("sj/v2.5/fetchalbum") Call<Album> getAlbum(@Query("nid") String albumID, @Query("include-tracks") boolean includeTracks); @GET("sj/v2.5/fetchtrack") Call<Track> fetchTrack(@Query("nid") String trackId); /** * Fetches for an artist by {@code artistID}. * * @param artistID {@link Artist#getArtistId()} of the artist searched for. * @param includeAlbums whether albums of the artist shall be included in the response. * @param numTopTracks response includes up to provided number of most heard songs in response * @param numRelArtist response includes up to provided number of similar artist in response * @return An executable call which returns an artist on execution. */ @GET("sj/v2.5/fetchartist") Call<Artist> getArtist(@Query("nid") String artistID, @Query("include-albums") boolean includeAlbums, @Query("num-top-tracks") int numTopTracks, @Query("num-related-artists") int numRelArtist); default MutationResponse makeBatchCall(String path, Mutator body) throws IOException { Response<MutationResponse> response = batchCall("sj/v2.5/" + path, body).execute(); if (!response.body().checkSuccess()) { NetworkException exception = new NetworkException(400, Language.get("network.GenericError")); exception.setResponse(response.raw()); throw exception; } return response.body(); } }