· 7 years ago · Oct 13, 2018, 01:36 AM
1Ti.include('/lib/oauth.js');
2Ti.include('/lib/sha1.js');
3
4var core = require('lib/core');
5var config = require('model/config')
6var util = require('ui/util');
7
8/* 1 minute */
9
10function RestClient(username, password, oAuth) {
11 if(!username) {
12 throw new Error('RestClient must be passed a username');
13 }
14
15 if(!password) {
16 throw new Error('RestClient must be passed a password');
17 }
18
19 this.username = username;
20 this.password = password;
21 if(oAuth != undefined && oAuth != null) {
22 this.oAuth = oAuth;
23 }
24 this.basicAuth = Ti.Utils.base64encode(this.username + ':' + this.password);
25}
26
27exports.RestClient = RestClient;
28
29RestClient.prototype.apiCall = function(method, path, options, suc, err, wholePath, includeOAUTH, clearCookies, uploadCallback) {
30 var self = this;
31 method = method.toUpperCase();
32 options = options || {};
33
34 var params = options.params;
35 var headers = options.headers || {};
36
37 // Set URL
38 var fullPath = '';
39 if(wholePath) {
40 fullPath = wholePath;
41 } else {
42 fullPath = config.API_SERVER + '/api';
43 if(path.length > 0) {
44 if(path[0] != '/') {
45 fullPath += '/';
46 }
47 fullPath += path;
48 }
49 }
50
51 var xhr = Ti.Network.createHTTPClient({
52 enableKeepAlive:false,
53 });
54 //var xhr = Ti.Network.createHTTPClient();
55 xhr.validatesSecureCertificate = false;
56
57 if (!core.isAndroid)
58 {
59 xhr.setEnableKeepAlive(false);
60 xhr.setTimeout(config.REQUEST_TIMEOUT_IOS);
61 }
62 else
63 {
64 xhr.setTimeout(config.REQUEST_TIMEOUT_ANDROID);
65 }
66
67 var abortXhrCall = function(e) {
68 xhr.abort();
69 };
70
71 Ti.App.addEventListener('abortXHR', abortXhrCall);
72
73 /*
74 xhr.onsendstream = function(e) {
75 uploadCallback(e.progress);
76 }
77 */
78
79 xhr.onerror = function(e) {
80 Ti.App.removeEventListener('abortXHR', abortXhrCall);
81 Ti.API.error('Starmeo.js | onerror | responseText = ' + JSON.stringify(xhr.responseText));
82 Ti.API.error('Starmeo.js | onerror | status = ' + xhr.status);
83
84 if(xhr.status === 401) {
85 Ti.App.removeEventListener('abortXHR', abortXhrCall);
86 Ti.API.error('readystate = 3 + xhr.status = 401 | xhr.responseText = ' + xhr.responseText);
87 Ti.API.error('readystate = 3 + xhr.status = 401 | this.responseText = ' + this.responseText);
88 err(L('AGBNotAccepted'));
89 return;
90 } else if(xhr.status === 403) {
91 Ti.API.error('readystate = 3 + xhr.status = 403');
92 Ti.App.removeEventListener('abortXHR', abortXhrCall);
93 err('AUTHORIZATION REQUIRED');
94 return;
95 }
96
97 if (typeof(e.error)=="undefined")
98 {
99 err(xhr.responseText);
100 return;
101 }
102 else
103 {
104 var error = L('server_error');
105
106 if (xhr.responseText.indexOf('allocate memory')<0)
107 {
108 error += "\n" + L('try_again_later');
109 }
110 else
111 {
112 error += "\n"+xhr.responseText;
113 }
114 Ti.API.error('e.error = ' + e.error);
115 err(error);
116 }
117 };
118
119 xhr.onreadystatechange = function() {
120 try {
121 if(xhr.readyState == 4) {
122 if(xhr.status != 200 && xhr.status != 201 && xhr.status != 401&& xhr.status != 403) {
123 Ti.App.removeEventListener('abortXHR', abortXhrCall);
124 Ti.API.error('readystate = 4 + xhr.status != 200');
125 err(xhr.responseText);
126 }
127 }
128
129 } catch(e) {
130 Ti.API.error('status = ' + xhr.status);
131 Ti.API.error(xhr.responseText);
132 }
133 };
134
135 xhr.onload = function() {
136 var results;
137 if(this.status === 201) {
138 results = {
139 responseText : this.responseText,
140 xhrStatus : this.status
141 };
142 } else {
143 try {
144 results = JSON.parse(xhr.responseText);
145 } catch(err) {
146 results = {
147 responseText : xhr.responseText,
148 xhrStatus : xhr.status
149 };
150 }
151 }
152 Ti.App.removeEventListener('abortXHR', abortXhrCall);
153 suc.call(xhr, results);
154 };
155 var finalUrl = fullPath;
156
157 if(includeOAUTH && config.AUTH_TYPE === 'OAUTH') {
158 var accessor = {
159 consumerSecret : config.OAUTH_CONSUMER_SECRET,
160 tokenSecret : self.oAuth.oauth_token_secret
161 };
162 var message = {
163 method : method,
164 action : fullPath,
165 parameters : [['oauth_signature_method', 'HMAC-SHA1'], ['oauth_verifier', 'None'], ['oauth_token', self.oAuth.oauth_token], ['oauth_consumer_key', config.OAUTH_CONSUMER_KEY], ['format', 'json'], ['oauth_callback', 'None'], ['oauth_version', '1.0']]
166 };
167
168 if( typeof (params) != 'undefined') {
169 //Ti.API.info('Adding the params to message.parameters');
170 var val;
171 for(var pKey in params) {
172 if (pKey == 'ffile' || pKey == 'vfile')
173 {
174 continue;
175 }
176 if(params[pKey] === true) {
177 val = 1;
178 }
179 if(params[pKey] === false) {
180 val = 0;
181 } else {
182 val = params[pKey];
183 }
184 message.parameters.push([pKey, val]);
185 }
186 }
187
188 Ti.API.info('params = ' + JSON.stringify(params));
189
190 OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
191 OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
192 OAuth.SignatureMethod.sign(message, accessor);
193 var finalUrl = OAuth.addToURL(message.action, message.parameters);
194 Ti.API.info('finalUrl = ' + finalUrl);
195 }
196
197 if(!!clearCookies) {
198 xhr.clearCookies(finalUrl);
199 }
200
201 try
202 {
203 Ti.API.info('Starmeo.js | xhr opening');
204 xhr.open(method, finalUrl);
205
206 if(config.AUTH_TYPE === 'BASIC') {
207 xhr.setRequestHeader('Authorization', 'Basic ' + self.basicAuth);
208 }
209
210 if( typeof (params) != 'undefined') {
211 if( typeof (params['ffile']) != "undefined") {
212 Ti.API.info('setting enctype');
213 xhr.setRequestHeader("enctype", "multipart/form-data");
214 if(!core.isAndroid) {
215 xhr.setRequestHeader("Content-Type", "image/png");
216 }
217 } else if( typeof (params['vfile']) != "undefined") {
218 xhr.setRequestHeader("enctype", "multipart/form-data");
219 Ti.API.info('setting enctype');
220 }
221 }
222
223 Ti.API.info('Starmeo.js | Additional headers');
224 // Additional headers
225 for(var prop in headers) {
226 if(headers.hasOwnProperty(prop)) {
227 Ti.API.info('Starmeo.js | prop = ' + prop + ' = ' + headers[prop]);
228 xhr.setRequestHeader(prop, headers[prop]);
229 }
230 }
231
232
233 // Add Version Header
234 //iOS App v2.03
235 var ver = 'Starmeo ' + Ti.Platform.osname + ' App v' + Ti.App.version
236 Ti.API.info('Starmeo.js | User-Agent = ' + ver);
237 xhr.setRequestHeader('User-Agent', ver);
238
239 Ti.API.info('Starmeo.js | send');
240 xhr.send(params);
241 }
242 catch (e)
243 {
244 Ti.App.removeEventListener('abortXHR', abortXhrCall);
245 Ti.API.error('status = ' + this.status);
246 Ti.API.info('Ti.Platform.availableMemory = ' + Ti.Platform.availableMemory);
247 Ti.API.info('Ti.Platform = ' + JSON.stringify(Ti.Platform));
248 if (typeof(e.error)=="undefined")
249 {
250 Ti.API.error('Starmeo.js | error catched = ' + JSON.stringify(e));
251 err(L('server_error')+"\n" + L('try_again_later'));
252 return;
253 }
254 else
255 {
256 Ti.API.error('e.error = ' + e.error);
257 err(e.error);
258 }
259 }
260};
261//---------------------------------------
262//----- oAuth ---------------------------
263//---------------------------------------
264function oAuthRequestToken(self, successCallback, errorCallback) {
265 function successRequestToken(responseText) {
266 // Extract Token
267 var uri = this.responseText;
268
269 var queryString = {
270 };
271 uri.replace(new RegExp("([^?=&]+)(=([^&]*))?", "g"), function($0, $1, $2, $3) {
272 queryString[$1] = $3;
273 });
274 Ti.API.info('successRequestToken queryString = ' + JSON.stringify(queryString));
275 var oAuthToken = {
276 oauth_token : queryString['oauth_token'],
277 oauth_token_secret : queryString['oauth_token_secret']
278 }
279
280 //Ti.App.Properties.setString("oauth_token", queryString['oauth_token'])
281 //Ti.App.Properties.setString("oauth_token_secret", queryString['oauth_token_secret']);
282
283 oAuthCSFR(self, oAuthToken, successCallback, errorCallback);
284 }
285
286 function errorRequestToken(responseText) {
287 Ti.API.error('Error received while requesting tokens for Starmeo oAuth: ' + JSON.stringify(responseText));
288 if(errorCallback) {
289 errorCallback(responseText);
290 }
291 }
292
293 var url = config.API_SERVER + '/api/' + 'oauth/request_token/';
294 var accessor = {
295 consumerSecret : config.OAUTH_CONSUMER_SECRET
296 };
297
298 var message = {
299 method : 'GET',
300 action : url,
301 parameters : [['oauth_signature_method', 'HMAC-SHA1'], ['oauth_consumer_key', config.OAUTH_CONSUMER_KEY], ['oauth_version', '1.0']]
302 };
303
304 OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
305 OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
306 OAuth.SignatureMethod.sign(message, accessor);
307 var finalUrl = OAuth.addToURL(message.action, message.parameters);
308
309 self.apiCall('GET', null, null, successRequestToken, errorRequestToken, finalUrl, null, true);
310}
311
312function oAuthCSFR(self, oAuthToken, successCallback, errorCallback) {
313 function successCSFR(responseText) {
314 //Ti.API.info('oAuthCSFR response = ' + responseText);
315 var regExForCSRFSearch = "(<input[^>]*name=[\"']csrf_signature[\"'][^>]*/?>)";
316 var re = new RegExp(regExForCSRFSearch);
317 var m = re.exec(this.responseText);
318 if(m == null) {
319 logger.error("oAuthCSFR - successCSFR -> No match");
320 } else {
321 var s = '';
322 for( i = 0; i < m.length; i++) {
323 s = s + m[i] + "\n";
324 }
325 var splittedInput = s.split('value="');
326 var splittedVal = splittedInput[1].split('"');
327 //Ti.API.info('csrf_signature = ' + splittedVal[0]);
328 oAuthToken.csrf_signature = splittedVal[0];
329 //Ti.API.info('oAuthCSFR calling oAuthAuthorize');
330 oAuthAuthorize(self, oAuthToken, successCallback, errorCallback);
331 }
332 }
333
334 function errorCSFR(responseText) {
335 Ti.API.info('Starmeo.js | errorCSFR | responseText = '+ responseText);
336 if(typeof(responseText)!="undefined" && responseText.length>0) {
337 errorCallback(responseText);
338 } else {
339 errorCallback('AUTHORIZATION REQUIRED');
340 }
341 }
342
343 var url = config.API_SERVER + '/api/' + 'oauth/authorize/';
344 var accessor = {
345 consumerSecret : config.OAUTH_CONSUMER_SECRET
346 };
347 var message = {
348 method : 'GET',
349 action : url,
350 parameters : [['oauth_token', oAuthToken.oauth_token], ['username', self.username], ['password', self.password], ['format', 'json'], ['authorize_access', 1]]
351 };
352
353 OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
354 OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
355 OAuth.SignatureMethod.sign(message, accessor);
356
357 var finalUrl = OAuth.addToURL(message.action, message.parameters);
358
359 self.apiCall('GET', null, null, successCSFR, errorCSFR, finalUrl, null, true);
360}
361
362function oAuthAuthorize(self, oAuthToken, successCallback, errorCallback) {
363 function successAuthorize(responseText) {
364 //Ti.API.info('oAuthAuthorize response = ' + responseText);
365 var uri = this.responseText;
366
367 var queryString = {
368 };
369 uri.replace(new RegExp("([^?=&]+)(=([^&]*))?", "g"), function($0, $1, $2, $3) {
370 queryString[$1] = $3;
371 });
372 //Ti.API.info('successAuthorize queryString = ' + JSON.stringify(queryString));
373
374 oAuthToken.oauth_token = queryString['oauth_token'];
375 oAuthToken.oauth_token_secret = queryString['oauth_token_secret'];
376 oAuthToken.oauth_verifier = queryString['oauth_verifier'];
377 // Ti.App.Properties.setString("oauth_token2", queryString['oauth_token'])
378 // Ti.App.Properties.setString("oauth_token_secret2", queryString['oauth_token_secret'])
379 // Ti.App.Properties.setString("oauth_verifier", queryString['oauth_verifier'])
380 oAuthAccessToken(self, oAuthToken, successCallback, errorCallback);
381 }
382
383 function errorAuthorize(responseText) {
384 Ti.API.error('Error received while requesting tokens for Starmeo oAuth: ' + JSON.stringify(responseText));
385 if(errorCallback) {
386 errorCallback(responseText);
387 }
388 }
389
390 var url = config.API_SERVER + '/api/' + 'oauth/authorize/';
391 var accessor = {
392 consumerSecret : config.OAUTH_CONSUMER_SECRET
393 };
394 var message = {
395 method : 'POST',
396 action : url,
397 parameters : [['oauth_token', oAuthToken.oauth_token], ['username', self.username], ['csrf_signature', oAuthToken.csrf_signature], ['password', self.password], ['authorize_access', 1]]
398 };
399 var data = {
400 'oauth_token' : oAuthToken.oauth_token,
401 'username' : self.username,
402 'csrf_signature' : oAuthToken.csrf_signature,
403 'password' : self.password,
404 'authorize_access' : 1
405 }
406
407 //Ti.API.info('calling oauth/authorize/ via POST');
408
409 self.apiCall('POST', null, {
410 params : data
411 }, successAuthorize, errorAuthorize, message.action);
412}
413
414function oAuthAccessToken(self, oAuthToken, successCallback, errorCallback) {
415 function successAccessToken(responseText) {
416 //Ti.API.info('oAuthAccessToken response = ' + this.responseText);
417 var uri = this.responseText;
418
419 var queryString = {
420 };
421 uri.replace(new RegExp("([^?=&]+)(=([^&]*))?", "g"), function($0, $1, $2, $3) {
422 queryString[$1] = $3;
423 });
424 //Ti.API.info('oAuthAccessToken queryString = ' + JSON.stringify(queryString));
425
426 //Ti.App.Properties.setString("oauth_token3", queryString['oauth_token'])
427 //Ti.App.Properties.setString("oauth_token_secret3", queryString['oauth_token_secret'])
428 //Ti.App.Properties.setString("oauth_verifier", queryString['oauth_verifier'])
429 successCallback({
430 oauth_token : queryString['oauth_token'],
431 oauth_token_secret : queryString['oauth_token_secret'],
432 oauth_verifier : queryString['oauth_verifier']
433 })
434 }
435
436 function errorAccessToken(responseText) {
437 Ti.API.error('Error received while requesting tokens for Starmeo oAuth: ' + JSON.stringify(responseText));
438 if(errorCallback) {
439 errorCallback(responseText);
440 }
441 }
442
443 var url = config.API_SERVER + '/api/' + 'oauth/access_token/';
444 var accessor = {
445 consumerSecret : config.OAUTH_CONSUMER_SECRET,
446 tokenSecret : oAuthToken.oauth_token_secret
447 };
448 var message = {
449 method : 'GET',
450 action : url,
451 parameters : [['oauth_signature_method', 'HMAC-SHA1'], ['oauth_verifier', oAuthToken.oauth_verifier], ['oauth_token', oAuthToken.oauth_token], ['oauth_consumer_key', config.OAUTH_CONSUMER_KEY], ['format', 'json'], ['oauth_callback', 'None'], ['oauth_version', '1.0']]
452 };
453
454 OAuth.setParameter(message, "oauth_nonce", 'accessnonce');
455 OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
456 OAuth.SignatureMethod.sign(message, accessor);
457 var finalUrl = OAuth.addToURL(message.action, message.parameters);
458
459 //Ti.API.info('oAuthAccessToken URL = ' + finalUrl);
460
461 self.apiCall('GET', null, null, successAccessToken, errorAccessToken, finalUrl);
462}
463
464RestClient.prototype.authenticateUser = function(/*object*/credentials, suc, err) {
465 var self = this;
466 oAuthRequestToken(self, suc, err);
467 Titanium.Analytics.featureEvent('user.authenticate', {
468 params: credentials
469 });
470};
471//---------------------------------------
472//----- Stars ---------------------------
473//---------------------------------------
474RestClient.prototype.getStarProfile = function(userID, suc, err) {
475 var path = 'stars/' + userID + '/app/';
476 this.apiCall('GET', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
477};
478RestClient.prototype.getQuestionsForStar = function(userID, suc, err) {
479 var path = 'stars/questions/' + userID + '/';
480 this.apiCall('GET', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
481};
482RestClient.prototype.getPostsForStar = function(userID, suc, err) {
483 var path = 'stars/posts/' + userID + '/';
484 this.apiCall('GET', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
485};
486//---------------------------------------
487//----- General Info --------------------
488//---------------------------------------
489RestClient.prototype.getMyProfile = function(suc, err) {
490 var path = 'users/me/';
491 this.apiCall('GET', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
492};
493RestClient.prototype.getPostComments = function(postID, suc, err) {
494 var path = 'posts/' + postID + '/comments/';
495 this.apiCall('GET', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
496};
497RestClient.prototype.getSocialMedia = function(userID, suc, err) {
498 var path = 'users/' + userID + '/external/';
499 this.apiCall('GET', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
500};
501RestClient.prototype.createPost = function(data, suc, err, upload) {
502 Ti.API.info('RestClient.prototype.createPost');
503 var path = 'posts/publish/';
504 Titanium.Analytics.featureEvent('post.new', {
505 params : data
506 });
507 this.apiCall('POST', path, {
508 params : data
509 }, suc, err, null, config.AUTH_TYPE === 'OAUTH', false, upload);
510};
511RestClient.prototype.answerQuestion = function(questionId, data, suc, err) {
512 var path = '/questions/' + questionId + '/answer/';
513 Titanium.Analytics.featureEvent('question.answer', {
514 params : data
515 });
516 this.apiCall('POST', path, {
517 params : data
518 }, suc, err, null, config.AUTH_TYPE === 'OAUTH');
519};
520RestClient.prototype.addLike = function(mediaId, suc, err) {
521 var path = 'v2/posts/' + mediaId + '/like/';
522 Titanium.Analytics.featureEvent('like.add', {
523 apiPath: path
524 });
525 this.apiCall('POST', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
526};
527RestClient.prototype.removeLike = function(mediaId, suc, err) {
528 var path = 'v2/posts/' + mediaId + '/like/';
529 this.apiCall('DELETE', path, null, suc, err, null, config.AUTH_TYPE === 'OAUTH');
530};
531RestClient.prototype.addComment = function(mediaId, data, suc, err) {
532 var path = 'posts/' + mediaId + '/comments/';
533 Titanium.Analytics.featureEvent('comment.new', {
534 params: data,
535 apiPath: path
536 });
537 this.apiCall('POST', path, {
538 params : data
539 }, suc, err, null, config.AUTH_TYPE === 'OAUTH');
540};