@sawport/peers-caller
Version:
WebRTC multi-peer video call library with mesh architecture supporting up to 4 participants
1,419 lines • 294 kB
JavaScript
var Eo = Object.defineProperty, Ro = Object.defineProperties;
var Po = Object.getOwnPropertyDescriptors;
var et = Object.getOwnPropertySymbols;
var cn = Object.prototype.hasOwnProperty, un = Object.prototype.propertyIsEnumerable;
var ne = Math.pow, mt = (n, e, t) => e in n ? Eo(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t, He = (n, e) => {
for (var t in e || (e = {}))
cn.call(e, t) && mt(n, t, e[t]);
if (et)
for (var t of et(e))
un.call(e, t) && mt(n, t, e[t]);
return n;
}, vt = (n, e) => Ro(n, Po(e));
var bt = (n, e) => {
var t = {};
for (var o in n)
cn.call(n, o) && e.indexOf(o) < 0 && (t[o] = n[o]);
if (n != null && et)
for (var o of et(n))
e.indexOf(o) < 0 && un.call(n, o) && (t[o] = n[o]);
return t;
};
var Ee = (n, e, t) => mt(n, typeof e != "symbol" ? e + "" : e, t);
import { io as Ao } from "socket.io-client";
import { create as To } from "zustand";
import { useState as Ne, useRef as Io, useCallback as be, useEffect as qe } from "react";
var wt = {};
typeof wt == "undefined" ? globalThis.process = {
env: {},
browser: !0,
version: "v18.0.0",
nextTick: (n, ...e) => {
setTimeout(() => n(...e), 0);
}
} : typeof wt.nextTick == "undefined" && (wt.nextTick = (n, ...e) => {
setTimeout(() => n(...e), 0);
});
typeof globalThis == "undefined" && (globalThis.global = globalThis);
var Oo = Object.defineProperty, ko = (n, e, t) => e in n ? Oo(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t, Be = (n, e, t) => ko(n, typeof e != "symbol" ? e + "" : e, t), Ie = (n, e, t) => new Promise((o, l) => {
var c = (f) => {
try {
a(t.next(f));
} catch (u) {
l(u);
}
}, E = (f) => {
try {
a(t.throw(f));
} catch (u) {
l(u);
}
}, a = (f) => f.done ? o(f.value) : Promise.resolve(f.value).then(c, E);
a((t = t.apply(n, e)).next());
});
class Bo {
constructor(e, t, o = "/apis/video-call") {
Be(this, "socket", null), Be(this, "serverUrl"), Be(this, "socketPath"), Be(this, "token"), Be(this, "connected", !1), Be(this, "reconnectAttempts", 0), Be(this, "maxReconnectAttempts", 5), this.serverUrl = e, this.token = t, this.socketPath = o;
}
/**
* Connect to the WebSocket server
*/
connect() {
return Ie(this, null, function* () {
return this.socket && this.socket.connected ? Promise.resolve() : (this.socket && (this.socket.removeAllListeners(), this.socket.disconnect(), this.socket = null), new Promise((e, t) => {
try {
this.socket = Ao(this.serverUrl, {
path: this.socketPath,
transports: ["websocket", "polling"],
timeout: 1e4,
forceNew: !0,
// Prevent connection reuse that might cause duplicates
auth: {
token: this.token
}
}), this.socket.on("connect", () => {
this.connected = !0, this.reconnectAttempts = 0, console.log("[CallSocket] Connected to signaling server"), e();
}), this.socket.on("disconnect", (o) => {
this.connected = !1, console.log("[CallSocket] Disconnected:", o), this.handleDisconnection(o);
}), this.socket.on("connect_error", (o) => {
console.error("[CallSocket] Connection error:", o), this.reconnectAttempts++, this.reconnectAttempts >= this.maxReconnectAttempts && t(
new Error(
`Failed to connect after ${this.maxReconnectAttempts} attempts`
)
);
});
} catch (o) {
t(o);
}
}));
});
}
/**
* Disconnect from the WebSocket server
*/
disconnect() {
this.socket && (this.socket.removeAllListeners(), this.socket.disconnect(), this.socket = null, this.connected = !1);
}
/**
* Check if socket is connected
*/
isConnected() {
var e;
return this.connected && ((e = this.socket) == null ? void 0 : e.connected) === !0;
}
/**
* Emit a signaling event - fire and forget (no response expected)
*/
emit(e, t) {
var o;
if (!this.isConnected())
throw new Error("Socket not connected");
console.log(`[CallSocket] Emitting ${e}:`, t), (o = this.socket) == null || o.emit(e, t, (l) => {
l != null && l.error && console.error(`[CallSocket] Error in ${e}:`, l.error);
});
}
/**
* Emit a signaling event and wait for response
*/
emitWithResponse(e, t, o = 1e4) {
return Ie(this, null, function* () {
if (!this.isConnected())
throw new Error("Socket not connected");
return console.log(`[CallSocket] Emitting ${e} with response:`, t), new Promise((l, c) => {
var E;
const a = setTimeout(() => {
c(new Error(`Timeout waiting for response to ${e}`));
}, o);
console.log(`[CallSocket] about to emit: ${e}...`), (E = this.socket) == null || E.emit(e, t, (f) => {
clearTimeout(a), f != null && f.error ? (console.error(`[CallSocket] Error in ${e}:`, f.error), c(new Error(f.error))) : (console.log(`[CallSocket] Response for ${e}:`, f), l(f));
});
});
});
}
/**
* Listen for an incoming signaling event (from server)
*/
on(e, t) {
if (!this.socket)
throw new Error("Socket not connected");
this.socket.on(e, t);
}
/**
* Remove an incoming signaling event listener
*/
off(e, t) {
this.socket && (t ? this.socket.off(e, t) : this.socket.removeAllListeners(e));
}
/**
* Start a new call
*/
startCall(e, t) {
return Ie(this, null, function* () {
return this.emitWithResponse("call.start", { conversationId: e, userId: t });
});
}
/**
* Join a call room for signaling
*/
joinRoom(e, t) {
return Ie(this, null, function* () {
return this.emitWithResponse("call.join", { conversationId: e, userId: t });
});
}
/**
* Leave a call
*/
leaveCall(e, t) {
return Ie(this, null, function* () {
return this.emitWithResponse("call.leave", { conversationId: e, userId: t });
});
}
/**
* Send WebRTC offer
*/
sendOffer(e, t, o, l) {
this.emit("call.offer", { to: e, from: t, offer: o, conversationId: l });
}
/**
* Send WebRTC answer
*/
sendAnswer(e, t, o, l) {
this.emit("call.answer", { to: e, from: t, answer: o, conversationId: l });
}
/**
* Send ICE candidate
*/
sendCandidate(e, t, o, l) {
this.emit("call.candidate", { to: e, from: t, candidate: o, conversationId: l });
}
/**
* Send participant state update
*/
sendStateUpdate(e, t, o, l) {
this.emit("call.state", { to: e, from: t, state: o, conversationId: l });
}
/**
* End call for specific participant (legacy method)
*/
endCall(e, t, o) {
this.emit("call.end", { conversationId: o, targetUserId: e });
}
/**
* End call for all participants
*/
endCallForAll(e) {
return Ie(this, null, function* () {
this.emit("call.end", { conversationId: e });
});
}
/**
* Start recording
*/
startRecording(e, t) {
return Ie(this, null, function* () {
return this.emitWithResponse("call.recording.start", {
conversationId: e,
recordingId: t
});
});
}
/**
* Send recording chunk
*/
sendRecordingChunk(e, t, o) {
this.emit("call.recording.chunk", { conversationId: e, recordingId: t, chunk: o });
}
/**
* End recording
*/
endRecording(e, t) {
return Ie(this, null, function* () {
return this.emitWithResponse("call.recording.end", {
conversationId: e,
recordingId: t
});
});
}
/**
* Send transcript
*/
sendTranscript(e, t, o) {
this.emit("call.transcript", {
conversationId: e,
userId: t,
transcript: o,
timestamp: Date.now()
});
}
/**
* Check call status
*/
checkCallStatus(e, t) {
return Ie(this, null, function* () {
return this.emitWithResponse("call.status", { conversationId: e, userId: t });
});
}
/**
* Handle disconnection scenarios
*/
handleDisconnection(e) {
[
"transport close",
"transport error",
"io server disconnect"
].includes(e) && this.reconnectAttempts < this.maxReconnectAttempts && setTimeout(() => {
this.connected || (console.log(
`[CallSocket] Attempting to reconnect... (${this.reconnectAttempts + 1}/${this.maxReconnectAttempts})`
), this.connect().catch(console.error));
}, Math.pow(2, this.reconnectAttempts) * 1e3);
}
/**
* Get connection health info
*/
getConnectionInfo() {
var e, t;
return {
connected: this.connected,
socketId: (e = this.socket) == null ? void 0 : e.id,
transport: (t = this.socket) == null ? void 0 : t.io.engine.transport.name,
reconnectAttempts: this.reconnectAttempts
};
}
}
var Mo = Object.defineProperty, Lo = (n, e, t) => e in n ? Mo(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t, tt = (n, e, t) => Lo(n, typeof e != "symbol" ? e + "" : e, t), rt = (n, e, t) => new Promise((o, l) => {
var c = (f) => {
try {
a(t.next(f));
} catch (u) {
l(u);
}
}, E = (f) => {
try {
a(t.throw(f));
} catch (u) {
l(u);
}
}, a = (f) => f.done ? o(f.value) : Promise.resolve(f.value).then(c, E);
a((t = t.apply(n, e)).next());
});
class No {
constructor(e = { video: !0, audio: !0 }) {
tt(this, "stream", null), tt(this, "videoElement", null), tt(this, "constraints"), tt(this, "isScreenShare", !1), this.constraints = e;
}
/**
* Initialize media stream with camera and microphone
*/
initialize() {
return rt(this, null, function* () {
try {
return console.log(
"[CallMediaStream] Initializing media stream with constraints:",
this.constraints
), this.stream = yield navigator.mediaDevices.getUserMedia(this.constraints), console.log("[CallMediaStream] Media stream initialized successfully"), this.stream;
} catch (e) {
throw console.error(
"[CallMediaStream] Failed to initialize media stream:",
e
), this.handleMediaError(e);
}
});
}
/**
* Start screen sharing
*/
startScreenShare() {
return rt(this, arguments, function* (e = { video: !0, audio: !1 }) {
try {
console.log("[CallMediaStream] Starting screen share");
const t = yield navigator.mediaDevices.getDisplayMedia({
video: e.video,
audio: e.audio
}), o = this.stream;
return this.stream = t, this.isScreenShare = !0, t.getVideoTracks()[0].addEventListener("ended", () => {
console.log("[CallMediaStream] Screen share ended by user"), this.stopScreenShare(o);
}), console.log("[CallMediaStream] Screen share started successfully"), t;
} catch (t) {
throw console.error("[CallMediaStream] Failed to start screen share:", t), this.handleMediaError(t);
}
});
}
/**
* Stop screen sharing and revert to camera
*/
stopScreenShare(e) {
return rt(this, null, function* () {
try {
return console.log("[CallMediaStream] Stopping screen share"), this.stream && this.isScreenShare && this.stream.getTracks().forEach((t) => t.stop()), e ? this.stream = e : this.stream = yield this.initialize(), this.isScreenShare = !1, console.log("[CallMediaStream] Reverted to camera stream"), this.stream;
} catch (t) {
throw console.error("[CallMediaStream] Failed to stop screen share:", t), this.handleMediaError(t);
}
});
}
/**
* Toggle audio track
*/
toggleAudio(e) {
if (!this.stream) {
console.warn("[CallMediaStream] No stream available for audio toggle");
return;
}
this.stream.getAudioTracks().forEach((o) => {
o.enabled = e;
}), console.log(`[CallMediaStream] Audio ${e ? "enabled" : "disabled"}`);
}
/**
* Toggle video track
*/
toggleVideo(e) {
if (!this.stream) {
console.warn("[CallMediaStream] No stream available for video toggle");
return;
}
this.stream.getVideoTracks().forEach((o) => {
o.enabled = e;
}), console.log(`[CallMediaStream] Video ${e ? "enabled" : "disabled"}`);
}
/**
* Create and return a video element for displaying the stream
*/
createVideoElement() {
const e = document.createElement("video");
return e.autoplay = !0, e.playsInline = !0, e.muted = !0, this.stream && (e.srcObject = this.stream), this.videoElement = e, e;
}
/**
* Attach stream to an existing video element
*/
attachToVideoElement(e) {
this.stream && (e.srcObject = this.stream, this.videoElement = e);
}
/**
* Replace the current stream (useful for switching between camera and screen)
*/
replaceStream(e) {
this.stream && this.stream.getTracks().forEach((t) => t.stop()), this.stream = e, this.videoElement && (this.videoElement.srcObject = e), console.log("[CallMediaStream] Stream replaced successfully");
}
/**
* Get current stream
*/
getStream() {
return this.stream;
}
/**
* Get video element
*/
getVideoElement() {
return this.videoElement;
}
/**
* Check if current stream is screen share
*/
getIsScreenShare() {
return this.isScreenShare;
}
/**
* Get audio track enabled state
*/
isAudioEnabled() {
if (!this.stream) return !1;
const e = this.stream.getAudioTracks();
return e.length > 0 && e[0].enabled;
}
/**
* Get video track enabled state
*/
isVideoEnabled() {
if (!this.stream) return !1;
const e = this.stream.getVideoTracks();
return e.length > 0 && e[0].enabled;
}
/**
* Get stream information
*/
getStreamInfo() {
if (!this.stream) return null;
const e = this.stream.getVideoTracks(), t = this.stream.getAudioTracks();
return {
id: this.stream.id,
videoTracks: e.length,
audioTracks: t.length,
isScreenShare: this.isScreenShare,
videoEnabled: e.length > 0 ? e[0].enabled : !1,
audioEnabled: t.length > 0 ? t[0].enabled : !1,
videoConstraints: e.length > 0 ? e[0].getSettings() : null,
audioConstraints: t.length > 0 ? t[0].getSettings() : null
};
}
/**
* Stop all tracks and cleanup
*/
cleanup() {
console.log("[CallMediaStream] Cleaning up media stream"), this.stream && (this.stream.getTracks().forEach((e) => {
e.stop();
}), this.stream = null), this.videoElement && (this.videoElement.srcObject = null, this.videoElement = null), this.isScreenShare = !1;
}
/**
* Handle media errors and provide user-friendly messages
*/
handleMediaError(e) {
let t = "Unknown media error";
return e.name === "NotAllowedError" ? t = "Permission denied. Please allow camera and microphone access." : e.name === "NotFoundError" ? t = "No camera or microphone found. Please check your devices." : e.name === "NotReadableError" ? t = "Camera or microphone is already in use by another application." : e.name === "OverconstrainedError" ? t = "Camera or microphone does not support the requested constraints." : e.name === "SecurityError" ? t = "Media access blocked due to security restrictions." : e.name === "AbortError" && (t = "Media access was aborted."), new Error(`${t} (${e.name})`);
}
/**
* Get available media devices
*/
static getAvailableDevices() {
return rt(this, null, function* () {
try {
const e = yield navigator.mediaDevices.enumerateDevices();
return {
videoDevices: e.filter((t) => t.kind === "videoinput"),
audioDevices: e.filter((t) => t.kind === "audioinput")
};
} catch (e) {
throw console.error(
"[CallMediaStream] Failed to get available devices:",
e
), e;
}
});
}
/**
* Check if browser supports required features
*/
static checkBrowserSupport() {
return {
getUserMedia: !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia),
getDisplayMedia: !!(navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia),
webRTC: !!window.RTCPeerConnection
};
}
}
function Zr(n) {
return n && n.__esModule && Object.prototype.hasOwnProperty.call(n, "default") ? n.default : n;
}
var nt = { exports: {} }, _t, fn;
function Do() {
if (fn) return _t;
fn = 1;
var n = 1e3, e = n * 60, t = e * 60, o = t * 24, l = o * 7, c = o * 365.25;
_t = function(w, A) {
A = A || {};
var C = typeof w;
if (C === "string" && w.length > 0)
return E(w);
if (C === "number" && isFinite(w))
return A.long ? f(w) : a(w);
throw new Error(
"val is not a non-empty string or a valid number. val=" + JSON.stringify(w)
);
};
function E(w) {
if (w = String(w), !(w.length > 100)) {
var A = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
w
);
if (A) {
var C = parseFloat(A[1]), j = (A[2] || "ms").toLowerCase();
switch (j) {
case "years":
case "year":
case "yrs":
case "yr":
case "y":
return C * c;
case "weeks":
case "week":
case "w":
return C * l;
case "days":
case "day":
case "d":
return C * o;
case "hours":
case "hour":
case "hrs":
case "hr":
case "h":
return C * t;
case "minutes":
case "minute":
case "mins":
case "min":
case "m":
return C * e;
case "seconds":
case "second":
case "secs":
case "sec":
case "s":
return C * n;
case "milliseconds":
case "millisecond":
case "msecs":
case "msec":
case "ms":
return C;
default:
return;
}
}
}
}
function a(w) {
var A = Math.abs(w);
return A >= o ? Math.round(w / o) + "d" : A >= t ? Math.round(w / t) + "h" : A >= e ? Math.round(w / e) + "m" : A >= n ? Math.round(w / n) + "s" : w + "ms";
}
function f(w) {
var A = Math.abs(w);
return A >= o ? u(w, A, o, "day") : A >= t ? u(w, A, t, "hour") : A >= e ? u(w, A, e, "minute") : A >= n ? u(w, A, n, "second") : w + " ms";
}
function u(w, A, C, j) {
var y = A >= C * 1.5;
return Math.round(w / C) + " " + j + (y ? "s" : "");
}
return _t;
}
var St, dn;
function Fo() {
if (dn) return St;
dn = 1;
function n(e) {
o.debug = o, o.default = o, o.coerce = u, o.disable = a, o.enable = c, o.enabled = f, o.humanize = Do(), o.destroy = w, Object.keys(e).forEach((A) => {
o[A] = e[A];
}), o.names = [], o.skips = [], o.formatters = {};
function t(A) {
let C = 0;
for (let j = 0; j < A.length; j++)
C = (C << 5) - C + A.charCodeAt(j), C |= 0;
return o.colors[Math.abs(C) % o.colors.length];
}
o.selectColor = t;
function o(A) {
let C, j = null, y, I;
function S(...h) {
if (!S.enabled)
return;
const b = S, P = Number(/* @__PURE__ */ new Date()), _ = P - (C || P);
b.diff = _, b.prev = C, b.curr = P, C = P, h[0] = o.coerce(h[0]), typeof h[0] != "string" && h.unshift("%O");
let R = 0;
h[0] = h[0].replace(/%([a-zA-Z%])/g, (g, M) => {
if (g === "%%")
return "%";
R++;
const U = o.formatters[M];
if (typeof U == "function") {
const F = h[R];
g = U.call(b, F), h.splice(R, 1), R--;
}
return g;
}), o.formatArgs.call(b, h), (b.log || o.log).apply(b, h);
}
return S.namespace = A, S.useColors = o.useColors(), S.color = o.selectColor(A), S.extend = l, S.destroy = o.destroy, Object.defineProperty(S, "enabled", {
enumerable: !0,
configurable: !1,
get: () => j !== null ? j : (y !== o.namespaces && (y = o.namespaces, I = o.enabled(A)), I),
set: (h) => {
j = h;
}
}), typeof o.init == "function" && o.init(S), S;
}
function l(A, C) {
const j = o(this.namespace + (typeof C == "undefined" ? ":" : C) + A);
return j.log = this.log, j;
}
function c(A) {
o.save(A), o.namespaces = A, o.names = [], o.skips = [];
const C = (typeof A == "string" ? A : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
for (const j of C)
j[0] === "-" ? o.skips.push(j.slice(1)) : o.names.push(j);
}
function E(A, C) {
let j = 0, y = 0, I = -1, S = 0;
for (; j < A.length; )
if (y < C.length && (C[y] === A[j] || C[y] === "*"))
C[y] === "*" ? (I = y, S = j, y++) : (j++, y++);
else if (I !== -1)
y = I + 1, S++, j = S;
else
return !1;
for (; y < C.length && C[y] === "*"; )
y++;
return y === C.length;
}
function a() {
const A = [
...o.names,
...o.skips.map((C) => "-" + C)
].join(",");
return o.enable(""), A;
}
function f(A) {
for (const C of o.skips)
if (E(A, C))
return !1;
for (const C of o.names)
if (E(A, C))
return !0;
return !1;
}
function u(A) {
return A instanceof Error ? A.stack || A.message : A;
}
function w() {
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
}
return o.enable(o.load()), o;
}
return St = n, St;
}
var hn;
function jo() {
return hn || (hn = 1, function(n, e) {
var t = { env: {} };
e.formatArgs = l, e.save = c, e.load = E, e.useColors = o, e.storage = a(), e.destroy = /* @__PURE__ */ (() => {
let u = !1;
return () => {
u || (u = !0, console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."));
};
})(), e.colors = [
"#0000CC",
"#0000FF",
"#0033CC",
"#0033FF",
"#0066CC",
"#0066FF",
"#0099CC",
"#0099FF",
"#00CC00",
"#00CC33",
"#00CC66",
"#00CC99",
"#00CCCC",
"#00CCFF",
"#3300CC",
"#3300FF",
"#3333CC",
"#3333FF",
"#3366CC",
"#3366FF",
"#3399CC",
"#3399FF",
"#33CC00",
"#33CC33",
"#33CC66",
"#33CC99",
"#33CCCC",
"#33CCFF",
"#6600CC",
"#6600FF",
"#6633CC",
"#6633FF",
"#66CC00",
"#66CC33",
"#9900CC",
"#9900FF",
"#9933CC",
"#9933FF",
"#99CC00",
"#99CC33",
"#CC0000",
"#CC0033",
"#CC0066",
"#CC0099",
"#CC00CC",
"#CC00FF",
"#CC3300",
"#CC3333",
"#CC3366",
"#CC3399",
"#CC33CC",
"#CC33FF",
"#CC6600",
"#CC6633",
"#CC9900",
"#CC9933",
"#CCCC00",
"#CCCC33",
"#FF0000",
"#FF0033",
"#FF0066",
"#FF0099",
"#FF00CC",
"#FF00FF",
"#FF3300",
"#FF3333",
"#FF3366",
"#FF3399",
"#FF33CC",
"#FF33FF",
"#FF6600",
"#FF6633",
"#FF9900",
"#FF9933",
"#FFCC00",
"#FFCC33"
];
function o() {
if (typeof window != "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs))
return !0;
if (typeof navigator != "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))
return !1;
let u;
return typeof document != "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
typeof window != "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
typeof navigator != "undefined" && navigator.userAgent && (u = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(u[1], 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
typeof navigator != "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
}
function l(u) {
if (u[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + u[0] + (this.useColors ? "%c " : " ") + "+" + n.exports.humanize(this.diff), !this.useColors)
return;
const w = "color: " + this.color;
u.splice(1, 0, w, "color: inherit");
let A = 0, C = 0;
u[0].replace(/%[a-zA-Z%]/g, (j) => {
j !== "%%" && (A++, j === "%c" && (C = A));
}), u.splice(C, 0, w);
}
e.log = console.debug || console.log || (() => {
});
function c(u) {
try {
u ? e.storage.setItem("debug", u) : e.storage.removeItem("debug");
} catch (w) {
}
}
function E() {
let u;
try {
u = e.storage.getItem("debug") || e.storage.getItem("DEBUG");
} catch (w) {
}
return !u && typeof t != "undefined" && "env" in t && (u = t.env.DEBUG), u;
}
function a() {
try {
return localStorage;
} catch (u) {
}
}
n.exports = Fo()(e);
const { formatters: f } = n.exports;
f.j = function(u) {
try {
return JSON.stringify(u);
} catch (w) {
return "[UnexpectedJSONParseError]: " + w.message;
}
};
}(nt, nt.exports)), nt.exports;
}
var Ct, pn;
function $o() {
return pn || (pn = 1, Ct = function() {
if (typeof globalThis == "undefined") return null;
var e = {
RTCPeerConnection: globalThis.RTCPeerConnection || globalThis.mozRTCPeerConnection || globalThis.webkitRTCPeerConnection,
RTCSessionDescription: globalThis.RTCSessionDescription || globalThis.mozRTCSessionDescription || globalThis.webkitRTCSessionDescription,
RTCIceCandidate: globalThis.RTCIceCandidate || globalThis.mozRTCIceCandidate || globalThis.webkitRTCIceCandidate
};
return e.RTCPeerConnection ? e : null;
}), Ct;
}
var it = { exports: {} }, ot = { exports: {} }, Et = {}, gn;
function Ye() {
return gn || (gn = 1, function(n) {
Object.defineProperties(n, { __esModule: { value: !0 }, [Symbol.toStringTag]: { value: "Module" } });
var e = {}, t = {};
t.byteLength = w, t.toByteArray = C, t.fromByteArray = I;
for (var o = [], l = [], c = typeof Uint8Array != "undefined" ? Uint8Array : Array, E = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", a = 0, f = E.length; a < f; ++a)
o[a] = E[a], l[E.charCodeAt(a)] = a;
l[45] = 62, l[95] = 63;
function u(b) {
var P = b.length;
if (P % 4 > 0)
throw new Error("Invalid string. Length must be a multiple of 4");
var _ = b.indexOf("=");
_ === -1 && (_ = P);
var R = _ === P ? 0 : 4 - _ % 4;
return [_, R];
}
function w(b) {
var P = u(b), _ = P[0], R = P[1];
return (_ + R) * 3 / 4 - R;
}
function A(b, P, _) {
return (P + _) * 3 / 4 - _;
}
function C(b) {
var P, _ = u(b), R = _[0], v = _[1], g = new c(A(b, R, v)), M = 0, U = v > 0 ? R - 4 : R, F;
for (F = 0; F < U; F += 4)
P = l[b.charCodeAt(F)] << 18 | l[b.charCodeAt(F + 1)] << 12 | l[b.charCodeAt(F + 2)] << 6 | l[b.charCodeAt(F + 3)], g[M++] = P >> 16 & 255, g[M++] = P >> 8 & 255, g[M++] = P & 255;
return v === 2 && (P = l[b.charCodeAt(F)] << 2 | l[b.charCodeAt(F + 1)] >> 4, g[M++] = P & 255), v === 1 && (P = l[b.charCodeAt(F)] << 10 | l[b.charCodeAt(F + 1)] << 4 | l[b.charCodeAt(F + 2)] >> 2, g[M++] = P >> 8 & 255, g[M++] = P & 255), g;
}
function j(b) {
return o[b >> 18 & 63] + o[b >> 12 & 63] + o[b >> 6 & 63] + o[b & 63];
}
function y(b, P, _) {
for (var R, v = [], g = P; g < _; g += 3)
R = (b[g] << 16 & 16711680) + (b[g + 1] << 8 & 65280) + (b[g + 2] & 255), v.push(j(R));
return v.join("");
}
function I(b) {
for (var P, _ = b.length, R = _ % 3, v = [], g = 16383, M = 0, U = _ - R; M < U; M += g)
v.push(y(b, M, M + g > U ? U : M + g));
return R === 1 ? (P = b[_ - 1], v.push(
o[P >> 2] + o[P << 4 & 63] + "=="
)) : R === 2 && (P = (b[_ - 2] << 8) + b[_ - 1], v.push(
o[P >> 10] + o[P >> 4 & 63] + o[P << 2 & 63] + "="
)), v.join("");
}
var S = {};
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
S.read = function(b, P, _, R, v) {
var g, M, U = v * 8 - R - 1, F = (1 << U) - 1, J = F >> 1, k = -7, te = _ ? v - 1 : 0, ee = _ ? -1 : 1, ae = b[P + te];
for (te += ee, g = ae & (1 << -k) - 1, ae >>= -k, k += U; k > 0; g = g * 256 + b[P + te], te += ee, k -= 8)
;
for (M = g & (1 << -k) - 1, g >>= -k, k += R; k > 0; M = M * 256 + b[P + te], te += ee, k -= 8)
;
if (g === 0)
g = 1 - J;
else {
if (g === F)
return M ? NaN : (ae ? -1 : 1) * (1 / 0);
M = M + Math.pow(2, R), g = g - J;
}
return (ae ? -1 : 1) * M * Math.pow(2, g - R);
}, S.write = function(b, P, _, R, v, g) {
var M, U, F, J = g * 8 - v - 1, k = (1 << J) - 1, te = k >> 1, ee = v === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0, ae = R ? 0 : g - 1, le = R ? 1 : -1, me = P < 0 || P === 0 && 1 / P < 0 ? 1 : 0;
for (P = Math.abs(P), isNaN(P) || P === 1 / 0 ? (U = isNaN(P) ? 1 : 0, M = k) : (M = Math.floor(Math.log(P) / Math.LN2), P * (F = Math.pow(2, -M)) < 1 && (M--, F *= 2), M + te >= 1 ? P += ee / F : P += ee * Math.pow(2, 1 - te), P * F >= 2 && (M++, F /= 2), M + te >= k ? (U = 0, M = k) : M + te >= 1 ? (U = (P * F - 1) * Math.pow(2, v), M = M + te) : (U = P * Math.pow(2, te - 1) * Math.pow(2, v), M = 0)); v >= 8; b[_ + ae] = U & 255, ae += le, U /= 256, v -= 8)
;
for (M = M << v | U, J += v; J > 0; b[_ + ae] = M & 255, ae += le, M /= 256, J -= 8)
;
b[_ + ae - le] |= me * 128;
};
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
(function(b) {
const P = t, _ = S, R = typeof Symbol == "function" && typeof Symbol.for == "function" ? Symbol.for("nodejs.util.inspect.custom") : null;
b.Buffer = k, b.SlowBuffer = L, b.INSPECT_MAX_BYTES = 50;
const v = 2147483647;
b.kMaxLength = v;
const { Uint8Array: g, ArrayBuffer: M, SharedArrayBuffer: U } = globalThis;
k.TYPED_ARRAY_SUPPORT = F(), !k.TYPED_ARRAY_SUPPORT && typeof console != "undefined" && typeof console.error == "function" && console.error(
"This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."
);
function F() {
try {
const s = new g(1), r = { foo: function() {
return 42;
} };
return Object.setPrototypeOf(r, g.prototype), Object.setPrototypeOf(s, r), s.foo() === 42;
} catch (s) {
return !1;
}
}
Object.defineProperty(k.prototype, "parent", {
enumerable: !0,
get: function() {
if (k.isBuffer(this))
return this.buffer;
}
}), Object.defineProperty(k.prototype, "offset", {
enumerable: !0,
get: function() {
if (k.isBuffer(this))
return this.byteOffset;
}
});
function J(s) {
if (s > v)
throw new RangeError('The value "' + s + '" is invalid for option "size"');
const r = new g(s);
return Object.setPrototypeOf(r, k.prototype), r;
}
function k(s, r, i) {
if (typeof s == "number") {
if (typeof r == "string")
throw new TypeError(
'The "string" argument must be of type string. Received type number'
);
return le(s);
}
return te(s, r, i);
}
k.poolSize = 8192;
function te(s, r, i) {
if (typeof s == "string")
return me(s, r);
if (M.isView(s))
return pe(s);
if (s == null)
throw new TypeError(
"The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type " + typeof s
);
if (Re(s, M) || s && Re(s.buffer, M) || typeof U != "undefined" && (Re(s, U) || s && Re(s.buffer, U)))
return ie(s, r, i);
if (typeof s == "number")
throw new TypeError(
'The "value" argument must not be of type number. Received type number'
);
const m = s.valueOf && s.valueOf();
if (m != null && m !== s)
return k.from(m, r, i);
const T = _e(s);
if (T) return T;
if (typeof Symbol != "undefined" && Symbol.toPrimitive != null && typeof s[Symbol.toPrimitive] == "function")
return k.from(s[Symbol.toPrimitive]("string"), r, i);
throw new TypeError(
"The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type " + typeof s
);
}
k.from = function(s, r, i) {
return te(s, r, i);
}, Object.setPrototypeOf(k.prototype, g.prototype), Object.setPrototypeOf(k, g);
function ee(s) {
if (typeof s != "number")
throw new TypeError('"size" argument must be of type number');
if (s < 0)
throw new RangeError('The value "' + s + '" is invalid for option "size"');
}
function ae(s, r, i) {
return ee(s), s <= 0 ? J(s) : r !== void 0 ? typeof i == "string" ? J(s).fill(r, i) : J(s).fill(r) : J(s);
}
k.alloc = function(s, r, i) {
return ae(s, r, i);
};
function le(s) {
return ee(s), J(s < 0 ? 0 : he(s) | 0);
}
k.allocUnsafe = function(s) {
return le(s);
}, k.allocUnsafeSlow = function(s) {
return le(s);
};
function me(s, r) {
if ((typeof r != "string" || r === "") && (r = "utf8"), !k.isEncoding(r))
throw new TypeError("Unknown encoding: " + r);
const i = $(s, r) | 0;
let m = J(i);
const T = m.write(s, r);
return T !== i && (m = m.slice(0, T)), m;
}
function ce(s) {
const r = s.length < 0 ? 0 : he(s.length) | 0, i = J(r);
for (let m = 0; m < r; m += 1)
i[m] = s[m] & 255;
return i;
}
function pe(s) {
if (Re(s, g)) {
const r = new g(s);
return ie(r.buffer, r.byteOffset, r.byteLength);
}
return ce(s);
}
function ie(s, r, i) {
if (r < 0 || s.byteLength < r)
throw new RangeError('"offset" is outside of buffer bounds');
if (s.byteLength < r + (i || 0))
throw new RangeError('"length" is outside of buffer bounds');
let m;
return r === void 0 && i === void 0 ? m = new g(s) : i === void 0 ? m = new g(s, r) : m = new g(s, r, i), Object.setPrototypeOf(m, k.prototype), m;
}
function _e(s) {
if (k.isBuffer(s)) {
const r = he(s.length) | 0, i = J(r);
return i.length === 0 || s.copy(i, 0, 0, r), i;
}
if (s.length !== void 0)
return typeof s.length != "number" || yt(s.length) ? J(0) : ce(s);
if (s.type === "Buffer" && Array.isArray(s.data))
return ce(s.data);
}
function he(s) {
if (s >= v)
throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x" + v.toString(16) + " bytes");
return s | 0;
}
function L(s) {
return +s != s && (s = 0), k.alloc(+s);
}
k.isBuffer = function(r) {
return r != null && r._isBuffer === !0 && r !== k.prototype;
}, k.compare = function(r, i) {
if (Re(r, g) && (r = k.from(r, r.offset, r.byteLength)), Re(i, g) && (i = k.from(i, i.offset, i.byteLength)), !k.isBuffer(r) || !k.isBuffer(i))
throw new TypeError(
'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'
);
if (r === i) return 0;
let m = r.length, T = i.length;
for (let N = 0, W = Math.min(m, T); N < W; ++N)
if (r[N] !== i[N]) {
m = r[N], T = i[N];
break;
}
return m < T ? -1 : T < m ? 1 : 0;
}, k.isEncoding = function(r) {
switch (String(r).toLowerCase()) {
case "hex":
case "utf8":
case "utf-8":
case "ascii":
case "latin1":
case "binary":
case "base64":
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
return !0;
default:
return !1;
}
}, k.concat = function(r, i) {
if (!Array.isArray(r))
throw new TypeError('"list" argument must be an Array of Buffers');
if (r.length === 0)
return k.alloc(0);
let m;
if (i === void 0)
for (i = 0, m = 0; m < r.length; ++m)
i += r[m].length;
const T = k.allocUnsafe(i);
let N = 0;
for (m = 0; m < r.length; ++m) {
let W = r[m];
if (Re(W, g))
N + W.length > T.length ? (k.isBuffer(W) || (W = k.from(W)), W.copy(T, N)) : g.prototype.set.call(
T,
W,
N
);
else if (k.isBuffer(W))
W.copy(T, N);
else
throw new TypeError('"list" argument must be an Array of Buffers');
N += W.length;
}
return T;
};
function $(s, r) {
if (k.isBuffer(s))
return s.length;
if (M.isView(s) || Re(s, M))
return s.byteLength;
if (typeof s != "string")
throw new TypeError(
'The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type ' + typeof s
);
const i = s.length, m = arguments.length > 2 && arguments[2] === !0;
if (!m && i === 0) return 0;
let T = !1;
for (; ; )
switch (r) {
case "ascii":
case "latin1":
case "binary":
return i;
case "utf8":
case "utf-8":
return gt(s).length;
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
return i * 2;
case "hex":
return i >>> 1;
case "base64":
return ln(s).length;
default:
if (T)
return m ? -1 : gt(s).length;
r = ("" + r).toLowerCase(), T = !0;
}
}
k.byteLength = $;
function G(s, r, i) {
let m = !1;
if ((r === void 0 || r < 0) && (r = 0), r > this.length || ((i === void 0 || i > this.length) && (i = this.length), i <= 0) || (i >>>= 0, r >>>= 0, i <= r))
return "";
for (s || (s = "utf8"); ; )
switch (s) {
case "hex":
return ve(this, r, i);
case "utf8":
case "utf-8":
return H(this, r, i);
case "ascii":
return Q(this, r, i);
case "latin1":
case "binary":
return q(this, r, i);
case "base64":
return x(this, r, i);
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
return ge(this, r, i);
default:
if (m) throw new TypeError("Unknown encoding: " + s);
s = (s + "").toLowerCase(), m = !0;
}
}
k.prototype._isBuffer = !0;
function Y(s, r, i) {
const m = s[r];
s[r] = s[i], s[i] = m;
}
k.prototype.swap16 = function() {
const r = this.length;
if (r % 2 !== 0)
throw new RangeError("Buffer size must be a multiple of 16-bits");
for (let i = 0; i < r; i += 2)
Y(this, i, i + 1);
return this;
}, k.prototype.swap32 = function() {
const r = this.length;
if (r % 4 !== 0)
throw new RangeError("Buffer size must be a multiple of 32-bits");
for (let i = 0; i < r; i += 4)
Y(this, i, i + 3), Y(this, i + 1, i + 2);
return this;
}, k.prototype.swap64 = function() {
const r = this.length;
if (r % 8 !== 0)
throw new RangeError("Buffer size must be a multiple of 64-bits");
for (let i = 0; i < r; i += 8)
Y(this, i, i + 7), Y(this, i + 1, i + 6), Y(this, i + 2, i + 5), Y(this, i + 3, i + 4);
return this;
}, k.prototype.toString = function() {
const r = this.length;
return r === 0 ? "" : arguments.length === 0 ? H(this, 0, r) : G.apply(this, arguments);
}, k.prototype.toLocaleString = k.prototype.toString, k.prototype.equals = function(r) {
if (!k.isBuffer(r)) throw new TypeError("Argument must be a Buffer");
return this === r ? !0 : k.compare(this, r) === 0;
}, k.prototype.inspect = function() {
let r = "";
const i = b.INSPECT_MAX_BYTES;
return r = this.toString("hex", 0, i).replace(/(.{2})/g, "$1 ").trim(), this.length > i && (r += " ... "), "<Buffer " + r + ">";
}, R && (k.prototype[R] = k.prototype.inspect), k.prototype.compare = function(r, i, m, T, N) {
if (Re(r, g) && (r = k.from(r, r.offset, r.byteLength)), !k.isBuffer(r))
throw new TypeError(
'The "target" argument must be one of type Buffer or Uint8Array. Received type ' + typeof r
);
if (i === void 0 && (i = 0), m === void 0 && (m = r ? r.length : 0), T === void 0 && (T = 0), N === void 0 && (N = this.length), i < 0 || m > r.length || T < 0 || N > this.length)
throw new RangeError("out of range index");
if (T >= N && i >= m)
return 0;
if (T >= N)
return -1;
if (i >= m)
return 1;
if (i >>>= 0, m >>>= 0, T >>>= 0, N >>>= 0, this === r) return 0;
let W = N - T, Z = m - i;
const fe = Math.min(W, Z), se = this.slice(T, N), de = r.slice(i, m);
for (let re = 0; re < fe; ++re)
if (se[re] !== de[re]) {
W = se[re], Z = de[re];
break;
}
return W < Z ? -1 : Z < W ? 1 : 0;
};
function B(s, r, i, m, T) {
if (s.length === 0) return -1;
if (typeof i == "string" ? (m = i, i = 0) : i > 2147483647 ? i = 2147483647 : i < -2147483648 && (i = -2147483648), i = +i, yt(i) && (i = T ? 0 : s.length - 1), i < 0 && (i = s.length + i), i >= s.length) {
if (T) return -1;
i = s.length - 1;
} else if (i < 0)
if (T) i = 0;
else return -1;
if (typeof r == "string" && (r = k.from(r, m)), k.isBuffer(r))
return r.length === 0 ? -1 : O(s, r, i, m, T);
if (typeof r == "number")
return r = r & 255, typeof g.prototype.indexOf == "function" ? T ? g.prototype.indexOf.call(s, r, i) : g.prototype.lastIndexOf.call(s, r, i) : O(s, [r], i, m, T);
throw new TypeError("val must be string, number or Buffer");
}
function O(s, r, i, m, T) {
let N = 1, W = s.length, Z = r.length;
if (m !== void 0 && (m = String(m).toLowerCase(), m === "ucs2" || m === "ucs-2" || m === "utf16le" || m === "utf-16le")) {
if (s.length < 2 || r.length < 2)
return -1;
N = 2, W /= 2, Z /= 2, i /= 2;
}
function fe(de, re) {
return N === 1 ? de[re] : de.readUInt16BE(re * N);
}
let se;
if (T) {
let de = -1;
for (se = i; se < W; se++)
if (fe(s, se) === fe(r, de === -1 ? 0 : se - de)) {
if (de === -1 && (de = se), se - de + 1 === Z) return de * N;
} else
de !== -1 && (se -= se - de), de = -1;
} else
for (i + Z > W && (i = W - Z), se = i; se >= 0; se--) {
let de = !0;
for (let re = 0; re < Z; re++)
if (fe(s, se + re) !== fe(r, re)) {
de = !1;
break;
}
if (de) return se;
}
return -1;
}
k.prototype.includes = function(r, i, m) {
return this.indexOf(r, i, m) !== -1;
}, k.prototype.indexOf = function(r, i, m) {
return B(this, r, i, m, !0);
}, k.prototype.lastIndexOf = function(r, i, m) {
return B(this, r, i, m, !1);
};
function D(s, r, i, m) {
i = Number(i) || 0;
const T = s.length - i;
m ? (m = Number(m), m > T && (m = T)) : m = T;
const N = r.length;
m > N / 2 && (m = N / 2);
let W;
for (W = 0; W < m; ++W) {
const Z = parseInt(r.substr(W * 2, 2), 16);
if (yt(Z)) return W;
s[i + W] = Z;
}
return W;
}
function z(s, r, i, m) {
return Qe(gt(r, s.length - i), s, i, m);
}
function V(s, r, i, m) {
return Qe(wo(r), s, i, m);
}
function d(s, r, i, m) {
return Qe(ln(r), s, i, m);
}
function p(s, r, i, m) {
return Qe(_o(r, s.length - i), s, i, m);
}
k.prototype.write = function(r, i, m, T) {
if (i === void 0)
T = "utf8", m = this.length, i = 0;
else if (m === void 0 && typeof i == "string")
T = i, m = this.length, i = 0;
else if (isFinite(i))
i = i >>> 0, isFinite(m) ? (m = m >>> 0, T === void 0 && (T = "utf8")) : (T = m, m = void 0);
else
throw new Error(
"Buffer.write(string, encoding, offset[, length]) is no longer supported"
);
const N = this.length - i;
if ((m === void 0 || m > N) && (m = N), r.length > 0 && (m < 0 || i < 0) || i > this.length)
throw new RangeError("Attempt to write outside buffer bounds");
T || (T = "utf8");
let W = !1;
for (; ; )
switch (T) {
case "hex":
return D(this, r, i, m);
case "utf8":
case "utf-8":
return z(this, r, i, m);
case "ascii":
case "latin1":
case "binary":
return V(this, r, i, m);
case "base64":
return d(this, r, i, m);
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
return p(this, r, i, m);
default:
if (W) throw new TypeError("Unknown encoding: " + T);
T = ("" + T).toLowerCase(), W = !0;
}
}, k.prototype.toJSON = function() {
return {
type: "Buffer",
data: Array.prototype.slice.call(this._arr || this, 0)
};
};
function x(s, r, i) {
return r === 0 && i === s.length ? P.fromByteArray(s) : P.fromByteArray(s.slice(r, i));
}
function H(s, r, i) {
i = Math.min(s.length, i);
const m = [];
let T = r;
for (; T < i; ) {
const N = s[T];
let W = null, Z = N > 239 ? 4 : N > 223 ? 3 : N > 191 ? 2 : 1;
if (T + Z <= i) {
let fe, se, de, re;
switch (Z) {
case 1:
N < 128 && (W = N);
break;
case 2:
fe = s[T + 1], (fe & 192) === 128 && (re = (N & 31) << 6 | fe & 63, re > 127 && (W = re));
break;
case 3:
fe = s[T + 1], se = s[T + 2], (fe & 192) === 128 && (se & 192) === 128 && (re = (N & 15) << 12 | (fe & 63) << 6 | se & 63, re > 2047 && (re < 55296 || re > 57343) && (W = re));
break;
case 4:
fe = s[T + 1], se = s[T + 2], de = s[T + 3], (fe & 192) === 128 && (se & 192) === 128 && (de & 192) === 128 && (re = (N & 15) << 18 | (fe & 63) << 12 | (se & 63) << 6 | de & 63, re > 65535 && re < 1114112 && (W = re));
}
}
W === null ? (W = 65533, Z = 1) : W > 65535 && (W -= 65536, m.push(W >>> 10 & 1023 | 55296), W = 56320 | W & 1023), m.push(W), T += Z;
}
return X(m);
}
const K = 4096;
function X(s) {
const r = s.length;
if (r <= K)
return String.fromCharCode.apply(String, s);
let i = "", m = 0;
for (; m < r; )
i += String.fromCharCode.apply(
String,
s.slice(m, m += K)
);
return i;
}
function Q(s, r, i) {
let m = "";
i = Math.min(s.length, i);
for (let T = r; T < i; ++T)
m += String.fromCharCode(s[T] & 127);
return m;
}
function q(s, r, i) {
let m = "";
i = Math.min(s.length, i);
for (let T = r; T < i; ++T)
m += String.fromCharCode(s[T]);
return m;
}
function ve(s, r, i) {
const m = s.length;
(!r || r < 0) && (r = 0), (!i || i < 0 || i > m) && (i = m);
let T = "";
for (let N = r; N < i; ++N)
T += So[s[N]];
return T;
}
function ge(s, r, i) {
const m = s.slice(r, i);
let T = "";
for (let N = 0; N < m.length - 1; N += 2)
T += String.fromCharCo