Ejemplo n.º 1
0
        public ActionResult Me()
        {
            var returnURL = "/Profiles/Me";
            var ah        = new AuthHelper();
            var result    = ah.DoAuth(returnURL, this);

            if (result != null)
            {
                return(Redirect(result));
            }

            var access_token = Session["AccessToken"].ToString();
            var url2         = "https://api.spotify.com/v1/me";
            var sh           = new SpotifyHelper();
            var result2      = sh.CallSpotifyAPIPassingToken(access_token, url2);

            var meReponse = JsonConvert.DeserializeObject <MeResponse>(result2);

            // Holder UserId in session so can turn menu on and off for login
            //Session["UserId"] = meReponse.id;

            meReponse.access_token = access_token;
            //return View(meReponse);
            // Redirect to PlaylistShuffler page
            return(Redirect("/Users/Playlists/" + meReponse.id));
        }
Ejemplo n.º 2
0
        public ActionResult Search(string searchTerm = "", bool isAPost = false)
        {
            var spotifyHelper = new SpotifyHelper();
            var vm            = new SearchViewModel();

            if (isAPost && searchTerm == "")
            {
                searchTerm = "Muse";
            }

            // Initial load of the page
            if (searchTerm == "")
            {
                return(View());
            }

            // To aid searching eg que
            searchTerm   += "*";
            vm.SearchTerm = searchTerm;

            string json   = spotifyHelper.CallSpotifyAPIArtistSearch(searchTerm);
            var    result = JsonConvert.DeserializeObject <ArtistsResponse2>(json);

            vm.ArtistsResponse2 = result;

            // eg fat bo* .. only get first 5
            json = spotifyHelper.CallSpotifyAPITrackSearch(searchTerm);
            var result2 = JsonConvert.DeserializeObject <TrackSearchResponse>(json);

            vm.TrackSearchResponse = result2;

            return(View(vm));
        }
Ejemplo n.º 3
0
        public ActionResult SpotifyCallback(string code)
        {
            bool   keepTrying    = true;
            string resultContent = "";

            while (keepTrying)
            {
                // Have now got authorization code (which can be exchanged for an access token)
                var client_id     = "0fd1718f5ef14cb291ef114a13382d15";
                var client_secret = "964e8a4a50de4dfd8247d061a8517920";

                var url = "https://accounts.spotify.com/api/token";

                // Request access and refresh tokens
                var postData = new Dictionary <string, string> {
                    { "grant_type", "authorization_code" },
                    { "code", code },
                    { "redirect_uri", GetRedirectUriWithServerName() },
                    { "client_id", client_id },
                    { "client_secret", client_secret }
                };

                HttpContent content = new FormUrlEncodedContent(postData.ToArray());

                var client       = new HttpClient();
                var httpResponse = client.PostAsync(url, content);
                var result       = httpResponse.Result;
                resultContent = result.Content.ReadAsStringAsync().Result;

                // Catching gateway timeouts or strange stuff from Spotify
                if (result.IsSuccessStatusCode)
                {
                    keepTrying = false;
                }
            }

            var obj = JsonConvert.DeserializeObject <AccessToken>(resultContent, new JsonSerializerSettings {
                TypeNameHandling       = TypeNameHandling.All,
                TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple
            });
            var access_token = obj.access_token;

            // Set access token in session
            Session["AccessToken"] = access_token;

            // do a quick call to get the username of the currently logged in user so I can use it to hide or display if it is davemateer (admin)
            var url2    = "https://api.spotify.com/v1/me";
            var sh      = new SpotifyHelper();
            var result2 = sh.CallSpotifyAPIPassingToken(access_token, url2);

            var meReponse = JsonConvert.DeserializeObject <MeResponse>(result2);

            Session["SpotifyUserID"] = meReponse.id;

            // Get return URL from session state
            var returnURL = Session["ReturnURL"].ToString();

            return(Redirect(returnURL));
        }
Ejemplo n.º 4
0
        public async Task <ActionResult> Details2(string id)
        {
            // get all albums async
            var artistID = id;
            var sh       = new SpotifyHelper();

            // call API synchronously once to get the total number of calls I need to do
            var          apiResult    = sh.CallSpotifyAPIArtistAlbums(null, artistID);
            ArtistAlbums artistAlbums = JsonConvert.DeserializeObject <ArtistAlbums>(apiResult.Json);
            int          total        = artistAlbums.total;

            var recordsPerPage      = 50;
            var records             = total;
            int numberOfTimesToLoop = (records + recordsPerPage - 1) / recordsPerPage;

            if (numberOfTimesToLoop == 1)
            {
                // don't need to do more calls
                return(View(artistAlbums));
            }
            var sw = new Stopwatch();

            sw.Start();

            ServicePointManager.DefaultConnectionLimit = 5;
            int n     = numberOfTimesToLoop;
            var tasks = new Task <string> [n];

            for (int i = 0; i < n; i++)
            {
                tasks[i] = CallAPI(i, artistID);
            }

            await Task.WhenAll(tasks);

            Debug.WriteLine(sw.ElapsedMilliseconds, "After all async tasks");

            // combine results
            var itemsList = new List <ArtistAlbums.Item>();
            int total2    = 0;

            for (int i = 0; i < n; i++)
            {
                ArtistAlbums albums = JsonConvert.DeserializeObject <ArtistAlbums>(tasks[i].Result);
                foreach (var item in albums.items)
                {
                    itemsList.Add(item);
                }
                total2 = albums.total;
            }
            var albums2 = new ArtistAlbums();

            albums2.items = itemsList;
            albums2.total = total2;

            return(View(albums2));
        }
Ejemplo n.º 5
0
        private List <TopTracksVM> GetTopTracks()
        {
            var vm = new List <TopTracksVM>();

            using (var db = DBHelper.GetOpenConnection())
            {
                vm = db.GetList <TopTracksVM>("ORDER BY AlbumDate Desc").ToList();
            }

            // If logged in
            if (Session["AccessToken"] != null)
            {
                ViewBag.access_token = Session["AccessToken"].ToString();

                var access_token = Session["AccessToken"].ToString();

                // User clicks via LoginRedirect to come back here
                // If this is the first time back to this page after logging in, need to get the UserID
                if (Session["UserID"] == null)
                {
                    var    url = "https://api.spotify.com/v1/me";
                    string json;
                    using (mp.CustomTiming("http", url))
                    {
                        var sh = new SpotifyHelper();
                        json = sh.CallSpotifyAPIPassingToken(access_token, url);
                    }

                    var meReponse = JsonConvert.DeserializeObject <MeResponse>(json);
                    meReponse.access_token = access_token;

                    Session["UserID"] = meReponse.id;
                }
                // Grab the userID as we'll use that in our database to remember what a user has selected
                ViewBag.user_id = Session["UserID"];

                // Find out what the user has already added to their playlist
                List <string> listTracksAlreadyAdded;
                var           userID = Session["UserID"];
                using (IDbConnection db = DBHelper.GetOpenConnection())
                {
                    listTracksAlreadyAdded =
                        db.Query <string>("SELECT TrackID FROM UserPlaylists WHERE UserID = @UserID", new { @UserID = userID })
                        .ToList();
                }

                foreach (var track in vm)
                {
                    if (listTracksAlreadyAdded.Contains(track.TrackID))
                    {
                        track.AddedInUserPlaylist = true;
                    }
                }
            }
            return(vm);
        }
Ejemplo n.º 6
0
        ///v1/users/{owner_id}/playlists/{playlist_id}/followers
        public ActionResult Follow(string ownerId, string playlistId)
        {
            var returnURL = "/Playlists/Follow/" + ownerId + "/" + playlistId;
            var ah        = new AuthHelper();
            var result    = ah.DoAuth(returnURL, this);

            if (result != null)
            {
                return(Redirect(result));
            }

            var access_token = Session["AccessToken"].ToString();
            var url2         = String.Format("https://api.spotify.com/v1/users/{0}/playlists/{1}/followers", ownerId, playlistId);
            var sh           = new SpotifyHelper();
            var result2      = sh.CallSpotifyPutAPIPassingToken(access_token, url2);

            return(Redirect("/Profiles/Me"));
        }
Ejemplo n.º 7
0
        public ActionResult TopAlbums()
        {
            var albumIDs = new List <string>();

            using (var connection = new SqlConnection(connectionString))
                using (var command = new SqlCommand(null, connection)) {
                    connection.Open();
                    command.CommandText = String.Format("SELECT DISTINCT AlbumID FROM Playlist");
                    using (var reader = command.ExecuteReader()) {
                        while (reader.Read())
                        {
                            var albumID = reader.GetString(reader.GetOrdinal("AlbumID"));
                            albumIDs.Add(albumID);
                        }
                    }
                }

            // now got a list of albumID's we want to call spotify to get info
            var listAlbumDetails = new List <AlbumDetails>();
            var spotifyHelper    = new SpotifyHelper();

            foreach (var albumID in albumIDs)
            {
                var      apiResult    = spotifyHelper.CallSpotifyAPIAlbumDetails(null, id: albumID);
                var      albumDetails = JsonConvert.DeserializeObject <AlbumDetails>(apiResult.Json);
                DateTime d;
                bool     success = DateTime.TryParse(albumDetails.release_date, out d);

                if (!success)
                {
                    // Black crowes was just a year ie 2009
                    int year = Int32.Parse(albumDetails.release_date);
                    d = new DateTime(year, 1, 1);
                }

                albumDetails.releaseDateTime = d;
                listAlbumDetails.Add(albumDetails);
            }

            // Pass current userID to view?
            var a = listAlbumDetails.OrderByDescending(x => x.releaseDateTime).ToList();

            return(View(a));
        }
Ejemplo n.º 8
0
        private AlbumDetailsViewModel GetAlbumDetailsViewModel(string id)
        {
            var spotifyHelper   = new SpotifyHelper();
            var stopWatchResult = new StopWatchResult();
            var apiResult       = spotifyHelper.CallSpotifyAPIAlbumDetails(stopWatchResult, id);

            ViewBag.Id = id;
            var albumDetails = JsonConvert.DeserializeObject <AlbumDetails>(apiResult.Json);

            // iterate through setting vm checked property
            using (var connection = new SqlConnection(connectionString))
                using (var command = new SqlCommand(null, connection)) {
                    connection.Open();
                    command.CommandText = String.Format("SELECT TrackID FROM Tracks");
                    command.CommandType = CommandType.Text;

                    var trackIDsSelectedInDb = new List <string>();
                    using (var reader = command.ExecuteReader()) {
                        while (reader.Read())
                        {
                            var trackID = reader.GetString(reader.GetOrdinal("TrackID"));
                            trackIDsSelectedInDb.Add(trackID);
                        }
                    }

                    foreach (var trackID in trackIDsSelectedInDb)
                    {
                        var track = albumDetails.tracks.items.FirstOrDefault(x => x.id == trackID);
                        if (track != null)
                        {
                            track.Checked = true;
                        }
                    }
                }

            var vm = new AlbumDetailsViewModel {
                APIDebugList = null,
                AlbumDetails = albumDetails,
            };

            return(vm);
        }
Ejemplo n.º 9
0
        public ActionResult Details(string id, string userId)
        {
            var returnURL = "/Playlists/Details/" + id + "/" + userId;
            var ah        = new AuthHelper();
            var result    = ah.DoAuth(returnURL, this);

            if (result != null)
            {
                return(Redirect(result));
            }

            var access_token = Session["AccessToken"].ToString();
            var url2         = String.Format("https://api.spotify.com/v1/users/{0}/playlists/{1}", userId, id);
            var sh           = new SpotifyHelper();
            var result2      = sh.CallSpotifyAPIPassingToken(access_token, url2);

            var meReponse = JsonConvert.DeserializeObject <PlaylistDetails>(result2);

            meReponse.access_token = access_token;
            return(View(meReponse));
        }
Ejemplo n.º 10
0
        ///v1/users/{user_id}
        public ActionResult User(string id)
        {
            var returnURL = "/Profiles/User";
            var ah        = new AuthHelper();
            var result    = ah.DoAuth(returnURL, this);

            if (result != null)
            {
                return(Redirect(result));
            }

            var access_token = Session["AccessToken"].ToString();
            var url2         = String.Format("https://api.spotify.com/v1/users/{0}", id);
            var sh           = new SpotifyHelper();
            var result2      = sh.CallSpotifyAPIPassingToken(access_token, url2);

            var response = JsonConvert.DeserializeObject <UserDetails>(result2);

            response.access_token = access_token;
            return(View(response));
        }
Ejemplo n.º 11
0
        // Browse/NewReleases
        public ActionResult NewReleases()
        {
            var returnURL = "/Browse/NewReleases";
            var ah        = new AuthHelper();
            var result    = ah.DoAuth(returnURL, this);

            if (result != null)
            {
                return(Redirect(result));
            }

            var access_token = Session["AccessToken"].ToString();
            var url2         = "https://api.spotify.com/v1/browse/new-releases?country=GB";
            var sh           = new SpotifyHelper();
            var result2      = sh.CallSpotifyAPIPassingToken(access_token, url2);

            var meReponse = JsonConvert.DeserializeObject <NewReleaseDetails>(result2);

            meReponse.access_token = access_token;
            return(View(meReponse));
        }
Ejemplo n.º 12
0
        public ActionResult FeaturedPlaylists()
        {
            var returnURL    = "/Browse/FeaturedPlaylists";
            var helper       = new AuthHelper();
            var helperResult = helper.DoAuth(returnURL, this);

            if (helperResult != null)
            {
                return(Redirect(helperResult));
            }

            var access_token = Session["AccessToken"].ToString();
            var url          = "https://api.spotify.com/v1/browse/featured-playlists?country=GB";
            var sh           = new SpotifyHelper();
            var result       = sh.CallSpotifyAPIPassingToken(access_token, url);

            var meReponse = JsonConvert.DeserializeObject <FeaturedPlaylists>(result);

            meReponse.access_token = access_token;
            return(View(meReponse));
        }
Ejemplo n.º 13
0
        //eg /v1/users/davemateer/playlists
        public ActionResult Create()
        {
            var returnURL = "/Playlists/Create";

            var ah     = new AuthHelper();
            var result = ah.DoAuth(returnURL, this);

            if (result != null)
            {
                return(Redirect(result));
            }

            var sh           = new SpotifyHelper();
            var access_token = Session["AccessToken"].ToString();

            // Get the current users id eg davemateer
            var url7    = "https://api.spotify.com/v1/me";
            var result7 = sh.CallSpotifyAPIPassingToken(access_token, url7);

            var    meReponse7 = JsonConvert.DeserializeObject <MeResponse>(result7);
            string userId     = meReponse7.id;

            // Does the playlist exist already for this user?
            var url4              = String.Format("https://api.spotify.com/v1/users/{0}/playlists", userId);
            var result4           = sh.CallSpotifyAPIPassingToken(access_token, url4);
            var meReponse         = JsonConvert.DeserializeObject <PlaylistSummaryViewModel>(result4);
            var currentPlaylistID = "";

            foreach (var thing in meReponse.items)
            {
                if (thing.name == "DTM - Playlist")
                {
                    currentPlaylistID = thing.id;
                }
            }

            // If not playlist create one
            if (currentPlaylistID == "")
            {
                var url2           = String.Format("https://api.spotify.com/v1/users/{0}/playlists", userId);
                var result2        = sh.CallSpotifyCreatePlaylistPostAPIPassingToken(access_token, url2);
                var playlistReturn = JsonConvert.DeserializeObject <CreatePlaylistReturn>(result2);
                currentPlaylistID = playlistReturn.id;
            }

            // Get trackID's from database to add to Spotify (the app saves the trackID's to the db before we send to spotify)
            var listOfTrackIDs = new List <String>();

            using (var connection = new SqlConnection(connectionString))
                using (var command = new SqlCommand(null, connection)) {
                    connection.Open();
                    command.CommandText = String.Format("SELECT TrackID FROM UserPlaylists WHERE UserID = @UserID");
                    command.Parameters.AddWithValue("@UserID", userId);
                    command.CommandType = System.Data.CommandType.Text;
                    using (var reader = command.ExecuteReader()) {
                        while (reader.Read())
                        {
                            var trackID = reader.GetString(reader.GetOrdinal("TrackID"));
                            listOfTrackIDs.Add(trackID);
                        }
                    }
                }

            if (listOfTrackIDs.Count > 100)
            {
                string csvOfUris = "";

                // Get first 100 tracks and put into a csv string
                var first100 = listOfTrackIDs.Take(100);
                foreach (var trackID in first100)
                {
                    csvOfUris += "spotify:track:" + trackID + ",";
                }
                csvOfUris = csvOfUris.TrimEnd(',');

                var url3 = String.Format("https://api.spotify.com/v1/users/{0}/playlists/{1}/tracks?uris={2}", userId, currentPlaylistID, csvOfUris);

                // this will replace
                var result3 = sh.CallSpotifyPutAPIPassingToken(access_token, url3);

                var recordsPerPage      = 100;
                var records             = listOfTrackIDs.Count;
                int numberOfTimesToLoop = (records + recordsPerPage - 1) / recordsPerPage;

                // 1 as we've already done the first loop (0 based)
                for (int i = 1; i < numberOfTimesToLoop; i++)
                {
                    var stuff = listOfTrackIDs.Skip(100 * i).Take(100);
                    csvOfUris = "";
                    foreach (var trackID in stuff)
                    {
                        csvOfUris += "spotify:track:" + trackID + ",";
                    }
                    csvOfUris = csvOfUris.TrimEnd(',');

                    // this will add
                    url3 = String.Format("https://api.spotify.com/v1/users/{0}/playlists/{1}/tracks?uris={2}", userId, currentPlaylistID, csvOfUris);
                    var result5 = sh.CallSpotifyPostAPIPassingToken(access_token, url3);
                }
            }
            else
            {
                string csvOfUris = "";

                var first100 = listOfTrackIDs;
                foreach (var trackID in first100)
                {
                    csvOfUris += "spotify:track:" + trackID + ",";
                }
                csvOfUris = csvOfUris.TrimEnd(',');

                var url3 = String.Format("https://api.spotify.com/v1/users/{0}/playlists/{1}/tracks?uris={2}", userId,
                                         currentPlaylistID, csvOfUris);

                // this will replace
                var result3 = sh.CallSpotifyPutAPIPassingToken(access_token, url3);
            }

            return(Redirect("/"));
        }
Ejemplo n.º 14
0
        public async Task <ActionResult> Playlists(PlaylistSummaryViewModel vm, string id)
        {
            ServicePointManager.DefaultConnectionLimit = 5;

            var userId       = id;
            var access_token = Session["AccessToken"].ToString();
            var sh           = new SpotifyHelper();

            // Create/Update playlist in Spotify
            // like /Playlists/Follow

            // Does the playlist exist already for this user?
            var    url4 = String.Format("https://api.spotify.com/v1/users/{0}/playlists", userId);
            string result4;

            using (mp.Step("POST - Does the DTM Shuffler playlist exist already for this user")) {
                result4 = sh.CallSpotifyAPIPassingToken(access_token, url4);
            }
            var meReponse         = JsonConvert.DeserializeObject <PlaylistSummaryViewModel>(result4);
            var currentPlaylistID = "";
            var shuffler          = meReponse.items.FirstOrDefault(x => x.name == "DTM - Shuffler");

            if (shuffler != null)
            {
                currentPlaylistID = shuffler.id;
            }

            // If not playlist create one
            if (currentPlaylistID == "")
            {
                var    url2 = String.Format("https://api.spotify.com/v1/users/{0}/playlists", userId);
                string result2;
                using (mp.Step("POST - Creating DTM - Shuffler playlist")) {
                    result2 = sh.CallSpotifyCreatePlaylistPostAPIPassingToken(access_token, url2, "DTM - Shuffler");
                }
                var playlistReturn = JsonConvert.DeserializeObject <CreatePlaylistReturn>(result2);
                currentPlaylistID = playlistReturn.id;
            }

            // Go through each Checked playlist and add to Shuffler list
            var listOfTrackIDs = new List <String>();

            foreach (var playlist in vm.items)
            {
                var ownerId    = playlist.owner.id;
                var playlistId = playlist.id;
                if (playlist.Checked)
                {
                    // Get the details of the playlist ie the tracks
                    PlaylistTracks result22;
                    using (mp.Step("POST - Async.. Get details of the playlist ie the tracks.. 50 at a time")) {
                        result22 = await sh.CallSpotifyAPIPassingTokenPlaylistsAsync(access_token, ownerId, playlistId);
                    }
                    // add tracks to list
                    foreach (var item in result22.items)
                    {
                        // catching a track in a playlist with no id
                        if (item.track != null)
                        {
                            listOfTrackIDs.Add(item.track.id);
                        }
                    }
                }
            }

            var result3 = await sh.CallSpotifyPutAPIPassingTokenSendTracksAsync(access_token, userId, currentPlaylistID, listOfTrackIDs);

            // Get data again as not saved, including Checked status
            var vm2 = await GetPlaylistDetailsViewModel(id);

            return(View(vm2));
        }
Ejemplo n.º 15
0
        private ArtistDetailsViewModel GetArtistDetailsViewModel(string id)
        {
            string artistID = id;
            var    sh       = new SpotifyHelper();

            // 1. Getting Artist details from Spotify
            string json;

            using (profiler.Step("1. Getting Artist details from Spotify")) {
                json = sh.CallSpotifyAPIArtist(artistID, null);
            }
            ViewBag.Id = artistID;
            var artistDetails = JsonConvert.DeserializeObject <ArtistDetails>(json);

            // 2. All Artists albums - possibly more than 50!
            APIResult apiResult;

            using (profiler.Step("2. All Artists albums - possibly more than 50!")) {
                apiResult = sh.CallSpotifyAPIArtistAlbums(null, artistID);
            }
            var artistAlbums = JsonConvert.DeserializeObject <ArtistAlbums>(apiResult.Json);

            // Want studio albums only - get rid of live albums and put into another bucket to display too
            IEnumerable <ArtistAlbums.Item> studioAlbums = artistAlbums.items.Where(x => !x.name.ToLower().Contains("live from"));

            studioAlbums = studioAlbums.Where(x => !x.name.ToLower().Contains("live at"));
            studioAlbums = studioAlbums.Where(x => !x.name.ToLower().Contains("(live"));
            studioAlbums = studioAlbums.Where(x => !x.name.ToLower().Contains("live in"));
            studioAlbums = studioAlbums.Where(x => !x.name.ToLower().Contains("greatest hits"));

            // get rid of any dupes - eg Phil Collins has many albums called Tarzan....could use DistinctBy
            studioAlbums = studioAlbums.GroupBy(x => x.name).Select(yy => yy.First());

            //Queen
            //if contains   (Deluxe
            //  or Deluxe
            // take start of the string before that…
            // and check another album exists
            var deluxeAlbums = studioAlbums.Where(x => x.name.ToLower().Contains("(deluxe"));

            // check another album exists
            foreach (var deluxeAlbum in deluxeAlbums)
            {
                var name = deluxeAlbum.name;
                //var firstBit = name.Substring(0)
                string[] res      = name.Split(new string[] { "(Deluxe" }, StringSplitOptions.None);
                var      firstBit = res[0];

                // does another album exist with this name but not the deluxe?
                var anohterAlbum = studioAlbums.FirstOrDefault(x => x.name.ToLower().Trim() == firstBit.ToLower().Trim());
                if (anohterAlbum != null)
                {
                    studioAlbums = studioAlbums.Where(x => x.id != anohterAlbum.id);
                }

                // does another album exist with this name but stuff in brackets
                // eg Queen (Deluxe Edition..) and Queen (2011 Remaster)
                var anohterAlbum2 = studioAlbums.FirstOrDefault(x => x.name.ToLower().Trim().Contains(firstBit.ToLower().Trim() + " ("));
                if (anohterAlbum2 != null)
                {
                    studioAlbums = studioAlbums.Where(x => x.id != anohterAlbum2.id);
                }
            }

            List <MultipleAlbums.Album> multiAlbumDetails3 = null;

            // The exponents - have no albums (even before filtering)
            if (studioAlbums.Count() > 0)
            {
                multiAlbumDetails3 = sh.CallSpotifyAPIMultipleAlbumDetails2(null, studioAlbums);
            }

            // 3. Artists Top Tracks
            using (profiler.Step("3. Artists Top Tracks")) {
                apiResult = sh.CallSpotifyAPIArtistTopTracks(null, artistID);
            }
            var artistTopTracks = JsonConvert.DeserializeObject <ArtistTopTracks>(apiResult.Json);

            var tracks        = artistTopTracks.tracks;
            var distinctTop10 = new List <ArtistTopTracks.Track>();
            List <ArtistTopTracks.Track> top10 = tracks.OrderByDescending(x => x.popularity).Take(10).ToList();

            // problem is that some tracks are related to their "Greatest Hits compilation" / not original album
            // eg Black Crowes - Twice as Hard (#2) related to Greatest Hits 1990-1999
            // take the track name, and find the earliest album it is on..
            IList <string> top10trackNames         = top10.Select(x => x.name).ToList();
            var            top10trackNamesDistinct = top10trackNames.Distinct(StringComparer.CurrentCultureIgnoreCase);

            foreach (var trackName in top10trackNamesDistinct)
            {
                var track = top10.FirstOrDefault(x => x.name == trackName);
                distinctTop10.Add(track);
            }

            var dictionaryOfNameAndAlbumIDAndNewTrackID = new Dictionary <string, Thing2>();

            // find track name in the earliest album
            foreach (var trackName in top10trackNamesDistinct)
            {
                MultipleAlbums.Album originalAlbum = null;

                // if there are any remaining albums for this artist (eg Brian May)
                if (multiAlbumDetails3 != null)
                {
                    var xxx = multiAlbumDetails3.Select(x => x.tracks.items.Where(yy => yy.name == trackName));
                    // Descending so last one, is the earliest one
                    var listOfTrackName = new List <Thing2>();
                    foreach (var album in multiAlbumDetails3.OrderByDescending(al => al.release_date))
                    {
                        foreach (var track in album.tracks.items)
                        {
                            if (track.name.ToLower() == trackName.ToLower())
                            {
                                originalAlbum = album;
                            }
                            var t2 = new Thing2 {
                                AlbumID = album.id,
                                TrackID = track.id
                            };
                            listOfTrackName.Add(t2);
                        }
                    }
                }

                if (originalAlbum == null)
                {
                    // Eminem - guts over fear.. on album Shadyyxv (a compilation)
                    var asdf = distinctTop10.SingleOrDefault(x => x.name == trackName);
                    var t2   = new Thing2 {
                        AlbumID = asdf.album.id,
                        TrackID = asdf.id
                    };
                    dictionaryOfNameAndAlbumIDAndNewTrackID.Add(trackName, t2);
                }
                else
                {
                    // add the albums trackID rather than whatever it is at the moment (compilation perhaps)
                    // want the last one added to the list
                    var t2 = new Thing2 {
                        AlbumID = originalAlbum.id,
                        TrackID = originalAlbum.tracks.items.FirstOrDefault(x => x.name.ToLower() == trackName.ToLower()).id
                    };
                    dictionaryOfNameAndAlbumIDAndNewTrackID.Add(trackName, t2);
                }
            }

            // Wire up new album if needed
            foreach (var track in distinctTop10)
            {
                var trackName = track.name;
                track.album.id = dictionaryOfNameAndAlbumIDAndNewTrackID[trackName].AlbumID;
                track.id       = dictionaryOfNameAndAlbumIDAndNewTrackID[trackName].TrackID;
            }

            // Iterate through records in db, setting vm checked property for Admin - add to playlist
            var trackIDsTemp = new List <string>();

            using (IDbConnection db = DBHelper.GetOpenConnection()) {
                trackIDsTemp = db.Query <string>("SELECT TrackID FROM Tracks").ToList();
            }

            foreach (var trackID in trackIDsTemp)
            {
                // Is this track in the current search list?
                var track = distinctTop10.FirstOrDefault(x => x.id == trackID);
                if (track != null)
                {
                    track.Checked = true;
                }
            }

            // 4. Artists top tracks and get the date that this track/album was released - using GetMultipleAlbums
            var csvStringOfAlbumIDs = "";
            var listOfAlbumIDs      = new List <string>();

            foreach (var track in distinctTop10)
            {
                if (listOfAlbumIDs.Contains(track.album.id))
                {
                }
                else
                {
                    csvStringOfAlbumIDs += track.album.id + ",";
                    listOfAlbumIDs.Add(track.album.id);
                }
            }
            csvStringOfAlbumIDs = csvStringOfAlbumIDs.TrimEnd(',');
            APIResult apiResult2;

            if (csvStringOfAlbumIDs.Length > 0)
            {
                using (profiler.Step("4. Artists top tracks and get the date that this track/album was released - using GetMultipleAlbums")) {
                    apiResult2 = sh.CallSpotifyAPIMultipleAlbumDetails(null, csvStringOfAlbumIDs);
                }
                var multiAlbumDetails = JsonConvert.DeserializeObject <MultipleAlbums>(apiResult2.Json);
                foreach (var album in multiAlbumDetails.albums)
                {
                    // get all associated albums in top10
                    var albumInTop10s = distinctTop10.Where(x => x.album.id == album.id);

                    foreach (var album2 in albumInTop10s)
                    {
                        album2.album.DateOfAlbumRelease = album.release_date;
                        album2.album.name = album.name;
                        album2.album.uri  = album.uri;

                        //images
                        var images = new List <ArtistTopTracks.Image>();
                        foreach (var image in album.images)
                        {
                            var att = new ArtistTopTracks.Image();
                            att.height = image.height;
                            att.width  = image.width;
                            att.url    = image.url;
                            images.Add(att);
                        }
                        album2.album.images = images;
                    }
                }
            }

            artistTopTracks.tracks = distinctTop10.ToList();

            // 5. Artist's related Artists - top 15
            using (profiler.Step("5. Artist's related Artists - top 15")) {
                apiResult = sh.CallSpotifyAPIArtistRelated(null, artistID);
            }
            var artistRelated = JsonConvert.DeserializeObject <ArtistRelated>(apiResult.Json);
            var y             = artistRelated.artists.Take(15).ToList();

            artistRelated.artists = y;


            // 6. Biography from Wikipedia via Echonest - deprecated!
            //using (profiler.Step("6. Biography (Echonest)")) {
            //    apiResult = sh.CallEchonestAPIArtistBiography(null, artistID);
            //}
            //var artistBiography = JsonConvert.DeserializeObject<ArtistBiography>(apiResult.Json);
            //if (artistBiography != null) {
            //    // Just get last.fm and Wikipedia entries
            //    if (artistBiography.response.biographies != null) {
            //        var a = artistBiography.response.biographies.SingleOrDefault(x => x.url.Contains("wikipedia"));
            //        artistBiography.response.biographies.Clear();
            //        artistBiography.response.biographies.Add(a);
            //    }
            //}

            // 7. Artists singles
            using (profiler.Step("7. Artists singles")) {
                apiResult = sh.CallSpotifyAPIArtistsSingles(artistID);
            }
            var artistSingles = JsonConvert.DeserializeObject <ArtistAlbums>(apiResult.Json);

            // use the query I did above
            foreach (var trackID in trackIDsTemp)
            {
                // Is this track in the current artist Singles list?
                var track = artistSingles.items.FirstOrDefault(x => x.id == trackID);
                if (track != null)
                {
                    track.Checked = true;
                }
            }

            var vm = new ArtistDetailsViewModel {
                ArtistDetails   = artistDetails,
                ArtistTopTracks = artistTopTracks,
                ArtistAlbums    = multiAlbumDetails3,

                ArtistRelated = artistRelated,
                //ArtistBiography = artistBiography,
                ArtistSingles = artistSingles
            };

            return(vm);
        }