2014-01-07 15:26:03 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Net ;
2014-02-17 11:58:15 +00:00
using System.Threading.Tasks ;
using System.Threading ;
2014-01-07 15:26:03 +00:00
using Newtonsoft.Json ;
2014-07-20 21:42:46 +01:00
namespace SpotifyAPI.SpotifyLocalAPI
2014-01-07 15:26:03 +00:00
{
class RemoteHandler
{
private static RemoteHandler instance = new RemoteHandler ( ) ;
2015-01-02 21:57:12 +00:00
public String oauthKey { get ; private set ; }
public String cfidKey { get ; private set ; }
2014-01-07 15:26:03 +00:00
2015-03-12 18:41:25 +00:00
public String host = "SpotifyAPI.spotilocal.com" ;
2014-01-07 15:26:03 +00:00
2015-01-02 21:57:12 +00:00
private class ExtendedWebClientInstance : ExtendedWebClient
{
internal ExtendedWebClientInstance ( )
{
Timeout = 2000 ;
Proxy = null ;
Headers . Add ( "Origin" , "https://embed.spotify.com" ) ;
Headers . Add ( "Referer" , "https://embed.spotify.com/?uri=spotify:track:5Zp4SWOpbuOdnsxLqwgutt" ) ;
}
}
2014-01-08 22:22:54 +00:00
internal static RemoteHandler GetInstance ( )
2014-01-07 15:26:03 +00:00
{
2015-01-02 21:57:12 +00:00
// Is this supposed to return the current instance?
2014-01-07 15:26:03 +00:00
return instance ;
}
2014-01-10 07:09:14 +00:00
internal RemoteHandler ( )
2014-01-07 15:26:03 +00:00
{
2014-02-17 11:58:15 +00:00
2014-01-07 15:26:03 +00:00
}
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
{
oauthKey = GetOAuthKey ( ) ;
cfidKey = GetCFID ( ) ;
2014-02-14 12:04:45 +00:00
if ( cfidKey = = "" )
return false ;
return true ;
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-03-12 18:41:25 +00:00
await QueryAsync ( string . Format ( "remote/play.json?uri={0}&context={1}" , url , 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
2014-01-08 22:22:54 +00:00
internal StatusResponse Update ( )
{
2014-02-01 12:52:33 +00:00
String response = query ( "remote/status.json" , true , true , - 1 ) ;
2015-01-02 21:57:12 +00:00
if ( 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-01-02 21:57:12 +00:00
List < StatusResponse > raw = ( List < StatusResponse > ) JsonConvert . DeserializeObject ( response , typeof ( List < StatusResponse > ) ) ;
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
{
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
wc . Proxy = null ;
raw = wc . DownloadString ( "http://open.spotify.com/token" ) ;
2014-01-07 15:26:03 +00:00
}
2014-01-10 07:09:14 +00:00
Dictionary < String , object > lol = ( Dictionary < String , object > ) JsonConvert . DeserializeObject < Dictionary < String , object > > ( raw ) ;
return ( String ) lol [ "t" ] ;
2014-01-07 15:26:03 +00:00
}
2015-01-02 21:57:12 +00:00
internal string GetCFID ( )
2014-01-07 15:26:03 +00:00
{
2014-02-01 12:52:33 +00:00
string a = query ( "simplecsrf/token.json" , false , false , - 1 ) ;
a = a . Replace ( @"\" , "" ) ;
2014-01-07 15:26:03 +00:00
List < CFID > d = ( List < CFID > ) JsonConvert . DeserializeObject ( a , typeof ( List < CFID > ) ) ;
2014-02-17 11:58:15 +00:00
if ( d = = null )
return "" ;
2014-01-07 15:26:03 +00:00
if ( d . Count ! = 1 )
2014-02-01 12:52:33 +00:00
throw new Exception ( "CFID couldn't be loaded" ) ;
if ( d [ 0 ] . error ! = null )
2014-02-14 12:04:45 +00:00
return "" ;
2014-01-07 15:26:03 +00:00
return d [ 0 ] . token ;
}
2015-01-02 21:57:12 +00: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 )
{
parameters + = "&oauth=" + oauthKey ;
}
if ( cfid )
{
parameters + = "&csrf=" + cfidKey ;
}
if ( wait ! = - 1 )
{
parameters + = "&returnafter=" + wait ;
parameters + = "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap" ;
}
string a = "http://" + host + ":4380/" + request + parameters ;
2014-02-13 13:23:52 +00:00
string response = "" ;
2014-01-07 15:26:03 +00:00
try
{
2014-02-17 11:58:15 +00:00
//Need to find a better solution
2015-01-02 23:49:39 +00:00
using ( var wc = new ExtendedWebClientInstance ( ) )
{
if ( SpotifyLocalAPIClass . IsSpotifyRunning ( ) )
response = "[ " + wc . DownloadString ( a ) + " ]" ;
}
2014-01-07 15:26:03 +00:00
}
catch ( Exception z )
{
2015-01-02 21:57:12 +00:00
Console . WriteLine ( z . Message ) ;
return "" ;
}
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 )
{
parameters + = "&oauth=" + oauthKey ;
}
if ( cfid )
{
parameters + = "&csrf=" + cfidKey ;
}
if ( wait ! = - 1 )
{
parameters + = "&returnafter=" + wait ;
parameters + = "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap" ;
}
2015-03-12 18:41:25 +00:00
string a = "http://" + host + ":4380/" + request + parameters ;
2015-01-02 21:57:12 +00:00
string response = "" ;
try
{
//Need to find a better solution
2015-01-02 23:49:39 +00:00
using ( var wc = new ExtendedWebClientInstance ( ) )
{
if ( SpotifyLocalAPIClass . IsSpotifyRunning ( ) )
response = "[ " + await wc . DownloadStringTaskAsync ( new Uri ( a ) ) + " ]" ;
}
2015-01-02 21:57:12 +00:00
}
catch ( Exception ex )
{
Console . WriteLine ( ex . Message ) ;
2014-02-17 11:58:15 +00:00
return "" ;
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
}
}