PlazaSharp/libplaza/Main.cs

183 lines
5.7 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 long updated;
public string artwork;
public string artwork_s;
public int likes;
public int hates;
}
public class PlazaJson {
public bool maintenance;
public int listeners;
[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 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 void EvtUpdate() => await Update();
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.playback.updated,
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<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
}
}