1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const path_1 = require("path");
|
4 | const fs = require("fs");
|
5 | const os_1 = require("os");
|
6 | const axios_1 = require("axios");
|
7 | const colors = require("colors");
|
8 | const FormData = require('form-data');
|
9 | const util = require('util');
|
10 | const exec = util.promisify(require('child_process').exec);
|
11 | const { hashElement } = require('folder-hash');
|
12 | const ora = require('ora');
|
13 | const BOTONIC_CLIENT_ID = process.env.BOTONIC_CLIENT_ID || 'jOIYDdvcfwqwSs7ZJ1CpmTKcE7UDapZDOSobFmEp';
|
14 | const BOTONIC_CLIENT_SECRET = process.env.BOTONIC_CLIENT_SECRET ||
|
15 | 'YY34FaaNMnIVKztd6LbLIKn3wFqtiLhDgl6ZVyICwsLVWkZN9UzXw0GXFMmWinP3noNGU9Obtb6Nrr1BwMc4IlCTcRDOKJ96JME5N02IGnIY62ZUezMgfeiUZUmMSu68';
|
16 | const BOTONIC_URL = process.env.BOTONIC_URL || 'https://api.hubtype.com';
|
17 | class BotonicAPIService {
|
18 | constructor() {
|
19 | this.cliendId = BOTONIC_CLIENT_ID;
|
20 | this.clientSecret = BOTONIC_CLIENT_SECRET;
|
21 | this.baseUrl = BOTONIC_URL;
|
22 | this.baseApiUrl = this.baseUrl + '/v1/';
|
23 | this.loginUrl = this.baseUrl + '/o/token/';
|
24 | this.botPath = process.cwd();
|
25 | this.botCredentialsPath = path_1.join(this.botPath, '.botonic.json');
|
26 | this.globalConfigPath = path_1.join(os_1.homedir(), '.botonic');
|
27 | this.globalCredentialsPath = path_1.join(this.globalConfigPath, 'credentials.json');
|
28 | this.bot = null;
|
29 | this.headers = null;
|
30 | this.loadGlobalCredentials();
|
31 | this.loadBotCredentials();
|
32 | }
|
33 | beforeExit() {
|
34 | this.saveGlobalCredentials();
|
35 | this.saveBotCredentials();
|
36 | }
|
37 | loadGlobalCredentials() {
|
38 | try {
|
39 | var credentials = JSON.parse(fs.readFileSync(this.globalCredentialsPath, 'utf8'));
|
40 | }
|
41 | catch (e) { }
|
42 | if (credentials) {
|
43 | this.oauth = credentials.oauth;
|
44 | this.me = credentials.me;
|
45 | this.analytics = credentials.analytics;
|
46 | if (credentials.oauth)
|
47 | this.headers = {
|
48 | Authorization: `Bearer ${this.oauth.access_token}`,
|
49 | 'content-type': 'application/json',
|
50 | 'x-segment-anonymous-id': this.analytics.anonymous_id
|
51 | };
|
52 | }
|
53 | }
|
54 | loadBotCredentials() {
|
55 | try {
|
56 | var credentials = JSON.parse(fs.readFileSync(this.botCredentialsPath, 'utf8'));
|
57 | }
|
58 | catch (e) { }
|
59 | if (credentials) {
|
60 | if (credentials.hasOwnProperty('bot')) {
|
61 | this.bot = credentials.bot;
|
62 | this.lastBuildHash = credentials.lastBuildHash;
|
63 | }
|
64 | else {
|
65 |
|
66 | this.bot = credentials;
|
67 | this.lastBuildHash = '';
|
68 | }
|
69 | }
|
70 | }
|
71 | async checkGlobalCredentialsPath() {
|
72 | if (!fs.existsSync(this.globalConfigPath))
|
73 | fs.mkdirSync(this.globalConfigPath);
|
74 | }
|
75 | async saveGlobalCredentials() {
|
76 | await this.checkGlobalCredentialsPath();
|
77 | fs.writeFileSync(this.globalCredentialsPath, JSON.stringify({
|
78 | oauth: this.oauth,
|
79 | me: this.me,
|
80 | analytics: this.analytics
|
81 | }));
|
82 | }
|
83 | saveBotCredentials() {
|
84 | let bc = { bot: this.bot, lastBuildHash: this.lastBuildHash };
|
85 | fs.writeFileSync(this.botCredentialsPath, JSON.stringify(bc));
|
86 | }
|
87 | async getCurrentBuildHash() {
|
88 | const options = {
|
89 | folders: { exclude: ['.*', 'node_modules', 'dist'] },
|
90 | files: {
|
91 | include: [
|
92 | '*.js',
|
93 | '*.jsx',
|
94 | '*.ts',
|
95 | '*.tsx',
|
96 | '*.css',
|
97 | '*.scss',
|
98 | 'webpack.config.js',
|
99 | '.babelrc',
|
100 | 'tsconfig.json'
|
101 | ]
|
102 | }
|
103 | };
|
104 | let hash = await hashElement('.', options);
|
105 | return hash.hash;
|
106 | }
|
107 | async build(npmCommand = 'build') {
|
108 | let spinner = new ora({
|
109 | text: 'Building...',
|
110 | spinner: 'bouncingBar'
|
111 | }).start();
|
112 | try {
|
113 | var build_out = await exec(`npm run ${npmCommand}`);
|
114 | }
|
115 | catch (error) {
|
116 | spinner.fail();
|
117 | console.log(`${error.stdout}` + colors.red(`\n\nBuild error:\n${error}`));
|
118 | return false;
|
119 | }
|
120 | spinner.succeed();
|
121 | return true;
|
122 | }
|
123 | async buildIfChanged(force, npmCommand) {
|
124 | let hash = await this.getCurrentBuildHash();
|
125 | if (force || hash != this.lastBuildHash) {
|
126 | this.lastBuildHash = hash;
|
127 | return await this.build(npmCommand);
|
128 | }
|
129 | return true;
|
130 | }
|
131 | setCurrentBot(bot) {
|
132 | this.bot = bot;
|
133 | }
|
134 | logout() {
|
135 | if (fs.existsSync(this.globalCredentialsPath))
|
136 | fs.unlinkSync(this.globalCredentialsPath);
|
137 | }
|
138 | async api(path, body = null, method = 'get', headers = null, params = null) {
|
139 | var b = 0;
|
140 | try {
|
141 | return await axios_1.default({
|
142 | method: method,
|
143 | url: this.baseApiUrl + path,
|
144 | headers: headers || this.headers,
|
145 | data: body,
|
146 | params: params
|
147 | });
|
148 | }
|
149 | catch (e) {
|
150 | if (e.response.status == 401) {
|
151 | b = 1;
|
152 | }
|
153 | else {
|
154 | return e;
|
155 | }
|
156 | }
|
157 | if (b == 1) {
|
158 | await this.refreshToken();
|
159 | }
|
160 | return await axios_1.default({
|
161 | method: method,
|
162 | url: this.baseApiUrl + path,
|
163 | headers: headers || this.headers,
|
164 | data: body,
|
165 | params: params
|
166 | });
|
167 | }
|
168 | async refreshToken() {
|
169 | let resp = await axios_1.default({
|
170 | method: 'post',
|
171 | url: this.loginUrl,
|
172 | params: {
|
173 | callback: 'none',
|
174 | grant_type: 'refresh_token',
|
175 | refresh_token: this.oauth.refresh_token,
|
176 | client_id: this.cliendId,
|
177 | client_secret: this.clientSecret
|
178 | }
|
179 | });
|
180 | if (!resp)
|
181 | return;
|
182 | this.oauth = resp.data;
|
183 | this.headers = {
|
184 | Authorization: `Bearer ${this.oauth.access_token}`,
|
185 | 'content-type': 'application/json',
|
186 | 'x-segment-anonymous-id': this.analytics.anonymous_id
|
187 | };
|
188 | await this.saveGlobalCredentials();
|
189 | return resp;
|
190 | }
|
191 | async login(email, password) {
|
192 | let resp = await axios_1.default({
|
193 | method: 'post',
|
194 | url: this.loginUrl,
|
195 | params: {
|
196 | username: email,
|
197 | password: password,
|
198 | client_id: this.cliendId,
|
199 | client_secret: this.clientSecret,
|
200 | grant_type: 'password'
|
201 | }
|
202 | });
|
203 | this.oauth = resp.data;
|
204 | this.headers = {
|
205 | Authorization: `Bearer ${this.oauth.access_token}`,
|
206 | 'content-type': 'application/json',
|
207 | 'x-segment-anonymous-id': this.analytics.anonymous_id
|
208 | };
|
209 | resp = await this.api('users/me');
|
210 | if (resp)
|
211 | this.me = resp.data;
|
212 | return resp;
|
213 | }
|
214 | signup(email, password, org_name, campaign) {
|
215 | let url = `${this.baseApiUrl}users/`;
|
216 | let signup_data = { email, password, org_name, campaign };
|
217 | return axios_1.default({ method: 'post', url: url, data: signup_data });
|
218 | }
|
219 | async saveBot(bot_name) {
|
220 | let resp = await this.api('bots/', { name: bot_name, framework: 'framework_botonic' }, 'post');
|
221 | if (resp.data)
|
222 | this.setCurrentBot(resp.data);
|
223 | return resp;
|
224 | }
|
225 | async getMe() {
|
226 | return this.api('users/me/');
|
227 | }
|
228 | async getBots() {
|
229 | return this.api('bots/bots_paginator/', null, 'get', null, {
|
230 | organization_id: this.me.organization_id
|
231 | });
|
232 | }
|
233 | async getMoreBots(bots, nextBots) {
|
234 | if (!nextBots)
|
235 | return bots;
|
236 | let resp = await this.api(nextBots.split(this.baseApiUrl)[1], null, 'get', null);
|
237 | resp.data.results.map(b => bots.push(b));
|
238 | nextBots = resp.data.next;
|
239 | return this.getMoreBots(bots, nextBots);
|
240 | }
|
241 | async getProviders() {
|
242 | return this.api('provider_accounts/', null, 'get', null, {
|
243 | bot_id: this.bot.id
|
244 | });
|
245 | }
|
246 | async deployBot(bundlePath, forceDeploy) {
|
247 | try {
|
248 | let a = await this.getMe();
|
249 | }
|
250 | catch (e) {
|
251 | console.log(`Error deploying: ${e}`);
|
252 | }
|
253 | const form = new FormData();
|
254 | let data = fs.createReadStream(bundlePath);
|
255 | form.append('bundle', data, 'botonic_bundle.zip');
|
256 | let headers = await this.getHeaders(form);
|
257 | return await this.api(`bots/${this.bot.id}/deploy_botonic_new/`, form, 'post', Object.assign(Object.assign({}, this.headers), headers), { forceDeploy: forceDeploy, version: '0.7' });
|
258 | }
|
259 | async deployStatus(deploy_id) {
|
260 | return this.api(`bots/${this.bot.id}/deploy_botonic_status/`, null, 'get', null, { deploy_id });
|
261 | }
|
262 | async getHeaders(form) {
|
263 |
|
264 | return new Promise((resolve, reject) => {
|
265 | form.getLength((err, length) => {
|
266 | if (err) {
|
267 | reject(err);
|
268 | }
|
269 | let headers = Object.assign({ 'Content-Length': length }, form.getHeaders());
|
270 | resolve(headers);
|
271 | });
|
272 | });
|
273 | }
|
274 | }
|
275 | exports.BotonicAPIService = BotonicAPIService;
|
276 |
|
\ | No newline at end of file |