Java tutorial
/* * Copyright (c) 2011 - 2016 by Edward J. Becker * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package controllers; import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpRequestInitializer; import com.google.api.client.json.Json; import com.google.api.services.youtube.YouTube; import com.google.api.services.youtube.YouTubeRequestInitializer; import com.google.api.services.youtube.model.Video; import com.google.api.services.youtube.model.VideoListResponse; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.io.IOException; import java.net.URLEncoder; import java.util.*; import jobs.YoutubeJob; import models.*; import org.joda.time.DateTime; import play.libs.WS; import play.libs.WS.HttpResponse; import play.libs.WS.WSRequest; import play.mvc.*; import play.Logger; import play.Play; import play.data.binding.NoBinding; import utils.Auth; import utils.MetricsReporter; import utils.RdioHelper; /** * * @author Edward Becker * */ public class Rdio extends Controller { public static String endpoint = "http://api.napster.com/v2.1/"; public static String NAPSTER_TOKEN_ENDPOINT = "https://api.napster.com/oauth/access_token"; public static Random generator = new Random(); private static MyOAuthClient connector = null; // This object is used to make YouTube Data API requests. The last // argument is required, but since we don't need anything // initialized when the HttpRequest is initialized, we override // the interface and provide a no-op function. private static YouTube youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, new HttpRequestInitializer() { public void initialize(HttpRequest request) throws IOException { } }).setYouTubeRequestInitializer( new YouTubeRequestInitializer(Play.configuration.getProperty("youtube.key"))) .setApplicationName("zMusicCafe").build(); public static MyOAuthClient getConnector(User user) { if (connector == null) { // See if its in cache connector = user.authClient; if (connector == null) { connector = new MyOAuthClient(null, null, null, Play.configuration.getProperty("rdio.key"), Play.configuration.getProperty("rdio.secret")); user.authClient = connector; user.save(); } } return connector; } public static boolean setupTokens(User user, String code, int retryAttempt) { Logger.info("Setuptokens"); if (retryAttempt > 1) { return false; } retryAttempt++; String url = NAPSTER_TOKEN_ENDPOINT; String charset = "UTF-8"; WS.WSRequest wsRequest = WS.url(url); //Logger.info(url); if (user.rdioCreds != null) { //Logger.info("Secret: " + user.rdioCreds.secret); } if (code == null && (user.rdioCreds != null && user.rdioCreds.secret != null)) { Logger.info("Getting refresh token for " + user.firstName); wsRequest.parameters.put("code", code); wsRequest.parameters.put("grant_type", "refresh_token"); } else { Logger.info("Getting auth code for " + user.firstName); if (code != null) { wsRequest.parameters.put("code", code); } wsRequest.parameters.put("grant_type", "authorization_code"); } wsRequest.parameters.put("redirect_uri", Play.configuration.getProperty("application.baseUrl") + "redirectRDIO"); wsRequest.parameters.put("client_id", Play.configuration.getProperty("rdio.key")); wsRequest.parameters.put("client_secret", Play.configuration.getProperty("rdio.secret")); if (user.rdioCreds != null && user.rdioCreds.secret != null) { wsRequest.parameters.put("refresh_token", user.rdioCreds.secret); } HttpResponse wsResponse = wsRequest.post(); String responseString = wsResponse.getString(charset); Logger.info("Token response: " + responseString); if (responseString.contains("Authentication code not valid")) { Logger.error("No way to re-authenticate user. Authentication code not valid. Clearing tokens"); user.performedNapsterCheck = false; // re-ask napster check user.rdioCreds = null; user.save(); return false; } else if (responseString.contains("Refresh token not valid")) { Logger.error("No way to re-authenticate user. Refresh token not valid .clearing tokens"); user.performedNapsterCheck = false; // re-ask napster check user.rdioCreds = null; user.save(); return false; } // if (responseString.contains("error")){ // Logger.error("FIX THIS CODE OR REMOVE IT " + responseString); // // Probably rdio token needs refreshing. let's clear auth creds and retry //// user.rdioCreds.secret = null; //// user.save(); //// return setupTokens(user, code, retryAttempt); // } RDIOTokenResponse tokenResponse = new RDIOTokenResponse(); Gson gson = new Gson(); // We know from experience that an error here usually indicates a bad rdio token try { tokenResponse = gson.fromJson(responseString, tokenResponse.getClass()); } catch (Exception e) { Logger.error("Exception parsing token response: " + tokenResponse + " Exception:" + e.getMessage()); // Lets clear auth completely user.rdioCreds.secret = null; user.save(); return false; } //Logger.info("Token response:" + tokenResponse.access_token +"/" + tokenResponse.refresh_token); if (user.rdioCreds == null) { user.rdioCreds = new AuthCredentials(); } user.rdioCreds.token = tokenResponse.access_token; user.rdioCreds.secret = tokenResponse.refresh_token; Logger.info("Token Expires IN:" + tokenResponse.expires_in); Date then = new Date(new Date().getTime() + (tokenResponse.expires_in * 1000)); Logger.info("Then:" + then.toString()); user.rdioCreds.expiryDate = then; user.rdioCreds.code = code; user.rdioCreds.save(); Logger.info("Created new auth tokens for " + user.firstName + " :" + user.rdioCreds.getToken()); user.save(); return true; } @NoBinding public static Track searchExactMatch(User user, String trackName, String artistName, String albumName, Track track) { return searchExactMatchUpdateTrackRdio(user, trackName, artistName, albumName, track); } @NoBinding public static ArrayList<Track> searchTrack(User user, String trackName, AuthCredentials backupCredentials) { if (user.rdioCreds == null) { Logger.info("Attempting to searchTrack without Catalog API credentials rejected."); return null; } //Logger.info("Rdio.searchTrack:" + trackName); ArrayList trackResults = null; // try { String url = endpoint + "search"; WSRequest sign; try { sign = getConnector(user).sign(user.rdioCreds == null ? backupCredentials : user.rdioCreds, WS.url(url), "GET"); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return null; } sign.setParameter("method", "search"); sign.setParameter("apikey", Play.configuration.getProperty("rdio.secret")); sign.setParameter("type", "track"); sign.setParameter("q", trackName); sign.setParameter("limit", 35); sign.setParameter("preference", "editorial"); JsonElement searchResult = sign.get().getJson(); if (searchResult.toString().contains("{\"code\":\"UnauthorizedError\",\"message\":\"Unauthorized\"}")) { Logger.error(searchResult.toString()); Logger.error(user.firstName + " is unauthorized.. @TODO add logic to setup token"); if (setupTokens(user, user.rdioCreds.code, 0)) { searchResult = sign.get().getJson(); } else { Logger.error("Severe error searching track for user " + user.firstName); return null; } } else if (searchResult.toString().toLowerCase().contains("unauthorized")) { Logger.error("Picking up unauthorized with wrong message: " + searchResult.toString()); } trackResults = new ArrayList(); JsonObject rdioTrack; if (searchResult == null) { Logger.info("Null search object getting " + trackName); } JsonObject dataObj = searchResult.getAsJsonObject(); JsonArray jArray = dataObj.get("data").getAsJsonArray(); for (JsonElement rdioTrackElement : jArray) { rdioTrack = rdioTrackElement.getAsJsonObject(); //Logger.info("type:" + rdioTrack.get("type").getAsString()); Track track = Track.retrieveTrackByRadioId(rdioTrack.get("id").getAsString()); if (track != null && track.coverArt.equals("http://www.zmusiccafe.com/public/images/missing-album-art.png")) { //Logger.warn("Reparsing missing album image art for existing track"); track.coverArt = "http://direct.rhapsody.com/imageserver/v2/albums/" + track.albumKey + "/images/200x200.jpg"; track.save(); } ; if (track == null) { Logger.info("Finding Similar track with network"); track = Track.find("byTitleAndAlbum_NameAndArtistAndNetwork", rdioTrack.get("name").getAsString(), rdioTrack.get("albumName").getAsString(), rdioTrack.get("artistName").getAsString(), "rdio") .first(); if (track != null && track.coverArt.equals("http://www.zmusiccafe.com/public/images/missing-album-art.png")) { //Logger.warn("Reparsing missing album iamage art"); track.coverArt = "http://direct.rhapsody.com/imageserver/v2/albums/" + track.albumKey + "/images/200x200.jpg"; track.save(); } if (track == null) { Logger.info("Finding similar track with no network"); track = Track.find("byTitleIlikeAndAlbum_NameIlikeAndArtistIlikeAndNetworkIsNull", rdioTrack.get("name").getAsString(), rdioTrack.get("albumName").getAsString(), rdioTrack.get("artistName").getAsString()).first(); if (track != null && track.coverArt .equals("http://www.zmusiccafe.com/public/images/missing-album-art.png")) { //Logger.warn("Reparsing missing album iamage art"); track.coverArt = "http://direct.rhapsody.com/imageserver/v2/albums/" + track.albumKey + "/images/200x200.jpg"; track.save(); } } if (track == null) { //Logger.info("Creating new track:" + rdioTrack.toString()); track = new Track(); track = RdioHelper.parseNewTrack(user, track, rdioTrack, false); track.save(); // YoutubeJob ty = new YoutubeJob(track); // ty.loadYoutubes(); // if (track.bestYoutubeMatch() == null || track.bestYoutubeMatch().getId() == null){ // Logger.info("No you tube match for :" + track.artist + ":" + track.title); // } else { // track.youtube_id = ty.bestYouTubeMatch().getId().getVideoId().toString(); // track.youtube_duration = getDuration(track.youtube_id); // } } else { // @TODO I don't think we need to do this, we have the track Logger.error("Why reparsing track " + track.title); // @TODO what does this have to do with anything? //RdioHelper.parseNewTrack(user, track, rdioTrack); } } // track.save(); if (track.canStream) { trackResults.add(track); } } return trackResults; } @NoBinding public static Track searchExactMatchUpdateTrackRdio(User user, String trackName, String artistName, String albumName, Track updateTrack) { // Logger.info("Searching" + trackName); Track matchedTrack = updateTrack; Track exactMatch = null; if (updateTrack != null) { // Force entity reload updateTrack = Track.findById(updateTrack.id); // Logger.info("Last time we tried to search " + trackName + "/" + albumName + "/" + artistName +":" + updateTrack.lastNoMatchLookupDate); if (updateTrack.lastNoMatchLookupDate != null) { return updateTrack; } updateTrack.lastNoMatchLookupDate = new Date(); updateTrack.save(); } Logger.info("Searching catalog API for " + trackName + "/" + albumName + "/" + artistName); AuthCredentials rdioCreds = user.rdioCreds; if (rdioCreds == null) { rdioCreds = user.room.owner.rdioCreds; } if (rdioCreds == null) { Logger.info("Unable to search catalog to no catalog credentials"); return null; } String url = endpoint + "search"; WSRequest sign; try { sign = getConnector(user).sign(rdioCreds, WS.url(url), "POST"); } catch (Exception ex) { Logger.error("Exception with endpoint" + ex.toString()); Logger.error("Exception with endpoint message " + ex.getMessage()); ex.printStackTrace(); return null; } sign.setHeader("Content-type", "application/json"); String query = trackName; if (artistName != null) { query = query + " " + artistName; } if (albumName != null) { query = query + " " + albumName; } /* @TODO we need to paginate these results */ query = query + "&type=track"; sign.setParameter("q", URLEncoder.encode(query)); sign.setParameter("limit", "" + 1000); JsonElement searchResult; try { searchResult = sign.get().getJson(); } catch (Exception e) { Logger.error(" Error getting json: " + e.getMessage()); return null; } // @TODO this is completely retarted. Let's look for real error codes instead. // if (searchResult.toString().contains("Unauthorized")){ // // Logger.info(searchResult.toString()); // Logger.error(user.firstName + " is unauthorized.. attempting to setup tokens and trying again..."); // // setupTokens(null, 0); // Logger.info("Resigning request"); // try { // sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); // } catch (Exception ex) { // Logger.error(ex.toString()); // ex.printStackTrace(); // return null; // } // try { // searchResult = sign.get().getJson(); // } catch (Exception e){ // MetricsReporter.sendMetric("rhapsody.unauthorizederror2 1"); // Logger.info("Search Napster error:" + e.getMessage()); // return null; // } // // if (searchResult.toString().contains("Unauthorized")) { // updateTrack.lastNoMatchLookupDate = null; // updateTrack.save(); // Logger.info(searchResult.toString()); // Logger.error(user.firstName + " is still unauthorized.. giving up. @TODO send UI an event to request re-login."); // MetricsReporter.sendMetric("rhapsody.unauthorizederror 1"); // } // } JsonArray resultArray = null; //try { resultArray = searchResult.getAsJsonObject().getAsJsonArray("data"); // } catch (Exception e){ // Logger.info("Error retrieving result from Napster:" + e.getMessage()); // updateTrack.lastNoMatchLookupDate = null; // updateTrack.save(); // Logger.info(searchResult.toString()); // return null; // } Track track = updateTrack; // if (track != null) { // Logger.info("Attempting to update existing track: " + track.title + "/" + track.album_name + "/" + track.artist); // } Logger.info("Catalog API returned " + resultArray.size() + " results"); // Note that we will load all tracks, but only return the last one we found, so that they at least get seeded in the library for (JsonElement rdioTrackElement : resultArray) { JsonObject rdioTrack = rdioTrackElement.getAsJsonObject(); if (rdioTrack.get("id").getAsString().startsWith("Tra")) { // Object's type if (track != null && track.rdio_id != null && track.rdio_id.equals(rdioTrack.get("id").getAsString())) { Logger.info("!!Found same track with id " + track.rdio_id + "... updating"); if (track.coverArt.equals("http://www.zmusiccafe.com/public/images/missing-album-art.png") || track.coverArt == null) { Logger.warn("Missing album art for " + track.title + ": Reparsing."); } RdioHelper.parseNewTrack(user, track, rdioTrack, true); exactMatch = track; continue; } //Logger.info("looking for closet match"); String closeMatchTitle = rdioTrack.get("name").getAsString().replace("(Album Version)", "") .replace("(Album Version)", "").replace("(Remastered)", "").replace("(Radio Edit)", "") .trim(); /** * See if we need to load this track while we have it. */ Track loadTrack = Track.retrieveTrackByRadioId(rdioTrack.get("id").getAsString()); if (loadTrack == null) { loadTrack = new Track(); //Logger.info("searchExactMatchUpdateTrackRdio calling parseNewTrack"); RdioHelper.parseNewTrack(user, loadTrack, rdioTrack, true); } if (loadTrack.title.equals(closeMatchTitle) && loadTrack.artist .equalsIgnoreCase(rdioTrack.get("artist").getAsJsonObject().get("name").getAsString())) { if (exactMatch == null) { Logger.info("Exact match" + loadTrack.title + "/" + loadTrack.artist); exactMatch = loadTrack; } } else { matchedTrack = loadTrack; } } } if (exactMatch != null) { return exactMatch; } else { return matchedTrack; } } public static Album retrieveAlbumByRdioId(User user, String album_key) { //Logger.info("Retrieving album by ID:" + album_key); Album album = Album.find("byRdio_Key", album_key).first(); if (album != null && album.tracksLoaded == true && album.albumTracks != null && album.albumTracks.size() > 1) { return album; } // Logger.info("Album not (fully) loaded, loading..."); WSRequest sign = null; String url = endpoint + "/albums/" + album_key + "?include=tracks,images"; boolean rerequest = false; try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); } catch (Exception ex) { Logger.error("User " + user.firstName + " had error with credentials"); Logger.error(ex.toString()); ex.printStackTrace(); rerequest = true; } if (rerequest) { setupTokens(user, null, 0); try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return null; } } JsonElement json = sign.get().getJson(); if (json.toString().equalsIgnoreCase("{\"code\":\"UnauthorizedError\",\"message\":\"Unauthorized\"}")) { json = reasssignCatalogAPIAccessToken(user, url, null); } if (json == null) { Logger.error("XZK:001 Null search result for " + user.firstName + " for album key" + album_key); return null; } JsonArray searchArray = json.getAsJsonObject().getAsJsonArray("albums"); JsonObject searchResult; if (searchArray == null) { Logger.error("Null searchArray in Rdio.java"); Logger.info(json.toString()); return null; } // Logger.info(searchArray.toString()); if (searchArray.size() < 1) { // @TODO Add flag to album to ignore in future Logger.error("Album " + album_key + " is missing from Napster catalog"); return null; } searchResult = searchArray.get(0).getAsJsonObject(); if (album == null) { Logger.info("No album at all, creating..0"); album = new Album(); } if (searchResult.get("name") == null) { Logger.error("Strange error:" + searchResult.toString()); return null; } album.rdio_key = album_key; album.name = searchResult.get("name").getAsString(); album.artist = searchResult.getAsJsonPrimitive("artistName").getAsString(); String dateString = searchResult.getAsJsonPrimitive("released").getAsString(); album.releaseDate = new DateTime(dateString).toDate(); JsonObject linked = searchResult.getAsJsonObject("linked"); JsonArray imagesArray = linked.getAsJsonArray("images"); JsonElement imageElement = imagesArray.get(0); album.icon = imageElement.getAsJsonObject().get("url").getAsString(); album.baseIcon = album.icon; album.bigIcon = album.icon; JsonArray tracks = linked.getAsJsonArray("tracks"); Iterator<JsonElement> iterator = tracks.iterator(); int trackNum = 1; album.albumTracks = new ArrayList<Track>(); int tracksAdded = 0; while (iterator.hasNext()) { JsonObject trackObj = iterator.next().getAsJsonObject(); Track track = Track.find("byRdio_Id", trackObj.get("id").getAsString()).first(); if (track == null) { track = new Track(); RdioHelper.parseNewTrack(user, track, trackObj, true); } // Make sure track is not already present boolean trackPresent = false; Iterator iter = album.albumTracks.iterator(); while (iter.hasNext()) { Track albumTrack = (Track) iter.next(); if (albumTrack.rdio_id == track.rdio_id) { trackPresent = true; break; } } if (trackPresent) { Logger.error("Trying to add a track to an album but it already exists in album!"); } else { tracksAdded++; track.album = album; album.albumTracks.add(track); } } album.tracksLoaded = true; album.save(); //Logger.info("Saved album " + album.rdio_key + " and added " + tracksAdded + " tracks."); return album; } private static JsonObject reasssignCatalogAPIAccessToken(User user, String url, JsonObject searchResult) { WSRequest sign; //Logger.info("!!!" + searchResult.toString()); if (searchResult == null || searchResult.toString() .contains("{\"code\":\"UnauthorizedError\",\"message\":\"Unauthorized\"}")) { if (searchResult == null) { Logger.error(user.firstName + " is unauthorized.. reassigning tokens."); // Message: " + searchResult.toString()); } else { Logger.error(user.firstName + " is unauthorized.. reassigning tokens. Message: " + searchResult.toString()); } MetricsReporter.sendMetric("rhapsody.unauthorizederror 1"); // Let's setup tokens and try again setupTokens(user, null, 0); if (user.rdioCreds == null) { Logger.error("Severe error retrieving and even reassiging tokens for " + user.firstName); return null; } try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return null; } searchResult = sign.get().getJson().getAsJsonObject(); if (searchResult.toString().contains("Unauthorized")) { Logger.info(searchResult.toString()); Logger.error(user.firstName + " is unauthorized"); MetricsReporter.sendMetric("catalog.unauthorizederror 1"); return null; } } return searchResult; } /* * * */ // public static List retrieveAlbumsForArtist(User user, String artist_key) { // Logger.info("Rdio.retrieveAlbumsForArtist" + artist_key); // // // // Now load discography // // ArrayList<Album> albumResults = new ArrayList(); // WSRequest sign; // // String url = endpoint + "artists/" + artist_key + "/albums" +"?apikey=" + Play.configuration.getProperty("rdio.key") + "&limit=200"; // // Logger.info(url); // // try { // sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); // } catch (Exception ex) { // Logger.error(ex.toString()); // ex.printStackTrace(); // return albumResults; // } // // JsonElement searchResult = sign.get().getJson(); // // JsonArray discs = searchResult.getAsJsonArray(); // //Logger.info(discs.toString()); // // // Iterator<JsonElement> discsIterator = discs.iterator(); // // while (discsIterator.hasNext()){ // JsonElement elem = discsIterator.next(); // JsonObject jsonAlbum = elem.getAsJsonObject(); // String aKey = jsonAlbum.get("id").getAsString(); // // Logger.info("Getting album for key" + aKey); // Album album = Album.find("byRdio_key", aKey).first(); // // if (album != null) { // Logger.info("Found album " + album.rdio_key); // Album foundAlbum = album; // // AlbumRating albumRating = AlbumRating.find("byUserAndRdio_key", user, foundAlbum.rdio_key).first(); // foundAlbum.album_rating = albumRating; // Logger.info("FF album " + foundAlbum.name); // // if (album.albumTracks.size() < 1){ // Logger.error("Missing album tracks for album!"); // //continue; //// album = new Album(); //// //// album.rdio_key = aKey; //// //// album.name = jsonAlbum.get("name").getAsString(); //// //// album.artist = jsonAlbum.getAsJsonObject("artist").get("name").getAsString(); //// if (jsonAlbum.get("duration") != null) { //// album.duration = jsonAlbum.get("duration").getAsInt(); //// } //// album.albumTracks = new ArrayList(); //// album.save(); //// albumResults.add(album); // // } // //continue; // } else { // Logger.info("No matches for album, so creating loading album for artist " +artist_key); // album = new Album(); // // album.rdio_key = aKey; // // album.name = jsonAlbum.get("name").getAsString(); // // album.artist = jsonAlbum.getAsJsonObject("artist").get("name").getAsString(); // if (jsonAlbum.get("duration") != null) { // album.duration = jsonAlbum.get("duration").getAsInt(); // } // album.albumTracks = new ArrayList(); // // // } // // Grab album detail // Logger.info("Have album " + album.name); // // url = endpoint + "albums/" + album.rdio_key; // try { // sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); // sign.setParameter("apikey", Play.configuration.getProperty("rdio.key")); // sign.setParameter("limit", "100"); // } catch (Exception ex) { // Logger.error(ex.toString()); // ex.printStackTrace(); // return albumResults; // } // // elem = sign.get().getJson(); // JsonArray images = elem.getAsJsonObject().get("images").getAsJsonArray(); // album.icon = images.get(0).getAsJsonObject().get("url").getAsString(); // album.bigIcon = album.icon; // album.baseIcon = album.icon; // album.releaseDate = new Date(jsonAlbum.get("released").getAsLong()); // album.duration = new Integer(0); // // Logger.info("Before album save"); // album.save(); // Logger.info("loading trtacks"); // // JsonArray tracks = elem.getAsJsonObject().get("tracks").getAsJsonArray(); // Iterator<JsonElement> trackIter = tracks.iterator(); // while (trackIter.hasNext()){ // JsonObject trackObj = trackIter.next().getAsJsonObject(); // // String trackId = trackObj.get("id").getAsString(); // // List AXtracks = Track.find("byRdio_id", trackId).fetch(); // // Track track = null; // if (AXtracks.size() > 0){ // track = (Track) AXtracks.get(0); // } // // album.save(); // if (track == null){ // track = new Track(); // RdioHelper.parseNewTrack(user, track, trackObj); // track.save(); // track.coverArt = album.icon; // } // boolean albumHasTrack = false; // Iterator tkIter = album.albumTracks.iterator(); // // while (tkIter.hasNext()){ // Track tkForID = (Track) tkIter.next(); // Track tk = Track.findById(tkForID.id); // if (tk.title.equals(track.title)){ // albumHasTrack = true; // } // // } // if (!albumHasTrack){ // Logger.info("Adding track " + track.title + "to album " + album.name); // album.albumTracks.add(track); // track.save(); // album.save(); // } // album.duration += (int) track.duration; // // } // // AlbumRating albumRating = AlbumRating.find("byUserAndRdio_key", user, album.rdio_key).first(); // // if (albumRating == null) { // Logger.info("Creating album rating"); // albumRating = new AlbumRating(); // albumRating.rdio_key = album.rdio_key; // albumRating.user = user; // albumRating.rating = -1L; // albumRating.artist_name = album.artist; // albumRating.album_name = album.name; // albumRating.numOfRatingStars = LibraryItem.getStarCount(albumRating.rating); // albumRating.save(); // } // // Logger.info("Duration:" + album.duration); // album.save(); // // Logger.info(albumResults.toString()); // Logger.info("Adding album results for " + album.name); // albumResults.add(album); // } // return albumResults; // } /* * * */ public static List retrieveAlbumsForArtist(User user, String artist_key) { Logger.info("Rdio.retrieveAlbumsForArtist" + artist_key); // Now load discography ArrayList<Album> albumResults = new ArrayList(); WSRequest sign; String url = endpoint + "artists/" + artist_key + "/albums" + "?apikey=" + Play.configuration.getProperty("rdio.key") + "&limit=200"; //Logger.info(url); try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return albumResults; } JsonElement searchResult = sign.get().getJson(); JsonElement albumsJsonElem = searchResult.getAsJsonObject().get("albums"); JsonArray albumsArray = albumsJsonElem.getAsJsonArray(); //Logger.info(searchResult.toString()); JsonArray discs = albumsArray; //Logger.info(discs.toString()); Iterator<JsonElement> iterator = discs.iterator(); while (iterator.hasNext()) { JsonElement elem = iterator.next(); JsonObject jsonAlbum = elem.getAsJsonObject(); String aKey = jsonAlbum.get("id").getAsString(); Album album = Album.find("byRdio_key", aKey).first(); if (album != null) { //Logger.info("Found album " + album.rdio_key); Album foundAlbum = album; AlbumRating albumRating = AlbumRating.find("byUserAndRdio_key", user, foundAlbum.rdio_key).first(); if (albumRating == null) { albumRating = new AlbumRating(); albumRating.rdio_key = foundAlbum.rdio_key; albumRating.user = user; albumRating.rating = -1L; albumRating.artist_name = foundAlbum.artist; albumRating.album_name = foundAlbum.name; albumRating.numOfRatingStars = LibraryItem.getStarCount(albumRating.rating); } foundAlbum.album_rating = albumRating; albumRating.save(); albumResults.add(foundAlbum); //Logger.info(foundAlbum.name); continue; } else { // Logger.info("No matches for album, so loading album " +artist_key); album = new Album(); album.albumTracks = new ArrayList(); } album.rdio_key = aKey; //Logger.info(jsonAlbum.toString()); album.name = jsonAlbum.get("name").getAsString(); album.artist = jsonAlbum.getAsJsonPrimitive("artistName").getAsString(); if (jsonAlbum.get("duration") != null) { album.duration = jsonAlbum.get("duration").getAsInt(); } // Grab album detail url = endpoint + "albums/" + album.rdio_key + "?include=tracks,images"; try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); sign.setParameter("apikey", Play.configuration.getProperty("rdio.key")); sign.setParameter("limit", "100"); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return albumResults; } //Logger.info(url + "&apiKey="); elem = sign.get().getJson(); // Logger.info(elem.toString()); JsonArray albums = elem.getAsJsonObject().getAsJsonArray("albums"); JsonObject thisAlbum = albums.get(0).getAsJsonObject(); JsonObject linked = thisAlbum.get("linked").getAsJsonObject(); JsonArray images = linked.getAsJsonArray("images"); // Logger.info(thisAlbum.toString()); album.icon = images.get(0).getAsJsonObject().get("url").getAsString(); album.bigIcon = album.icon; album.baseIcon = album.icon; String dateString = thisAlbum.getAsJsonPrimitive("released").getAsString(); album.releaseDate = new DateTime(dateString).toDate(); album.duration = new Integer(0); JsonArray tracks = linked.getAsJsonArray("tracks").getAsJsonArray(); Iterator<JsonElement> trackIter = tracks.iterator(); while (trackIter.hasNext()) { JsonObject trackObj = trackIter.next().getAsJsonObject(); String trackId = trackObj.get("id").getAsString(); List AXtracks = Track.find("byRdio_id", trackId).fetch(); Track track = null; if (AXtracks.size() > 0) { track = (Track) AXtracks.get(0); } if (track == null) { track = new Track(); // track.rdio_id = trackObj.get("id").getAsString(); // the object key of the track // track.save(); RdioHelper.parseNewTrack(user, track, trackObj, true); track.coverArt = album.icon; } album.duration += (int) track.duration; } AlbumRating albumRating = AlbumRating.find("byUserAndRdio_key", user, album.rdio_key).first(); if (albumRating == null) { albumRating = new AlbumRating(); albumRating.rdio_key = album.rdio_key; albumRating.user = user; albumRating.rating = -1L; albumRating.artist_name = album.artist; albumRating.album_name = album.name; albumRating.numOfRatingStars = LibraryItem.getStarCount(albumRating.rating); } // Logger.info("Duration:" + album.duration); album = album.save(); album.album_rating = albumRating; albumRating.save(); albumResults.add(album); } return albumResults; } public static Track updateTrackFromRdio(User user, Track track) { String url = endpoint + "tracks/" + track.rdio_id + "?apikey=" + Play.configuration.getProperty("rdio.key") + "&limit=200"; Logger.info("AX: Updating " + track.title + " from Rdio"); if (track == null || track.rdio_id == null) { Logger.info("Rdio.UpdateTrackFromRdio has null track or id: " + track); return track; } ArrayList trackResults = null; WSRequest sign; try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return null; } sign.setParameter("method", "get"); sign.setParameter("domain", Play.configuration.getProperty("domain")); sign.setHeader("Content-type", "application/json"); JsonElement searchResult = null; searchResult = sign.get().getJson(); //if (searchResult != null) //Logger.info(searchResult.toString()); if (searchResult == null || searchResult.getAsJsonObject() == null) { Logger.error("Null searrch result" + track.rdio_id); try { // track.delete(); // track.save(); Logger.info("Deleted track"); return null; } catch (Exception e) { Logger.info("" + e.getMessage()); } finally { return null; } } com.google.gson.JsonObject asJsonObj = searchResult.getAsJsonObject(); Logger.info("updateTrackFromRadio calling parseNewTrack"); RdioHelper.parseNewTrack(user, track, asJsonObj, true); Logger.info("Updated " + track.title + "/" + track.album_name + "/" + track.artist + " from Rdio - CX011"); track.lastUpdated = new Date(); // YoutubeJob ty = new YoutubeJob(track); // ty.loadYoutubes(); track.uniformSave(); return track; } // @TODO we need to look for variations .. i.e. "The Smashing Pumpkins" vs. "Smashing Pumpkins" @NoBinding public static Artist searchArtist(User user, String artist_name) { Logger.info("Rdio.searchArtist"); ArrayList trackResults = null; Artist artist = null; // try { //String url = endpoint + "search?apikey=" + Play.configuration.getProperty("rdio.key") + "&q=" + URLEncoder.encode(artist_name) + "&type=artist"; String url = endpoint + "search"; //Logger.info(url); WSRequest sign; try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); sign.setParameter("type", "artist"); sign.setParameter("q", URLEncoder.encode(artist_name)); sign.setParameter("apikey", Play.configuration.getProperty("rdio.key")); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return null; } JsonElement searchResult = sign.get().getJson(); //Logger.info(searchResult.toString()); JsonArray results = searchResult.getAsJsonArray(); JsonObject artistResult = null; for (JsonElement result : results) { JsonObject resObj = result.getAsJsonObject(); //Logger.info(resObj.toString()); if (resObj.get("name").getAsString().equals(artist_name)) { artistResult = resObj; Logger.info("Found artist " + artist_name + " with " + artistResult.get("id").getAsString()); break; } } if (artistResult == null) { Logger.error("Trying to get artist result for non existent artist"); return null; } Artist newArtist = new Artist(); newArtist.rdio_key = artistResult.get("id").getAsString(); newArtist.name = artistResult.get("name").getAsString(); // Grab image url = endpoint + "artists/" + newArtist.rdio_key + "/images"; try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "GET"); sign.setParameter("type", "artist"); sign.setParameter("q", URLEncoder.encode(artist_name)); sign.setParameter("apikey", Play.configuration.getProperty("rdio.key")); } catch (Exception ex) { Logger.error(ex.toString()); ex.printStackTrace(); return null; } JsonElement imgResp = sign.get().getJson(); JsonArray imgArray = imgResp.getAsJsonArray(); JsonObject firstimage = imgArray.iterator().next().getAsJsonObject(); newArtist.baseIcon = firstimage.get("url").getAsString(); newArtist.icon = newArtist.baseIcon; return newArtist; } public static ArrayList<Track> suggestsearchTrack(User user, String trackName) { ArrayList trackResults = null; // try { String url = endpoint; WSRequest sign; try { sign = getConnector(user).sign(user.rdioCreds, WS.url(url), "POST"); } catch (Exception ex) { Logger.info(ex.toString()); ex.printStackTrace(); return null; } sign.setParameter("method", "searchSuggestions"); sign.setParameter("domain", Play.configuration.getProperty("domain")); sign.setParameter("types", "Track,Album,Artist"); sign.setParameter("query", trackName); sign.setParameter("never_or", true); sign.setHeader("Content-type", "application/json"); JsonElement searchResult = sign.post().getJson(); //Logger.info(searchResult.toString()); com.google.gson.JsonObject asJsonObj = searchResult.getAsJsonObject(); // JsonElement rawResult = asJsonObj.get("result").getAsJsonObject(); com.google.gson.JsonArray resultArray = asJsonObj.getAsJsonObject().get("result").getAsJsonArray(); trackResults = new ArrayList(); for (JsonElement rdioTrackElement : resultArray) { JsonObject rdioTrack = rdioTrackElement.getAsJsonObject(); if (rdioTrack.get("type").getAsString().contains("t")) { // Object's type Track track = Track.retrieveTrackByRadioId(rdioTrack.get("key").getAsString()); if (track == null) { track = new Track(); RdioHelper.parseNewTrack(user, track, rdioTrack, true); // YoutubeJob ty = new YoutubeJob(track); // ty.loadYoutubes(); } track.uniformSave(); if (track.canStream) { trackResults.add(track); } } } return trackResults; } }