cactive
Version:
Link in to the vast and epic CactiveNetwork ecosystem.
300 lines • 10.8 kB
JavaScript
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
;