194 lines
6.0 KiB
C#
194 lines
6.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace libplaza {
|
|
internal class PlazaApi {
|
|
internal const string ApiBase="https://api.plaza.one/";
|
|
internal const string ArtworkBase="https://plaza.one/";
|
|
internal const string RadioBase="https://radio.plaza.one/";
|
|
}
|
|
public class PlazaPlayback {
|
|
public string artist;
|
|
public string title;
|
|
public string album;
|
|
public int length;
|
|
public int position;
|
|
public string artwork;
|
|
public string artwork_s;
|
|
public int likes;
|
|
public int hates;
|
|
}
|
|
public class PlazaJson {
|
|
public bool maintenance;
|
|
public int listeners;
|
|
public long updated_at;
|
|
[JsonProperty]
|
|
public PlazaPlayback playback;
|
|
}
|
|
public class PlazaUser {
|
|
public int id;
|
|
public string username;
|
|
public string email;
|
|
public int role;
|
|
public string created_at;
|
|
}
|
|
public class PlazaVote {
|
|
public string status;
|
|
public int[] ratings;
|
|
}
|
|
public class PlazaGetVote {
|
|
public int rate;
|
|
}
|
|
public class PlazaLogonResult {
|
|
public string status;
|
|
public string username;
|
|
public string email;
|
|
public string token;
|
|
}
|
|
internal class PlazaInMaintenanceException : Exception { }
|
|
internal class PlazaUnavailableException : Exception { }
|
|
public class Status {
|
|
public bool InMaintenance;
|
|
public bool FaultOccurred;
|
|
public string Title;
|
|
public string Artist;
|
|
public string Album;
|
|
public string ArtworkUri;
|
|
public int Elapsed;
|
|
public int Duration;
|
|
public long Since;
|
|
public int ServerTimeOffset;
|
|
public int CalculatedElapsed =>
|
|
(int)(DateTimeOffset.Now.ToUnixTimeSeconds() - ServerTimeOffset - Since) + Elapsed;
|
|
public int Likes;
|
|
public int Dislikes;
|
|
public int Listeners;
|
|
}
|
|
public class Nightwave {
|
|
public int MinRefreshTime=10;
|
|
private long tsLastRefresh=0;
|
|
private static HttpClient _hcl=new HttpClient();
|
|
public enum Vote {
|
|
Dislike=-1,
|
|
Neutral,
|
|
Like,
|
|
Favourite
|
|
}
|
|
private Status _bc;
|
|
public Nightwave() {
|
|
_hcl.BaseAddress = new Uri(PlazaApi.ApiBase);
|
|
_hcl.Timeout = TimeSpan.FromSeconds(2);
|
|
_hcl.DefaultRequestHeaders.Accept.Clear();
|
|
_hcl.DefaultRequestHeaders.Accept.Add(
|
|
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
|
|
}
|
|
public async Task<Status> Broadcast(bool Force = false) {
|
|
if(!Force && tsLastRefresh + MinRefreshTime >= DateTimeOffset.Now.ToUnixTimeSeconds() && _bc.CalculatedElapsed < _bc.Duration)
|
|
return _bc;
|
|
await Update();
|
|
tsLastRefresh = DateTimeOffset.Now.ToUnixTimeSeconds();
|
|
return _bc;
|
|
}
|
|
public async Task Update() {
|
|
try {
|
|
Status _=await GetNightwaveAsync();
|
|
_.InMaintenance = false;
|
|
_.FaultOccurred = false;
|
|
_bc = _;
|
|
} catch(PlazaInMaintenanceException) {
|
|
_bc.InMaintenance = true;
|
|
_bc.FaultOccurred = false;
|
|
} catch(Exception) { //TODO make this more reliable?
|
|
_bc.FaultOccurred = true;
|
|
}
|
|
}
|
|
public async Task<Status> GetNightwaveAsync() {
|
|
Status status;
|
|
HttpResponseMessage _r=await _hcl.GetAsync("/status");
|
|
if(!_r.IsSuccessStatusCode)
|
|
throw new PlazaUnavailableException();
|
|
//string _=await _r.Content.ReadAsStringAsync();
|
|
PlazaJson j=JsonConvert.DeserializeObject<PlazaJson>(await _r.Content.ReadAsStringAsync());
|
|
if(j.maintenance)
|
|
throw new PlazaInMaintenanceException();
|
|
status = new Status {
|
|
Title = j.playback.title,
|
|
Album = j.playback.album,
|
|
Artist = j.playback.artist,
|
|
Elapsed = j.playback.position,
|
|
Duration = j.playback.length,
|
|
Since = j.updated_at,
|
|
Likes = j.playback.likes,
|
|
Dislikes = j.playback.hates,
|
|
Listeners = j.listeners,
|
|
ServerTimeOffset = (int)(DateTimeOffset.Now.ToUnixTimeSeconds() - _r.Headers.Date.Value.ToUnixTimeSeconds()),
|
|
ArtworkUri = $"{PlazaApi.ArtworkBase}{j.playback.artwork}"
|
|
};
|
|
return status;
|
|
}
|
|
public async Task<Vote?> GetVote() {
|
|
if(!await CheckSession())
|
|
return null;
|
|
HttpResponseMessage _r=await _hcl.GetAsync("/vote");
|
|
if(!_r.IsSuccessStatusCode)
|
|
return null;
|
|
PlazaGetVote r=JsonConvert.DeserializeObject<PlazaGetVote>(await _r.Content.ReadAsStringAsync());
|
|
return (Vote)r.rate;
|
|
}
|
|
public async Task<bool> CastVote(Vote v) {
|
|
if(!await CheckSession())
|
|
return false;
|
|
HttpResponseMessage _r=await _hcl.PostAsync("/vote", new FormUrlEncodedContent(new[] {
|
|
new KeyValuePair<string, string>("rate", ((int)v).ToString())}));
|
|
if(!_r.IsSuccessStatusCode)
|
|
return false;
|
|
PlazaVote r=JsonConvert.DeserializeObject<PlazaVote>(await _r.Content.ReadAsStringAsync());
|
|
if(r.status != "success")
|
|
return false;
|
|
return true;
|
|
}
|
|
public async Task<bool> CheckSession(string str) {
|
|
_=_hcl.DefaultRequestHeaders.Remove("X-Access-Token");
|
|
_hcl.DefaultRequestHeaders.Add("X-Access-Token", str);
|
|
return await CheckSession();
|
|
}
|
|
public async Task<bool> CheckSession() {
|
|
if(await GetUser() != null)
|
|
return true;
|
|
return false;
|
|
}
|
|
public async Task<string> GetUser() {
|
|
HttpResponseMessage _r=await _hcl.GetAsync("/user");
|
|
if(!_r.IsSuccessStatusCode)
|
|
return null;
|
|
PlazaUser r=JsonConvert.DeserializeObject<PlazaUser>(await _r.Content.ReadAsStringAsync());
|
|
if(r.id <= 0)
|
|
return null;
|
|
return r.username;
|
|
}
|
|
public async Task<bool> Login(string u, string p) => await Login(Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{u}:{p}")));
|
|
public async Task<bool> Login(string str) {
|
|
_hcl.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", str);
|
|
HttpResponseMessage _r=await _hcl.PostAsync("/user/login", null);
|
|
if(!_r.IsSuccessStatusCode)
|
|
return false;
|
|
PlazaLogonResult r=JsonConvert.DeserializeObject<PlazaLogonResult>(await _r.Content.ReadAsStringAsync());
|
|
if(r.status != "success")
|
|
return false;
|
|
_hcl.DefaultRequestHeaders.Add("X-Access-Token", r.token);
|
|
_=_hcl.DefaultRequestHeaders.Remove("Authorization");
|
|
return true;
|
|
}
|
|
#if DEBUG
|
|
public string GetAuthorizationToken() {
|
|
IEnumerator<string> h=_hcl.DefaultRequestHeaders.GetValues("X-Access-Token").GetEnumerator();
|
|
_ = h.MoveNext();
|
|
return h.Current;
|
|
}
|
|
#endif
|
|
}
|
|
}
|