UNPKG

homebridge-bold

Version:
157 lines (156 loc) 8.08 kB
"use strict"; 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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BoldAPI = void 0; const axios_1 = __importDefault(require("axios")); const form_data_1 = __importDefault(require("form-data")); const const_1 = require("./const"); class BoldAPI { constructor(config, log) { this.config = config; this.log = log; } request(method, endpoint, body = undefined, headers = undefined) { var _a, _b, _c; return __awaiter(this, void 0, void 0, function* () { try { let response = yield axios_1.default.request({ method: method, url: `https://api.boldsmartlock.com${endpoint}`, headers: Object.assign(Object.assign({ 'Authorization': `Bearer ${this.config.accessToken}` }, (!Object.keys(headers || {}).some((header) => header.toLowerCase() == 'content-type') && { 'Content-Type': 'application/json' })), headers), data: body }); if ((response.data.errorCode != null && response.data.errorCode != 'OK') && (response.data.errorMessage != null && response.data.errorMessage != 'OK')) { return { success: false, error: { code: response.data.errorCode, message: response.data.errorMessage } }; } return { success: true, data: response.data }; } catch (error) { if (axios_1.default.isAxiosError(error)) { let axiosError = error; return { success: false, error: { code: ((_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.data.errorCode) || ((_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.status) || axiosError.code, message: ((_c = axiosError.response) === null || _c === void 0 ? void 0 : _c.data.errorMessage) || `${axiosError}` } }; } else { return { success: false, error: { message: `${error}` } }; } } }); } getDevices() { return __awaiter(this, void 0, void 0, function* () { this.log.debug('Getting all devices'); let response = yield this.request('GET', '/v1/effective-device-permissions'); if (!response.success) { throw new Error(`Error ${response.error.code ? `(${response.error.code}) ` : ''}while getting devices: ${response.error.message}`); } if (Array.isArray(response.data)) { let devices = response.data; let supportedDevices = devices.filter((device) => device.id != null && device.name && device.featureSet.isActivatable && device.gateway != null); this.log.debug(`Total device count: ${devices.length}, Supported device count: ${supportedDevices.length}`); return supportedDevices; } else { throw new Error('Unknown reponse while getting devices: ${response.data}'); } }); } activate(deviceId, hasRefreshedToken = false) { return __awaiter(this, void 0, void 0, function* () { this.log.debug(`Activating device (${deviceId})`); let response = yield this.request('POST', `/v1/devices/${deviceId}/remote-activation`); if (!response.success && response.error.code == 401 && !hasRefreshedToken) { // If HTTP 401, try token refresh this.log.warn(`Error while activating device (${deviceId}). Refreshing token and retrying.`); yield this.refresh(); let result = yield this.activate(deviceId, true); if (!result) { this.log.error('Activation failed even after token refresh. Try logging in again. If this problem persists, open an issue.'); } return result; } else if (!response.success) { this.log.error(`Error ${response.error.code ? `(${response.error.code}) ` : ''}while activating device (${deviceId}): ${response.error.message}`); return false; } this.log.debug(`Successfully activated device (${deviceId})`); return true; }); } refresh() { var _a, _b, _c, _d; return __awaiter(this, void 0, void 0, function* () { this.log.debug('Refreshing access token'); if (this.config.legacyAuthentication) { return yield this.refreshLegacy(); } try { let response = yield axios_1.default.post(this.config.refreshURL || const_1.REFRESH_URL, { refreshToken: this.config.refreshToken }); let { accessToken, refreshToken } = response.data.data; if (!accessToken || !refreshToken) { this.log.error(`Missing access or refresh token: ${JSON.stringify(response.data)}`); return; } this.log.debug('Successfully refreshed access token'); return { accessToken, refreshToken }; } catch (error) { if (axios_1.default.isAxiosError(error)) { let axiosError = error; this.log.error(`Error (${(_a = error.response) === null || _a === void 0 ? void 0 : _a.status}) while refreshing token: ${((_d = (_c = (_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) === null || _d === void 0 ? void 0 : _d.message) || error}`); } else { this.log.error(`Error while refreshing access token: ${error}`); } } }); } refreshLegacy() { return __awaiter(this, void 0, void 0, function* () { let formData = new form_data_1.default(); formData.append('client_id', const_1.LEGACY_CLIENT_ID); formData.append('client_secret', const_1.LEGACY_CLIENT_SECRET); formData.append('refresh_token', this.config.refreshToken); formData.append('grant_type', 'refresh_token'); let response = yield this.request('POST', '/v2/oauth/token', formData, formData.getHeaders()); if (!response.success) { this.log.error(`Error ${response.error.code ? `(${response.error.code}) ` : ''}while refreshing token: ${response.error.message}`); return; } let data = response.data; this.log.debug('Successfully refreshed access token'); return { accessToken: data.access_token, refreshToken: data.refresh_token }; }); } } exports.BoldAPI = BoldAPI;