diff --git a/NightwaveForWorkgroups/MainWindow.xaml b/NightwaveForWorkgroups/MainWindow.xaml
index d3a809b..4646b37 100644
--- a/NightwaveForWorkgroups/MainWindow.xaml
+++ b/NightwaveForWorkgroups/MainWindow.xaml
@@ -33,9 +33,9 @@
-
+
-
+
@@ -43,24 +43,31 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/NightwaveForWorkgroups/MainWindow.xaml.cs b/NightwaveForWorkgroups/MainWindow.xaml.cs
index cb7e8e0..aa2a498 100644
--- a/NightwaveForWorkgroups/MainWindow.xaml.cs
+++ b/NightwaveForWorkgroups/MainWindow.xaml.cs
@@ -65,7 +65,7 @@ namespace NightwaveForWorkgroups {
btLogin.Visibility = Visibility.Hidden;
imLogin.IsEnabled = false;
imLogin.Visibility = Visibility.Hidden;
- btDislike.IsEnabled = true;
+ //btDislike.IsEnabled = true;
btLike.IsEnabled = true;
SetStatus($"Logged in as {await NwP.GetUser()}");
}
@@ -88,43 +88,43 @@ namespace NightwaveForWorkgroups {
slDuration.Value = s.CalculatedElapsed;
sbListeners.Text = $"{s.Listeners} listeners";
lbLikeCt.Content = s.Likes;
- lbDislikeCt.Content = s.Dislikes;
+ //lbDislikeCt.Content = s.Dislikes;
lbElapsed.Content = $"{(s.CalculatedElapsed / 60).ToString("D")}:{(s.CalculatedElapsed % 60).ToString("D2")}";
if(LastArtwork != s.ArtworkUri || Force) {
//TODO should probably break this part out into a separate function cause this feels real messy
Vote v = await NwP.Vote() ?? Vote.Neutral;
switch(v) {
- case Vote.Dislike:
+ /*case Vote.Dislike:
sbVote.Text = "π";
sbVote.ToolTip = "You dislike this.";
btLike.Content = "π";
btLike.ToolTip = "Like this track";
btDislike.Content = "π€·ββοΈ";
btDislike.ToolTip = "Remove your vote for this track";
- break;
+ break;*/
case Vote.Like:
sbVote.Text = "π";
sbVote.ToolTip = "You like this.";
btLike.Content = "π";
btLike.ToolTip = "Favourite this track";
- btDislike.Content = "π";
- btDislike.ToolTip = "Dislike this track";
+ //btDislike.Content = "π";
+ //btDislike.ToolTip = "Dislike this track";
break;
case Vote.Favourite:
sbVote.Text = "π";
sbVote.ToolTip = "You have favourited this.";
btLike.Content = "π€·ββοΈ";
btLike.ToolTip = "Remove your vote for this track";
- btDislike.Content = "π";
- btDislike.ToolTip = "Dislike this track";
+ //btDislike.Content = "π";
+ //btDislike.ToolTip = "Dislike this track";
break;
default:
sbVote.Text = "π€·ββοΈ";
sbVote.ToolTip = "You have no feelings towards this, or you have not expressed your feelings for this.";
btLike.Content = "π";
btLike.ToolTip = "Like this track";
- btDislike.Content = "π";
- btDislike.ToolTip = "Dislike this track";
+ //btDislike.Content = "π";
+ //btDislike.ToolTip = "Dislike this track";
break;
}
//TODO visual effect on the like/dislike buttons to indicate user's vote
@@ -259,7 +259,10 @@ namespace NightwaveForWorkgroups {
return;
}
//user may have stored credentials and not want to keep them any more, delete with reckless abandon.
- CredentialManager.DeleteCredential("Nightwave.NET");
+ // on certain versions of windows, the lack of existing creds here will cause an exception.
+ try {
+ CredentialManager.DeleteCredential("Nightwave.NET");
+ } catch(Exception) { }
if(_c.CredentialSaved == CredentialSaveOption.Selected) {
CredentialManager.WriteCredential("Nightwave.NET", _c.UserName, _c.Password, CredentialPersistence.Enterprise);
Credential c=CredentialManager.ReadCredential("Nightwave.NET");
@@ -278,13 +281,14 @@ namespace NightwaveForWorkgroups {
btLogin.Visibility = Visibility.Hidden;
imLogin.IsEnabled = false;
imLogin.Visibility = Visibility.Hidden;
- btDislike.IsEnabled = true;
+ //btDislike.IsEnabled = true;
btLike.IsEnabled = true;
SetStatus($"Logged in as {await NwP.GetUser()}");
}
private async void BtLike_Click(object sender, RoutedEventArgs e) {
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btLike);
Vote v = await NwP.Vote() ?? Vote.Neutral;
+ // Kinda like a garbage state machine
v = v switch {
Vote.Like => Vote.Favourite,
Vote.Favourite => Vote.Neutral,
@@ -297,7 +301,7 @@ namespace NightwaveForWorkgroups {
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btLike);
_ = Dispatcher.BeginInvoke(new dgtBool(DgtRefresh), true);
}
- private async void BtDislike_Click(object sender, RoutedEventArgs e) {
+ /*private async void BtDislike_Click(object sender, RoutedEventArgs e) {
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btDislike);
Vote v = Vote.Dislike;
if(await NwP.Vote() == Vote.Dislike)
@@ -308,9 +312,13 @@ namespace NightwaveForWorkgroups {
SetStatus($"Something went weird while casting {v}");
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btDislike);
_ = Dispatcher.BeginInvoke(new dgtBool(DgtRefresh), true);
- }
+ }*/
private void SbOnTop_Click(object sender, RoutedEventArgs e) {
- Topmost = sbOnTop.IsChecked == true;
+ Topmost = sbOnTop.IsChecked.GetValueOrDefault(false);
+ WindowStyle = Topmost ? WindowStyle.None : WindowStyle.SingleBorderWindow;
+ ResizeMode = Topmost ? ResizeMode.NoResize : ResizeMode.CanResize;
+ //I don't remember what this is and I don't remember why it's being set
+ // only when always-on-top is enabled and then never again.
if(tGfx.Enabled && Topmost)
tGfx.Interval = 1000.0 / 60.0;
}
diff --git a/NightwaveForWorkgroups/NightwaveForWorkgroups.csproj b/NightwaveForWorkgroups/NightwaveForWorkgroups.csproj
index adb3d4f..1cfdf18 100644
--- a/NightwaveForWorkgroups/NightwaveForWorkgroups.csproj
+++ b/NightwaveForWorkgroups/NightwaveForWorkgroups.csproj
@@ -1,20 +1,20 @@
-ο»Ώ
+ο»ΏWinExe
- netcoreapp3.0
+ net6.0-windowstrueNightwave.NET for WorkgroupsSoftpup Aesthetics & Petting, p.r.p.l.Maff
- 1.7.0.1
- 1.7.0.1
+ 1.8.0.0
+ 1.8.0.0en-GBhttps://soft.pup.cloud/Nightwave.NET/
- https://git.maff.scot/maff/PlazaSharp/src/branch/master/NightwaveForWorkgroups
+ https://commit.pup.cloud/maff/PlazaSharp/src/branch/master/NightwaveForWorkgroupsgitBSD-3-CLAUSE
- 1.7-0r1
+ 1.8-0r0app.manifestResources\app.icoNightwaveForWorkgroups.App
diff --git a/NightwaveForWorkgroups/README.md b/NightwaveForWorkgroups/README.md
index 88688b1..7afa2ea 100644
--- a/NightwaveForWorkgroups/README.md
+++ b/NightwaveForWorkgroups/README.md
@@ -7,10 +7,12 @@ while maintaining aesthetics.
You can [get it here][6].
Intended future improvements include:
-* Optional session storage between sessions to avoid logging in again
* Multiple visualiser types
* Better use of additional application real-estate when resized
* Integration with the Windows native media APIs (so keyboard play/pause buttons work)
+* Storage for window height/width, always-on-top and volume state
+* Log-out button lmfao
+* Miniplayer!
## First-Party
@@ -25,6 +27,20 @@ Nightwave.NET uses the following third-party libraries and resources:
* [JSON.Net][4] by Newtonsoft for deserialisation of JSON strings.
* [CredentialManager][5] by Meziantou for access to the Windows Credential Manager APIs
+## Privacy, data collection & usage
+
+Nightwave.NET collects the following information and stores it locally in your Windows install's Enterprise Credentials Store:
+* Username for Nightwave Plaza
+* Password for Nightwave Plaza (encrypted)
+
+Nightwave.NET does not transmit any data over the internet itself, however the Nightwave Plaza library interface, **libplaza**, uploads the following information to remote servers:
+* Username and Password for Nightwave Plaza, uploaded by means of the Nightwave Plaza standard login mechanism, to **api.plaza.one/user/auth**, the standard login endpoint for Nightwave Plaza
+* Your vote for the current track, whenever you cast it, uploaded by means of the Nightwave Plaza reactions mechanism, to **api.plaza.one/reactions**, the standard voting endpoint for Nightwave Plaza
+
+Nightwave.NET and libplaza are both developed solely by me, and do not collect any information not mentioned here. To the best of my knowledge and personal verification,
+no third-party library in use by either Nightwave.NET or libplaza collects any data or makes any network connections, with the exception of **BASS**, which
+makes one network connection: to stream the Nightwave Radio audio stream to your computer.
+
[1]: https://plaza.one
[2]: https://www.un4seen.com/bass.html
[3]: https://github.com/ManagedBass/ManagedBass
diff --git a/libplaza/Main.cs b/libplaza/Main.cs
index b7673f8..005bf9a 100644
--- a/libplaza/Main.cs
+++ b/libplaza/Main.cs
@@ -1,6 +1,7 @@
ο»Ώusing System;
-using System.Collections.Generic;
+using System.Net;
using System.Net.Http;
+using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
@@ -38,22 +39,22 @@ namespace libplaza {
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public string artwork;
+ public string artwork_src;
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public string artwork_s;
+ public string artwork_sm_src;
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public int likes;
+ public int reactions;
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public int hates;
+ //public int hates;
}
///
@@ -79,7 +80,7 @@ namespace libplaza {
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
[JsonProperty]
- public PlazaPlayback playback;
+ public PlazaPlayback song;
}
///
@@ -110,6 +111,11 @@ namespace libplaza {
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
public string created_at;
+
+ ///
+ /// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+ ///
+ public PlazaCurrentVote current_like;
}
///
@@ -119,12 +125,12 @@ namespace libplaza {
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public string status;
+ public string result;
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public int[] ratings;
+ public int reactions;
}
///
@@ -134,7 +140,42 @@ namespace libplaza {
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public int rate;
+ public int reaction;
+ }
+
+ ///
+ /// A transitional class used internally by
+ ///
+ public class PlazaCurrentVote {
+ ///
+ /// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+ ///
+ public bool like_id;
+
+ ///
+ /// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+ ///
+ public PlazaLikedSong song;
+ }
+
+ ///
+ /// A transitional class used internally by
+ ///
+ public class PlazaLikedSong {
+ ///
+ /// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+ ///
+ public string artist;
+
+ ///
+ /// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+ ///
+ public string artwork_src;
+
+ ///
+ /// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+ ///
+ public string title;
}
///
@@ -154,7 +195,7 @@ namespace libplaza {
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
///
- public string status;
+ public string result;
///
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
@@ -182,6 +223,11 @@ namespace libplaza {
/// An object indicating that an error or exception occurred when communicating with the API.
///
internal class PlazaUnavailableException : Exception { }
+
+ ///
+ /// A object indicating that, while an error occurred, it's one that we can silently retry.
+ ///
+ internal class PlazaQuietlyUnavailableException : PlazaUnavailableException { }
#endregion
#region Type Definitions
///
@@ -252,7 +298,7 @@ namespace libplaza {
///
/// Contains an integer value of the number of dislikes the currently-playing track has received
///
- public int Dislikes;
+ //public int Dislikes;
///
/// Contains an integer value of the number of people currently listening to the broadcast
@@ -266,8 +312,9 @@ namespace libplaza {
///
/// To Dislike is to indicate the user's disposition towards this track is one of displeasure;
/// that the user does not appreciate hearing this track, perhaps even that the user wishes not to hear this track.
+ /// This field was removed at some point, because it "no longer makes any sense" - I disagree.
///
- Dislike = -1,
+ //Dislike = -1,
///
/// To be of Neutral disposition is to indicate the user has no feelings towards this track,
@@ -288,6 +335,7 @@ namespace libplaza {
Favourite
}
#endregion
+ #region Nightwave
///
/// is the primary class by which the Nightwave Plaza API can be used.
///
@@ -313,7 +361,7 @@ namespace libplaza {
/// nwd = new ("http://localhost:8000");
///
public Nightwave(string baseuri = "https://api.plaza.one/") {
- MinRefreshTime = 10;
+ MinRefreshTime = 15;
_hcl.BaseAddress = new Uri(baseuri);
_hcl.Timeout = TimeSpan.FromSeconds(2);
_hcl.DefaultRequestHeaders.Accept.Clear();
@@ -373,7 +421,7 @@ namespace libplaza {
// or if the currently-playing track's elapsed time is more than the track duration.
if(Force
|| (tsLastRefresh + MinRefreshTime < DateTimeOffset.Now.ToUnixTimeSeconds())
- || _bc.CalculatedElapsed < _bc.Duration) {
+ || _bc.CalculatedElapsed > _bc.Duration) {
await Update();
tsLastRefresh = DateTimeOffset.Now.ToUnixTimeSeconds();
}
@@ -393,6 +441,10 @@ namespace libplaza {
} catch(PlazaInMaintenanceException) {
_bc.InMaintenance = true;
_bc.FaultOccurred = false;
+ } catch(PlazaQuietlyUnavailableException) {
+ _bc.FaultOccurred = false;
+ } catch(PlazaUnavailableException) {
+ _bc.FaultOccurred = true;
} catch(Exception) { //TODO make this more reliable?
_bc.FaultOccurred = true;
}
@@ -407,23 +459,25 @@ namespace libplaza {
public async Task GetNightwaveAsync() {
Status status;
HttpResponseMessage _r=await _hcl.GetAsync("/status");
+ if(_r.StatusCode == HttpStatusCode.TooManyRequests)
+ throw new PlazaQuietlyUnavailableException();
if(!_r.IsSuccessStatusCode)
throw new PlazaUnavailableException();
PlazaJson j=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
if(j.maintenance)
throw new PlazaInMaintenanceException();
+ // Previously this calculated ServerTimeOffset as Now - Headers.Date.Value.ToUnixTimeSeconds
status = new Status {
- Title = j.playback.title,
- Album = j.playback.album,
- Artist = j.playback.artist,
- Elapsed = j.playback.position,
- Duration = j.playback.length,
+ Title = j.song.title,
+ Album = j.song.album,
+ Artist = j.song.artist,
+ Elapsed = j.song.position,
+ Duration = j.song.length,
Since = j.updated_at,
- Likes = j.playback.likes,
- Dislikes = j.playback.hates,
+ Likes = j.song.reactions,
Listeners = j.listeners,
- ServerTimeOffset = (int)(DateTimeOffset.Now.ToUnixTimeSeconds() - _r.Headers.Date.Value.ToUnixTimeSeconds()),
- ArtworkUri = $"https://plaza.one/{j.playback.artwork}"
+ ServerTimeOffset = (int)(DateTimeOffset.Now.ToUnixTimeSeconds() - j.updated_at),
+ ArtworkUri = j.song.artwork_src
};
return status;
}
@@ -435,11 +489,12 @@ namespace libplaza {
public async Task Vote() {
if(!await CheckSession())
return null;
- HttpResponseMessage _r=await _hcl.GetAsync("/vote");
- if(!_r.IsSuccessStatusCode)
- return null;
- PlazaGetVote r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
- return (Vote)r.rate;
+ PlazaUser r=await GetUser();
+ if(r.current_like == null)
+ return libplaza.Vote.Neutral;
+ if(r.current_like.like_id)
+ return libplaza.Vote.Favourite;
+ return libplaza.Vote.Like;
}
///
@@ -450,12 +505,12 @@ namespace libplaza {
public async Task Vote(Vote v) {
if(!await CheckSession())
return false;
- HttpResponseMessage _r=await _hcl.PostAsync("/vote", new FormUrlEncodedContent(new[] {
- new KeyValuePair("rate", ((int)v).ToString())}));
+ HttpResponseMessage _r=await _hcl.PostAsync("/reactions", new StringContent(
+ $"{{\"reaction\":{(int)v}}}", Encoding.UTF8, "application/json"));
if(!_r.IsSuccessStatusCode)
return false;
PlazaVote r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
- return r.status == "success";
+ return r.result == "success";
}
///
@@ -474,18 +529,27 @@ namespace libplaza {
///
/// A boolean value indicating whether the request succeeded
public async Task CheckSession() =>
- await GetUser() != null;
+ await GetUsername() != null;
+
+ ///
+ /// Performs a basic read-only API request to fetch the profile information for the current user
+ ///
+ /// If successful, returns a containing the user's profile information. If unsuccessful, returns null.
+ public async Task GetUser() {
+ HttpResponseMessage _r=await _hcl.GetAsync("/user");
+ if(!_r.IsSuccessStatusCode)
+ return null;
+ PlazaUser r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
+ return r;
+ }
///
/// Performs a basic read-only API request to fetch the currently-authenticated user's profile details.
///
/// If successful, returns a string containing the authenticated user's username. If unsuccessful, will return null.
- public async Task GetUser() {
- HttpResponseMessage _r=await _hcl.GetAsync("/user");
- if(!_r.IsSuccessStatusCode)
- return null;
- PlazaUser r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
- return r.id <= 0 ? null : r.username;
+ public async Task GetUsername() {
+ PlazaUser r=await GetUser();
+ return (r==null || r.username==null || r.username?.Length <= 0) ? null : r.username;
}
///
@@ -497,8 +561,21 @@ namespace libplaza {
///
/// Functionally, this method is a wrapper for , performing the function of generating a Basic authentication string
///
- public async Task Login(string u, string p) =>
- await Login(Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{u}:{p}")));
+ public async Task Login(string u, string p) {
+ _hcl.DefaultRequestHeaders.Add("Authorization", "Bearer 1");
+ HttpResponseMessage _r=await _hcl.PostAsync("/user/auth", new StringContent(
+ $"{{\"username\":\"{u}\",\"password\":\"{p}\"}}", Encoding.UTF8, "application/json"));
+ _ = _hcl.DefaultRequestHeaders.Remove("Authorization");
+ if(_r.StatusCode == HttpStatusCode.TooManyRequests)
+ return false;
+ if(!_r.IsSuccessStatusCode)
+ return false;
+ PlazaLogonResult r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
+ if(r.result != "ok")
+ return false;
+ _hcl.DefaultRequestHeaders.Add("Authorization", $"Bearer {r.token}");
+ return true;
+ }
///
/// Performs a login request to the API with the given HTTP Basic authentication string.
@@ -511,7 +588,7 @@ namespace libplaza {
if(!_r.IsSuccessStatusCode)
return false;
PlazaLogonResult r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
- if(r.status != "success")
+ if(r.result != "success")
return false;
_hcl.DefaultRequestHeaders.Add("X-Access-Token", r.token);
_ = _hcl.DefaultRequestHeaders.Remove("Authorization");
@@ -531,4 +608,5 @@ namespace libplaza {
_ = _hcl.DefaultRequestHeaders.Remove("X-Access-Token");
}
}
+ #endregion
}
diff --git a/libplaza/libplaza.csproj b/libplaza/libplaza.csproj
index 0b36714..1ceba2c 100644
--- a/libplaza/libplaza.csproj
+++ b/libplaza/libplaza.csproj
@@ -1,7 +1,7 @@
ο»Ώ
- netstandard1.4
+ net6.0-windowsfalseen-GBfalse
@@ -11,12 +11,12 @@
A moderately generic .Net interface to the Nightwave Plaza APINightwave Plaza is wholly copyright and owned by its creator, I just wrote this unofficial library that talks to it.https://soft.pup.cloud/Nightwave.NET/
- https://git.maff.scot/maff/PlazaSharp/src/branch/master/libplaza
+ https://commit.pup.cloud/maff/PlazaSharp/src/branch/master/libplaza
- C:\Users\MC185353\source\repos\PlazaSharp\libplaza\libplaza.xml
+ C:\Users\maff\source\repos\PlazaSharp\libplaza\libplaza.xml
diff --git a/libplaza/libplaza.xml b/libplaza/libplaza.xml
index 09462c3..c469e5a 100644
--- a/libplaza/libplaza.xml
+++ b/libplaza/libplaza.xml
@@ -34,22 +34,17 @@
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
-
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
-
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
-
-
- A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
-
-
-
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
@@ -74,7 +69,7 @@
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
-
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
@@ -109,17 +104,22 @@
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+
+
+ A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+
+
A transitional class used internally by
-
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
-
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
@@ -129,7 +129,42 @@
A transitional class used internally by
-
+
+
+ A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+
+
+
+
+ A transitional class used internally by
+
+
+
+
+ A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+
+
+
+
+ A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+
+
+
+
+ A transitional class used internally by
+
+
+
+
+ A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+
+
+
+
+ A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
+
+
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
@@ -149,7 +184,7 @@
A transitional class used internally by
-
+
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
@@ -179,6 +214,11 @@
An object indicating that an error or exception occurred when communicating with the API.
+
+
+ A object indicating that, while an error occurred, it's one that we can silently retry.
+
+
Represents the current broadcast information returned by a API object.
@@ -244,11 +284,6 @@
Contains an integer value of the number of likes the currently-playing track has received
-
-
- Contains an integer value of the number of dislikes the currently-playing track has received
-
-
Contains an integer value of the number of people currently listening to the broadcast
@@ -259,12 +294,6 @@
Represents the user's disposition towards the currently-playing track.
-
-
- To Dislike is to indicate the user's disposition towards this track is one of displeasure;
- that the user does not appreciate hearing this track, perhaps even that the user wishes not to hear this track.
-
-
To be of Neutral disposition is to indicate the user has no feelings towards this track,
@@ -395,6 +424,12 @@
A boolean value indicating whether the request succeeded
+
+ Performs a basic read-only API request to fetch the profile information for the current user
+
+ If successful, returns a containing the user's profile information. If unsuccessful, returns null.
+
+
Performs a basic read-only API request to fetch the currently-authenticated user's profile details.