├── .gitignore ├── Makefile ├── README.md ├── package.json ├── sdk.js └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | test.js 2 | .idea 3 | node_modules 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | ./node_modules/mocha/bin/mocha test/ --reporter spec 3 | .PHONY: test 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | nodejs-vksdk 2 | ============ 3 | Small SDK for vk.com API. 4 | 5 | # Installation 6 | npm install vksdk 7 | 8 | # Example 9 | ```js 10 | // Setup 11 | var VK = require('vksdk'); 12 | var vk = new VK({ 13 | 'appId' : 2807970, 14 | 'appSecret' : 'L14ZKpgQPalJdumI6vFK', 15 | 'language' : 'ru' 16 | }); 17 | 18 | /** 19 | * Request server methods 20 | */ 21 | 22 | // Setup server access token for server API methods 23 | vk.on('serverTokenReady', function(_o) { 24 | // Here will be server access token 25 | vk.setToken(_o.access_token); 26 | }); 27 | 28 | // Turn on requests with access tokens 29 | vk.setSecureRequests(true); 30 | 31 | // Request server API method 32 | vk.request('secure.getSMSHistory', {}, function(_dd) { 33 | console.log(_dd); 34 | }); 35 | 36 | /** 37 | * Request client methods 38 | */ 39 | // First you have to pass access_token from client side JS code 40 | vk.setToken(access_token); 41 | 42 | // Request 'users.get' method 43 | vk.request('users.get', {'user_id' : 1}, function(_o) { 44 | console.log(_o); 45 | }); 46 | ``` 47 | 48 | # Setup 49 | ```js 50 | var VK = require('vksdk'); 51 | 52 | var vk = new VK({ 53 | 'appId' : [Your application ID here], 54 | 'appSecret' : [Your application secret code here], 55 | }); 56 | ``` 57 | 58 | Required config options: 59 | * appSecret — application secret code (check your application settings on vk.com) 60 | * appId — vk.com application id 61 | 62 | Available config options: 63 | 64 | * **[bool] https** — with this options all links in API answers will be with https protocol. Disabled by default. 65 | * **[string] version** — vk.com api verions. Default: 5.27 66 | * **[string] language** — Language code for api answers (for old deprecated API) 67 | * **[bool] secure** — enable api requests with tokens. Default false. 68 | 69 | 70 | You can read and change some config options: 71 | * **getVersion()** — get current API version 72 | * **setVersion(_v)** — set current API version 73 | * **getLanguage()** — get current API language 74 | * **setLanguage(_v)** — set current API language 75 | * **getHttps()** — get https links usage for API answers 76 | * **setHttps(_v)** — set https links usage for API answers 77 | * **getSecureRequests()** — get token's usage for API requests 78 | * **setSecureRequests(_v)** — set token's usage for API requests 79 | 80 | 81 | # API requests 82 | For vk.com API requests you have to use method *request(_method, _requestParams, _response)*. 83 | 84 | * **[string] _method** — name of vk.com API method, 85 | * **[mixed] _requestParams** - object with values of params for api method. This param is not required. You also can pass empty object *{}* 86 | * **[mixed] _response** — special response handler (not required), function or event name. 87 | 88 | Request method gets data from API and returns result. There are 3 ways to get data from API 89 | 90 | ## Callback 91 | ```js 92 | vk.setSecureRequests(false); 93 | vk.request('users.get', {'user_id' : 1}, function(_o) { 94 | console.log(_o); 95 | }); 96 | ``` 97 | 98 | ## Event 99 | After success API call SDK emits the event named 'done:' + _method; 100 | So if you call method *users.get*, you have to wait event *done:users.get* 101 | 102 | ```js 103 | vk.setSecureRequests(false); 104 | vk.request('users.get', {'user_id' : 1}); 105 | vk.on('done:users.get', function(_o) { 106 | console.log(_o); 107 | }); 108 | ``` 109 | 110 | ## Custom event 111 | Result of request will be returned with your custom event 112 | 113 | ```js 114 | vk.setSecureRequests(false); 115 | vk.request('users.get', {'user_id' : 1}, 'myCustomEvent'); 116 | vk.on('myCustomEvent', function(_o) { 117 | console.log(_o); 118 | }); 119 | ``` 120 | 121 | # Server access token 122 | For some api methods you need server access token 123 | 124 | ```js 125 | vk.requestServerToken(); 126 | 127 | // Waiting for special 'serverTokenReady' event 128 | vk.on('serverTokenReady', function(_o) { 129 | // Here will be server access token 130 | console.log(_o); 131 | }); 132 | ``` 133 | 134 | You also can get tokeb with callback or custom event 135 | 136 | # HTTP errors 137 | SDK emits 'http-error' event in case of http errors. 138 | 139 | ```js 140 | vk.on('http-error', function(_e) { 141 | console.log(_e); 142 | }); 143 | ``` 144 | 145 | # JSON parsing errors 146 | SDK emits 'parse-error' event in case of non-valid API answer. 147 | 148 | ```js 149 | vk.on('parse-error', function(_e) { 150 | console.log(_e); 151 | }); 152 | ``` 153 | 154 | SDK provides all methods from [events.EventEmitter](http://nodejs.org/api/events.html) 155 | 156 | # Bonus 157 | You also can request some api methods without any tokens, with [app signature](https://vk.com/pages?oid=-17680044&p=Application_Interaction_with_API) 158 | 159 | ```js 160 | vk.oldRequest('places.getCountryById', {'cids' : '1,2'}, function(_o) { 161 | console.log(_o); 162 | }); 163 | ``` 164 | 165 | But this way is deprecated and doesn't work for all api methods. 166 | 167 | 168 | # For developers 169 | Your commits and pull requests are welcome. Please run the tests before 170 | 171 | npm test 172 | 173 | You have to provide tests for the new features. 174 | 175 | # Support 176 | * 57uff3r@gmail.com 177 | * skype: andrey.korchak 178 | * http://57uff3r.ru 179 | * http://vk.com/s7uff3r 180 | 181 | # Thanks to 182 | * [Alex0007](https://github.com/Alex0007) 183 | 184 | See also vk.com [cities and counties DB](http://citieslist.ru/) 185 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vksdk", 3 | "description": "SDK for API of vk.com", 4 | "version": "5.3.2", 5 | "homepage": "https://github.com/57uff3r/nodejs-vksdk", 6 | "email": "57uff3r@gmail.com", 7 | "license": "BSD-3-Clause", 8 | "main": "sdk.js", 9 | "scripts": { 10 | "test": "make test" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/57uff3r/nodejs-vksdk.git" 15 | }, 16 | "keywords": [ 17 | "vk", 18 | "vkontakte", 19 | "sdk" 20 | ], 21 | "author": "Andrey Korchak <57uff3r@gmail.com> (http://57uff3r.ru/)", 22 | "bugs": { 23 | "url": "https://github.com/57uff3r/nodejs-vksdk/issues" 24 | }, 25 | "devDependencies": { 26 | "chai": "^3.4.0", 27 | "mocha": "^2.3.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sdk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SDK for vk.com API 4 | * 5 | * @author 57uff3r@gmail.com 6 | * @see https://github.com/57uff3r/nodejs-vksdk 7 | * @see http://57uff3r.ru 8 | */ 9 | var util = require('util'), 10 | EventEmitter = require('events').EventEmitter, 11 | crypto = require('crypto'), 12 | http = require('http'), 13 | https = require('https'); 14 | 15 | /** 16 | * Create new SDK object 17 | * @param {object} _options 18 | * - mode - auth mode (oauth or sig) 19 | * - appID - 20 | * @returns {undefined} 21 | */ 22 | function VK(_options) { 23 | 24 | // set default options 25 | this.options = { 26 | 'appSecret' : false, 27 | 'appId' : false, 28 | 'https' : false, 29 | 'version' : '5.58', 30 | 'language' : 'ru', 31 | 'secure' : false 32 | }; 33 | 34 | // no default token 35 | this.token = false; 36 | 37 | /** 38 | * Setup config options 39 | */ 40 | if (typeof(_options) != 'object' || this.isEmpty(_options)) { 41 | throw new Error('nodejs-vk-sdk: you have to specify options in sdk constructor'); 42 | } 43 | 44 | if (!_options.hasOwnProperty('appId')) { 45 | throw new Error('nodejs-vk-sdk: you have to specify VK application id'); 46 | } 47 | 48 | this.options = this.extend(this.options, _options); 49 | 50 | this.reqLastTime = new Date(0) 51 | this.requestingNow = false 52 | } 53 | 54 | 55 | util.inherits(VK, EventEmitter); 56 | module.exports = VK; 57 | 58 | 59 | /** 60 | * =========================== Getters and setters 61 | */ 62 | /** 63 | * Get current API version 64 | * @return {string} 65 | */ 66 | VK.prototype.getVersion = function() { 67 | return this.options.version; 68 | }; 69 | 70 | /** 71 | * Set current API version 72 | * @param {string} _v 73 | * 74 | * @return {string} 75 | */ 76 | VK.prototype.setVersion = function(_v) { 77 | this.options.version = _v; 78 | return true; 79 | }; 80 | 81 | /** 82 | * Get current API language 83 | * @return {string} 84 | */ 85 | VK.prototype.getLanguage = function() { 86 | return this.options.language; 87 | }; 88 | 89 | /** 90 | * Set current API language 91 | * @param {string} _v 92 | * 93 | * @return {string} 94 | */ 95 | VK.prototype.setLanguage = function(_l) { 96 | this.options.language = _l; 97 | return true; 98 | }; 99 | 100 | 101 | /** 102 | * Enable https 103 | * @return {bool} 104 | */ 105 | VK.prototype.setHttps = function(_v) { 106 | this.options.https = _v; 107 | return true; 108 | }; 109 | 110 | /** 111 | * Disable https 112 | * @return {bool} 113 | */ 114 | VK.prototype.getHttps = function() { 115 | return this.options.https; 116 | }; 117 | 118 | /** 119 | * Enable https 120 | * @return {bool} 121 | */ 122 | VK.prototype.setSecureRequests = function(_v) { 123 | this.options.secure = _v; 124 | return true; 125 | }; 126 | 127 | /** 128 | * Disable https 129 | * @return {bool} 130 | */ 131 | VK.prototype.getSecureRequests = function() { 132 | return this.options.secure; 133 | }; 134 | 135 | /** 136 | * Get current access token 137 | * @return {string} 138 | */ 139 | VK.prototype.getToken = function() { 140 | return this.token; 141 | }; 142 | 143 | /** 144 | * Set current access token 145 | * @param {strinf} 146 | * @return {string} 147 | */ 148 | VK.prototype.setToken = function(_t) { 149 | this.token = _t; 150 | return true; 151 | }; 152 | 153 | VK.prototype.waitForNextRequest = function (_cb) { 154 | var self = this; 155 | 156 | if (new Date() - this.reqLastTime > 334 && !this.requestingNow) { 157 | _cb(); 158 | } else setTimeout(function () { 159 | self.waitForNextRequest(_cb); 160 | }, 50); 161 | }; 162 | 163 | /** 164 | * =========================== Dealing with api 165 | */ 166 | /** 167 | * Request API method with signature 168 | * @param {string} _method 169 | * @param {mixed} _params 170 | * @param {mixed} _response 171 | * @returns {mixed} 172 | * 173 | * @see https://vk.com/pages?oid=-17680044&p=Application_Interaction_with_API 174 | */ 175 | VK.prototype.oldRequest = function(_method, _requestParams, _response) { 176 | var responseType = 'event'; 177 | 178 | if ( typeof(_response) === 'function') { 179 | responseType = 'callback'; 180 | } 181 | 182 | var params = (!!_requestParams ? _requestParams : {}); 183 | params.api_id = this.options.appId; 184 | params.v = '3.0'; 185 | params.lang = ('lang' in params) ? params['lang'] : this.options.language || this.default.language; 186 | params.method = _method; 187 | params.timestamp = Math.round(new Date().getTime() / 1000); 188 | params.format = 'json'; 189 | params.random = Math.floor(Math.random() * 9999); 190 | 191 | // JS doesn't guarantee the sequence of parameters in the object. It can break. 192 | params = this.sortObjectByKey(params); 193 | params.sig = this._createSig(params); 194 | 195 | var requestString = this.buildQuery(params); 196 | 197 | var options = { 198 | host: 'api.vk.com', 199 | port: 80, 200 | path: '/api.php?' + requestString 201 | }; 202 | 203 | var self = this; 204 | 205 | http.get(options, function(res) { 206 | var apiResponse = new String(); 207 | res.setEncoding('utf8'); 208 | 209 | res.on('data', function(chunk) { 210 | apiResponse += chunk; 211 | }); 212 | 213 | res.on('end', function() { 214 | var o = JSON.parse(apiResponse); 215 | if (responseType === 'callback' && typeof _response === 'function') { 216 | _response(o); 217 | } else { 218 | if (responseType === 'event' && !!_response) { 219 | return self.emit(_response, o); 220 | } 221 | return self.emit('done:' + _method, o); 222 | } 223 | }); 224 | }).on('error', function (e) { 225 | self.emit('http-error', e); 226 | }); 227 | }; 228 | 229 | /** 230 | * Request API method 231 | * @param {string} _method 232 | * @param {mixed} _params 233 | * @param {mixed} _response 234 | * @returns {mixed} 235 | * 236 | * @see https://vk.com/pages?oid=-17680044&p=Application_Interaction_with_API 237 | */ 238 | VK.prototype.request = function(_method, _requestParams, _response) { 239 | var responseType = 'event'; 240 | 241 | if ( typeof(_response) === 'function') { 242 | responseType = 'callback'; 243 | } 244 | 245 | var self = this; 246 | 247 | var params = { 248 | 'lang' : this.options.lang, 249 | 'v' : this.options.version, 250 | 'https' : (this.options.https) ? 1 : 0 251 | }; 252 | 253 | if (this.isEmpty(_requestParams) === false) { 254 | for (var i in _requestParams) { 255 | params[i] = _requestParams[i]; 256 | } 257 | } 258 | 259 | var requestString = this.buildQuery(params); 260 | 261 | if (this.options.secure) { 262 | if (this.token) { 263 | requestString = requestString + '&access_token=' + this.token; 264 | } 265 | 266 | if (this.options.appSecret) { 267 | requestString = requestString + '&client_secret=' + this.options.appSecret; 268 | } 269 | } 270 | 271 | var options = { 272 | host: 'api.vk.com', 273 | port: 443, 274 | path: '/method/' + _method , 275 | method: 'POST', 276 | headers: { 277 | 'Content-Type': 'application/x-www-form-urlencoded', 278 | 'Content-Length': requestString.length 279 | } 280 | }; 281 | 282 | this.waitForNextRequest(function () { 283 | self.requestingNow = true; 284 | var post_req = https.request(options, function(res) { 285 | var apiResponse = ""; 286 | res.setEncoding('utf8'); 287 | 288 | res.on('data', function(chunk) { 289 | apiResponse += chunk; 290 | }); 291 | 292 | res.on('end', function() { 293 | self.reqLastTime = new Date(); 294 | self.requestingNow = false; 295 | try { 296 | var o = JSON.parse(apiResponse); 297 | } catch(e) { 298 | return self.emit('parse-error', apiResponse); 299 | } 300 | 301 | if (responseType === 'callback' && typeof _response === 'function') { 302 | _response(o); 303 | } else { 304 | if (responseType === 'event' && !!_response) { 305 | return self.emit(_response, o); 306 | } 307 | return self.emit('done:' + _method, o); 308 | } 309 | }); 310 | }).on('error', function (e) { 311 | self.requestingNow = false; 312 | self.emit('http-error', e); 313 | }); 314 | 315 | post_req.write(requestString); 316 | post_req.end(); 317 | }) 318 | }; 319 | 320 | /** 321 | * Request server token 322 | * 323 | * @param {Function} _response - callback 324 | * @param {String} [_code] - authorization code 325 | * @param {String} [_redirect_uri] - URL where code has been received 326 | * 327 | */ 328 | VK.prototype.requestServerToken = function(_response, _code, _redirect_uri) { 329 | var responseType = 'event'; 330 | 331 | if ( typeof(_response) === 'function') { 332 | responseType = 'callback'; 333 | } 334 | 335 | var path = '/access_token?client_id=' + this.options.appId + 336 | '&client_secret=' + this.options.appSecret; 337 | 338 | if (typeof _code !== 'undefined' && typeof _redirect_uri !== 'undefined') { 339 | path += '&redirect_uri=' + _redirect_uri + '&code=' + _code; 340 | } else { 341 | path += '&v=' + this.options.version + '&grant_type=client_credentials'; 342 | } 343 | 344 | var options = { 345 | host: 'oauth.vk.com', 346 | port: 443, 347 | path: path 348 | }; 349 | 350 | var self = this; 351 | 352 | https.get(options, function(res) { 353 | var apiResponse = new String(); 354 | res.setEncoding('utf8'); 355 | 356 | res.on('data', function(chunk) { 357 | apiResponse += chunk; 358 | }); 359 | 360 | res.on('end', function() { 361 | var o = JSON.parse(apiResponse); 362 | if (responseType === 'callback' && typeof _response === 'function') { 363 | _response(o); 364 | } else { 365 | if (responseType === 'event' && !!_response) { 366 | return self.emit(_response, o); 367 | } 368 | return self.emit('serverTokenReady', o); 369 | } 370 | }); 371 | }).on('error', function (e) { 372 | self.emit('http-error', e); 373 | }); 374 | }; 375 | 376 | 377 | 378 | /** 379 | * =========================== Extra stuff 380 | */ 381 | // Speed up calls to hasOwnProperty 382 | VK.prototype.hasOwnProperty = Object.prototype.hasOwnProperty; 383 | 384 | /** 385 | * Test — if variable empty 386 | * @param {mixed} 387 | * @return {bool} 388 | */ 389 | VK.prototype.isEmpty = function(_obj) { 390 | // null and undefined are "empty" 391 | if (_obj == null) return true; 392 | 393 | // Assume if it has a length property with a non-zero value 394 | // that that property is correct. 395 | if (_obj.length > 0) return false; 396 | if (_obj.length === 0) return true; 397 | 398 | // Otherwise, does it have any properties of its own? 399 | // Note that this doesn't handle 400 | // toString and valueOf enumeration bugs in IE < 9 401 | for (var key in _obj) { 402 | if (this.hasOwnProperty.call(_obj, key)) return false; 403 | } 404 | return true; 405 | }; 406 | 407 | /** 408 | * Merge multiple JSON's 409 | * @param {object} 410 | * @return {object} 411 | */ 412 | VK.prototype.extend = function(target) { 413 | var sources = [].slice.call(arguments, 1); 414 | sources.forEach(function (source) { 415 | for (var prop in source) { 416 | target[prop] = source[prop]; 417 | } 418 | }); 419 | return target; 420 | }; 421 | 422 | /** 423 | * Implode array to string 424 | * @param {string} glue 425 | * @param {array} pieces 426 | * @returns {@exp;pieces@call;join|@exp;@exp;pieces@call;joinpieces|VK.implode.pieces} 427 | */ 428 | VK.prototype.implode = function implode( glue, pieces ) { 429 | return ( ( pieces instanceof Array ) ? pieces.join ( glue ) : pieces ); 430 | }; 431 | 432 | /** 433 | * Sort object properties by name 434 | * @param {object} o 435 | * @returns {object} 436 | */ 437 | VK.prototype.sortObjectByKey = function (o) { 438 | var sorted = {}, 439 | key, a = []; 440 | 441 | for (key in o) { 442 | if (o.hasOwnProperty(key)) { 443 | a.push(key); 444 | } 445 | } 446 | 447 | a.sort(); 448 | 449 | for (var key = 0; key < a.length; key++) { 450 | sorted[a[key]] = o[a[key]]; 451 | } 452 | return sorted; 453 | }; 454 | 455 | 456 | /** 457 | * Generate URL-encoded query string 458 | * @param {object} params 459 | * @return {string} 460 | */ 461 | VK.prototype.buildQuery = function(params) { 462 | var arr = []; 463 | for(var name in params) { 464 | var value = params[name]; 465 | 466 | if("undefined" !== typeof value) { 467 | arr.push( name+'='+ encodeURIComponent(value) ); 468 | } 469 | } 470 | 471 | return this.implode('&', arr); 472 | }; 473 | 474 | /** 475 | * Authorization on a Remote Side 476 | * https://vk.com/dev/openapi_auth 477 | * 478 | * @param {String} sessionData 479 | * @returns {Boolean} 480 | */ 481 | VK.prototype.isAuthOpenAPIMember = function(sessionData) { 482 | var data = this._parseSessionData(sessionData); 483 | 484 | if (data && data.sig === this._createSig(data) && data.expire > Math.floor(Date.now() / 1000)) { 485 | return true; 486 | } 487 | return false; 488 | }; 489 | 490 | /** 491 | * Create signature from parameters 492 | * 493 | * @param {Object} params 494 | * @returns {String} 495 | * @private 496 | */ 497 | VK.prototype._createSig = function(params) { 498 | var sig = ''; 499 | for(var key in params) { 500 | if (key !== 'sig') { 501 | sig += key + '=' + params[key]; 502 | } 503 | } 504 | sig = sig + this.options.appSecret; 505 | return crypto.createHash('md5').update(sig, 'utf8').digest('hex'); 506 | }; 507 | 508 | /** 509 | * Parse params from auth session data 510 | * 511 | * @param {String} data 512 | * 513 | * @returns {Object|Undefined} 514 | * @private 515 | */ 516 | VK.prototype._parseSessionData = function(data) { 517 | var items = data.split('&'), 518 | validKeys = ['expire', 'mid', 'secret', 'sid', 'sig'], 519 | parsedData = {}, 520 | item, 521 | key, 522 | k; 523 | 524 | for (k in items) { 525 | 526 | item = items[k].split('='); 527 | key = item[0]; 528 | 529 | if (this.isEmpty(key) || this.isEmpty(item[1]) || validKeys.indexOf(key) === -1) { 530 | return; 531 | } 532 | 533 | parsedData[key] = item[1]; 534 | } 535 | 536 | for (k in validKeys) { 537 | if (typeof parsedData[validKeys[k]] === 'undefined') { 538 | return; 539 | } 540 | } 541 | 542 | return this.sortObjectByKey(parsedData); 543 | }; 544 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert, 2 | should = require('chai').should(), 3 | VK = require('../sdk'); 4 | 5 | 6 | 7 | // small tests workaround 8 | var done = function(_o) { 9 | }; 10 | 11 | describe('basicSdk', function() { 12 | var vk = new VK({ 13 | 'appId' : 2807970, 14 | 'appSecret' : 'L14ZKpgQPalJdumI6vFK', 15 | 'language' : 'ru' 16 | }); 17 | 18 | this.timeout(20000); 19 | 20 | it('Should test getters and setters', function(done) { 21 | 22 | assert.doesNotThrow(function() { 23 | assert.equal(vk.getVersion(), '5.28'); 24 | }); 25 | 26 | assert.doesNotThrow(function() { 27 | assert.isTrue(vk.setVersion('5.25')); 28 | assert.equal(vk.getVersion(), '5.25'); 29 | }); 30 | 31 | assert.doesNotThrow(function() { 32 | assert.isFalse(vk.getToken()); 33 | }); 34 | 35 | assert.doesNotThrow(function() { 36 | assert.isTrue(vk.setToken('abcd')); 37 | assert.equal(vk.getToken(), 'abcd'); 38 | }); 39 | 40 | assert.doesNotThrow(function() { 41 | assert.isFalse(vk.getHttps()); 42 | assert.isTrue(vk.setHttps(true)); 43 | assert.isTrue(vk.getHttps()); 44 | }); 45 | 46 | done(); 47 | }); 48 | 49 | 50 | it('Should use oldRequest method', function(done) { 51 | assert.doesNotThrow(function() { 52 | vk.oldRequest('places.getCountryById', {'cids' : '1,2'}); 53 | vk.on('done:places.getCountryById', function(_o) { 54 | assert.equal(_o.response[0].cid, 1); 55 | assert.equal(_o.response[1].cid, 2); 56 | done(); 57 | }); 58 | }); 59 | }); 60 | 61 | it('Should use oldRequest method with custom event', function(done) { 62 | assert.doesNotThrow(function() { 63 | vk.oldRequest('places.getCountryById', {'cids' : '1,2'}, 'customEvent'); 64 | vk.on('customEvent', function(_o) { 65 | assert.equal(_o.response[0].cid, 1); 66 | assert.equal(_o.response[1].cid, 2); 67 | }); 68 | done(); 69 | }); 70 | }); 71 | 72 | it('Should use oldRequest method with callback', function(done) { 73 | assert.doesNotThrow(function() { 74 | vk.oldRequest('places.getCountryById', {'cids' : '1,2'}, function(_o) { 75 | assert.equal(_o.response[0].cid, 1); 76 | assert.equal(_o.response[1].cid, 2); 77 | done(); 78 | }); 79 | }); 80 | }); 81 | 82 | 83 | it('Should get server access token', function(done) { 84 | assert.doesNotThrow(function() { 85 | vk.requestServerToken(function(_o) { 86 | assert.isTrue('access_token' in _o); 87 | assert.isTrue('expires_in' in _o); 88 | assert.isTrue(_o.expires_in === 0); 89 | done(); 90 | }); 91 | }); 92 | }); 93 | 94 | it('Should get server access token with callback', function(done) { 95 | assert.doesNotThrow(function() { 96 | vk.requestServerToken(); 97 | vk.on('serverTokenReady', function(_o) { 98 | assert.isTrue('access_token' in _o); 99 | assert.isTrue('expires_in' in _o); 100 | assert.isTrue(_o.expires_in === 0); 101 | done(); 102 | }); 103 | }); 104 | }); 105 | 106 | it('Should get server access token with custom event', function(done) { 107 | assert.doesNotThrow(function() { 108 | vk.requestServerToken('myCustomEvent'); 109 | vk.on('myCustomEvent', function(_o) { 110 | assert.isTrue('access_token' in _o); 111 | assert.isTrue('expires_in' in _o); 112 | assert.isTrue(_o.expires_in === 0); 113 | done(); 114 | }); 115 | }); 116 | }); 117 | 118 | it('Should get Durov\'s profile with callback in insecure mode', function(done) { 119 | assert.doesNotThrow(function() { 120 | vk.setSecureRequests(false); 121 | vk.request('users.get', {'user_id' : 1}, function(_o) { 122 | //console.log(_o); 123 | assert.equal(_o.response[0].id, 1); 124 | assert.ok(['Павел', 'Pavel'].indexOf(_o.response[0].first_name) !== -1); 125 | assert.ok(['Дуров', 'Durov'].indexOf(_o.response[0].last_name) !== -1); 126 | done(); 127 | }); 128 | }); 129 | }); 130 | 131 | it('Should get error on server request', function(done) { 132 | assert.doesNotThrow(function() { 133 | vk.setSecureRequests(true); 134 | vk.request('secure.getAppBalance', {}, function(_o) { 135 | assert.equal(_o.error.error_code, 10); 136 | done(); 137 | }); 138 | }); 139 | }); 140 | 141 | it('Should request server method with server token', function(done) { 142 | assert.doesNotThrow(function() { 143 | vk.requestServerToken(function(_o) { 144 | vk.setToken(_o.access_token); 145 | vk.setVersion('5.27'); 146 | vk.request('secure.getSMSHistory', {}, function(_dd) { 147 | assert.deepEqual(_dd, { response: [] }); 148 | done(); 149 | }); 150 | }); 151 | }); 152 | }); 153 | 154 | it('Should request server method with server token and event', function(done) { 155 | assert.doesNotThrow(function() { 156 | vk.requestServerToken(function(_o) { 157 | vk.setToken(_o.access_token); 158 | vk.setVersion('5.27'); 159 | vk.request('secure.getAppBalance'); 160 | vk.on('done:secure.getAppBalance', function(_o) { 161 | assert.equal(_o.error.error_code, 500); 162 | done(); 163 | }); 164 | }); 165 | }); 166 | }); 167 | 168 | it('Should request server method with server token and custom event', function(done) { 169 | assert.doesNotThrow(function() { 170 | vk.requestServerToken(function(_o) { 171 | vk.setToken(_o.access_token); 172 | vk.setVersion('5.27'); 173 | vk.request('secure.getAppBalance', {}, 'done'); 174 | vk.on('done', function(_o) { 175 | assert.equal(_o.error.error_code, 500); 176 | done(); 177 | }); 178 | }); 179 | }); 180 | }); 181 | 182 | }); 183 | 184 | 185 | describe('systemStuff', function() { 186 | var vk = new VK({ 187 | 'appId' : 2807970, 188 | 'appSecret' : 'L14ZKpgQPalJdumI6vFK' 189 | }); 190 | 191 | this.timeout(20000); 192 | 193 | it('Should correctly identify non-empty objects', function(done) { 194 | assert.doesNotThrow(function() { 195 | assert.isFalse(vk.isEmpty("Hello")); 196 | assert.isFalse(vk.isEmpty([1,2,3])); 197 | assert.isFalse(vk.isEmpty({test: 1})); 198 | assert.isFalse(vk.isEmpty({length: 3, custom_property: [1,2,3]})); 199 | done(); 200 | }); 201 | }); 202 | 203 | it('Should correctly identify empty objects', function(done) { 204 | assert.doesNotThrow(function() { 205 | assert.isTrue(vk.isEmpty("")); 206 | assert.isTrue(vk.isEmpty({})); 207 | assert.isTrue(vk.isEmpty([])); 208 | assert.isTrue(vk.isEmpty({length: 0, custom_property: []})); 209 | done(); 210 | }); 211 | }); 212 | 213 | 214 | it('Should correctly merge objects', function(done) { 215 | assert.doesNotThrow(function() { 216 | assert.deepEqual(vk.extend({}), {}); 217 | assert.deepEqual(vk.extend({}, {'t' : 1}), {'t' : 1}); 218 | assert.deepEqual(vk.extend({'a' : 1}, {'t' : 1}, {'t' : 2}), {'t' : 2, 'a' : 1}); 219 | done(); 220 | }); 221 | }); 222 | 223 | it('Should create equal sig', function () { 224 | var rightSid = 'expire=1271238742&mid=100172&secret=97c1e8933e&sid=549b550f608e4a4d247734941debb5e68df50a66c58dc6ee2a4f60a2&sig=372df9795fe8dd29684a2f996872457c', 225 | rightSessionData = vk._parseSessionData(rightSid), 226 | wrongSid; 227 | 228 | assert.deepEqual(rightSessionData, { 229 | expire: '1271238742', 230 | mid: '100172', 231 | secret: '97c1e8933e', 232 | sid: '549b550f608e4a4d247734941debb5e68df50a66c58dc6ee2a4f60a2', 233 | sig: '372df9795fe8dd29684a2f996872457c' 234 | }); 235 | wrongSid = 'test=here&expire=1271238742&mid=100172&secret=97c1e8933e&sid=549b550f608e4a4d247734941debb5e68df50a66c58dc6ee2a4f60a2&sig=372df9795fe8dd29684a2f996872457c'; 236 | assert.isUndefined(vk._parseSessionData(wrongSid)); 237 | wrongSid = 'mid=100172&secret=97c1e8933e&sid=549b550f608e4a4d247734941debb5e68df50a66c58dc6ee2a4f60a2&sig=372df9795fe8dd29684a2f996872457c'; 238 | assert.isUndefined(vk._parseSessionData(wrongSid)); 239 | 240 | var testVk = new VK({ appId: 1, appSecret: '6FF1PUlZfEyutJxctvtd'}); 241 | assert.equal(testVk._createSig(rightSessionData), '372df9795fe8dd29684a2f996872457c'); 242 | 243 | // It will be ok, if disable check by data.expire 244 | //assert.ok(testVk.isAuthOpenAPIMember(rightSid)); 245 | }); 246 | 247 | }); 248 | --------------------------------------------------------------------------------