@4players/odin-foundation
Version:
A set of classes defining a standard protocol for messaging and user data built on top of the Odin protocol.
171 lines (170 loc) • 7.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Utilities = void 0;
/**
* A set of utility functions used to serialize and deserialize data.
*/
class Utilities {
/**
* @summary Capitalizes the first letter of a string
* @param string The string to capitalize
*/
static capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
/**
* @summary Converts a string to a base64url string
* @param string The string to convert
*/
static base64url(string) {
return btoa(string).replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');
}
/**
* @summary URL encodes a string
* @param string The string to encode
*/
static urlencode(string) {
return encodeURIComponent(string)
.replace(/['()]/g, escape)
.replace(/\*/g, '%2A')
.replace(/%(?:7C|60|5E)/g, unescape);
}
/**
* @summary Converts a decimal number to a hex string
* @param dec The number to convert to hex string
*/
static dec2hex(dec) {
return dec.toString(16).padStart(2, '0');
}
/**
* Parses a JWT token and returns the payload
* @param token The JWT token to parse
*/
static parseJwt(token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(atob(base64)
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join(''));
return JSON.parse(jsonPayload);
}
/**
* @summary Function to filter out duplicate values in an array
* @param value
* @param index
* @param self
*/
static uniqueFilter(value, index, self) {
return self.indexOf(value) === index;
}
/**
* @summary Parses a string for URLs and returns an array of URLs
* @param text The text to parse
*/
static parseLinks(text) {
var urls = [];
const matches = text.matchAll(/([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi);
for (const match of matches) {
urls.push(match[0]);
}
return urls.filter(this.uniqueFilter);
}
/**
* @summary Builds a chat message from a user and a message transfer message
* @param user The user who sent the message
* @param message The message transfer message
*/
static buildMessage(user, message) {
if (user && message) {
if (message.kind === 'poke' || message.kind === 'message') {
const newMessage = {
fromId: user.id,
fromName: user.name,
fromAvatar: user.avatar,
kind: message.kind,
text: message.payload.text,
urls: this.parseLinks(message.payload.text),
time: new Date()
};
if (message.isPrivate) {
newMessage.isPrivate = message.isPrivate;
}
return newMessage;
}
}
else {
console.warn('Cannot build message, user or message is null', user, message);
}
return null;
}
/**
* @summary Creates a user from user data.
* Deprecated fields are still filled in for backwards compatibility. Use `data` field for storing user data instead.
* @param userData The user data to create a user from
* @param peerId The peer ID of the user
*/
static createUserFromUserData(userData, peerId) {
return {
id: (userData === null || userData === void 0 ? void 0 : userData.id) ? userData.id : '',
name: (userData === null || userData === void 0 ? void 0 : userData.name) ? userData.name : 'Unknown',
avatar: userData === null || userData === void 0 ? void 0 : userData.avatar,
peerId: peerId,
status: (userData === null || userData === void 0 ? void 0 : userData.status) ? userData.status : 'online',
outputMuted: (userData === null || userData === void 0 ? void 0 : userData.outputMuted) ? userData.outputMuted : 0,
inputMuted: 1,
renderer: (userData === null || userData === void 0 ? void 0 : userData.renderer) ? userData.renderer : '',
platform: (userData === null || userData === void 0 ? void 0 : userData.platform) ? userData.platform : '',
revision: (userData === null || userData === void 0 ? void 0 : userData.revision) ? userData.revision : '',
version: (userData === null || userData === void 0 ? void 0 : userData.version) ? userData.version : '',
buildNo: (userData === null || userData === void 0 ? void 0 : userData.buildNo) ? userData.buildNo : 0,
data: userData
};
}
/**
* @summary Creates user data from a user.
* @deprecated Use IUser.data instead of duplicating data all the time back and forth
* @param user The user to create user data from
*/
static userDataFromUser(user) {
const userData = {};
userData.id = (user === null || user === void 0 ? void 0 : user.id) ? user.id : '';
userData.avatar = (user === null || user === void 0 ? void 0 : user.avatar) ? user.avatar : '';
userData.name = (user === null || user === void 0 ? void 0 : user.name) ? user.name : 'Unknown';
userData.status = (user === null || user === void 0 ? void 0 : user.status) ? user.status : 'online';
userData.outputMuted = (user === null || user === void 0 ? void 0 : user.outputMuted) ? user.outputMuted : 0;
userData.renderer = (user === null || user === void 0 ? void 0 : user.renderer) ? user.renderer : '';
userData.revision = (user === null || user === void 0 ? void 0 : user.revision) ? user.revision : '';
userData.version = (user === null || user === void 0 ? void 0 : user.version) ? user.version : '';
userData.platform = (user === null || user === void 0 ? void 0 : user.platform) ? user.platform : '';
userData.buildNo = (user === null || user === void 0 ? void 0 : user.buildNo) ? user.buildNo : 0;
return userData;
}
/**
* @summary Encodes an object to a Uint8Array
* Use this function to encode objects to send them over the network
* @param data The object to encode
*/
static encodeObjToUint8Array(data) {
return new TextEncoder().encode(JSON.stringify(data));
}
/**
* @summary Decodes a Uint8Array to an object
* Use this function to encode objects to send them over the network
* @param data
*/
static decodeUint8ArrayToObject(data) {
if (data.length === 0)
return {};
try {
return JSON.parse(new TextDecoder().decode(data));
}
catch (e) {
console.warn('Error decoding Uint8Array to object:', e, data);
return null;
}
}
}
exports.Utilities = Utilities;