1.8: Make Nightwave for Workgroups/Nightwave.NET work again
Nightwave Plaza had a couple of API changes! i have now made it work.
This commit is contained in:
parent
6be173855a
commit
f688cd63a9
|
@ -33,9 +33,9 @@
|
||||||
<Label x:Name="lbElapsed" Content="00:00" HorizontalAlignment="Left" Margin="0,99,0,0" VerticalAlignment="Top" FontStyle="Italic" FontSize="9" Grid.Column="1"/>
|
<Label x:Name="lbElapsed" Content="00:00" HorizontalAlignment="Left" Margin="0,99,0,0" VerticalAlignment="Top" FontStyle="Italic" FontSize="9" Grid.Column="1"/>
|
||||||
<Label x:Name="lbTime" Content="00:00" Margin="0,99,0,0" VerticalAlignment="Top" HorizontalAlignment="Right" FontStyle="Italic" FontSize="9" Grid.Column="2"/>
|
<Label x:Name="lbTime" Content="00:00" Margin="0,99,0,0" VerticalAlignment="Top" HorizontalAlignment="Right" FontStyle="Italic" FontSize="9" Grid.Column="2"/>
|
||||||
<Button x:Name="btLike" Content="❤" ToolTip="Like this track" IsEnabled="False" HorizontalAlignment="Right" Margin="0,40,2,0" Width="22" Height="20" VerticalAlignment="Top" FontSize="10" Grid.Column="2" Click="BtLike_Click"/>
|
<Button x:Name="btLike" Content="❤" ToolTip="Like this track" IsEnabled="False" HorizontalAlignment="Right" Margin="0,40,2,0" Width="22" Height="20" VerticalAlignment="Top" FontSize="10" Grid.Column="2" Click="BtLike_Click"/>
|
||||||
<Button x:Name="btDislike" Content="💔" ToolTip="Dislike this track" IsEnabled="False" HorizontalAlignment="Right" Margin="0,64,2,0" Width="22" Height="20" VerticalAlignment="Top" FontSize="10" Grid.Column="2" Click="BtDislike_Click"/>
|
<!--<Button x:Name="btDislike" Content="💔" ToolTip="Dislike this track" IsEnabled="False" HorizontalAlignment="Right" Margin="0,64,2,0" Width="22" Height="20" VerticalAlignment="Top" FontSize="10" Grid.Column="2" Click="BtDislike_Click"/>-->
|
||||||
<Label x:Name="lbLikeCt" Content="0" HorizontalAlignment="Right" Margin="0,36.5,22,0" VerticalAlignment="Top" Grid.Column="2" Grid.ColumnSpan="2"/>
|
<Label x:Name="lbLikeCt" Content="0" HorizontalAlignment="Right" Margin="0,36.5,22,0" VerticalAlignment="Top" Grid.Column="2" Grid.ColumnSpan="2"/>
|
||||||
<Label x:Name="lbDislikeCt" Content="0" HorizontalAlignment="Right" Margin="0,60.5,22,0" VerticalAlignment="Top" Grid.Column="2" Grid.ColumnSpan="2"/>
|
<!--<Label x:Name="lbDislikeCt" Content="0" HorizontalAlignment="Right" Margin="0,60.5,22,0" VerticalAlignment="Top" Grid.Column="2" Grid.ColumnSpan="2"/>-->
|
||||||
<Image x:Name="imLogin" IsHitTestVisible="False" Panel.ZIndex="1" Width="18" Height="18" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,17,3,0" Grid.Column="2" Source="Resources/usr.png" Stretch="UniformToFill"/>
|
<Image x:Name="imLogin" IsHitTestVisible="False" Panel.ZIndex="1" Width="18" Height="18" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,17,3,0" Grid.Column="2" Source="Resources/usr.png" Stretch="UniformToFill"/>
|
||||||
<Button x:Name="btLogin" Content="" ToolTip="Log into Nightwave Plaza" HorizontalAlignment="Right" Margin="0,16,2,0" Width="22" Height="20" VerticalAlignment="Top" FontSize="9" Grid.Column="2" Click="BtLogin_Click"/>
|
<Button x:Name="btLogin" Content="" ToolTip="Log into Nightwave Plaza" HorizontalAlignment="Right" Margin="0,16,2,0" Width="22" Height="20" VerticalAlignment="Top" FontSize="9" Grid.Column="2" Click="BtLogin_Click"/>
|
||||||
<TextBlock ToolTip="Visit Nightwave Plaza! If you don't have an account, you can make one there!" FontSize="10" FontStyle="Italic" Grid.Column="2" Grid.Row="0" Margin="0,0,2,13" HorizontalAlignment="Right" VerticalAlignment="Bottom" Foreground="#FF5A5A5A">
|
<TextBlock ToolTip="Visit Nightwave Plaza! If you don't have an account, you can make one there!" FontSize="10" FontStyle="Italic" Grid.Column="2" Grid.Row="0" Margin="0,0,2,13" HorizontalAlignment="Right" VerticalAlignment="Bottom" Foreground="#FF5A5A5A">
|
||||||
|
@ -43,24 +43,31 @@
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<DockPanel Grid.ColumnSpan="5" Margin="0,0,0,0" Grid.Row="1">
|
<DockPanel Grid.ColumnSpan="5" Margin="0,0,0,0" Grid.Row="1">
|
||||||
<StatusBar x:Name="statusBar" Margin="0,0,0,-2" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" BorderBrush="#FFDFDFDF" BorderThickness="1" Height="28" VerticalContentAlignment="Bottom">
|
<StatusBar x:Name="statusBar" Margin="0,0,0,-2" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" BorderBrush="#FFDFDFDF" BorderThickness="1" Height="28" VerticalContentAlignment="Bottom">
|
||||||
<StatusBarItem HorizontalAlignment="Left">
|
<StatusBarItem HorizontalAlignment="Left">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock x:Name="sbListeners" Text="Listener count" Margin="4,0,4,0"/>
|
<ToggleButton x:Name="btPlayPause" Content="⏯" ToolTip="Start/Stop playback" VerticalContentAlignment="Center" Checked="BtPlayPause_Click" Unchecked="BtPlayPause_Click" Margin="0,-2,4,-2"/>
|
||||||
<ToggleButton x:Name="btPlayPause" Content="⏯" ToolTip="Start/Stop playback" VerticalContentAlignment="Center" Checked="BtPlayPause_Click" Unchecked="BtPlayPause_Click" Margin="0,-2,4,-2"/>
|
<TextBlock x:Name="sbListeners" Text="Listener count" Margin="2,0,0,0"/>
|
||||||
<TextBlock x:Name="sbStatus" Text="Status"/>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StatusBarItem>
|
||||||
</StatusBarItem>
|
<Separator/>
|
||||||
<StatusBarItem HorizontalAlignment="Right">
|
<StatusBarItem HorizontalAlignment="Left">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<!--TODO implement tracking of time spent listening (this session and all-time)
|
<TextBlock x:Name="sbStatus" Text="Status"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StatusBarItem>
|
||||||
|
<StatusBarItem DockPanel.Dock="Right" HorizontalAlignment="Right">
|
||||||
|
<Slider x:Name="sbVol" Maximum="100" Minimum="0" ToolTip="Volume level" Value="100" SmallChange="1" LargeChange="5" Width="80" ValueChanged="SbVol_ValueChanged" MouseWheel="SbVol_MouseWheel" Margin="0,0,4,0"/>
|
||||||
|
</StatusBarItem>
|
||||||
|
<Separator DockPanel.Dock="Right" HorizontalAlignment="Right" />
|
||||||
|
<StatusBarItem DockPanel.Dock="Right" HorizontalAlignment="Right" >
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<!--TODO implement tracking of time spent listening (this session and all-time)
|
||||||
<TextBlock x:Name="sbListeningTimers" Text="00:00 (00:00)"/>-->
|
<TextBlock x:Name="sbListeningTimers" Text="00:00 (00:00)"/>-->
|
||||||
<TextBlock x:Name="sbVote" Text="Vote" Margin="0,0,4,0"/>
|
<TextBlock x:Name="sbVote" Text="Vote" Margin="0,0,4,0"/>
|
||||||
<ToggleButton x:Name="sbOnTop" Content="📌" ToolTip="Toggle always-on-top" Checked="SbOnTop_Click" Margin="0,-2,4,-2"/>
|
<ToggleButton x:Name="sbOnTop" Content="📌" ToolTip="Toggle always-on-top" Checked="SbOnTop_Click" Unchecked="SbOnTop_Click" Margin="0,-2,4,-2"/>
|
||||||
<ToggleButton x:Name="sbMute" Content="🔊" ToolTip="Toggle mute" Checked="SbMute_Click" Unchecked="SbMute_Click" Margin="0,-2,0,-2"/>
|
<ToggleButton x:Name="sbMute" Content="🔊" ToolTip="Toggle mute" Checked="SbMute_Click" Unchecked="SbMute_Click" Margin="0,-2,0,-2"/>
|
||||||
<Separator Width="6" Background="{x:Null}" Foreground="{x:Null}"/>
|
</StackPanel>
|
||||||
<Slider x:Name="sbVol" Maximum="100" Minimum="0" ToolTip="Volume level" Value="100" SmallChange="1" LargeChange="5" Width="80" ValueChanged="SbVol_ValueChanged" MouseWheel="SbVol_MouseWheel" Margin="0,0,4,0"/>
|
</StatusBarItem>
|
||||||
</StackPanel>
|
|
||||||
</StatusBarItem>
|
|
||||||
</StatusBar>
|
</StatusBar>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
<Rectangle Height="1" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="0" Margin="0,0,0,10" Fill="#FF003C49" VerticalAlignment="Bottom"/>
|
<Rectangle Height="1" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="0" Margin="0,0,0,10" Fill="#FF003C49" VerticalAlignment="Bottom"/>
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace NightwaveForWorkgroups {
|
||||||
btLogin.Visibility = Visibility.Hidden;
|
btLogin.Visibility = Visibility.Hidden;
|
||||||
imLogin.IsEnabled = false;
|
imLogin.IsEnabled = false;
|
||||||
imLogin.Visibility = Visibility.Hidden;
|
imLogin.Visibility = Visibility.Hidden;
|
||||||
btDislike.IsEnabled = true;
|
//btDislike.IsEnabled = true;
|
||||||
btLike.IsEnabled = true;
|
btLike.IsEnabled = true;
|
||||||
SetStatus($"Logged in as {await NwP.GetUser()}");
|
SetStatus($"Logged in as {await NwP.GetUser()}");
|
||||||
}
|
}
|
||||||
|
@ -88,43 +88,43 @@ namespace NightwaveForWorkgroups {
|
||||||
slDuration.Value = s.CalculatedElapsed;
|
slDuration.Value = s.CalculatedElapsed;
|
||||||
sbListeners.Text = $"{s.Listeners} listeners";
|
sbListeners.Text = $"{s.Listeners} listeners";
|
||||||
lbLikeCt.Content = s.Likes;
|
lbLikeCt.Content = s.Likes;
|
||||||
lbDislikeCt.Content = s.Dislikes;
|
//lbDislikeCt.Content = s.Dislikes;
|
||||||
lbElapsed.Content = $"{(s.CalculatedElapsed / 60).ToString("D")}:{(s.CalculatedElapsed % 60).ToString("D2")}";
|
lbElapsed.Content = $"{(s.CalculatedElapsed / 60).ToString("D")}:{(s.CalculatedElapsed % 60).ToString("D2")}";
|
||||||
if(LastArtwork != s.ArtworkUri || Force) {
|
if(LastArtwork != s.ArtworkUri || Force) {
|
||||||
//TODO should probably break this part out into a separate function cause this feels real messy
|
//TODO should probably break this part out into a separate function cause this feels real messy
|
||||||
Vote v = await NwP.Vote() ?? Vote.Neutral;
|
Vote v = await NwP.Vote() ?? Vote.Neutral;
|
||||||
switch(v) {
|
switch(v) {
|
||||||
case Vote.Dislike:
|
/*case Vote.Dislike:
|
||||||
sbVote.Text = "👎";
|
sbVote.Text = "👎";
|
||||||
sbVote.ToolTip = "You dislike this.";
|
sbVote.ToolTip = "You dislike this.";
|
||||||
btLike.Content = "👍";
|
btLike.Content = "👍";
|
||||||
btLike.ToolTip = "Like this track";
|
btLike.ToolTip = "Like this track";
|
||||||
btDislike.Content = "🤷♀️";
|
btDislike.Content = "🤷♀️";
|
||||||
btDislike.ToolTip = "Remove your vote for this track";
|
btDislike.ToolTip = "Remove your vote for this track";
|
||||||
break;
|
break;*/
|
||||||
case Vote.Like:
|
case Vote.Like:
|
||||||
sbVote.Text = "👍";
|
sbVote.Text = "👍";
|
||||||
sbVote.ToolTip = "You like this.";
|
sbVote.ToolTip = "You like this.";
|
||||||
btLike.Content = "💖";
|
btLike.Content = "💖";
|
||||||
btLike.ToolTip = "Favourite this track";
|
btLike.ToolTip = "Favourite this track";
|
||||||
btDislike.Content = "👎";
|
//btDislike.Content = "👎";
|
||||||
btDislike.ToolTip = "Dislike this track";
|
//btDislike.ToolTip = "Dislike this track";
|
||||||
break;
|
break;
|
||||||
case Vote.Favourite:
|
case Vote.Favourite:
|
||||||
sbVote.Text = "💖";
|
sbVote.Text = "💖";
|
||||||
sbVote.ToolTip = "You have favourited this.";
|
sbVote.ToolTip = "You have favourited this.";
|
||||||
btLike.Content = "🤷♀️";
|
btLike.Content = "🤷♀️";
|
||||||
btLike.ToolTip = "Remove your vote for this track";
|
btLike.ToolTip = "Remove your vote for this track";
|
||||||
btDislike.Content = "👎";
|
//btDislike.Content = "👎";
|
||||||
btDislike.ToolTip = "Dislike this track";
|
//btDislike.ToolTip = "Dislike this track";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sbVote.Text = "🤷♀️";
|
sbVote.Text = "🤷♀️";
|
||||||
sbVote.ToolTip = "You have no feelings towards this, or you have not expressed your feelings for this.";
|
sbVote.ToolTip = "You have no feelings towards this, or you have not expressed your feelings for this.";
|
||||||
btLike.Content = "👍";
|
btLike.Content = "👍";
|
||||||
btLike.ToolTip = "Like this track";
|
btLike.ToolTip = "Like this track";
|
||||||
btDislike.Content = "👎";
|
//btDislike.Content = "👎";
|
||||||
btDislike.ToolTip = "Dislike this track";
|
//btDislike.ToolTip = "Dislike this track";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//TODO visual effect on the like/dislike buttons to indicate user's vote
|
//TODO visual effect on the like/dislike buttons to indicate user's vote
|
||||||
|
@ -259,7 +259,10 @@ namespace NightwaveForWorkgroups {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//user may have stored credentials and not want to keep them any more, delete with reckless abandon.
|
//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) {
|
if(_c.CredentialSaved == CredentialSaveOption.Selected) {
|
||||||
CredentialManager.WriteCredential("Nightwave.NET", _c.UserName, _c.Password, CredentialPersistence.Enterprise);
|
CredentialManager.WriteCredential("Nightwave.NET", _c.UserName, _c.Password, CredentialPersistence.Enterprise);
|
||||||
Credential c=CredentialManager.ReadCredential("Nightwave.NET");
|
Credential c=CredentialManager.ReadCredential("Nightwave.NET");
|
||||||
|
@ -278,13 +281,14 @@ namespace NightwaveForWorkgroups {
|
||||||
btLogin.Visibility = Visibility.Hidden;
|
btLogin.Visibility = Visibility.Hidden;
|
||||||
imLogin.IsEnabled = false;
|
imLogin.IsEnabled = false;
|
||||||
imLogin.Visibility = Visibility.Hidden;
|
imLogin.Visibility = Visibility.Hidden;
|
||||||
btDislike.IsEnabled = true;
|
//btDislike.IsEnabled = true;
|
||||||
btLike.IsEnabled = true;
|
btLike.IsEnabled = true;
|
||||||
SetStatus($"Logged in as {await NwP.GetUser()}");
|
SetStatus($"Logged in as {await NwP.GetUser()}");
|
||||||
}
|
}
|
||||||
private async void BtLike_Click(object sender, RoutedEventArgs e) {
|
private async void BtLike_Click(object sender, RoutedEventArgs e) {
|
||||||
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btLike);
|
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btLike);
|
||||||
Vote v = await NwP.Vote() ?? Vote.Neutral;
|
Vote v = await NwP.Vote() ?? Vote.Neutral;
|
||||||
|
// Kinda like a garbage state machine
|
||||||
v = v switch {
|
v = v switch {
|
||||||
Vote.Like => Vote.Favourite,
|
Vote.Like => Vote.Favourite,
|
||||||
Vote.Favourite => Vote.Neutral,
|
Vote.Favourite => Vote.Neutral,
|
||||||
|
@ -297,7 +301,7 @@ namespace NightwaveForWorkgroups {
|
||||||
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btLike);
|
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btLike);
|
||||||
_ = Dispatcher.BeginInvoke(new dgtBool(DgtRefresh), true);
|
_ = 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);
|
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btDislike);
|
||||||
Vote v = Vote.Dislike;
|
Vote v = Vote.Dislike;
|
||||||
if(await NwP.Vote() == Vote.Dislike)
|
if(await NwP.Vote() == Vote.Dislike)
|
||||||
|
@ -308,9 +312,13 @@ namespace NightwaveForWorkgroups {
|
||||||
SetStatus($"Something went weird while casting {v}");
|
SetStatus($"Something went weird while casting {v}");
|
||||||
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btDislike);
|
_ = Dispatcher.BeginInvoke(new dgtCtrl(DgtToggleEnabled), btDislike);
|
||||||
_ = Dispatcher.BeginInvoke(new dgtBool(DgtRefresh), true);
|
_ = Dispatcher.BeginInvoke(new dgtBool(DgtRefresh), true);
|
||||||
}
|
}*/
|
||||||
private void SbOnTop_Click(object sender, RoutedEventArgs e) {
|
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)
|
if(tGfx.Enabled && Topmost)
|
||||||
tGfx.Interval = 1000.0 / 60.0;
|
tGfx.Interval = 1000.0 / 60.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<Product>Nightwave.NET for Workgroups</Product>
|
<Product>Nightwave.NET for Workgroups</Product>
|
||||||
<Company>Softpup Aesthetics & Petting, p.r.p.l.</Company>
|
<Company>Softpup Aesthetics & Petting, p.r.p.l.</Company>
|
||||||
<Authors>Maff</Authors>
|
<Authors>Maff</Authors>
|
||||||
<AssemblyVersion>1.7.0.1</AssemblyVersion>
|
<AssemblyVersion>1.8.0.0</AssemblyVersion>
|
||||||
<FileVersion>1.7.0.1</FileVersion>
|
<FileVersion>1.8.0.0</FileVersion>
|
||||||
<NeutralLanguage>en-GB</NeutralLanguage>
|
<NeutralLanguage>en-GB</NeutralLanguage>
|
||||||
<PackageProjectUrl>https://soft.pup.cloud/Nightwave.NET/</PackageProjectUrl>
|
<PackageProjectUrl>https://soft.pup.cloud/Nightwave.NET/</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://git.maff.scot/maff/PlazaSharp/src/branch/master/NightwaveForWorkgroups</RepositoryUrl>
|
<RepositoryUrl>https://commit.pup.cloud/maff/PlazaSharp/src/branch/master/NightwaveForWorkgroups</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<PackageLicenseExpression>BSD-3-CLAUSE</PackageLicenseExpression>
|
<PackageLicenseExpression>BSD-3-CLAUSE</PackageLicenseExpression>
|
||||||
<Version>1.7-0r1</Version>
|
<Version>1.8-0r0</Version>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<ApplicationIcon>Resources\app.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\app.ico</ApplicationIcon>
|
||||||
<StartupObject>NightwaveForWorkgroups.App</StartupObject>
|
<StartupObject>NightwaveForWorkgroups.App</StartupObject>
|
||||||
|
|
|
@ -7,10 +7,12 @@ while maintaining aesthetics.
|
||||||
You can [get it here][6].
|
You can [get it here][6].
|
||||||
|
|
||||||
Intended future improvements include:
|
Intended future improvements include:
|
||||||
* Optional session storage between sessions to avoid logging in again
|
|
||||||
* Multiple visualiser types
|
* Multiple visualiser types
|
||||||
* Better use of additional application real-estate when resized
|
* Better use of additional application real-estate when resized
|
||||||
* Integration with the Windows native media APIs (so keyboard play/pause buttons work)
|
* 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
|
## 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.
|
* [JSON.Net][4] by Newtonsoft for deserialisation of JSON strings.
|
||||||
* [CredentialManager][5] by Meziantou for access to the Windows Credential Manager APIs
|
* [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
|
[1]: https://plaza.one
|
||||||
[2]: https://www.un4seen.com/bass.html
|
[2]: https://www.un4seen.com/bass.html
|
||||||
[3]: https://github.com/ManagedBass/ManagedBass
|
[3]: https://github.com/ManagedBass/ManagedBass
|
||||||
|
|
160
libplaza/Main.cs
160
libplaza/Main.cs
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
@ -38,22 +39,22 @@ namespace libplaza {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string artwork;
|
public string artwork_src;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string artwork_s;
|
public string artwork_sm_src;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int likes;
|
public int reactions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int hates;
|
//public int hates;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -79,7 +80,7 @@ namespace libplaza {
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
public PlazaPlayback playback;
|
public PlazaPlayback song;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -110,6 +111,11 @@ namespace libplaza {
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string created_at;
|
public string created_at;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
/// </summary>
|
||||||
|
public PlazaCurrentVote current_like;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -119,12 +125,12 @@ namespace libplaza {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string status;
|
public string result;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int[] ratings;
|
public int reactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -134,7 +140,42 @@ namespace libplaza {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int rate;
|
public int reaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A transitional class used internally by <see cref="JsonConvert.DeserializeObject{T}(string)"/>
|
||||||
|
/// </summary>
|
||||||
|
public class PlazaCurrentVote {
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
/// </summary>
|
||||||
|
public bool like_id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
/// </summary>
|
||||||
|
public PlazaLikedSong song;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A transitional class used internally by <see cref="JsonConvert.DeserializeObject{T}(string)"/>
|
||||||
|
/// </summary>
|
||||||
|
public class PlazaLikedSong {
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
/// </summary>
|
||||||
|
public string artist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
/// </summary>
|
||||||
|
public string artwork_src;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
/// </summary>
|
||||||
|
public string title;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -154,7 +195,7 @@ namespace libplaza {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string status;
|
public string result;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
|
@ -182,6 +223,11 @@ namespace libplaza {
|
||||||
/// An <see cref="Exception"/> object indicating that an error or exception occurred when communicating with the <see cref="Nightwave"/> API.
|
/// An <see cref="Exception"/> object indicating that an error or exception occurred when communicating with the <see cref="Nightwave"/> API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class PlazaUnavailableException : Exception { }
|
internal class PlazaUnavailableException : Exception { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="PlazaUnavailableException"/> object indicating that, while an error occurred, it's one that we can silently retry.
|
||||||
|
/// </summary>
|
||||||
|
internal class PlazaQuietlyUnavailableException : PlazaUnavailableException { }
|
||||||
#endregion
|
#endregion
|
||||||
#region Type Definitions
|
#region Type Definitions
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -252,7 +298,7 @@ namespace libplaza {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains an integer value of the number of dislikes the currently-playing track has received
|
/// Contains an integer value of the number of dislikes the currently-playing track has received
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Dislikes;
|
//public int Dislikes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains an integer value of the number of people currently listening to the broadcast
|
/// Contains an integer value of the number of people currently listening to the broadcast
|
||||||
|
@ -266,8 +312,9 @@ namespace libplaza {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// To <c>Dislike</c> is to indicate the user's disposition towards this track is one of displeasure;
|
/// To <c>Dislike</c> 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.
|
/// 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Dislike = -1,
|
//Dislike = -1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// To be of <c>Neutral</c> disposition is to indicate the user has no feelings towards this track,
|
/// To be of <c>Neutral</c> disposition is to indicate the user has no feelings towards this track,
|
||||||
|
@ -288,6 +335,7 @@ namespace libplaza {
|
||||||
Favourite
|
Favourite
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
#region Nightwave
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="Nightwave"/> is the primary class by which the Nightwave Plaza API can be used.
|
/// <see cref="Nightwave"/> is the primary class by which the Nightwave Plaza API can be used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -313,7 +361,7 @@ namespace libplaza {
|
||||||
/// <code><see cref="Nightwave"/> nwd = new <see cref="Nightwave"/>("http://localhost:8000");</code>
|
/// <code><see cref="Nightwave"/> nwd = new <see cref="Nightwave"/>("http://localhost:8000");</code>
|
||||||
/// </example>
|
/// </example>
|
||||||
public Nightwave(string baseuri = "https://api.plaza.one/") {
|
public Nightwave(string baseuri = "https://api.plaza.one/") {
|
||||||
MinRefreshTime = 10;
|
MinRefreshTime = 15;
|
||||||
_hcl.BaseAddress = new Uri(baseuri);
|
_hcl.BaseAddress = new Uri(baseuri);
|
||||||
_hcl.Timeout = TimeSpan.FromSeconds(2);
|
_hcl.Timeout = TimeSpan.FromSeconds(2);
|
||||||
_hcl.DefaultRequestHeaders.Accept.Clear();
|
_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.
|
// or if the currently-playing track's elapsed time is more than the track duration.
|
||||||
if(Force
|
if(Force
|
||||||
|| (tsLastRefresh + MinRefreshTime < DateTimeOffset.Now.ToUnixTimeSeconds())
|
|| (tsLastRefresh + MinRefreshTime < DateTimeOffset.Now.ToUnixTimeSeconds())
|
||||||
|| _bc.CalculatedElapsed < _bc.Duration) {
|
|| _bc.CalculatedElapsed > _bc.Duration) {
|
||||||
await Update();
|
await Update();
|
||||||
tsLastRefresh = DateTimeOffset.Now.ToUnixTimeSeconds();
|
tsLastRefresh = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
}
|
}
|
||||||
|
@ -393,6 +441,10 @@ namespace libplaza {
|
||||||
} catch(PlazaInMaintenanceException) {
|
} catch(PlazaInMaintenanceException) {
|
||||||
_bc.InMaintenance = true;
|
_bc.InMaintenance = true;
|
||||||
_bc.FaultOccurred = false;
|
_bc.FaultOccurred = false;
|
||||||
|
} catch(PlazaQuietlyUnavailableException) {
|
||||||
|
_bc.FaultOccurred = false;
|
||||||
|
} catch(PlazaUnavailableException) {
|
||||||
|
_bc.FaultOccurred = true;
|
||||||
} catch(Exception) { //TODO make this more reliable?
|
} catch(Exception) { //TODO make this more reliable?
|
||||||
_bc.FaultOccurred = true;
|
_bc.FaultOccurred = true;
|
||||||
}
|
}
|
||||||
|
@ -407,23 +459,25 @@ namespace libplaza {
|
||||||
public async Task<Status> GetNightwaveAsync() {
|
public async Task<Status> GetNightwaveAsync() {
|
||||||
Status status;
|
Status status;
|
||||||
HttpResponseMessage _r=await _hcl.GetAsync("/status");
|
HttpResponseMessage _r=await _hcl.GetAsync("/status");
|
||||||
|
if(_r.StatusCode == HttpStatusCode.TooManyRequests)
|
||||||
|
throw new PlazaQuietlyUnavailableException();
|
||||||
if(!_r.IsSuccessStatusCode)
|
if(!_r.IsSuccessStatusCode)
|
||||||
throw new PlazaUnavailableException();
|
throw new PlazaUnavailableException();
|
||||||
PlazaJson j=JsonConvert.DeserializeObject<PlazaJson>(await _r.Content.ReadAsStringAsync());
|
PlazaJson j=JsonConvert.DeserializeObject<PlazaJson>(await _r.Content.ReadAsStringAsync());
|
||||||
if(j.maintenance)
|
if(j.maintenance)
|
||||||
throw new PlazaInMaintenanceException();
|
throw new PlazaInMaintenanceException();
|
||||||
|
// Previously this calculated ServerTimeOffset as Now - Headers.Date.Value.ToUnixTimeSeconds
|
||||||
status = new Status {
|
status = new Status {
|
||||||
Title = j.playback.title,
|
Title = j.song.title,
|
||||||
Album = j.playback.album,
|
Album = j.song.album,
|
||||||
Artist = j.playback.artist,
|
Artist = j.song.artist,
|
||||||
Elapsed = j.playback.position,
|
Elapsed = j.song.position,
|
||||||
Duration = j.playback.length,
|
Duration = j.song.length,
|
||||||
Since = j.updated_at,
|
Since = j.updated_at,
|
||||||
Likes = j.playback.likes,
|
Likes = j.song.reactions,
|
||||||
Dislikes = j.playback.hates,
|
|
||||||
Listeners = j.listeners,
|
Listeners = j.listeners,
|
||||||
ServerTimeOffset = (int)(DateTimeOffset.Now.ToUnixTimeSeconds() - _r.Headers.Date.Value.ToUnixTimeSeconds()),
|
ServerTimeOffset = (int)(DateTimeOffset.Now.ToUnixTimeSeconds() - j.updated_at),
|
||||||
ArtworkUri = $"https://plaza.one/{j.playback.artwork}"
|
ArtworkUri = j.song.artwork_src
|
||||||
};
|
};
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -435,11 +489,12 @@ namespace libplaza {
|
||||||
public async Task<Vote?> Vote() {
|
public async Task<Vote?> Vote() {
|
||||||
if(!await CheckSession())
|
if(!await CheckSession())
|
||||||
return null;
|
return null;
|
||||||
HttpResponseMessage _r=await _hcl.GetAsync("/vote");
|
PlazaUser r=await GetUser();
|
||||||
if(!_r.IsSuccessStatusCode)
|
if(r.current_like == null)
|
||||||
return null;
|
return libplaza.Vote.Neutral;
|
||||||
PlazaGetVote r=JsonConvert.DeserializeObject<PlazaGetVote>(await _r.Content.ReadAsStringAsync());
|
if(r.current_like.like_id)
|
||||||
return (Vote)r.rate;
|
return libplaza.Vote.Favourite;
|
||||||
|
return libplaza.Vote.Like;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -450,12 +505,12 @@ namespace libplaza {
|
||||||
public async Task<bool> Vote(Vote v) {
|
public async Task<bool> Vote(Vote v) {
|
||||||
if(!await CheckSession())
|
if(!await CheckSession())
|
||||||
return false;
|
return false;
|
||||||
HttpResponseMessage _r=await _hcl.PostAsync("/vote", new FormUrlEncodedContent(new[] {
|
HttpResponseMessage _r=await _hcl.PostAsync("/reactions", new StringContent(
|
||||||
new KeyValuePair<string, string>("rate", ((int)v).ToString())}));
|
$"{{\"reaction\":{(int)v}}}", Encoding.UTF8, "application/json"));
|
||||||
if(!_r.IsSuccessStatusCode)
|
if(!_r.IsSuccessStatusCode)
|
||||||
return false;
|
return false;
|
||||||
PlazaVote r=JsonConvert.DeserializeObject<PlazaVote>(await _r.Content.ReadAsStringAsync());
|
PlazaVote r=JsonConvert.DeserializeObject<PlazaVote>(await _r.Content.ReadAsStringAsync());
|
||||||
return r.status == "success";
|
return r.result == "success";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -474,18 +529,27 @@ namespace libplaza {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A <c>bool</c>ean value indicating whether the request succeeded</returns>
|
/// <returns>A <c>bool</c>ean value indicating whether the request succeeded</returns>
|
||||||
public async Task<bool> CheckSession() =>
|
public async Task<bool> CheckSession() =>
|
||||||
await GetUser() != null;
|
await GetUsername() != null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a basic read-only API request to fetch the profile information for the current user
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>If successful, returns a <see cref="PlazaUser"/> containing the user's profile information. If unsuccessful, returns null.</returns>
|
||||||
|
public async Task<PlazaUser> GetUser() {
|
||||||
|
HttpResponseMessage _r=await _hcl.GetAsync("/user");
|
||||||
|
if(!_r.IsSuccessStatusCode)
|
||||||
|
return null;
|
||||||
|
PlazaUser r=JsonConvert.DeserializeObject<PlazaUser>(await _r.Content.ReadAsStringAsync());
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a basic read-only API request to fetch the currently-authenticated user's profile details.
|
/// Performs a basic read-only API request to fetch the currently-authenticated user's profile details.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>If successful, returns a <c>string</c> containing the authenticated user's username. If unsuccessful, will return null.</returns>
|
/// <returns>If successful, returns a <c>string</c> containing the authenticated user's username. If unsuccessful, will return null.</returns>
|
||||||
public async Task<string> GetUser() {
|
public async Task<string> GetUsername() {
|
||||||
HttpResponseMessage _r=await _hcl.GetAsync("/user");
|
PlazaUser r=await GetUser();
|
||||||
if(!_r.IsSuccessStatusCode)
|
return (r==null || r.username==null || r.username?.Length <= 0) ? null : r.username;
|
||||||
return null;
|
|
||||||
PlazaUser r=JsonConvert.DeserializeObject<PlazaUser>(await _r.Content.ReadAsStringAsync());
|
|
||||||
return r.id <= 0 ? null : r.username;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -497,8 +561,21 @@ namespace libplaza {
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Functionally, this method is a wrapper for <see cref="Login(string)"/>, performing the function of generating a Basic authentication string
|
/// Functionally, this method is a wrapper for <see cref="Login(string)"/>, performing the function of generating a Basic authentication string
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public async Task<bool> Login(string u, string p) =>
|
public async Task<bool> Login(string u, string p) {
|
||||||
await Login(Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{u}:{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<PlazaLogonResult>(await _r.Content.ReadAsStringAsync());
|
||||||
|
if(r.result != "ok")
|
||||||
|
return false;
|
||||||
|
_hcl.DefaultRequestHeaders.Add("Authorization", $"Bearer {r.token}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a login request to the <see cref="Nightwave"/> API with the given HTTP Basic authentication <paramref name="str">string</paramref>.
|
/// Performs a login request to the <see cref="Nightwave"/> API with the given HTTP Basic authentication <paramref name="str">string</paramref>.
|
||||||
|
@ -511,7 +588,7 @@ namespace libplaza {
|
||||||
if(!_r.IsSuccessStatusCode)
|
if(!_r.IsSuccessStatusCode)
|
||||||
return false;
|
return false;
|
||||||
PlazaLogonResult r=JsonConvert.DeserializeObject<PlazaLogonResult>(await _r.Content.ReadAsStringAsync());
|
PlazaLogonResult r=JsonConvert.DeserializeObject<PlazaLogonResult>(await _r.Content.ReadAsStringAsync());
|
||||||
if(r.status != "success")
|
if(r.result != "success")
|
||||||
return false;
|
return false;
|
||||||
_hcl.DefaultRequestHeaders.Add("X-Access-Token", r.token);
|
_hcl.DefaultRequestHeaders.Add("X-Access-Token", r.token);
|
||||||
_ = _hcl.DefaultRequestHeaders.Remove("Authorization");
|
_ = _hcl.DefaultRequestHeaders.Remove("Authorization");
|
||||||
|
@ -531,4 +608,5 @@ namespace libplaza {
|
||||||
_ = _hcl.DefaultRequestHeaders.Remove("X-Access-Token");
|
_ = _hcl.DefaultRequestHeaders.Remove("X-Access-Token");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard1.4</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||||
<NeutralLanguage>en-GB</NeutralLanguage>
|
<NeutralLanguage>en-GB</NeutralLanguage>
|
||||||
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
|
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
|
||||||
|
@ -11,12 +11,12 @@
|
||||||
<Description>A moderately generic .Net interface to the Nightwave Plaza API</Description>
|
<Description>A moderately generic .Net interface to the Nightwave Plaza API</Description>
|
||||||
<Copyright>Nightwave Plaza is wholly copyright and owned by its creator, I just wrote this unofficial library that talks to it.</Copyright>
|
<Copyright>Nightwave Plaza is wholly copyright and owned by its creator, I just wrote this unofficial library that talks to it.</Copyright>
|
||||||
<PackageProjectUrl>https://soft.pup.cloud/Nightwave.NET/</PackageProjectUrl>
|
<PackageProjectUrl>https://soft.pup.cloud/Nightwave.NET/</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://git.maff.scot/maff/PlazaSharp/src/branch/master/libplaza</RepositoryUrl>
|
<RepositoryUrl>https://commit.pup.cloud/maff/PlazaSharp/src/branch/master/libplaza</RepositoryUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DefineConstants />
|
<DefineConstants />
|
||||||
<DocumentationFile>C:\Users\MC185353\source\repos\PlazaSharp\libplaza\libplaza.xml</DocumentationFile>
|
<DocumentationFile>C:\Users\maff\source\repos\PlazaSharp\libplaza\libplaza.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -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
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaPlayback.artwork">
|
<member name="F:libplaza.PlazaPlayback.artwork_src">
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaPlayback.artwork_s">
|
<member name="F:libplaza.PlazaPlayback.artwork_sm_src">
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaPlayback.likes">
|
<member name="F:libplaza.PlazaPlayback.reactions">
|
||||||
<summary>
|
|
||||||
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="F:libplaza.PlazaPlayback.hates">
|
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -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
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaJson.playback">
|
<member name="F:libplaza.PlazaJson.song">
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -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
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="F:libplaza.PlazaUser.current_like">
|
||||||
|
<summary>
|
||||||
|
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:libplaza.PlazaVote">
|
<member name="T:libplaza.PlazaVote">
|
||||||
<summary>
|
<summary>
|
||||||
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaVote.status">
|
<member name="F:libplaza.PlazaVote.result">
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaVote.ratings">
|
<member name="F:libplaza.PlazaVote.reactions">
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -129,7 +129,42 @@
|
||||||
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaGetVote.rate">
|
<member name="F:libplaza.PlazaGetVote.reaction">
|
||||||
|
<summary>
|
||||||
|
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:libplaza.PlazaCurrentVote">
|
||||||
|
<summary>
|
||||||
|
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:libplaza.PlazaCurrentVote.like_id">
|
||||||
|
<summary>
|
||||||
|
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:libplaza.PlazaCurrentVote.song">
|
||||||
|
<summary>
|
||||||
|
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:libplaza.PlazaLikedSong">
|
||||||
|
<summary>
|
||||||
|
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:libplaza.PlazaLikedSong.artist">
|
||||||
|
<summary>
|
||||||
|
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:libplaza.PlazaLikedSong.artwork_src">
|
||||||
|
<summary>
|
||||||
|
A representation of a JSON object attribute, used transitionally while processing a deserialized JSON payload
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:libplaza.PlazaLikedSong.title">
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -149,7 +184,7 @@
|
||||||
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
A transitional class used internally by <see cref="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)"/>
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.PlazaLogonResult.status">
|
<member name="F:libplaza.PlazaLogonResult.result">
|
||||||
<summary>
|
<summary>
|
||||||
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
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -179,6 +214,11 @@
|
||||||
An <see cref="T:System.Exception"/> object indicating that an error or exception occurred when communicating with the <see cref="T:libplaza.Nightwave"/> API.
|
An <see cref="T:System.Exception"/> object indicating that an error or exception occurred when communicating with the <see cref="T:libplaza.Nightwave"/> API.
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:libplaza.PlazaQuietlyUnavailableException">
|
||||||
|
<summary>
|
||||||
|
A <see cref="T:libplaza.PlazaUnavailableException"/> object indicating that, while an error occurred, it's one that we can silently retry.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:libplaza.Status">
|
<member name="T:libplaza.Status">
|
||||||
<summary>
|
<summary>
|
||||||
Represents the current broadcast information returned by a <see cref="T:libplaza.Nightwave"/> API object.
|
Represents the current broadcast information returned by a <see cref="T:libplaza.Nightwave"/> 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 likes the currently-playing track has received
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.Status.Dislikes">
|
|
||||||
<summary>
|
|
||||||
Contains an integer value of the number of dislikes the currently-playing track has received
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="F:libplaza.Status.Listeners">
|
<member name="F:libplaza.Status.Listeners">
|
||||||
<summary>
|
<summary>
|
||||||
Contains an integer value of the number of people currently listening to the broadcast
|
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.
|
Represents the user's disposition towards the currently-playing track.
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:libplaza.Vote.Dislike">
|
|
||||||
<summary>
|
|
||||||
To <c>Dislike</c> 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.
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="F:libplaza.Vote.Neutral">
|
<member name="F:libplaza.Vote.Neutral">
|
||||||
<summary>
|
<summary>
|
||||||
To be of <c>Neutral</c> disposition is to indicate the user has no feelings towards this track,
|
To be of <c>Neutral</c> disposition is to indicate the user has no feelings towards this track,
|
||||||
|
@ -395,6 +424,12 @@
|
||||||
<returns>A <c>bool</c>ean value indicating whether the request succeeded</returns>
|
<returns>A <c>bool</c>ean value indicating whether the request succeeded</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:libplaza.Nightwave.GetUser">
|
<member name="M:libplaza.Nightwave.GetUser">
|
||||||
|
<summary>
|
||||||
|
Performs a basic read-only API request to fetch the profile information for the current user
|
||||||
|
</summary>
|
||||||
|
<returns>If successful, returns a <see cref="T:libplaza.PlazaUser"/> containing the user's profile information. If unsuccessful, returns null.</returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:libplaza.Nightwave.GetUsername">
|
||||||
<summary>
|
<summary>
|
||||||
Performs a basic read-only API request to fetch the currently-authenticated user's profile details.
|
Performs a basic read-only API request to fetch the currently-authenticated user's profile details.
|
||||||
</summary>
|
</summary>
|
||||||
|
|
Loading…
Reference in New Issue