UNPKG

cactive

Version:

Link in to the vast and epic CactiveNetwork ecosystem.

300 lines 10.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Client = void 0; const node_fetch_1 = __importDefault(require("node-fetch")); const error_1 = __importDefault(require("./error")); const user_1 = __importDefault(require("./user")); const ws_1 = __importDefault(require("ws")); const events_1 = __importDefault(require("events")); const crypto_1 = require("crypto"); const Constants = { UUID_REGEX: /^\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b$/ }; class Connections extends events_1.default { /** * Creates a client * @param token Authorization token * @param options Client options */ constructor(token, options = {}) { super(); this._token = token; this._timer = null; this.options = { base_url: options.base_url ?? 'https://api.cactive.network', socket_url: options.socket_url ?? 'wss://api.cactive.network/socket/', verbose: options.verbose ?? false, socket_keepalive: options.socket_keepalive ?? 5 * 1000 }; // Ensure API key works this.getSelf() .catch((err) => { throw err; }); this._socket = new ws_1.default(this.options.socket_url); this._socket_store = {}; this._socket.on('message', (raw) => { if (this.options.verbose) console.log(`[🧦] ${raw}`); try { const { event, data } = JSON.parse(raw); if (!data.identifier) return; if (!this._socket_store[data.identifier]) return; this._socket_store[data.identifier](event, data); } catch (err) { console.warn(`Connections Socket Error: ${err}`); } }); this._socket.once('open', () => this.emit('ready')); this._socket.on('error', (error) => { throw error; }); this._socket.on('close', (r) => { if (this.options.verbose) console.log(`[🧦] Socket Closing: ${r}`); }); this._timer = setInterval(() => { if (this.options.verbose) console.log('[🧦] Socket Keepalive Ping'); this.socketEmit('ping', { identifier: 'ping' }); }, this.options.socket_keepalive); } /** * Makes a request to the API * @param endpoint Endpoint to target * @param method Method to use * @param data Outgoing data * @returns Response promise */ request(endpoint, method, data) { const url = `${this.options.base_url}/${endpoint}`; if (this.options.verbose) console.log(`[📡] ${method} :: ${url}`); return new Promise((resolve, reject) => { let options = { method, headers: { 'Authorization': this._token }, }; if (data) { options['body'] = JSON.stringify(data); options['headers']['Content-Type'] = 'application/json'; } (0, node_fetch_1.default)(url, options) .then(res => { if (res.headers.get('Content-Type')?.includes('application/json')) { res.json() .then((data) => { if (data.error) { return reject(new Error(`Connections API Error: ${data.message ?? 'Unknown Error'}`)); } resolve(data); }) .catch(reject); } else resolve(); }) .catch(reject); }); } /** * Sends an event and data to the server * @param event Event name * @param data Event data */ socketEmit(event, data) { this._socket.send(JSON.stringify({ event, data, authorization: this._token })); } /* ----- OAUTH METHODS FOLLOW -----*/ /** * Fetches a refresh token based on Identification token from an OAuth gateway * @param identifier_token Identifier token provided by the oauth gateway * @param client_id Project Client Id * @param client_secret Project Client Secret * @param redirect_uri Used Redirect URI * @param scopes Used Scopes * @returns Refresh token */ oauthIdentify(identifier_token, client_id, client_secret, redirect_uri, scopes) { return new Promise((resolve, reject) => { this.request(`identify?token=${identifier_token}&client_id=${client_id}&client_secret=${client_secret}&redirect_uri=${redirect_uri}&scope=${scopes.join(',')}`, 'GET') .then(data => { resolve(data.token); }) .catch(reject); }); } /** * Creates an Access Token from a Refresh Token * @param refresh_token Refresh token * @returns Access token */ refreshToken(refresh_token) { return new Promise((resolve, reject) => { this.request(`refresh?token=${refresh_token}`, 'GET') .then(data => { resolve(data.token); }) .catch(reject); }); } getUserByAccessToken(access_token) { return new Promise((resolve, reject) => { this.request(`oauth_user?token=${access_token}`, 'GET') .then(data => { resolve(data); }) .catch(reject); }); } /* ----- API METHODS FOLLOW -----*/ /** * Fetches a User by their ID * @param id User ID * @returns User */ getUser(id) { return new Promise((resolve, reject) => { if (!Constants.UUID_REGEX.test(id)) throw (0, error_1.default)('INVALID_UUID'); this.request(`user/${id}`, 'GET') .then(data => { resolve(new user_1.default(this, data)); }).catch(reject); }); } /** * Changes the instance's display name * @param display_name New display name * @returns Resolution result */ changeName(display_name) { return new Promise((resolve, reject) => { this.request(`display_name?display_name=${encodeURIComponent(display_name)}`, 'PUT') .then(() => resolve()) .catch(reject); }); } /** * Fetches the instance's User object * @returns Own User */ getSelf() { return new Promise((resolve, reject) => { this.request(`self`, 'GET') .then(data => { resolve(new user_1.default(this, data)); }).catch(reject); }); } /** * Updates a User's role * * Requires access to the 'MODIFY_ROLES' permission. * @param target Target User's ID * @param role New role * @returns Updated User */ setRole(target, role) { return new Promise((resolve, reject) => { if (!Constants.UUID_REGEX.test(target)) throw (0, error_1.default)('INVALID_UUID'); this.request(`role?target=${encodeURIComponent(target)}&role=${encodeURIComponent(role)}`, 'PUT') .then(data => { resolve(new user_1.default(this, data)); }).catch(reject); }); } /** * Registers or updates your Service's default data structure * * Requires access to the 'CREATE_SERVICE' permission. * @param name Service name, must be unique * @param structure Default fields for your service * @returns Resolution result */ registerService(name, structure) { return new Promise((resolve, reject) => { this.request(`service`, 'PUT', { name, data: structure }) .then(() => resolve()) .catch(reject); }); } /** * Updates an owned service's data for a user * @param name Service name, must be owned * @param target Target User's ID * @param data Updated service structure * @returns Resolution result */ setService(name, target, data) { if (!Constants.UUID_REGEX.test(target)) throw (0, error_1.default)('INVALID_UUID'); return new Promise((resolve, reject) => { this.request(`service/${encodeURIComponent(name)}?target=${encodeURIComponent(target)}`, 'PUT', data) .then(() => resolve()) .catch(reject); }); } /** * Registers an intent for a user to pay for a service * @param price The price to pay, must be less that 9999 and greater than 0 * @param currency Three digit ISO country code * @param purchase_handler Function to handle payments once made * @returns Promise of Gateway URL */ registerPayment(price, currency, purchase_handler) { return new Promise((resolve, reject) => { let identifier = (0, crypto_1.randomUUID)(); this._socket_store[identifier] = (event, data) => { if (event === 'error') { return reject(data.message); } if (event === 'purchase_registered') { return resolve(data.url); } if (event === 'purchase_complete') { purchase_handler(); delete this._socket_store[identifier]; } }; this.socketEmit('create_purchase', { identifier, price, currency }); }); } /** * Creates a new Project * * Requires access to the 'CREATE_PROJECT' permission. * * Max of 25 * @returns Resolution result */ createProject() { return new Promise((resolve, reject) => { this.request(`PROJECT`, 'PUT') .then(resolve) .catch(reject); }); } /** * Fetches an owned project by ID * @param id Project ID * @returns Project */ fetchProject(id) { return new Promise((resolve, reject) => { if (!Constants.UUID_REGEX.test(id)) throw (0, error_1.default)('INVALID_UUID'); this.request(`project/${id}`, 'GET') .then(data => { resolve(new user_1.default(this, data)); }).catch(reject); }); } } exports.Client = Connections; //# sourceMappingURL=index.js.map