Spotify.NET/SpotifyAPI/Local/RemoteHandler.cs

194 lines
6.5 KiB
C#
Raw Permalink Normal View History

using Newtonsoft.Json;
using SpotifyAPI.Local.Models;
using System;
2014-01-07 15:26:03 +00:00
using System.Collections.Generic;
using System.Collections.Specialized;
2014-01-07 15:26:03 +00:00
using System.Net;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Web;
[assembly: InternalsVisibleTo("SpotifyAPI.Tests")]
2014-01-07 15:26:03 +00:00
namespace SpotifyAPI.Local
2014-01-07 15:26:03 +00:00
{
internal class RemoteHandler
2014-01-07 15:26:03 +00:00
{
2016-03-31 11:08:23 +01:00
public string OauthKey { get; private set; }
public string CfidKey { get; private set; }
2017-09-03 13:44:11 +01:00
private SpotifyLocalAPIConfig _config;
public RemoteHandler(SpotifyLocalAPIConfig config)
{
_config = config;
}
2018-01-15 22:07:50 +00:00
internal bool Init()
2014-01-07 15:26:03 +00:00
{
OauthKey = GetOAuthKey();
CfidKey = GetCfid();
2016-03-31 11:08:23 +01:00
return !string.IsNullOrEmpty(CfidKey);
2014-01-07 15:26:03 +00:00
}
internal async Task SendPauseRequest()
2014-01-10 07:09:14 +00:00
{
2018-01-15 22:07:50 +00:00
NameValueCollection @params = new NameValueCollection { { "pause", "true" } };
await QueryAsync("remote/pause.json", true, true, -1, @params).ConfigureAwait(false);
2014-01-10 07:09:14 +00:00
}
internal async Task SendPlayRequest()
2014-01-10 07:09:14 +00:00
{
2018-01-15 22:07:50 +00:00
NameValueCollection @params = new NameValueCollection { { "pause", "false" } };
await QueryAsync("remote/pause.json", true, true, -1, @params).ConfigureAwait(false);
2014-01-10 07:09:14 +00:00
}
internal async Task SendPlayRequest(string url, string context = "")
2014-02-01 12:52:33 +00:00
{
2015-03-12 18:44:54 +00:00
// TODO: instead of having an empty context, one way to fix the bug with the playback time beyond the length of a song would be to provide a 1-song context, and it would be fixed.
2018-01-15 22:07:50 +00:00
NameValueCollection @params = new NameValueCollection
{
{"uri", url},
{"context", context}
};
await QueryAsync($"remote/play.json", true, true, -1, @params).ConfigureAwait(false);
2014-02-01 12:52:33 +00:00
}
internal async Task SendQueueRequest(string url)
{
2018-01-15 22:07:50 +00:00
NameValueCollection @params = new NameValueCollection
{
{"uri", url},
{"action", "queue"}
};
await QueryAsync("remote/play.json", true, true, -1, @params).ConfigureAwait(false);
}
internal StatusResponse GetNewStatus()
2014-01-08 22:22:54 +00:00
{
2016-03-31 11:08:23 +01:00
string response = Query("remote/status.json", true, true, -1);
if (string.IsNullOrEmpty(response))
2014-02-13 13:23:52 +00:00
return null;
2014-01-08 22:22:54 +00:00
response = response.Replace("\\n", "");
List<StatusResponse> raw = JsonConvert.DeserializeObject<List<StatusResponse>>(response);
2014-01-08 22:22:54 +00:00
return raw[0];
}
2016-03-31 11:08:23 +01:00
internal string GetOAuthKey()
2014-01-07 15:26:03 +00:00
{
2016-03-31 11:08:23 +01:00
string raw;
using (WebClient wc = GetWebClientWithUserAgentHeader())
2014-01-07 15:26:03 +00:00
{
2014-01-10 07:09:14 +00:00
raw = wc.DownloadString("http://open.spotify.com/token");
2014-01-07 15:26:03 +00:00
}
2016-03-31 11:08:23 +01:00
Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(raw);
return dic == null ? "" : (string)dic["t"];
2014-01-07 15:26:03 +00:00
}
internal string GetCfid()
2014-01-07 15:26:03 +00:00
{
string response = Query("simplecsrf/token.json", false, false, -1);
response = response.Replace(@"\", "");
List<Cfid> cfidList = (List<Cfid>)JsonConvert.DeserializeObject(response, typeof(List<Cfid>));
if (cfidList == null)
return "";
if (cfidList.Count != 1)
throw new Exception("CFID could not be loaded");
return cfidList[0].Error == null ? cfidList[0].Token : "";
2014-01-07 15:26:03 +00:00
}
internal string BuildQueryString(bool oauth, bool cfid, int wait, NameValueCollection @params = null)
2014-01-07 15:26:03 +00:00
{
if (@params == null)
2014-01-07 15:26:03 +00:00
{
@params = new NameValueCollection();
2014-01-07 15:26:03 +00:00
}
2018-01-15 22:07:50 +00:00
NameValueCollection queryParameter = HttpUtility.ParseQueryString(string.Empty);
queryParameter.Add(@params);
queryParameter.Add(new NameValueCollection() {
{ "ref", string.Empty},
{ "cors", string.Empty},
{ "_", GetTimestamp().ToString()}
});
2014-01-07 15:26:03 +00:00
if (oauth)
{
queryParameter.Add("oauth", OauthKey);
2014-01-07 15:26:03 +00:00
}
if (cfid)
{
queryParameter.Add("csrf", CfidKey);
2014-01-07 15:26:03 +00:00
}
if (wait != -1)
{
queryParameter.Add("returnafter", wait.ToString());
queryParameter.Add("returnon", "login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap");
2014-01-07 15:26:03 +00:00
}
return queryParameter.ToString();
}
internal string Query(string baseUrl, bool oauth, bool cfid, int wait, NameValueCollection @params = null)
{
string parameters = BuildQueryString(oauth, cfid, wait, @params);
string address = $"{_config.HostUrl}:{_config.Port}/{baseUrl}?{parameters}";
string response = string.Empty;
2014-01-07 15:26:03 +00:00
try
{
2018-01-15 22:07:50 +00:00
using (ExtendedWebClient wc = new ExtendedWebClient())
{
if (SpotifyLocalAPI.IsSpotifyRunning())
{
response = "[ " + wc.DownloadString(address) + " ]";
}
}
2014-01-07 15:26:03 +00:00
}
catch
2014-01-07 15:26:03 +00:00
{
2016-03-31 11:08:23 +01:00
return string.Empty;
}
return response;
}
internal async Task<string> QueryAsync(string baseUrl, bool oauth, bool cfid, int wait, NameValueCollection @params = null)
{
string parameters = BuildQueryString(oauth, cfid, wait, @params);
string address = $"{_config.HostUrl}:{_config.Port}/{baseUrl}?{parameters}";
string response = "";
try
{
2018-01-15 22:07:50 +00:00
using (ExtendedWebClient wc = new ExtendedWebClient())
{
if (SpotifyLocalAPI.IsSpotifyRunning())
2016-09-08 11:06:24 +01:00
response = "[ " + await wc.DownloadStringTaskAsync(new Uri(address)).ConfigureAwait(false) + " ]";
}
}
catch
{
2016-03-31 11:08:23 +01:00
return string.Empty;
2014-01-07 15:26:03 +00:00
}
2014-02-13 13:23:52 +00:00
return response;
2014-01-07 15:26:03 +00:00
}
2014-02-13 13:23:52 +00:00
internal int GetTimestamp()
2014-01-10 07:09:14 +00:00
{
2014-02-01 12:52:33 +00:00
return Convert.ToInt32((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
2014-01-10 07:09:14 +00:00
}
internal WebClient GetWebClientWithUserAgentHeader()
{
WebClient wc = new WebClient
{
Proxy = _config?.ProxyConfig?.CreateWebProxy()
};
wc.Headers.Add(HttpRequestHeader.UserAgent, "Spotify (1.0.50.41368.gbd68dbef)");
return wc;
}
2014-01-07 15:26:03 +00:00
}
}