1 | const fs = require('fs');
|
2 | const qs = require('querystring');
|
3 | const axios = require('axios');
|
4 | const FormData = require('form-data');
|
5 |
|
6 | const Keyboard = require('./interfaces/keyboard');
|
7 | const Attachment = require('./interfaces/attachment');
|
8 |
|
9 | const { ApiError, UploadError, TypeError, NotImplementedError } = require('./exceptions');
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | class VkBotSdkClient {
|
17 | |
18 |
|
19 |
|
20 |
|
21 | constructor(options) {
|
22 | this.options = {
|
23 | v: '5.107',
|
24 | lang: 'ru',
|
25 | debug: true,
|
26 | group_id: 0,
|
27 | secret: '',
|
28 | confirmation: '',
|
29 | access_token: ''
|
30 | };
|
31 |
|
32 | if(!options.access_token) {
|
33 | throw new NotImplementedError('options.access_token is required');
|
34 | }
|
35 |
|
36 | if('v' in options) this.options.v = options.v;
|
37 | if('lang' in options) this.options.lang = options.lang;
|
38 | if('debug' in options) this.options.debug = options.debug;
|
39 | if('group_id' in options) this.options.group_id = options.group_id;
|
40 | if('secret' in options) this.options.secret = options.secret;
|
41 | if('confirmation' in options) this.options.confirmation = options.confirmation;
|
42 | if('access_token' in options) this.options.access_token = options.access_token;
|
43 |
|
44 | this.client = axios.create({
|
45 | baseURL: 'https://api.vk.com/method/'
|
46 | });
|
47 | }
|
48 |
|
49 | |
50 |
|
51 |
|
52 | debug(...args) {
|
53 | if(this.options.debug) console.log('[sdk]', ...args);
|
54 | }
|
55 |
|
56 | |
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | async get(url, params) {
|
63 | const result = await axios.get(url, {
|
64 | headers: {},
|
65 | params: params
|
66 | });
|
67 |
|
68 | return result.data;
|
69 | }
|
70 |
|
71 | |
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | async request(method, params) {
|
79 | if(!params.v) params.v = this.options.v;
|
80 | if(!params.lang) params.lang = this.options.lang;
|
81 | if(!params.access_token) params.access_token = this.options.access_token;
|
82 |
|
83 | try {
|
84 | const result = await this.client.post(method, qs.encode(params), {
|
85 | headers: { 'content-type': 'application/x-www-form-urlencoded' }
|
86 | });
|
87 |
|
88 | if('error' in result.data) {
|
89 | throw new ApiError(
|
90 | result.data['error']['error_code'],
|
91 | result.data['error']['error_msg'],
|
92 | result.data['error']['request_params'],
|
93 | )
|
94 | }
|
95 |
|
96 | return result.data['response'];
|
97 | }
|
98 | catch (e) {
|
99 | if(this.options.debug) console.error('[sdk]', e);
|
100 |
|
101 | throw new ApiError(0, 'Unknown error', []);
|
102 | }
|
103 | }
|
104 |
|
105 | |
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 | async uploadFile(url, file, key, filename) {
|
114 | if(typeof file === 'string') {
|
115 | file = await fs.readFileSync(file);
|
116 | }
|
117 |
|
118 | const formData = new FormData();
|
119 |
|
120 | formData.append(key, file, {
|
121 | filename: filename
|
122 | });
|
123 |
|
124 | const result = await axios.post(url, formData, {
|
125 | headers: {
|
126 | 'content-type': 'multipart/form-data',
|
127 | ...formData.getHeaders()
|
128 | }
|
129 | });
|
130 |
|
131 | if(typeof result.data === 'string') {
|
132 | throw new UploadError(result.data);
|
133 | }
|
134 |
|
135 | return result.data;
|
136 | }
|
137 |
|
138 | |
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 | sendMessage() {
|
149 | let args = Array.from(arguments);
|
150 | let params = { random_id: 0 };
|
151 |
|
152 | let peer, text, attachment, keyboard, props = {};
|
153 |
|
154 | |
155 |
|
156 |
|
157 | if(args.length < 1) throw new TypeError('Invalid arguments count');
|
158 |
|
159 | if(typeof args[0] === 'object') {
|
160 | const object = args[0];
|
161 |
|
162 | if('peer_id' in object) peer = object['peer_id'];
|
163 | else if('peer_ids' in object) peer = args['peer_ids'];
|
164 | else if('user_id' in object) peer = args['user_id'];
|
165 | else if('user_ids' in object) peer = args['user_ids'];
|
166 |
|
167 | if('text' in object) text = object['text'];
|
168 | if('attachment' in object) attachment = object['attachment'];
|
169 | if('keyboard' in object) keyboard = object['keyboard'];
|
170 | if('params' in object) props = object['params'];
|
171 | }
|
172 | else {
|
173 | if(args[0]) peer = args[0];
|
174 | if(args[1]) text = args[1];
|
175 | if(args[2]) attachment = args[2];
|
176 | if(args[3]) keyboard = args[3];
|
177 | if(args[4]) props = args[4];
|
178 | }
|
179 |
|
180 | |
181 |
|
182 |
|
183 | if(text !== undefined && text.length > 0) params.message = text;
|
184 |
|
185 | if(peer !== undefined && Array.isArray(peer)) params.peer_ids = peer.join(',');
|
186 | else params.peer_id = peer;
|
187 |
|
188 | if(attachment !== undefined) {
|
189 | const attachmentList = Array.isArray(attachment) ? attachment : [attachment];
|
190 | const attachmentListResult = [];
|
191 |
|
192 | for (let item of attachmentList) {
|
193 | if(typeof item === 'string') attachmentListResult.push(item);
|
194 | else if(item instanceof Attachment) attachmentList.push(item.toString());
|
195 | else throw new TypeError('Invalid attachment type');
|
196 | }
|
197 |
|
198 | params.attachment = attachmentListResult.join(',');
|
199 | }
|
200 |
|
201 | if(keyboard !== undefined) {
|
202 | if(keyboard instanceof Keyboard) params.keyboard = keyboard.formatToJSON();
|
203 | else throw new TypeError('Invalid keyboard type');
|
204 | }
|
205 |
|
206 | |
207 |
|
208 |
|
209 | const propsKeys = Object.keys(props);
|
210 |
|
211 | if(propsKeys.length > 0) {
|
212 | for (let key of propsKeys) params[key] = props[key];
|
213 | }
|
214 |
|
215 | return this.request('messages.send', params);
|
216 | }
|
217 | }
|
218 |
|
219 | module.exports = VkBotSdkClient;
|