22using SpotifyAPI . Local . Models ;
33using System ;
44using System . Collections . Generic ;
5+ using System . Collections . Specialized ;
56using System . Net ;
6- using System . Text ;
7+ using System . Runtime . CompilerServices ;
78using System . Threading . Tasks ;
9+ using System . Web ;
10+
11+ [ assembly: InternalsVisibleTo ( "SpotifyAPI.Tests" ) ]
12+
813
914namespace SpotifyAPI . Local
1015{
16+
1117 internal class RemoteHandler
1218 {
1319 public string OauthKey { get ; private set ; }
@@ -29,23 +35,32 @@ internal Boolean Init()
2935
3036 internal async Task SendPauseRequest ( )
3137 {
32- await QueryAsync ( "remote/pause.json?pause=true" , true , true , - 1 ) . ConfigureAwait ( false ) ;
38+ var @params = new NameValueCollection ( ) { { "pause" , "true" } } ;
39+ await QueryAsync ( "remote/pause.json" , true , true , - 1 , @params ) . ConfigureAwait ( false ) ;
3340 }
3441
3542 internal async Task SendPlayRequest ( )
3643 {
37- await QueryAsync ( "remote/pause.json?pause=false" , true , true , - 1 ) . ConfigureAwait ( false ) ;
44+ var @params = new NameValueCollection ( ) { { "pause" , "false" } } ;
45+ await QueryAsync ( "remote/pause.json" , true , true , - 1 , @params ) . ConfigureAwait ( false ) ;
3846 }
3947
4048 internal async Task SendPlayRequest ( string url , string context = "" )
4149 {
50+
4251 // 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.
43- await QueryAsync ( $ "remote/play.json?uri={ url } &context={ context } ", true , true , - 1 ) . ConfigureAwait ( false ) ;
52+ var @params = new NameValueCollection ( ) { { "uri" , url } ,
53+ { "context" , context } } ;
54+ await QueryAsync ( $ "remote/play.json", true , true , - 1 , @params ) . ConfigureAwait ( false ) ;
55+
4456 }
4557
4658 internal async Task SendQueueRequest ( string url )
4759 {
48- await QueryAsync ( "remote/play.json?uri=" + url + "?action=queue" , true , true , - 1 ) . ConfigureAwait ( false ) ;
60+ var @params = new NameValueCollection ( ) { { "uri" , url } ,
61+ { "action" , "queue" } } ;
62+ await QueryAsync ( "remote/play.json" , true , true , - 1 , @params ) . ConfigureAwait ( false ) ;
63+
4964 }
5065
5166 internal StatusResponse GetNewStatus ( )
@@ -83,31 +98,41 @@ internal string GetCfid()
8398 return cfidList [ 0 ] . Error == null ? cfidList [ 0 ] . Token : "" ;
8499 }
85100
86- internal string Query ( string request , bool oauth , bool cfid , int wait )
101+ internal string BuildQueryString ( bool oauth , bool cfid , int wait , NameValueCollection @params = null )
87102 {
88- string parameters = "?&ref=&cors=&_=" + GetTimestamp ( ) ;
89- if ( request . Contains ( "?" ) )
103+ if ( @params == null )
90104 {
91- parameters = parameters . Substring ( 1 ) ;
105+ @params = new NameValueCollection ( ) ;
92106 }
93-
107+ var queryParameter = HttpUtility . ParseQueryString ( string . Empty ) ;
108+ queryParameter . Add ( @params ) ;
109+ queryParameter . Add ( new NameValueCollection ( ) {
110+ { "ref" , string . Empty } ,
111+ { "cors" , string . Empty } ,
112+ { "_" , GetTimestamp ( ) . ToString ( ) }
113+ } ) ;
94114 if ( oauth )
95115 {
96- parameters += "& oauth=" + OauthKey ;
116+ queryParameter . Add ( " oauth" , OauthKey ) ;
97117 }
98118 if ( cfid )
99119 {
100- parameters += "& csrf=" + CfidKey ;
120+ queryParameter . Add ( " csrf" , CfidKey ) ;
101121 }
102122
103123 if ( wait != - 1 )
104124 {
105- parameters += "& returnafter=" + wait ;
106- parameters += "& returnon= login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap";
125+ queryParameter . Add ( " returnafter" , wait . ToString ( ) ) ;
126+ queryParameter . Add ( " returnon" , " login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap") ;
107127 }
108128
109- string address = $ "{ _config . HostUrl } :{ _config . Port } /{ request } { parameters } ";
110- string response = "" ;
129+ return queryParameter . ToString ( ) ;
130+ }
131+ internal string Query ( string baseUrl , bool oauth , bool cfid , int wait , NameValueCollection @params = null )
132+ {
133+ string parameters = BuildQueryString ( oauth , cfid , wait , @params ) ;
134+ string address = $ "{ _config . HostUrl } :{ _config . Port } /{ baseUrl } { parameters } ";
135+ string response = string . Empty ;
111136 try
112137 {
113138 using ( var wc = new ExtendedWebClient ( ) )
@@ -126,30 +151,10 @@ internal string Query(string request, bool oauth, bool cfid, int wait)
126151 return response ;
127152 }
128153
129- internal async Task < string > QueryAsync ( string request , bool oauth , bool cfid , int wait )
154+ internal async Task < string > QueryAsync ( string baseUrl , bool oauth , bool cfid , int wait , NameValueCollection @params = null )
130155 {
131- string parameters = "?&ref=&cors=&_=" + GetTimestamp ( ) ;
132- if ( request . Contains ( "?" ) )
133- {
134- parameters = parameters . Substring ( 1 ) ;
135- }
136-
137- if ( oauth )
138- {
139- parameters += "&oauth=" + OauthKey ;
140- }
141- if ( cfid )
142- {
143- parameters += "&csrf=" + CfidKey ;
144- }
145-
146- if ( wait != - 1 )
147- {
148- parameters += "&returnafter=" + wait ;
149- parameters += "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap" ;
150- }
151-
152- string address = $ "{ _config . HostUrl } :{ _config . Port } /{ request } { parameters } ";
156+ string parameters = BuildQueryString ( oauth , cfid , wait , @params ) ;
157+ string address = $ "{ _config . HostUrl } :{ _config . Port } /{ baseUrl } { parameters } ";
153158 string response = "" ;
154159 try
155160 {
@@ -166,7 +171,6 @@ internal async Task<string> QueryAsync(string request, bool oauth, bool cfid, in
166171
167172 return response ;
168173 }
169-
170174 internal int GetTimestamp ( )
171175 {
172176 return Convert . ToInt32 ( ( DateTime . UtcNow - new DateTime ( 1970 , 1 , 1 , 0 , 0 , 0 ) ) . TotalSeconds ) ;
0 commit comments