private IList <VisifySavedTrack> _visifyTracksFromPaging(string spotifyid, Paging <SavedTrack> pst, DateTimeOffset mostRecentlyAdded) { List <VisifySavedTrack> vsts = new List <VisifySavedTrack>(); if (pst == null || pst.Items == null || pst.Items.Count == 0) { /* short curcuit */ return(vsts); } foreach (SavedTrack st in pst.Items) { if (String.IsNullOrEmpty(st?.Track?.Id)) { // protecting against weirdness logger.Info("Found a track that was null or without a spotify id"); continue; } // check that track is from a date more recent than our most recently added if (DateTimeOffset.Parse(st.Added_At) <= mostRecentlyAdded) { // TODO FIXME is this a bug that will fail when adding an entire album, and therefore has multiple items added at the same time? continue; } // Assemble artists List <VisifyArtist> artists = new List <VisifyArtist>(); foreach (Artist a in st.Track.Artists) { VisifyArtist va = new VisifyArtist(a.Id, a.Name); artists.Add(va); } // Assemble track VisifyTrack vt = new VisifyTrack(st.Track.Id, st.Track.Name, st.Track.Album.Name, artists); // Assemble Saved Track DateTimeOffset dto = DateTimeOffset.Parse(st.Added_At); VisifySavedTrack vst = new VisifySavedTrack(vt, spotifyid, dto); vsts.Add(vst); } return(vsts); }
/// <summary> /// Retrieves LIMIT tracks from the users library /// </summary> /// <param name="aspnetuserid"></param> /// <param name="offset"></param> /// <param name="limit"></param> /// <returns></returns> public static async Task <VOption <IList <VisifySavedTrack> > > GetUsersSavedTracks(string aspnetuserid, int offset = 0, int limit = 50) { using (SqliteConnection conn = new SqliteConnection(AppConstants.ConnectionString)) { await conn.OpenAsync(); using (SqliteCommand comm = conn.CreateCommand()) { comm.CommandText = "SELECT SpotifyTrackId, DateAdded, TrackName, AlbumName FROM VisifySavedTrack AS vst JOIN VisifyTrack AS vt ON vt.SpotifyId=vst.SpotifyTrackId WHERE AspNetUserId=@auid ORDER BY DateAdded DESC LIMIT @lim OFFSET @off"; comm.Parameters.Add("@auid", SqliteType.Text).Value = aspnetuserid; comm.Parameters.Add("@off", SqliteType.Integer).Value = offset; comm.Parameters.Add("@lim", SqliteType.Integer).Value = limit; Dictionary <string, VisifyTrack> dtracks = new Dictionary <string, VisifyTrack>(); VisifyTrack[] vts = new VisifyTrack[limit]; VisifySavedTrack[] vsts = new VisifySavedTrack[limit]; // Tracks without artists DbDataReader reader = await comm.ExecuteReaderAsync(); int i = 0; while (await reader.ReadAsync()) { string tid = reader.GetString(0); DateTimeOffset dateadded = DateTimeOffset.FromUnixTimeMilliseconds(reader.GetInt64(1)); string tname = reader.GetString(2); string aname = reader.GetString(3); VisifyTrack vt = new VisifyTrack(tid, tname, aname, new VisifyArtist[0]); VisifySavedTrack vst = new VisifySavedTrack(vt, "", dateadded); dtracks.Add(tid, vt); vts[i] = vt; vsts[i] = vst; i += 1; } Array.Resize(ref vsts, i); reader.Close(); // Now artists Dictionary <string, VisifyArtist> dartists = new Dictionary <string, VisifyArtist>(); List <VisifyArtist> vas = new List <VisifyArtist>(); comm.CommandText = "SELECT vt.SpotifyId AS tid, va.SpotifyId AS aid, va.ArtistName AS aname FROM (SELECT * FROM VisifySavedTrack WHERE AspNetUserId=@auid ORDER BY DateAdded DESC LIMIT @lim OFFSET @off) AS vst JOIN VisifyTrack AS vt ON vt.SpotifyId=vst.SpotifyTrackId JOIN VisifyTrackArtistMap AS vtam ON vtam.SpotifyTrackId=vt.SpotifyId JOIN VisifyArtist AS va ON va.SpotifyId=vtam.SpotifyArtistId;"; reader = await comm.ExecuteReaderAsync(); while (await reader.ReadAsync()) { string tid = reader.GetString(0); string aid = reader.GetString(1); string aname = reader.GetString(2); VisifyArtist va = null; if (!dartists.ContainsKey(aid)) { va = new VisifyArtist(aid, aname); dartists.Add(aid, va); } else { va = dartists[aid]; } dtracks[tid].Artists.Add(va); } return(new VOption <IList <VisifySavedTrack> >(vsts)); } } }
public async Task <IActionResult> GetArtistCollabLinks() { VisifyUser user = await _userManager.GetUserAsync(User); if (user == null) { logger.LogInformation($"Tried to get Artist Collab Link graph data for user {_userManager.GetUserId(User)}, but user did not exist"); return(NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.")); } // Get the tracks and artists VOption <IList <VisifySavedTrack> > stracks = await DatabaseService.GetUsersSavedTracks(user.Id, limit : 10_000); if (!stracks.WasSuccess) { logger.LogError($"Failed to retreive saved tracks for user {_userManager.GetUserId(User)}", stracks.ErrorMessage); return(Json("FAILED")); } // create a proper d3 structure Dictionary <string, FDGNode> nodes = new Dictionary <string, FDGNode>(); Dictionary <string, FDGEdge> edges = new Dictionary <string, FDGEdge>(); foreach (VisifySavedTrack vst in stracks.Value) { string tid = $"tid_{vst.VisifyTrack.SpotifyId}"; string[] idarr = new string[2]; Stack <string> artistsOnThisTrack = new Stack <string>(vst.VisifyTrack.Artists.Count); for (int i = 0; i < vst.VisifyTrack.Artists.Count; i++) { VisifyArtist va = vst.VisifyTrack.Artists[i]; if (!nodes.ContainsKey(va.SpotifyId)) { nodes.Add(va.SpotifyId, new FDGNode(va.SpotifyId, 0, va.ArtistName, 1, 1000)); } artistsOnThisTrack.Push(va.SpotifyId); } while (artistsOnThisTrack.Count > 0) { string a = artistsOnThisTrack.Pop(); foreach (string othera in artistsOnThisTrack) { idarr[0] = a; idarr[1] = othera; Array.Sort(idarr); string lid0 = String.Join("", idarr); Dictionary <string, string> tn = new Dictionary <string, string>() { { "name", vst.VisifyTrack.TrackName } }; if (edges.ContainsKey(lid0)) { edges[lid0].strength += 0.1; edges[lid0].tracks.Add(tn); } else { FDGEdge n = new FDGEdge(othera, a, 0.1); n.tracks.Add(tn); edges.Add(lid0, n); } } } } Dictionary <string, object> keys = new Dictionary <string, object>() { { "nodes", nodes.Values }, { "links", edges.Values } }; return(Json(keys)); }