UNPKG

@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
"use strict"; 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;