UNPKG

node-vk-api-bot

Version:

A library that helps you to create chat-bot for group or user

286 lines (285 loc) 14.4 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 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) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _Bot_token, _Bot_Emitter, _Bot_longPollAbortController, _Bot_stop; import request from './request.js'; import { EventEmitter } from 'events'; import Methods from './methods.js'; import { GroupUpdates } from './group-updates.js'; var _; (function (_) { function getTypedObjectEntries(obj) { return Object.entries(obj); } _.getTypedObjectEntries = getTypedObjectEntries; })(_ || (_ = {})); var Entries = _.getTypedObjectEntries; import { UserUpdates } from './user-updates.js'; class MethodResponse { constructor(data) { this.response = null; this.error = null; if ('response' in data) { this.response = data.response; } else { this.error = data.error; } } /** * Calls callback function if response state is not error * @returns reference to response so you can chain `ifError` and `ifResponse` * ```js * new Bot().method().then(data => data.ifError((e) => console.error(e)).ifResponse((r) => {})); * ``` */ ifResponse(cb) { if (this.response && !this.error) cb(this.response); return this; } /** * Calls callback function if response state is error * @returns reference to response so you can chain `ifError` and `ifResponse` * ```js * new Bot().method().then(data => data.ifError((e) => console.error(e)).ifResponse((r) => {})); * ``` */ ifError(cb) { if (this.error && !this.response) cb(this.error); return this; } } class Bot { constructor(options) { _Bot_token.set(this, void 0); _Bot_Emitter.set(this, new EventEmitter()); _Bot_longPollAbortController.set(this, null); _Bot_stop.set(this, false); this.v = 5.131; this.on = this.addEventListener; const { token, type, group_id, } = options; __classPrivateFieldSet(this, _Bot_token, token !== null && token !== void 0 ? token : (() => { throw new TypeError('Token is undefined or null'); })(), "f"); this.type = ['group', 'user'].includes(type) ? type : (t => { throw new TypeError(`"Type" property must be "group" or "user", but it is "${t}"`); })(type); this.group_id = group_id !== null && group_id !== void 0 ? group_id : (id => { if (type === 'group' && !id) throw new TypeError('"group_id" must exist in group bot'); return null; })(group_id); } /** * Add a listener to event * * If added a listener to `any` event, no one typed event is more returned * * If event type is `raw` (for user long poll) adding of listeners for not-`raw` version is ignored * @param event Event name * @param listener callback function * @returns reference to `this` */ addEventListener(event, listener) { __classPrivateFieldGet(this, _Bot_Emitter, "f").addListener(event, listener); return this; } static method(options, cb) { const { method, token, params } = options; const url = new URL(`https://api.vk.com/method/${method}`); [...Entries((params !== null && params !== void 0 ? params : {})), ['access_token', token], ['v', 5.131]].forEach(([key, prop]) => { url.searchParams.append(key.toString(), prop.toString()); }); const data = request(url, { method: 'GET', keepalive: false, }).then(data => new MethodResponse(data)); if (typeof cb === 'function') { data.then(cb); return; } return data; } method(options, cb) { const { method, params, overrideToken } = options; const data = Bot.method({ method, params: params, token: overrideToken !== null && overrideToken !== void 0 ? overrideToken : __classPrivateFieldGet(this, _Bot_token, "f"), }); if (typeof cb === 'function') { data.then(cb); return; } return data; } startPolling(optionsOrCb, cb) { var _a, _b, _c, _d; return __awaiter(this, void 0, void 0, function* () { let isUsedCb = false; const options = typeof optionsOrCb === 'object' ? optionsOrCb : { wait: 25, mode: 0, returnRawData: false, }; const { wait = 25, } = options; const callback = typeof optionsOrCb === 'function' ? optionsOrCb : typeof cb === 'function' ? cb : () => void 0; if (wait > 90 || wait < 0) throw new RangeError('"wait" must be more than 0 and less than 90 (0 < wait < 90)'); __classPrivateFieldSet(this, _Bot_stop, false, "f"); const connectionData /* { [T in keyof Methods.MethodResponse[Methods.Groups.getLongPollServer]]: Methods.MethodResponse[Methods.Groups.getLongPollServer][T] | null; } */ = { key: null, server: null, ts: null }; const setConnectionData = (data) => { const { key, server, ts } = data; connectionData.key = key; connectionData.server = server; connectionData.ts = ts; }; const isGroupBot = (bot) => bot.type === 'group'; const isUserBot = (bot) => bot.type === 'user'; // Outer loop // Getting data for connection to longpoll server while (!__classPrivateFieldGet(this, _Bot_stop, "f")) { if (isGroupBot(this)) { (yield (this /* as Bot<'group'> */).method({ method: Methods.Groups.getLongPollServer, params: { group_id: (_a = this.group_id) !== null && _a !== void 0 ? _a : (() => { throw new TypeError('group_id is null or undefined'); })(), } })).ifError(e => console.error(e)) .ifResponse((d) => { setConnectionData(d); !isUsedCb && (isUsedCb = true) && (callback === null || callback === void 0 ? void 0 : callback()); }); // Inner loop // Get updates while connection data is valid while (!__classPrivateFieldGet(this, _Bot_stop, "f")) { const { key, server, ts } = connectionData; const ac = new AbortController(); __classPrivateFieldSet(this, _Bot_longPollAbortController, ac, "f"); const updates = yield request(`${server}?act=a_check&key=${key}&ts=${ts}&wait=${wait}`, { method: 'GET', signal: ac.signal, }); if ('failed' in updates) { if (updates.failed === 1) { connectionData.ts = updates.ts; continue; } break; } connectionData.ts = updates.ts; updates.updates.forEach(update => { if (!__classPrivateFieldGet(this, _Bot_Emitter, "f").emit('any', update)) __classPrivateFieldGet(this, _Bot_Emitter, "f").emit(update.type, update); }); } } else if (isUserBot(this)) { const mode_enum = UserUpdates.LongPollMode; const { mode = { attachment: false, extraEvents: false, return$extraInEvent8: false, returnPTS: false, returnRandomId: false, }, } = typeof options.mode === 'number' ? { mode: (m => ({ attachment: !!(m & mode_enum.attachment), extraEvents: !!(m & mode_enum.extraEvents), return$extraInEvent8: !!(m & mode_enum.return$extraInEvent8), returnPTS: !!(m & mode_enum.returnPTS), returnRandomId: !!(m & mode_enum.returnRandomId), }))(options.mode), } : options; const mode_num = typeof options.mode === 'number' ? options.mode : (m => { return Object.entries(m).reduce((res, curr) => { if (!curr || !curr[0]) throw new TypeError(); return res | mode_enum[curr[0]]; }, 0); })(mode); while (!__classPrivateFieldGet(this, _Bot_stop, "f")) { const connData = yield (this /* as Bot<'user'> */).method({ method: Methods.Messages.getLongPollServer, params: { need_pts: (+((_b = mode.returnPTS) !== null && _b !== void 0 ? _b : 0)), lp_version: 3 } }); connData.ifError(e => { throw new Error(e.error_msg); }).ifResponse(data => { setConnectionData(data); }); while (!__classPrivateFieldGet(this, _Bot_stop, "f")) { const updates = yield request(`https://${connectionData.server}?act=a_check&key=${connectionData.key}&ts=${connectionData.ts}&wait=${wait}&mode=${mode_num}&version=3`, { method: 'GET', signal: (_d = (_c = __classPrivateFieldGet(this, _Bot_longPollAbortController, "f")) === null || _c === void 0 ? void 0 : _c.signal) !== null && _d !== void 0 ? _d : null }); if ('failed' in updates) { const { failed } = updates; if (failed === 1) { connectionData.ts = updates.ts.toString(); continue; } if (failed === 4) throw new RangeError(`Version must be more than ${updates.min_version} and less than ${updates.max_version}`); break; } connectionData.ts = updates.ts.toString(); updates.updates.forEach(update => { var _a; if (!__classPrivateFieldGet(this, _Bot_Emitter, "f").emit('any_raw', update)) if (!__classPrivateFieldGet(this, _Bot_Emitter, "f").emit(UserUpdates.UpdateTypes[(_a = UserUpdates.RawUpdateTypes[update[0]]) !== null && _a !== void 0 ? _a : 'unknown_event'], update)) { const parsed = UserUpdates.parseRawUpdate(update); if (!__classPrivateFieldGet(this, _Bot_Emitter, "f").emit('any', parsed)) { __classPrivateFieldGet(this, _Bot_Emitter, "f").emit(parsed.type, parsed); } } }); } } } } }); } /** * Stops current LongPoll request * @returns `true` if polling has been stopped otherwise `false` */ stopPolling(cb) { __classPrivateFieldSet(this, _Bot_stop, true, "f"); if (!__classPrivateFieldGet(this, _Bot_longPollAbortController, "f")) return (cb === null || cb === void 0 ? void 0 : cb(), false); __classPrivateFieldGet(this, _Bot_longPollAbortController, "f").abort(); __classPrivateFieldSet(this, _Bot_longPollAbortController, null, "f"); typeof cb === 'function' && cb(); return true; } } _Bot_token = new WeakMap(), _Bot_Emitter = new WeakMap(), _Bot_longPollAbortController = new WeakMap(), _Bot_stop = new WeakMap(); export { Methods, GroupUpdates, UserUpdates, }; export default Bot;