UNPKG

airship-server

Version:

Airship is a framework for Node.JS & TypeScript that helps you to write big, scalable and maintainable API servers.

217 lines (213 loc) 8.94 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const CallbackQueue_1 = require("../utils/CallbackQueue"); const VKApiError_1 = require("./VKApiError"); const req = require('tiny_request'); const REQUESTS_PER_SECOND = 3; const API_BASE_URL = 'https://api.vk.com/method/'; const API_VERSION = '5.53'; class VKApi { constructor(logger, cache) { this._queues = new Map(); this.appServiceKey = '46d3f43f46d3f43f468d06a38646896cbb446d346d3f43f1e023074e283b74286af81f0'; this._logger = logger; if (cache) this._cache = cache; } call(method, token, params, useQueue = true) { return __awaiter(this, void 0, void 0, function* () { params['v'] = API_VERSION; params['access_token'] = token; return new Promise((resolve, reject) => { let request = () => { req.post({ url: API_BASE_URL + method, form: params, json: true, timeout: 1000 * 5 }, (body, response, err) => { if (!err && response.statusCode == 200 && !body.error) { resolve(body); return; } if (body && body.error) { reject(VKApiError_1.default.deserialize(body)); this._logger.warn('VK Api error', { response: JSON.stringify(body, null, 2), method, token, params }); return; } if (err) { this._logger.error('VK Api:', { 'Networking error:': err, method, token, params }); reject(err); return; } this._logger.error('VK Api:', { 'api request error: Body:': body, 'Error:': err }); reject(err); }); }; if (!useQueue) { request(); return; } this.getQueueForGroup(token).push(request); }); }); } callWithAsyncLock(method, token, params) { return __awaiter(this, void 0, void 0, function* () { if (!this._cache) throw new Error('No cache'); if (!this._cache) throw new Error('No cache'); let canWork = yield this._cache.setnx(`LOCK_${token}`, 1); if (canWork == 1) { yield this._cache.cache(`LOCK_${token}`, Date.now() + 338 + 1, 338); return yield this.call(method, token, params, false); } else { // let g = await this._cache.get(`LOCK_${token}`) // // if (Date.now() > (g as number)) { // g = await this._cache.getset(`LOCK_${token}`, Date.now() + 338 + 1) // // if (Date.now() > g) { // await this._cache.del(`LOCK_${token}`) // // return this.call(method, token, params, false) // } // } return new Promise((resolve, reject) => { setTimeout(() => { this.callWithAsyncLock(method, token, params) .then(resolve) .catch(reject); }, 100); }); } }); } callWithRetry(method, token, params, useQueue = true) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { let makeCall = (resolve, reject, method, token, params, useQueue = true) => { this.call(method, token, params, useQueue) .then(r => { resolve(r); }) .catch(e => { if (e instanceof VKApiError_1.default) { /** * 6 - too many requests per second * 10 - internal server error */ if (e.errorCode == 6 || e.errorCode == 10) { setTimeout(() => { makeCall(resolve, reject, method, token, params, useQueue); }, 300); } reject(e); } else { /** * Networking error */ setTimeout(() => { makeCall(resolve, reject, method, token, params, useQueue); }, 300); } }); }; makeCall(resolve, reject, method, token, params, useQueue); }); }); } getGroupMembers(groupId, token) { return __awaiter(this, void 0, void 0, function* () { let users = []; let offset = 0; let code = this.generateGetGroupMembersCode(groupId, offset); let response = yield this.callWithRetry('execute', token, { code }); let usersCount = response.response.count; users.push(...response.response.items); let reqsCount = Math.floor(usersCount / (1000 * 25)); offset = 1000 * 25; for (let i = 0; i <= reqsCount; i++) { let resp = yield this.callWithRetry('execute', token, { code: this.generateGetGroupMembersCode(groupId, offset) }); users.push(...resp.response.items); offset += 1000 * 25; } return users; }); } getQueueForGroup(token) { if (!this._queues.has(token)) this._queues.set(token, new CallbackQueue_1.default(REQUESTS_PER_SECOND)); return this._queues.get(token); } generateGetGroupMembersCode(groupId, offset) { return ` var Data = []; var group_id = ${groupId}; var i = 0; var offset = ${offset}; while(true){ var response = API.groups.getMembers({"offset": offset ,"group_id": group_id, "count":"1000"}); Data = Data + (response.items); i = i+1; offset = offset + 1000; if(i == 25){ return { count: response.count, items: Data }; } } `; } getGroupPosts(groupId, token) { return __awaiter(this, void 0, void 0, function* () { let code = ` var Data = []; var group_id = ${groupId * -1}; var i = 0; var offset = 0; while(true){ var response = API.wall.get({"offset": offset ,"owner_id": group_id, "count":"100"}); Data = Data + (response.items); i = i+1; offset = offset + 100; if(i == 25){ return { count: response.count, items: Data }; } } `; //console.log(code) let posts = yield this.call('execute', '434910c8434910c8434910c8d04313884c44349434910c81babcebd9850569337cb4498', { code }); //console.log(posts) return [1]; }); } } exports.default = VKApi; //# sourceMappingURL=VKApi.js.map