2015-10-16 23:44:35 +01:00
using Newtonsoft.Json ;
using SpotifyAPI.Local.Models ;
using System ;
2014-01-07 15:26:03 +00:00
using System.Collections.Generic ;
using System.Net ;
2015-07-07 17:11:11 +01:00
using System.Text ;
2014-02-17 11:58:15 +00:00
using System.Threading.Tasks ;
2014-01-07 15:26:03 +00:00
2015-07-07 17:11:11 +01:00
namespace SpotifyAPI.Local
2014-01-07 15:26:03 +00:00
{
2015-07-07 17:11:11 +01:00
internal class RemoteHandler
2014-01-07 15:26:03 +00:00
{
2015-07-07 17:11:11 +01:00
public String OauthKey { get ; private set ; }
public String CfidKey { get ; private set ; }
2015-01-02 21:57:12 +00:00
2015-07-07 17:11:11 +01:00
public const String Host = "SpotifyAPI.spotilocal.com" ;
2015-01-02 21:57:12 +00:00
2014-02-14 12:04:45 +00:00
internal Boolean Init ( )
2014-01-07 15:26:03 +00:00
{
2015-07-07 17:11:11 +01:00
OauthKey = GetOAuthKey ( ) ;
CfidKey = GetCfid ( ) ;
2015-10-16 23:31:01 +01:00
return ! String . IsNullOrEmpty ( CfidKey ) ;
2014-01-07 15:26:03 +00:00
}
2015-01-02 21:57:12 +00:00
internal async void SendPauseRequest ( )
2014-01-10 07:09:14 +00:00
{
2015-01-02 21:57:12 +00:00
await QueryAsync ( "remote/pause.json?pause=true" , true , true , - 1 ) ;
2014-01-10 07:09:14 +00:00
}
2015-01-02 21:57:12 +00:00
internal async void SendPlayRequest ( )
2014-01-10 07:09:14 +00:00
{
2015-01-02 21:57:12 +00:00
await QueryAsync ( "remote/pause.json?pause=false" , true , true , - 1 ) ;
2014-01-10 07:09:14 +00:00
}
2015-01-02 21:57:12 +00:00
2015-03-12 18:41:25 +00:00
internal async void 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.
2015-10-28 16:05:09 +00:00
await QueryAsync ( $"remote/play.json?uri={url}&context={context}" , true , true , - 1 ) ;
2014-02-01 12:52:33 +00:00
}
2015-01-02 21:57:12 +00:00
internal async void SendQueueRequest ( String url )
2014-08-05 17:56:29 +01:00
{
2015-01-02 21:57:12 +00:00
await QueryAsync ( "remote/play.json?uri=" + url + "?action=queue" , true , true , - 1 ) ;
2014-08-05 17:56:29 +01:00
}
2015-01-02 21:57:12 +00:00
2015-07-07 17:11:11 +01:00
internal StatusResponse GetNewStatus ( )
2014-01-08 22:22:54 +00:00
{
2015-07-07 17:11:11 +01:00
String response = Query ( "remote/status.json" , true , true , - 1 ) ;
2015-10-16 23:31:01 +01:00
if ( String . IsNullOrEmpty ( response ) )
2014-01-08 22:22:54 +00:00
{
2014-02-13 13:23:52 +00:00
return null ;
2014-01-08 22:22:54 +00:00
}
response = response . Replace ( "\\n" , "" ) ;
2014-02-01 12:52:33 +00:00
byte [ ] bytes = Encoding . Default . GetBytes ( response ) ;
response = Encoding . UTF8 . GetString ( bytes ) ;
2015-07-07 17:11:11 +01:00
List < StatusResponse > raw = JsonConvert . DeserializeObject < List < StatusResponse > > ( response ) ;
2014-01-08 22:22:54 +00:00
return raw [ 0 ] ;
}
2015-01-02 21:57:12 +00:00
2014-02-13 13:23:52 +00:00
internal String GetOAuthKey ( )
2014-01-07 15:26:03 +00:00
{
2015-07-07 17:11:11 +01:00
String raw ;
2015-01-02 21:57:12 +00:00
using ( WebClient wc = new WebClient ( ) )
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
}
2015-07-07 17:11:11 +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
}
2015-07-07 17:11:11 +01:00
internal string GetCfid ( )
2014-01-07 15:26:03 +00:00
{
2015-07-07 17:11:11 +01: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 )
2014-02-17 11:58:15 +00:00
return "" ;
2015-07-07 17:11:11 +01:00
if ( cfidList . Count ! = 1 )
2015-10-16 23:31:01 +01:00
throw new Exception ( "CFID could not be loaded" ) ;
2015-07-07 17:11:11 +01:00
return cfidList [ 0 ] . Error = = null ? cfidList [ 0 ] . Token : "" ;
2014-01-07 15:26:03 +00:00
}
2015-01-02 21:57:12 +00:00
2015-07-07 17:11:11 +01:00
internal string Query ( string request , bool oauth , bool cfid , int wait )
2014-01-07 15:26:03 +00:00
{
2014-02-01 12:52:33 +00:00
string parameters = "?&ref=&cors=&_=" + GetTimestamp ( ) ;
2014-01-07 15:26:03 +00:00
if ( request . Contains ( "?" ) )
{
parameters = parameters . Substring ( 1 ) ;
}
if ( oauth )
{
2015-07-07 17:11:11 +01:00
parameters + = "&oauth=" + OauthKey ;
2014-01-07 15:26:03 +00:00
}
if ( cfid )
{
2015-07-07 17:11:11 +01:00
parameters + = "&csrf=" + CfidKey ;
2014-01-07 15:26:03 +00:00
}
if ( wait ! = - 1 )
{
parameters + = "&returnafter=" + wait ;
parameters + = "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap" ;
}
2015-07-07 17:11:11 +01:00
string address = "http://" + Host + ":4380/" + request + parameters ;
2014-02-13 13:23:52 +00:00
string response = "" ;
2014-01-07 15:26:03 +00:00
try
{
2015-07-07 17:11:11 +01:00
using ( var wc = new ExtendedWebClient ( ) )
2015-01-02 23:49:39 +00:00
{
2015-07-07 17:11:11 +01:00
if ( SpotifyLocalAPI . IsSpotifyRunning ( ) )
response = "[ " + wc . DownloadString ( address ) + " ]" ;
2015-01-02 23:49:39 +00:00
}
2014-01-07 15:26:03 +00:00
}
2015-10-16 23:31:01 +01:00
catch
2014-01-07 15:26:03 +00:00
{
2015-10-16 23:31:01 +01:00
return String . Empty ;
2015-01-02 21:57:12 +00:00
}
2015-07-07 17:11:11 +01:00
2015-01-02 21:57:12 +00:00
return response ;
}
internal async Task < string > QueryAsync ( string request , bool oauth , bool cfid , int wait )
{
string parameters = "?&ref=&cors=&_=" + GetTimestamp ( ) ;
if ( request . Contains ( "?" ) )
{
parameters = parameters . Substring ( 1 ) ;
}
if ( oauth )
{
2015-07-07 17:11:11 +01:00
parameters + = "&oauth=" + OauthKey ;
2015-01-02 21:57:12 +00:00
}
if ( cfid )
{
2015-07-07 17:11:11 +01:00
parameters + = "&csrf=" + CfidKey ;
2015-01-02 21:57:12 +00:00
}
if ( wait ! = - 1 )
{
parameters + = "&returnafter=" + wait ;
parameters + = "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap" ;
}
2015-10-16 23:44:35 +01:00
string address = "http://" + Host + ":4380/" + request + parameters ;
2015-01-02 21:57:12 +00:00
string response = "" ;
try
{
2015-07-07 17:11:11 +01:00
using ( var wc = new ExtendedWebClient ( ) )
2015-01-02 23:49:39 +00:00
{
2015-07-07 17:11:11 +01:00
if ( SpotifyLocalAPI . IsSpotifyRunning ( ) )
response = "[ " + await wc . DownloadStringTaskAsync ( new Uri ( address ) ) + " ]" ;
2015-01-02 23:49:39 +00:00
}
2015-01-02 21:57:12 +00:00
}
2015-10-16 23:31:01 +01:00
catch
2015-01-02 21:57:12 +00:00
{
2015-10-16 23:31:01 +01:00
return String . Empty ;
2014-01-07 15:26:03 +00:00
}
2015-01-02 21:57:12 +00:00
2014-02-13 13:23:52 +00:00
return response ;
2014-01-07 15:26:03 +00:00
}
2015-01-02 21:57:12 +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
}
2014-01-07 15:26:03 +00:00
}
2015-10-16 23:44:35 +01:00
}